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