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

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

Issue 165723007: Move signal_blocker to platform and use it by default in TEMP_FAILURE_RETRY. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Tiny fix. Created 6 years, 9 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/bin/dbg_connection_macos.cc ('k') | runtime/bin/directory_linux.cc » ('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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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_ANDROID) 6 #if defined(TARGET_OS_ANDROID)
7 7
8 #include "bin/directory.h" 8 #include "bin/directory.h"
9 9
10 #include <dirent.h> // NOLINT 10 #include <dirent.h> // NOLINT
11 #include <errno.h> // NOLINT 11 #include <errno.h> // NOLINT
12 #include <string.h> // NOLINT 12 #include <string.h> // NOLINT
13 #include <sys/param.h> // NOLINT 13 #include <sys/param.h> // NOLINT
14 #include <sys/stat.h> // NOLINT 14 #include <sys/stat.h> // NOLINT
15 #include <unistd.h> // NOLINT 15 #include <unistd.h> // NOLINT
16 16
17 #include "bin/file.h" 17 #include "bin/file.h"
18 #include "bin/platform.h" 18 #include "bin/platform.h"
19 19
20 #include "platform/signal_blocker.h"
21
20 22
21 namespace dart { 23 namespace dart {
22 namespace bin { 24 namespace bin {
23 25
24 26
25 PathBuffer::PathBuffer() : length_(0) { 27 PathBuffer::PathBuffer() : length_(0) {
26 data_ = calloc(PATH_MAX + 1, sizeof(char)); // NOLINT 28 data_ = calloc(PATH_MAX + 1, sizeof(char)); // NOLINT
27 } 29 }
28 30
29 bool PathBuffer::AddW(const wchar_t* name) { 31 bool PathBuffer::AddW(const wchar_t* name) {
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 } 99 }
98 // Reset. 100 // Reset.
99 listing->path_buffer().Reset(path_length_); 101 listing->path_buffer().Reset(path_length_);
100 ResetLink(); 102 ResetLink();
101 103
102 // Iterate the directory and post the directories and files to the 104 // Iterate the directory and post the directories and files to the
103 // ports. 105 // ports.
104 int status = 0; 106 int status = 0;
105 dirent entry; 107 dirent entry;
106 dirent* result; 108 dirent* result;
107 if ((status = TEMP_FAILURE_RETRY(readdir_r(reinterpret_cast<DIR*>(lister_), 109 if ((status = NO_RETRY_EXPECTED(readdir_r(reinterpret_cast<DIR*>(lister_),
108 &entry, 110 &entry,
109 &result))) == 0 && 111 &result))) == 0 &&
110 result != NULL) { 112 result != NULL) {
111 if (!listing->path_buffer().Add(entry.d_name)) { 113 if (!listing->path_buffer().Add(entry.d_name)) {
112 done_ = true; 114 done_ = true;
113 return kListError; 115 return kListError;
114 } 116 }
115 switch (entry.d_type) { 117 switch (entry.d_type) {
116 case DT_DIR: 118 case DT_DIR:
117 if (strcmp(entry.d_name, ".") == 0) return Next(listing); 119 if (strcmp(entry.d_name, ".") == 0) return Next(listing);
118 if (strcmp(entry.d_name, "..") == 0) return Next(listing); 120 if (strcmp(entry.d_name, "..") == 0) return Next(listing);
119 return kListDirectory; 121 return kListDirectory;
120 case DT_REG: 122 case DT_REG:
121 return kListFile; 123 return kListFile;
122 case DT_LNK: 124 case DT_LNK:
123 if (!listing->follow_links()) { 125 if (!listing->follow_links()) {
124 return kListLink; 126 return kListLink;
125 } 127 }
126 // Else fall through to next case. 128 // Else fall through to next case.
127 // Fall through. 129 // Fall through.
128 case DT_UNKNOWN: { 130 case DT_UNKNOWN: {
129 // On some file systems the entry type is not determined by 131 // On some file systems the entry type is not determined by
130 // readdir_r. For those and for links we use stat to determine 132 // readdir_r. For those and for links we use stat to determine
131 // the actual entry type. Notice that stat returns the type of 133 // the actual entry type. Notice that stat returns the type of
132 // the file pointed to. 134 // the file pointed to.
133 struct stat entry_info; 135 struct stat entry_info;
134 int stat_success; 136 int stat_success;
135 stat_success = TEMP_FAILURE_RETRY( 137 stat_success = NO_RETRY_EXPECTED(
136 lstat(listing->path_buffer().AsString(), &entry_info)); 138 lstat(listing->path_buffer().AsString(), &entry_info));
137 if (stat_success == -1) { 139 if (stat_success == -1) {
138 return kListError; 140 return kListError;
139 } 141 }
140 if (listing->follow_links() && S_ISLNK(entry_info.st_mode)) { 142 if (listing->follow_links() && S_ISLNK(entry_info.st_mode)) {
141 // Check to see if we are in a loop created by a symbolic link. 143 // Check to see if we are in a loop created by a symbolic link.
142 LinkList current_link = { entry_info.st_dev, 144 LinkList current_link = { entry_info.st_dev,
143 entry_info.st_ino, 145 entry_info.st_ino,
144 link_ }; 146 link_ };
145 LinkList* previous = link_; 147 LinkList* previous = link_;
146 while (previous != NULL) { 148 while (previous != NULL) {
147 if (previous->dev == current_link.dev && 149 if (previous->dev == current_link.dev &&
148 previous->ino == current_link.ino) { 150 previous->ino == current_link.ino) {
149 // Report the looping link as a link, rather than following it. 151 // Report the looping link as a link, rather than following it.
150 return kListLink; 152 return kListLink;
151 } 153 }
152 previous = previous->next; 154 previous = previous->next;
153 } 155 }
154 stat_success = TEMP_FAILURE_RETRY( 156 stat_success = NO_RETRY_EXPECTED(
155 stat(listing->path_buffer().AsString(), &entry_info)); 157 stat(listing->path_buffer().AsString(), &entry_info));
156 if (stat_success == -1) { 158 if (stat_success == -1) {
157 // Report a broken link as a link, even if follow_links is true. 159 // Report a broken link as a link, even if follow_links is true.
158 return kListLink; 160 return kListLink;
159 } 161 }
160 if (S_ISDIR(entry_info.st_mode)) { 162 if (S_ISDIR(entry_info.st_mode)) {
161 // Recurse into the subdirectory with current_link added to the 163 // Recurse into the subdirectory with current_link added to the
162 // linked list of seen file system links. 164 // linked list of seen file system links.
163 link_ = new LinkList(current_link); 165 link_ = new LinkList(current_link);
164 if (strcmp(entry.d_name, ".") == 0) return Next(listing); 166 if (strcmp(entry.d_name, ".") == 0) return Next(listing);
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
225 if (strcmp(dir_name, ".") == 0) return true; 227 if (strcmp(dir_name, ".") == 0) return true;
226 if (strcmp(dir_name, "..") == 0) return true; 228 if (strcmp(dir_name, "..") == 0) return true;
227 return path->Add(dir_name) && DeleteRecursively(path); 229 return path->Add(dir_name) && DeleteRecursively(path);
228 } 230 }
229 231
230 232
231 static bool DeleteRecursively(PathBuffer* path) { 233 static bool DeleteRecursively(PathBuffer* path) {
232 // Do not recurse into links for deletion. Instead delete the link. 234 // Do not recurse into links for deletion. Instead delete the link.
233 // If it's a file, delete it. 235 // If it's a file, delete it.
234 struct stat st; 236 struct stat st;
235 if (TEMP_FAILURE_RETRY(lstat(path->AsString(), &st)) == -1) { 237 if (NO_RETRY_EXPECTED(lstat(path->AsString(), &st)) == -1) {
236 return false; 238 return false;
237 } else if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) { 239 } else if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
238 return (unlink(path->AsString()) == 0); 240 return (unlink(path->AsString()) == 0);
239 } 241 }
240 242
241 if (!path->Add(File::PathSeparator())) return false; 243 if (!path->Add(File::PathSeparator())) return false;
242 244
243 // Not a link. Attempt to open as a directory and recurse into the 245 // Not a link. Attempt to open as a directory and recurse into the
244 // directory. 246 // directory.
245 DIR* dir_pointer; 247 DIR* dir_pointer;
246 do { 248 do {
247 dir_pointer = opendir(path->AsString()); 249 dir_pointer = opendir(path->AsString());
248 } while (dir_pointer == NULL && errno == EINTR); 250 } while (dir_pointer == NULL && errno == EINTR);
249 251
250 if (dir_pointer == NULL) { 252 if (dir_pointer == NULL) {
251 return false; 253 return false;
252 } 254 }
253 255
254 // Iterate the directory and delete all files and directories. 256 // Iterate the directory and delete all files and directories.
255 int path_length = path->length(); 257 int path_length = path->length();
256 int read = 0; 258 int read = 0;
257 bool success = true; 259 bool success = true;
258 dirent entry; 260 dirent entry;
259 dirent* result; 261 dirent* result;
260 while ((read = TEMP_FAILURE_RETRY(readdir_r(dir_pointer, 262 while ((read = NO_RETRY_EXPECTED(readdir_r(dir_pointer,
261 &entry, 263 &entry,
262 &result))) == 0 && 264 &result))) == 0 &&
263 result != NULL && 265 result != NULL &&
264 success) { 266 success) {
265 switch (entry.d_type) { 267 switch (entry.d_type) {
266 case DT_DIR: 268 case DT_DIR:
267 success = success && DeleteDir(entry.d_name, path); 269 success = success && DeleteDir(entry.d_name, path);
268 break; 270 break;
269 case DT_REG: 271 case DT_REG:
270 case DT_LNK: 272 case DT_LNK:
271 // Treat all links as files. This will delete the link which 273 // Treat all links as files. This will delete the link which
272 // is what we want no matter if the link target is a file or a 274 // is what we want no matter if the link target is a file or a
273 // directory. 275 // directory.
274 success = success && DeleteFile(entry.d_name, path); 276 success = success && DeleteFile(entry.d_name, path);
275 break; 277 break;
276 case DT_UNKNOWN: { 278 case DT_UNKNOWN: {
277 // On some file systems the entry type is not determined by 279 // On some file systems the entry type is not determined by
278 // readdir_r. For those we use lstat to determine the entry 280 // readdir_r. For those we use lstat to determine the entry
279 // type. 281 // type.
280 struct stat entry_info; 282 struct stat entry_info;
281 if (!path->Add(entry.d_name)) { 283 if (!path->Add(entry.d_name)) {
282 success = false; 284 success = false;
283 break; 285 break;
284 } 286 }
285 int lstat_success = TEMP_FAILURE_RETRY( 287 int lstat_success = NO_RETRY_EXPECTED(
286 lstat(path->AsString(), &entry_info)); 288 lstat(path->AsString(), &entry_info));
287 if (lstat_success == -1) { 289 if (lstat_success == -1) {
288 success = false; 290 success = false;
289 break; 291 break;
290 } 292 }
291 path->Reset(path_length); 293 path->Reset(path_length);
292 if (S_ISDIR(entry_info.st_mode)) { 294 if (S_ISDIR(entry_info.st_mode)) {
293 success = success && DeleteDir(entry.d_name, path); 295 success = success && DeleteDir(entry.d_name, path);
294 } else if (S_ISREG(entry_info.st_mode) || S_ISLNK(entry_info.st_mode)) { 296 } else if (S_ISREG(entry_info.st_mode) || S_ISLNK(entry_info.st_mode)) {
295 // Treat links as files. This will delete the link which is 297 // Treat links as files. This will delete the link which is
(...skipping 13 matching lines...) Expand all
309 (closedir(dir_pointer) == -1) || 311 (closedir(dir_pointer) == -1) ||
310 (remove(path->AsString()) == -1)) { 312 (remove(path->AsString()) == -1)) {
311 return false; 313 return false;
312 } 314 }
313 return success; 315 return success;
314 } 316 }
315 317
316 318
317 Directory::ExistsResult Directory::Exists(const char* dir_name) { 319 Directory::ExistsResult Directory::Exists(const char* dir_name) {
318 struct stat entry_info; 320 struct stat entry_info;
319 int success = TEMP_FAILURE_RETRY(stat(dir_name, &entry_info)); 321 int success = NO_RETRY_EXPECTED(stat(dir_name, &entry_info));
320 if (success == 0) { 322 if (success == 0) {
321 if (S_ISDIR(entry_info.st_mode)) { 323 if (S_ISDIR(entry_info.st_mode)) {
322 return EXISTS; 324 return EXISTS;
323 } else { 325 } else {
324 return DOES_NOT_EXIST; 326 return DOES_NOT_EXIST;
325 } 327 }
326 } else { 328 } else {
327 if (errno == EACCES || 329 if (errno == EACCES ||
328 errno == EBADF || 330 errno == EBADF ||
329 errno == EFAULT || 331 errno == EFAULT ||
(...skipping 20 matching lines...) Expand all
350 char buffer[PATH_MAX]; 352 char buffer[PATH_MAX];
351 if (NULL == getcwd(buffer, PATH_MAX)) { 353 if (NULL == getcwd(buffer, PATH_MAX)) {
352 return NULL; 354 return NULL;
353 } 355 }
354 356
355 return strdup(buffer); 357 return strdup(buffer);
356 } 358 }
357 359
358 360
359 bool Directory::SetCurrent(const char* path) { 361 bool Directory::SetCurrent(const char* path) {
360 int result = TEMP_FAILURE_RETRY(chdir(path)); 362 int result = NO_RETRY_EXPECTED(chdir(path));
361 return result == 0; 363 return result == 0;
362 } 364 }
363 365
364 366
365 bool Directory::Create(const char* dir_name) { 367 bool Directory::Create(const char* dir_name) {
366 // Create the directory with the permissions specified by the 368 // Create the directory with the permissions specified by the
367 // process umask. 369 // process umask.
368 int result = TEMP_FAILURE_RETRY(mkdir(dir_name, 0777)); 370 int result = NO_RETRY_EXPECTED(mkdir(dir_name, 0777));
369 // If the directory already exists, treat it as a success. 371 // If the directory already exists, treat it as a success.
370 if (result == -1 && errno == EEXIST) { 372 if (result == -1 && errno == EEXIST) {
371 return (Exists(dir_name) == EXISTS); 373 return (Exists(dir_name) == EXISTS);
372 } 374 }
373 return (result == 0); 375 return (result == 0);
374 } 376 }
375 377
376 378
377 // Android doesn't currently provide mkdtemp. Once Android provied mkdtemp, 379 // Android doesn't currently provide mkdtemp. Once Android provied mkdtemp,
378 // remove this function in favor of calling mkdtemp directly. 380 // remove this function in favor of calling mkdtemp directly.
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
423 return NULL; 425 return NULL;
424 } 426 }
425 return strdup(result); 427 return strdup(result);
426 } 428 }
427 429
428 430
429 bool Directory::Delete(const char* dir_name, bool recursive) { 431 bool Directory::Delete(const char* dir_name, bool recursive) {
430 if (!recursive) { 432 if (!recursive) {
431 if (File::GetType(dir_name, false) == File::kIsLink && 433 if (File::GetType(dir_name, false) == File::kIsLink &&
432 File::GetType(dir_name, true) == File::kIsDirectory) { 434 File::GetType(dir_name, true) == File::kIsDirectory) {
433 return (TEMP_FAILURE_RETRY(unlink(dir_name)) == 0); 435 return (NO_RETRY_EXPECTED(unlink(dir_name)) == 0);
434 } 436 }
435 return (TEMP_FAILURE_RETRY(rmdir(dir_name)) == 0); 437 return (NO_RETRY_EXPECTED(rmdir(dir_name)) == 0);
436 } else { 438 } else {
437 PathBuffer path; 439 PathBuffer path;
438 if (!path.Add(dir_name)) { 440 if (!path.Add(dir_name)) {
439 return false; 441 return false;
440 } 442 }
441 return DeleteRecursively(&path); 443 return DeleteRecursively(&path);
442 } 444 }
443 } 445 }
444 446
445 447
446 bool Directory::Rename(const char* path, const char* new_path) { 448 bool Directory::Rename(const char* path, const char* new_path) {
447 ExistsResult exists = Exists(path); 449 ExistsResult exists = Exists(path);
448 if (exists != EXISTS) return false; 450 if (exists != EXISTS) return false;
449 return (TEMP_FAILURE_RETRY(rename(path, new_path)) == 0); 451 return (NO_RETRY_EXPECTED(rename(path, new_path)) == 0);
450 } 452 }
451 453
452 } // namespace bin 454 } // namespace bin
453 } // namespace dart 455 } // namespace dart
454 456
455 #endif // defined(TARGET_OS_ANDROID) 457 #endif // defined(TARGET_OS_ANDROID)
OLDNEW
« no previous file with comments | « runtime/bin/dbg_connection_macos.cc ('k') | runtime/bin/directory_linux.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698