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 "pathut.h"
|
||||||
#include "fstreewalk.h"
|
#include "fstreewalk.h"
|
||||||
|
|
||||||
#ifndef NO_NAMESPACES
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
#endif /* NO_NAMESPACES */
|
|
||||||
|
|
||||||
bool FsTreeWalker::o_useFnmPathname = true;
|
bool FsTreeWalker::o_useFnmPathname = true;
|
||||||
|
|
||||||
const int FsTreeWalker::FtwTravMask = FtwTravNatural|
|
const int FsTreeWalker::FtwTravMask = FtwTravNatural|
|
||||||
FtwTravBreadth|FtwTravFilesThenDirs|FtwTravBreadthThenDepth;
|
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 {
|
class DirId {
|
||||||
public:
|
public:
|
||||||
dev_t dev;
|
dev_t dev;
|
||||||
|
@ -57,6 +58,7 @@ public:
|
||||||
return dev < r.dev || (dev == r.dev && ino < r.ino);
|
return dev < r.dev || (dev == r.dev && ino < r.ino);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
class FsTreeWalker::Internal {
|
class FsTreeWalker::Internal {
|
||||||
public:
|
public:
|
||||||
|
@ -75,7 +77,9 @@ public:
|
||||||
// of directory paths to be processed, and we do not recurse.
|
// of directory paths to be processed, and we do not recurse.
|
||||||
deque<string> dirs;
|
deque<string> dirs;
|
||||||
int errors;
|
int errors;
|
||||||
|
#ifndef _WIN32
|
||||||
set<DirId> donedirs;
|
set<DirId> donedirs;
|
||||||
|
#endif
|
||||||
void logsyserr(const char *call, const string ¶m)
|
void logsyserr(const char *call, const string ¶m)
|
||||||
{
|
{
|
||||||
errors++;
|
errors++;
|
||||||
|
@ -344,6 +348,7 @@ FsTreeWalker::Status FsTreeWalker::iwalk(const string &top,
|
||||||
// no point in entering again.
|
// no point in entering again.
|
||||||
// For now, we'll ignore the "other kind of cycle" part and only monitor
|
// For now, we'll ignore the "other kind of cycle" part and only monitor
|
||||||
// this is FtwFollow is set
|
// this is FtwFollow is set
|
||||||
|
#ifndef _WIN32
|
||||||
if (data->options & FtwFollow) {
|
if (data->options & FtwFollow) {
|
||||||
DirId dirid(stp->st_dev, stp->st_ino);
|
DirId dirid(stp->st_dev, stp->st_ino);
|
||||||
if (data->donedirs.find(dirid) != data->donedirs.end()) {
|
if (data->donedirs.find(dirid) != data->donedirs.end()) {
|
||||||
|
@ -353,7 +358,8 @@ FsTreeWalker::Status FsTreeWalker::iwalk(const string &top,
|
||||||
}
|
}
|
||||||
data->donedirs.insert(dirid);
|
data->donedirs.insert(dirid);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
DIR *d = opendir(top.c_str());
|
DIR *d = opendir(top.c_str());
|
||||||
if (d == 0) {
|
if (d == 0) {
|
||||||
data->logsyserr("opendir", top);
|
data->logsyserr("opendir", top);
|
||||||
|
@ -390,12 +396,25 @@ FsTreeWalker::Status FsTreeWalker::iwalk(const string &top,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn = path_cat(top, ent->d_name);
|
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) :
|
int statret = (data->options & FtwFollow) ? stat(fn.c_str(), &st) :
|
||||||
lstat(fn.c_str(), &st);
|
lstat(fn.c_str(), &st);
|
||||||
if (statret == -1) {
|
if (statret == -1) {
|
||||||
data->logsyserr("stat", fn);
|
data->logsyserr("stat", fn);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!data->skippedPaths.empty()) {
|
if (!data->skippedPaths.empty()) {
|
||||||
// We do not check the ancestors. This means that you can have
|
// We do not check the ancestors. This means that you can have
|
||||||
// a topdirs member under a skippedPath, to index a portion of
|
// a topdirs member under a skippedPath, to index a portion of
|
||||||
|
|
|
@ -120,6 +120,7 @@ class FsTreeWalker {
|
||||||
class FsTreeWalkerCB {
|
class FsTreeWalkerCB {
|
||||||
public:
|
public:
|
||||||
virtual ~FsTreeWalkerCB() {}
|
virtual ~FsTreeWalkerCB() {}
|
||||||
|
// Only st_mtime, st_ctime, st_size, st_mode (filetype bits: dir/reg/lnk),
|
||||||
virtual FsTreeWalker::Status
|
virtual FsTreeWalker::Status
|
||||||
processone(const string &, const struct stat *, FsTreeWalker::CbFlag)
|
processone(const string &, const struct stat *, FsTreeWalker::CbFlag)
|
||||||
= 0;
|
= 0;
|
||||||
|
|
|
@ -103,7 +103,13 @@ struct dirent *readdir(DIR *dir)
|
||||||
if(!dir->result.d_name || _findnext(dir->handle, &dir->info) != -1)
|
if(!dir->result.d_name || _findnext(dir->handle, &dir->info) != -1)
|
||||||
{
|
{
|
||||||
result = &dir->result;
|
result = &dir->result;
|
||||||
|
result->d_mtime = dir->info.time_write;
|
||||||
|
result->d_size = dir->info.size;
|
||||||
result->d_name = dir->info.name;
|
result->d_name = dir->info.name;
|
||||||
|
if (dir->info.attrib & _A_SUBDIR)
|
||||||
|
result->d_mode = S_IFDIR;
|
||||||
|
else
|
||||||
|
result->d_mode = S_IFREG;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -21,6 +21,12 @@ typedef struct DIR DIR;
|
||||||
struct dirent
|
struct dirent
|
||||||
{
|
{
|
||||||
char *d_name;
|
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 *);
|
DIR *opendir(const char *);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue