| Index: runtime/bin/directory_linux.cc
|
| diff --git a/runtime/bin/directory_linux.cc b/runtime/bin/directory_linux.cc
|
| index 30cc860444850163fc2387110f01b003927637a8..f6ad163905b8daae5fcdce5dcae26e2c7c907cfb 100644
|
| --- a/runtime/bin/directory_linux.cc
|
| +++ b/runtime/bin/directory_linux.cc
|
| @@ -57,6 +57,7 @@ class PathBuffer {
|
| // Forward declarations.
|
| static bool ListRecursively(PathBuffer* path,
|
| bool recursive,
|
| + bool follow_links,
|
| DirectoryListing* listing);
|
| static bool DeleteRecursively(PathBuffer* path);
|
|
|
| @@ -70,6 +71,7 @@ static void PostError(DirectoryListing *listing,
|
| static bool HandleDir(char* dir_name,
|
| PathBuffer* path,
|
| bool recursive,
|
| + bool follow_links,
|
| DirectoryListing *listing) {
|
| if (strcmp(dir_name, ".") == 0) return true;
|
| if (strcmp(dir_name, "..") == 0) return true;
|
| @@ -78,7 +80,7 @@ static bool HandleDir(char* dir_name,
|
| return false;
|
| }
|
| return listing->HandleDirectory(path->data) &&
|
| - (!recursive || ListRecursively(path, recursive, listing));
|
| + (!recursive || ListRecursively(path, recursive, follow_links, listing));
|
| }
|
|
|
|
|
| @@ -93,8 +95,20 @@ static bool HandleFile(char* file_name,
|
| }
|
|
|
|
|
| +static bool HandleLink(char* link_name,
|
| + PathBuffer* path,
|
| + DirectoryListing *listing) {
|
| + if (!path->Add(link_name)) {
|
| + PostError(listing, path->data);
|
| + return false;
|
| + }
|
| + return listing->HandleLink(path->data);
|
| +}
|
| +
|
| +
|
| static bool ListRecursively(PathBuffer* path,
|
| bool recursive,
|
| + bool follow_links,
|
| DirectoryListing *listing) {
|
| if (!path->Add(File::PathSeparator())) {
|
| PostError(listing, path->data);
|
| @@ -125,6 +139,7 @@ static bool ListRecursively(PathBuffer* path,
|
| success = HandleDir(entry.d_name,
|
| path,
|
| recursive,
|
| + follow_links,
|
| listing) && success;
|
| break;
|
| case DT_REG:
|
| @@ -133,6 +148,14 @@ static bool ListRecursively(PathBuffer* path,
|
| listing) && success;
|
| break;
|
| case DT_LNK:
|
| + if (!follow_links) {
|
| + success = HandleLink(entry.d_name,
|
| + path,
|
| + listing) && success;
|
| + break;
|
| + }
|
| + // Else fall through to next case.
|
| + // Fall through.
|
| case DT_UNKNOWN: {
|
| // On some file systems the entry type is not determined by
|
| // readdir_r. For those and for links we use stat to determine
|
| @@ -143,7 +166,12 @@ static bool ListRecursively(PathBuffer* path,
|
| success = false;
|
| break;
|
| }
|
| - int stat_success = TEMP_FAILURE_RETRY(stat(path->data, &entry_info));
|
| + int stat_success;
|
| + if (follow_links) {
|
| + stat_success = TEMP_FAILURE_RETRY(stat(path->data, &entry_info));
|
| + } else {
|
| + stat_success = TEMP_FAILURE_RETRY(lstat(path->data, &entry_info));
|
| + }
|
| if (stat_success == -1) {
|
| success = false;
|
| PostError(listing, path->data);
|
| @@ -154,13 +182,18 @@ static bool ListRecursively(PathBuffer* path,
|
| success = HandleDir(entry.d_name,
|
| path,
|
| recursive,
|
| + follow_links,
|
| listing) && success;
|
| } else if (S_ISREG(entry_info.st_mode)) {
|
| success = HandleFile(entry.d_name,
|
| path,
|
| listing) && success;
|
| + } else if (S_ISLNK(entry_info.st_mode)) {
|
| + ASSERT(!follow_links);
|
| + success = HandleLink(entry.d_name,
|
| + path,
|
| + listing) && success;
|
| }
|
| - ASSERT(!S_ISLNK(entry_info.st_mode));
|
| break;
|
| }
|
| default:
|
| @@ -283,13 +316,14 @@ static bool DeleteRecursively(PathBuffer* path) {
|
|
|
| bool Directory::List(const char* dir_name,
|
| bool recursive,
|
| + bool follow_links,
|
| DirectoryListing *listing) {
|
| PathBuffer path;
|
| if (!path.Add(dir_name)) {
|
| PostError(listing, dir_name);
|
| return false;
|
| }
|
| - return ListRecursively(&path, recursive, listing);
|
| + return ListRecursively(&path, recursive, follow_links, listing);
|
| }
|
|
|
|
|
|
|