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

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

Issue 9316066: Implement recursive directory deletion. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fixing comment. Created 8 years, 10 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
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 "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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698