diff --git a/programs/fileio.c b/programs/fileio.c index 44b41221c..3d31a07c6 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -388,17 +388,18 @@ static int FIO_compressFilename_dstFile(cRess_t ress, const char* dstFileName, const char* srcFileName) { int result; - time_t modtime = 0; + stat_t statbuf; + int stat_result = 0; ress.dstFile = FIO_openDstFile(dstFileName); if (ress.dstFile==NULL) return 1; /* could not open dstFileName */ - if (strcmp (srcFileName, stdinmark)) modtime = UTIL_getModificationTime(srcFileName); + if (strcmp (srcFileName, stdinmark) && UTIL_getFileStat(srcFileName, &statbuf)) stat_result = 1; result = FIO_compressFilename_srcFile(ress, dstFileName, srcFileName); if (fclose(ress.dstFile)) { DISPLAYLEVEL(1, "zstd: %s: %s \n", dstFileName, strerror(errno)); result=1; } /* error closing dstFile */ if (result!=0) { if (remove(dstFileName)) EXM_THROW(1, "zstd: %s: %s", dstFileName, strerror(errno)); } /* remove operation artefact */ - else if (strcmp (dstFileName, stdoutmark)) UTIL_setModificationTime(dstFileName, modtime); + else if (strcmp (dstFileName, stdoutmark) && stat_result) UTIL_setFileStat(dstFileName, &statbuf); return result; } @@ -723,12 +724,13 @@ static int FIO_decompressDstFile(dRess_t ress, const char* dstFileName, const char* srcFileName) { int result; - time_t modtime = 0; + stat_t statbuf; + int stat_result = 0; ress.dstFile = FIO_openDstFile(dstFileName); if (ress.dstFile==0) return 1; - if (strcmp (srcFileName, stdinmark)) modtime = UTIL_getModificationTime(srcFileName); + if (strcmp (srcFileName, stdinmark) && UTIL_getFileStat(srcFileName, &statbuf)) stat_result = 1; result = FIO_decompressSrcFile(ress, srcFileName); if (fclose(ress.dstFile)) EXM_THROW(38, "Write error : cannot properly close %s", dstFileName); @@ -737,7 +739,7 @@ static int FIO_decompressDstFile(dRess_t ress, && strcmp(dstFileName, nulmark) /* special case : don't remove() /dev/null (#316) */ && remove(dstFileName) ) result=1; /* don't do anything special if remove() fails */ - else if (strcmp (dstFileName, stdoutmark)) UTIL_setModificationTime(dstFileName, modtime); + else if (strcmp (dstFileName, stdoutmark) && stat_result) UTIL_setFileStat(dstFileName, &statbuf); return result; } diff --git a/programs/util.h b/programs/util.h index 1bbe2a736..7d503d9df 100644 --- a/programs/util.h +++ b/programs/util.h @@ -50,6 +50,7 @@ extern "C" { #include /* stat */ #include /* utime */ #include /* time */ +#include /* chown, stat */ #include "mem.h" /* U32, U64 */ @@ -144,33 +145,44 @@ UTIL_STATIC void UTIL_waitForNextTick(UTIL_time_t ticksPerSecond) /*-**************************************** * File functions ******************************************/ -UTIL_STATIC int UTIL_setModificationTime(const char *filename, time_t modtime) -{ - struct utimbuf timebuf; +#if defined(_MSC_VER) + typedef struct _stat64 stat_t; +#else + typedef struct stat stat_t; +#endif - if (modtime == 0) return -1; + +UTIL_STATIC int UTIL_setFileStat(const char *filename, stat_t *statbuf) +{ + int res = 0; + struct utimbuf timebuf; + +#if !defined(_WIN32) + res += chown(filename, statbuf->st_uid, statbuf->st_gid); /* Copy ownership */ +#endif + + res += chmod(filename, statbuf->st_mode & 07777); /* Copy file permissions */ timebuf.actime = time(NULL); - timebuf.modtime = modtime; + timebuf.modtime = statbuf->st_mtime; + res += utime(filename, &timebuf); /* set access and modification times */ - /* On success, zero is returned. On error, -1 is returned, and errno is set appropriately. */ - return utime(filename, &timebuf); + errno = 0; + return -res; /* number of errors is returned */ } -UTIL_STATIC time_t UTIL_getModificationTime(const char* infilename) +UTIL_STATIC int UTIL_getFileStat(const char* infilename, stat_t *statbuf) { int r; #if defined(_MSC_VER) - struct _stat64 statbuf; - r = _stat64(infilename, &statbuf); - if (r || !(statbuf.st_mode & S_IFREG)) return 0; /* No good... */ + r = _stat64(infilename, statbuf); + if (r || !(statbuf->st_mode & S_IFREG)) return 0; /* No good... */ #else - struct stat statbuf; - r = stat(infilename, &statbuf); - if (r || !S_ISREG(statbuf.st_mode)) return 0; /* No good... */ + r = stat(infilename, statbuf); + if (r || !S_ISREG(statbuf->st_mode)) return 0; /* No good... */ #endif - return statbuf.st_mtime; + return 1; }