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

Unified Diff: runtime/bin/directory_android.cc

Issue 12220034: Use a PathBuffer class in dart:io directory lister. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Add Windows platform Created 7 years, 10 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
« no previous file with comments | « no previous file | runtime/bin/directory_linux.cc » ('j') | runtime/bin/directory_win.cc » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/bin/directory_android.cc
diff --git a/runtime/bin/directory_android.cc b/runtime/bin/directory_android.cc
index f3f471fd0e21594fddde6158711f2a0c8013f06f..90d95f9d19a64c402c9ef16853db671748997425 100644
--- a/runtime/bin/directory_android.cc
+++ b/runtime/bin/directory_android.cc
@@ -13,12 +13,35 @@
#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 {
+ return false;
Søren Gjesse 2013/02/08 08:49:29 I think we should try to set errno to something he
Bill Hesse 2013/02/08 12:11:37 Done. Also, call PostError in places where this r
+ }
+ }
+
+ 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,67 +51,42 @@ 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 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);
- }
- }
- return true;
+ if (strcmp(dir_name, ".") == 0) return true;
+ if (strcmp(dir_name, "..") == 0) return true;
+ return path->Add(dir_name) &&
+ 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)) {
- return false;
- }
- return listing->HandleFile(path);
+ return path->Add(file_name) && listing->HandleFile(path->data);
}
@@ -115,38 +113,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 +148,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 +175,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 +188,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 +230,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 +247,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) ||
@@ -393,7 +353,7 @@ bool Directory::Create(const char* dir_name) {
// process umask.
int result = TEMP_FAILURE_RETRY(mkdir(dir_name, 0777));
// If the directory already exists, treat it as a success.
- if (result == -1 && errno == EEXISTS) {
+ if (result == -1 && errno == EEXIST) {
return (Exists(dir_name) == EXISTS);
}
return (result == 0);
@@ -418,16 +378,9 @@ 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 {
+ PathBuffer* path = new PathBuffer();
+ path->Add(const_template);
+ if (path->length == 0) {
// Android does not have a /tmp directory. A partial substitute,
// suitable for bring-up work and tests, is to create a tmp
// directory in /data/local/tmp.
@@ -439,17 +392,29 @@ char* Directory::CreateTemp(const char* const_template) {
if (stat(ANDROID_TEMP_DIR, &st) != 0) {
mkdir(ANDROID_TEMP_DIR, 0777);
}
- snprintf(path, PATH_MAX, ANDROID_TEMP_DIR "/temp_dir1_XXXXXX");
+ path->Add(ANDROID_TEMP_DIR "/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 = MakeTempDirectory(path);
+ result = MakeTempDirectory(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;
}
« no previous file with comments | « no previous file | runtime/bin/directory_linux.cc » ('j') | runtime/bin/directory_win.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698