From 64dc75786d12cc4df005de50add12e36503f579a Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Fri, 23 Sep 2016 21:56:19 -0700 Subject: [PATCH] Detect nonstandard or missing nanosecond-precision stat timestamps Reported-by: maarten-k --- programs/detect.sh | 32 ++++++++++++++++++++++++++++++-- programs/gzip.c | 8 ++++---- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/programs/detect.sh b/programs/detect.sh index 7e310a0..5f811b4 100755 --- a/programs/detect.sh +++ b/programs/detect.sh @@ -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 + #include + 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 */" diff --git a/programs/gzip.c b/programs/gzip.c index 00b2a00..61acaf3 100644 --- a/programs/gzip.c +++ b/programs/gzip.c @@ -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, ×); -#endif /* !HAVE_FUTIMES */ +#endif if (ret != 0) msg_errno("%"TS": unable to preserve timestamps", out->name); }