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

Unified Diff: runtime/bin/directory_posix.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_posix.cc
diff --git a/runtime/bin/directory_posix.cc b/runtime/bin/directory_posix.cc
index c201988325b4052ea2bc21e6ddec98377d1036a4..9cad78824f6228ea1da59b8b4c55e40000db396b 100644
--- a/runtime/bin/directory_posix.cc
+++ b/runtime/bin/directory_posix.cc
@@ -27,30 +27,36 @@ static void SetOsErrorMessage(char* os_error_message,
}
-// Forward declaration.
+// Forward declarations.
static bool ListRecursively(const char* dir_name,
bool recursive,
Dart_Port dir_port,
Dart_Port file_port,
Dart_Port done_port,
Dart_Port error_port);
+static bool DeleteRecursively(const char* dir_name);
-static void ComputeFullPath(const char* dir_name,
+static bool ComputeFullPath(const char* dir_name,
char* path,
int* path_length) {
char* abs_path;
do {
abs_path = realpath(dir_name, path);
} while (abs_path == NULL && errno == EINTR);
- ASSERT(abs_path != NULL);
+ if (abs_path == NULL) {
+ return false;
+ }
*path_length = strlen(path);
size_t written = snprintf(path + *path_length,
Bill Hesse 2012/02/03 12:17:51 I would consider moving the addition of PathSepara
Mads Ager (google) 2012/02/03 12:37:12 I would like to keep this as is. That way the code
PATH_MAX - *path_length,
"%s",
File::PathSeparator());
- ASSERT(written == strlen(File::PathSeparator()));
+ if (written != strlen(File::PathSeparator())) {
+ return false;
+ }
*path_length += written;
+ return true;
}
@@ -68,7 +74,9 @@ static bool HandleDir(char* dir_name,
PATH_MAX - 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);
@@ -86,7 +94,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) {
@@ -95,10 +103,13 @@ static void HandleFile(char* file_name,
PATH_MAX - 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;
}
@@ -140,36 +151,48 @@ static bool ListRecursively(const char* dir_name,
return false;
}
- // Compute full path for the directory currently being listed.
+ // 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(PATH_MAX));
ASSERT(path != NULL);
int path_length = 0;
- ComputeFullPath(dir_name, path, &path_length);
+ bool valid = ComputeFullPath(dir_name, path, &path_length);
+ if (!valid) {
+ free(path);
+ PostError(error_port, "Directory listing failed for: ", dir_name, errno);
+ return false;
+ }
// Iterated the directory and post the directories and files to the
// ports.
- int success = 0;
- bool listing_error = false;
+ int read = 0;
+ bool success = true;
dirent entry;
dirent* result;
- while ((success = TEMP_FAILURE_RETRY(readdir_r(dir_pointer,
- &entry,
- &result))) == 0 &&
+ while ((read = TEMP_FAILURE_RETRY(readdir_r(dir_pointer,
+ &entry,
+ &result))) == 0 &&
result != NULL &&
- !listing_error) {
+ success) {
switch (entry.d_type) {
case DT_DIR:
- listing_error = listing_error || !HandleDir(entry.d_name,
- path,
- path_length,
- recursive,
- dir_port,
- file_port,
- done_port,
- error_port);
+ success = success && HandleDir(entry.d_name,
+ path,
+ path_length,
+ recursive,
+ dir_port,
+ file_port,
+ done_port,
+ error_port);
break;
case DT_REG:
- HandleFile(entry.d_name, path, path_length, file_port);
+ success = success && HandleFile(entry.d_name,
+ path,
+ path_length,
+ file_port);
break;
case DT_UNKNOWN: {
// On some file systems the entry type is not determined by
@@ -180,24 +203,30 @@ static bool ListRecursively(const char* dir_name,
PATH_MAX - path_length,
"%s",
entry.d_name);
- ASSERT(written == strlen(entry.d_name));
+ if (written != strlen(entry.d_name)) {
+ success = false;
+ break;
+ }
int lstat_success = TEMP_FAILURE_RETRY(lstat(path, &entry_info));
if (lstat_success == -1) {
- listing_error = true;
+ success = false;
PostError(error_port, "Directory listing failed for: ", path, errno);
break;
}
if ((entry_info.st_mode & S_IFMT) == S_IFDIR) {
- listing_error = listing_error || !HandleDir(entry.d_name,
- path,
- path_length,
- recursive,
- dir_port,
- file_port,
- done_port,
- error_port);
+ success = success && HandleDir(entry.d_name,
+ path,
+ path_length,
+ recursive,
+ dir_port,
+ file_port,
+ done_port,
+ error_port);
} else if ((entry_info.st_mode & S_IFMT) == S_IFREG) {
- HandleFile(entry.d_name, path, path_length, file_port);
+ success = success && HandleFile(entry.d_name,
+ path,
+ path_length,
+ file_port);
}
break;
}
@@ -206,9 +235,9 @@ static bool ListRecursively(const char* dir_name,
}
}
- if (success != 0) {
- listing_error = true;
- PostError(error_port, "Directory listing failed", "", success);
+ if (read != 0) {
+ success = false;
+ PostError(error_port, "Directory listing failed", "", read);
}
if (closedir(dir_pointer) == -1) {
@@ -216,7 +245,122 @@ 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,
+ PATH_MAX - path_length,
+ "%s",
+ file_name);
+ if (written != strlen(file_name)) {
+ return false;
+ }
+ return (remove(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,
+ PATH_MAX - path_length,
+ "%s",
+ dir_name);
+ if (written != strlen(dir_name)) {
+ return false;
+ }
+ return DeleteRecursively(path);
+ }
+ return true;
+}
+
+
+static bool DeleteRecursively(const char* dir_name) {
+ DIR* dir_pointer;
+ do {
+ dir_pointer = opendir(dir_name);
+ } while (dir_pointer == NULL && errno == EINTR);
+
+ if (dir_pointer == NULL) {
+ return false;
+ }
+
+ // 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(PATH_MAX));
+ ASSERT(path != NULL);
+ int path_length = 0;
+ bool valid = ComputeFullPath(dir_name, path, &path_length);
+ if (!valid) {
+ free(path);
+ return false;
+ }
+
+ // Iterate the directory and delete all files and directories.
+ int read = 0;
+ bool success = true;
+ dirent entry;
+ dirent* result;
+ while ((read = TEMP_FAILURE_RETRY(readdir_r(dir_pointer,
+ &entry,
+ &result))) == 0 &&
+ result != NULL &&
+ success) {
+ switch (entry.d_type) {
+ case DT_DIR:
+ success = success && DeleteDir(entry.d_name, path, path_length);
+ break;
+ case DT_REG:
+ success = success && DeleteFile(entry.d_name, path, path_length);
+ break;
+ case DT_UNKNOWN: {
+ // On some file systems the entry type is not determined by
+ // readdir_r. For those we use lstat to determine the entry
+ // type.
+ struct stat entry_info;
+ size_t written = snprintf(path + path_length,
+ PATH_MAX - path_length,
+ "%s",
+ entry.d_name);
+ if (written != strlen(entry.d_name)) {
+ success = false;
+ break;
+ }
+ int lstat_success = TEMP_FAILURE_RETRY(lstat(path, &entry_info));
+ if (lstat_success == -1) {
+ success = false;
+ break;
+ }
+ if ((entry_info.st_mode & S_IFMT) == S_IFDIR) {
+ success = success && DeleteDir(entry.d_name, path, path_length);
+ } else if ((entry_info.st_mode & S_IFMT) == S_IFREG) {
+ success = success && DeleteFile(entry.d_name, path, path_length);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ free(path);
+
+ if ((read != 0) ||
+ (closedir(dir_pointer) == -1) ||
+ (remove(dir_name) == -1)) {
+ return false;
+ }
+
+ return success;
}
@@ -309,6 +453,10 @@ int Directory::CreateTemp(const char* const_template,
}
-bool Directory::Delete(const char* dir_name) {
- return (TEMP_FAILURE_RETRY(rmdir(dir_name)) == 0);
+bool Directory::Delete(const char* dir_name, bool recursive) {
+ if (!recursive) {
+ return (TEMP_FAILURE_RETRY(remove(dir_name)) == 0);
+ } else {
+ return DeleteRecursively(dir_name);
+ }
}

Powered by Google App Engine
This is Rietveld 408576698