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

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: Fixing comment. 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..0bcc62b242f9c4ccf32405c65ec601977ab532db 100644
--- a/runtime/bin/directory_posix.cc
+++ b/runtime/bin/directory_posix.cc
@@ -27,13 +27,14 @@ 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,
@@ -220,6 +221,106 @@ static bool ListRecursively(const char* dir_name,
}
+static bool DeleteFile(char* file_name,
Bill Hesse 2012/02/02 17:24:39 Put a comment that strlen(path) may not be path_le
Mads Ager (google) 2012/02/03 11:48:54 This applies to all the methods in this file. I ha
+ char* path,
+ int path_length) {
+ size_t written = snprintf(path + path_length,
+ PATH_MAX - path_length,
+ "%s",
+ file_name);
+ ASSERT(written == strlen(file_name));
+ 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);
+ ASSERT(written == strlen(dir_name));
Bill Hesse 2012/02/02 17:24:39 In release mode, could a snprintf turn "long_path/
Mads Ager (google) 2012/02/03 11:48:54 Yes, that is not good. I have changed all the ASSE
+ 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.
+ char *path = static_cast<char*>(malloc(PATH_MAX));
+ ASSERT(path != NULL);
+ int path_length = 0;
+ ComputeFullPath(dir_name, path, &path_length);
Bill Hesse 2012/02/02 17:24:39 ASSERT on path_length here?
Mads Ager (google) 2012/02/03 11:48:54 Reworked so ComputeFullPath returns a failure stat
+
+ // Iterated the directory and delete all files and directories.
Bill Hesse 2012/02/02 17:24:39 Iterate the directory ...
Mads Ager (google) 2012/02/03 11:48:54 Done.
+ int success = 0;
+ bool error = false;
+ dirent entry;
+ dirent* result;
+ while ((success = TEMP_FAILURE_RETRY(readdir_r(dir_pointer,
+ &entry,
+ &result))) == 0 &&
+ result != NULL &&
+ !error) {
+ switch (entry.d_type) {
+ case DT_DIR:
+ error = error || !DeleteDir(entry.d_name, path, path_length);
+ break;
+ case DT_REG:
+ error = error || !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);
+ ASSERT(written == strlen(entry.d_name));
+ int lstat_success = TEMP_FAILURE_RETRY(lstat(path, &entry_info));
+ if (lstat_success == -1) {
+ error = true;
+ break;
+ }
+ if ((entry_info.st_mode & S_IFMT) == S_IFDIR) {
+ error = error || !DeleteDir(entry.d_name, path, path_length);
+ } else if ((entry_info.st_mode & S_IFMT) == S_IFREG) {
+ error = error || !DeleteFile(entry.d_name, path, path_length);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ free(path);
+
+ if ((success != 0) ||
+ (closedir(dir_pointer) == -1) ||
+ (remove(dir_name) == -1)) {
+ return false;
+ }
+
+ return !error;
Bill Hesse 2012/02/02 17:24:39 Every use of error really wants to use !error inst
Mads Ager (google) 2012/02/03 11:48:54 Good point. Renamed success->read, error->success
+}
+
+
void Directory::List(const char* dir_name,
bool recursive,
Dart_Port dir_port,
@@ -309,6 +410,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