Chromium Code Reviews| Index: runtime/bin/directory_win.cc |
| diff --git a/runtime/bin/directory_win.cc b/runtime/bin/directory_win.cc |
| index 5070c9c39c1dff61178a8d38cc0ec4848654199f..7547c8da65838f911943d83d81c5227c7b83d4f7 100644 |
| --- a/runtime/bin/directory_win.cc |
| +++ b/runtime/bin/directory_win.cc |
| @@ -1,4 +1,4 @@ |
| -// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| @@ -39,6 +39,7 @@ static bool ListRecursively(const char* dir_name, |
| Dart_Port file_port, |
| Dart_Port done_port, |
| Dart_Port error_port); |
| +static bool DeleteRecursively(const char* dir_name); |
| static bool HandleDir(char* dir_name, |
| @@ -55,7 +56,9 @@ static bool HandleDir(char* dir_name, |
| MAX_PATH - path_length, |
| "%s", |
| dir_name); |
| - ASSERT(written == strlen(dir_name)); |
| + if (written != strlen(dir_name)) { |
| + return false; |
| + } |
| if (dir_port != 0) { |
| Dart_Handle name = Dart_NewString(path); |
| Dart_Post(dir_port, name); |
| @@ -73,7 +76,7 @@ static bool HandleDir(char* dir_name, |
| } |
| -static void HandleFile(char* file_name, |
| +static bool HandleFile(char* file_name, |
| char* path, |
| int path_length, |
| Dart_Port file_port) { |
| @@ -82,10 +85,13 @@ static void HandleFile(char* file_name, |
| MAX_PATH - path_length, |
| "%s", |
| file_name); |
| - ASSERT(written == strlen(file_name)); |
| + if (written != strlen(file_name)) { |
| + return false; |
| + }; |
| Dart_Handle name = Dart_NewString(path); |
| Dart_Post(file_port, name); |
| } |
| + return true; |
| } |
| @@ -108,27 +114,36 @@ static bool HandleEntry(LPWIN32_FIND_DATA find_file_data, |
| done_port, |
| error_port); |
| } else { |
| - HandleFile(find_file_data->cFileName, path, path_length, file_port); |
| - return true; |
| + return HandleFile(find_file_data->cFileName, path, path_length, file_port); |
| } |
| } |
| -static void ComputeFullSearchPath(const char* dir_name, |
| +// ComputeFullSearchPath must be called with a path array of size at |
| +// least MAX_PATH. |
|
Bill Hesse
2012/02/03 12:17:51
On Windows, ComputeFullSearchPath does do somethin
|
| +static bool ComputeFullSearchPath(const char* dir_name, |
| char* path, |
| int* path_length) { |
| // GetFullPathName only works in a multi-threaded environment if |
| // SetCurrentDirectory is not used. We currently have no plan for |
| // exposing SetCurrentDirectory. |
| - size_t written = |
| - GetFullPathName(dir_name, MAX_PATH - *path_length, path, NULL); |
| - *path_length += written; |
| + size_t written = GetFullPathName(dir_name, MAX_PATH, path, NULL); |
| + // GetFullPathName only accepts input strings of size less than |
| + // MAX_PATH and returns 0 to indicate failure for paths longer than |
| + // that. Therefore the path buffer is always big enough. |
| + if (written == 0) { |
| + return false; |
| + } |
| + *path_length = written; |
| written = snprintf(path + *path_length, |
| MAX_PATH - *path_length, |
| "%s", |
| "\\*"); |
| - ASSERT(written == 2); |
| + if (written != 2) { |
| + return false; |
| + } |
| *path_length += written; |
| + return true; |
| } |
| static void PostError(Dart_Port error_port, |
| @@ -140,11 +155,11 @@ static void PostError(Dart_Port error_port, |
| strlen(prefix) + strlen(suffix) + strlen(error_str) + 3; |
| char* message = static_cast<char*>(malloc(error_message_size + 1)); |
| size_t written = snprintf(message, |
| - error_message_size + 1, |
| - "%s%s (%s)", |
| - prefix, |
| - suffix, |
| - error_str); |
| + error_message_size + 1, |
| + "%s%s (%s)", |
| + prefix, |
| + suffix, |
| + error_str); |
| ASSERT(written == error_message_size); |
| free(error_str); |
| Dart_Post(error_port, Dart_NewString(message)); |
| @@ -159,9 +174,19 @@ static bool ListRecursively(const char* dir_name, |
| Dart_Port file_port, |
| Dart_Port done_port, |
| Dart_Port error_port) { |
| + // Compute full path for the directory currently being listed. The |
| + // path buffer will be used to construct the current path in the |
| + // recursive traversal. path_length does not always equal |
| + // strlen(path) but indicates the current prefix of path that is the |
| + // path of the current directory in the traversal. |
| char* path = static_cast<char*>(malloc(MAX_PATH)); |
| int path_length = 0; |
| - ComputeFullSearchPath(dir_name, path, &path_length); |
| + bool valid = ComputeFullSearchPath(dir_name, path, &path_length); |
| + if (!valid) { |
| + PostError(error_port, "Directory listing failed for: ", dir_name); |
| + free(path); |
| + return false; |
| + } |
| WIN32_FIND_DATA find_file_data; |
| HANDLE find_handle = FindFirstFile(path, &find_file_data); |
| @@ -176,28 +201,28 @@ static bool ListRecursively(const char* dir_name, |
| return false; |
| } |
| - bool listing_error = !HandleEntry(&find_file_data, |
| - path, |
| - path_length, |
| - recursive, |
| - dir_port, |
| - file_port, |
| - done_port, |
| - error_port); |
| - |
| - while ((FindNextFile(find_handle, &find_file_data) != 0) && !listing_error) { |
| - listing_error = listing_error || !HandleEntry(&find_file_data, |
| - path, |
| - path_length, |
| - recursive, |
| - dir_port, |
| - file_port, |
| - done_port, |
| - error_port); |
| + bool success = HandleEntry(&find_file_data, |
| + path, |
| + path_length, |
| + recursive, |
| + dir_port, |
| + file_port, |
| + done_port, |
| + error_port); |
| + |
| + while ((FindNextFile(find_handle, &find_file_data) != 0) && success) { |
| + success = success && HandleEntry(&find_file_data, |
| + path, |
| + path_length, |
| + recursive, |
| + dir_port, |
| + file_port, |
| + done_port, |
| + error_port); |
| } |
| if (GetLastError() != ERROR_NO_MORE_FILES) { |
| - listing_error = true; |
| + success = false; |
| PostError(error_port, "Directory listing failed", ""); |
| } |
| @@ -206,7 +231,95 @@ static bool ListRecursively(const char* dir_name, |
| } |
| free(path); |
| - return !listing_error; |
| + return success; |
| +} |
| + |
| + |
| +static bool DeleteFile(char* file_name, |
| + char* path, |
| + int path_length) { |
| + size_t written = snprintf(path + path_length, |
| + MAX_PATH - path_length, |
| + "%s", |
| + file_name); |
| + if (written != strlen(file_name)) { |
| + return false; |
| + } |
| + return (DeleteFile(path) != 0); |
| +} |
| + |
| + |
| +static bool DeleteDir(char* dir_name, |
| + char* path, |
| + int path_length) { |
| + if (strcmp(dir_name, ".") != 0 && |
| + strcmp(dir_name, "..") != 0) { |
| + size_t written = snprintf(path + path_length, |
| + MAX_PATH - path_length, |
| + "%s", |
| + dir_name); |
| + if (written != strlen(dir_name)) { |
| + return false; |
| + } |
| + return DeleteRecursively(path); |
| + } |
| + return true; |
| +} |
| + |
| + |
| +static bool DeleteEntry(LPWIN32_FIND_DATA find_file_data, |
| + char* path, |
| + int path_length) { |
| + DWORD attributes = find_file_data->dwFileAttributes; |
| + if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { |
| + return DeleteDir(find_file_data->cFileName, path, path_length); |
| + } else { |
| + return DeleteFile(find_file_data->cFileName, path, path_length); |
| + } |
| +} |
| + |
| + |
| +static bool DeleteRecursively(const char* dir_name) { |
| + // Compute full path for the directory currently being deleted. The |
| + // path buffer will be used to construct the current path in the |
| + // recursive traversal. path_length does not always equal |
| + // strlen(path) but indicates the current prefix of path that is the |
| + // path of the current directory in the traversal. |
| + char* path = static_cast<char*>(malloc(MAX_PATH)); |
| + int path_length = 0; |
| + bool valid = ComputeFullSearchPath(dir_name, path, &path_length); |
| + if (!valid) { |
| + free(path); |
| + return false; |
| + } |
| + |
| + WIN32_FIND_DATA find_file_data; |
| + HANDLE find_handle = FindFirstFile(path, &find_file_data); |
| + |
| + // Adjust the path by removing the '*' used for the search. |
| + path_length -= 1; |
| + path[path_length] = '\0'; |
| + |
| + if (find_handle == INVALID_HANDLE_VALUE) { |
| + free(path); |
| + return false; |
| + } |
| + |
| + bool success = DeleteEntry(&find_file_data, path, path_length); |
| + |
| + while ((FindNextFile(find_handle, &find_file_data) != 0) && success) { |
| + success = success && DeleteEntry(&find_file_data, path, path_length); |
| + } |
| + |
| + free(path); |
| + |
| + if ((GetLastError() != ERROR_NO_MORE_FILES) || |
| + (FindClose(find_handle) == 0) || |
| + (RemoveDirectory(dir_name) == 0)) { |
| + return false; |
| + } |
| + |
| + return success; |
| } |
| @@ -327,6 +440,10 @@ int Directory::CreateTemp(const char* const_template, |
| } |
| -bool Directory::Delete(const char* dir_name) { |
| - return (RemoveDirectory(dir_name) != 0); |
| +bool Directory::Delete(const char* dir_name, bool recursive) { |
| + if (!recursive) { |
| + return (RemoveDirectory(dir_name) != 0); |
| + } else { |
| + return DeleteRecursively(dir_name); |
| + } |
| } |