Copy ns time stat
diff --git a/c/tools/brotli.c b/c/tools/brotli.c index 80ead72..bd2fe93 100644 --- a/c/tools/brotli.c +++ b/c/tools/brotli.c
@@ -26,11 +26,7 @@ #include "../common/constants.h" #include "../common/version.h" -#if !defined(_WIN32) -#include <unistd.h> -#include <utime.h> -#define MAKE_BINARY(FILENO) (FILENO) -#else +#if defined(_WIN32) #include <io.h> #include <share.h> #include <sys/utime.h> @@ -72,7 +68,23 @@ _sopen_s(&result, filename, oflag | O_BINARY, _SH_DENYNO, pmode); return result; } -#endif /* WIN32 */ +#else /* !defined(_WIN32) */ +#include <unistd.h> +#include <utime.h> +#define MAKE_BINARY(FILENO) (FILENO) +#endif /* defined(_WIN32) */ + +#if defined(__APPLE__) && !defined(_POSIX_C_SOURCE) +#define HAVE_UTIMENSAT 1 +#define ATIME_NSEC(S) ((S)->st_atimespec.tv_nsec) +#define MTIME_NSEC(S) ((S)->st_mtimespec.tv_nsec) +#elif defined(_WIN32) && !defined(__MINGW32__) +#define HAVE_UTIMENSAT 0 +#else +#define HAVE_UTIMENSAT 1 +#define ATIME_NSEC(S) ((S)->st_atim.tv_nsec) +#define MTIME_NSEC(S) ((S)->st_mtim.tv_nsec) +#endif typedef enum { COMMAND_COMPRESS, @@ -664,12 +676,27 @@ return retval; } +static int CopyTimeStat(const struct stat* statbuf, const char* output_path) { +#if HAVE_UTIMENSAT + struct timespec times[2]; + times[0].tv_sec = statbuf->st_atime; + times[0].tv_nsec = ATIME_NSEC(statbuf); + times[1].tv_sec = statbuf->st_mtime; + times[1].tv_nsec = MTIME_NSEC(statbuf); + return utimensat(AT_FDCWD, output_path, times, AT_SYMLINK_NOFOLLOW); +#else + struct utimbuf times; + times.actime = statbuf->st_atime; + times.modtime = statbuf->st_mtime; + return utime(output_path, ×); +#endif +} + /* Copy file times and permissions. TODO(eustas): this is a "best effort" implementation; honest cross-platform fully featured implementation is way too hacky; add more hacks by request. */ static void CopyStat(const char* input_path, const char* output_path) { struct stat statbuf; - struct utimbuf times; int res; if (input_path == 0 || output_path == 0) { return; @@ -677,9 +704,7 @@ if (stat(input_path, &statbuf) != 0) { return; } - times.actime = statbuf.st_atime; - times.modtime = statbuf.st_mtime; - utime(output_path, ×); + res = CopyTimeStat(&statbuf, output_path); res = chmod(output_path, statbuf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO)); if (res != 0) { fprintf(stderr, "setting access bits failed for [%s]: %s\n",