diff --git a/programs/fileio.c b/programs/fileio.c index dc7636949..77f3d35f9 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -585,8 +585,6 @@ FIO_openDstFile(FIO_ctx_t* fCtx, FIO_prefs_t* const prefs, const char* srcFileName, const char* dstFileName, const int mode) { - int isDstRegFile; - if (prefs->testMode) return NULL; /* do not open file in test mode */ assert(dstFileName != NULL); @@ -606,16 +604,7 @@ FIO_openDstFile(FIO_ctx_t* fCtx, FIO_prefs_t* const prefs, return NULL; } - isDstRegFile = UTIL_isRegularFile(dstFileName); /* invoke once */ - if (prefs->sparseFileSupport == 1) { - prefs->sparseFileSupport = ZSTD_SPARSE_DEFAULT; - if (!isDstRegFile) { - prefs->sparseFileSupport = 0; - DISPLAYLEVEL(4, "Sparse File Support is disabled when output is not a file \n"); - } - } - - if (isDstRegFile) { + if (UTIL_isRegularFile(dstFileName)) { /* Check if destination file already exists */ #if !defined(_WIN32) /* this test does not work on Windows : @@ -641,6 +630,7 @@ FIO_openDstFile(FIO_ctx_t* fCtx, FIO_prefs_t* const prefs, } { + int isDstRegFile; #if defined(_WIN32) /* Windows requires opening the file as a "binary" file to avoid * mangling. This macro doesn't exist on unix. */ @@ -658,6 +648,17 @@ FIO_openDstFile(FIO_ctx_t* fCtx, FIO_prefs_t* const prefs, f = fdopen(fd, "wb"); } #endif + + /* Check regular file after opening with O_CREAT */ + isDstRegFile = UTIL_isFdRegularFile(fd); + if (prefs->sparseFileSupport == 1) { + prefs->sparseFileSupport = ZSTD_SPARSE_DEFAULT; + if (!isDstRegFile) { + prefs->sparseFileSupport = 0; + DISPLAYLEVEL(4, "Sparse File Support is disabled when output is not a file \n"); + } + } + if (f == NULL) { if (UTIL_isFileDescriptorPipe(dstFileName)) { DISPLAYLEVEL(1, "zstd: error: no output specified (use -o or -c). \n"); diff --git a/programs/util.c b/programs/util.c index 94c40cc95..d11f13cfd 100644 --- a/programs/util.c +++ b/programs/util.c @@ -197,6 +197,16 @@ int UTIL_stat(const char* filename, stat_t* statbuf) return UTIL_fstat(-1, filename, statbuf); } +int UTIL_isFdRegularFile(int fd) +{ + stat_t statbuf; + int ret; + UTIL_TRACE_CALL("UTIL_isFdRegularFile(%d)", fd); + ret = fd >= 0 && UTIL_fstat(fd, "", &statbuf) && UTIL_isRegularFileStat(&statbuf); + UTIL_TRACE_RET(ret); + return ret; +} + int UTIL_isRegularFile(const char* infilename) { stat_t statbuf; diff --git a/programs/util.h b/programs/util.h index 427bcf441..65e12633a 100644 --- a/programs/util.h +++ b/programs/util.h @@ -184,6 +184,7 @@ int UTIL_fchmod(const int fd, char const* filename, const stat_t* statbuf, mode_ * compute the needed information. */ +int UTIL_isFdRegularFile(int fd); int UTIL_isRegularFile(const char* infilename); int UTIL_isDirectory(const char* infilename); int UTIL_isSameFile(const char* file1, const char* file2); diff --git a/tests/cli-tests/file-stat/compress-file-to-dir-without-write-perm.sh.stderr.exact b/tests/cli-tests/file-stat/compress-file-to-dir-without-write-perm.sh.stderr.exact index 9f254f8c2..05d91ffc9 100644 --- a/tests/cli-tests/file-stat/compress-file-to-dir-without-write-perm.sh.stderr.exact +++ b/tests/cli-tests/file-stat/compress-file-to-dir-without-write-perm.sh.stderr.exact @@ -22,6 +22,8 @@ Trace:FileStat: > UTIL_isRegularFile(out/file.zst) Trace:FileStat: > UTIL_stat(-1, out/file.zst) Trace:FileStat: < 0 Trace:FileStat: < 0 +Trace:FileStat: > UTIL_isFdRegularFile(-1) +Trace:FileStat: < 0 Trace:FileStat: > UTIL_isFileDescriptorPipe(out/file.zst) Trace:FileStat: < 0 zstd: out/file.zst: Permission denied 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.glob similarity index 91% rename from tests/cli-tests/file-stat/compress-file-to-file.sh.stderr.exact rename to tests/cli-tests/file-stat/compress-file-to-file.sh.stderr.glob index 32d248ee5..17a677deb 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.glob @@ -22,6 +22,10 @@ Trace:FileStat: > UTIL_isRegularFile(file.zst) Trace:FileStat: > UTIL_stat(-1, file.zst) Trace:FileStat: < 0 Trace:FileStat: < 0 +Trace:FileStat: > UTIL_isFdRegularFile(*) +Trace:FileStat: > UTIL_stat(*, ) +Trace:FileStat: < 1 +Trace:FileStat: < 1 Trace:FileStat: > UTIL_isRegularFile(file.zst) Trace:FileStat: > UTIL_stat(-1, file.zst) Trace:FileStat: < 1 diff --git a/tests/cli-tests/file-stat/compress-stdin-to-file.sh.stderr.exact b/tests/cli-tests/file-stat/compress-stdin-to-file.sh.stderr.glob similarity index 86% rename from tests/cli-tests/file-stat/compress-stdin-to-file.sh.stderr.exact rename to tests/cli-tests/file-stat/compress-stdin-to-file.sh.stderr.glob index 9183c4674..38732cbe9 100644 --- a/tests/cli-tests/file-stat/compress-stdin-to-file.sh.stderr.exact +++ b/tests/cli-tests/file-stat/compress-stdin-to-file.sh.stderr.glob @@ -14,6 +14,10 @@ Trace:FileStat: > UTIL_isRegularFile(file.zst) Trace:FileStat: > UTIL_stat(-1, file.zst) Trace:FileStat: < 0 Trace:FileStat: < 0 +Trace:FileStat: > UTIL_isFdRegularFile(*) +Trace:FileStat: > UTIL_stat(*, ) +Trace:FileStat: < 1 +Trace:FileStat: < 1 Trace:FileStat: > UTIL_isRegularFile(file.zst) Trace:FileStat: > UTIL_stat(-1, file.zst) Trace:FileStat: < 1 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.glob similarity index 90% rename from tests/cli-tests/file-stat/decompress-file-to-file.sh.stderr.exact rename to tests/cli-tests/file-stat/decompress-file-to-file.sh.stderr.glob index ad3a0deb8..ce194dfb3 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.glob @@ -22,6 +22,10 @@ Trace:FileStat: > UTIL_isRegularFile(file) Trace:FileStat: > UTIL_stat(-1, file) Trace:FileStat: < 0 Trace:FileStat: < 0 +Trace:FileStat: > UTIL_isFdRegularFile(*) +Trace:FileStat: > UTIL_stat(*, ) +Trace:FileStat: < 1 +Trace:FileStat: < 1 Trace:FileStat: > UTIL_isRegularFile(file) Trace:FileStat: > UTIL_stat(-1, file) Trace:FileStat: < 1 diff --git a/tests/cli-tests/file-stat/decompress-stdin-to-file.sh.stderr.exact b/tests/cli-tests/file-stat/decompress-stdin-to-file.sh.stderr.glob similarity index 84% rename from tests/cli-tests/file-stat/decompress-stdin-to-file.sh.stderr.exact rename to tests/cli-tests/file-stat/decompress-stdin-to-file.sh.stderr.glob index 716a7ac7b..9eb920883 100644 --- a/tests/cli-tests/file-stat/decompress-stdin-to-file.sh.stderr.exact +++ b/tests/cli-tests/file-stat/decompress-stdin-to-file.sh.stderr.glob @@ -14,6 +14,10 @@ Trace:FileStat: > UTIL_isRegularFile(file) Trace:FileStat: > UTIL_stat(-1, file) Trace:FileStat: < 0 Trace:FileStat: < 0 +Trace:FileStat: > UTIL_isFdRegularFile(*) +Trace:FileStat: > UTIL_stat(*, ) +Trace:FileStat: < 1 +Trace:FileStat: < 1 Trace:FileStat: > UTIL_isRegularFile(file) Trace:FileStat: > UTIL_stat(-1, file) Trace:FileStat: < 1