From 5bf1359e3be0e64149bbb989f2addfc42adf30d3 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 31 Mar 2023 11:13:52 -0700 Subject: [PATCH 1/2] fix decompression with -o writing into a block device decompression features automatic support of sparse files, aka a form of "compression" where entire blocks consists only of zeroes. This only works for some compatible file systems (like ext4), others simply ignore it (like afs). Triggering this feature relies of `fseek()`. But `fseek()` is not compatible with non-seekable devices, such as pipes. Therefore it's disabled for pipes. However, there are other objects which are not compatible with `fseek()`, such as block devices. Changed the logic, so that `fseek()` (and therefore sparse write) is only automatically enabled on regular files. Note that this automatic behavior can always be overridden by explicit commands `--sparse` and `--no-sparse`. fix #3583 --- programs/fileio.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/programs/fileio.c b/programs/fileio.c index dc5d95b3988..877460302b6 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -601,6 +601,10 @@ FIO_openDstFile(FIO_ctx_t* fCtx, FIO_prefs_t* const prefs, } if (prefs->sparseFileSupport == 1) { + if (!UTIL_isRegularFile(dstFileName)) { + prefs->sparseFileSupport = 0; + DISPLAYLEVEL(4, "Sparse File Support is disabled when output is not a file \n"); + } prefs->sparseFileSupport = ZSTD_SPARSE_DEFAULT; } @@ -2259,8 +2263,8 @@ static void FIO_freeDResources(dRess_t ress) AIO_ReadPool_free(ress.readCtx); } -/** FIO_passThrough() : just copy input into output, for compatibility with gzip -df mode - @return : 0 (no error) */ +/* FIO_passThrough() : just copy input into output, for compatibility with gzip -df mode + * @return : 0 (no error) */ static int FIO_passThrough(dRess_t *ress) { size_t const blockSize = MIN(MIN(64 KB, ZSTD_DStreamInSize()), ZSTD_DStreamOutSize()); @@ -2288,7 +2292,8 @@ static int FIO_passThrough(dRess_t *ress) static void FIO_zstdErrorHelp(const FIO_prefs_t* const prefs, const dRess_t* ress, - size_t err, const char* srcFileName) + size_t err, + const char* srcFileName) { ZSTD_frameHeader header; From 14d0cd5d690ef0956a2e3085e81c78578f55b81e Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 31 Mar 2023 13:09:52 -0700 Subject: [PATCH 2/2] do not add invocation of UTIL_isRegularFile() --- programs/fileio.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/programs/fileio.c b/programs/fileio.c index 877460302b6..4f75ff4748a 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -581,6 +581,8 @@ 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); @@ -600,15 +602,16 @@ FIO_openDstFile(FIO_ctx_t* fCtx, FIO_prefs_t* const prefs, return NULL; } + isDstRegFile = UTIL_isRegularFile(dstFileName); /* invoke once */ if (prefs->sparseFileSupport == 1) { - if (!UTIL_isRegularFile(dstFileName)) { + if (!isDstRegFile) { prefs->sparseFileSupport = 0; DISPLAYLEVEL(4, "Sparse File Support is disabled when output is not a file \n"); } prefs->sparseFileSupport = ZSTD_SPARSE_DEFAULT; } - if (UTIL_isRegularFile(dstFileName)) { + if (isDstRegFile) { /* Check if destination file already exists */ #if !defined(_WIN32) /* this test does not work on Windows :