Detect nonstandard or missing nanosecond-precision stat timestamps

Reported-by: maarten-k <maarten.kooyman@surfsara.nl>
This commit is contained in:
Eric Biggers 2016-09-23 21:56:19 -07:00
parent 76dcdec6f0
commit 64dc75786d
2 changed files with 34 additions and 6 deletions

View File

@ -11,24 +11,52 @@ echo "#define CONFIG_H"
tmpfile="$(mktemp -t libdeflate_config.XXXXXXXX)"
trap "rm -f \"$tmpfile\"" EXIT
program_compiles() {
echo "$1" > "$tmpfile"
$CC $PROG_CFLAGS -x c "$tmpfile" -o /dev/null > /dev/null 2>&1
}
check_function() {
funcname="$1"
macro="HAVE_$(echo $funcname | tr a-z A-Z)"
echo "int main() { $funcname(); }" > "$tmpfile"
echo
echo "/* Is the $funcname() function available? */"
if $CC $CFLAGS -x c $tmpfile -o /dev/null > /dev/null 2>&1; then
if program_compiles "int main() { $funcname(); }"; then
echo "#define $macro 1"
else
echo "/* $macro is not set */"
fi
}
have_stat_field() {
program_compiles "#include <sys/types.h>
#include <sys/stat.h>
int main() { struct stat st; st.$1; }"
}
check_stat_nanosecond_precision() {
echo
echo "/* Does stat() provide nanosecond-precision timestamps? */"
if have_stat_field st_atim; then
echo "#define HAVE_STAT_NANOSECOND_PRECISION 1"
elif have_stat_field st_atimespec; then
# Nonstandard field names used by OS X and older BSDs
echo "#define HAVE_STAT_NANOSECOND_PRECISION 1"
echo "#define st_atim st_atimespec"
echo "#define st_mtim st_mtimespec"
echo "#define st_ctim st_ctimespec"
else
echo "/* HAVE_STAT_NANOSECOND_PRECISION is not set */"
fi
}
check_function clock_gettime
check_function futimens
check_function futimes
check_function posix_fadvise
check_function posix_madvise
check_stat_nanosecond_precision
echo
echo "#endif /* CONFIG_H */"

View File

@ -257,23 +257,23 @@ restore_timestamps(struct file_stream *out, const tchar *newpath,
const struct stat *stbuf)
{
int ret;
#if defined(HAVE_FUTIMENS)
#if defined(HAVE_FUTIMENS) && defined(HAVE_STAT_NANOSECOND_PRECISION)
struct timespec times[2] = {
stbuf->st_atim, stbuf->st_mtim,
};
ret = futimens(out->fd, times);
#elif defined(HAVE_FUTIMES)
#elif defined(HAVE_FUTIMES) && defined(HAVE_STAT_NANOSECOND_PRECISION)
struct timeval times[2] = {
{ stbuf->st_atim.tv_sec, stbuf->st_atim.tv_nsec / 1000, },
{ stbuf->st_mtim.tv_sec, stbuf->st_mtim.tv_nsec / 1000, },
};
ret = futimes(out->fd, times);
#else /* HAVE_FUTIMES */
#else
struct tutimbuf times = {
stbuf->st_atime, stbuf->st_mtime,
};
ret = tutime(newpath, &times);
#endif /* !HAVE_FUTIMES */
#endif
if (ret != 0)
msg_errno("%"TS": unable to preserve timestamps", out->name);
}