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

Side by Side Diff: src/platform/update_engine/filesystem_iterator.cc

Issue 465067: Missed new files in last commit
Patch Set: Created 11 years 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
OLDNEW
(Empty)
1 // Copyright (c) 2009 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 "update_engine/filesystem_iterator.h"
6 #include <sys/types.h>
7 #include <dirent.h>
8 #include <errno.h>
9 #include <set>
10 #include <string>
11 #include <vector>
12 #include "chromeos/obsolete_logging.h"
13 #include "update_engine/utils.h"
14
15 using std::set;
16 using std::string;
17 using std::vector;
18
19 namespace chromeos_update_engine {
20
21 // We use a macro here for two reasons:
22 // 1. We want to be able to return from the caller's function.
23 // 2. We can use the #macro_arg ism to get a string of the calling statement,
24 // which we can log.
25
26 #define RETURN_ERROR_IF_FALSE(_statement) \
27 do { \
28 bool _result = (_statement); \
29 if (!_result) { \
30 string _message = utils::ErrnoNumberAsString(errno); \
31 LOG(INFO) << #_statement << " failed: " << _message << ". Aborting"; \
32 is_end_ = true; \
33 is_err_ = true; \
34 return; \
35 } \
36 } while (0)
37
38 FilesystemIterator::FilesystemIterator(
39 const std::string& path,
40 const std::set<std::string>& excl_prefixes)
41 : excl_prefixes_(excl_prefixes),
42 is_end_(false),
43 is_err_(false) {
44 root_path_ = utils::NormalizePath(path, true);
45 RETURN_ERROR_IF_FALSE(lstat(root_path_.c_str(), &stbuf_) == 0);
46 root_dev_ = stbuf_.st_dev;
47 }
48
49 FilesystemIterator::~FilesystemIterator() {
50 for (vector<DIR*>::iterator it = dirs_.begin(); it != dirs_.end(); ++it) {
51 LOG_IF(ERROR, closedir(*it) != 0) << "closedir failed";
52 }
53 }
54
55 // Returns full path for current file
56 std::string FilesystemIterator::GetFullPath() const {
57 return root_path_ + GetPartialPath();
58 }
59
60 std::string FilesystemIterator::GetPartialPath() const {
61 std::string ret;
62 for (vector<string>::const_iterator it = names_.begin();
63 it != names_.end(); ++it) {
64 ret += "/";
65 ret += *it;
66 }
67 return ret;
68 }
69
70 // Increments to the next file
71 void FilesystemIterator::Increment() {
72 // If we're currently on a dir, descend into children, but only if
73 // we're on the same device as the root device
74
75 bool entering_dir = false; // true if we're entering into a new dir
76 if (S_ISDIR(stbuf_.st_mode) && (stbuf_.st_dev == root_dev_)) {
77 DIR* dir = opendir(GetFullPath().c_str());
78 if ((!dir) && ((errno == ENOTDIR) || (errno == ENOENT))) {
79 // opendir failed b/c either it's not a dir or it doesn't exist.
80 // that's fine. let's just skip over this.
81 LOG(ERROR) << "Can't descend into " << GetFullPath();
82 } else {
83 RETURN_ERROR_IF_FALSE(dir);
84 entering_dir = true;
85 dirs_.push_back(dir);
86 }
87 }
88
89 if (!entering_dir && names_.empty()) {
90 // root disappeared while we tried to descend into it
91 is_end_ = true;
92 return;
93 }
94
95 if (!entering_dir)
96 names_.pop_back();
97
98 IncrementInternal();
99 for (set<string>::const_iterator it = excl_prefixes_.begin();
100 it != excl_prefixes_.end(); ++it) {
101 if (utils::StringHasPrefix(GetPartialPath(), *it)) {
102 Increment();
103 break;
104 }
105 }
106 return;
107 }
108
109 // Assumes that we need to find the next child of dirs_.back(), or if
110 // there are none more, go up the chain
111 void FilesystemIterator::IncrementInternal() {
112 CHECK_EQ(dirs_.size(), names_.size() + 1);
113 for (;;) {
114 struct dirent dir_entry;
115 struct dirent* dir_entry_pointer;
116 int r;
117 RETURN_ERROR_IF_FALSE(
118 (r = readdir_r(dirs_.back(), &dir_entry, &dir_entry_pointer)) == 0);
119 if (dir_entry_pointer) {
120 // Found an entry
121 names_.push_back(dir_entry_pointer->d_name);
122 // Validate
123 RETURN_ERROR_IF_FALSE(lstat(GetFullPath().c_str(), &stbuf_) == 0);
124 if (strcmp(dir_entry_pointer->d_name, ".") &&
125 strcmp(dir_entry_pointer->d_name, "..")) {
126 // Done
127 return;
128 }
129 // Child didn't work out. Try again
130 names_.pop_back();
131 } else {
132 // No more children in this dir. Pop it and try again
133 RETURN_ERROR_IF_FALSE(closedir(dirs_.back()) == 0);
134 dirs_.pop_back();
135 if (dirs_.empty()) {
136 CHECK(names_.empty());
137 // Done with the entire iteration
138 is_end_ = true;
139 return;
140 }
141 CHECK(!names_.empty());
142 names_.pop_back();
143 }
144 }
145 }
146
147 } // namespace chromeos_update_engine
OLDNEW
« no previous file with comments | « src/platform/update_engine/filesystem_iterator.h ('k') | src/platform/update_engine/filesystem_iterator_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698