OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 <windows.h> | 7 #include <windows.h> |
8 #include <psapi.h> | 8 #include <psapi.h> |
9 #include <shellapi.h> | 9 #include <shellapi.h> |
10 #include <shlobj.h> | 10 #include <shlobj.h> |
(...skipping 577 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
588 return true; | 588 return true; |
589 } | 589 } |
590 | 590 |
591 // Sets the current working directory for the process. | 591 // Sets the current working directory for the process. |
592 bool SetCurrentDirectory(const FilePath& directory) { | 592 bool SetCurrentDirectory(const FilePath& directory) { |
593 base::ThreadRestrictions::AssertIOAllowed(); | 593 base::ThreadRestrictions::AssertIOAllowed(); |
594 BOOL ret = ::SetCurrentDirectory(directory.value().c_str()); | 594 BOOL ret = ::SetCurrentDirectory(directory.value().c_str()); |
595 return ret != 0; | 595 return ret != 0; |
596 } | 596 } |
597 | 597 |
| 598 /////////////////////////////////////////////// |
| 599 // FileEnumerator |
| 600 |
| 601 FileEnumerator::FileEnumerator(const FilePath& root_path, |
| 602 bool recursive, |
| 603 int file_type) |
| 604 : recursive_(recursive), |
| 605 file_type_(file_type), |
| 606 has_find_data_(false), |
| 607 find_handle_(INVALID_HANDLE_VALUE) { |
| 608 // INCLUDE_DOT_DOT must not be specified if recursive. |
| 609 DCHECK(!(recursive && (INCLUDE_DOT_DOT & file_type_))); |
| 610 memset(&find_data_, 0, sizeof(find_data_)); |
| 611 pending_paths_.push(root_path); |
| 612 } |
| 613 |
| 614 FileEnumerator::FileEnumerator(const FilePath& root_path, |
| 615 bool recursive, |
| 616 int file_type, |
| 617 const FilePath::StringType& pattern) |
| 618 : recursive_(recursive), |
| 619 file_type_(file_type), |
| 620 has_find_data_(false), |
| 621 pattern_(pattern), |
| 622 find_handle_(INVALID_HANDLE_VALUE) { |
| 623 // INCLUDE_DOT_DOT must not be specified if recursive. |
| 624 DCHECK(!(recursive && (INCLUDE_DOT_DOT & file_type_))); |
| 625 memset(&find_data_, 0, sizeof(find_data_)); |
| 626 pending_paths_.push(root_path); |
| 627 } |
| 628 |
| 629 FileEnumerator::~FileEnumerator() { |
| 630 if (find_handle_ != INVALID_HANDLE_VALUE) |
| 631 FindClose(find_handle_); |
| 632 } |
| 633 |
| 634 void FileEnumerator::GetFindInfo(FindInfo* info) { |
| 635 DCHECK(info); |
| 636 |
| 637 if (!has_find_data_) |
| 638 return; |
| 639 |
| 640 memcpy(info, &find_data_, sizeof(*info)); |
| 641 } |
| 642 |
| 643 // static |
| 644 bool FileEnumerator::IsDirectory(const FindInfo& info) { |
| 645 return (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; |
| 646 } |
| 647 |
| 648 // static |
| 649 FilePath FileEnumerator::GetFilename(const FindInfo& find_info) { |
| 650 return FilePath(find_info.cFileName); |
| 651 } |
| 652 |
| 653 // static |
| 654 int64 FileEnumerator::GetFilesize(const FindInfo& find_info) { |
| 655 ULARGE_INTEGER size; |
| 656 size.HighPart = find_info.nFileSizeHigh; |
| 657 size.LowPart = find_info.nFileSizeLow; |
| 658 DCHECK_LE(size.QuadPart, std::numeric_limits<int64>::max()); |
| 659 return static_cast<int64>(size.QuadPart); |
| 660 } |
| 661 |
| 662 // static |
| 663 base::Time FileEnumerator::GetLastModifiedTime(const FindInfo& find_info) { |
| 664 return base::Time::FromFileTime(find_info.ftLastWriteTime); |
| 665 } |
| 666 |
| 667 FilePath FileEnumerator::Next() { |
| 668 base::ThreadRestrictions::AssertIOAllowed(); |
| 669 |
| 670 while (has_find_data_ || !pending_paths_.empty()) { |
| 671 if (!has_find_data_) { |
| 672 // The last find FindFirstFile operation is done, prepare a new one. |
| 673 root_path_ = pending_paths_.top(); |
| 674 pending_paths_.pop(); |
| 675 |
| 676 // Start a new find operation. |
| 677 FilePath src = root_path_; |
| 678 |
| 679 if (pattern_.empty()) |
| 680 src = src.Append(L"*"); // No pattern = match everything. |
| 681 else |
| 682 src = src.Append(pattern_); |
| 683 |
| 684 find_handle_ = FindFirstFile(src.value().c_str(), &find_data_); |
| 685 has_find_data_ = true; |
| 686 } else { |
| 687 // Search for the next file/directory. |
| 688 if (!FindNextFile(find_handle_, &find_data_)) { |
| 689 FindClose(find_handle_); |
| 690 find_handle_ = INVALID_HANDLE_VALUE; |
| 691 } |
| 692 } |
| 693 |
| 694 if (INVALID_HANDLE_VALUE == find_handle_) { |
| 695 has_find_data_ = false; |
| 696 |
| 697 // This is reached when we have finished a directory and are advancing to |
| 698 // the next one in the queue. We applied the pattern (if any) to the files |
| 699 // in the root search directory, but for those directories which were |
| 700 // matched, we want to enumerate all files inside them. This will happen |
| 701 // when the handle is empty. |
| 702 pattern_ = FilePath::StringType(); |
| 703 |
| 704 continue; |
| 705 } |
| 706 |
| 707 FilePath cur_file(find_data_.cFileName); |
| 708 if (ShouldSkip(cur_file)) |
| 709 continue; |
| 710 |
| 711 // Construct the absolute filename. |
| 712 cur_file = root_path_.Append(find_data_.cFileName); |
| 713 |
| 714 if (find_data_.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { |
| 715 if (recursive_) { |
| 716 // If |cur_file| is a directory, and we are doing recursive searching, |
| 717 // add it to pending_paths_ so we scan it after we finish scanning this |
| 718 // directory. |
| 719 pending_paths_.push(cur_file); |
| 720 } |
| 721 if (file_type_ & FileEnumerator::DIRECTORIES) |
| 722 return cur_file; |
| 723 } else if (file_type_ & FileEnumerator::FILES) { |
| 724 return cur_file; |
| 725 } |
| 726 } |
| 727 |
| 728 return FilePath(); |
| 729 } |
| 730 |
598 bool NormalizeFilePath(const FilePath& path, FilePath* real_path) { | 731 bool NormalizeFilePath(const FilePath& path, FilePath* real_path) { |
599 base::ThreadRestrictions::AssertIOAllowed(); | 732 base::ThreadRestrictions::AssertIOAllowed(); |
600 FilePath mapped_file; | 733 FilePath mapped_file; |
601 if (!NormalizeToNativeFilePath(path, &mapped_file)) | 734 if (!NormalizeToNativeFilePath(path, &mapped_file)) |
602 return false; | 735 return false; |
603 // NormalizeToNativeFilePath() will return a path that starts with | 736 // NormalizeToNativeFilePath() will return a path that starts with |
604 // "\Device\Harddisk...". Helper DevicePathToDriveLetterPath() | 737 // "\Device\Harddisk...". Helper DevicePathToDriveLetterPath() |
605 // will find a drive letter which maps to the path's device, so | 738 // will find a drive letter which maps to the path's device, so |
606 // that we return a path starting with a drive letter. | 739 // that we return a path starting with a drive letter. |
607 return DevicePathToDriveLetterPath(mapped_file, real_path); | 740 return DevicePathToDriveLetterPath(mapped_file, real_path); |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
724 | 857 |
725 // Length of |path| with path separator appended. | 858 // Length of |path| with path separator appended. |
726 size_t prefix = path.StripTrailingSeparators().value().size() + 1; | 859 size_t prefix = path.StripTrailingSeparators().value().size() + 1; |
727 // The whole path string must be shorter than MAX_PATH. That is, it must be | 860 // The whole path string must be shorter than MAX_PATH. That is, it must be |
728 // prefix + component_length < MAX_PATH (or equivalently, <= MAX_PATH - 1). | 861 // prefix + component_length < MAX_PATH (or equivalently, <= MAX_PATH - 1). |
729 int whole_path_limit = std::max(0, MAX_PATH - 1 - static_cast<int>(prefix)); | 862 int whole_path_limit = std::max(0, MAX_PATH - 1 - static_cast<int>(prefix)); |
730 return std::min(whole_path_limit, static_cast<int>(max_length)); | 863 return std::min(whole_path_limit, static_cast<int>(max_length)); |
731 } | 864 } |
732 | 865 |
733 } // namespace file_util | 866 } // namespace file_util |
OLD | NEW |