file_enumerator.h 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  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 enum(my_dir, false, base::FileEnumerator::FILES,
  33. // FILE_PATH_LITERAL("*.txt"));
  34. // for (base::FilePath name = enum.Next(); !name.empty(); name = enum.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. Time GetLastModifiedTime() const;
  50. #if defined(OS_WIN)
  51. // Note that the cAlternateFileName (used to hold the "short" 8.3 name)
  52. // of the WIN32_FIND_DATA will be empty. Since we don't use short file
  53. // names, we tell Windows to omit it which speeds up the query slightly.
  54. const WIN32_FIND_DATA& find_data() const { return find_data_; }
  55. #elif defined(OS_POSIX) || defined(OS_FUCHSIA)
  56. const stat_wrapper_t& stat() const { return stat_; }
  57. #endif
  58. private:
  59. friend class FileEnumerator;
  60. #if defined(OS_WIN)
  61. WIN32_FIND_DATA find_data_;
  62. #elif defined(OS_POSIX) || defined(OS_FUCHSIA)
  63. stat_wrapper_t stat_;
  64. FilePath filename_;
  65. #endif
  66. };
  67. enum FileType {
  68. FILES = 1 << 0,
  69. DIRECTORIES = 1 << 1,
  70. INCLUDE_DOT_DOT = 1 << 2,
  71. #if defined(OS_POSIX) || defined(OS_FUCHSIA)
  72. SHOW_SYM_LINKS = 1 << 4,
  73. #endif
  74. };
  75. // Search policy for intermediate folders.
  76. enum class FolderSearchPolicy {
  77. // Recursive search will pass through folders whose names match the
  78. // pattern. Inside each one, all files will be returned. Folders with names
  79. // that do not match the pattern will be ignored within their interior.
  80. MATCH_ONLY,
  81. // Recursive search will pass through every folder and perform pattern
  82. // matching inside each one.
  83. ALL,
  84. };
  85. // Determines how a FileEnumerator handles errors encountered during
  86. // enumeration. When no ErrorPolicy is explicitly set, FileEnumerator defaults
  87. // to IGNORE_ERRORS.
  88. enum class ErrorPolicy {
  89. // Errors are ignored if possible and FileEnumerator returns as many files
  90. // as it is able to enumerate.
  91. IGNORE_ERRORS,
  92. // Any error encountered during enumeration will terminate the enumeration
  93. // immediately. An error code indicating the nature of a failure can be
  94. // retrieved from |GetError()|.
  95. STOP_ENUMERATION,
  96. };
  97. // |root_path| is the starting directory to search for. It may or may not end
  98. // in a slash.
  99. //
  100. // If |recursive| is true, this will enumerate all matches in any
  101. // subdirectories matched as well. It does a breadth-first search, so all
  102. // files in one directory will be returned before any files in a
  103. // subdirectory.
  104. //
  105. // |file_type|, a bit mask of FileType, specifies whether the enumerator
  106. // should match files, directories, or both.
  107. //
  108. // |pattern| is an optional pattern for which files to match. This
  109. // works like shell globbing. For example, "*.txt" or "Foo???.doc".
  110. // However, be careful in specifying patterns that aren't cross platform
  111. // since the underlying code uses OS-specific matching routines. In general,
  112. // Windows matching is less featureful than others, so test there first.
  113. // If unspecified, this will match all files.
  114. FileEnumerator(const FilePath& root_path, bool recursive, int file_type);
  115. FileEnumerator(const FilePath& root_path,
  116. bool recursive,
  117. int file_type,
  118. const FilePath::StringType& pattern);
  119. FileEnumerator(const FilePath& root_path,
  120. bool recursive,
  121. int file_type,
  122. const FilePath::StringType& pattern,
  123. FolderSearchPolicy folder_search_policy);
  124. FileEnumerator(const FilePath& root_path,
  125. bool recursive,
  126. int file_type,
  127. const FilePath::StringType& pattern,
  128. FolderSearchPolicy folder_search_policy,
  129. ErrorPolicy error_policy);
  130. ~FileEnumerator();
  131. // Returns the next file or an empty string if there are no more results.
  132. //
  133. // The returned path will incorporate the |root_path| passed in the
  134. // constructor: "<root_path>/file_name.txt". If the |root_path| is absolute,
  135. // then so will be the result of Next().
  136. FilePath Next();
  137. // Write the file info into |info|.
  138. FileInfo GetInfo() const;
  139. // Once |Next()| returns an empty path, enumeration has been terminated. If
  140. // termination was normal (i.e. no more results to enumerate) or ErrorPolicy
  141. // is set to IGNORE_ERRORS, this returns FILE_OK. Otherwise it returns an
  142. // error code reflecting why enumeration was stopped early.
  143. File::Error GetError() const { return error_; }
  144. private:
  145. // Returns true if the given path should be skipped in enumeration.
  146. bool ShouldSkip(const FilePath& path);
  147. bool IsTypeMatched(bool is_dir) const;
  148. bool IsPatternMatched(const FilePath& src) const;
  149. #if defined(OS_WIN)
  150. // True when find_data_ is valid.
  151. bool has_find_data_ = false;
  152. WIN32_FIND_DATA find_data_;
  153. HANDLE find_handle_ = INVALID_HANDLE_VALUE;
  154. #elif defined(OS_POSIX) || defined(OS_FUCHSIA)
  155. // The files in the current directory
  156. std::vector<FileInfo> directory_entries_;
  157. // Set of visited directories. Used to prevent infinite looping along
  158. // circular symlinks.
  159. std::unordered_set<ino_t> visited_directories_;
  160. // The next entry to use from the directory_entries_ vector
  161. size_t current_directory_entry_;
  162. #endif
  163. FilePath root_path_;
  164. const bool recursive_;
  165. const int file_type_;
  166. FilePath::StringType pattern_;
  167. const FolderSearchPolicy folder_search_policy_;
  168. const ErrorPolicy error_policy_;
  169. File::Error error_ = File::FILE_OK;
  170. // A stack that keeps track of which subdirectories we still need to
  171. // enumerate in the breadth-first search.
  172. base::stack<FilePath> pending_paths_;
  173. DISALLOW_COPY_AND_ASSIGN(FileEnumerator);
  174. };
  175. } // namespace base
  176. #endif // BASE_FILES_FILE_ENUMERATOR_H_