| 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 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 371 *dir = FilePath(system_buffer); | 371 *dir = FilePath(system_buffer); |
| 372 return true; | 372 return true; |
| 373 } | 373 } |
| 374 | 374 |
| 375 // Sets the current working directory for the process. | 375 // Sets the current working directory for the process. |
| 376 bool SetCurrentDirectory(const FilePath& path) { | 376 bool SetCurrentDirectory(const FilePath& path) { |
| 377 int ret = chdir(path.value().c_str()); | 377 int ret = chdir(path.value().c_str()); |
| 378 return !ret; | 378 return !ret; |
| 379 } | 379 } |
| 380 | 380 |
| 381 FileEnumerator::FileEnumerator(const std::wstring& root_path, | 381 FileEnumerator::FileEnumerator(const FilePath& root_path, |
| 382 bool recursive, | 382 bool recursive, |
| 383 FileEnumerator::FILE_TYPE file_type) | 383 FileEnumerator::FILE_TYPE file_type) |
| 384 : recursive_(recursive), | 384 : recursive_(recursive), |
| 385 file_type_(file_type), | 385 file_type_(file_type), |
| 386 is_in_find_op_(false), | 386 is_in_find_op_(false), |
| 387 fts_(NULL) { | 387 fts_(NULL) { |
| 388 pending_paths_.push(root_path); | 388 pending_paths_.push(root_path); |
| 389 } | 389 } |
| 390 | 390 |
| 391 FileEnumerator::FileEnumerator(const std::wstring& root_path, | 391 FileEnumerator::FileEnumerator(const FilePath& root_path, |
| 392 bool recursive, | 392 bool recursive, |
| 393 FileEnumerator::FILE_TYPE file_type, | 393 FileEnumerator::FILE_TYPE file_type, |
| 394 const std::wstring& pattern) | 394 const FilePath::StringType& pattern) |
| 395 : recursive_(recursive), | 395 : recursive_(recursive), |
| 396 file_type_(file_type), | 396 file_type_(file_type), |
| 397 pattern_(root_path), | 397 pattern_(root_path.value()), |
| 398 is_in_find_op_(false), | 398 is_in_find_op_(false), |
| 399 fts_(NULL) { | 399 fts_(NULL) { |
| 400 // The Windows version of this code only matches against items in the top-most | 400 // The Windows version of this code only matches against items in the top-most |
| 401 // directory, and we're comparing fnmatch against full paths, so this is the | 401 // directory, and we're comparing fnmatch against full paths, so this is the |
| 402 // easiest way to get the right pattern. | 402 // easiest way to get the right pattern. |
| 403 AppendToPath(&pattern_, pattern); | 403 pattern_ = pattern_.Append(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) { | 412 void FileEnumerator::GetFindInfo(FindInfo* info) { |
| 413 DCHECK(info); | 413 DCHECK(info); |
| 414 | 414 |
| 415 if (!is_in_find_op_) | 415 if (!is_in_find_op_) |
| 416 return; | 416 return; |
| 417 | 417 |
| 418 memcpy(&(info->stat), fts_ent_->fts_statp, sizeof(info->stat)); | 418 memcpy(&(info->stat), fts_ent_->fts_statp, sizeof(info->stat)); |
| 419 info->filename.assign(fts_ent_->fts_name); | 419 info->filename.assign(fts_ent_->fts_name); |
| 420 } | 420 } |
| 421 | 421 |
| 422 // 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 |
| 423 // 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 |
| 424 // large directories with many files this can be quite deep. | 424 // large directories with many files this can be quite deep. |
| 425 // TODO(erikkay) - get rid of this recursive pattern | 425 // TODO(erikkay) - get rid of this recursive pattern |
| 426 std::wstring FileEnumerator::Next() { | 426 FilePath FileEnumerator::Next() { |
| 427 if (!is_in_find_op_) { | 427 if (!is_in_find_op_) { |
| 428 if (pending_paths_.empty()) | 428 if (pending_paths_.empty()) |
| 429 return std::wstring(); | 429 return FilePath(); |
| 430 | 430 |
| 431 // The last find FindFirstFile operation is done, prepare a new one. | 431 // The last find FindFirstFile operation is done, prepare a new one. |
| 432 root_path_ = pending_paths_.top(); | 432 root_path_ = pending_paths_.top(); |
| 433 TrimTrailingSeparator(&root_path_); | 433 root_path_ = root_path_.StripTrailingSeparators(); |
| 434 pending_paths_.pop(); | 434 pending_paths_.pop(); |
| 435 | 435 |
| 436 // Start a new find operation. | 436 // Start a new find operation. |
| 437 int ftsflags = FTS_LOGICAL; | 437 int ftsflags = FTS_LOGICAL; |
| 438 char top_dir[PATH_MAX]; | 438 char top_dir[PATH_MAX]; |
| 439 base::strlcpy(top_dir, WideToUTF8(root_path_).c_str(), sizeof(top_dir)); | 439 base::strlcpy(top_dir, root_path_.value().c_str(), sizeof(top_dir)); |
| 440 char* dir_list[2] = { top_dir, NULL }; | 440 char* dir_list[2] = { top_dir, NULL }; |
| 441 fts_ = fts_open(dir_list, ftsflags, NULL); | 441 fts_ = fts_open(dir_list, ftsflags, NULL); |
| 442 if (!fts_) | 442 if (!fts_) |
| 443 return Next(); | 443 return Next(); |
| 444 is_in_find_op_ = true; | 444 is_in_find_op_ = true; |
| 445 } | 445 } |
| 446 | 446 |
| 447 fts_ent_ = fts_read(fts_); | 447 fts_ent_ = fts_read(fts_); |
| 448 if (fts_ent_ == NULL) { | 448 if (fts_ent_ == NULL) { |
| 449 fts_close(fts_); | 449 fts_close(fts_); |
| 450 fts_ = NULL; | 450 fts_ = NULL; |
| 451 is_in_find_op_ = false; | 451 is_in_find_op_ = false; |
| 452 return Next(); | 452 return Next(); |
| 453 } | 453 } |
| 454 | 454 |
| 455 // Level 0 is the top, which is always skipped. | 455 // Level 0 is the top, which is always skipped. |
| 456 if (fts_ent_->fts_level == 0) | 456 if (fts_ent_->fts_level == 0) |
| 457 return Next(); | 457 return Next(); |
| 458 | 458 |
| 459 // 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. |
| 460 // (see Windows implementation) | 460 // (see Windows implementation) |
| 461 if (fts_ent_->fts_level == 1 && pattern_.length() > 0) { | 461 if (fts_ent_->fts_level == 1 && pattern_.value().length() > 0) { |
| 462 if (fnmatch(WideToUTF8(pattern_).c_str(), fts_ent_->fts_path, 0) != 0) { | 462 if (fnmatch(pattern_.value().c_str(), fts_ent_->fts_path, 0) != 0) { |
| 463 if (fts_ent_->fts_info == FTS_D) | 463 if (fts_ent_->fts_info == FTS_D) |
| 464 fts_set(fts_, fts_ent_, FTS_SKIP); | 464 fts_set(fts_, fts_ent_, FTS_SKIP); |
| 465 return Next(); | 465 return Next(); |
| 466 } | 466 } |
| 467 } | 467 } |
| 468 | 468 |
| 469 std::wstring cur_file(UTF8ToWide(fts_ent_->fts_path)); | 469 FilePath cur_file(fts_ent_->fts_path); |
| 470 if (fts_ent_->fts_info == FTS_D) { | 470 if (fts_ent_->fts_info == FTS_D) { |
| 471 // If not recursive, then prune children. | 471 // If not recursive, then prune children. |
| 472 if (!recursive_) | 472 if (!recursive_) |
| 473 fts_set(fts_, fts_ent_, FTS_SKIP); | 473 fts_set(fts_, fts_ent_, FTS_SKIP); |
| 474 return (file_type_ & FileEnumerator::DIRECTORIES) ? cur_file : Next(); | 474 return (file_type_ & FileEnumerator::DIRECTORIES) ? cur_file : Next(); |
| 475 } else if (fts_ent_->fts_info == FTS_F) { | 475 } else if (fts_ent_->fts_info == FTS_F) { |
| 476 return (file_type_ & FileEnumerator::FILES) ? cur_file : Next(); | 476 return (file_type_ & FileEnumerator::FILES) ? cur_file : Next(); |
| 477 } | 477 } |
| 478 // 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 |
| 479 return Next(); | 479 return Next(); |
| 480 } | 480 } |
| 481 | 481 |
| 482 | 482 |
| 483 } // namespace file_util | 483 } // namespace file_util |
| OLD | NEW |