Chromium Code Reviews| 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 "bin/directory.h" | 5 #include "bin/directory.h" |
| 6 | 6 |
| 7 #include <dirent.h> | 7 #include <dirent.h> |
| 8 #include <errno.h> | 8 #include <errno.h> |
| 9 #include <sys/param.h> | 9 #include <sys/param.h> |
| 10 #include <sys/stat.h> | 10 #include <sys/stat.h> |
| 11 #include <unistd.h> | 11 #include <unistd.h> |
| 12 | 12 |
| 13 #include "bin/file.h" | 13 #include "bin/file.h" |
| 14 #include "bin/platform.h" | 14 #include "bin/platform.h" |
| 15 | 15 |
| 16 | 16 |
| 17 static char* SafeStrNCpy(char* dest, const char* src, size_t n) { | 17 static char* SafeStrNCpy(char* dest, const char* src, size_t n) { |
| 18 strncpy(dest, src, n); | 18 strncpy(dest, src, n); |
| 19 dest[n - 1] = '\0'; | 19 dest[n - 1] = '\0'; |
| 20 return dest; | 20 return dest; |
| 21 } | 21 } |
| 22 | 22 |
| 23 | 23 |
| 24 static void SetOsErrorMessage(char* os_error_message, | 24 static void SetOsErrorMessage(char* os_error_message, |
| 25 int os_error_message_len) { | 25 int os_error_message_len) { |
| 26 SafeStrNCpy(os_error_message, strerror(errno), os_error_message_len); | 26 SafeStrNCpy(os_error_message, strerror(errno), os_error_message_len); |
| 27 } | 27 } |
| 28 | 28 |
| 29 | 29 |
| 30 // Forward declaration. | 30 // Forward declarations. |
| 31 static bool ListRecursively(const char* dir_name, | 31 static bool ListRecursively(const char* dir_name, |
| 32 bool recursive, | 32 bool recursive, |
| 33 Dart_Port dir_port, | 33 Dart_Port dir_port, |
| 34 Dart_Port file_port, | 34 Dart_Port file_port, |
| 35 Dart_Port done_port, | 35 Dart_Port done_port, |
| 36 Dart_Port error_port); | 36 Dart_Port error_port); |
| 37 static bool DeleteRecursively(const char* dir_name); | |
| 37 | 38 |
| 38 | 39 |
| 39 static void ComputeFullPath(const char* dir_name, | 40 static void ComputeFullPath(const char* dir_name, |
| 40 char* path, | 41 char* path, |
| 41 int* path_length) { | 42 int* path_length) { |
| 42 char* abs_path; | 43 char* abs_path; |
| 43 do { | 44 do { |
| 44 abs_path = realpath(dir_name, path); | 45 abs_path = realpath(dir_name, path); |
| 45 } while (abs_path == NULL && errno == EINTR); | 46 } while (abs_path == NULL && errno == EINTR); |
| 46 ASSERT(abs_path != NULL); | 47 ASSERT(abs_path != NULL); |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 213 | 214 |
| 214 if (closedir(dir_pointer) == -1) { | 215 if (closedir(dir_pointer) == -1) { |
| 215 PostError(error_port, "Failed to close directory", "", errno); | 216 PostError(error_port, "Failed to close directory", "", errno); |
| 216 } | 217 } |
| 217 free(path); | 218 free(path); |
| 218 | 219 |
| 219 return !listing_error; | 220 return !listing_error; |
| 220 } | 221 } |
| 221 | 222 |
| 222 | 223 |
| 224 static bool DeleteFile(char* file_name, | |
|
Bill Hesse
2012/02/02 17:24:39
Put a comment that strlen(path) may not be path_le
Mads Ager (google)
2012/02/03 11:48:54
This applies to all the methods in this file. I ha
| |
| 225 char* path, | |
| 226 int path_length) { | |
| 227 size_t written = snprintf(path + path_length, | |
| 228 PATH_MAX - path_length, | |
| 229 "%s", | |
| 230 file_name); | |
| 231 ASSERT(written == strlen(file_name)); | |
| 232 return (remove(path) == 0); | |
| 233 } | |
| 234 | |
| 235 | |
| 236 static bool DeleteDir(char* dir_name, | |
| 237 char* path, | |
| 238 int path_length) { | |
| 239 if (strcmp(dir_name, ".") != 0 && | |
| 240 strcmp(dir_name, "..") != 0) { | |
| 241 size_t written = snprintf(path + path_length, | |
| 242 PATH_MAX - path_length, | |
| 243 "%s", | |
| 244 dir_name); | |
| 245 ASSERT(written == strlen(dir_name)); | |
|
Bill Hesse
2012/02/02 17:24:39
In release mode, could a snprintf turn "long_path/
Mads Ager (google)
2012/02/03 11:48:54
Yes, that is not good. I have changed all the ASSE
| |
| 246 return DeleteRecursively(path); | |
| 247 } | |
| 248 return true; | |
| 249 } | |
| 250 | |
| 251 | |
| 252 static bool DeleteRecursively(const char* dir_name) { | |
| 253 DIR* dir_pointer; | |
| 254 do { | |
| 255 dir_pointer = opendir(dir_name); | |
| 256 } while (dir_pointer == NULL && errno == EINTR); | |
| 257 | |
| 258 if (dir_pointer == NULL) { | |
| 259 return false; | |
| 260 } | |
| 261 | |
| 262 // Compute full path for the directory currently being deleted. | |
| 263 char *path = static_cast<char*>(malloc(PATH_MAX)); | |
| 264 ASSERT(path != NULL); | |
| 265 int path_length = 0; | |
| 266 ComputeFullPath(dir_name, path, &path_length); | |
|
Bill Hesse
2012/02/02 17:24:39
ASSERT on path_length here?
Mads Ager (google)
2012/02/03 11:48:54
Reworked so ComputeFullPath returns a failure stat
| |
| 267 | |
| 268 // Iterated the directory and delete all files and directories. | |
|
Bill Hesse
2012/02/02 17:24:39
Iterate the directory ...
Mads Ager (google)
2012/02/03 11:48:54
Done.
| |
| 269 int success = 0; | |
| 270 bool error = false; | |
| 271 dirent entry; | |
| 272 dirent* result; | |
| 273 while ((success = TEMP_FAILURE_RETRY(readdir_r(dir_pointer, | |
| 274 &entry, | |
| 275 &result))) == 0 && | |
| 276 result != NULL && | |
| 277 !error) { | |
| 278 switch (entry.d_type) { | |
| 279 case DT_DIR: | |
| 280 error = error || !DeleteDir(entry.d_name, path, path_length); | |
| 281 break; | |
| 282 case DT_REG: | |
| 283 error = error || !DeleteFile(entry.d_name, path, path_length); | |
| 284 break; | |
| 285 case DT_UNKNOWN: { | |
| 286 // On some file systems the entry type is not determined by | |
| 287 // readdir_r. For those we use lstat to determine the entry | |
| 288 // type. | |
| 289 struct stat entry_info; | |
| 290 size_t written = snprintf(path + path_length, | |
| 291 PATH_MAX - path_length, | |
| 292 "%s", | |
| 293 entry.d_name); | |
| 294 ASSERT(written == strlen(entry.d_name)); | |
| 295 int lstat_success = TEMP_FAILURE_RETRY(lstat(path, &entry_info)); | |
| 296 if (lstat_success == -1) { | |
| 297 error = true; | |
| 298 break; | |
| 299 } | |
| 300 if ((entry_info.st_mode & S_IFMT) == S_IFDIR) { | |
| 301 error = error || !DeleteDir(entry.d_name, path, path_length); | |
| 302 } else if ((entry_info.st_mode & S_IFMT) == S_IFREG) { | |
| 303 error = error || !DeleteFile(entry.d_name, path, path_length); | |
| 304 } | |
| 305 break; | |
| 306 } | |
| 307 default: | |
| 308 break; | |
| 309 } | |
| 310 } | |
| 311 | |
| 312 free(path); | |
| 313 | |
| 314 if ((success != 0) || | |
| 315 (closedir(dir_pointer) == -1) || | |
| 316 (remove(dir_name) == -1)) { | |
| 317 return false; | |
| 318 } | |
| 319 | |
| 320 return !error; | |
|
Bill Hesse
2012/02/02 17:24:39
Every use of error really wants to use !error inst
Mads Ager (google)
2012/02/03 11:48:54
Good point. Renamed success->read, error->success
| |
| 321 } | |
| 322 | |
| 323 | |
| 223 void Directory::List(const char* dir_name, | 324 void Directory::List(const char* dir_name, |
| 224 bool recursive, | 325 bool recursive, |
| 225 Dart_Port dir_port, | 326 Dart_Port dir_port, |
| 226 Dart_Port file_port, | 327 Dart_Port file_port, |
| 227 Dart_Port done_port, | 328 Dart_Port done_port, |
| 228 Dart_Port error_port) { | 329 Dart_Port error_port) { |
| 229 bool completed = ListRecursively(dir_name, | 330 bool completed = ListRecursively(dir_name, |
| 230 recursive, | 331 recursive, |
| 231 dir_port, | 332 dir_port, |
| 232 file_port, | 333 file_port, |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 302 if (result == NULL) { | 403 if (result == NULL) { |
| 303 SetOsErrorMessage(os_error_message, os_error_message_len); | 404 SetOsErrorMessage(os_error_message, os_error_message_len); |
| 304 free(*path); | 405 free(*path); |
| 305 *path = NULL; | 406 *path = NULL; |
| 306 return errno; | 407 return errno; |
| 307 } | 408 } |
| 308 return 0; | 409 return 0; |
| 309 } | 410 } |
| 310 | 411 |
| 311 | 412 |
| 312 bool Directory::Delete(const char* dir_name) { | 413 bool Directory::Delete(const char* dir_name, bool recursive) { |
| 313 return (TEMP_FAILURE_RETRY(rmdir(dir_name)) == 0); | 414 if (!recursive) { |
| 415 return (TEMP_FAILURE_RETRY(remove(dir_name)) == 0); | |
| 416 } else { | |
| 417 return DeleteRecursively(dir_name); | |
| 418 } | |
| 314 } | 419 } |
| OLD | NEW |