From 547c36f65337917db7eb830d4e86056d5d3d7f19 Mon Sep 17 00:00:00 2001 From: Yonatan Komornik Date: Fri, 29 Jul 2022 14:12:55 -0700 Subject: [PATCH 1/2] Fixes for https://github.com/facebook/zstd/issues/3206 - bugs when handling stdin as part of multiple files. --- programs/fileio.c | 10 +++++++++ programs/util.c | 10 +++++++++ programs/util.h | 5 +++++ programs/zstdcli.c | 8 +++---- tests/cli-tests/compression/multiple-files.sh | 21 +++++++++++++++++++ .../multiple-files.sh.stdout.exact | 12 +++++++++++ 6 files changed, 62 insertions(+), 4 deletions(-) create mode 100755 tests/cli-tests/compression/multiple-files.sh create mode 100644 tests/cli-tests/compression/multiple-files.sh.stdout.exact diff --git a/programs/fileio.c b/programs/fileio.c index b8b2818bcd8..8d95a907ee4 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -1796,6 +1796,11 @@ FIO_determineCompressedName(const char* srcFileName, const char* outDirName, con char* outDirFilename = NULL; size_t sfnSize = strlen(srcFileName); size_t const srcSuffixLen = strlen(suffix); + + if(!strcmp(srcFileName, stdinmark)) { + return stdoutmark; + } + if (outDirName) { outDirFilename = FIO_createFilename_fromOutDir(srcFileName, outDirName, srcSuffixLen); sfnSize = strlen(outDirFilename); @@ -2576,6 +2581,11 @@ FIO_determineDstName(const char* srcFileName, const char* outDirName) size_t srcSuffixLen; const char* const srcSuffix = strrchr(srcFileName, '.'); + + if(!strcmp(srcFileName, stdinmark)) { + return stdoutmark; + } + if (srcSuffix == NULL) { DISPLAYLEVEL(1, "zstd: %s: unknown suffix (%s expected). " diff --git a/programs/util.c b/programs/util.c index f53eb03fbec..f5e2958c8f0 100644 --- a/programs/util.c +++ b/programs/util.c @@ -509,6 +509,16 @@ FileNamesTable* UTIL_allocateFileNamesTable(size_t tableSize) return fnt; } +int UTIL_searchFileNamesTable(FileNamesTable* table, char const* name) { + size_t i; + for(i=0 ;i < table->tableSize; i++) { + if(!strcmp(table->fileNames[i], name)) { + return (int)i; + } + } + return -1; +} + void UTIL_refFilename(FileNamesTable* fnt, const char* filename) { assert(fnt->tableSize < fnt->tableCapacity); diff --git a/programs/util.h b/programs/util.h index add165d57ce..faf8c9f11cb 100644 --- a/programs/util.h +++ b/programs/util.h @@ -269,6 +269,11 @@ UTIL_createFNT_fromROTable(const char** filenames, size_t nbFilenames); */ FileNamesTable* UTIL_allocateFileNamesTable(size_t tableSize); +/*! UTIL_searchFileNamesTable() : + * Searched through entries in FileNamesTable for a specific name. + * @return : index of entry if found or -1 if not found + */ +int UTIL_searchFileNamesTable(FileNamesTable* table, char const* name); /*! UTIL_refFilename() : * Add a reference to read-only name into @fnt table. diff --git a/programs/zstdcli.c b/programs/zstdcli.c index fbacb908a92..ed247956fbf 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -1388,19 +1388,19 @@ int main(int argCount, const char* argv[]) UTIL_refFilename(filenames, stdinmark); } - if (!strcmp(filenames->fileNames[0], stdinmark) && !outFileName) + if (filenames->tableSize == 1 && !strcmp(filenames->fileNames[0], stdinmark) && !outFileName) outFileName = stdoutmark; /* when input is stdin, default output is stdout */ /* Check if input/output defined as console; trigger an error in this case */ if (!forceStdin - && !strcmp(filenames->fileNames[0], stdinmark) + && (UTIL_searchFileNamesTable(filenames, stdinmark) != -1) && IS_CONSOLE(stdin) ) { DISPLAYLEVEL(1, "stdin is a console, aborting\n"); CLEAN_RETURN(1); } - if ( outFileName && !strcmp(outFileName, stdoutmark) + if ( (!outFileName || !strcmp(outFileName, stdoutmark)) && IS_CONSOLE(stdout) - && !strcmp(filenames->fileNames[0], stdinmark) + && (UTIL_searchFileNamesTable(filenames, stdinmark) != -1) && !forceStdout && operation!=zom_decompress ) { DISPLAYLEVEL(1, "stdout is a console, aborting\n"); diff --git a/tests/cli-tests/compression/multiple-files.sh b/tests/cli-tests/compression/multiple-files.sh new file mode 100755 index 00000000000..feda4ac8699 --- /dev/null +++ b/tests/cli-tests/compression/multiple-files.sh @@ -0,0 +1,21 @@ +#!/bin/sh +set -e + +# setup +echo "file1" > file1 +echo "file2" > file2 + +echo "Test zstd ./file1 - file2" +rm -f ./file*.zst +echo "stdin" | zstd ./file1 - ./file2 | zstd -d +cat file1.zst | zstd -d +cat file2.zst | zstd -d + +echo "Test zstd -d ./file1.zst - file2.zst" +rm ./file1 ./file2 +echo "stdin" | zstd - | zstd -d ./file1.zst - file2.zst +cat file1 +cat file2 + +echo "zstd -d ./file1.zst - file2.zst -c" +echo "stdin" | zstd | zstd -d ./file1.zst - file2.zst -c \ No newline at end of file diff --git a/tests/cli-tests/compression/multiple-files.sh.stdout.exact b/tests/cli-tests/compression/multiple-files.sh.stdout.exact new file mode 100644 index 00000000000..aad61d6359a --- /dev/null +++ b/tests/cli-tests/compression/multiple-files.sh.stdout.exact @@ -0,0 +1,12 @@ +Test zstd ./file1 - file2 +stdin +file1 +file2 +Test zstd -d ./file1.zst - file2.zst +stdin +file1 +file2 +zstd -d ./file1.zst - file2.zst -c +file1 +stdin +file2 From a8969d6a96c87ddde2848a38057cde4fd9dcad68 Mon Sep 17 00:00:00 2001 From: Yonatan Komornik Date: Fri, 29 Jul 2022 15:35:04 -0700 Subject: [PATCH 2/2] new line at end of multiple-files.sh --- tests/cli-tests/compression/multiple-files.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cli-tests/compression/multiple-files.sh b/tests/cli-tests/compression/multiple-files.sh index feda4ac8699..aeb74cf25eb 100755 --- a/tests/cli-tests/compression/multiple-files.sh +++ b/tests/cli-tests/compression/multiple-files.sh @@ -18,4 +18,4 @@ cat file1 cat file2 echo "zstd -d ./file1.zst - file2.zst -c" -echo "stdin" | zstd | zstd -d ./file1.zst - file2.zst -c \ No newline at end of file +echo "stdin" | zstd | zstd -d ./file1.zst - file2.zst -c