blob: a1ba8af7ebc5d82fbd44edee4eb7ed3c9123b108 [file] [log] [blame]
adlr@google.com3defe6a2009-12-04 20:57:17 +00001// 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#ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_FILESYSTEM_ITERATOR_H__
6#define CHROMEOS_PLATFORM_UPDATE_ENGINE_FILESYSTEM_ITERATOR_H__
7
8// This class is used to walk a filesystem. It will iterate over every file
9// on the same device as the file passed in the ctor. Directories will be
10// visited before their children. Children will be visited in no particular
11// order.
12
13// The iterator is a forward iterator. It's not random access nor can it be
14// decremented.
15
16// Note: If the iterator comes across a mount point where another filesystem
17// is mounted, that mount point will be present, but none of its children
18// will be. Technically the mount point is on the other filesystem (and
19// the Stat() call will verify that), but we return it anyway since:
20// 1. Such a folder must exist in the first filesystem if it got used
21// as a mount point.
22// 2. You probably want to copy if it you're using the iterator to do a
23// filesystem copy
24// 3. If you don't want that, you can just check Stat().st_dev and skip
25// foreign filesystems manually.
26
27#include <sys/stat.h>
28#include <sys/types.h>
29#include <dirent.h>
30#include <unistd.h>
31#include <string>
32#include <set>
33#include <vector>
34
35namespace chromeos_update_engine {
36
37class FilesystemIterator {
38 public:
39 FilesystemIterator(const std::string& path,
40 const std::set<std::string>& excl_prefixes);
41
42 ~FilesystemIterator();
43
44 // Returns stat struct for the current file.
45 struct stat GetStat() const {
46 return stbuf_;
47 }
48
49 // Returns full path for current file.
50 std::string GetFullPath() const;
51
52 // Returns the path that's part of the iterator. For example, if
53 // the object were constructed by passing in "/foo/bar" and Path()
54 // returns "/foo/bar/baz/bat.txt", IterPath would return
55 // "/baz/bat.txt". When this object is on root (ie, the very first
56 // path), IterPath will return "", otherwise the first character of
57 // IterPath will be "/".
58 std::string GetPartialPath() const;
59
60 // Returns name for current file.
61 std::string GetBasename() const {
62 return names_.back();
63 }
64
65 // Increments to the next file.
66 void Increment();
67
68 // If we're at the end. If at the end, do not call Stat(), Path(), etc.,
69 // since this iterator currently isn't pointing to any file at all.
70 bool IsEnd() const {
71 return is_end_;
72 }
73
74 // Returns true if the iterator is in an error state.
75 bool IsErr() const {
76 return is_err_;
77 }
78 private:
79 // Helper for Increment.
80 void IncrementInternal();
81
82 // Returns true if path exists and it's a directory.
83 bool DirectoryExists(const std::string& path);
84
85 // In general (i.e., not midway through a call to Increment()), there is a
86 // relationship between dirs_ and names_: dirs[i] == names_[i - 1].
87 // For example, say we are asked to iterate "/usr/local" and we're currently
88 // at /usr/local/share/dict/words. dirs_ contains DIR* variables for the
89 // dirs at: {"/usr/local", ".../share", ".../dict"} and names_ contains:
90 // {"share", "dict", "words"}. root_path_ contains "/usr/local".
91 // root_dev_ would be the dev for root_path_
92 // (and /usr/local/share/dict/words). stbuf_ would be the stbuf for
93 // /usr/local/share/dict/words.
94
95 // All opened directories. If this is empty, we're currently on the root,
96 // but not descended into the root.
97 // This will always contain the current directory and all it's ancestors
98 // in root-to-leaf order. For more details, see comment above.
99 std::vector<DIR*> dirs_;
100
101 // The list of all filenames for the current path that we've descended into.
102 std::vector<std::string> names_;
103
104 // The device of the root path we've been asked to iterate.
105 dev_t root_dev_;
106
107 // The root path we've been asked to iteratate.
108 std::string root_path_;
109
110 // Exclude items w/ this prefix.
111 std::set<std::string> excl_prefixes_;
112
113 // The struct stat of the current file we're at.
114 struct stat stbuf_;
115
116 // Generally false; set to true when we reach the end of files to iterate
117 // or error occurs.
118 bool is_end_;
119
120 // Generally false; set to true if an error occurrs.
121 bool is_err_;
122};
123
124} // namespace chromeos_update_engine
125
126#endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_FILESYSTEM_ITERATOR_H__