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); |
+ } |
} |