diff --git a/programs/fileio.c b/programs/fileio.c index 7666b0725..d4aea1591 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -270,9 +270,9 @@ void FIO_addAbortHandler() static FIO_compressionType_t g_compressionType = FIO_zstdCompression; void FIO_setCompressionType(FIO_compressionType_t compressionType) { g_compressionType = compressionType; } static U32 g_overwrite = 0; -void FIO_overwriteMode(void) { g_overwrite=1; } -static U32 g_sparseFileSupport = 1; /* 0: no sparse allowed; 1: auto (file yes, stdout no); 2: force sparse */ -void FIO_setSparseWrite(unsigned sparse) { g_sparseFileSupport=sparse; } +void FIO_overwriteMode(void) { g_overwrite = 1; } +static U32 g_sparseFileSupport = ZSTD_SPARSE_DEFAULT; /* 0: no sparse allowed; 1: auto (file yes, stdout no); 2: force sparse */ +void FIO_setSparseWrite(unsigned sparse) { g_sparseFileSupport = sparse; } static U32 g_dictIDFlag = 1; void FIO_setDictIDFlag(unsigned dictIDFlag) { g_dictIDFlag = dictIDFlag; } static U32 g_checksumFlag = 1; @@ -416,23 +416,23 @@ static FILE* FIO_openDstFile(const char* srcFileName, const char* dstFileName) if (!strcmp (dstFileName, stdoutmark)) { DISPLAYLEVEL(4,"Using stdout for output \n"); SET_BINARY_MODE(stdout); - if (g_sparseFileSupport==1) { + if (g_sparseFileSupport == 1) { g_sparseFileSupport = 0; DISPLAYLEVEL(4, "Sparse File Support is automatically disabled on stdout ; try --sparse \n"); } return stdout; } + if (srcFileName != NULL) { stat_t srcStat; stat_t dstStat; if ( UTIL_getFileStat(srcFileName, &srcStat) - && UTIL_getFileStat(dstFileName, &dstStat) - && srcStat.st_dev == dstStat.st_dev - && srcStat.st_ino == dstStat.st_ino ) { - DISPLAYLEVEL(1, "zstd: Refusing to open a output file which will overwrite the input file \n"); - return NULL; - } - } + && UTIL_getFileStat(dstFileName, &dstStat) ) { + if ( srcStat.st_dev == dstStat.st_dev + && 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) { g_sparseFileSupport = ZSTD_SPARSE_DEFAULT; @@ -1440,12 +1440,14 @@ static unsigned FIO_fwriteSparse(FILE* file, const void* buffer, size_t bufferSi static void FIO_fwriteSparseEnd(FILE* file, unsigned storedSkips) { - if (storedSkips-->0) { /* implies g_sparseFileSupport>0 */ - int const seekResult = LONG_SEEK(file, storedSkips, SEEK_CUR); - if (seekResult != 0) EXM_THROW(69, "Final skip error (sparse file)"); + if (storedSkips>0) { + assert(g_sparseFileSupport > 0); /* storedSkips>0 implies sparse support is enabled */ + if (LONG_SEEK(file, storedSkips-1, SEEK_CUR) != 0) + EXM_THROW(69, "Final skip error (sparse file support)"); + /* last zero must be explicitly written, + * so that skipped ones get implicitly translated as zero by FS */ { const char lastZeroByte[1] = { 0 }; - size_t const sizeCheck = fwrite(lastZeroByte, 1, 1, file); - if (sizeCheck != 1) + if (fwrite(lastZeroByte, 1, 1, file) != 1) EXM_THROW(69, "Write error : cannot write last zero"); } } } diff --git a/programs/util.c b/programs/util.c index 4ef988c26..00fc4fe2c 100644 --- a/programs/util.c +++ b/programs/util.c @@ -18,6 +18,7 @@ extern "C" { ******************************************/ #include /* strncmp */ #include +#include #include "util.h" @@ -175,21 +176,23 @@ int UTIL_prepareFileList(const char *dirName, char** bufStart, size_t* pos, char pathLength = dirLength+1+fnameLength; path[pathLength] = 0; if (cFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - if (strcmp (cFile.cFileName, "..") == 0 || - strcmp (cFile.cFileName, ".") == 0) continue; - - nbFiles += UTIL_prepareFileList(path, bufStart, pos, bufEnd, followLinks); /* Recursively call "UTIL_prepareFileList" with the new path. */ + if ( strcmp (cFile.cFileName, "..") == 0 + || strcmp (cFile.cFileName, ".") == 0 ) + continue; + /* Recursively call "UTIL_prepareFileList" with the new path. */ + nbFiles += UTIL_prepareFileList(path, bufStart, pos, bufEnd, followLinks); if (*bufStart == NULL) { free(path); FindClose(hFile); return 0; } - } - else if ((cFile.dwFileAttributes & FILE_ATTRIBUTE_NORMAL) || (cFile.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) || (cFile.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED)) { + } else if ( (cFile.dwFileAttributes & FILE_ATTRIBUTE_NORMAL) + || (cFile.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) + || (cFile.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED) ) { if (*bufStart + *pos + pathLength >= *bufEnd) { - ptrdiff_t newListSize = (*bufEnd - *bufStart) + LIST_SIZE_INCREASE; + ptrdiff_t const newListSize = (*bufEnd - *bufStart) + LIST_SIZE_INCREASE; *bufStart = (char*)UTIL_realloc(*bufStart, newListSize); - *bufEnd = *bufStart + newListSize; if (*bufStart == NULL) { free(path); FindClose(hFile); return 0; } + *bufEnd = *bufStart + newListSize; } if (*bufStart + *pos + pathLength < *bufEnd) { - strncpy(*bufStart + *pos, path, *bufEnd - (*bufStart + *pos)); + memcpy(*bufStart + *pos, path, pathLength+1 /* include final \0 */); *pos += pathLength + 1; nbFiles++; } @@ -246,7 +249,7 @@ int UTIL_prepareFileList(const char *dirName, char** bufStart, size_t* pos, char if (*bufStart == NULL) { free(path); closedir(dir); return 0; } } if (*bufStart + *pos + pathLength < *bufEnd) { - strncpy(*bufStart + *pos, path, *bufEnd - (*bufStart + *pos)); + memcpy(*bufStart + *pos, path, pathLength + 1); /* with final \0 */ *pos += pathLength + 1; nbFiles++; } @@ -304,7 +307,7 @@ UTIL_createFileList(const char **inputNames, unsigned inputNamesNb, if (!buf) return NULL; } if (buf + pos + len < bufend) { - strncpy(buf + pos, inputNames[i], bufend - (buf + pos)); + memcpy(buf+pos, inputNames[i], len+1); /* with final \0 */ pos += len + 1; nbFiles++; } @@ -336,6 +339,7 @@ UTIL_createFileList(const char **inputNames, unsigned inputNamesNb, ******************************************/ int g_utilDisplayLevel; + /*-**************************************** * Time functions ******************************************/ @@ -354,6 +358,7 @@ U64 UTIL_getSpanTimeMicro(UTIL_time_t clockStart, UTIL_time_t clockEnd) } return 1000000ULL*(clockEnd.QuadPart - clockStart.QuadPart)/ticksPerSecond.QuadPart; } + U64 UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd) { static LARGE_INTEGER ticksPerSecond; @@ -367,7 +372,9 @@ U64 UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd) } #elif defined(__APPLE__) && defined(__MACH__) + UTIL_time_t UTIL_getTime(void) { return mach_absolute_time(); } + U64 UTIL_getSpanTimeMicro(UTIL_time_t clockStart, UTIL_time_t clockEnd) { static mach_timebase_info_data_t rate; @@ -436,11 +443,13 @@ U64 UTIL_getSpanTimeNano(UTIL_time_t begin, UTIL_time_t end) } #else /* relies on standard C (note : clock_t measurements can be wrong when using multi-threading) */ + typedef clock_t UTIL_time_t; #define UTIL_TIME_INITIALIZER 0 UTIL_time_t UTIL_getTime(void) { return clock(); } U64 UTIL_getSpanTimeMicro(UTIL_time_t clockStart, UTIL_time_t clockEnd) { return 1000000ULL * (clockEnd - clockStart) / CLOCKS_PER_SEC; } U64 UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd) { return 1000000000ULL * (clockEnd - clockStart) / CLOCKS_PER_SEC; } + #endif /* returns time span in microseconds */ diff --git a/tests/playTests.sh b/tests/playTests.sh index fc45ef5ec..94a70458c 100755 --- a/tests/playTests.sh +++ b/tests/playTests.sh @@ -184,9 +184,9 @@ $ZSTD tmpro -c --no-progress | $ZSTD -d -o "$INTOVOID" --no-progress $ZSTD tmpro -cv --no-progress | $ZSTD -dv -o "$INTOVOID" --no-progress 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: properly detect input file does not exist" +$ZSTD tmp -fo tmp && die "zstd compression overwrote the input file" +$ZSTD tmp.zst -dfo tmp.zst && die "zstd decompression overwrote the input file" +$ECHO "test: detect that input file does not exist" $ZSTD nothere && die "zstd hasn't detected that input file does not exist" $ECHO "test : file removal"