xref: /aosp_15_r20/external/cronet/base/files/file_enumerator.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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