|
a/src/utils/fstreewalk.cpp |
|
b/src/utils/fstreewalk.cpp |
|
... |
|
... |
26 |
#include <fnmatch.h>
|
26 |
#include <fnmatch.h>
|
27 |
#include <cstring>
|
27 |
#include <cstring>
|
28 |
#include <algorithm>
|
28 |
#include <algorithm>
|
29 |
|
29 |
|
30 |
#include <sstream>
|
30 |
#include <sstream>
|
31 |
#include <list>
|
31 |
#include <vector>
|
|
|
32 |
#include <deque>
|
32 |
#include <set>
|
33 |
#include <set>
|
33 |
|
34 |
|
34 |
#include "cstr.h"
|
35 |
#include "cstr.h"
|
35 |
#include "debuglog.h"
|
36 |
#include "debuglog.h"
|
36 |
#include "pathut.h"
|
37 |
#include "pathut.h"
|
|
... |
|
... |
58 |
|
59 |
|
59 |
class FsTreeWalker::Internal {
|
60 |
class FsTreeWalker::Internal {
|
60 |
int options;
|
61 |
int options;
|
61 |
int depthswitch;
|
62 |
int depthswitch;
|
62 |
stringstream reason;
|
63 |
stringstream reason;
|
63 |
list<string> skippedNames;
|
64 |
vector<string> skippedNames;
|
64 |
list<string> skippedPaths;
|
65 |
vector<string> skippedPaths;
|
65 |
// When doing Breadth or FilesThenDirs traversal, we keep a list
|
66 |
// When doing Breadth or FilesThenDirs traversal, we keep a list
|
66 |
// of directory paths to be processed, and we do not recurse.
|
67 |
// of directory paths to be processed, and we do not recurse.
|
67 |
list<string> dirs;
|
68 |
deque<string> dirs;
|
68 |
int errors;
|
69 |
int errors;
|
69 |
set<DirId> donedirs;
|
70 |
set<DirId> donedirs;
|
70 |
void logsyserr(const char *call, const string ¶m)
|
71 |
void logsyserr(const char *call, const string ¶m)
|
71 |
{
|
72 |
{
|
72 |
errors++;
|
73 |
errors++;
|
|
... |
|
... |
117 |
if (find(data->skippedNames.begin(),
|
118 |
if (find(data->skippedNames.begin(),
|
118 |
data->skippedNames.end(), pattern) == data->skippedNames.end())
|
119 |
data->skippedNames.end(), pattern) == data->skippedNames.end())
|
119 |
data->skippedNames.push_back(pattern);
|
120 |
data->skippedNames.push_back(pattern);
|
120 |
return true;
|
121 |
return true;
|
121 |
}
|
122 |
}
|
122 |
bool FsTreeWalker::setSkippedNames(const list<string> &patterns)
|
123 |
bool FsTreeWalker::setSkippedNames(const vector<string> &patterns)
|
123 |
{
|
124 |
{
|
124 |
data->skippedNames = patterns;
|
125 |
data->skippedNames = patterns;
|
125 |
return true;
|
126 |
return true;
|
126 |
}
|
127 |
}
|
127 |
bool FsTreeWalker::inSkippedNames(const string& name)
|
128 |
bool FsTreeWalker::inSkippedNames(const string& name)
|
128 |
{
|
129 |
{
|
129 |
list<string>::const_iterator it;
|
130 |
for (vector<string>::const_iterator it = data->skippedNames.begin();
|
130 |
for (it = data->skippedNames.begin();
|
|
|
131 |
it != data->skippedNames.end(); it++) {
|
131 |
it != data->skippedNames.end(); it++) {
|
132 |
if (fnmatch(it->c_str(), name.c_str(), 0) == 0) {
|
132 |
if (fnmatch(it->c_str(), name.c_str(), 0) == 0) {
|
133 |
return true;
|
133 |
return true;
|
134 |
}
|
134 |
}
|
135 |
}
|
135 |
}
|
|
... |
|
... |
142 |
if (find(data->skippedPaths.begin(),
|
142 |
if (find(data->skippedPaths.begin(),
|
143 |
data->skippedPaths.end(), path) == data->skippedPaths.end())
|
143 |
data->skippedPaths.end(), path) == data->skippedPaths.end())
|
144 |
data->skippedPaths.push_back(path);
|
144 |
data->skippedPaths.push_back(path);
|
145 |
return true;
|
145 |
return true;
|
146 |
}
|
146 |
}
|
147 |
bool FsTreeWalker::setSkippedPaths(const list<string> &paths)
|
147 |
bool FsTreeWalker::setSkippedPaths(const vector<string> &paths)
|
148 |
{
|
148 |
{
|
149 |
data->skippedPaths = paths;
|
149 |
data->skippedPaths = paths;
|
150 |
for (list<string>::iterator it = data->skippedPaths.begin();
|
150 |
for (vector<string>::iterator it = data->skippedPaths.begin();
|
151 |
it != data->skippedPaths.end(); it++)
|
151 |
it != data->skippedPaths.end(); it++)
|
152 |
if (!(data->options & FtwNoCanon))
|
152 |
if (!(data->options & FtwNoCanon))
|
153 |
*it = path_canon(*it);
|
153 |
*it = path_canon(*it);
|
154 |
return true;
|
154 |
return true;
|
155 |
}
|
155 |
}
|
|
... |
|
... |
158 |
int fnmflags = o_useFnmPathname ? FNM_PATHNAME : 0;
|
158 |
int fnmflags = o_useFnmPathname ? FNM_PATHNAME : 0;
|
159 |
#ifdef FNM_LEADING_DIR
|
159 |
#ifdef FNM_LEADING_DIR
|
160 |
if (ckparents)
|
160 |
if (ckparents)
|
161 |
fnmflags |= FNM_LEADING_DIR;
|
161 |
fnmflags |= FNM_LEADING_DIR;
|
162 |
#endif
|
162 |
#endif
|
163 |
list<string>::const_iterator it;
|
163 |
|
164 |
for (it = data->skippedPaths.begin();
|
164 |
for (vector<string>::const_iterator it = data->skippedPaths.begin();
|
165 |
it != data->skippedPaths.end(); it++) {
|
165 |
it != data->skippedPaths.end(); it++) {
|
166 |
#ifndef FNM_LEADING_DIR
|
166 |
#ifndef FNM_LEADING_DIR
|
167 |
if (ckparents) {
|
167 |
if (ckparents) {
|
168 |
string mpath = path;
|
168 |
string mpath = path;
|
169 |
while (mpath.length() > 2) {
|
169 |
while (mpath.length() > 2) {
|
|
... |
|
... |
215 |
if ((data->options & FtwTravMask) == FtwTravNatural) {
|
215 |
if ((data->options & FtwTravMask) == FtwTravNatural) {
|
216 |
return iwalk(top, &st, cb);
|
216 |
return iwalk(top, &st, cb);
|
217 |
}
|
217 |
}
|
218 |
|
218 |
|
219 |
// Breadth first of filesThenDirs semi-depth first order
|
219 |
// Breadth first of filesThenDirs semi-depth first order
|
220 |
// Managing lists of directories to be visited later, in breadth or
|
220 |
// Managing queues of directories to be visited later, in breadth or
|
221 |
// depth order. Null marker are inserted in the list to indicate
|
221 |
// depth order. Null marker are inserted in the queue to indicate
|
222 |
// father directory changes (avoids computing parents all the time).
|
222 |
// father directory changes (avoids computing parents all the time).
|
223 |
data->dirs.push_back(top);
|
223 |
data->dirs.push_back(top);
|
224 |
Status status;
|
224 |
Status status;
|
225 |
while (!data->dirs.empty()) {
|
225 |
while (!data->dirs.empty()) {
|
226 |
string dir, nfather;
|
226 |
string dir, nfather;
|
227 |
if (data->options & (FtwTravBreadth|FtwTravBreadthThenDepth)) {
|
227 |
if (data->options & (FtwTravBreadth|FtwTravBreadthThenDepth)) {
|
228 |
// Breadth first, pop and process an older dir at the
|
228 |
// Breadth first, pop and process an older dir at the
|
229 |
// front of the list. This will add any child dirs at the
|
229 |
// front of the queue. This will add any child dirs at the
|
230 |
// back
|
230 |
// back
|
231 |
dir = data->dirs.front();
|
231 |
dir = data->dirs.front();
|
232 |
data->dirs.pop_front();
|
232 |
data->dirs.pop_front();
|
233 |
if (dir.empty()) {
|
233 |
if (dir.empty()) {
|
234 |
// Father change marker.
|
234 |
// Father change marker.
|
|
... |
|
... |
277 |
if (stat(dir.c_str(), &st) == -1) {
|
277 |
if (stat(dir.c_str(), &st) == -1) {
|
278 |
data->logsyserr("stat", dir);
|
278 |
data->logsyserr("stat", dir);
|
279 |
return errno == ENOENT ? FtwOk : FtwError;
|
279 |
return errno == ENOENT ? FtwOk : FtwError;
|
280 |
}
|
280 |
}
|
281 |
// iwalk will not recurse in this case, just process file entries
|
281 |
// iwalk will not recurse in this case, just process file entries
|
282 |
// and append subdir entries to the list.
|
282 |
// and append subdir entries to the queue.
|
283 |
status = iwalk(dir, &st, cb);
|
283 |
status = iwalk(dir, &st, cb);
|
284 |
if (status != FtwOk)
|
284 |
if (status != FtwOk)
|
285 |
return status;
|
285 |
return status;
|
286 |
}
|
286 |
}
|
287 |
return FtwOk;
|
287 |
return FtwOk;
|
|
... |
|
... |
495 |
exit(1);
|
495 |
exit(1);
|
496 |
}
|
496 |
}
|
497 |
|
497 |
|
498 |
int main(int argc, const char **argv)
|
498 |
int main(int argc, const char **argv)
|
499 |
{
|
499 |
{
|
500 |
list<string> patterns;
|
500 |
vector<string> patterns;
|
501 |
list<string> paths;
|
501 |
vector<string> paths;
|
502 |
thisprog = argv[0];
|
502 |
thisprog = argv[0];
|
503 |
argc--; argv++;
|
503 |
argc--; argv++;
|
504 |
|
504 |
|
505 |
while (argc > 0 && **argv == '-') {
|
505 |
while (argc > 0 && **argv == '-') {
|
506 |
(*argv)++;
|
506 |
(*argv)++;
|