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 a1d4659d5b
commit fad8f5151b
9 changed files with 52 additions and 18 deletions

View file

@ -342,7 +342,7 @@ bool BeagleQueueIndexer::indexFiles(list<string>& files)
it++; continue;
}
struct stat st;
if (lstat(it->c_str(), &st) != 0) {
if (path_fileprops(*it, &st) != 0) {
LOGERR(("BeagleQueueIndexer::indexfiles: cant stat [%s]\n",
it->c_str()));
it++; continue;

View file

@ -21,11 +21,11 @@
#include "debuglog.h"
#include "cstr.h"
#include "fetcher.h"
#include "fsfetcher.h"
#include "fsindexer.h"
#include "debuglog.h"
#include "pathut.h"
using std::string;
@ -43,7 +43,7 @@ static bool urltopath(RclConfig* cnf,
bool follow = false;
cnf->getConfParam("followLinks", &follow);
if ((follow ? stat(fn.c_str(), &st) : lstat(fn.c_str(), &st))< 0) {
if (path_fileprops(fn, &st, follow) < 0) {
LOGERR(("FSDocFetcher::fetch: stat errno %d for [%s]\n",
errno, fn.c_str()));
return false;

View file

@ -362,10 +362,9 @@ bool FsIndexer::indexFiles(list<string>& files, int flags)
}
struct stat stb;
int ststat = follow ? stat(it->c_str(), &stb) :
lstat(it->c_str(), &stb);
int ststat = path_fileprops(*it, &stb, follow);
if (ststat != 0) {
LOGERR(("FsIndexer::indexFiles: lstat(%s): %s", it->c_str(),
LOGERR(("FsIndexer::indexFiles: (l)stat %s: %s", it->c_str(),
strerror(errno)));
it++;
continue;

View file

@ -195,7 +195,7 @@ void FileInterner::init(const string &f, const struct stat *stp, RclConfig *cnf,
m_fn = m_tfile;
// Stat the uncompressed file, mainly to get the size
struct stat ucstat;
if (stat(m_fn.c_str(), &ucstat) != 0) {
if (path_fileprops(m_fn, &ucstat) != 0) {
LOGERR(("FileInterner: can't stat the uncompressed file"
"[%s] errno %d\n", m_fn.c_str(), errno));
return;
@ -1042,7 +1042,7 @@ bool FileInterner::isCompressed(const string& fn, RclConfig *cnf)
{
LOGDEB(("FileInterner::isCompressed: [%s]\n", fn.c_str()));
struct stat st;
if (stat(fn.c_str(), &st) < 0) {
if (path_fileprops(fn, &st) < 0) {
LOGERR(("FileInterner::isCompressed: can't stat [%s]\n", fn.c_str()));
return false;
}
@ -1066,7 +1066,7 @@ bool FileInterner::maybeUncompressToTemp(TempFile& temp, const string& fn,
{
LOGDEB(("FileInterner::maybeUncompressToTemp: [%s]\n", fn.c_str()));
struct stat st;
if (stat(fn.c_str(), &st) < 0) {
if (path_fileprops(fn.c_str(), &st) < 0) {
LOGERR(("FileInterner::maybeUncompressToTemp: can't stat [%s]\n",
fn.c_str()));
return false;

View file

@ -20,7 +20,6 @@
#include <errno.h>
#include "safefcntl.h"
#include <sys/types.h>
#include "safesysstat.h"
#include "safeunistd.h"
#include <iostream>
@ -56,7 +55,7 @@ bool MimeHandlerText::set_document_file(const string& mt, const string &fn)
// file size for oversize check
long long fsize = path_filesize(m_fn);
if (fsize < 0) {
LOGERR(("MimeHandlerText::set_document_file: stat(%s) errno %d\n",
LOGERR(("MimeHandlerText::set_document_file: stat %s errno %d\n",
m_fn.c_str(), errno));
return false;
}

View file

@ -553,6 +553,9 @@ void UIPrefsDialog::delExtraDbPB_clicked()
static bool samedir(const string& dir1, const string& dir2)
{
#ifdef _WIN32
return !dir1.compare(dir2);
#else
struct stat st1, st2;
if (stat(dir1.c_str(), &st1))
return false;
@ -562,6 +565,7 @@ static bool samedir(const string& dir1, const string& dir2)
return true;
}
return false;
#endif
}
void UIPrefsDialog::on_showTrayIconCB_clicked()

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;

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;

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.