| 1150 | #endif |
| 1151 | |
| 1152 | String FileSystem::GetAbsolutePath(StringView path) |
| 1153 | { |
| 1154 | if (path.empty()) return {}; |
| 1155 | |
| 1156 | #if defined(DEATH_TARGET_WINDOWS) |
| 1157 | SmallVector<wchar_t, MAX_PATH + 1> pathW(DefaultInit, path.size() + 1); |
| 1158 | Utf8::ToUtf16(pathW.data(), std::int32_t(pathW.size()), path.data(), std::int32_t(path.size())); |
| 1159 | |
| 1160 | wchar_t buffer[MaxPathLength + 1]; |
| 1161 | DWORD length = ::GetFullPathNameW(pathW.data(), DWORD(arraySize(buffer)), buffer, nullptr); |
| 1162 | if (length == 0) { |
| 1163 | return {}; |
| 1164 | } |
| 1165 | |
| 1166 | return Utf8::FromUtf16(buffer, length); |
| 1167 | #elif defined(DEATH_TARGET_SWITCH) || defined(DEATH_TARGET_VITA) |
| 1168 | // realpath() is missing in libnx and Vita |
| 1169 | char left[MaxPathLength]; |
| 1170 | char nextToken[MaxPathLength]; |
| 1171 | char result[MaxPathLength]; |
| 1172 | std::size_t resultLength = 0; |
| 1173 | # if !defined(DEATH_TARGET_SWITCH) && !defined(DEATH_TARGET_VITA) |
| 1174 | std::int32_t symlinks = 0; |
| 1175 | # endif |
| 1176 | |
| 1177 | std::size_t pathRootLength = GetPathRootLength(path); |
| 1178 | if (pathRootLength > 0) { |
| 1179 | strncpy(result, path.data(), pathRootLength); |
| 1180 | resultLength = pathRootLength; |
| 1181 | if (path.size() == pathRootLength) { |
| 1182 | return String{result, resultLength}; |
| 1183 | } |
| 1184 | |
| 1185 | strncpy(left, path.data() + pathRootLength, sizeof(left)); |
| 1186 | } else { |
| 1187 | if (::getcwd(result, sizeof(result)) == nullptr) { |
| 1188 | return "."_s; |
| 1189 | } |
| 1190 | resultLength = std::strlen(result); |
| 1191 | strncpy(left, path.data(), sizeof(left)); |
| 1192 | } |
| 1193 | std::size_t leftLength = std::strlen(left); |
| 1194 | if (leftLength >= sizeof(left) || resultLength >= MaxPathLength) { |
| 1195 | // Path is too long |
| 1196 | return path; |
| 1197 | } |
| 1198 | |
| 1199 | while (leftLength != 0) { |
| 1200 | char* p = strchr(left, '/'); |
| 1201 | char* s = (p != nullptr ? p : left + leftLength); |
| 1202 | std::size_t nextTokenLength = s - left; |
| 1203 | if (nextTokenLength >= sizeof(nextToken)) { |
| 1204 | // Path is too long |
| 1205 | return path; |
| 1206 | } |
| 1207 | std::memcpy(nextToken, left, nextTokenLength); |
| 1208 | nextToken[nextTokenLength] = '\0'; |
| 1209 | leftLength -= nextTokenLength; |