| OLD | NEW |
| 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_LINUX) | 6 #if defined(TARGET_OS_LINUX) |
| 7 | 7 |
| 8 #include "bin/directory.h" | 8 #include "bin/directory.h" |
| 9 | 9 |
| 10 #include <dirent.h> // NOLINT | 10 #include <dirent.h> // NOLINT |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 127 } | 127 } |
| 128 // Else fall through to next case. | 128 // Else fall through to next case. |
| 129 // Fall through. | 129 // Fall through. |
| 130 case DT_UNKNOWN: { | 130 case DT_UNKNOWN: { |
| 131 // On some file systems the entry type is not determined by | 131 // On some file systems the entry type is not determined by |
| 132 // 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 |
| 133 // the actual entry type. Notice that stat returns the type of | 133 // the actual entry type. Notice that stat returns the type of |
| 134 // the file pointed to. | 134 // the file pointed to. |
| 135 struct stat64 entry_info; | 135 struct stat64 entry_info; |
| 136 int stat_success; | 136 int stat_success; |
| 137 stat_success = NO_RETRY_EXPECTED( | 137 stat_success = TEMP_FAILURE_RETRY( |
| 138 lstat64(listing->path_buffer().AsString(), &entry_info)); | 138 lstat64(listing->path_buffer().AsString(), &entry_info)); |
| 139 if (stat_success == -1) { | 139 if (stat_success == -1) { |
| 140 return kListError; | 140 return kListError; |
| 141 } | 141 } |
| 142 if (listing->follow_links() && S_ISLNK(entry_info.st_mode)) { | 142 if (listing->follow_links() && S_ISLNK(entry_info.st_mode)) { |
| 143 // 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. |
| 144 LinkList current_link = { entry_info.st_dev, | 144 LinkList current_link = { entry_info.st_dev, |
| 145 entry_info.st_ino, | 145 entry_info.st_ino, |
| 146 link_ }; | 146 link_ }; |
| 147 LinkList* previous = link_; | 147 LinkList* previous = link_; |
| 148 while (previous != NULL) { | 148 while (previous != NULL) { |
| 149 if (previous->dev == current_link.dev && | 149 if (previous->dev == current_link.dev && |
| 150 previous->ino == current_link.ino) { | 150 previous->ino == current_link.ino) { |
| 151 // Report the looping link as a link, rather than following it. | 151 // Report the looping link as a link, rather than following it. |
| 152 return kListLink; | 152 return kListLink; |
| 153 } | 153 } |
| 154 previous = previous->next; | 154 previous = previous->next; |
| 155 } | 155 } |
| 156 stat_success = NO_RETRY_EXPECTED( | 156 stat_success = TEMP_FAILURE_RETRY( |
| 157 stat64(listing->path_buffer().AsString(), &entry_info)); | 157 stat64(listing->path_buffer().AsString(), &entry_info)); |
| 158 if (stat_success == -1) { | 158 if (stat_success == -1) { |
| 159 // 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. |
| 160 return kListLink; | 160 return kListLink; |
| 161 } | 161 } |
| 162 if (S_ISDIR(entry_info.st_mode)) { | 162 if (S_ISDIR(entry_info.st_mode)) { |
| 163 // Recurse into the subdirectory with current_link added to the | 163 // Recurse into the subdirectory with current_link added to the |
| 164 // linked list of seen file system links. | 164 // linked list of seen file system links. |
| 165 link_ = new LinkList(current_link); | 165 link_ = new LinkList(current_link); |
| 166 if (strcmp(entry.d_name, ".") == 0) return Next(listing); | 166 if (strcmp(entry.d_name, ".") == 0) return Next(listing); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 228 if (strcmp(dir_name, ".") == 0) return true; | 228 if (strcmp(dir_name, ".") == 0) return true; |
| 229 if (strcmp(dir_name, "..") == 0) return true; | 229 if (strcmp(dir_name, "..") == 0) return true; |
| 230 return path->Add(dir_name) && DeleteRecursively(path); | 230 return path->Add(dir_name) && DeleteRecursively(path); |
| 231 } | 231 } |
| 232 | 232 |
| 233 | 233 |
| 234 static bool DeleteRecursively(PathBuffer* path) { | 234 static bool DeleteRecursively(PathBuffer* path) { |
| 235 // Do not recurse into links for deletion. Instead delete the link. | 235 // Do not recurse into links for deletion. Instead delete the link. |
| 236 // If it's a file, delete it. | 236 // If it's a file, delete it. |
| 237 struct stat64 st; | 237 struct stat64 st; |
| 238 if (NO_RETRY_EXPECTED(lstat64(path->AsString(), &st)) == -1) { | 238 if (TEMP_FAILURE_RETRY(lstat64(path->AsString(), &st)) == -1) { |
| 239 return false; | 239 return false; |
| 240 } else if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) { | 240 } else if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) { |
| 241 return (NO_RETRY_EXPECTED(unlink(path->AsString())) == 0); | 241 return (NO_RETRY_EXPECTED(unlink(path->AsString())) == 0); |
| 242 } | 242 } |
| 243 | 243 |
| 244 if (!path->Add(File::PathSeparator())) return false; | 244 if (!path->Add(File::PathSeparator())) return false; |
| 245 | 245 |
| 246 // Not a link. Attempt to open as a directory and recurse into the | 246 // Not a link. Attempt to open as a directory and recurse into the |
| 247 // directory. | 247 // directory. |
| 248 DIR* dir_pointer; | 248 DIR* dir_pointer; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 276 ok = DeleteFile(entry.d_name, path); | 276 ok = DeleteFile(entry.d_name, path); |
| 277 break; | 277 break; |
| 278 case DT_UNKNOWN: { | 278 case DT_UNKNOWN: { |
| 279 if (!path->Add(entry.d_name)) { | 279 if (!path->Add(entry.d_name)) { |
| 280 break; | 280 break; |
| 281 } | 281 } |
| 282 // On some file systems the entry type is not determined by | 282 // On some file systems the entry type is not determined by |
| 283 // readdir_r. For those we use lstat to determine the entry | 283 // readdir_r. For those we use lstat to determine the entry |
| 284 // type. | 284 // type. |
| 285 struct stat64 entry_info; | 285 struct stat64 entry_info; |
| 286 if (NO_RETRY_EXPECTED(lstat64(path->AsString(), &entry_info)) == -1) { | 286 if (TEMP_FAILURE_RETRY(lstat64(path->AsString(), &entry_info)) == -1) { |
| 287 break; | 287 break; |
| 288 } | 288 } |
| 289 path->Reset(path_length); | 289 path->Reset(path_length); |
| 290 if (S_ISDIR(entry_info.st_mode)) { | 290 if (S_ISDIR(entry_info.st_mode)) { |
| 291 ok = DeleteDir(entry.d_name, path); | 291 ok = DeleteDir(entry.d_name, path); |
| 292 } else if (S_ISREG(entry_info.st_mode) || S_ISLNK(entry_info.st_mode)) { | 292 } else if (S_ISREG(entry_info.st_mode) || S_ISLNK(entry_info.st_mode)) { |
| 293 // Treat links as files. This will delete the link which is | 293 // Treat links as files. This will delete the link which is |
| 294 // what we want no matter if the link target is a file or a | 294 // what we want no matter if the link target is a file or a |
| 295 // directory. | 295 // directory. |
| 296 ok = DeleteFile(entry.d_name, path); | 296 ok = DeleteFile(entry.d_name, path); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 309 ASSERT(errno != 0); | 309 ASSERT(errno != 0); |
| 310 int err = errno; | 310 int err = errno; |
| 311 VOID_NO_RETRY_EXPECTED(closedir(dir_pointer)); | 311 VOID_NO_RETRY_EXPECTED(closedir(dir_pointer)); |
| 312 errno = err; | 312 errno = err; |
| 313 return false; | 313 return false; |
| 314 } | 314 } |
| 315 | 315 |
| 316 | 316 |
| 317 Directory::ExistsResult Directory::Exists(const char* dir_name) { | 317 Directory::ExistsResult Directory::Exists(const char* dir_name) { |
| 318 struct stat64 entry_info; | 318 struct stat64 entry_info; |
| 319 int success = NO_RETRY_EXPECTED(stat64(dir_name, &entry_info)); | 319 int success = TEMP_FAILURE_RETRY(stat64(dir_name, &entry_info)); |
| 320 if (success == 0) { | 320 if (success == 0) { |
| 321 if (S_ISDIR(entry_info.st_mode)) { | 321 if (S_ISDIR(entry_info.st_mode)) { |
| 322 return EXISTS; | 322 return EXISTS; |
| 323 } else { | 323 } else { |
| 324 return DOES_NOT_EXIST; | 324 return DOES_NOT_EXIST; |
| 325 } | 325 } |
| 326 } else { | 326 } else { |
| 327 if (errno == EACCES || | 327 if (errno == EACCES || |
| 328 errno == EBADF || | 328 errno == EBADF || |
| 329 errno == EFAULT || | 329 errno == EFAULT || |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 436 bool Directory::Rename(const char* path, const char* new_path) { | 436 bool Directory::Rename(const char* path, const char* new_path) { |
| 437 ExistsResult exists = Exists(path); | 437 ExistsResult exists = Exists(path); |
| 438 if (exists != EXISTS) return false; | 438 if (exists != EXISTS) return false; |
| 439 return NO_RETRY_EXPECTED(rename(path, new_path)) == 0; | 439 return NO_RETRY_EXPECTED(rename(path, new_path)) == 0; |
| 440 } | 440 } |
| 441 | 441 |
| 442 } // namespace bin | 442 } // namespace bin |
| 443 } // namespace dart | 443 } // namespace dart |
| 444 | 444 |
| 445 #endif // defined(TARGET_OS_LINUX) | 445 #endif // defined(TARGET_OS_LINUX) |
| OLD | NEW |