file_enumerator_win.cc revision 3551c9c881056c480085172ff9840cab31610854
1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 2868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// found in the LICENSE file. 4868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/files/file_enumerator.h" 6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <string.h> 8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/logging.h" 10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/threading/thread_restrictions.h" 11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace base { 13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// FileEnumerator::FileInfo ---------------------------------------------------- 15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)FileEnumerator::FileInfo::FileInfo() { 17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) memset(&find_data_, 0, sizeof(find_data_)); 18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool FileEnumerator::FileInfo::IsDirectory() const { 21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return (find_data_.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; 22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)FilePath FileEnumerator::FileInfo::GetName() const { 25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return FilePath(find_data_.cFileName); 26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int64 FileEnumerator::FileInfo::GetSize() const { 29868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ULARGE_INTEGER size; 30868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) size.HighPart = find_data_.nFileSizeHigh; 31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) size.LowPart = find_data_.nFileSizeLow; 32868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK_LE(size.QuadPart, std::numeric_limits<int64>::max()); 33868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return static_cast<int64>(size.QuadPart); 34868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)base::Time FileEnumerator::FileInfo::GetLastModifiedTime() const { 37868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return base::Time::FromFileTime(find_data_.ftLastWriteTime); 38868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 39868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// FileEnumerator -------------------------------------------------------------- 41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)FileEnumerator::FileEnumerator(const FilePath& root_path, 43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) bool recursive, 44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int file_type) 45868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) : recursive_(recursive), 46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) file_type_(file_type), 47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) has_find_data_(false), 48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) find_handle_(INVALID_HANDLE_VALUE) { 49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // INCLUDE_DOT_DOT must not be specified if recursive. 50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(!(recursive && (INCLUDE_DOT_DOT & file_type_))); 51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) memset(&find_data_, 0, sizeof(find_data_)); 52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) pending_paths_.push(root_path); 53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 54868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)FileEnumerator::FileEnumerator(const FilePath& root_path, 56868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) bool recursive, 57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int file_type, 58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const FilePath::StringType& pattern) 59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) : recursive_(recursive), 60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) file_type_(file_type), 61868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) has_find_data_(false), 62868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) pattern_(pattern), 63868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) find_handle_(INVALID_HANDLE_VALUE) { 64868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // INCLUDE_DOT_DOT must not be specified if recursive. 65868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(!(recursive && (INCLUDE_DOT_DOT & file_type_))); 66868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) memset(&find_data_, 0, sizeof(find_data_)); 67868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) pending_paths_.push(root_path); 68868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 69868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 70868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)FileEnumerator::~FileEnumerator() { 71868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (find_handle_ != INVALID_HANDLE_VALUE) 72868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) FindClose(find_handle_); 73868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 74868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 75868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)FileEnumerator::FileInfo FileEnumerator::GetInfo() const { 76868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!has_find_data_) { 77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) NOTREACHED(); 78868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return FileInfo(); 79868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 80868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) FileInfo ret; 81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) memcpy(&ret.find_data_, &find_data_, sizeof(find_data_)); 82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return ret; 83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)FilePath FileEnumerator::Next() { 86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::ThreadRestrictions::AssertIOAllowed(); 87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) while (has_find_data_ || !pending_paths_.empty()) { 89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!has_find_data_) { 90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // The last find FindFirstFile operation is done, prepare a new one. 91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) root_path_ = pending_paths_.top(); 92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) pending_paths_.pop(); 93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Start a new find operation. 95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) FilePath src = root_path_; 96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 97868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (pattern_.empty()) 98868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) src = src.Append(L"*"); // No pattern = match everything. 99868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) else 100868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) src = src.Append(pattern_); 101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) find_handle_ = FindFirstFile(src.value().c_str(), &find_data_); 103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) has_find_data_ = true; 104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } else { 105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Search for the next file/directory. 106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!FindNextFile(find_handle_, &find_data_)) { 107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) FindClose(find_handle_); 108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) find_handle_ = INVALID_HANDLE_VALUE; 109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (INVALID_HANDLE_VALUE == find_handle_) { 113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) has_find_data_ = false; 114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // This is reached when we have finished a directory and are advancing to 116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // the next one in the queue. We applied the pattern (if any) to the files 117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // in the root search directory, but for those directories which were 118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // matched, we want to enumerate all files inside them. This will happen 119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // when the handle is empty. 120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) pattern_ = FilePath::StringType(); 121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) continue; 123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) FilePath cur_file(find_data_.cFileName); 126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (ShouldSkip(cur_file)) 127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) continue; 128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Construct the absolute filename. 130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) cur_file = root_path_.Append(find_data_.cFileName); 131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (find_data_.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { 133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (recursive_) { 134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // If |cur_file| is a directory, and we are doing recursive searching, 135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // add it to pending_paths_ so we scan it after we finish scanning this 1363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // directory. However, don't do recursion through reparse points or we 1373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // may end up with an infinite cycle. 1383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!(find_data_.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) 1393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) pending_paths_.push(cur_file); 140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (file_type_ & FileEnumerator::DIRECTORIES) 142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return cur_file; 143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } else if (file_type_ & FileEnumerator::FILES) { 144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return cur_file; 145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return FilePath(); 149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} // namespace base 152