| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "bin/directory.h" | 5 #include "bin/directory.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <sys/stat.h> | 8 #include <sys/stat.h> |
| 9 | 9 |
| 10 #include "bin/log.h" | 10 #include "bin/log.h" |
| 11 | 11 |
| 12 // Forward declaration. | 12 // Forward declaration. |
| 13 static bool ListRecursively(const char* dir_name, | 13 static bool ListRecursively(const wchar_t* dir_name, |
| 14 bool recursive, | 14 bool recursive, |
| 15 DirectoryListing* listing); | 15 DirectoryListing* listing); |
| 16 static bool DeleteRecursively(const char* dir_name); | 16 static bool DeleteRecursively(const wchar_t* dir_name); |
| 17 | 17 |
| 18 | 18 |
| 19 static bool HandleDir(char* dir_name, | 19 static bool HandleDir(wchar_t* dir_name, |
| 20 char* path, | 20 wchar_t* path, |
| 21 int path_length, | 21 int path_length, |
| 22 bool recursive, | 22 bool recursive, |
| 23 DirectoryListing* listing) { | 23 DirectoryListing* listing) { |
| 24 if (strcmp(dir_name, ".") != 0 && | 24 if (wcscmp(dir_name, L".") != 0 && |
| 25 strcmp(dir_name, "..") != 0) { | 25 wcscmp(dir_name, L"..") != 0) { |
| 26 size_t written = snprintf(path + path_length, | 26 size_t written = _snwprintf(path + path_length, |
| 27 MAX_PATH - path_length, | 27 MAX_PATH - path_length, |
| 28 "%s", | 28 L"%s", |
| 29 dir_name); | 29 dir_name); |
| 30 if (written != strlen(dir_name)) { | 30 if (written != wcslen(dir_name)) { |
| 31 return false; | 31 return false; |
| 32 } | 32 } |
| 33 char* utf8_path = StringUtils::ConsoleStringToUtf8(path); | 33 char* utf8_path = StringUtils::WideToUtf8(path); |
| 34 bool ok = listing->HandleDirectory(utf8_path); | 34 bool ok = listing->HandleDirectory(utf8_path); |
| 35 free(utf8_path); | 35 free(utf8_path); |
| 36 if (!ok) return ok; | 36 if (!ok) return ok; |
| 37 if (recursive) { | 37 if (recursive) { |
| 38 return ListRecursively(path, recursive, listing); | 38 return ListRecursively(path, recursive, listing); |
| 39 } | 39 } |
| 40 } | 40 } |
| 41 return true; | 41 return true; |
| 42 } | 42 } |
| 43 | 43 |
| 44 | 44 |
| 45 static bool HandleFile(char* file_name, | 45 static bool HandleFile(wchar_t* file_name, |
| 46 char* path, | 46 wchar_t* path, |
| 47 int path_length, | 47 int path_length, |
| 48 DirectoryListing* listing) { | 48 DirectoryListing* listing) { |
| 49 size_t written = snprintf(path + path_length, | 49 size_t written = _snwprintf(path + path_length, |
| 50 MAX_PATH - path_length, | 50 MAX_PATH - path_length, |
| 51 "%s", | 51 L"%s", |
| 52 file_name); | 52 file_name); |
| 53 if (written != strlen(file_name)) { | 53 if (written != wcslen(file_name)) { |
| 54 return false; | 54 return false; |
| 55 }; | 55 }; |
| 56 char* utf8_path = StringUtils::ConsoleStringToUtf8(path); | 56 char* utf8_path = StringUtils::WideToUtf8(path); |
| 57 bool ok = listing->HandleFile(utf8_path); | 57 bool ok = listing->HandleFile(utf8_path); |
| 58 free(utf8_path); | 58 free(utf8_path); |
| 59 return ok; | 59 return ok; |
| 60 } | 60 } |
| 61 | 61 |
| 62 | 62 |
| 63 static bool HandleEntry(LPWIN32_FIND_DATA find_file_data, | 63 static bool HandleEntry(LPWIN32_FIND_DATAW find_file_data, |
| 64 char* path, | 64 wchar_t* path, |
| 65 int path_length, | 65 int path_length, |
| 66 bool recursive, | 66 bool recursive, |
| 67 DirectoryListing* listing) { | 67 DirectoryListing* listing) { |
| 68 DWORD attributes = find_file_data->dwFileAttributes; | 68 DWORD attributes = find_file_data->dwFileAttributes; |
| 69 if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { | 69 if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { |
| 70 return HandleDir(find_file_data->cFileName, | 70 return HandleDir(find_file_data->cFileName, |
| 71 path, | 71 path, |
| 72 path_length, | 72 path_length, |
| 73 recursive, | 73 recursive, |
| 74 listing); | 74 listing); |
| 75 } else { | 75 } else { |
| 76 return HandleFile(find_file_data->cFileName, path, path_length, listing); | 76 return HandleFile(find_file_data->cFileName, path, path_length, listing); |
| 77 } | 77 } |
| 78 } | 78 } |
| 79 | 79 |
| 80 | 80 |
| 81 // ComputeFullSearchPath must be called with a path array of size at | 81 // ComputeFullSearchPath must be called with a path array of size at |
| 82 // least MAX_PATH. | 82 // least MAX_PATH. |
| 83 static bool ComputeFullSearchPath(const char* dir_name, | 83 static bool ComputeFullSearchPath(const wchar_t* dir_name, |
| 84 char* path, | 84 wchar_t* path, |
| 85 int* path_length) { | 85 int* path_length) { |
| 86 // GetFullPathName only works in a multi-threaded environment if | 86 // GetFullPathName only works in a multi-threaded environment if |
| 87 // SetCurrentDirectory is not used. We currently have no plan for | 87 // SetCurrentDirectory is not used. We currently have no plan for |
| 88 // exposing SetCurrentDirectory. | 88 // exposing SetCurrentDirectory. |
| 89 size_t written = GetFullPathName(dir_name, MAX_PATH, path, NULL); | 89 size_t written = GetFullPathNameW(dir_name, MAX_PATH, path, NULL); |
| 90 // GetFullPathName only accepts input strings of size less than | 90 // GetFullPathName only accepts input strings of size less than |
| 91 // MAX_PATH and returns 0 to indicate failure for paths longer than | 91 // MAX_PATH and returns 0 to indicate failure for paths longer than |
| 92 // that. Therefore the path buffer is always big enough. | 92 // that. Therefore the path buffer is always big enough. |
| 93 if (written == 0) { | 93 if (written == 0 || written > MAX_PATH) { |
| 94 return false; | 94 return false; |
| 95 } | 95 } |
| 96 *path_length = written; | 96 *path_length = written; |
| 97 written = snprintf(path + *path_length, | 97 written = _snwprintf(path + *path_length, |
| 98 MAX_PATH - *path_length, | 98 MAX_PATH - *path_length, |
| 99 "%s", | 99 L"%s", |
| 100 "\\*"); | 100 L"\\*"); |
| 101 if (written != 2) { | 101 if (written != 2) { |
| 102 return false; | 102 return false; |
| 103 } | 103 } |
| 104 *path_length += written; | 104 *path_length += written; |
| 105 return true; | 105 return true; |
| 106 } | 106 } |
| 107 | 107 |
| 108 static void PostError(DirectoryListing* listing, | 108 static void PostError(DirectoryListing* listing, |
| 109 const char* dir_name) { | 109 const wchar_t* dir_name) { |
| 110 const char* utf8_path = StringUtils::ConsoleStringToUtf8(dir_name); | 110 const char* utf8_path = StringUtils::WideToUtf8(dir_name); |
| 111 listing->HandleError(utf8_path); | 111 listing->HandleError(utf8_path); |
| 112 free(const_cast<char*>(utf8_path)); | 112 free(const_cast<char*>(utf8_path)); |
| 113 } | 113 } |
| 114 | 114 |
| 115 | 115 |
| 116 static bool ListRecursively(const char* dir_name, | 116 static bool ListRecursively(const wchar_t* dir_name, |
| 117 bool recursive, | 117 bool recursive, |
| 118 DirectoryListing* listing) { | 118 DirectoryListing* listing) { |
| 119 // Compute full path for the directory currently being listed. The | 119 // Compute full path for the directory currently being listed. The |
| 120 // path buffer will be used to construct the current path in the | 120 // path buffer will be used to construct the current path in the |
| 121 // recursive traversal. path_length does not always equal | 121 // recursive traversal. path_length does not always equal |
| 122 // strlen(path) but indicates the current prefix of path that is the | 122 // strlen(path) but indicates the current prefix of path that is the |
| 123 // path of the current directory in the traversal. | 123 // path of the current directory in the traversal. |
| 124 char* path = static_cast<char*>(malloc(MAX_PATH)); | 124 wchar_t* path = static_cast<wchar_t*>(malloc(MAX_PATH * sizeof(wchar_t))); |
| 125 int path_length = 0; | 125 int path_length = 0; |
| 126 bool valid = ComputeFullSearchPath(dir_name, path, &path_length); | 126 bool valid = ComputeFullSearchPath(dir_name, path, &path_length); |
| 127 if (!valid) { | 127 if (!valid) { |
| 128 PostError(listing, dir_name); | 128 PostError(listing, dir_name); |
| 129 free(path); | 129 free(path); |
| 130 return false; | 130 return false; |
| 131 } | 131 } |
| 132 | 132 |
| 133 WIN32_FIND_DATA find_file_data; | 133 WIN32_FIND_DATAW find_file_data; |
| 134 HANDLE find_handle = FindFirstFile(path, &find_file_data); | 134 HANDLE find_handle = FindFirstFileW(path, &find_file_data); |
| 135 | 135 |
| 136 // Adjust the path by removing the '*' used for the search. | 136 // Adjust the path by removing the '*' used for the search. |
| 137 path_length -= 1; | 137 path_length -= 1; |
| 138 path[path_length] = '\0'; | 138 path[path_length] = '\0'; |
| 139 | 139 |
| 140 if (find_handle == INVALID_HANDLE_VALUE) { | 140 if (find_handle == INVALID_HANDLE_VALUE) { |
| 141 PostError(listing, path); | 141 PostError(listing, path); |
| 142 free(path); | 142 free(path); |
| 143 return false; | 143 return false; |
| 144 } | 144 } |
| 145 | 145 |
| 146 bool success = HandleEntry(&find_file_data, | 146 bool success = HandleEntry(&find_file_data, |
| 147 path, | 147 path, |
| 148 path_length, | 148 path_length, |
| 149 recursive, | 149 recursive, |
| 150 listing); | 150 listing); |
| 151 | 151 |
| 152 while ((FindNextFile(find_handle, &find_file_data) != 0)) { | 152 while ((FindNextFileW(find_handle, &find_file_data) != 0)) { |
| 153 success = HandleEntry(&find_file_data, | 153 success = HandleEntry(&find_file_data, |
| 154 path, | 154 path, |
| 155 path_length, | 155 path_length, |
| 156 recursive, | 156 recursive, |
| 157 listing) && success; | 157 listing) && success; |
| 158 } | 158 } |
| 159 | 159 |
| 160 if (GetLastError() != ERROR_NO_MORE_FILES) { | 160 if (GetLastError() != ERROR_NO_MORE_FILES) { |
| 161 success = false; | 161 success = false; |
| 162 PostError(listing, dir_name); | 162 PostError(listing, dir_name); |
| 163 } | 163 } |
| 164 | 164 |
| 165 if (FindClose(find_handle) == 0) { | 165 if (FindClose(find_handle) == 0) { |
| 166 success = false; | 166 success = false; |
| 167 PostError(listing, dir_name); | 167 PostError(listing, dir_name); |
| 168 } | 168 } |
| 169 free(path); | 169 free(path); |
| 170 | 170 |
| 171 return success; | 171 return success; |
| 172 } | 172 } |
| 173 | 173 |
| 174 | 174 |
| 175 static bool DeleteFile(char* file_name, | 175 static bool DeleteFile(wchar_t* file_name, |
| 176 char* path, | 176 wchar_t* path, |
| 177 int path_length) { | 177 int path_length) { |
| 178 size_t written = snprintf(path + path_length, | 178 size_t written = _snwprintf(path + path_length, |
| 179 MAX_PATH - path_length, | 179 MAX_PATH - path_length, |
| 180 "%s", | 180 L"%s", |
| 181 file_name); | 181 file_name); |
| 182 if (written != strlen(file_name)) { | 182 if (written != wcslen(file_name)) { |
| 183 return false; | 183 return false; |
| 184 } | 184 } |
| 185 | 185 |
| 186 if (DeleteFile(path) != 0) { | 186 if (DeleteFileW(path) != 0) { |
| 187 return true; | 187 return true; |
| 188 } | 188 } |
| 189 | 189 |
| 190 // If we failed because the file is read-only, make it writeable and try | 190 // If we failed because the file is read-only, make it writeable and try |
| 191 // again. This mirrors Linux/Mac where a directory containing read-only files | 191 // again. This mirrors Linux/Mac where a directory containing read-only files |
| 192 // can still be recursively deleted. | 192 // can still be recursively deleted. |
| 193 if (GetLastError() == ERROR_ACCESS_DENIED) { | 193 if (GetLastError() == ERROR_ACCESS_DENIED) { |
| 194 DWORD attributes = GetFileAttributes(path); | 194 DWORD attributes = GetFileAttributesW(path); |
| 195 if (attributes == INVALID_FILE_ATTRIBUTES) { | 195 if (attributes == INVALID_FILE_ATTRIBUTES) { |
| 196 return false; | 196 return false; |
| 197 } | 197 } |
| 198 | 198 |
| 199 if ((attributes & FILE_ATTRIBUTE_READONLY) == FILE_ATTRIBUTE_READONLY) { | 199 if ((attributes & FILE_ATTRIBUTE_READONLY) == FILE_ATTRIBUTE_READONLY) { |
| 200 attributes &= ~FILE_ATTRIBUTE_READONLY; | 200 attributes &= ~FILE_ATTRIBUTE_READONLY; |
| 201 | 201 |
| 202 if (SetFileAttributes(path, attributes) == 0) { | 202 if (SetFileAttributesW(path, attributes) == 0) { |
| 203 return false; | 203 return false; |
| 204 } | 204 } |
| 205 | 205 |
| 206 return DeleteFile(path) != 0; | 206 return DeleteFileW(path) != 0; |
| 207 } | 207 } |
| 208 } | 208 } |
| 209 | 209 |
| 210 return false; | 210 return false; |
| 211 } | 211 } |
| 212 | 212 |
| 213 | 213 |
| 214 static bool DeleteDir(char* dir_name, | 214 static bool DeleteDir(wchar_t* dir_name, |
| 215 char* path, | 215 wchar_t* path, |
| 216 int path_length) { | 216 int path_length) { |
| 217 if (strcmp(dir_name, ".") != 0 && | 217 if (wcscmp(dir_name, L".") != 0 && |
| 218 strcmp(dir_name, "..") != 0) { | 218 wcscmp(dir_name, L"..") != 0) { |
| 219 size_t written = snprintf(path + path_length, | 219 size_t written = _snwprintf(path + path_length, |
| 220 MAX_PATH - path_length, | 220 MAX_PATH - path_length, |
| 221 "%s", | 221 L"%s", |
| 222 dir_name); | 222 dir_name); |
| 223 if (written != strlen(dir_name)) { | 223 if (written != wcslen(dir_name)) { |
| 224 return false; | 224 return false; |
| 225 } | 225 } |
| 226 return DeleteRecursively(path); | 226 return DeleteRecursively(path); |
| 227 } | 227 } |
| 228 return true; | 228 return true; |
| 229 } | 229 } |
| 230 | 230 |
| 231 | 231 |
| 232 static bool DeleteEntry(LPWIN32_FIND_DATA find_file_data, | 232 static bool DeleteEntry(LPWIN32_FIND_DATAW find_file_data, |
| 233 char* path, | 233 wchar_t* path, |
| 234 int path_length) { | 234 int path_length) { |
| 235 DWORD attributes = find_file_data->dwFileAttributes; | 235 DWORD attributes = find_file_data->dwFileAttributes; |
| 236 | 236 |
| 237 if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { | 237 if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { |
| 238 return DeleteDir(find_file_data->cFileName, path, path_length); | 238 return DeleteDir(find_file_data->cFileName, path, path_length); |
| 239 } else { | 239 } else { |
| 240 return DeleteFile(find_file_data->cFileName, path, path_length); | 240 return DeleteFile(find_file_data->cFileName, path, path_length); |
| 241 } | 241 } |
| 242 } | 242 } |
| 243 | 243 |
| 244 | 244 |
| 245 static bool DeleteRecursively(const char* dir_name) { | 245 static bool DeleteRecursively(const wchar_t* dir_name) { |
| 246 // If the directory is a junction, it's pointing to some other place in the | 246 // If the directory is a junction, it's pointing to some other place in the |
| 247 // filesystem that we do not want to recurse into. | 247 // filesystem that we do not want to recurse into. |
| 248 DWORD attributes = GetFileAttributes(dir_name); | 248 DWORD attributes = GetFileAttributesW(dir_name); |
| 249 if ((attributes != INVALID_FILE_ATTRIBUTES) && | 249 if ((attributes != INVALID_FILE_ATTRIBUTES) && |
| 250 (attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) { | 250 (attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) { |
| 251 // Just delete the junction itself. | 251 // Just delete the junction itself. |
| 252 return RemoveDirectory(dir_name) != 0; | 252 return RemoveDirectoryW(dir_name) != 0; |
| 253 } | 253 } |
| 254 | 254 |
| 255 // Compute full path for the directory currently being deleted. The | 255 // Compute full path for the directory currently being deleted. The |
| 256 // path buffer will be used to construct the current path in the | 256 // path buffer will be used to construct the current path in the |
| 257 // recursive traversal. path_length does not always equal | 257 // recursive traversal. path_length does not always equal |
| 258 // strlen(path) but indicates the current prefix of path that is the | 258 // strlen(path) but indicates the current prefix of path that is the |
| 259 // path of the current directory in the traversal. | 259 // path of the current directory in the traversal. |
| 260 char* path = static_cast<char*>(malloc(MAX_PATH)); | 260 wchar_t* path = static_cast<wchar_t*>(malloc(MAX_PATH * sizeof(wchar_t))); |
| 261 int path_length = 0; | 261 int path_length = 0; |
| 262 bool valid = ComputeFullSearchPath(dir_name, path, &path_length); | 262 bool valid = ComputeFullSearchPath(dir_name, path, &path_length); |
| 263 if (!valid) { | 263 if (!valid) { |
| 264 free(path); | 264 free(path); |
| 265 return false; | 265 return false; |
| 266 } | 266 } |
| 267 | 267 |
| 268 WIN32_FIND_DATA find_file_data; | 268 WIN32_FIND_DATAW find_file_data; |
| 269 HANDLE find_handle = FindFirstFile(path, &find_file_data); | 269 HANDLE find_handle = FindFirstFileW(path, &find_file_data); |
| 270 | 270 |
| 271 // Adjust the path by removing the '*' used for the search. | 271 // Adjust the path by removing the '*' used for the search. |
| 272 path_length -= 1; | 272 path_length -= 1; |
| 273 path[path_length] = '\0'; | 273 path[path_length] = '\0'; |
| 274 | 274 |
| 275 if (find_handle == INVALID_HANDLE_VALUE) { | 275 if (find_handle == INVALID_HANDLE_VALUE) { |
| 276 free(path); | 276 free(path); |
| 277 return false; | 277 return false; |
| 278 } | 278 } |
| 279 | 279 |
| 280 bool success = DeleteEntry(&find_file_data, path, path_length); | 280 bool success = DeleteEntry(&find_file_data, path, path_length); |
| 281 | 281 |
| 282 while ((FindNextFile(find_handle, &find_file_data) != 0) && success) { | 282 while ((FindNextFileW(find_handle, &find_file_data) != 0) && success) { |
| 283 success = success && DeleteEntry(&find_file_data, path, path_length); | 283 success = success && DeleteEntry(&find_file_data, path, path_length); |
| 284 } | 284 } |
| 285 | 285 |
| 286 free(path); | 286 free(path); |
| 287 | 287 |
| 288 if ((GetLastError() != ERROR_NO_MORE_FILES) || | 288 if ((GetLastError() != ERROR_NO_MORE_FILES) || |
| 289 (FindClose(find_handle) == 0) || | 289 (FindClose(find_handle) == 0) || |
| 290 (RemoveDirectory(dir_name) == 0)) { | 290 (RemoveDirectoryW(dir_name) == 0)) { |
| 291 return false; | 291 return false; |
| 292 } | 292 } |
| 293 | 293 |
| 294 return success; | 294 return success; |
| 295 } | 295 } |
| 296 | 296 |
| 297 | 297 |
| 298 bool Directory::List(const char* dir_name, | 298 bool Directory::List(const char* dir_name, |
| 299 bool recursive, | 299 bool recursive, |
| 300 DirectoryListing* listing) { | 300 DirectoryListing* listing) { |
| 301 const char* system_name = StringUtils::Utf8ToConsoleString(dir_name); | 301 const wchar_t* system_name = StringUtils::Utf8ToWide(dir_name); |
| 302 bool completed = ListRecursively(system_name, recursive, listing); | 302 bool completed = ListRecursively(system_name, recursive, listing); |
| 303 free(const_cast<char*>(system_name)); | 303 free(const_cast<wchar_t*>(system_name)); |
| 304 return completed; | 304 return completed; |
| 305 } | 305 } |
| 306 | 306 |
| 307 | 307 |
| 308 static Directory::ExistsResult ExistsHelper(const char* dir_name) { | 308 static Directory::ExistsResult ExistsHelper(const wchar_t* dir_name) { |
| 309 DWORD attributes = GetFileAttributes(dir_name); | 309 DWORD attributes = GetFileAttributesW(dir_name); |
| 310 if (attributes == INVALID_FILE_ATTRIBUTES) { | 310 if (attributes == INVALID_FILE_ATTRIBUTES) { |
| 311 DWORD last_error = GetLastError(); | 311 DWORD last_error = GetLastError(); |
| 312 if (last_error == ERROR_FILE_NOT_FOUND || | 312 if (last_error == ERROR_FILE_NOT_FOUND || |
| 313 last_error == ERROR_PATH_NOT_FOUND) { | 313 last_error == ERROR_PATH_NOT_FOUND) { |
| 314 return Directory::DOES_NOT_EXIST; | 314 return Directory::DOES_NOT_EXIST; |
| 315 } else { | 315 } else { |
| 316 // We might not be able to get the file attributes for other | 316 // We might not be able to get the file attributes for other |
| 317 // reasons such as lack of permissions. In that case we do | 317 // reasons such as lack of permissions. In that case we do |
| 318 // not know if the directory exists. | 318 // not know if the directory exists. |
| 319 return Directory::UNKNOWN; | 319 return Directory::UNKNOWN; |
| 320 } | 320 } |
| 321 } | 321 } |
| 322 bool exists = (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0; | 322 bool exists = (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0; |
| 323 return exists ? Directory::EXISTS : Directory::DOES_NOT_EXIST; | 323 return exists ? Directory::EXISTS : Directory::DOES_NOT_EXIST; |
| 324 } | 324 } |
| 325 | 325 |
| 326 | 326 |
| 327 Directory::ExistsResult Directory::Exists(const char* dir_name) { | 327 Directory::ExistsResult Directory::Exists(const char* dir_name) { |
| 328 const char* system_name = StringUtils::Utf8ToConsoleString(dir_name); | 328 const wchar_t* system_name = StringUtils::Utf8ToWide(dir_name); |
| 329 Directory::ExistsResult result = ExistsHelper(system_name); | 329 Directory::ExistsResult result = ExistsHelper(system_name); |
| 330 free(const_cast<char*>(system_name)); | 330 free(const_cast<wchar_t*>(system_name)); |
| 331 return result; | 331 return result; |
| 332 } | 332 } |
| 333 | 333 |
| 334 | 334 |
| 335 char* Directory::Current() { | 335 char* Directory::Current() { |
| 336 int length = GetCurrentDirectory(0, NULL); | 336 int length = GetCurrentDirectoryW(0, NULL); |
| 337 char* current = reinterpret_cast<char*>(malloc(length + 1)); | 337 wchar_t* current = new wchar_t[length + 1]; |
| 338 GetCurrentDirectory(length + 1, current); | 338 GetCurrentDirectoryW(length + 1, current); |
| 339 char* result = StringUtils::ConsoleStringToUtf8(current); | 339 char* result = StringUtils::WideToUtf8(current); |
| 340 free(current); | 340 delete[] current; |
| 341 return result; | 341 return result; |
| 342 } | 342 } |
| 343 | 343 |
| 344 | 344 |
| 345 bool Directory::Create(const char* dir_name) { | 345 bool Directory::Create(const char* dir_name) { |
| 346 const char* system_name = StringUtils::Utf8ToConsoleString(dir_name); | 346 const wchar_t* system_name = StringUtils::Utf8ToWide(dir_name); |
| 347 // If the directory already exists and is a directory do not | 347 // If the directory already exists and is a directory do not |
| 348 // attempt to create it again and treat it as a success. | 348 // attempt to create it again and treat it as a success. |
| 349 if (ExistsHelper(system_name) == EXISTS) { | 349 if (ExistsHelper(system_name) == EXISTS) { |
| 350 free(const_cast<char*>(system_name)); | 350 free(const_cast<wchar_t*>(system_name)); |
| 351 return true; | 351 return true; |
| 352 } | 352 } |
| 353 int create_status = CreateDirectory(system_name, NULL); | 353 int create_status = CreateDirectoryW(system_name, NULL); |
| 354 free(const_cast<char*>(system_name)); | 354 free(const_cast<wchar_t*>(system_name)); |
| 355 return (create_status != 0); | 355 return (create_status != 0); |
| 356 } | 356 } |
| 357 | 357 |
| 358 | 358 |
| 359 char* Directory::CreateTemp(const char* const_template) { | 359 char* Directory::CreateTemp(const char* const_template) { |
| 360 // Returns a new, unused directory name, modifying the contents of | 360 // Returns a new, unused directory name, modifying the contents of |
| 361 // dir_template. Creates this directory, with a default security | 361 // dir_template. Creates this directory, with a default security |
| 362 // descriptor inherited from its parent directory. | 362 // descriptor inherited from its parent directory. |
| 363 // The return value must be freed by the caller. | 363 // The return value must be freed by the caller. |
| 364 char* path = static_cast<char*>(malloc(MAX_PATH)); | 364 wchar_t* path = static_cast<wchar_t*>(malloc(MAX_PATH * sizeof(wchar_t))); |
| 365 int path_length; | 365 int path_length; |
| 366 if (0 == strncmp(const_template, "", 1)) { | 366 if (0 == strncmp(const_template, "", 1)) { |
| 367 path_length = GetTempPath(MAX_PATH, path); | 367 path_length = GetTempPathW(MAX_PATH, path); |
| 368 if (path_length == 0) { | 368 if (path_length == 0) { |
| 369 free(path); | 369 free(path); |
| 370 return NULL; | 370 return NULL; |
| 371 } | 371 } |
| 372 } else { | 372 } else { |
| 373 const char* system_template = | 373 const wchar_t* system_template = StringUtils::Utf8ToWide(const_template); |
| 374 StringUtils::Utf8ToConsoleString(const_template); | 374 _snwprintf(path, MAX_PATH, L"%s", system_template); |
| 375 snprintf(path, MAX_PATH, "%s", system_template); | 375 free(const_cast<wchar_t*>(system_template)); |
| 376 free(const_cast<char*>(system_template)); | 376 path_length = wcslen(path); |
| 377 path_length = strlen(path); | |
| 378 } | 377 } |
| 379 // Length of tempdir-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx is 44. | 378 // Length of tempdir-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx is 44. |
| 380 if (path_length > MAX_PATH - 44) { | 379 if (path_length > MAX_PATH - 44) { |
| 381 free(path); | 380 free(path); |
| 382 return NULL; | 381 return NULL; |
| 383 } | 382 } |
| 384 if ((path)[path_length - 1] == '\\') { | 383 if ((path)[path_length - 1] == L'\\') { |
| 385 // No base name for the directory - use "tempdir". | 384 // No base name for the directory - use "tempdir". |
| 386 snprintf(path + path_length, MAX_PATH - path_length, "tempdir"); | 385 _snwprintf(path + path_length, MAX_PATH - path_length, L"tempdir"); |
| 387 path_length = strlen(path); | 386 path_length = wcslen(path); |
| 388 } | 387 } |
| 389 | 388 |
| 390 UUID uuid; | 389 UUID uuid; |
| 391 RPC_STATUS status = UuidCreateSequential(&uuid); | 390 RPC_STATUS status = UuidCreateSequential(&uuid); |
| 392 if (status != RPC_S_OK && status != RPC_S_UUID_LOCAL_ONLY) { | 391 if (status != RPC_S_OK && status != RPC_S_UUID_LOCAL_ONLY) { |
| 393 free(path); | 392 free(path); |
| 394 return NULL; | 393 return NULL; |
| 395 } | 394 } |
| 396 RPC_CSTR uuid_string; | 395 RPC_WSTR uuid_string; |
| 397 status = UuidToString(&uuid, &uuid_string); | 396 status = UuidToStringW(&uuid, &uuid_string); |
| 398 if (status != RPC_S_OK) { | 397 if (status != RPC_S_OK) { |
| 399 free(path); | 398 free(path); |
| 400 return NULL; | 399 return NULL; |
| 401 } | 400 } |
| 402 | 401 |
| 403 snprintf(path + path_length, MAX_PATH - path_length, "-%s", uuid_string); | 402 _snwprintf(path + path_length, MAX_PATH - path_length, L"-%s", uuid_string); |
| 404 if (!CreateDirectory(path, NULL)) { | 403 RpcStringFreeW(&uuid_string); |
| 404 if (!CreateDirectoryW(path, NULL)) { |
| 405 free(path); | 405 free(path); |
| 406 return NULL; | 406 return NULL; |
| 407 } | 407 } |
| 408 char* result = StringUtils::ConsoleStringToUtf8(path); | 408 char* result = StringUtils::WideToUtf8(path); |
| 409 free(path); | 409 free(path); |
| 410 return result; | 410 return result; |
| 411 } | 411 } |
| 412 | 412 |
| 413 | 413 |
| 414 bool Directory::Delete(const char* dir_name, bool recursive) { | 414 bool Directory::Delete(const char* dir_name, bool recursive) { |
| 415 bool result = false; | 415 bool result = false; |
| 416 const char* system_dir_name = | 416 const wchar_t* system_dir_name = StringUtils::Utf8ToWide(dir_name); |
| 417 StringUtils::Utf8ToConsoleString(dir_name); | |
| 418 if (!recursive) { | 417 if (!recursive) { |
| 419 result = (RemoveDirectory(system_dir_name) != 0); | 418 result = (RemoveDirectoryW(system_dir_name) != 0); |
| 420 } else { | 419 } else { |
| 421 result = DeleteRecursively(system_dir_name); | 420 result = DeleteRecursively(system_dir_name); |
| 422 } | 421 } |
| 423 free(const_cast<char*>(system_dir_name)); | 422 free(const_cast<wchar_t*>(system_dir_name)); |
| 424 return result; | 423 return result; |
| 425 } | 424 } |
| 426 | 425 |
| 427 | 426 |
| 428 bool Directory::Rename(const char* path, const char* new_path) { | 427 bool Directory::Rename(const char* path, const char* new_path) { |
| 429 const char* system_path = StringUtils::Utf8ToConsoleString(path); | 428 const wchar_t* system_path = StringUtils::Utf8ToWide(path); |
| 430 const char* system_new_path = | 429 const wchar_t* system_new_path = StringUtils::Utf8ToWide(new_path); |
| 431 StringUtils::Utf8ToConsoleString(new_path); | |
| 432 ExistsResult exists = ExistsHelper(system_path); | 430 ExistsResult exists = ExistsHelper(system_path); |
| 433 if (exists != EXISTS) return false; | 431 if (exists != EXISTS) return false; |
| 434 ExistsResult new_exists = ExistsHelper(system_new_path); | 432 ExistsResult new_exists = ExistsHelper(system_new_path); |
| 435 // MoveFile does not allow replacing exising directories. Therefore, | 433 // MoveFile does not allow replacing exising directories. Therefore, |
| 436 // if the new_path is currently a directory we need to delete it | 434 // if the new_path is currently a directory we need to delete it |
| 437 // first. | 435 // first. |
| 438 if (new_exists == EXISTS) { | 436 if (new_exists == EXISTS) { |
| 439 bool success = DeleteRecursively(system_new_path); | 437 bool success = DeleteRecursively(system_new_path); |
| 440 if (!success) return false; | 438 if (!success) return false; |
| 441 } | 439 } |
| 442 DWORD flags = MOVEFILE_WRITE_THROUGH; | 440 DWORD flags = MOVEFILE_WRITE_THROUGH; |
| 443 int move_status = | 441 int move_status = |
| 444 MoveFileEx(system_path, system_new_path, flags); | 442 MoveFileExW(system_path, system_new_path, flags); |
| 445 free(const_cast<char*>(system_path)); | 443 free(const_cast<wchar_t*>(system_path)); |
| 446 free(const_cast<char*>(system_new_path)); | 444 free(const_cast<wchar_t*>(system_new_path)); |
| 447 return (move_status != 0); | 445 return (move_status != 0); |
| 448 } | 446 } |
| OLD | NEW |