Avoid calling stat() after readdir() on Windows as we already have what we want
This commit is contained in:
parent
7f549e5847
commit
97c5ecdcce
4 changed files with 35 additions and 3 deletions
|
@ -38,15 +38,16 @@
|
|||
#include "pathut.h"
|
||||
#include "fstreewalk.h"
|
||||
|
||||
#ifndef NO_NAMESPACES
|
||||
using namespace std;
|
||||
#endif /* NO_NAMESPACES */
|
||||
|
||||
bool FsTreeWalker::o_useFnmPathname = true;
|
||||
|
||||
const int FsTreeWalker::FtwTravMask = FtwTravNatural|
|
||||
FtwTravBreadth|FtwTravFilesThenDirs|FtwTravBreadthThenDepth;
|
||||
|
||||
#ifndef _WIN32
|
||||
// dev/ino means nothing on Windows. It seems that FileId could replace it
|
||||
// but we only use this for cycle detection which we just disable.
|
||||
class DirId {
|
||||
public:
|
||||
dev_t dev;
|
||||
|
@ -57,6 +58,7 @@ public:
|
|||
return dev < r.dev || (dev == r.dev && ino < r.ino);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
class FsTreeWalker::Internal {
|
||||
public:
|
||||
|
@ -75,7 +77,9 @@ public:
|
|||
// of directory paths to be processed, and we do not recurse.
|
||||
deque<string> dirs;
|
||||
int errors;
|
||||
#ifndef _WIN32
|
||||
set<DirId> donedirs;
|
||||
#endif
|
||||
void logsyserr(const char *call, const string ¶m)
|
||||
{
|
||||
errors++;
|
||||
|
@ -344,6 +348,7 @@ FsTreeWalker::Status FsTreeWalker::iwalk(const string &top,
|
|||
// no point in entering again.
|
||||
// For now, we'll ignore the "other kind of cycle" part and only monitor
|
||||
// this is FtwFollow is set
|
||||
#ifndef _WIN32
|
||||
if (data->options & FtwFollow) {
|
||||
DirId dirid(stp->st_dev, stp->st_ino);
|
||||
if (data->donedirs.find(dirid) != data->donedirs.end()) {
|
||||
|
@ -353,6 +358,7 @@ FsTreeWalker::Status FsTreeWalker::iwalk(const string &top,
|
|||
}
|
||||
data->donedirs.insert(dirid);
|
||||
}
|
||||
#endif
|
||||
|
||||
DIR *d = opendir(top.c_str());
|
||||
if (d == 0) {
|
||||
|
@ -390,12 +396,25 @@ FsTreeWalker::Status FsTreeWalker::iwalk(const string &top,
|
|||
}
|
||||
|
||||
fn = path_cat(top, ent->d_name);
|
||||
#ifdef _WIN32
|
||||
// readdir gets the useful attrs, no inode indirection on windows
|
||||
memset(&st, 0, sizeof(st));
|
||||
st.st_mtime = ent->d_mtime;
|
||||
st.st_size = ent->d_size;
|
||||
st.st_mode = ent->d_mode;
|
||||
// ctime is really creation time on Windows. Just use mtime
|
||||
// for all. We only use ctime on Unix to catch xattr changes
|
||||
// anyway.
|
||||
st.st_ctime = st.st_mtime;
|
||||
#else
|
||||
int statret = (data->options & FtwFollow) ? stat(fn.c_str(), &st) :
|
||||
lstat(fn.c_str(), &st);
|
||||
if (statret == -1) {
|
||||
data->logsyserr("stat", fn);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!data->skippedPaths.empty()) {
|
||||
// We do not check the ancestors. This means that you can have
|
||||
// a topdirs member under a skippedPath, to index a portion of
|
||||
|
|
|
@ -120,6 +120,7 @@ class FsTreeWalker {
|
|||
class FsTreeWalkerCB {
|
||||
public:
|
||||
virtual ~FsTreeWalkerCB() {}
|
||||
// Only st_mtime, st_ctime, st_size, st_mode (filetype bits: dir/reg/lnk),
|
||||
virtual FsTreeWalker::Status
|
||||
processone(const string &, const struct stat *, FsTreeWalker::CbFlag)
|
||||
= 0;
|
||||
|
|
|
@ -103,7 +103,13 @@ struct dirent *readdir(DIR *dir)
|
|||
if(!dir->result.d_name || _findnext(dir->handle, &dir->info) != -1)
|
||||
{
|
||||
result = &dir->result;
|
||||
result->d_mtime = dir->info.time_write;
|
||||
result->d_size = dir->info.size;
|
||||
result->d_name = dir->info.name;
|
||||
if (dir->info.attrib & _A_SUBDIR)
|
||||
result->d_mode = S_IFDIR;
|
||||
else
|
||||
result->d_mode = S_IFREG;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -21,6 +21,12 @@ typedef struct DIR DIR;
|
|||
struct dirent
|
||||
{
|
||||
char *d_name;
|
||||
// The native call we use, findfirst/next return file attributes at once,
|
||||
// no need for a separate stat() call in most cases
|
||||
// Note that ctime is actually creation time. No use for posix.
|
||||
time_t d_mtime;
|
||||
off_t d_size;
|
||||
int d_mode; // S_IFREG or S_IFDIR only
|
||||
};
|
||||
|
||||
DIR *opendir(const char *);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue