From: W. Felix Handte Date: Mon, 6 Feb 2023 16:05:47 +0000 (-0800) Subject: Use File Descriptor in Setting Stat on Output File X-Git-Tag: v1.5.5~2^2~46^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F3479%2Fhead;p=thirdparty%2Fzstd.git Use File Descriptor in Setting Stat on Output File Note that the `fd` is only valid while the file is still open. So we need to move the setting calls to before we close the file. However! We cannot do so with the `utime()` call (even though `futimens()` exists) because the follow- ing `close()` call to the `fd` will reset the atime of the file. So it seems the `utime()` call has to happen after the file is closed. --- diff --git a/programs/fileio.c b/programs/fileio.c index 9a8300cdd..75f247677 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -1681,6 +1681,7 @@ static int FIO_compressFilename_dstFile(FIO_ctx_t* const fCtx, int result; int transferStat = 0; FILE *dstFile; + int dstFd = -1; assert(AIO_ReadPool_getFile(ress.readCtx) != NULL); if (AIO_WritePool_getFile(ress.writeCtx) == NULL) { @@ -1696,6 +1697,7 @@ static int FIO_compressFilename_dstFile(FIO_ctx_t* const fCtx, DISPLAYLEVEL(6, "FIO_compressFilename_dstFile: opening dst: %s \n", dstFileName); dstFile = FIO_openDstFile(fCtx, prefs, srcFileName, dstFileName, dstFileInitialPermissions); if (dstFile==NULL) return 1; /* could not open dstFileName */ + dstFd = fileno(dstFile); AIO_WritePool_setFile(ress.writeCtx, dstFile); /* Must only be added after FIO_openDstFile() succeeds. * Otherwise we may delete the destination file if it already exists, @@ -1709,14 +1711,20 @@ static int FIO_compressFilename_dstFile(FIO_ctx_t* const fCtx, if (closeDstFile) { clearHandler(); + if (transferStat) { + UTIL_setFDStat(dstFd, dstFileName, srcFileStat); + } + DISPLAYLEVEL(6, "FIO_compressFilename_dstFile: closing dst: %s \n", dstFileName); if (AIO_WritePool_closeFile(ress.writeCtx)) { /* error closing file */ DISPLAYLEVEL(1, "zstd: %s: %s \n", dstFileName, strerror(errno)); result=1; } + if (transferStat) { - UTIL_setFileStat(dstFileName, srcFileStat); + UTIL_utime(dstFileName, srcFileStat); } + if ( (result != 0) /* operation failure */ && strcmp(dstFileName, stdoutmark) /* special case : don't remove() stdout */ ) { @@ -2540,6 +2548,7 @@ static int FIO_decompressDstFile(FIO_ctx_t* const fCtx, int result; int releaseDstFile = 0; int transferStat = 0; + int dstFd = 0; if ((AIO_WritePool_getFile(ress.writeCtx) == NULL) && (prefs->testMode == 0)) { FILE *dstFile; @@ -2555,6 +2564,7 @@ static int FIO_decompressDstFile(FIO_ctx_t* const fCtx, dstFile = FIO_openDstFile(fCtx, prefs, srcFileName, dstFileName, dstFilePermissions); if (dstFile==NULL) return 1; + dstFd = fileno(dstFile); AIO_WritePool_setFile(ress.writeCtx, dstFile); /* Must only be added after FIO_openDstFile() succeeds. @@ -2568,13 +2578,18 @@ static int FIO_decompressDstFile(FIO_ctx_t* const fCtx, if (releaseDstFile) { clearHandler(); + + if (transferStat) { + UTIL_setFDStat(dstFd, dstFileName, srcFileStat); + } + if (AIO_WritePool_closeFile(ress.writeCtx)) { DISPLAYLEVEL(1, "zstd: %s: %s \n", dstFileName, strerror(errno)); result = 1; } if (transferStat) { - UTIL_setFileStat(dstFileName, srcFileStat); + UTIL_utime(dstFileName, srcFileStat); } if ( (result != 0) /* operation failure */ diff --git a/programs/util.c b/programs/util.c index a3f5564af..c9031e91d 100644 --- a/programs/util.c +++ b/programs/util.c @@ -295,9 +295,6 @@ int UTIL_setFDStat(const int fd, const char *filename, const stat_t *statbuf) return -1; } - /* set access and modification times */ - res += UTIL_utime(filename, statbuf); - /* Mimic gzip's behavior: * * "Change the group first, then the permissions, then the owner. diff --git a/tests/cli-tests/file-stat/compress-file-to-file.sh.stderr.exact b/tests/cli-tests/file-stat/compress-file-to-file.sh.stderr.exact index 913a99e1e..32d248ee5 100644 --- a/tests/cli-tests/file-stat/compress-file-to-file.sh.stderr.exact +++ b/tests/cli-tests/file-stat/compress-file-to-file.sh.stderr.exact @@ -30,13 +30,13 @@ Trace:FileStat: > UTIL_getFileSize(file) Trace:FileStat: > UTIL_stat(-1, file) Trace:FileStat: < 1 Trace:FileStat: < 65537 -Trace:FileStat: > UTIL_setFileStat(-1, file.zst) -Trace:FileStat: > UTIL_stat(-1, file.zst) +Trace:FileStat: > UTIL_setFileStat(4, file.zst) +Trace:FileStat: > UTIL_stat(4, file.zst) Trace:FileStat: < 1 -Trace:FileStat: > UTIL_utime(file.zst) -Trace:FileStat: < 0 Trace:FileStat: > UTIL_chmod(file.zst, 0642) -Trace:FileStat: > chmod +Trace:FileStat: > fchmod Trace:FileStat: < 0 Trace:FileStat: < 0 Trace:FileStat: < 0 +Trace:FileStat: > UTIL_utime(file.zst) +Trace:FileStat: < 0 diff --git a/tests/cli-tests/file-stat/decompress-file-to-file.sh.stderr.exact b/tests/cli-tests/file-stat/decompress-file-to-file.sh.stderr.exact index 1d872fb7d..ad3a0deb8 100644 --- a/tests/cli-tests/file-stat/decompress-file-to-file.sh.stderr.exact +++ b/tests/cli-tests/file-stat/decompress-file-to-file.sh.stderr.exact @@ -26,13 +26,13 @@ Trace:FileStat: > UTIL_isRegularFile(file) Trace:FileStat: > UTIL_stat(-1, file) Trace:FileStat: < 1 Trace:FileStat: < 1 -Trace:FileStat: > UTIL_setFileStat(-1, file) -Trace:FileStat: > UTIL_stat(-1, file) +Trace:FileStat: > UTIL_setFileStat(4, file) +Trace:FileStat: > UTIL_stat(4, file) Trace:FileStat: < 1 -Trace:FileStat: > UTIL_utime(file) -Trace:FileStat: < 0 Trace:FileStat: > UTIL_chmod(file, 0642) -Trace:FileStat: > chmod +Trace:FileStat: > fchmod Trace:FileStat: < 0 Trace:FileStat: < 0 Trace:FileStat: < 0 +Trace:FileStat: > UTIL_utime(file) +Trace:FileStat: < 0