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_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 |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
122 if (!listing->follow_links()) { | 122 if (!listing->follow_links()) { |
123 return kListLink; | 123 return kListLink; |
124 } | 124 } |
125 // Else fall through to next case. | 125 // Else fall through to next case. |
126 // Fall through. | 126 // Fall through. |
127 case DT_UNKNOWN: { | 127 case DT_UNKNOWN: { |
128 // On some file systems the entry type is not determined by | 128 // On some file systems the entry type is not determined by |
129 // readdir_r. For those and for links we use stat to determine | 129 // readdir_r. For those and for links we use stat to determine |
130 // the actual entry type. Notice that stat returns the type of | 130 // the actual entry type. Notice that stat returns the type of |
131 // the file pointed to. | 131 // the file pointed to. |
132 struct stat64 entry_info; | 132 struct stat entry_info; |
133 int stat_success; | 133 int stat_success; |
134 stat_success = TEMP_FAILURE_RETRY( | 134 stat_success = TEMP_FAILURE_RETRY( |
135 lstat64(listing->path_buffer().AsString(), &entry_info)); | 135 lstat(listing->path_buffer().AsString(), &entry_info)); |
136 if (stat_success == -1) { | 136 if (stat_success == -1) { |
137 return kListError; | 137 return kListError; |
138 } | 138 } |
139 if (listing->follow_links() && S_ISLNK(entry_info.st_mode)) { | 139 if (listing->follow_links() && S_ISLNK(entry_info.st_mode)) { |
140 // Check to see if we are in a loop created by a symbolic link. | 140 // Check to see if we are in a loop created by a symbolic link. |
141 LinkList current_link = { entry_info.st_dev, | 141 LinkList current_link = { entry_info.st_dev, |
142 entry_info.st_ino, | 142 entry_info.st_ino, |
143 link_ }; | 143 link_ }; |
144 LinkList* previous = link_; | 144 LinkList* previous = link_; |
145 while (previous != NULL) { | 145 while (previous != NULL) { |
146 if (previous->dev == current_link.dev && | 146 if (previous->dev == current_link.dev && |
147 previous->ino == current_link.ino) { | 147 previous->ino == current_link.ino) { |
148 // Report the looping link as a link, rather than following it. | 148 // Report the looping link as a link, rather than following it. |
149 return kListLink; | 149 return kListLink; |
150 } | 150 } |
151 previous = previous->next; | 151 previous = previous->next; |
152 } | 152 } |
153 stat_success = TEMP_FAILURE_RETRY( | 153 stat_success = TEMP_FAILURE_RETRY( |
154 stat64(listing->path_buffer().AsString(), &entry_info)); | 154 stat(listing->path_buffer().AsString(), &entry_info)); |
155 if (stat_success == -1) { | 155 if (stat_success == -1) { |
156 // Report a broken link as a link, even if follow_links is true. | 156 // Report a broken link as a link, even if follow_links is true. |
157 return kListLink; | 157 return kListLink; |
158 } | 158 } |
159 if (S_ISDIR(entry_info.st_mode)) { | 159 if (S_ISDIR(entry_info.st_mode)) { |
160 // Recurse into the subdirectory with current_link added to the | 160 // Recurse into the subdirectory with current_link added to the |
161 // linked list of seen file system links. | 161 // linked list of seen file system links. |
162 link_ = new LinkList(current_link); | 162 link_ = new LinkList(current_link); |
163 if (strcmp(entry.d_name, ".") == 0) return Next(listing); | 163 if (strcmp(entry.d_name, ".") == 0) return Next(listing); |
164 if (strcmp(entry.d_name, "..") == 0) return Next(listing); | 164 if (strcmp(entry.d_name, "..") == 0) return Next(listing); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
223 PathBuffer* path) { | 223 PathBuffer* path) { |
224 if (strcmp(dir_name, ".") == 0) return true; | 224 if (strcmp(dir_name, ".") == 0) return true; |
225 if (strcmp(dir_name, "..") == 0) return true; | 225 if (strcmp(dir_name, "..") == 0) return true; |
226 return path->Add(dir_name) && DeleteRecursively(path); | 226 return path->Add(dir_name) && DeleteRecursively(path); |
227 } | 227 } |
228 | 228 |
229 | 229 |
230 static bool DeleteRecursively(PathBuffer* path) { | 230 static bool DeleteRecursively(PathBuffer* path) { |
231 // Do not recurse into links for deletion. Instead delete the link. | 231 // Do not recurse into links for deletion. Instead delete the link. |
232 // If it's a file, delete it. | 232 // If it's a file, delete it. |
233 struct stat64 st; | 233 struct stat st; |
234 if (TEMP_FAILURE_RETRY(lstat64(path->AsString(), &st)) == -1) { | 234 if (TEMP_FAILURE_RETRY(lstat(path->AsString(), &st)) == -1) { |
235 return false; | 235 return false; |
236 } else if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) { | 236 } else if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) { |
237 return (unlink(path->AsString()) == 0); | 237 return (unlink(path->AsString()) == 0); |
238 } | 238 } |
239 | 239 |
240 if (!path->Add(File::PathSeparator())) return false; | 240 if (!path->Add(File::PathSeparator())) return false; |
241 | 241 |
242 // Not a link. Attempt to open as a directory and recurse into the | 242 // Not a link. Attempt to open as a directory and recurse into the |
243 // directory. | 243 // directory. |
244 DIR* dir_pointer; | 244 DIR* dir_pointer; |
(...skipping 24 matching lines...) Expand all Loading... |
269 case DT_LNK: | 269 case DT_LNK: |
270 // Treat all links as files. This will delete the link which | 270 // Treat all links as files. This will delete the link which |
271 // is what we want no matter if the link target is a file or a | 271 // is what we want no matter if the link target is a file or a |
272 // directory. | 272 // directory. |
273 success = success && DeleteFile(entry.d_name, path); | 273 success = success && DeleteFile(entry.d_name, path); |
274 break; | 274 break; |
275 case DT_UNKNOWN: { | 275 case DT_UNKNOWN: { |
276 // On some file systems the entry type is not determined by | 276 // On some file systems the entry type is not determined by |
277 // readdir_r. For those we use lstat to determine the entry | 277 // readdir_r. For those we use lstat to determine the entry |
278 // type. | 278 // type. |
279 struct stat64 entry_info; | 279 struct stat entry_info; |
280 if (!path->Add(entry.d_name)) { | 280 if (!path->Add(entry.d_name)) { |
281 success = false; | 281 success = false; |
282 break; | 282 break; |
283 } | 283 } |
284 int lstat_success = TEMP_FAILURE_RETRY( | 284 int lstat_success = TEMP_FAILURE_RETRY( |
285 lstat64(path->AsString(), &entry_info)); | 285 lstat(path->AsString(), &entry_info)); |
286 if (lstat_success == -1) { | 286 if (lstat_success == -1) { |
287 success = false; | 287 success = false; |
288 break; | 288 break; |
289 } | 289 } |
290 path->Reset(path_length); | 290 path->Reset(path_length); |
291 if (S_ISDIR(entry_info.st_mode)) { | 291 if (S_ISDIR(entry_info.st_mode)) { |
292 success = success && DeleteDir(entry.d_name, path); | 292 success = success && DeleteDir(entry.d_name, path); |
293 } else if (S_ISREG(entry_info.st_mode) || S_ISLNK(entry_info.st_mode)) { | 293 } else if (S_ISREG(entry_info.st_mode) || S_ISLNK(entry_info.st_mode)) { |
294 // Treat links as files. This will delete the link which is | 294 // Treat links as files. This will delete the link which is |
295 // what we want no matter if the link target is a file or a | 295 // what we want no matter if the link target is a file or a |
(...skipping 11 matching lines...) Expand all Loading... |
307 if ((read != 0) || | 307 if ((read != 0) || |
308 (closedir(dir_pointer) == -1) || | 308 (closedir(dir_pointer) == -1) || |
309 (remove(path->AsString()) == -1)) { | 309 (remove(path->AsString()) == -1)) { |
310 return false; | 310 return false; |
311 } | 311 } |
312 return success; | 312 return success; |
313 } | 313 } |
314 | 314 |
315 | 315 |
316 Directory::ExistsResult Directory::Exists(const char* dir_name) { | 316 Directory::ExistsResult Directory::Exists(const char* dir_name) { |
317 struct stat64 entry_info; | 317 struct stat entry_info; |
318 int success = TEMP_FAILURE_RETRY(stat64(dir_name, &entry_info)); | 318 int success = TEMP_FAILURE_RETRY(stat(dir_name, &entry_info)); |
319 if (success == 0) { | 319 if (success == 0) { |
320 if (S_ISDIR(entry_info.st_mode)) { | 320 if (S_ISDIR(entry_info.st_mode)) { |
321 return EXISTS; | 321 return EXISTS; |
322 } else { | 322 } else { |
323 return DOES_NOT_EXIST; | 323 return DOES_NOT_EXIST; |
324 } | 324 } |
325 } else { | 325 } else { |
326 if (errno == EACCES || | 326 if (errno == EACCES || |
327 errno == EBADF || | 327 errno == EBADF || |
328 errno == EFAULT || | 328 errno == EFAULT || |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
388 | 388 |
389 char* Directory::SystemTemp() { | 389 char* Directory::SystemTemp() { |
390 // Android does not have a /tmp directory. A partial substitute, | 390 // Android does not have a /tmp directory. A partial substitute, |
391 // suitable for bring-up work and tests, is to create a tmp | 391 // suitable for bring-up work and tests, is to create a tmp |
392 // directory in /data/local/tmp. | 392 // directory in /data/local/tmp. |
393 // | 393 // |
394 // TODO(4413): In the long run, when running in an application we should | 394 // TODO(4413): In the long run, when running in an application we should |
395 // probably use the appropriate directory from the Android API, | 395 // probably use the appropriate directory from the Android API, |
396 // probably what File.createTempFile uses. | 396 // probably what File.createTempFile uses. |
397 #define ANDROID_TEMP_DIR "/data/local/tmp" | 397 #define ANDROID_TEMP_DIR "/data/local/tmp" |
398 struct stat64 st; | 398 struct stat st; |
399 if (stat64(ANDROID_TEMP_DIR, &st) != 0) { | 399 if (stat(ANDROID_TEMP_DIR, &st) != 0) { |
400 mkdir(ANDROID_TEMP_DIR, 0777); | 400 mkdir(ANDROID_TEMP_DIR, 0777); |
401 } | 401 } |
402 return strdup(ANDROID_TEMP_DIR); | 402 return strdup(ANDROID_TEMP_DIR); |
403 } | 403 } |
404 | 404 |
405 | 405 |
406 char* Directory::CreateTemp(const char* prefix) { | 406 char* Directory::CreateTemp(const char* prefix) { |
407 // Returns a new, unused directory name, adding characters to the end | 407 // Returns a new, unused directory name, adding characters to the end |
408 // of prefix. Creates the directory with the permissions specified | 408 // of prefix. Creates the directory with the permissions specified |
409 // by the process umask. | 409 // by the process umask. |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
445 bool Directory::Rename(const char* path, const char* new_path) { | 445 bool Directory::Rename(const char* path, const char* new_path) { |
446 ExistsResult exists = Exists(path); | 446 ExistsResult exists = Exists(path); |
447 if (exists != EXISTS) return false; | 447 if (exists != EXISTS) return false; |
448 return (TEMP_FAILURE_RETRY(rename(path, new_path)) == 0); | 448 return (TEMP_FAILURE_RETRY(rename(path, new_path)) == 0); |
449 } | 449 } |
450 | 450 |
451 } // namespace bin | 451 } // namespace bin |
452 } // namespace dart | 452 } // namespace dart |
453 | 453 |
454 #endif // defined(TARGET_OS_ANDROID) | 454 #endif // defined(TARGET_OS_ANDROID) |
OLD | NEW |