Home | History | Annotate | Download | only in files
      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 
      5 #ifndef BASE_FILES_FILE_ENUMERATOR_H_
      6 #define BASE_FILES_FILE_ENUMERATOR_H_
      7 
      8 #include <stddef.h>
      9 #include <stdint.h>
     10 
     11 #include <stack>
     12 #include <vector>
     13 
     14 #include "base/base_export.h"
     15 #include "base/files/file_path.h"
     16 #include "base/macros.h"
     17 #include "base/time/time.h"
     18 #include "build/build_config.h"
     19 
     20 #if defined(OS_WIN)
     21 #include <windows.h>
     22 #elif defined(OS_POSIX)
     23 #include <sys/stat.h>
     24 #include <unistd.h>
     25 #endif
     26 
     27 namespace base {
     28 
     29 // A class for enumerating the files in a provided path. The order of the
     30 // results is not guaranteed.
     31 //
     32 // This is blocking. Do not use on critical threads.
     33 //
     34 // Example:
     35 //
     36 //   base::FileEnumerator enum(my_dir, false, base::FileEnumerator::FILES,
     37 //                             FILE_PATH_LITERAL("*.txt"));
     38 //   for (base::FilePath name = enum.Next(); !name.empty(); name = enum.Next())
     39 //     ...
     40 class BASE_EXPORT FileEnumerator {
     41  public:
     42   // Note: copy & assign supported.
     43   class BASE_EXPORT FileInfo {
     44    public:
     45     FileInfo();
     46     ~FileInfo();
     47 
     48     bool IsDirectory() const;
     49 
     50     // The name of the file. This will not include any path information. This
     51     // is in constrast to the value returned by FileEnumerator.Next() which
     52     // includes the |root_path| passed into the FileEnumerator constructor.
     53     FilePath GetName() const;
     54 
     55     int64_t GetSize() const;
     56     Time GetLastModifiedTime() const;
     57 
     58 #if defined(OS_WIN)
     59     // Note that the cAlternateFileName (used to hold the "short" 8.3 name)
     60     // of the WIN32_FIND_DATA will be empty. Since we don't use short file
     61     // names, we tell Windows to omit it which speeds up the query slightly.
     62     const WIN32_FIND_DATA& find_data() const { return find_data_; }
     63 #elif defined(OS_POSIX)
     64     const struct stat& stat() const { return stat_; }
     65 #endif
     66 
     67    private:
     68     friend class FileEnumerator;
     69 
     70 #if defined(OS_WIN)
     71     WIN32_FIND_DATA find_data_;
     72 #elif defined(OS_POSIX)
     73     struct stat stat_;
     74     FilePath filename_;
     75 #endif
     76   };
     77 
     78   enum FileType {
     79     FILES                 = 1 << 0,
     80     DIRECTORIES           = 1 << 1,
     81     INCLUDE_DOT_DOT       = 1 << 2,
     82 #if defined(OS_POSIX)
     83     SHOW_SYM_LINKS        = 1 << 4,
     84 #endif
     85   };
     86 
     87   // |root_path| is the starting directory to search for. It may or may not end
     88   // in a slash.
     89   //
     90   // If |recursive| is true, this will enumerate all matches in any
     91   // subdirectories matched as well. It does a breadth-first search, so all
     92   // files in one directory will be returned before any files in a
     93   // subdirectory.
     94   //
     95   // |file_type|, a bit mask of FileType, specifies whether the enumerator
     96   // should match files, directories, or both.
     97   //
     98   // |pattern| is an optional pattern for which files to match. This
     99   // works like shell globbing. For example, "*.txt" or "Foo???.doc".
    100   // However, be careful in specifying patterns that aren't cross platform
    101   // since the underlying code uses OS-specific matching routines.  In general,
    102   // Windows matching is less featureful than others, so test there first.
    103   // If unspecified, this will match all files.
    104   // NOTE: the pattern only matches the contents of root_path, not files in
    105   // recursive subdirectories.
    106   // TODO(erikkay): Fix the pattern matching to work at all levels.
    107   FileEnumerator(const FilePath& root_path,
    108                  bool recursive,
    109                  int file_type);
    110   FileEnumerator(const FilePath& root_path,
    111                  bool recursive,
    112                  int file_type,
    113                  const FilePath::StringType& pattern);
    114   ~FileEnumerator();
    115 
    116   // Returns the next file or an empty string if there are no more results.
    117   //
    118   // The returned path will incorporate the |root_path| passed in the
    119   // constructor: "<root_path>/file_name.txt". If the |root_path| is absolute,
    120   // then so will be the result of Next().
    121   FilePath Next();
    122 
    123   // Write the file info into |info|.
    124   FileInfo GetInfo() const;
    125 
    126  private:
    127   // Returns true if the given path should be skipped in enumeration.
    128   bool ShouldSkip(const FilePath& path);
    129 
    130 #if defined(OS_WIN)
    131   // True when find_data_ is valid.
    132   bool has_find_data_;
    133   WIN32_FIND_DATA find_data_;
    134   HANDLE find_handle_;
    135 #elif defined(OS_POSIX)
    136 
    137   // Read the filenames in source into the vector of DirectoryEntryInfo's
    138   static bool ReadDirectory(std::vector<FileInfo>* entries,
    139                             const FilePath& source, bool show_links);
    140 
    141   // The files in the current directory
    142   std::vector<FileInfo> directory_entries_;
    143 
    144   // The next entry to use from the directory_entries_ vector
    145   size_t current_directory_entry_;
    146 #endif
    147 
    148   FilePath root_path_;
    149   bool recursive_;
    150   int file_type_;
    151   FilePath::StringType pattern_;  // Empty when we want to find everything.
    152 
    153   // A stack that keeps track of which subdirectories we still need to
    154   // enumerate in the breadth-first search.
    155   std::stack<FilePath> pending_paths_;
    156 
    157   DISALLOW_COPY_AND_ASSIGN(FileEnumerator);
    158 };
    159 
    160 }  // namespace base
    161 
    162 #endif  // BASE_FILES_FILE_ENUMERATOR_H_
    163