Centralize stat calls to ensure consistency of time fields on windows
This commit is contained in:
@@ -21,7 +21,6 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <fnmatch.h>
|
||||
#include "safesysstat.h"
|
||||
@@ -226,7 +225,7 @@ FsTreeWalker::Status FsTreeWalker::walk(const string& _top,
|
||||
data->basedepth = slashcount(top); // Only used for breadthxx
|
||||
struct stat st;
|
||||
// We always follow symlinks at this point. Makes more sense.
|
||||
if (stat(top.c_str(), &st) == -1) {
|
||||
if (path_fileprops(top, &st) == -1) {
|
||||
// Note that we do not return an error if the stat call
|
||||
// fails. A temp file may have gone away.
|
||||
data->logsyserr("stat", top);
|
||||
@@ -288,7 +287,7 @@ FsTreeWalker::Status FsTreeWalker::walk(const string& _top,
|
||||
|
||||
// If changing parent directory, advise our user.
|
||||
if (!nfather.empty()) {
|
||||
if (stat(nfather.c_str(), &st) == -1) {
|
||||
if (path_fileprops(nfather, &st) == -1) {
|
||||
data->logsyserr("stat", nfather);
|
||||
return errno == ENOENT ? FtwOk : FtwError;
|
||||
}
|
||||
@@ -298,7 +297,7 @@ FsTreeWalker::Status FsTreeWalker::walk(const string& _top,
|
||||
}
|
||||
}
|
||||
|
||||
if (stat(dir.c_str(), &st) == -1) {
|
||||
if (path_fileprops(dir, &st) == -1) {
|
||||
data->logsyserr("stat", dir);
|
||||
return errno == ENOENT ? FtwOk : FtwError;
|
||||
}
|
||||
@@ -397,7 +396,8 @@ 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
|
||||
// readdir gets the useful attrs, no inode indirection on windows,
|
||||
// spare the path_fileprops() call, but make sure we mimick it.
|
||||
memset(&st, 0, sizeof(st));
|
||||
st.st_mtime = ent->d_mtime;
|
||||
st.st_size = ent->d_size;
|
||||
@@ -407,8 +407,7 @@ FsTreeWalker::Status FsTreeWalker::iwalk(const string &top,
|
||||
// anyway.
|
||||
st.st_ctime = st.st_mtime;
|
||||
#else
|
||||
int statret = (data->options & FtwFollow) ? stat(fn.c_str(), &st) :
|
||||
lstat(fn.c_str(), &st);
|
||||
int statret = path_fileprops(fn.c_str(), &st, data->options&FtwFollow);
|
||||
if (statret == -1) {
|
||||
data->logsyserr("stat", fn);
|
||||
continue;
|
||||
|
||||
@@ -710,6 +710,28 @@ long long path_filesize(const string& path)
|
||||
return (long long)st.st_size;
|
||||
}
|
||||
|
||||
int path_fileprops(const std::string path, struct stat *stp, bool follow)
|
||||
{
|
||||
if (!stp)
|
||||
return -1;
|
||||
memset(stp, 0, sizeof(struct stat));
|
||||
struct stat mst;
|
||||
int ret = follow ? stat(path.c_str(), &mst) : lstat(path.c_str(), &mst);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
stp->st_size = mst.st_size;
|
||||
stp->st_mode = mst.st_mode;
|
||||
stp->st_mtime = mst.st_mtime;
|
||||
#ifdef _WIN32
|
||||
stp->st_ctime = mst.st_mtime;
|
||||
#else
|
||||
stp->st_ino = mst.st_ino;
|
||||
stp->st_dev = mst.st_dev;
|
||||
stp->st_ctime = mst.st_ctime;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool path_exists(const string& path)
|
||||
{
|
||||
return access(path.c_str(), 0) == 0;
|
||||
|
||||
@@ -79,6 +79,17 @@ extern bool path_isdir(const std::string& path);
|
||||
/// Retrieve file size
|
||||
extern long long path_filesize(const std::string& path);
|
||||
|
||||
/// Retrieve essential file attributes. This is used rather than a
|
||||
/// bare stat() to ensure consistent use of the time fields (on
|
||||
/// windows, we set ctime=mtime as ctime is actually the creation
|
||||
/// time, for which we have no use).
|
||||
/// Only st_mtime, st_ctime, st_size, st_mode (file type bits) are set on
|
||||
/// all systems. st_dev and st_ino are set for special posix usage.
|
||||
/// The rest is zeroed.
|
||||
struct stat;
|
||||
extern int path_fileprops(const std::string path, struct stat *stp,
|
||||
bool follow = true);
|
||||
|
||||
/// Check that path is traversable and last element exists
|
||||
/// Returns true if last elt could be checked to exist. False may mean that
|
||||
/// the file/dir does not exist or that an error occurred.
|
||||
|
||||
Reference in New Issue
Block a user