[zstdcli] Refuse to overwrite input file
Compare the input and output files by their inode number and refuse to open the output file if the input file is the same. This doesn't work when (de)compressing multiple files to a single file, but that is a very uncommon use case, mostly used for benchmarking by me. Fixes #1422.
This commit is contained in:
parent
517d8c984c
commit
cd2c8defad
@ -404,7 +404,7 @@ static FILE* FIO_openSrcFile(const char* srcFileName)
|
|||||||
/** FIO_openDstFile() :
|
/** FIO_openDstFile() :
|
||||||
* condition : `dstFileName` must be non-NULL.
|
* condition : `dstFileName` must be non-NULL.
|
||||||
* @result : FILE* to `dstFileName`, or NULL if it fails */
|
* @result : FILE* to `dstFileName`, or NULL if it fails */
|
||||||
static FILE* FIO_openDstFile(const char* dstFileName)
|
static FILE* FIO_openDstFile(const char* srcFileName, const char* dstFileName)
|
||||||
{
|
{
|
||||||
assert(dstFileName != NULL);
|
assert(dstFileName != NULL);
|
||||||
if (!strcmp (dstFileName, stdoutmark)) {
|
if (!strcmp (dstFileName, stdoutmark)) {
|
||||||
@ -416,6 +416,16 @@ static FILE* FIO_openDstFile(const char* dstFileName)
|
|||||||
}
|
}
|
||||||
return stdout;
|
return stdout;
|
||||||
}
|
}
|
||||||
|
if (srcFileName != NULL) {
|
||||||
|
stat_t srcStat;
|
||||||
|
stat_t dstStat;
|
||||||
|
if (UTIL_getFileStat(srcFileName, &srcStat) && UTIL_getFileStat(dstFileName, &dstStat)) {
|
||||||
|
if (srcStat.st_ino == dstStat.st_ino) {
|
||||||
|
DISPLAYLEVEL(1, "zstd: Refusing to open a output file which will overwrite the input file \n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (g_sparseFileSupport == 1) {
|
if (g_sparseFileSupport == 1) {
|
||||||
g_sparseFileSupport = ZSTD_SPARSE_DEFAULT;
|
g_sparseFileSupport = ZSTD_SPARSE_DEFAULT;
|
||||||
@ -1114,7 +1124,7 @@ static int FIO_compressFilename_dstFile(cRess_t ress,
|
|||||||
if (ress.dstFile == NULL) {
|
if (ress.dstFile == NULL) {
|
||||||
closeDstFile = 1;
|
closeDstFile = 1;
|
||||||
DISPLAYLEVEL(6, "FIO_compressFilename_dstFile: opening dst: %s", dstFileName);
|
DISPLAYLEVEL(6, "FIO_compressFilename_dstFile: opening dst: %s", dstFileName);
|
||||||
ress.dstFile = FIO_openDstFile(dstFileName);
|
ress.dstFile = FIO_openDstFile(srcFileName, dstFileName);
|
||||||
if (ress.dstFile==NULL) return 1; /* could not open dstFileName */
|
if (ress.dstFile==NULL) return 1; /* could not open dstFileName */
|
||||||
/* Must only be added after FIO_openDstFile() succeeds.
|
/* Must only be added after FIO_openDstFile() succeeds.
|
||||||
* Otherwise we may delete the destination file if it already exists,
|
* Otherwise we may delete the destination file if it already exists,
|
||||||
@ -1264,7 +1274,7 @@ int FIO_compressMultipleFilenames(const char** inFileNamesTable, unsigned nbFile
|
|||||||
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) */
|
||||||
ress.dstFile = FIO_openDstFile(outFileName);
|
ress.dstFile = FIO_openDstFile(NULL, outFileName);
|
||||||
if (ress.dstFile == NULL) { /* could not open outFileName */
|
if (ress.dstFile == NULL) { /* could not open outFileName */
|
||||||
error = 1;
|
error = 1;
|
||||||
} else {
|
} else {
|
||||||
@ -1880,7 +1890,7 @@ static int FIO_decompressDstFile(dRess_t ress, FILE* srcFile,
|
|||||||
if (ress.dstFile == NULL) {
|
if (ress.dstFile == NULL) {
|
||||||
releaseDstFile = 1;
|
releaseDstFile = 1;
|
||||||
|
|
||||||
ress.dstFile = FIO_openDstFile(dstFileName);
|
ress.dstFile = FIO_openDstFile(srcFileName, dstFileName);
|
||||||
if (ress.dstFile==0) return 1;
|
if (ress.dstFile==0) return 1;
|
||||||
|
|
||||||
/* Must only be added after FIO_openDstFile() succeeds.
|
/* Must only be added after FIO_openDstFile() succeeds.
|
||||||
@ -2057,7 +2067,7 @@ FIO_decompressMultipleFilenames(const char* srcNamesTable[], unsigned nbFiles,
|
|||||||
|
|
||||||
if (outFileName) {
|
if (outFileName) {
|
||||||
unsigned u;
|
unsigned u;
|
||||||
ress.dstFile = FIO_openDstFile(outFileName);
|
ress.dstFile = FIO_openDstFile(NULL, 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++)
|
||||||
error |= FIO_decompressSrcFile(ress, outFileName, srcNamesTable[u]);
|
error |= FIO_decompressSrcFile(ress, outFileName, srcNamesTable[u]);
|
||||||
|
@ -183,6 +183,9 @@ $ECHO "test: --no-progress flag"
|
|||||||
$ZSTD tmpro -c --no-progress | $ZSTD -d -o "$INTOVOID" --no-progress
|
$ZSTD tmpro -c --no-progress | $ZSTD -d -o "$INTOVOID" --no-progress
|
||||||
$ZSTD tmpro -cv --no-progress | $ZSTD -dv -o "$INTOVOID" --no-progress
|
$ZSTD tmpro -cv --no-progress | $ZSTD -dv -o "$INTOVOID" --no-progress
|
||||||
rm -f tmpro tmpro.zst
|
rm -f tmpro tmpro.zst
|
||||||
|
$ECHO "test: overwrite input file (must fail)"
|
||||||
|
$ZSTD tmp -fo tmp && die "zstd overwrote the input file"
|
||||||
|
$ZSTD tmp.zst -dfo tmp.zst && die "zstd overwrote the input file"
|
||||||
|
|
||||||
|
|
||||||
$ECHO "test : file removal"
|
$ECHO "test : file removal"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user