zstd -d -f do no longer erase destination file

when source file does not exist (#1082)
This commit is contained in:
Yann Collet 2018-10-01 14:04:00 -07:00
parent 1ab71a8e72
commit c7bd6a41ab
2 changed files with 77 additions and 63 deletions

View File

@ -1792,11 +1792,72 @@ static int FIO_decompressFrames(dRess_t ress, FILE* srcFile,
return 0; return 0;
} }
/** FIO_decompressDstFile() :
open `dstFileName`,
or path-through if ress.dstFile is already != 0,
then start decompression process (FIO_decompressFrames()).
@return : 0 : OK
1 : operation aborted
*/
static int FIO_decompressDstFile(dRess_t ress, FILE* srcFile,
const char* dstFileName, const char* srcFileName)
{
int result;
stat_t statbuf;
int transfer_permissions = 0;
int releaseDstFile = 0;
if (ress.dstFile == NULL) {
releaseDstFile = 1;
ress.dstFile = FIO_openDstFile(dstFileName);
if (ress.dstFile==0) return 1;
/* Must only be added after FIO_openDstFile() succeeds.
* Otherwise we may delete the destination file if it already exists,
* and the user presses Ctrl-C when asked if they wish to overwrite.
*/
addHandler(dstFileName);
if ( strcmp(srcFileName, stdinmark) /* special case : don't transfer permissions from stdin */
&& UTIL_getFileStat(srcFileName, &statbuf) )
transfer_permissions = 1;
}
result = FIO_decompressFrames(ress, srcFile, dstFileName, srcFileName);
if (releaseDstFile) {
FILE* const dstFile = ress.dstFile;
clearHandler();
ress.dstFile = NULL;
if (fclose(dstFile)) {
DISPLAYLEVEL(1, "zstd: %s: %s \n", dstFileName, strerror(errno));
result = 1;
}
if ( (result != 0) /* operation failure */
&& strcmp(dstFileName, nulmark) /* special case : don't remove() /dev/null (#316) */
&& strcmp(dstFileName, stdoutmark) /* special case : don't remove() stdout */
) {
FIO_remove(dstFileName); /* remove decompression artefact; note: don't do anything special if remove() fails */
} else { /* operation success */
if ( strcmp(dstFileName, stdoutmark) /* special case : don't chmod stdout */
&& strcmp(dstFileName, nulmark) /* special case : don't chmod /dev/null */
&& transfer_permissions ) /* file permissions correctly extracted from src */
UTIL_setFileStat(dstFileName, &statbuf); /* transfer file permissions from src into dst */
}
signal(SIGINT, SIG_DFL);
}
return result;
}
/** FIO_decompressSrcFile() : /** FIO_decompressSrcFile() :
Decompression `srcFileName` into `ress.dstFile` Open `srcFileName`, transfer control to decompressDstFile()
@return : 0 : OK @return : 0 : OK
1 : operation not started 1 : error
*/ */
static int FIO_decompressSrcFile(dRess_t ress, const char* dstFileName, const char* srcFileName) static int FIO_decompressSrcFile(dRess_t ress, const char* dstFileName, const char* srcFileName)
{ {
@ -1812,7 +1873,7 @@ static int FIO_decompressSrcFile(dRess_t ress, const char* dstFileName, const ch
if (srcFile==NULL) return 1; if (srcFile==NULL) return 1;
ress.srcBufferLoaded = 0; ress.srcBufferLoaded = 0;
result = FIO_decompressFrames(ress, srcFile, dstFileName, srcFileName); result = FIO_decompressDstFile(ress, srcFile, dstFileName, srcFileName);
/* Close file */ /* Close file */
if (fclose(srcFile)) { if (fclose(srcFile)) {
@ -1835,60 +1896,13 @@ static int FIO_decompressSrcFile(dRess_t ress, const char* dstFileName, const ch
} }
/** FIO_decompressFile_extRess() :
decompress `srcFileName` into `dstFileName`
@return : 0 : OK
1 : operation aborted (src not available, dst already taken, etc.)
*/
static int FIO_decompressDstFile(dRess_t ress,
const char* dstFileName, const char* srcFileName)
{
int result;
stat_t statbuf;
int stat_result = 0;
ress.dstFile = FIO_openDstFile(dstFileName);
if (ress.dstFile==0) return 1;
/* Must ony be added after FIO_openDstFile() succeeds.
* Otherwise we may delete the destination file if at already exists, and
* the user presses Ctrl-C when asked if they wish to overwrite.
*/
addHandler(dstFileName);
if ( strcmp(srcFileName, stdinmark)
&& UTIL_getFileStat(srcFileName, &statbuf) )
stat_result = 1;
result = FIO_decompressSrcFile(ress, dstFileName, srcFileName);
clearHandler();
if (fclose(ress.dstFile)) {
DISPLAYLEVEL(1, "zstd: %s: %s \n", dstFileName, strerror(errno));
result = 1;
}
if ( (result != 0) /* operation failure */
&& strcmp(dstFileName, nulmark) /* special case : don't remove() /dev/null (#316) */
&& strcmp(dstFileName, stdoutmark) ) /* special case : don't remove() stdout */
FIO_remove(dstFileName); /* remove decompression artefact; note don't do anything special if remove() fails */
else { /* operation success */
if ( strcmp(dstFileName, stdoutmark) /* special case : don't chmod stdout */
&& strcmp(dstFileName, nulmark) /* special case : don't chmod /dev/null */
&& stat_result ) /* file permissions correctly extracted from src */
UTIL_setFileStat(dstFileName, &statbuf); /* transfer file permissions from src into dst */
}
signal(SIGINT, SIG_DFL);
return result;
}
int FIO_decompressFilename(const char* dstFileName, const char* srcFileName, int FIO_decompressFilename(const char* dstFileName, const char* srcFileName,
const char* dictFileName) const char* dictFileName)
{ {
dRess_t const ress = FIO_createDResources(dictFileName); dRess_t const ress = FIO_createDResources(dictFileName);
int const decodingError = FIO_decompressDstFile(ress, dstFileName, srcFileName); int const decodingError = FIO_decompressSrcFile(ress, dstFileName, srcFileName);
FIO_freeDResources(ress); FIO_freeDResources(ress);
return decodingError; return decodingError;
@ -1963,12 +1977,12 @@ FIO_determineDstName(const char* srcFileName)
} }
int FIO_decompressMultipleFilenames(const char** srcNamesTable, unsigned nbFiles, int
FIO_decompressMultipleFilenames(const char* srcNamesTable[], unsigned nbFiles,
const char* outFileName, const char* outFileName,
const char* dictFileName) const char* dictFileName)
{ {
int skippedFiles = 0; int error = 0;
int missingFiles = 0;
dRess_t ress = FIO_createDResources(dictFileName); dRess_t ress = FIO_createDResources(dictFileName);
if (outFileName) { if (outFileName) {
@ -1976,7 +1990,7 @@ int FIO_decompressMultipleFilenames(const char** srcNamesTable, unsigned nbFiles
ress.dstFile = FIO_openDstFile(outFileName); ress.dstFile = FIO_openDstFile(outFileName);
if (ress.dstFile == 0) EXM_THROW(71, "cannot open %s", outFileName); if (ress.dstFile == 0) EXM_THROW(71, "cannot open %s", outFileName);
for (u=0; u<nbFiles; u++) for (u=0; u<nbFiles; u++)
missingFiles += FIO_decompressSrcFile(ress, outFileName, srcNamesTable[u]); error |= FIO_decompressSrcFile(ress, outFileName, srcNamesTable[u]);
if (fclose(ress.dstFile)) if (fclose(ress.dstFile))
EXM_THROW(72, "Write error : cannot properly close output file"); EXM_THROW(72, "Write error : cannot properly close output file");
} else { } else {
@ -1984,14 +1998,14 @@ int FIO_decompressMultipleFilenames(const char** srcNamesTable, unsigned nbFiles
for (u=0; u<nbFiles; u++) { /* create dstFileName */ for (u=0; u<nbFiles; u++) { /* create dstFileName */
const char* const srcFileName = srcNamesTable[u]; const char* const srcFileName = srcNamesTable[u];
const char* const dstFileName = FIO_determineDstName(srcFileName); const char* const dstFileName = FIO_determineDstName(srcFileName);
if (dstFileName == NULL) { skippedFiles++; continue; } if (dstFileName == NULL) { error=1; continue; }
missingFiles += FIO_decompressDstFile(ress, dstFileName, srcFileName); error |= FIO_decompressSrcFile(ress, dstFileName, srcFileName);
} }
} }
FIO_freeDResources(ress); FIO_freeDResources(ress);
return missingFiles + skippedFiles; return error;
} }

View File

@ -201,7 +201,7 @@ test ! -f tmp.zst # tmp.zst should not be created
$ECHO "test : do not delete destination when source is not present" $ECHO "test : do not delete destination when source is not present"
touch tmp # create destination file touch tmp # create destination file
$ZSTD -d -f tmp.zst && die "attempt to decompress a non existing file" $ZSTD -d -f tmp.zst && die "attempt to decompress a non existing file"
! test -f tmp # destination file should still be present (test disabled temporarily) test -f tmp # destination file should still be present (test disabled temporarily)
rm tmp* rm tmp*