file_enumerator.h 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  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/macros.h"
  14. #include "base/optional.h"
  15. #include "base/time/time.h"
  16. #include "build/build_config.h"
  17. #if defined(OS_WIN)
  18. #include <windows.h>
  19. #elif defined(OS_POSIX) || defined(OS_FUCHSIA)
  20. #include <unistd.h>
  21. #include <unordered_set>
  22. #include "base/files/file.h"
  23. #endif
  24. namespace base {
  25. // A class for enumerating the files in a provided path. The order of the
  26. // results is not guaranteed.
  27. //
  28. // This is blocking. Do not use on critical threads.
  29. //
  30. // Example:
  31. //
  32. // base::FileEnumerator e(my_dir, false, base::FileEnumerator::FILES,
  33. // FILE_PATH_LITERAL("*.txt"));
  34. // for (base::FilePath name = e.Next(); !name.empty(); name = e.Next())
  35. // ...
  36. class BASE_EXPORT FileEnumerator {
  37. public:
  38. // Note: copy & assign supported.
  39. class BASE_EXPORT FileInfo {
  40. public:
  41. FileInfo();
  42. ~FileInfo();
  43. bool IsDirectory() const;
  44. // The name of the file. This will not include any path information. This
  45. // is in constrast to the value returned by FileEnumerator.Next() which
  46. // includes the |root_path| passed into the FileEnumerator constructor.
  47. FilePath GetName() const;
  48. int64_t GetSize() const;
  49. // On POSIX systems, this is rounded down to the second.
  50. Time GetLastModifiedTime() const;
  51. #if defined(OS_WIN)
  52. // Note that the cAlternateFileName (used to hold the "short" 8.3 name)
  53. // of the WIN32_FIND_DATA will be empty. Since we don't use short file
  54. // names, we tell Windows to omit it which speeds up the query slightly.
  55. const WIN32_FIND_DATA& find_data() const { return find_data_; }
  56. #elif defined(OS_POSIX) || defined(OS_FUCHSIA)
  57. const stat_wrapper_t& stat() const { return stat_; }
  58. #endif
  59. private:
  60. friend class FileEnumerator;
  61. #if defined(OS_WIN)
  62. WIN32_FIND_DATA find_data_;
  63. #elif defined(OS_POSIX) || defined(OS_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 defined(OS_POSIX) || defined(OS_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();
  132. // Returns the next file or an empty string if there are no more results.
  133. //
  134. // The returned path will incorporate the |root_path| passed in the
  135. // constructor: "<root_path>/file_name.txt". If the |root_path| is absolute,
  136. // then so will be the result of Next().
  137. FilePath Next();
  138. // Returns info about the file last returned by Next(). Note that on Windows
  139. // and Fuchsia, GetInfo() does not play well with INCLUDE_DOT_DOT. In
  140. // particular, the GetLastModifiedTime() for the .. directory is 1601-01-01
  141. // on Fuchsia (https://crbug.com/1106172) and is equal to the last modified
  142. // time of the current directory on Windows (https://crbug.com/1119546).
  143. FileInfo GetInfo() const;
  144. // Once |Next()| returns an empty path, enumeration has been terminated. If
  145. // termination was normal (i.e. no more results to enumerate) or ErrorPolicy
  146. // is set to IGNORE_ERRORS, this returns FILE_OK. Otherwise it returns an
  147. // error code reflecting why enumeration was stopped early.
  148. File::Error GetError() const { return error_; }
  149. private:
  150. // Returns true if the given path should be skipped in enumeration.
  151. bool ShouldSkip(const FilePath& path);
  152. bool IsTypeMatched(bool is_dir) const;
  153. bool IsPatternMatched(const FilePath& src) const;
  154. #if defined(OS_WIN)
  155. // True when find_data_ is valid.
  156. bool has_find_data_ = false;
  157. WIN32_FIND_DATA find_data_;
  158. HANDLE find_handle_ = INVALID_HANDLE_VALUE;
  159. #elif defined(OS_POSIX) || defined(OS_FUCHSIA)
  160. // The files in the current directory
  161. std::vector<FileInfo> directory_entries_;
  162. // Set of visited directories. Used to prevent infinite looping along
  163. // circular symlinks.
  164. std::unordered_set<ino_t> visited_directories_;
  165. // The next entry to use from the directory_entries_ vector
  166. size_t current_directory_entry_;
  167. #endif
  168. FilePath root_path_;
  169. const bool recursive_;
  170. const int file_type_;
  171. FilePath::StringType pattern_;
  172. const FolderSearchPolicy folder_search_policy_;
  173. const ErrorPolicy error_policy_;
  174. File::Error error_ = File::FILE_OK;
  175. // A stack that keeps track of which subdirectories we still need to
  176. // enumerate in the breadth-first search.
  177. base::stack<FilePath> pending_paths_;
  178. DISALLOW_COPY_AND_ASSIGN(FileEnumerator);
  179. };
  180. } // namespace base
  181. #endif // BASE_FILES_FILE_ENUMERATOR_H_