file_enumerator.h 7.6 KB

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