1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors 2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file. 4*6777b538SAndroid Build Coastguard Worker 5*6777b538SAndroid Build Coastguard Worker #ifndef BASE_FILES_FILE_ENUMERATOR_H_ 6*6777b538SAndroid Build Coastguard Worker #define BASE_FILES_FILE_ENUMERATOR_H_ 7*6777b538SAndroid Build Coastguard Worker 8*6777b538SAndroid Build Coastguard Worker #include <stddef.h> 9*6777b538SAndroid Build Coastguard Worker #include <stdint.h> 10*6777b538SAndroid Build Coastguard Worker 11*6777b538SAndroid Build Coastguard Worker #include <vector> 12*6777b538SAndroid Build Coastguard Worker 13*6777b538SAndroid Build Coastguard Worker #include "base/base_export.h" 14*6777b538SAndroid Build Coastguard Worker #include "base/containers/stack.h" 15*6777b538SAndroid Build Coastguard Worker #include "base/files/file.h" 16*6777b538SAndroid Build Coastguard Worker #include "base/files/file_path.h" 17*6777b538SAndroid Build Coastguard Worker #include "base/functional/function_ref.h" 18*6777b538SAndroid Build Coastguard Worker #include "base/time/time.h" 19*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h" 20*6777b538SAndroid Build Coastguard Worker 21*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN) 22*6777b538SAndroid Build Coastguard Worker #include "base/win/windows_types.h" 23*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) 24*6777b538SAndroid Build Coastguard Worker #include <sys/stat.h> 25*6777b538SAndroid Build Coastguard Worker #include <unistd.h> 26*6777b538SAndroid Build Coastguard Worker #include <unordered_set> 27*6777b538SAndroid Build Coastguard Worker #endif 28*6777b538SAndroid Build Coastguard Worker 29*6777b538SAndroid Build Coastguard Worker namespace base { 30*6777b538SAndroid Build Coastguard Worker 31*6777b538SAndroid Build Coastguard Worker // A class for enumerating the files in a provided path. The order of the 32*6777b538SAndroid Build Coastguard Worker // results is not guaranteed. 33*6777b538SAndroid Build Coastguard Worker // 34*6777b538SAndroid Build Coastguard Worker // This is blocking. Do not use on critical threads. 35*6777b538SAndroid Build Coastguard Worker // 36*6777b538SAndroid Build Coastguard Worker // Example: 37*6777b538SAndroid Build Coastguard Worker // 38*6777b538SAndroid Build Coastguard Worker // base::FileEnumerator e(my_dir, false, base::FileEnumerator::FILES, 39*6777b538SAndroid Build Coastguard Worker // FILE_PATH_LITERAL("*.txt")); 40*6777b538SAndroid Build Coastguard Worker // Using `ForEach` with a lambda: 41*6777b538SAndroid Build Coastguard Worker // e.ForEach([](const base::FilePath& item) {...}); 42*6777b538SAndroid Build Coastguard Worker // Using a `for` loop: 43*6777b538SAndroid Build Coastguard Worker // for (base::FilePath name = e.Next(); !name.empty(); name = e.Next()) 44*6777b538SAndroid Build Coastguard Worker // ... 45*6777b538SAndroid Build Coastguard Worker class BASE_EXPORT FileEnumerator { 46*6777b538SAndroid Build Coastguard Worker public: 47*6777b538SAndroid Build Coastguard Worker // Note: copy & assign supported. 48*6777b538SAndroid Build Coastguard Worker class BASE_EXPORT FileInfo { 49*6777b538SAndroid Build Coastguard Worker public: 50*6777b538SAndroid Build Coastguard Worker FileInfo(); 51*6777b538SAndroid Build Coastguard Worker ~FileInfo(); 52*6777b538SAndroid Build Coastguard Worker 53*6777b538SAndroid Build Coastguard Worker bool IsDirectory() const; 54*6777b538SAndroid Build Coastguard Worker 55*6777b538SAndroid Build Coastguard Worker // The name of the file. This will not include any path information. This 56*6777b538SAndroid Build Coastguard Worker // is in constrast to the value returned by FileEnumerator.Next() which 57*6777b538SAndroid Build Coastguard Worker // includes the |root_path| passed into the FileEnumerator constructor. 58*6777b538SAndroid Build Coastguard Worker FilePath GetName() const; 59*6777b538SAndroid Build Coastguard Worker 60*6777b538SAndroid Build Coastguard Worker int64_t GetSize() const; 61*6777b538SAndroid Build Coastguard Worker 62*6777b538SAndroid Build Coastguard Worker // On POSIX systems, this is rounded down to the second. 63*6777b538SAndroid Build Coastguard Worker Time GetLastModifiedTime() const; 64*6777b538SAndroid Build Coastguard Worker 65*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN) 66*6777b538SAndroid Build Coastguard Worker // Note that the cAlternateFileName (used to hold the "short" 8.3 name) 67*6777b538SAndroid Build Coastguard Worker // of the WIN32_FIND_DATA will be empty. Since we don't use short file 68*6777b538SAndroid Build Coastguard Worker // names, we tell Windows to omit it which speeds up the query slightly. find_data()69*6777b538SAndroid Build Coastguard Worker const WIN32_FIND_DATA& find_data() const { 70*6777b538SAndroid Build Coastguard Worker return *ChromeToWindowsType(&find_data_); 71*6777b538SAndroid Build Coastguard Worker } 72*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) stat()73*6777b538SAndroid Build Coastguard Worker const stat_wrapper_t& stat() const { return stat_; } 74*6777b538SAndroid Build Coastguard Worker #endif 75*6777b538SAndroid Build Coastguard Worker 76*6777b538SAndroid Build Coastguard Worker private: 77*6777b538SAndroid Build Coastguard Worker friend class FileEnumerator; 78*6777b538SAndroid Build Coastguard Worker 79*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN) 80*6777b538SAndroid Build Coastguard Worker CHROME_WIN32_FIND_DATA find_data_; 81*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) 82*6777b538SAndroid Build Coastguard Worker stat_wrapper_t stat_; 83*6777b538SAndroid Build Coastguard Worker FilePath filename_; 84*6777b538SAndroid Build Coastguard Worker #endif 85*6777b538SAndroid Build Coastguard Worker }; 86*6777b538SAndroid Build Coastguard Worker 87*6777b538SAndroid Build Coastguard Worker enum FileType { 88*6777b538SAndroid Build Coastguard Worker FILES = 1 << 0, 89*6777b538SAndroid Build Coastguard Worker DIRECTORIES = 1 << 1, 90*6777b538SAndroid Build Coastguard Worker INCLUDE_DOT_DOT = 1 << 2, 91*6777b538SAndroid Build Coastguard Worker 92*6777b538SAndroid Build Coastguard Worker // Report only the names of entries and not their type, size, or 93*6777b538SAndroid Build Coastguard Worker // last-modified time. May only be used for non-recursive enumerations, and 94*6777b538SAndroid Build Coastguard Worker // implicitly includes both files and directories (neither of which may be 95*6777b538SAndroid Build Coastguard Worker // specified). When used, an enumerator's `GetInfo()` method must not be 96*6777b538SAndroid Build Coastguard Worker // called. 97*6777b538SAndroid Build Coastguard Worker NAMES_ONLY = 1 << 3, 98*6777b538SAndroid Build Coastguard Worker 99*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) 100*6777b538SAndroid Build Coastguard Worker SHOW_SYM_LINKS = 1 << 4, 101*6777b538SAndroid Build Coastguard Worker #endif 102*6777b538SAndroid Build Coastguard Worker }; 103*6777b538SAndroid Build Coastguard Worker 104*6777b538SAndroid Build Coastguard Worker // Search policy for intermediate folders. 105*6777b538SAndroid Build Coastguard Worker enum class FolderSearchPolicy { 106*6777b538SAndroid Build Coastguard Worker // Recursive search will pass through folders whose names match the 107*6777b538SAndroid Build Coastguard Worker // pattern. Inside each one, all files will be returned. Folders with names 108*6777b538SAndroid Build Coastguard Worker // that do not match the pattern will be ignored within their interior. 109*6777b538SAndroid Build Coastguard Worker MATCH_ONLY, 110*6777b538SAndroid Build Coastguard Worker // Recursive search will pass through every folder and perform pattern 111*6777b538SAndroid Build Coastguard Worker // matching inside each one. 112*6777b538SAndroid Build Coastguard Worker ALL, 113*6777b538SAndroid Build Coastguard Worker }; 114*6777b538SAndroid Build Coastguard Worker 115*6777b538SAndroid Build Coastguard Worker // Determines how a FileEnumerator handles errors encountered during 116*6777b538SAndroid Build Coastguard Worker // enumeration. When no ErrorPolicy is explicitly set, FileEnumerator defaults 117*6777b538SAndroid Build Coastguard Worker // to IGNORE_ERRORS. 118*6777b538SAndroid Build Coastguard Worker enum class ErrorPolicy { 119*6777b538SAndroid Build Coastguard Worker // Errors are ignored if possible and FileEnumerator returns as many files 120*6777b538SAndroid Build Coastguard Worker // as it is able to enumerate. 121*6777b538SAndroid Build Coastguard Worker IGNORE_ERRORS, 122*6777b538SAndroid Build Coastguard Worker 123*6777b538SAndroid Build Coastguard Worker // Any error encountered during enumeration will terminate the enumeration 124*6777b538SAndroid Build Coastguard Worker // immediately. An error code indicating the nature of a failure can be 125*6777b538SAndroid Build Coastguard Worker // retrieved from |GetError()|. 126*6777b538SAndroid Build Coastguard Worker STOP_ENUMERATION, 127*6777b538SAndroid Build Coastguard Worker }; 128*6777b538SAndroid Build Coastguard Worker 129*6777b538SAndroid Build Coastguard Worker // |root_path| is the starting directory to search for. It may or may not end 130*6777b538SAndroid Build Coastguard Worker // in a slash. 131*6777b538SAndroid Build Coastguard Worker // 132*6777b538SAndroid Build Coastguard Worker // If |recursive| is true, this will enumerate all matches in any 133*6777b538SAndroid Build Coastguard Worker // subdirectories matched as well. It does a breadth-first search, so all 134*6777b538SAndroid Build Coastguard Worker // files in one directory will be returned before any files in a 135*6777b538SAndroid Build Coastguard Worker // subdirectory. 136*6777b538SAndroid Build Coastguard Worker // 137*6777b538SAndroid Build Coastguard Worker // |file_type|, a bit mask of FileType, specifies whether the enumerator 138*6777b538SAndroid Build Coastguard Worker // should match files, directories, or both. 139*6777b538SAndroid Build Coastguard Worker // 140*6777b538SAndroid Build Coastguard Worker // |pattern| is an optional pattern for which files to match. This 141*6777b538SAndroid Build Coastguard Worker // works like shell globbing. For example, "*.txt" or "Foo???.doc". 142*6777b538SAndroid Build Coastguard Worker // However, be careful in specifying patterns that aren't cross platform 143*6777b538SAndroid Build Coastguard Worker // since the underlying code uses OS-specific matching routines. In general, 144*6777b538SAndroid Build Coastguard Worker // Windows matching is less featureful than others, so test there first. 145*6777b538SAndroid Build Coastguard Worker // If unspecified, this will match all files. 146*6777b538SAndroid Build Coastguard Worker // 147*6777b538SAndroid Build Coastguard Worker // |folder_search_policy| optionally specifies a search behavior. Refer to 148*6777b538SAndroid Build Coastguard Worker // |FolderSearchPolicy| for a list of folder search policies and the meaning 149*6777b538SAndroid Build Coastguard Worker // of them. If |recursive| is false, this parameter has no effect. 150*6777b538SAndroid Build Coastguard Worker // 151*6777b538SAndroid Build Coastguard Worker // |error_policy| optionally specifies the behavior when an error occurs. 152*6777b538SAndroid Build Coastguard Worker // Refer to |ErrorPolicy| for a list of error policies and the meaning of 153*6777b538SAndroid Build Coastguard Worker // them. 154*6777b538SAndroid Build Coastguard Worker FileEnumerator(const FilePath& root_path, bool recursive, int file_type); 155*6777b538SAndroid Build Coastguard Worker FileEnumerator(const FilePath& root_path, 156*6777b538SAndroid Build Coastguard Worker bool recursive, 157*6777b538SAndroid Build Coastguard Worker int file_type, 158*6777b538SAndroid Build Coastguard Worker const FilePath::StringType& pattern); 159*6777b538SAndroid Build Coastguard Worker FileEnumerator(const FilePath& root_path, 160*6777b538SAndroid Build Coastguard Worker bool recursive, 161*6777b538SAndroid Build Coastguard Worker int file_type, 162*6777b538SAndroid Build Coastguard Worker const FilePath::StringType& pattern, 163*6777b538SAndroid Build Coastguard Worker FolderSearchPolicy folder_search_policy); 164*6777b538SAndroid Build Coastguard Worker FileEnumerator(const FilePath& root_path, 165*6777b538SAndroid Build Coastguard Worker bool recursive, 166*6777b538SAndroid Build Coastguard Worker int file_type, 167*6777b538SAndroid Build Coastguard Worker const FilePath::StringType& pattern, 168*6777b538SAndroid Build Coastguard Worker FolderSearchPolicy folder_search_policy, 169*6777b538SAndroid Build Coastguard Worker ErrorPolicy error_policy); 170*6777b538SAndroid Build Coastguard Worker FileEnumerator(const FileEnumerator&) = delete; 171*6777b538SAndroid Build Coastguard Worker FileEnumerator& operator=(const FileEnumerator&) = delete; 172*6777b538SAndroid Build Coastguard Worker ~FileEnumerator(); 173*6777b538SAndroid Build Coastguard Worker 174*6777b538SAndroid Build Coastguard Worker // Calls `ref` synchronously for each path found by the `FileEnumerator`. Each 175*6777b538SAndroid Build Coastguard Worker // path will incorporate the `root_path` passed in the constructor: 176*6777b538SAndroid Build Coastguard Worker // "<root_path>/file_name.txt". If the `root_path` is absolute, then so will 177*6777b538SAndroid Build Coastguard Worker // be the paths provided in the `ref` invocations. 178*6777b538SAndroid Build Coastguard Worker void ForEach(FunctionRef<void(const FilePath& path)> ref); 179*6777b538SAndroid Build Coastguard Worker 180*6777b538SAndroid Build Coastguard Worker // Returns the next file or an empty string if there are no more results. 181*6777b538SAndroid Build Coastguard Worker // 182*6777b538SAndroid Build Coastguard Worker // The returned path will incorporate the |root_path| passed in the 183*6777b538SAndroid Build Coastguard Worker // constructor: "<root_path>/file_name.txt". If the |root_path| is absolute, 184*6777b538SAndroid Build Coastguard Worker // then so will be the result of Next(). 185*6777b538SAndroid Build Coastguard Worker FilePath Next(); 186*6777b538SAndroid Build Coastguard Worker 187*6777b538SAndroid Build Coastguard Worker // Returns info about the file last returned by Next(). Note that on Windows 188*6777b538SAndroid Build Coastguard Worker // and Fuchsia, GetInfo() does not play well with INCLUDE_DOT_DOT. In 189*6777b538SAndroid Build Coastguard Worker // particular, the GetLastModifiedTime() for the .. directory is 1601-01-01 190*6777b538SAndroid Build Coastguard Worker // on Fuchsia (https://crbug.com/1106172) and is equal to the last modified 191*6777b538SAndroid Build Coastguard Worker // time of the current directory on Windows (https://crbug.com/1119546). 192*6777b538SAndroid Build Coastguard Worker // Must not be used with FileType::NAMES_ONLY. 193*6777b538SAndroid Build Coastguard Worker FileInfo GetInfo() const; 194*6777b538SAndroid Build Coastguard Worker 195*6777b538SAndroid Build Coastguard Worker // Once |Next()| returns an empty path, enumeration has been terminated. If 196*6777b538SAndroid Build Coastguard Worker // termination was normal (i.e. no more results to enumerate) or ErrorPolicy 197*6777b538SAndroid Build Coastguard Worker // is set to IGNORE_ERRORS, this returns FILE_OK. Otherwise it returns an 198*6777b538SAndroid Build Coastguard Worker // error code reflecting why enumeration was stopped early. GetError()199*6777b538SAndroid Build Coastguard Worker File::Error GetError() const { return error_; } 200*6777b538SAndroid Build Coastguard Worker 201*6777b538SAndroid Build Coastguard Worker private: 202*6777b538SAndroid Build Coastguard Worker // Returns true if the given path should be skipped in enumeration. 203*6777b538SAndroid Build Coastguard Worker bool ShouldSkip(const FilePath& path); 204*6777b538SAndroid Build Coastguard Worker 205*6777b538SAndroid Build Coastguard Worker bool IsTypeMatched(bool is_dir) const; 206*6777b538SAndroid Build Coastguard Worker 207*6777b538SAndroid Build Coastguard Worker bool IsPatternMatched(const FilePath& src) const; 208*6777b538SAndroid Build Coastguard Worker 209*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN) find_data()210*6777b538SAndroid Build Coastguard Worker const WIN32_FIND_DATA& find_data() const { 211*6777b538SAndroid Build Coastguard Worker return *ChromeToWindowsType(&find_data_); 212*6777b538SAndroid Build Coastguard Worker } 213*6777b538SAndroid Build Coastguard Worker 214*6777b538SAndroid Build Coastguard Worker // True when find_data_ is valid. 215*6777b538SAndroid Build Coastguard Worker bool has_find_data_ = false; 216*6777b538SAndroid Build Coastguard Worker CHROME_WIN32_FIND_DATA find_data_; 217*6777b538SAndroid Build Coastguard Worker HANDLE find_handle_ = INVALID_HANDLE_VALUE; 218*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) 219*6777b538SAndroid Build Coastguard Worker // The files in the current directory 220*6777b538SAndroid Build Coastguard Worker std::vector<FileInfo> directory_entries_; 221*6777b538SAndroid Build Coastguard Worker 222*6777b538SAndroid Build Coastguard Worker // Set of visited directories. Used to prevent infinite looping along 223*6777b538SAndroid Build Coastguard Worker // circular symlinks. 224*6777b538SAndroid Build Coastguard Worker // The Android NDK (r23) does not declare `st_ino` as an `ino_t`, hence the 225*6777b538SAndroid Build Coastguard Worker // need for the ugly decltype. 226*6777b538SAndroid Build Coastguard Worker std::unordered_set<decltype(stat_wrapper_t::st_ino)> visited_directories_; 227*6777b538SAndroid Build Coastguard Worker 228*6777b538SAndroid Build Coastguard Worker // The next entry to use from the directory_entries_ vector 229*6777b538SAndroid Build Coastguard Worker size_t current_directory_entry_; 230*6777b538SAndroid Build Coastguard Worker #endif 231*6777b538SAndroid Build Coastguard Worker FilePath root_path_; 232*6777b538SAndroid Build Coastguard Worker const bool recursive_; 233*6777b538SAndroid Build Coastguard Worker int file_type_; 234*6777b538SAndroid Build Coastguard Worker FilePath::StringType pattern_; 235*6777b538SAndroid Build Coastguard Worker const FolderSearchPolicy folder_search_policy_; 236*6777b538SAndroid Build Coastguard Worker const ErrorPolicy error_policy_; 237*6777b538SAndroid Build Coastguard Worker File::Error error_ = File::FILE_OK; 238*6777b538SAndroid Build Coastguard Worker 239*6777b538SAndroid Build Coastguard Worker // A stack that keeps track of which subdirectories we still need to 240*6777b538SAndroid Build Coastguard Worker // enumerate in the breadth-first search. 241*6777b538SAndroid Build Coastguard Worker base::stack<FilePath> pending_paths_; 242*6777b538SAndroid Build Coastguard Worker }; 243*6777b538SAndroid Build Coastguard Worker 244*6777b538SAndroid Build Coastguard Worker } // namespace base 245*6777b538SAndroid Build Coastguard Worker 246*6777b538SAndroid Build Coastguard Worker #endif // BASE_FILES_FILE_ENUMERATOR_H_ 247