Merge pull request #2279 from senhuang42/show_warnings_with_multiple_input_files

Add a warning whenever (de)compressing multiple files
This commit is contained in:
Nick Terrell
2020-09-02 11:32:11 -07:00
committed by GitHub
5 changed files with 88 additions and 12 deletions
+46 -9
View File
@@ -619,17 +619,10 @@ FIO_openDstFile(FIO_prefs_t* const prefs,
dstFileName); dstFileName);
return NULL; return NULL;
} }
DISPLAY("zstd: %s already exists; overwrite (y/N) ? ", DISPLAY("zstd: %s already exists; ", dstFileName);
dstFileName); if (UTIL_requireUserConfirmation("overwrite (y/n) ? ", "Not overwritten \n", "yY"))
{ int ch = getchar();
if ((ch!='Y') && (ch!='y')) {
DISPLAY(" not overwritten \n");
/* flush rest of input line */
while ((ch!=EOF) && (ch!='\n')) ch = getchar();
return NULL; return NULL;
} }
while ((ch!=EOF) && (ch!='\n')) ch = getchar();
} }
/* need to unlink */ /* need to unlink */
FIO_removeFile(dstFileName); FIO_removeFile(dstFileName);
} } } }
@@ -796,6 +789,42 @@ static void FIO_adjustMemLimitForPatchFromMode(FIO_prefs_t* const prefs,
FIO_setMemLimit(prefs, (unsigned)maxSize); FIO_setMemLimit(prefs, (unsigned)maxSize);
} }
/* FIO_removeMultiFilesWarning() :
* Returns 1 if the console should abort, 0 if console should proceed.
* This function handles logic when processing multiple files with -o, displaying the appropriate warnings/prompts.
*
* If -f is specified, or there is just 1 file, zstd will always proceed as usual.
* If --rm is specified, there will be a prompt asking for user confirmation.
* If -f is specified with --rm, zstd will proceed as usual
* If -q is specified with --rm, zstd will abort pre-emptively
* If neither flag is specified, zstd will prompt the user for confirmation to proceed.
* If --rm is not specified, then zstd will print a warning to the user (which can be silenced with -q).
*/
static int FIO_removeMultiFilesWarning(const FIO_prefs_t* const prefs, int displayLevelCutoff, const char* outFileName)
{
int error = 0;
if (prefs->nbFiles > 1 && !prefs->overwrite) {
if (g_display_prefs.displayLevel <= displayLevelCutoff) {
if (prefs->removeSrcFile) {
DISPLAYLEVEL(1, "zstd: Aborting... not deleting files and processing into dst: %s", outFileName);
error = 1;
}
} else {
if (!strcmp(outFileName, stdoutmark)) {
DISPLAYLEVEL(2, "zstd: WARNING: all input files will be processed and concatenated into stdout. ");
} else {
DISPLAYLEVEL(2, "zstd: WARNING: all input files will be processed and concatenated into a single output file: %s ", outFileName);
}
DISPLAYLEVEL(2, "\nThe concatenated output CANNOT regenerate the original directory tree. ")
if (prefs->removeSrcFile) {
error = g_display_prefs.displayLevel > displayLevelCutoff && UTIL_requireUserConfirmation("This is a destructive operation. Proceed? (y/n): ", "Aborting...", "yY");
}
}
DISPLAY("\n");
}
return error;
}
#ifndef ZSTD_NOCOMPRESS #ifndef ZSTD_NOCOMPRESS
/* ********************************************************************** /* **********************************************************************
@@ -1700,6 +1729,10 @@ int FIO_compressMultipleFilenames(FIO_prefs_t* const prefs,
/* init */ /* init */
assert(outFileName != NULL || suffix != NULL); assert(outFileName != NULL || suffix != NULL);
if (outFileName != NULL) { /* output into a single destination (stdout typically) */ if (outFileName != NULL) { /* output into a single destination (stdout typically) */
if (FIO_removeMultiFilesWarning(prefs, 1 /* displayLevelCutoff */, outFileName)) {
FIO_freeCResources(ress);
return 1;
}
ress.dstFile = FIO_openDstFile(prefs, NULL, outFileName); ress.dstFile = FIO_openDstFile(prefs, NULL, outFileName);
if (ress.dstFile == NULL) { /* could not open outFileName */ if (ress.dstFile == NULL) { /* could not open outFileName */
error = 1; error = 1;
@@ -2594,6 +2627,10 @@ FIO_decompressMultipleFilenames(FIO_prefs_t* const prefs,
dRess_t ress = FIO_createDResources(prefs, dictFileName); dRess_t ress = FIO_createDResources(prefs, dictFileName);
if (outFileName) { if (outFileName) {
if (FIO_removeMultiFilesWarning(prefs, 1 /* displayLevelCutoff */, outFileName)) {
FIO_freeDResources(ress);
return 1;
}
if (!prefs->testMode) { if (!prefs->testMode) {
ress.dstFile = FIO_openDstFile(prefs, NULL, outFileName); ress.dstFile = FIO_openDstFile(prefs, NULL, outFileName);
if (ress.dstFile == 0) EXM_THROW(19, "cannot open %s", outFileName); if (ress.dstFile == 0) EXM_THROW(19, "cannot open %s", outFileName);
+16
View File
@@ -87,6 +87,22 @@ UTIL_STATIC void* UTIL_realloc(void *ptr, size_t size)
******************************************/ ******************************************/
int g_utilDisplayLevel; int g_utilDisplayLevel;
int UTIL_requireUserConfirmation(const char* prompt, const char* abortMsg,
const char* acceptableLetters) {
int ch, result;
UTIL_DISPLAY("%s", prompt);
ch = getchar();
result = 0;
if (strchr(acceptableLetters, ch) == NULL) {
UTIL_DISPLAY("%s", abortMsg);
result = 1;
}
/* flush the rest */
while ((ch!=EOF) && (ch!='\n'))
ch = getchar();
return result;
}
/*-************************************* /*-*************************************
* Constants * Constants
+6
View File
@@ -93,6 +93,12 @@ extern "C" {
******************************************/ ******************************************/
extern int g_utilDisplayLevel; extern int g_utilDisplayLevel;
/**
* Displays a message prompt and returns success (0) if first character from stdin
* matches any from acceptableLetters. Otherwise, returns failure (1) and displays abortMsg.
*/
int UTIL_requireUserConfirmation(const char* prompt, const char* abortMsg, const char* acceptableLetters);
/*-**************************************** /*-****************************************
* File functions * File functions
+2 -1
View File
@@ -213,7 +213,8 @@ the last one takes effect.
and disabled when output is stdout. and disabled when output is stdout.
This setting overrides default and can force sparse mode over stdout. This setting overrides default and can force sparse mode over stdout.
* `--rm`: * `--rm`:
remove source file(s) after successful compression or decompression remove source file(s) after successful compression or decompression. If used in combination with
-o, will trigger a confirmation prompt (which can be silenced with -f), as this is a destructive operation.
* `-k`, `--keep`: * `-k`, `--keep`:
keep source file(s) after successful compression or decompression. keep source file(s) after successful compression or decompression.
This is the default behavior. This is the default behavior.
+16
View File
@@ -369,6 +369,22 @@ zstd -d tmp1.zst tmp2.zst -o tmp
touch tmpexists touch tmpexists
zstd tmp1 tmp2 -f -o tmpexists zstd tmp1 tmp2 -f -o tmpexists
zstd tmp1 tmp2 -q -o tmpexists && die "should have refused to overwrite" zstd tmp1 tmp2 -q -o tmpexists && die "should have refused to overwrite"
println gooder > tmp_rm1
println boi > tmp_rm2
println worldly > tmp_rm3
echo 'y' | zstd tmp_rm1 tmp_rm2 -o tmp_rm3.zst --rm # tests the warning prompt for --rm with multiple inputs into once source
test ! -f tmp_rm1
test ! -f tmp_rm2
cp tmp_rm3.zst tmp_rm4.zst
echo 'Y' | zstd -d tmp_rm3.zst tmp_rm4.zst -o tmp_rm_out --rm
test ! -f tmp_rm3.zst
test ! -f tmp_rm4.zst
echo 'yes' | zstd tmp_rm_out tmp_rm3 -c --rm
test ! -f tmp_rm_out
test ! -f tmp_rm3
println gooder > tmpexists1
zstd tmpexists1 tmpexists -c --rm -f
# Bug: PR #972 # Bug: PR #972
if [ "$?" -eq 139 ]; then if [ "$?" -eq 139 ]; then
die "should not have segfaulted" die "should not have segfaulted"