Skip to content

Commit 7e895e0

Browse files
committed
disable --rm on -o command
make it more similar to -c (aka `stdout`) convention.
1 parent 41682e6 commit 7e895e0

File tree

4 files changed

+91
-45
lines changed

4 files changed

+91
-45
lines changed

programs/fileio.c

Lines changed: 56 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -823,41 +823,62 @@ static void FIO_adjustMemLimitForPatchFromMode(FIO_prefs_t* const prefs,
823823
FIO_setMemLimit(prefs, (unsigned)maxSize);
824824
}
825825

826-
/* FIO_removeMultiFilesWarning() :
826+
/* FIO_multiFilesConcatWarning() :
827+
* This function handles logic when processing multiple files with -o or -c, displaying the appropriate warnings/prompts.
827828
* Returns 1 if the console should abort, 0 if console should proceed.
828-
* This function handles logic when processing multiple files with -o, displaying the appropriate warnings/prompts.
829829
*
830-
* If -f is specified, or there is just 1 file, zstd will always proceed as usual.
831-
* If --rm is specified, there will be a prompt asking for user confirmation.
832-
* If -f is specified with --rm, zstd will proceed as usual
833-
* If -q is specified with --rm, zstd will abort pre-emptively
834-
* If neither flag is specified, zstd will prompt the user for confirmation to proceed.
835-
* If --rm is not specified, then zstd will print a warning to the user (which can be silenced with -q).
836-
* Note : --rm in combination with stdout is not allowed.
830+
* If output is stdout or test mode is active, check or enforce `--rm` disabled.
831+
*
832+
* If there is just 1 file to process, zstd will proceed as usual.
833+
* If each file get processed into its own separate destination file, proceed as usual.
834+
*
835+
* When multiple files are processed into a single output,
836+
* display a warning message, then disable --rm if it's set.
837+
*
838+
* If -f is specified or if output is stdout, just proceed.
839+
* If output is set with -o, prompt for confirmation.
837840
*/
838-
static int FIO_removeMultiFilesWarning(FIO_ctx_t* const fCtx, const FIO_prefs_t* const prefs, const char* outFileName, int displayLevelCutoff)
841+
static int FIO_multiFilesConcatWarning(const FIO_ctx_t* fCtx, FIO_prefs_t* prefs, const char* outFileName, int displayLevelCutoff)
839842
{
840-
int error = 0;
841-
if (fCtx->nbFilesTotal > 1 && !prefs->overwrite) {
842-
if (g_display_prefs.displayLevel <= displayLevelCutoff) {
843-
if (prefs->removeSrcFile) {
844-
DISPLAYLEVEL(1, "zstd: Aborting... not deleting files and processing into dst: %s\n", outFileName);
845-
error = 1;
846-
}
847-
} else {
848-
if (!strcmp(outFileName, stdoutmark)) {
849-
DISPLAYLEVEL(2, "zstd: WARNING: all input files will be processed and concatenated into stdout. \n");
850-
} else {
851-
DISPLAYLEVEL(2, "zstd: WARNING: all input files will be processed and concatenated into a single output file: %s \n", outFileName);
852-
}
853-
DISPLAYLEVEL(2, "The concatenated output CANNOT regenerate original file names nor directory structure. \n")
854-
if (prefs->removeSrcFile) {
855-
assert(fCtx->hasStdoutOutput == 0); /* not possible : never erase source files when output == stdout */
856-
error = (g_display_prefs.displayLevel > displayLevelCutoff) && UTIL_requireUserConfirmation("This is a destructive operation. Proceed? (y/n): ", "Aborting...", "yY", fCtx->hasStdinInput);
857-
}
858-
}
843+
if (fCtx->hasStdoutOutput) assert(prefs->removeSrcFile == 0);
844+
if (prefs->testMode) {
845+
prefs->removeSrcFile = 0; /* enforce */
846+
return 0;
859847
}
860-
return error;
848+
849+
if (fCtx->nbFilesTotal == 1) return 0;
850+
assert(fCtx->nbFilesTotal > 1);
851+
852+
if (!outFileName) return 0;
853+
854+
if (fCtx->hasStdoutOutput) {
855+
DISPLAYLEVEL(2, "zstd: WARNING: all input files will be processed and concatenated into stdout. \n");
856+
} else {
857+
DISPLAYLEVEL(2, "zstd: WARNING: all input files will be processed and concatenated into a single output file: %s \n", outFileName);
858+
}
859+
DISPLAYLEVEL(2, "The concatenated output CANNOT regenerate original file names nor directory structure. \n")
860+
861+
/* multi-input into single output : --rm is not allowed */
862+
if (prefs->removeSrcFile) {
863+
DISPLAYLEVEL(2, "Since it's a destructive operation, input files will not be removed. \n");
864+
prefs->removeSrcFile = 0;
865+
}
866+
867+
if (fCtx->hasStdoutOutput) return 0;
868+
if (prefs->overwrite) return 0;
869+
870+
/* multiple files concatenated into single destination file using -o without -f */
871+
DISPLAY("multiple files concatenated into single destination file using -o without -f \n");
872+
DISPLAY("g_display_prefs.displayLevel = %i \n", g_display_prefs.displayLevel);
873+
DISPLAY("displayLevelCutoff = %i \n", displayLevelCutoff);
874+
if (g_display_prefs.displayLevel <= displayLevelCutoff) {
875+
/* quiet mode => no prompt => fail automatically */
876+
DISPLAYLEVEL(1, "Concatenating multiple processed inputs into a single output loses file metadata. \n");
877+
DISPLAYLEVEL(1, "Aborting. \n");
878+
return 1;
879+
}
880+
/* normal mode => prompt */
881+
return UTIL_requireUserConfirmation("Proceed? (y/n): ", "Aborting...", "yY", fCtx->hasStdinInput);
861882
}
862883

863884
static ZSTD_inBuffer setInBuffer(const void* buf, size_t s, size_t pos)
@@ -1767,9 +1788,9 @@ FIO_compressFilename_srcFile(FIO_ctx_t* const fCtx,
17671788
&srcFileStat, compressionLevel);
17681789
AIO_ReadPool_closeFile(ress.readCtx);
17691790

1770-
if ( prefs->removeSrcFile /* --rm */
1771-
&& result == 0 /* success */
1772-
&& strcmp(srcFileName, stdinmark) /* exception : don't erase stdin */
1791+
if ( prefs->removeSrcFile /* --rm */
1792+
&& result == 0 /* success */
1793+
&& strcmp(srcFileName, stdinmark) /* exception : don't erase stdin */
17731794
) {
17741795
/* We must clear the handler, since after this point calling it would
17751796
* delete both the source and destination files.
@@ -1920,7 +1941,7 @@ int FIO_compressMultipleFilenames(FIO_ctx_t* const fCtx,
19201941
assert(outFileName != NULL || suffix != NULL);
19211942
if (outFileName != NULL) { /* output into a single destination (stdout typically) */
19221943
FILE *dstFile;
1923-
if (FIO_removeMultiFilesWarning(fCtx, prefs, outFileName, 1 /* displayLevelCutoff */)) {
1944+
if (FIO_multiFilesConcatWarning(fCtx, prefs, outFileName, 1 /* displayLevelCutoff */)) {
19241945
FIO_freeCResources(&ress);
19251946
return 1;
19261947
}
@@ -2742,7 +2763,7 @@ FIO_decompressMultipleFilenames(FIO_ctx_t* const fCtx,
27422763
dRess_t ress = FIO_createDResources(prefs, dictFileName);
27432764

27442765
if (outFileName) {
2745-
if (FIO_removeMultiFilesWarning(fCtx, prefs, outFileName, 1 /* displayLevelCutoff */)) {
2766+
if (FIO_multiFilesConcatWarning(fCtx, prefs, outFileName, 1 /* displayLevelCutoff */)) {
27462767
FIO_freeDResources(ress);
27472768
return 1;
27482769
}

programs/util.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ int UTIL_requireUserConfirmation(const char* prompt, const char* abortMsg,
121121
ch = getchar();
122122
result = 0;
123123
if (strchr(acceptableLetters, ch) == NULL) {
124-
UTIL_DISPLAY("%s", abortMsg);
124+
UTIL_DISPLAY("%s \n", abortMsg);
125125
result = 1;
126126
}
127127
/* flush the rest */

programs/zstdcli.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1510,6 +1510,7 @@ int main(int argCount, const char* argv[])
15101510
FIO_setHasStdoutOutput(fCtx, hasStdout);
15111511
FIO_setNbFilesTotal(fCtx, (int)filenames->tableSize);
15121512
FIO_determineHasStdinInput(fCtx, filenames);
1513+
DISPLAY("setting displayLevel to %i \n", g_displayLevel);
15131514
FIO_setNotificationLevel(g_displayLevel);
15141515
FIO_setAllowBlockDevices(prefs, allowBlockDevices);
15151516
FIO_setPatchFromMode(prefs, patchFromDictFileName != NULL);

tests/playTests.sh

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@ println "\n===> file removal"
387387
zstd -f --rm tmp
388388
test ! -f tmp # tmp should no longer be present
389389
zstd -f -d --rm tmp.zst
390-
test ! -f tmp.zst # tmp.zst should no longer be present
390+
test ! -f tmp.zst # tmp.zst should no longer be present
391391
println "test: --rm is disabled when output is stdout"
392392
test -f tmp
393393
zstd --rm tmp -c > $INTOVOID
@@ -396,6 +396,25 @@ zstd -f --rm tmp -c > $INTOVOID
396396
test -f tmp # tmp shall still be there
397397
zstd -f tmp -c > $INTOVOID --rm
398398
test -f tmp # tmp shall still be there
399+
println "test: --rm is disabled when multiple inputs are concatenated into a single output"
400+
cp tmp tmp2
401+
zstd --rm tmp tmp2 -c > $INTOVOID
402+
test -f tmp
403+
test -f tmp2
404+
rm -f tmp3.zst
405+
echo zstd tmp tmp2 -o tmp3.zst --rm with yes
406+
echo 'y' | zstd tmp tmp2 -o tmp3.zst --rm # prompt for confirmation
407+
echo operation completed succesfully after prompt
408+
test -f tmp
409+
test -f tmp2
410+
echo zstd -f tmp tmp2 -o tmp3.zst --rm
411+
zstd -f tmp tmp2 -o tmp3.zst --rm # just warns, no prompt
412+
test -f tmp
413+
test -f tmp2
414+
echo zstd -q tmp tmp2 -o tmp3.zst --rm
415+
zstd -q tmp tmp2 -o tmp3.zst --rm && die "should refuse to concatenate"
416+
echo operation failed as expected
417+
399418
println "test : should quietly not remove non-regular file"
400419
println hello > tmp
401420
zstd tmp -f -o "$DEVDEVICE" 2>tmplog > "$INTOVOID"
@@ -437,34 +456,35 @@ println hello > tmp1
437456
println world > tmp2
438457
zstd tmp1 tmp2 -o "$INTOVOID" -f
439458
zstd tmp1 tmp2 -c | zstd -t
440-
zstd tmp1 tmp2 -o tmp.zst
459+
echo 'y' | zstd tmp1 tmp2 -o tmp.zst
441460
test ! -f tmp1.zst
442461
test ! -f tmp2.zst
443462
zstd tmp1 tmp2
444463
zstd -t tmp1.zst tmp2.zst
445464
zstd -dc tmp1.zst tmp2.zst
446465
zstd tmp1.zst tmp2.zst -o "$INTOVOID" -f
447-
zstd -d tmp1.zst tmp2.zst -o tmp
466+
echo 'y' | zstd -d tmp1.zst tmp2.zst -o tmp
448467
touch tmpexists
449468
zstd tmp1 tmp2 -f -o tmpexists
450469
zstd tmp1 tmp2 -q -o tmpexists && die "should have refused to overwrite"
451470
println gooder > tmp_rm1
452471
println boi > tmp_rm2
453472
println worldly > tmp_rm3
454-
echo 'y' | zstd tmp_rm1 tmp_rm2 -v -o tmp_rm3.zst --rm # tests the warning prompt for --rm with multiple inputs into once source
455-
test ! -f tmp_rm1
456-
test ! -f tmp_rm2
473+
echo 'y' | zstd tmp_rm1 tmp_rm2 -v -o tmp_rm3.zst
474+
test -f tmp_rm1
475+
test -f tmp_rm2
457476
cp tmp_rm3.zst tmp_rm4.zst
458477
echo 'Y' | zstd -d tmp_rm3.zst tmp_rm4.zst -v -o tmp_rm_out --rm
459-
test ! -f tmp_rm3.zst
460-
test ! -f tmp_rm4.zst
478+
test -f tmp_rm3.zst
479+
test -f tmp_rm4.zst
461480
println gooder > tmpexists1
462481
zstd tmpexists1 tmpexists -c --rm -f > $INTOVOID
463-
464482
# Bug: PR #972
465483
if [ "$?" -eq 139 ]; then
466484
die "should not have segfaulted"
467485
fi
486+
test -f tmpexists1
487+
test -f tmpexists
468488
println "\n===> multiple files and shell completion "
469489
datagen -s1 > tmp1 2> $INTOVOID
470490
datagen -s2 -g100K > tmp2 2> $INTOVOID
@@ -1172,6 +1192,10 @@ zstd -t tmp3 && die "bad file not detected !" # detects 0-sized files as bad
11721192
println "test --rm and --test combined "
11731193
zstd -t --rm tmp1.zst
11741194
test -f tmp1.zst # check file is still present
1195+
cp tmp1.zst tmp2.zst
1196+
zstd -t tmp1.zst tmp2.zst --rm
1197+
test -f tmp1.zst # check file is still present
1198+
test -f tmp2.zst # check file is still present
11751199
split -b16384 tmp1.zst tmpSplit.
11761200
zstd -t tmpSplit.* && die "bad file not detected !"
11771201
datagen | zstd -c | zstd -t

0 commit comments

Comments
 (0)