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

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

Issue 249233002: Fix recursive directory deletion, to not leak file descriptors (and pointers). (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Add check Created 6 years, 8 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/directory_linux.cc ('k') | no next file » | 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_MACOS) 6 #if defined(TARGET_OS_MACOS)
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 226 matching lines...) Expand 10 before | Expand all | Expand 10 after
237 if (NO_RETRY_EXPECTED(lstat(path->AsString(), &st)) == -1) { 237 if (NO_RETRY_EXPECTED(lstat(path->AsString(), &st)) == -1) {
238 return false; 238 return false;
239 } 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)) {
240 return (unlink(path->AsString()) == 0); 240 return (unlink(path->AsString()) == 0);
241 } 241 }
242 242
243 if (!path->Add(File::PathSeparator())) return false; 243 if (!path->Add(File::PathSeparator())) return false;
244 244
245 // 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
246 // directory. 246 // directory.
247 DIR* dir_pointer; 247 DIR* dir_pointer = opendir(path->AsString());
248 do {
249 dir_pointer = opendir(path->AsString());
250 } while (dir_pointer == NULL && errno == EINTR);
251
252 if (dir_pointer == NULL) { 248 if (dir_pointer == NULL) {
253 return false; 249 return false;
254 } 250 }
255 251
256 // Iterate the directory and delete all files and directories. 252 // Iterate the directory and delete all files and directories.
257 int path_length = path->length(); 253 int path_length = path->length();
258 int read = 0;
259 bool success = true;
260 dirent entry; 254 dirent entry;
261 dirent* result; 255 dirent* result;
262 while ((read = NO_RETRY_EXPECTED(readdir_r(dir_pointer, 256 while (NO_RETRY_EXPECTED(readdir_r(dir_pointer, &entry, &result)) == 0) {
263 &entry, 257 if (result == NULL) {
264 &result))) == 0 && 258 // End of directory.
265 result != NULL && 259 return NO_RETRY_EXPECTED(closedir(dir_pointer)) == 0 &&
266 success) { 260 NO_RETRY_EXPECTED(remove(path->AsString())) == 0;
261 }
262 bool ok = false;
267 switch (entry.d_type) { 263 switch (entry.d_type) {
268 case DT_DIR: 264 case DT_DIR:
269 success = success && DeleteDir(entry.d_name, path); 265 ok = DeleteDir(entry.d_name, path);
270 break; 266 break;
271 case DT_REG: 267 case DT_REG:
272 case DT_LNK: 268 case DT_LNK:
273 // Treat all links as files. This will delete the link which 269 // Treat all links as files. This will delete the link which
274 // is what we want no matter if the link target is a file or a 270 // is what we want no matter if the link target is a file or a
275 // directory. 271 // directory.
276 success = success && DeleteFile(entry.d_name, path); 272 ok = DeleteFile(entry.d_name, path);
277 break; 273 break;
278 case DT_UNKNOWN: { 274 case DT_UNKNOWN: {
275 if (!path->Add(entry.d_name)) {
276 break;
277 }
279 // On some file systems the entry type is not determined by 278 // On some file systems the entry type is not determined by
280 // readdir_r. For those we use lstat to determine the entry 279 // readdir_r. For those we use lstat to determine the entry
281 // type. 280 // type.
282 struct stat entry_info; 281 struct stat entry_info;
283 if (!path->Add(entry.d_name)) { 282 if (NO_RETRY_EXPECTED(lstat(path->AsString(), &entry_info)) == -1) {
284 success = false;
285 break;
286 }
287 int lstat_success = NO_RETRY_EXPECTED(
288 lstat(path->AsString(), &entry_info));
289 if (lstat_success == -1) {
290 success = false;
291 break; 283 break;
292 } 284 }
293 path->Reset(path_length); 285 path->Reset(path_length);
294 if (S_ISDIR(entry_info.st_mode)) { 286 if (S_ISDIR(entry_info.st_mode)) {
295 success = success && DeleteDir(entry.d_name, path); 287 ok = DeleteDir(entry.d_name, path);
296 } else if (S_ISREG(entry_info.st_mode) || S_ISLNK(entry_info.st_mode)) { 288 } else if (S_ISREG(entry_info.st_mode) || S_ISLNK(entry_info.st_mode)) {
297 // Treat links as files. This will delete the link which is 289 // Treat links as files. This will delete the link which is
298 // what we want no matter if the link target is a file or a 290 // what we want no matter if the link target is a file or a
299 // directory. 291 // directory.
300 success = success && DeleteFile(entry.d_name, path); 292 ok = DeleteFile(entry.d_name, path);
301 } 293 }
302 break; 294 break;
303 } 295 }
304 default: 296 default:
305 break; 297 break;
306 } 298 }
299 if (!ok) {
300 break;
301 }
307 path->Reset(path_length); 302 path->Reset(path_length);
308 } 303 }
309 304 // Only happens if an error.
310 if ((read != 0) || 305 ASSERT(errno != 0);
311 (closedir(dir_pointer) == -1) || 306 int err = errno;
312 (remove(path->AsString()) == -1)) { 307 VOID_NO_RETRY_EXPECTED(closedir(dir_pointer));
313 return false; 308 errno = err;
314 } 309 return false;
315 return success;
316 } 310 }
317 311
318 312
319 Directory::ExistsResult Directory::Exists(const char* dir_name) { 313 Directory::ExistsResult Directory::Exists(const char* dir_name) {
320 struct stat entry_info; 314 struct stat entry_info;
321 int success = NO_RETRY_EXPECTED(stat(dir_name, &entry_info)); 315 int success = NO_RETRY_EXPECTED(stat(dir_name, &entry_info));
322 if (success == 0) { 316 if (success == 0) {
323 if (S_ISDIR(entry_info.st_mode)) { 317 if (S_ISDIR(entry_info.st_mode)) {
324 return EXISTS; 318 return EXISTS;
325 } else { 319 } else {
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
428 bool Directory::Rename(const char* path, const char* new_path) { 422 bool Directory::Rename(const char* path, const char* new_path) {
429 ExistsResult exists = Exists(path); 423 ExistsResult exists = Exists(path);
430 if (exists != EXISTS) return false; 424 if (exists != EXISTS) return false;
431 return (NO_RETRY_EXPECTED(rename(path, new_path)) == 0); 425 return (NO_RETRY_EXPECTED(rename(path, new_path)) == 0);
432 } 426 }
433 427
434 } // namespace bin 428 } // namespace bin
435 } // namespace dart 429 } // namespace dart
436 430
437 #endif // defined(TARGET_OS_MACOS) 431 #endif // defined(TARGET_OS_MACOS)
OLDNEW
« no previous file with comments | « runtime/bin/directory_linux.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698