| 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 |