From 64bc441d7d06b267aba52cfdae681a5582d4cfe7 Mon Sep 17 00:00:00 2001 From: Sen Huang Date: Thu, 3 Oct 2019 13:53:04 -0400 Subject: [PATCH] Now constructs final destination path without allocating new table --- programs/fileio.c | 184 +++++++++++++++++++++++++++++++++++---------- programs/fileio.h | 14 ++-- programs/util.c | 93 ----------------------- programs/util.h | 5 -- programs/zstdcli.c | 37 +-------- 5 files changed, 157 insertions(+), 176 deletions(-) diff --git a/programs/fileio.c b/programs/fileio.c index 6006af01b..9988e2d6a 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -628,6 +628,104 @@ static size_t FIO_createDictBuffer(void** bufferPtr, const char* fileName) return (size_t)fileSize; } + + +/* FIO_checkFilenameCollisions() : + * Checks for and warns if there are any files that would have the same output path + */ +int FIO_checkFilenameCollisions(const char** filenameTable, unsigned nbFiles) { + const char** filenameTableSorted; + const char* c, *prevElem; + char* filename; + unsigned u; + + #if defined(_MSC_VER) || defined(__MINGW32__) || defined (__MSVCRT__) /* windows support */ + c = "\\"; + #else + c = "/"; + #endif + + filenameTableSorted = (const char**) malloc(sizeof(char*) * nbFiles); + if (!filenameTableSorted) { + DISPLAY("Unable to malloc new str array, not checking for name collisions\n"); + return 1; + } + + for (u = 0; u < nbFiles; ++u) { + filename = strrchr(filenameTable[u], c[0]); + if (filename == NULL) { + filenameTableSorted[u] = filenameTable[u]; + } else { + filenameTableSorted[u] = filename+1; + } + } + + qsort(filenameTableSorted, nbFiles, sizeof(char*), UTIL_compareStr); + prevElem = filenameTableSorted[0]; + for (u = 1; u < nbFiles; ++u) { + if (strcmp(prevElem, filenameTableSorted[u]) == 0) { + DISPLAY("WARNING: Two files have same filename: %s\n", prevElem); + } + prevElem = filenameTableSorted[u]; + } + + free(filenameTableSorted); + return 0; +} + +/* FIO_determineDstFilenameOutdir() : + * Takes a source file name and specified output directory, and + * allocates memory for and returns a pointer to final path. + * This function never returns an error (it may abort() in case of pb) + */ +static char* +FIO_determineDstFilenameOutdir(const char* srcFilename, const char* outDirName, const size_t suffixLen) +{ + const char* c, *filenameBegin; + char* filename, *result; + size_t finalPathLen; + + #if defined(_MSC_VER) || defined(__MINGW32__) || defined (__MSVCRT__) /* windows support */ + c = "\\"; + #else + c = "/"; + #endif + + finalPathLen = strlen(outDirName); + filenameBegin = strrchr(srcFilename, c[0]); + if (filenameBegin == NULL) { + filename = (char*) malloc((strlen(srcFilename)+1) * sizeof(char)); + if (!filename) { + EXM_THROW(30, "zstd: %s", strerror(errno)); + } + strcpy(filename, srcFilename); + } else { + filename = (char*) malloc((strlen(filenameBegin+1)+1) * sizeof(char)); + if (!filename) { + EXM_THROW(30, "zstd: %s", strerror(errno)); + } + strcpy(filename, filenameBegin+1); + } + + finalPathLen += strlen(filename); + result = (char*) malloc((finalPathLen+suffixLen+30) * sizeof(char)); + if (!result) { + free(filename); + EXM_THROW(30, "zstd: %s", strerror(errno)); + } + + strcpy(result, outDirName); + if (outDirName[strlen(outDirName)-1] == c[0]) { + strcat(result, filename); + } else { + strcat(result, c); + strcat(result, filename); + } + + free(filename); + return result; +} + #ifndef ZSTD_NOCOMPRESS /* ********************************************************************** @@ -1379,19 +1477,25 @@ int FIO_compressFilename(FIO_prefs_t* const prefs, const char* dstFileName, return result; } - /* FIO_determineCompressedName() : * create a destination filename for compressed srcFileName. * @return a pointer to it. * This function never returns an error (it may abort() in case of pb) */ static const char* -FIO_determineCompressedName(const char* srcFileName, const char* suffix) +FIO_determineCompressedName(const char* srcFileName, const char* outDirName, const char* suffix) { static size_t dfnbCapacity = 0; static char* dstFileNameBuffer = NULL; /* using static allocation : this function cannot be multi-threaded */ - size_t const sfnSize = strlen(srcFileName); + char* outDirFilename = NULL; + size_t sfnSize = strlen(srcFileName); size_t const suffixSize = strlen(suffix); + if (outDirName) { + outDirFilename = FIO_determineDstFilenameOutdir(srcFileName, outDirName, suffixSize); + sfnSize = strlen(outDirFilename); + assert(outDirFilename != NULL); + } + if (dfnbCapacity <= sfnSize+suffixSize+1) { /* resize buffer for dstName */ free(dstFileNameBuffer); @@ -1399,9 +1503,16 @@ FIO_determineCompressedName(const char* srcFileName, const char* suffix) dstFileNameBuffer = (char*)malloc(dfnbCapacity); if (!dstFileNameBuffer) { EXM_THROW(30, "zstd: %s", strerror(errno)); - } } + } + } assert(dstFileNameBuffer != NULL); - memcpy(dstFileNameBuffer, srcFileName, sfnSize); + + if (outDirFilename) { + memcpy(dstFileNameBuffer, outDirFilename, sfnSize); + free(outDirFilename); + } else { + memcpy(dstFileNameBuffer, srcFileName, sfnSize); + } memcpy(dstFileNameBuffer+sfnSize, suffix, suffixSize+1 /* Include terminating null */); return dstFileNameBuffer; } @@ -1414,24 +1525,17 @@ FIO_determineCompressedName(const char* srcFileName, const char* suffix) * or into a destination folder (specified with -O) */ int FIO_compressMultipleFilenames(FIO_prefs_t* const prefs, const char** inFileNamesTable, - const char* outDirName, char** dstFileNamesTable, - unsigned nbFiles, const char* outFileName, - const char* suffix, const char* dictFileName, - int compressionLevel, ZSTD_compressionParameters comprParams) + const char* outDirName, unsigned nbFiles, + const char* outFileName, const char* suffix, + const char* dictFileName, int compressionLevel, + ZSTD_compressionParameters comprParams) { int error = 0; cRess_t ress = FIO_createCResources(prefs, dictFileName, compressionLevel, comprParams); /* init */ assert(outFileName != NULL || suffix != NULL); - if (outDirName != NULL) { /* output into a particular folder */ - unsigned u; - for (u = 0; u < nbFiles; ++u) { - const char* const srcFileName = inFileNamesTable[u]; - const char* const dstFileName = FIO_determineCompressedName(dstFileNamesTable[u], suffix); - error |= FIO_compressFilename_srcFile(prefs, ress, dstFileName, srcFileName, compressionLevel); - } - } else if (outFileName != NULL) { /* output into a single destination (stdout typically) */ + if (outFileName != NULL) { /* output into a single destination (stdout typically) */ ress.dstFile = FIO_openDstFile(prefs, NULL, outFileName); if (ress.dstFile == NULL) { /* could not open outFileName */ error = 1; @@ -1448,9 +1552,11 @@ int FIO_compressMultipleFilenames(FIO_prefs_t* const prefs, const char** inFileN unsigned u; for (u=0; u= 1 */ - char** dstFilenameTable; unsigned filenameIdx = 0; const char* programName = argv[0]; const char* outFileName = NULL; @@ -1175,26 +1174,10 @@ int main(int argCount, const char* argv[]) if (adaptMin > cLevel) cLevel = adaptMin; if (adaptMax < cLevel) cLevel = adaptMax; - if (outDirName) { - if (UTIL_isDirectory(outDirName)) { - DISPLAY("Output of files will be in directory: %s\n", outDirName); - dstFilenameTable = (char**)malloc(filenameIdx * sizeof(char*)); - UTIL_createDestinationDirTable(dstFilenameTable, filenameTable, filenameIdx, outDirName); - } else { - DISPLAY("%s is not a directory!\n", outDirName); - CLEAN_RETURN(1); - } - } else { - dstFilenameTable = NULL; - } - if ((filenameIdx==1) && outFileName) operationResult = FIO_compressFilename(prefs, outFileName, filenameTable[0], dictFileName, cLevel, compressionParams); else - operationResult = FIO_compressMultipleFilenames(prefs, filenameTable, outDirName, dstFilenameTable, filenameIdx, outFileName, suffix, dictFileName, cLevel, compressionParams); - - if (dstFilenameTable) - UTIL_freeDestinationFilenameTable(dstFilenameTable, filenameIdx); + operationResult = FIO_compressMultipleFilenames(prefs, filenameTable, outDirName, filenameIdx, outFileName, suffix, dictFileName, cLevel, compressionParams); #else (void)suffix; (void)adapt; (void)rsyncable; (void)ultra; (void)cLevel; (void)ldmFlag; (void)literalCompressionMode; (void)targetCBlockSize; (void)streamSrcSize; (void)srcSizeHint; /* not used when ZSTD_NOCOMPRESS set */ DISPLAY("Compression not supported \n"); @@ -1209,26 +1192,10 @@ int main(int argCount, const char* argv[]) } } FIO_setMemLimit(prefs, memLimit); - - if (outDirName) { - if (UTIL_isDirectory(outDirName)) { - DISPLAY("Output of files will be in directory: %s\n", outDirName); - dstFilenameTable = (char**)malloc(filenameIdx * sizeof(char*)); - UTIL_createDestinationDirTable(dstFilenameTable, filenameTable, filenameIdx, outDirName); - } else { - DISPLAY("%s is not a directory!\n", outDirName); - CLEAN_RETURN(1); - } - } else { - dstFilenameTable = NULL; - } - if (filenameIdx==1 && outFileName) operationResult = FIO_decompressFilename(prefs, outFileName, filenameTable[0], dictFileName); else - operationResult = FIO_decompressMultipleFilenames(prefs, filenameTable, filenameIdx, outDirName, dstFilenameTable, outFileName, dictFileName); - if (dstFilenameTable) - UTIL_freeDestinationFilenameTable(dstFilenameTable, filenameIdx); + operationResult = FIO_decompressMultipleFilenames(prefs, filenameTable, filenameIdx, outDirName, outFileName, dictFileName); #else DISPLAY("Decompression not supported \n"); #endif