Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(181)

Unified Diff: runtime/bin/directory_win.cc

Issue 9316066: Implement recursive directory deletion. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address comments. Created 8 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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);
+ }
}

Powered by Google App Engine
This is Rietveld 408576698