Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011, 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/platform.h" | 10 #include "bin/platform.h" |
| 11 | 11 |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 32 } | 32 } |
| 33 | 33 |
| 34 | 34 |
| 35 // Forward declaration. | 35 // Forward declaration. |
| 36 static bool ListRecursively(const char* dir_name, | 36 static bool ListRecursively(const char* dir_name, |
| 37 bool recursive, | 37 bool recursive, |
| 38 Dart_Port dir_port, | 38 Dart_Port dir_port, |
| 39 Dart_Port file_port, | 39 Dart_Port file_port, |
| 40 Dart_Port done_port, | 40 Dart_Port done_port, |
| 41 Dart_Port error_port); | 41 Dart_Port error_port); |
| 42 static bool DeleteRecursively(const char* dir_name); | |
| 42 | 43 |
| 43 | 44 |
| 44 static bool HandleDir(char* dir_name, | 45 static bool HandleDir(char* dir_name, |
| 45 char* path, | 46 char* path, |
| 46 int path_length, | 47 int path_length, |
| 47 bool recursive, | 48 bool recursive, |
| 48 Dart_Port dir_port, | 49 Dart_Port dir_port, |
| 49 Dart_Port file_port, | 50 Dart_Port file_port, |
| 50 Dart_Port done_port, | 51 Dart_Port done_port, |
| 51 Dart_Port error_port) { | 52 Dart_Port error_port) { |
| 52 if (strcmp(dir_name, ".") != 0 && | 53 if (strcmp(dir_name, ".") != 0 && |
| 53 strcmp(dir_name, "..") != 0) { | 54 strcmp(dir_name, "..") != 0) { |
| 54 size_t written = snprintf(path + path_length, | 55 size_t written = snprintf(path + path_length, |
| 55 MAX_PATH - path_length, | 56 MAX_PATH - path_length, |
| 56 "%s", | 57 "%s", |
| 57 dir_name); | 58 dir_name); |
| 58 ASSERT(written == strlen(dir_name)); | 59 if (written != strlen(dir_name)) { |
| 60 return false; | |
| 61 } | |
| 59 if (dir_port != 0) { | 62 if (dir_port != 0) { |
| 60 Dart_Handle name = Dart_NewString(path); | 63 Dart_Handle name = Dart_NewString(path); |
| 61 Dart_Post(dir_port, name); | 64 Dart_Post(dir_port, name); |
| 62 } | 65 } |
| 63 if (recursive) { | 66 if (recursive) { |
| 64 return ListRecursively(path, | 67 return ListRecursively(path, |
| 65 recursive, | 68 recursive, |
| 66 dir_port, | 69 dir_port, |
| 67 file_port, | 70 file_port, |
| 68 done_port, | 71 done_port, |
| 69 error_port); | 72 error_port); |
| 70 } | 73 } |
| 71 } | 74 } |
| 72 return true; | 75 return true; |
| 73 } | 76 } |
| 74 | 77 |
| 75 | 78 |
| 76 static void HandleFile(char* file_name, | 79 static bool HandleFile(char* file_name, |
| 77 char* path, | 80 char* path, |
| 78 int path_length, | 81 int path_length, |
| 79 Dart_Port file_port) { | 82 Dart_Port file_port) { |
| 80 if (file_port != 0) { | 83 if (file_port != 0) { |
| 81 size_t written = snprintf(path + path_length, | 84 size_t written = snprintf(path + path_length, |
| 82 MAX_PATH - path_length, | 85 MAX_PATH - path_length, |
| 83 "%s", | 86 "%s", |
| 84 file_name); | 87 file_name); |
| 85 ASSERT(written == strlen(file_name)); | 88 if (written != strlen(file_name)) { |
| 89 return false; | |
| 90 }; | |
| 86 Dart_Handle name = Dart_NewString(path); | 91 Dart_Handle name = Dart_NewString(path); |
| 87 Dart_Post(file_port, name); | 92 Dart_Post(file_port, name); |
| 88 } | 93 } |
| 94 return true; | |
| 89 } | 95 } |
| 90 | 96 |
| 91 | 97 |
| 92 static bool HandleEntry(LPWIN32_FIND_DATA find_file_data, | 98 static bool HandleEntry(LPWIN32_FIND_DATA find_file_data, |
| 93 char* path, | 99 char* path, |
| 94 int path_length, | 100 int path_length, |
| 95 bool recursive, | 101 bool recursive, |
| 96 Dart_Port dir_port, | 102 Dart_Port dir_port, |
| 97 Dart_Port file_port, | 103 Dart_Port file_port, |
| 98 Dart_Port done_port, | 104 Dart_Port done_port, |
| 99 Dart_Port error_port) { | 105 Dart_Port error_port) { |
| 100 DWORD attributes = find_file_data->dwFileAttributes; | 106 DWORD attributes = find_file_data->dwFileAttributes; |
| 101 if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { | 107 if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { |
| 102 return HandleDir(find_file_data->cFileName, | 108 return HandleDir(find_file_data->cFileName, |
| 103 path, | 109 path, |
| 104 path_length, | 110 path_length, |
| 105 recursive, | 111 recursive, |
| 106 dir_port, | 112 dir_port, |
| 107 file_port, | 113 file_port, |
| 108 done_port, | 114 done_port, |
| 109 error_port); | 115 error_port); |
| 110 } else { | 116 } else { |
| 111 HandleFile(find_file_data->cFileName, path, path_length, file_port); | 117 return HandleFile(find_file_data->cFileName, path, path_length, file_port); |
| 112 return true; | |
| 113 } | 118 } |
| 114 } | 119 } |
| 115 | 120 |
| 116 | 121 |
| 117 static void ComputeFullSearchPath(const char* dir_name, | 122 // ComputeFullSearchPath must be called with a path array of size at |
| 123 // least MAX_PATH. | |
|
Bill Hesse
2012/02/03 12:17:51
On Windows, ComputeFullSearchPath does do somethin
| |
| 124 static bool ComputeFullSearchPath(const char* dir_name, | |
| 118 char* path, | 125 char* path, |
| 119 int* path_length) { | 126 int* path_length) { |
| 120 // GetFullPathName only works in a multi-threaded environment if | 127 // GetFullPathName only works in a multi-threaded environment if |
| 121 // SetCurrentDirectory is not used. We currently have no plan for | 128 // SetCurrentDirectory is not used. We currently have no plan for |
| 122 // exposing SetCurrentDirectory. | 129 // exposing SetCurrentDirectory. |
| 123 size_t written = | 130 size_t written = GetFullPathName(dir_name, MAX_PATH, path, NULL); |
| 124 GetFullPathName(dir_name, MAX_PATH - *path_length, path, NULL); | 131 // GetFullPathName only accepts input strings of size less than |
| 125 *path_length += written; | 132 // MAX_PATH and returns 0 to indicate failure for paths longer than |
| 133 // that. Therefore the path buffer is always big enough. | |
| 134 if (written == 0) { | |
| 135 return false; | |
| 136 } | |
| 137 *path_length = written; | |
| 126 written = snprintf(path + *path_length, | 138 written = snprintf(path + *path_length, |
| 127 MAX_PATH - *path_length, | 139 MAX_PATH - *path_length, |
| 128 "%s", | 140 "%s", |
| 129 "\\*"); | 141 "\\*"); |
| 130 ASSERT(written == 2); | 142 if (written != 2) { |
| 143 return false; | |
| 144 } | |
| 131 *path_length += written; | 145 *path_length += written; |
| 146 return true; | |
| 132 } | 147 } |
| 133 | 148 |
| 134 static void PostError(Dart_Port error_port, | 149 static void PostError(Dart_Port error_port, |
| 135 const char* prefix, | 150 const char* prefix, |
| 136 const char* suffix) { | 151 const char* suffix) { |
| 137 if (error_port != 0) { | 152 if (error_port != 0) { |
| 138 char* error_str = Platform::StrError(GetLastError()); | 153 char* error_str = Platform::StrError(GetLastError()); |
| 139 int error_message_size = | 154 int error_message_size = |
| 140 strlen(prefix) + strlen(suffix) + strlen(error_str) + 3; | 155 strlen(prefix) + strlen(suffix) + strlen(error_str) + 3; |
| 141 char* message = static_cast<char*>(malloc(error_message_size + 1)); | 156 char* message = static_cast<char*>(malloc(error_message_size + 1)); |
| 142 size_t written = snprintf(message, | 157 size_t written = snprintf(message, |
| 143 error_message_size + 1, | 158 error_message_size + 1, |
| 144 "%s%s (%s)", | 159 "%s%s (%s)", |
| 145 prefix, | 160 prefix, |
| 146 suffix, | 161 suffix, |
| 147 error_str); | 162 error_str); |
| 148 ASSERT(written == error_message_size); | 163 ASSERT(written == error_message_size); |
| 149 free(error_str); | 164 free(error_str); |
| 150 Dart_Post(error_port, Dart_NewString(message)); | 165 Dart_Post(error_port, Dart_NewString(message)); |
| 151 free(message); | 166 free(message); |
| 152 } | 167 } |
| 153 } | 168 } |
| 154 | 169 |
| 155 | 170 |
| 156 static bool ListRecursively(const char* dir_name, | 171 static bool ListRecursively(const char* dir_name, |
| 157 bool recursive, | 172 bool recursive, |
| 158 Dart_Port dir_port, | 173 Dart_Port dir_port, |
| 159 Dart_Port file_port, | 174 Dart_Port file_port, |
| 160 Dart_Port done_port, | 175 Dart_Port done_port, |
| 161 Dart_Port error_port) { | 176 Dart_Port error_port) { |
| 177 // Compute full path for the directory currently being listed. The | |
| 178 // path buffer will be used to construct the current path in the | |
| 179 // recursive traversal. path_length does not always equal | |
| 180 // strlen(path) but indicates the current prefix of path that is the | |
| 181 // path of the current directory in the traversal. | |
| 162 char* path = static_cast<char*>(malloc(MAX_PATH)); | 182 char* path = static_cast<char*>(malloc(MAX_PATH)); |
| 163 int path_length = 0; | 183 int path_length = 0; |
| 164 ComputeFullSearchPath(dir_name, path, &path_length); | 184 bool valid = ComputeFullSearchPath(dir_name, path, &path_length); |
| 185 if (!valid) { | |
| 186 PostError(error_port, "Directory listing failed for: ", dir_name); | |
| 187 free(path); | |
| 188 return false; | |
| 189 } | |
| 165 | 190 |
| 166 WIN32_FIND_DATA find_file_data; | 191 WIN32_FIND_DATA find_file_data; |
| 167 HANDLE find_handle = FindFirstFile(path, &find_file_data); | 192 HANDLE find_handle = FindFirstFile(path, &find_file_data); |
| 168 | 193 |
| 169 // Adjust the path by removing the '*' used for the search. | 194 // Adjust the path by removing the '*' used for the search. |
| 170 path_length -= 1; | 195 path_length -= 1; |
| 171 path[path_length] = '\0'; | 196 path[path_length] = '\0'; |
| 172 | 197 |
| 173 if (find_handle == INVALID_HANDLE_VALUE) { | 198 if (find_handle == INVALID_HANDLE_VALUE) { |
| 174 PostError(error_port, "Directory listing failed for: ", path); | 199 PostError(error_port, "Directory listing failed for: ", path); |
| 175 free(path); | 200 free(path); |
| 176 return false; | 201 return false; |
| 177 } | 202 } |
| 178 | 203 |
| 179 bool listing_error = !HandleEntry(&find_file_data, | 204 bool success = HandleEntry(&find_file_data, |
| 180 path, | 205 path, |
| 181 path_length, | 206 path_length, |
| 182 recursive, | 207 recursive, |
| 183 dir_port, | 208 dir_port, |
| 184 file_port, | 209 file_port, |
| 185 done_port, | 210 done_port, |
| 186 error_port); | 211 error_port); |
| 187 | 212 |
| 188 while ((FindNextFile(find_handle, &find_file_data) != 0) && !listing_error) { | 213 while ((FindNextFile(find_handle, &find_file_data) != 0) && success) { |
| 189 listing_error = listing_error || !HandleEntry(&find_file_data, | 214 success = success && HandleEntry(&find_file_data, |
| 190 path, | 215 path, |
| 191 path_length, | 216 path_length, |
| 192 recursive, | 217 recursive, |
| 193 dir_port, | 218 dir_port, |
| 194 file_port, | 219 file_port, |
| 195 done_port, | 220 done_port, |
| 196 error_port); | 221 error_port); |
| 197 } | 222 } |
| 198 | 223 |
| 199 if (GetLastError() != ERROR_NO_MORE_FILES) { | 224 if (GetLastError() != ERROR_NO_MORE_FILES) { |
| 200 listing_error = true; | 225 success = false; |
| 201 PostError(error_port, "Directory listing failed", ""); | 226 PostError(error_port, "Directory listing failed", ""); |
| 202 } | 227 } |
| 203 | 228 |
| 204 if (FindClose(find_handle) == 0) { | 229 if (FindClose(find_handle) == 0) { |
| 205 PostError(error_port, "Failed to close directory", ""); | 230 PostError(error_port, "Failed to close directory", ""); |
| 206 } | 231 } |
| 207 free(path); | 232 free(path); |
| 208 | 233 |
| 209 return !listing_error; | 234 return success; |
| 210 } | 235 } |
| 211 | 236 |
| 212 | 237 |
| 238 static bool DeleteFile(char* file_name, | |
| 239 char* path, | |
| 240 int path_length) { | |
| 241 size_t written = snprintf(path + path_length, | |
| 242 MAX_PATH - path_length, | |
| 243 "%s", | |
| 244 file_name); | |
| 245 if (written != strlen(file_name)) { | |
| 246 return false; | |
| 247 } | |
| 248 return (DeleteFile(path) != 0); | |
| 249 } | |
| 250 | |
| 251 | |
| 252 static bool DeleteDir(char* dir_name, | |
| 253 char* path, | |
| 254 int path_length) { | |
| 255 if (strcmp(dir_name, ".") != 0 && | |
| 256 strcmp(dir_name, "..") != 0) { | |
| 257 size_t written = snprintf(path + path_length, | |
| 258 MAX_PATH - path_length, | |
| 259 "%s", | |
| 260 dir_name); | |
| 261 if (written != strlen(dir_name)) { | |
| 262 return false; | |
| 263 } | |
| 264 return DeleteRecursively(path); | |
| 265 } | |
| 266 return true; | |
| 267 } | |
| 268 | |
| 269 | |
| 270 static bool DeleteEntry(LPWIN32_FIND_DATA find_file_data, | |
| 271 char* path, | |
| 272 int path_length) { | |
| 273 DWORD attributes = find_file_data->dwFileAttributes; | |
| 274 if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { | |
| 275 return DeleteDir(find_file_data->cFileName, path, path_length); | |
| 276 } else { | |
| 277 return DeleteFile(find_file_data->cFileName, path, path_length); | |
| 278 } | |
| 279 } | |
| 280 | |
| 281 | |
| 282 static bool DeleteRecursively(const char* dir_name) { | |
| 283 // Compute full path for the directory currently being deleted. The | |
| 284 // path buffer will be used to construct the current path in the | |
| 285 // recursive traversal. path_length does not always equal | |
| 286 // strlen(path) but indicates the current prefix of path that is the | |
| 287 // path of the current directory in the traversal. | |
| 288 char* path = static_cast<char*>(malloc(MAX_PATH)); | |
| 289 int path_length = 0; | |
| 290 bool valid = ComputeFullSearchPath(dir_name, path, &path_length); | |
| 291 if (!valid) { | |
| 292 free(path); | |
| 293 return false; | |
| 294 } | |
| 295 | |
| 296 WIN32_FIND_DATA find_file_data; | |
| 297 HANDLE find_handle = FindFirstFile(path, &find_file_data); | |
| 298 | |
| 299 // Adjust the path by removing the '*' used for the search. | |
| 300 path_length -= 1; | |
| 301 path[path_length] = '\0'; | |
| 302 | |
| 303 if (find_handle == INVALID_HANDLE_VALUE) { | |
| 304 free(path); | |
| 305 return false; | |
| 306 } | |
| 307 | |
| 308 bool success = DeleteEntry(&find_file_data, path, path_length); | |
| 309 | |
| 310 while ((FindNextFile(find_handle, &find_file_data) != 0) && success) { | |
| 311 success = success && DeleteEntry(&find_file_data, path, path_length); | |
| 312 } | |
| 313 | |
| 314 free(path); | |
| 315 | |
| 316 if ((GetLastError() != ERROR_NO_MORE_FILES) || | |
| 317 (FindClose(find_handle) == 0) || | |
| 318 (RemoveDirectory(dir_name) == 0)) { | |
| 319 return false; | |
| 320 } | |
| 321 | |
| 322 return success; | |
| 323 } | |
| 324 | |
| 325 | |
| 213 void Directory::List(const char* dir_name, | 326 void Directory::List(const char* dir_name, |
| 214 bool recursive, | 327 bool recursive, |
| 215 Dart_Port dir_port, | 328 Dart_Port dir_port, |
| 216 Dart_Port file_port, | 329 Dart_Port file_port, |
| 217 Dart_Port done_port, | 330 Dart_Port done_port, |
| 218 Dart_Port error_port) { | 331 Dart_Port error_port) { |
| 219 bool result = ListRecursively(dir_name, | 332 bool result = ListRecursively(dir_name, |
| 220 recursive, | 333 recursive, |
| 221 dir_port, | 334 dir_port, |
| 222 file_port, | 335 file_port, |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 320 free(*path); | 433 free(*path); |
| 321 *path = NULL; | 434 *path = NULL; |
| 322 int error_code = | 435 int error_code = |
| 323 SetOsErrorMessage(os_error_message, os_error_message_len); | 436 SetOsErrorMessage(os_error_message, os_error_message_len); |
| 324 return error_code; | 437 return error_code; |
| 325 } | 438 } |
| 326 return 0; | 439 return 0; |
| 327 } | 440 } |
| 328 | 441 |
| 329 | 442 |
| 330 bool Directory::Delete(const char* dir_name) { | 443 bool Directory::Delete(const char* dir_name, bool recursive) { |
| 331 return (RemoveDirectory(dir_name) != 0); | 444 if (!recursive) { |
| 445 return (RemoveDirectory(dir_name) != 0); | |
| 446 } else { | |
| 447 return DeleteRecursively(dir_name); | |
| 448 } | |
| 332 } | 449 } |
| OLD | NEW |