Centralize stat calls to ensure consistency of time fields on windows

This commit is contained in:
Jean-Francois Dockes
2016-01-08 11:23:10 +01:00
parent b2066f6133
commit ff15f8fb1c
9 changed files with 52 additions and 18 deletions
+6 -7
View File
@@ -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;
+22
View File
@@ -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;
+11
View File
@@ -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.