| Index: runtime/bin/directory_macos.cc
|
| diff --git a/runtime/bin/directory_macos.cc b/runtime/bin/directory_macos.cc
|
| index 241fce2f9cd31ae2123d67e5c95b3897afe2bb3a..5b02a21402c8ca10986e1f0bf0b6286d2feaf1ed 100644
|
| --- a/runtime/bin/directory_macos.cc
|
| +++ b/runtime/bin/directory_macos.cc
|
| @@ -13,12 +13,36 @@
|
| #include "bin/file.h"
|
| #include "bin/platform.h"
|
|
|
| +class PathBuffer {
|
| + public:
|
| + PathBuffer() : length(0) { }
|
| +
|
| +
|
| +
|
| + char data[PATH_MAX + 1];
|
| + int length;
|
| +
|
| + bool Add(const char* name) {
|
| + size_t written = snprintf(data + length,
|
| + PATH_MAX - length,
|
| + "%s",
|
| + name);
|
| + data[PATH_MAX] = '\0';
|
| + if (written == strnlen(name, PATH_MAX + 1)) {
|
| + length += written;
|
| + return true;
|
| + } else {
|
| + errno = ENAMETOOLONG;
|
| + return false;
|
| + }
|
| + }
|
| +
|
| + void Reset(int new_length) {
|
| + length = new_length;
|
| + data[length] = '\0';
|
| + }
|
| +};
|
|
|
| -static char* SafeStrNCpy(char* dest, const char* src, size_t n) {
|
| - strncpy(dest, src, n);
|
| - dest[n - 1] = '\0';
|
| - return dest;
|
| -}
|
|
|
|
|
| // Forward declarations.
|
| @@ -28,73 +52,53 @@ static bool ListRecursively(const char* dir_name,
|
| static bool DeleteRecursively(const char* dir_name);
|
|
|
|
|
| -static bool ComputeFullPath(const char* dir_name,
|
| - char* path,
|
| - int* path_length) {
|
| +static void PostError(DirectoryListing *listing,
|
| + const char* dir_name) {
|
| + listing->HandleError(dir_name);
|
| +}
|
| +
|
| +
|
| +static PathBuffer* ComputeFullPath(const char* dir_name) {
|
| + PathBuffer* path = new PathBuffer();
|
| char* abs_path;
|
| do {
|
| - abs_path = realpath(dir_name, path);
|
| + abs_path = realpath(dir_name, path->data);
|
| } while (abs_path == NULL && errno == EINTR);
|
| if (abs_path == NULL) {
|
| - return false;
|
| + delete path;
|
| + return NULL;
|
| }
|
| - *path_length = strlen(path);
|
| - size_t written = snprintf(path + *path_length,
|
| - PATH_MAX - *path_length,
|
| - "%s",
|
| - File::PathSeparator());
|
| - if (written != strlen(File::PathSeparator())) {
|
| - return false;
|
| + path->length = strnlen(path->data, PATH_MAX);
|
| + if (path->Add(File::PathSeparator())) {
|
| + return path;
|
| + } else {
|
| + delete path;
|
| + return NULL;
|
| }
|
| - *path_length += written;
|
| - return true;
|
| }
|
|
|
| -
|
| static bool HandleDir(char* dir_name,
|
| - char* path,
|
| - int path_length,
|
| + PathBuffer* path,
|
| bool recursive,
|
| DirectoryListing *listing) {
|
| - 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;
|
| - }
|
| - bool ok = listing->HandleDirectory(path);
|
| - if (!ok) return ok;
|
| - if (recursive) {
|
| - return ListRecursively(path, recursive, listing);
|
| - }
|
| + if (strcmp(dir_name, ".") == 0) return true;
|
| + if (strcmp(dir_name, "..") == 0) return true;
|
| + if (!path->Add(dir_name)) {
|
| + PostError(listing, path->data);
|
| + return false;
|
| }
|
| - return true;
|
| + return listing->HandleDirectory(path->data) &&
|
| + (!recursive || ListRecursively(path->data, recursive, listing));
|
| }
|
|
|
| -
|
| static bool HandleFile(char* file_name,
|
| - char* path,
|
| - int path_length,
|
| + PathBuffer* path,
|
| DirectoryListing *listing) {
|
| - // TODO(sgjesse): Pass flags to indicate whether file responses are
|
| - // needed.
|
| - size_t written = snprintf(path + path_length,
|
| - PATH_MAX - path_length,
|
| - "%s",
|
| - file_name);
|
| - if (written != strlen(file_name)) {
|
| + if (!path->Add(file_name)) {
|
| + PostError(listing, path->data);
|
| return false;
|
| }
|
| - return listing->HandleFile(path);
|
| -}
|
| -
|
| -
|
| -static void PostError(DirectoryListing *listing,
|
| - const char* dir_name) {
|
| - listing->HandleError(dir_name);
|
| + return listing->HandleFile(path->data);
|
| }
|
|
|
|
|
| @@ -115,38 +119,32 @@ static bool ListRecursively(const char* dir_name,
|
| // 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);
|
| + PathBuffer* path = ComputeFullPath(dir_name);
|
| + if (path == NULL) {
|
| PostError(listing, dir_name);
|
| return false;
|
| }
|
| -
|
| - // Iterated the directory and post the directories and files to the
|
| + // Iterate the directory and post the directories and files to the
|
| // ports.
|
| - int read = 0;
|
| + int path_length = path->length;
|
| + int status = 0;
|
| bool success = true;
|
| dirent entry;
|
| dirent* result;
|
| - while ((read = TEMP_FAILURE_RETRY(readdir_r(dir_pointer,
|
| - &entry,
|
| - &result))) == 0 &&
|
| + while ((status = TEMP_FAILURE_RETRY(readdir_r(dir_pointer,
|
| + &entry,
|
| + &result))) == 0 &&
|
| result != NULL) {
|
| switch (entry.d_type) {
|
| case DT_DIR:
|
| success = HandleDir(entry.d_name,
|
| path,
|
| - path_length,
|
| recursive,
|
| listing) && success;
|
| break;
|
| case DT_REG:
|
| success = HandleFile(entry.d_name,
|
| path,
|
| - path_length,
|
| listing) && success;
|
| break;
|
| case DT_LNK:
|
| @@ -156,30 +154,25 @@ static bool ListRecursively(const char* dir_name,
|
| // the actual entry type. Notice that stat returns the type of
|
| // the file pointed to.
|
| 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)) {
|
| + if (!path->Add(entry.d_name)) {
|
| success = false;
|
| break;
|
| }
|
| - int stat_success = TEMP_FAILURE_RETRY(stat(path, &entry_info));
|
| + int stat_success = TEMP_FAILURE_RETRY(stat(path->data, &entry_info));
|
| if (stat_success == -1) {
|
| success = false;
|
| - PostError(listing, path);
|
| + PostError(listing, path->data);
|
| break;
|
| }
|
| + path->Reset(path_length);
|
| if (S_ISDIR(entry_info.st_mode)) {
|
| success = HandleDir(entry.d_name,
|
| path,
|
| - path_length,
|
| recursive,
|
| listing) && success;
|
| } else if (S_ISREG(entry_info.st_mode)) {
|
| success = HandleFile(entry.d_name,
|
| path,
|
| - path_length,
|
| listing) && success;
|
| }
|
| ASSERT(!S_ISLNK(entry_info.st_mode));
|
| @@ -188,10 +181,11 @@ static bool ListRecursively(const char* dir_name,
|
| default:
|
| break;
|
| }
|
| + path->Reset(path_length);
|
| }
|
|
|
| - if (read != 0) {
|
| - errno = read;
|
| + if (status != 0) {
|
| + errno = status;
|
| success = false;
|
| PostError(listing, dir_name);
|
| }
|
| @@ -200,41 +194,23 @@ static bool ListRecursively(const char* dir_name,
|
| success = false;
|
| PostError(listing, dir_name);
|
| }
|
| - free(path);
|
| + delete path;
|
|
|
| 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);
|
| + PathBuffer* path) {
|
| + return path->Add(file_name) && remove(path->data) == 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;
|
| + PathBuffer* path) {
|
| + if (strcmp(dir_name, ".") == 0) return true;
|
| + if (strcmp(dir_name, "..") == 0) return true;
|
| + return path->Add(dir_name) && DeleteRecursively(path->data);
|
| }
|
|
|
|
|
| @@ -260,19 +236,12 @@ 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(PATH_MAX));
|
| - ASSERT(path != NULL);
|
| - int path_length = 0;
|
| - bool valid = ComputeFullPath(dir_name, path, &path_length);
|
| - if (!valid) {
|
| - free(path);
|
| - return false;
|
| - }
|
| + // recursive traversal.
|
| + PathBuffer* path = ComputeFullPath(dir_name);
|
| + if (path == NULL) return false;
|
|
|
| // Iterate the directory and delete all files and directories.
|
| + int path_length = path->length;
|
| int read = 0;
|
| bool success = true;
|
| dirent entry;
|
| @@ -284,49 +253,46 @@ static bool DeleteRecursively(const char* dir_name) {
|
| success) {
|
| switch (entry.d_type) {
|
| case DT_DIR:
|
| - success = success && DeleteDir(entry.d_name, path, path_length);
|
| + success = success && DeleteDir(entry.d_name, path);
|
| break;
|
| case DT_REG:
|
| case DT_LNK:
|
| // Treat all links as files. This will delete the link which
|
| // is what we want no matter if the link target is a file or a
|
| // directory.
|
| - success = success && DeleteFile(entry.d_name, path, path_length);
|
| + success = success && DeleteFile(entry.d_name, path);
|
| 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)) {
|
| + if (!path->Add(entry.d_name)) {
|
| success = false;
|
| break;
|
| }
|
| - int lstat_success = TEMP_FAILURE_RETRY(lstat(path, &entry_info));
|
| + int lstat_success = TEMP_FAILURE_RETRY(lstat(path->data, &entry_info));
|
| if (lstat_success == -1) {
|
| success = false;
|
| break;
|
| }
|
| + path->Reset(path_length);
|
| if (S_ISDIR(entry_info.st_mode)) {
|
| - success = success && DeleteDir(entry.d_name, path, path_length);
|
| + success = success && DeleteDir(entry.d_name, path);
|
| } else if (S_ISREG(entry_info.st_mode) || S_ISLNK(entry_info.st_mode)) {
|
| // Treat links as files. This will delete the link which is
|
| // what we want no matter if the link target is a file or a
|
| // directory.
|
| - success = success && DeleteFile(entry.d_name, path, path_length);
|
| + success = success && DeleteFile(entry.d_name, path);
|
| }
|
| break;
|
| }
|
| default:
|
| break;
|
| }
|
| + path->Reset(path_length);
|
| }
|
| -
|
| - free(path);
|
| + delete path;
|
|
|
| if ((read != 0) ||
|
| (closedir(dir_pointer) == -1) ||
|
| @@ -397,27 +363,32 @@ char* Directory::CreateTemp(const char* const_template) {
|
| // dir_template. Creates the directory with the permissions specified
|
| // by the process umask.
|
| // The return value must be freed by the caller.
|
| - char* path = static_cast<char*>(malloc(PATH_MAX + 1));
|
| - SafeStrNCpy(path, const_template, PATH_MAX + 1);
|
| - int path_length = strlen(path);
|
| - if (path_length > 0) {
|
| - if ((path)[path_length - 1] == '/') {
|
| - snprintf(path + path_length, PATH_MAX - path_length, "temp_dir_XXXXXX");
|
| - } else {
|
| - snprintf(path + path_length, PATH_MAX - path_length, "XXXXXX");
|
| - }
|
| - } else {
|
| - snprintf(path, PATH_MAX, "/tmp/temp_dir1_XXXXXX");
|
| + PathBuffer* path = new PathBuffer();
|
| + path->Add(const_template);
|
| + if (path->length == 0) {
|
| + path->Add("/tmp/temp_dir1_");
|
| + } else if ((path->data)[path->length - 1] == '/') {
|
| + path->Add("temp_dir_");
|
| + }
|
| + if (!path->Add("XXXXXX")) {
|
| + // Pattern has overflowed.
|
| + delete path;
|
| + return NULL;
|
| }
|
| char* result;
|
| do {
|
| - result = mkdtemp(path);
|
| + result = mkdtemp(path->data);
|
| } while (result == NULL && errno == EINTR);
|
| if (result == NULL) {
|
| - free(path);
|
| + delete path;
|
| return NULL;
|
| }
|
| - return path;
|
| + int length = strnlen(path->data, PATH_MAX);
|
| + result = static_cast<char*>(malloc(length + 1));
|
| + strncpy(result, path->data, length);
|
| + result[length] = '\0';
|
| + delete path;
|
| + return result;
|
| }
|
|
|
|
|
|
|