OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/file_util.h" | 5 #include "base/file_util.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <fcntl.h> | 8 #include <fcntl.h> |
9 #include <fnmatch.h> | 9 #include <fnmatch.h> |
10 #include <fts.h> | 10 #include <fts.h> |
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
402 // easiest way to get the right pattern. | 402 // easiest way to get the right pattern. |
403 AppendToPath(&pattern_, pattern); | 403 AppendToPath(&pattern_, pattern); |
404 pending_paths_.push(root_path); | 404 pending_paths_.push(root_path); |
405 } | 405 } |
406 | 406 |
407 FileEnumerator::~FileEnumerator() { | 407 FileEnumerator::~FileEnumerator() { |
408 if (fts_) | 408 if (fts_) |
409 fts_close(fts_); | 409 fts_close(fts_); |
410 } | 410 } |
411 | 411 |
| 412 void FileEnumerator::GetFindInfo(FindInfo* info) { |
| 413 DCHECK(info); |
| 414 |
| 415 if (!is_in_find_op_) |
| 416 return; |
| 417 |
| 418 memcpy(&(info->stat), fts_ent_->fts_statp, sizeof(info->stat)); |
| 419 info->filename.assign(fts_ent_->fts_name); |
| 420 } |
| 421 |
412 // As it stands, this method calls itself recursively when the next item of | 422 // As it stands, this method calls itself recursively when the next item of |
413 // the fts enumeration doesn't match (type, pattern, etc.). In the case of | 423 // the fts enumeration doesn't match (type, pattern, etc.). In the case of |
414 // large directories with many files this can be quite deep. | 424 // large directories with many files this can be quite deep. |
415 // TODO(erikkay) - get rid of this recursive pattern | 425 // TODO(erikkay) - get rid of this recursive pattern |
416 std::wstring FileEnumerator::Next() { | 426 std::wstring FileEnumerator::Next() { |
417 if (!is_in_find_op_) { | 427 if (!is_in_find_op_) { |
418 if (pending_paths_.empty()) | 428 if (pending_paths_.empty()) |
419 return std::wstring(); | 429 return std::wstring(); |
420 | 430 |
421 // The last find FindFirstFile operation is done, prepare a new one. | 431 // The last find FindFirstFile operation is done, prepare a new one. |
422 root_path_ = pending_paths_.top(); | 432 root_path_ = pending_paths_.top(); |
423 TrimTrailingSeparator(&root_path_); | 433 TrimTrailingSeparator(&root_path_); |
424 pending_paths_.pop(); | 434 pending_paths_.pop(); |
425 | 435 |
426 // Start a new find operation. | 436 // Start a new find operation. |
427 int ftsflags = FTS_LOGICAL; | 437 int ftsflags = FTS_LOGICAL; |
428 char top_dir[PATH_MAX]; | 438 char top_dir[PATH_MAX]; |
429 base::strlcpy(top_dir, WideToUTF8(root_path_).c_str(), sizeof(top_dir)); | 439 base::strlcpy(top_dir, WideToUTF8(root_path_).c_str(), sizeof(top_dir)); |
430 char* dir_list[2] = { top_dir, NULL }; | 440 char* dir_list[2] = { top_dir, NULL }; |
431 fts_ = fts_open(dir_list, ftsflags, NULL); | 441 fts_ = fts_open(dir_list, ftsflags, NULL); |
432 if (!fts_) | 442 if (!fts_) |
433 return Next(); | 443 return Next(); |
434 is_in_find_op_ = true; | 444 is_in_find_op_ = true; |
435 } | 445 } |
436 | 446 |
437 FTSENT* fts_ent = fts_read(fts_); | 447 fts_ent_ = fts_read(fts_); |
438 if (fts_ent == NULL) { | 448 if (fts_ent_ == NULL) { |
439 fts_close(fts_); | 449 fts_close(fts_); |
440 fts_ = NULL; | 450 fts_ = NULL; |
441 is_in_find_op_ = false; | 451 is_in_find_op_ = false; |
442 return Next(); | 452 return Next(); |
443 } | 453 } |
444 | 454 |
445 // Level 0 is the top, which is always skipped. | 455 // Level 0 is the top, which is always skipped. |
446 if (fts_ent->fts_level == 0) | 456 if (fts_ent_->fts_level == 0) |
447 return Next(); | 457 return Next(); |
448 | 458 |
449 // Patterns are only matched on the items in the top-most directory. | 459 // Patterns are only matched on the items in the top-most directory. |
450 // (see Windows implementation) | 460 // (see Windows implementation) |
451 if (fts_ent->fts_level == 1 && pattern_.length() > 0) { | 461 if (fts_ent_->fts_level == 1 && pattern_.length() > 0) { |
452 if (fnmatch(WideToUTF8(pattern_).c_str(), fts_ent->fts_path, 0) != 0) { | 462 if (fnmatch(WideToUTF8(pattern_).c_str(), fts_ent_->fts_path, 0) != 0) { |
453 if (fts_ent->fts_info == FTS_D) | 463 if (fts_ent_->fts_info == FTS_D) |
454 fts_set(fts_, fts_ent, FTS_SKIP); | 464 fts_set(fts_, fts_ent_, FTS_SKIP); |
455 return Next(); | 465 return Next(); |
456 } | 466 } |
457 } | 467 } |
458 | 468 |
459 std::wstring cur_file(UTF8ToWide(fts_ent->fts_path)); | 469 std::wstring cur_file(UTF8ToWide(fts_ent_->fts_path)); |
460 if (fts_ent->fts_info == FTS_D) { | 470 if (fts_ent_->fts_info == FTS_D) { |
461 // If not recursive, then prune children. | 471 // If not recursive, then prune children. |
462 if (!recursive_) | 472 if (!recursive_) |
463 fts_set(fts_, fts_ent, FTS_SKIP); | 473 fts_set(fts_, fts_ent_, FTS_SKIP); |
464 return (file_type_ & FileEnumerator::DIRECTORIES) ? cur_file : Next(); | 474 return (file_type_ & FileEnumerator::DIRECTORIES) ? cur_file : Next(); |
465 } else if (fts_ent->fts_info == FTS_F) { | 475 } else if (fts_ent_->fts_info == FTS_F) { |
466 return (file_type_ & FileEnumerator::FILES) ? cur_file : Next(); | 476 return (file_type_ & FileEnumerator::FILES) ? cur_file : Next(); |
467 } | 477 } |
468 // TODO(erikkay) - verify that the other fts_info types aren't interesting | 478 // TODO(erikkay) - verify that the other fts_info types aren't interesting |
469 return Next(); | 479 return Next(); |
470 } | 480 } |
471 | 481 |
472 | 482 |
473 } // namespace file_util | 483 } // namespace file_util |
OLD | NEW |