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