Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(113)

Side by Side Diff: base/files/file_enumerator_posix.cc

Issue 13247008: base: Extract FileEnumerator out of file_util.h (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: file_enumerator_posix.cc should not compile on win Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « base/files/file_enumerator.cc ('k') | base/files/file_enumerator_win.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2013 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 #include "base/files/file_enumerator.h"
6
7 #include <dirent.h>
8 #include <errno.h>
9 #include <fnmatch.h>
10
11 #include "base/logging.h"
12 #include "base/threading/thread_restrictions.h"
13 #include "base/time.h"
14
15 using base::FilePath;
16 using base::Time;
17
18 namespace file_util {
19
20 FileEnumerator::FileEnumerator(const FilePath& root_path,
21 bool recursive,
22 int file_type)
23 : current_directory_entry_(0),
24 root_path_(root_path),
25 recursive_(recursive),
26 file_type_(file_type) {
27 // INCLUDE_DOT_DOT must not be specified if recursive.
28 DCHECK(!(recursive && (INCLUDE_DOT_DOT & file_type_)));
29 pending_paths_.push(root_path);
30 }
31
32 FileEnumerator::FileEnumerator(const FilePath& root_path,
33 bool recursive,
34 int file_type,
35 const FilePath::StringType& pattern)
36 : current_directory_entry_(0),
37 root_path_(root_path),
38 recursive_(recursive),
39 file_type_(file_type),
40 pattern_(root_path.Append(pattern).value()) {
41 // INCLUDE_DOT_DOT must not be specified if recursive.
42 DCHECK(!(recursive && (INCLUDE_DOT_DOT & file_type_)));
43 // The Windows version of this code appends the pattern to the root_path,
44 // potentially only matching against items in the top-most directory.
45 // Do the same here.
46 if (pattern.empty())
47 pattern_ = FilePath::StringType();
48 pending_paths_.push(root_path);
49 }
50
51 FileEnumerator::~FileEnumerator() {
52 }
53
54 FilePath FileEnumerator::Next() {
55 ++current_directory_entry_;
56
57 // While we've exhausted the entries in the current directory, do the next
58 while (current_directory_entry_ >= directory_entries_.size()) {
59 if (pending_paths_.empty())
60 return FilePath();
61
62 root_path_ = pending_paths_.top();
63 root_path_ = root_path_.StripTrailingSeparators();
64 pending_paths_.pop();
65
66 std::vector<DirectoryEntryInfo> entries;
67 if (!ReadDirectory(&entries, root_path_, file_type_ & SHOW_SYM_LINKS))
68 continue;
69
70 directory_entries_.clear();
71 current_directory_entry_ = 0;
72 for (std::vector<DirectoryEntryInfo>::const_iterator
73 i = entries.begin(); i != entries.end(); ++i) {
74 FilePath full_path = root_path_.Append(i->filename);
75 if (ShouldSkip(full_path))
76 continue;
77
78 if (pattern_.size() &&
79 fnmatch(pattern_.c_str(), full_path.value().c_str(), FNM_NOESCAPE))
80 continue;
81
82 if (recursive_ && S_ISDIR(i->stat.st_mode))
83 pending_paths_.push(full_path);
84
85 if ((S_ISDIR(i->stat.st_mode) && (file_type_ & DIRECTORIES)) ||
86 (!S_ISDIR(i->stat.st_mode) && (file_type_ & FILES)))
87 directory_entries_.push_back(*i);
88 }
89 }
90
91 return root_path_.Append(directory_entries_[current_directory_entry_
92 ].filename);
93 }
94
95 void FileEnumerator::GetFindInfo(FindInfo* info) {
96 DCHECK(info);
97
98 if (current_directory_entry_ >= directory_entries_.size())
99 return;
100
101 DirectoryEntryInfo* cur_entry = &directory_entries_[current_directory_entry_];
102 memcpy(&(info->stat), &(cur_entry->stat), sizeof(info->stat));
103 info->filename.assign(cur_entry->filename.value());
104 }
105
106 // static
107 bool FileEnumerator::IsDirectory(const FindInfo& info) {
108 return S_ISDIR(info.stat.st_mode);
109 }
110
111 // static
112 FilePath FileEnumerator::GetFilename(const FindInfo& find_info) {
113 return FilePath(find_info.filename);
114 }
115
116 // static
117 int64 FileEnumerator::GetFilesize(const FindInfo& find_info) {
118 return find_info.stat.st_size;
119 }
120
121 // static
122 Time FileEnumerator::GetLastModifiedTime(const FindInfo& find_info) {
123 return Time::FromTimeT(find_info.stat.st_mtime);
124 }
125
126 bool FileEnumerator::ReadDirectory(std::vector<DirectoryEntryInfo>* entries,
127 const FilePath& source, bool show_links) {
128 base::ThreadRestrictions::AssertIOAllowed();
129 DIR* dir = opendir(source.value().c_str());
130 if (!dir)
131 return false;
132
133 struct dirent dent_buf;
134 struct dirent* dent;
135 while (readdir_r(dir, &dent_buf, &dent) == 0 && dent) {
136 DirectoryEntryInfo info;
137 info.filename = FilePath(dent->d_name);
138
139 FilePath full_name = source.Append(dent->d_name);
140 int ret;
141 if (show_links)
142 ret = lstat(full_name.value().c_str(), &info.stat);
143 else
144 ret = stat(full_name.value().c_str(), &info.stat);
145 if (ret < 0) {
146 // Print the stat() error message unless it was ENOENT and we're
147 // following symlinks.
148 if (!(errno == ENOENT && !show_links)) {
149 DPLOG(ERROR) << "Couldn't stat "
150 << source.Append(dent->d_name).value();
151 }
152 memset(&info.stat, 0, sizeof(info.stat));
153 }
154 entries->push_back(info);
155 }
156
157 closedir(dir);
158 return true;
159 }
160
161 } // namespace file_util
OLDNEW
« no previous file with comments | « base/files/file_enumerator.cc ('k') | base/files/file_enumerator_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698