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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: src/platform/update_engine/filesystem_iterator.cc
diff --git a/src/platform/update_engine/filesystem_iterator.cc b/src/platform/update_engine/filesystem_iterator.cc
new file mode 100644
index 0000000000000000000000000000000000000000..9d98dea92386a16202abaf308f8363bc7e70f1dc
--- /dev/null
+++ b/src/platform/update_engine/filesystem_iterator.cc
@@ -0,0 +1,147 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "update_engine/filesystem_iterator.h"
+#include <sys/types.h>
+#include <dirent.h>
+#include <errno.h>
+#include <set>
+#include <string>
+#include <vector>
+#include "chromeos/obsolete_logging.h"
+#include "update_engine/utils.h"
+
+using std::set;
+using std::string;
+using std::vector;
+
+namespace chromeos_update_engine {
+
+// We use a macro here for two reasons:
+// 1. We want to be able to return from the caller's function.
+// 2. We can use the #macro_arg ism to get a string of the calling statement,
+// which we can log.
+
+#define RETURN_ERROR_IF_FALSE(_statement) \
+ do { \
+ bool _result = (_statement); \
+ if (!_result) { \
+ string _message = utils::ErrnoNumberAsString(errno); \
+ LOG(INFO) << #_statement << " failed: " << _message << ". Aborting"; \
+ is_end_ = true; \
+ is_err_ = true; \
+ return; \
+ } \
+ } while (0)
+
+FilesystemIterator::FilesystemIterator(
+ const std::string& path,
+ const std::set<std::string>& excl_prefixes)
+ : excl_prefixes_(excl_prefixes),
+ is_end_(false),
+ is_err_(false) {
+ root_path_ = utils::NormalizePath(path, true);
+ RETURN_ERROR_IF_FALSE(lstat(root_path_.c_str(), &stbuf_) == 0);
+ root_dev_ = stbuf_.st_dev;
+}
+
+FilesystemIterator::~FilesystemIterator() {
+ for (vector<DIR*>::iterator it = dirs_.begin(); it != dirs_.end(); ++it) {
+ LOG_IF(ERROR, closedir(*it) != 0) << "closedir failed";
+ }
+}
+
+// Returns full path for current file
+std::string FilesystemIterator::GetFullPath() const {
+ return root_path_ + GetPartialPath();
+}
+
+std::string FilesystemIterator::GetPartialPath() const {
+ std::string ret;
+ for (vector<string>::const_iterator it = names_.begin();
+ it != names_.end(); ++it) {
+ ret += "/";
+ ret += *it;
+ }
+ return ret;
+}
+
+// Increments to the next file
+void FilesystemIterator::Increment() {
+ // If we're currently on a dir, descend into children, but only if
+ // we're on the same device as the root device
+
+ bool entering_dir = false; // true if we're entering into a new dir
+ if (S_ISDIR(stbuf_.st_mode) && (stbuf_.st_dev == root_dev_)) {
+ DIR* dir = opendir(GetFullPath().c_str());
+ if ((!dir) && ((errno == ENOTDIR) || (errno == ENOENT))) {
+ // opendir failed b/c either it's not a dir or it doesn't exist.
+ // that's fine. let's just skip over this.
+ LOG(ERROR) << "Can't descend into " << GetFullPath();
+ } else {
+ RETURN_ERROR_IF_FALSE(dir);
+ entering_dir = true;
+ dirs_.push_back(dir);
+ }
+ }
+
+ if (!entering_dir && names_.empty()) {
+ // root disappeared while we tried to descend into it
+ is_end_ = true;
+ return;
+ }
+
+ if (!entering_dir)
+ names_.pop_back();
+
+ IncrementInternal();
+ for (set<string>::const_iterator it = excl_prefixes_.begin();
+ it != excl_prefixes_.end(); ++it) {
+ if (utils::StringHasPrefix(GetPartialPath(), *it)) {
+ Increment();
+ break;
+ }
+ }
+ return;
+}
+
+// Assumes that we need to find the next child of dirs_.back(), or if
+// there are none more, go up the chain
+void FilesystemIterator::IncrementInternal() {
+ CHECK_EQ(dirs_.size(), names_.size() + 1);
+ for (;;) {
+ struct dirent dir_entry;
+ struct dirent* dir_entry_pointer;
+ int r;
+ RETURN_ERROR_IF_FALSE(
+ (r = readdir_r(dirs_.back(), &dir_entry, &dir_entry_pointer)) == 0);
+ if (dir_entry_pointer) {
+ // Found an entry
+ names_.push_back(dir_entry_pointer->d_name);
+ // Validate
+ RETURN_ERROR_IF_FALSE(lstat(GetFullPath().c_str(), &stbuf_) == 0);
+ if (strcmp(dir_entry_pointer->d_name, ".") &&
+ strcmp(dir_entry_pointer->d_name, "..")) {
+ // Done
+ return;
+ }
+ // Child didn't work out. Try again
+ names_.pop_back();
+ } else {
+ // No more children in this dir. Pop it and try again
+ RETURN_ERROR_IF_FALSE(closedir(dirs_.back()) == 0);
+ dirs_.pop_back();
+ if (dirs_.empty()) {
+ CHECK(names_.empty());
+ // Done with the entire iteration
+ is_end_ = true;
+ return;
+ }
+ CHECK(!names_.empty());
+ names_.pop_back();
+ }
+ }
+}
+
+} // namespace chromeos_update_engine
« 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