Merge pull request #650 from iburinoc/ro-overwrite

Make zstd overwrite destination files even when it is read only
This commit is contained in:
Yann Collet 2017-04-07 06:09:25 -07:00 committed by GitHub
commit 97b23a98d9
2 changed files with 43 additions and 12 deletions

View File

@ -31,6 +31,11 @@
#include <time.h> /* clock */ #include <time.h> /* clock */
#include <errno.h> /* errno */ #include <errno.h> /* errno */
#if defined (_MSC_VER)
# include <sys/stat.h>
# include <io.h>
#endif
#include "mem.h" #include "mem.h"
#include "fileio.h" #include "fileio.h"
#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_magicNumber, ZSTD_frameHeaderSize_max */ #define ZSTD_STATIC_LINKING_ONLY /* ZSTD_magicNumber, ZSTD_frameHeaderSize_max */
@ -188,6 +193,18 @@ void FIO_setOverlapLog(unsigned overlapLog){
/*-************************************* /*-*************************************
* Functions * Functions
***************************************/ ***************************************/
/** FIO_remove() :
* @result : Unlink `fileName`, even if it's read-only */
static int FIO_remove(const char* path)
{
#if defined(_WIN32) || defined(WIN32)
/* windows doesn't allow remove read-only files, so try to make it
* writable first */
chmod(path, _S_IWRITE);
#endif
return remove(path);
}
/** FIO_openSrcFile() : /** FIO_openSrcFile() :
* 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 */
@ -230,10 +247,11 @@ static FILE* FIO_openDstFile(const char* dstFileName)
if (g_sparseFileSupport == 1) { if (g_sparseFileSupport == 1) {
g_sparseFileSupport = ZSTD_SPARSE_DEFAULT; g_sparseFileSupport = ZSTD_SPARSE_DEFAULT;
} }
if (!g_overwrite && strcmp (dstFileName, nulmark)) { /* Check if destination file already exists */ if (strcmp (dstFileName, nulmark)) { /* Check if destination file already exists */
f = fopen( dstFileName, "rb" ); f = fopen( dstFileName, "rb" );
if (f != 0) { /* dest file exists, prompt for overwrite authorization */ if (f != 0) { /* dest file exists, prompt for overwrite authorization */
fclose(f); fclose(f);
if (!g_overwrite) {
if (g_displayLevel <= 1) { if (g_displayLevel <= 1) {
/* No interaction possible */ /* No interaction possible */
DISPLAY("zstd: %s already exists; not overwritten \n", dstFileName); DISPLAY("zstd: %s already exists; not overwritten \n", dstFileName);
@ -246,7 +264,12 @@ static FILE* FIO_openDstFile(const char* dstFileName)
return NULL; return NULL;
} }
while ((ch!=EOF) && (ch!='\n')) ch = getchar(); /* flush rest of input line */ while ((ch!=EOF) && (ch!='\n')) ch = getchar(); /* flush rest of input line */
} } } }
}
/* need to unlink */
FIO_remove(dstFileName);
} }
f = fopen( dstFileName, "wb" ); f = fopen( dstFileName, "wb" );
if (f==NULL) DISPLAYLEVEL(1, "zstd: %s: %s\n", dstFileName, strerror(errno)); if (f==NULL) DISPLAYLEVEL(1, "zstd: %s: %s\n", dstFileName, strerror(errno));
} }

View File

@ -109,6 +109,14 @@ $ZSTD -q tmp && die "overwrite check failed!"
$ECHO "test : force overwrite" $ECHO "test : force overwrite"
$ZSTD -q -f tmp $ZSTD -q -f tmp
$ZSTD -q --force tmp $ZSTD -q --force tmp
$ECHO "test : overwrite readonly file"
rm -f tmpro tmpro.zst
$ECHO foo > tmpro.zst
$ECHO foo > tmpro
chmod 400 tmpro.zst
$ZSTD -q tmpro && die "should have refused to overwrite read-only file"
$ZSTD -q -f tmpro
rm -f tmpro tmpro.zst
$ECHO "test : file removal" $ECHO "test : file removal"
$ZSTD -f --rm tmp $ZSTD -f --rm tmp
ls tmp && die "tmp should no longer be present" ls tmp && die "tmp should no longer be present"