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