diff -Nur zstd-1.5.0/programs/fileio.c new-zstd-1.5.0/programs/fileio.c --- zstd-1.5.0/programs/fileio.c 2021-05-14 22:59:34.000000000 +0800 +++ new-zstd-1.5.0/programs/fileio.c 2021-10-25 10:30:36.546222652 +0800 @@ -1638,6 +1638,7 @@ int closeDstFile = 0; int result; stat_t statbuf; + int transferMTime = 0; assert(ress.srcFile != NULL); if (ress.dstFile == NULL) { int dstFilePermissions = DEFAULT_FILE_PERMISSIONS; @@ -1645,6 +1646,7 @@ && UTIL_stat(srcFileName, &statbuf) && UTIL_isRegularFileStat(&statbuf) ) { dstFilePermissions = statbuf.st_mode; + transferMTime = 1; } closeDstFile = 1; @@ -1671,6 +1673,12 @@ DISPLAYLEVEL(1, "zstd: %s: %s \n", dstFileName, strerror(errno)); result=1; } + + if (transferMTime) { + UTIL_utime(dstFileName, &statbuf); + } + + if ( (result != 0) /* operation failure */ && strcmp(dstFileName, stdoutmark) /* special case : don't remove() stdout */ ) { @@ -2537,6 +2545,7 @@ int result; stat_t statbuf; int releaseDstFile = 0; + int transferMTime = 0; if ((ress.dstFile == NULL) && (prefs->testMode==0)) { int dstFilePermissions = DEFAULT_FILE_PERMISSIONS; @@ -2544,6 +2553,7 @@ && UTIL_stat(srcFileName, &statbuf) && UTIL_isRegularFileStat(&statbuf) ) { dstFilePermissions = statbuf.st_mode; + transferMTime = 1; } releaseDstFile = 1; @@ -2568,7 +2578,9 @@ DISPLAYLEVEL(1, "zstd: %s: %s \n", dstFileName, strerror(errno)); result = 1; } - + if (transferMTime) { + UTIL_utime(dstFileName, &statbuf); + } if ( (result != 0) /* operation failure */ && strcmp(dstFileName, stdoutmark) /* special case : don't remove() stdout */ ) { diff -Nur zstd-1.5.0/programs/util.c new-zstd-1.5.0/programs/util.c --- zstd-1.5.0/programs/util.c 2021-05-14 22:59:34.000000000 +0800 +++ new-zstd-1.5.0/programs/util.c 2021-10-25 10:30:43.246350653 +0800 @@ -31,6 +31,7 @@ # if PLATFORM_POSIX_VERSION < 200809L || !defined(st_mtime) # include /* utime */ # else +# include # include /* AT_FDCWD */ # include /* utimensat */ # endif @@ -159,6 +160,31 @@ return chmod(filename, permissions); } +/*set access and modification times */ +int UTIL_utime(const char* filename, const stat_t *statbuf) +{ + int ret; + /* We check that st_mtime is a macro here in order to give us confidence + * that struct stat has a struct timespec st_mtim member. We need this + * check because there are some platforms that claim to be POSIX 2008 + * compliant but which do not have st_mtim... + * */ +#if (PLATFORM_POSIX_VERSION >= 200809L) && defined(st_time) + /* (atime, mtime)*/ + struct timespec timebuf[2] = { {0, UTIME_NOW} }; + timebuf[1] = statbuf->st_mtim; + ret = utimensat(AT_FDCWD, filename, timebuf, 0); +#else + struct utimbuf timebuf; + timebuf.actime = time(NULL); + timebuf.modtime = statbuf->st_mtime; + ret = utime(filename, &timebuf); +#endif + errno = 0; + return ret; +} + + int UTIL_setFileStat(const char *filename, const stat_t *statbuf) { int res = 0; @@ -168,25 +194,7 @@ return -1; /* set access and modification times */ - /* We check that st_mtime is a macro here in order to give us confidence - * that struct stat has a struct timespec st_mtim member. We need this - * check because there are some platforms that claim to be POSIX 2008 - * compliant but which do not have st_mtim... */ -#if (PLATFORM_POSIX_VERSION >= 200809L) && defined(st_mtime) - { - /* (atime, mtime) */ - struct timespec timebuf[2] = { {0, UTIME_NOW} }; - timebuf[1] = statbuf->st_mtim; - res += utimensat(AT_FDCWD, filename, timebuf, 0); - } -#else - { - struct utimbuf timebuf; - timebuf.actime = time(NULL); - timebuf.modtime = statbuf->st_mtime; - res += utime(filename, &timebuf); - } -#endif + res += UTIL_utime(filename, statbuf); #if !defined(_WIN32) res += chown(filename, statbuf->st_uid, statbuf->st_gid); /* Copy ownership */ diff -Nur zstd-1.5.0/programs/util.h new-zstd-1.5.0/programs/util.h --- zstd-1.5.0/programs/util.h 2021-05-14 22:59:34.000000000 +0800 +++ new-zstd-1.5.0/programs/util.h 2021-10-25 10:30:43.246350653 +0800 @@ -135,6 +135,16 @@ */ int UTIL_setFileStat(const char* filename, const stat_t* statbuf); +/** + * Set atime to now and mtime to the st_mtim in statbuf. + * + * Directly wraps utime() or utimensat(). Returns -1 on error. + * Does not validate filename is valid. + * */ +int UTIL_utime(const char* filename, const stat_t *statbuf); + + + /* * These helpers operate on a pre-populated stat_t, i.e., the result of * calling one of the above functions.