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

Side by Side Diff: runtime/bin/directory_fuchsia.cc

Issue 2579483002: Fuchsia: Directory listing (Closed)
Patch Set: Format Created 4 years 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 unified diff | Download patch
« no previous file with comments | « no previous file | runtime/tests/vm/dart/hello_fuchsia_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "platform/globals.h" 5 #include "platform/globals.h"
6 #if defined(TARGET_OS_FUCHSIA) 6 #if defined(TARGET_OS_FUCHSIA)
7 7
8 #include "bin/directory.h" 8 #include "bin/directory.h"
9 9
10 #include <dirent.h> // NOLINT
10 #include <errno.h> // NOLINT 11 #include <errno.h> // NOLINT
11 #include <stdlib.h> // NOLINT 12 #include <stdlib.h> // NOLINT
12 #include <string.h> // NOLINT 13 #include <string.h> // NOLINT
14 #include <sys/param.h> // NOLINT
13 #include <sys/stat.h> // NOLINT 15 #include <sys/stat.h> // NOLINT
14 #include <unistd.h> // NOLINT 16 #include <unistd.h> // NOLINT
15 17
16 #include "bin/dartutils.h" 18 #include "bin/dartutils.h"
17 #include "bin/file.h" 19 #include "bin/file.h"
18 #include "bin/platform.h" 20 #include "bin/platform.h"
19 #include "platform/signal_blocker.h" 21 #include "platform/signal_blocker.h"
20 22
21 namespace dart { 23 namespace dart {
22 namespace bin { 24 namespace bin {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
72 } 74 }
73 } 75 }
74 76
75 77
76 void PathBuffer::Reset(intptr_t new_length) { 78 void PathBuffer::Reset(intptr_t new_length) {
77 length_ = new_length; 79 length_ = new_length;
78 AsString()[length_] = '\0'; 80 AsString()[length_] = '\0';
79 } 81 }
80 82
81 83
84 // A linked list of symbolic links, with their unique file system identifiers.
85 // These are scanned to detect loops while doing a recursive directory listing.
86 struct LinkList {
87 dev_t dev;
88 ino64_t ino;
89 LinkList* next;
90 };
91
92
82 ListType DirectoryListingEntry::Next(DirectoryListing* listing) { 93 ListType DirectoryListingEntry::Next(DirectoryListing* listing) {
83 UNIMPLEMENTED(); 94 if (done_) {
84 return kListError; 95 return kListDone;
96 }
97
98 if (lister_ == 0) {
99 lister_ =
100 reinterpret_cast<intptr_t>(opendir(listing->path_buffer().AsString()));
101 if (lister_ == 0) {
102 perror("opendir failed: ");
103 done_ = true;
104 return kListError;
105 }
106 if (parent_ != NULL) {
107 if (!listing->path_buffer().Add(File::PathSeparator())) {
108 return kListError;
109 }
110 }
111 path_length_ = listing->path_buffer().length();
112 }
113 // Reset.
114 listing->path_buffer().Reset(path_length_);
115 ResetLink();
116
117 // Iterate the directory and post the directories and files to the
118 // ports.
119 errno = 0;
120 dirent* entry = readdir(reinterpret_cast<DIR*>(lister_));
121 if (entry == NULL) {
122 perror("readdir failed: ");
123 }
124 if (entry != NULL) {
125 if (!listing->path_buffer().Add(entry->d_name)) {
126 done_ = true;
127 return kListError;
128 }
129 switch (entry->d_type) {
130 case DT_DIR:
131 if ((strcmp(entry->d_name, ".") == 0) ||
132 (strcmp(entry->d_name, "..") == 0)) {
133 return Next(listing);
134 }
135 return kListDirectory;
136 case DT_BLK:
137 case DT_CHR:
138 case DT_FIFO:
139 case DT_SOCK:
140 case DT_REG:
141 return kListFile;
142 case DT_LNK:
143 if (!listing->follow_links()) {
144 return kListLink;
145 }
146 // Else fall through to next case.
147 // Fall through.
148 case DT_UNKNOWN: {
149 // On some file systems the entry type is not determined by
150 // readdir. For those and for links we use stat to determine
151 // the actual entry type. Notice that stat returns the type of
152 // the file pointed to.
153 struct stat64 entry_info;
154 int stat_success;
155 stat_success = NO_RETRY_EXPECTED(
156 lstat64(listing->path_buffer().AsString(), &entry_info));
157 if (stat_success == -1) {
158 perror("lstat64 failed: ");
159 return kListError;
160 }
161 if (listing->follow_links() && S_ISLNK(entry_info.st_mode)) {
162 // Check to see if we are in a loop created by a symbolic link.
163 LinkList current_link = {entry_info.st_dev, entry_info.st_ino, link_};
164 LinkList* previous = link_;
165 while (previous != NULL) {
166 if ((previous->dev == current_link.dev) &&
167 (previous->ino == current_link.ino)) {
168 // Report the looping link as a link, rather than following it.
169 return kListLink;
170 }
171 previous = previous->next;
172 }
173 stat_success = NO_RETRY_EXPECTED(
174 stat64(listing->path_buffer().AsString(), &entry_info));
175 if (stat_success == -1) {
176 perror("lstat64 failed");
177 // Report a broken link as a link, even if follow_links is true.
178 return kListLink;
179 }
180 if (S_ISDIR(entry_info.st_mode)) {
181 // Recurse into the subdirectory with current_link added to the
182 // linked list of seen file system links.
183 link_ = new LinkList(current_link);
184 if ((strcmp(entry->d_name, ".") == 0) ||
185 (strcmp(entry->d_name, "..") == 0)) {
186 return Next(listing);
187 }
188 return kListDirectory;
189 }
190 }
191 if (S_ISDIR(entry_info.st_mode)) {
192 if ((strcmp(entry->d_name, ".") == 0) ||
193 (strcmp(entry->d_name, "..") == 0)) {
194 return Next(listing);
195 }
196 return kListDirectory;
197 } else if (S_ISREG(entry_info.st_mode) || S_ISCHR(entry_info.st_mode) ||
198 S_ISBLK(entry_info.st_mode) ||
199 S_ISFIFO(entry_info.st_mode) ||
200 S_ISSOCK(entry_info.st_mode)) {
201 return kListFile;
202 } else if (S_ISLNK(entry_info.st_mode)) {
203 return kListLink;
204 } else {
205 FATAL1("Unexpected st_mode: %d\n", entry_info.st_mode);
206 return kListError;
207 }
208 }
209
210 default:
211 // We should have covered all the bases. If not, let's get an error.
212 FATAL1("Unexpected d_type: %d\n", entry->d_type);
213 return kListError;
214 }
215 }
216 done_ = true;
217
218 if (errno != 0) {
219 return kListError;
220 }
221
222 return kListDone;
85 } 223 }
86 224
87 225
88 DirectoryListingEntry::~DirectoryListingEntry() { 226 DirectoryListingEntry::~DirectoryListingEntry() {
89 UNIMPLEMENTED(); 227 ResetLink();
228 if (lister_ != 0) {
229 VOID_NO_RETRY_EXPECTED(closedir(reinterpret_cast<DIR*>(lister_)));
230 }
90 } 231 }
91 232
92 233
93 void DirectoryListingEntry::ResetLink() { 234 void DirectoryListingEntry::ResetLink() {
94 UNIMPLEMENTED(); 235 if ((link_ != NULL) && ((parent_ == NULL) || (parent_->link_ != link_))) {
236 delete link_;
237 link_ = NULL;
238 }
239 if (parent_ != NULL) {
240 link_ = parent_->link_;
241 }
95 } 242 }
96 243
97 244
98 Directory::ExistsResult Directory::Exists(const char* dir_name) { 245 Directory::ExistsResult Directory::Exists(const char* dir_name) {
99 struct stat entry_info; 246 struct stat entry_info;
100 int success = NO_RETRY_EXPECTED(stat(dir_name, &entry_info)); 247 int success = NO_RETRY_EXPECTED(stat(dir_name, &entry_info));
101 if (success == 0) { 248 if (success == 0) {
102 if (S_ISDIR(entry_info.st_mode)) { 249 if (S_ISDIR(entry_info.st_mode)) {
103 return EXISTS; 250 return EXISTS;
104 } else { 251 } else {
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
216 if (exists != EXISTS) { 363 if (exists != EXISTS) {
217 return false; 364 return false;
218 } 365 }
219 return (NO_RETRY_EXPECTED(rename(path, new_path)) == 0); 366 return (NO_RETRY_EXPECTED(rename(path, new_path)) == 0);
220 } 367 }
221 368
222 } // namespace bin 369 } // namespace bin
223 } // namespace dart 370 } // namespace dart
224 371
225 #endif // defined(TARGET_OS_FUCHSIA) 372 #endif // defined(TARGET_OS_FUCHSIA)
OLDNEW
« no previous file with comments | « no previous file | runtime/tests/vm/dart/hello_fuchsia_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698