diff options
author | Yann Collet <Cyan4973@users.noreply.github.com> | 2022-07-01 16:40:33 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-07-01 16:40:33 (GMT) |
commit | ea3eef071ffaff5831fe7c99496a3db94a7ab5bb (patch) | |
tree | 8103fc0c693c3f209508d49b3292bd6234b36f26 | |
parent | 4ebe313e00aa52c837ee029ede39a0503a8a39c9 (diff) | |
parent | 49e63cd52202b1bbda2dc97309eb2e25a3677983 (diff) | |
download | lz4-ea3eef071ffaff5831fe7c99496a3db94a7ab5bb.zip lz4-ea3eef071ffaff5831fe7c99496a3db94a7ab5bb.tar.gz lz4-ea3eef071ffaff5831fe7c99496a3db94a7ab5bb.tar.bz2 |
Merge pull request #1098 from lz4/blockDeviceTest
Block device compression
-rw-r--r-- | .github/workflows/ci.yml | 16 | ||||
-rw-r--r-- | programs/lz4cli.c | 72 | ||||
-rw-r--r-- | programs/lz4io.c | 242 | ||||
-rw-r--r-- | programs/util.h | 50 | ||||
-rw-r--r-- | tests/Makefile | 14 |
5 files changed, 217 insertions, 177 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 33319ce..9e9c790 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -250,7 +250,6 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 # https://github.com/actions/checkout - - name: custom LZ4_DISTANCE_MAX; test LZ4_USER_MEMORY_FUNCTIONS run: | MOREFLAGS='-DLZ4_DISTANCE_MAX=8000' make V=1 check @@ -261,6 +260,21 @@ jobs: make V=1 clean CC="c++ -Wno-deprecated" make V=1 -C tests fullbench-wmalloc # stricter function signature check + # test block device compression #1086 + lz4cli-block-device: + name: Test lz4 compression on a block device + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 # https://github.com/actions/checkout + - name: create a block device, compress it with lz4 # alternative : blindly use /dev/loop0, seems to always exist + run: | + make lz4 + dd if=/dev/zero of=full0.img bs=2M count=1 + BLOCK_DEVICE=$(sudo losetup --show -fP full0.img) + sudo chmod 666 $BLOCK_DEVICE + ./lz4 -v $BLOCK_DEVICE -c > /dev/null + sudo losetup -d $BLOCK_DEVICE + rm full0.img ############################################################### diff --git a/programs/lz4cli.c b/programs/lz4cli.c index b5cb000..254a6ce 100644 --- a/programs/lz4cli.c +++ b/programs/lz4cli.c @@ -314,6 +314,7 @@ int main(int argc, const char** argv) cLevelLast=-10000, legacy_format=0, forceStdout=0, + forceOverwrite=0, main_pause=0, multiple_inputs=0, all_arguments_are_files=0, @@ -330,9 +331,8 @@ int main(int argc, const char** argv) const char extension[] = LZ4_EXTENSION; size_t blockSize = LZ4IO_setBlockSizeID(prefs, LZ4_BLOCKSIZEID_DEFAULT); const char* const exeName = lastNameFromPath(argv[0]); -#ifdef UTIL_HAS_CREATEFILELIST - const char** extendedFileList = NULL; char* fileNamesBuf = NULL; +#ifdef UTIL_HAS_CREATEFILELIST unsigned fileNamesNb, recursive=0; #endif @@ -491,7 +491,7 @@ int main(int argc, const char** argv) case 't': mode = om_test; break; /* Overwrite */ - case 'f': LZ4IO_setOverwrite(prefs, 1); break; + case 'f': forceOverwrite=1; LZ4IO_setOverwrite(prefs, 1); break; /* Verbose mode */ case 'v': displayLevel++; break; @@ -581,20 +581,24 @@ int main(int argc, const char** argv) } /* Store in *inFileNames[] if -m is used. */ - if (multiple_inputs) { inFileNames[ifnIdx++]=argument; continue; } + if (multiple_inputs) { inFileNames[ifnIdx++] = argument; continue; } - /* Store first non-option arg in input_filename to preserve original cli logic. */ - if (!input_filename) { input_filename=argument; continue; } + /* original cli logic : lz4 input output */ + /* First non-option arg is input_filename. */ + if (!input_filename) { input_filename = argument; continue; } - /* Second non-option arg in output_filename to preserve original cli logic. */ + /* Second non-option arg is output_filename */ if (!output_filename) { - output_filename=argument; + output_filename = argument; if (!strcmp (output_filename, nullOutput)) output_filename = nulmark; continue; } - /* 3rd non-option arg should not exist */ - DISPLAYLEVEL(1, "Warning : %s won't be used ! Do you want multiple input files (-m) ? \n", argument); + /* 3rd+ non-option arg should not exist */ + DISPLAYLEVEL(1, "%s : %s won't be used ! Do you want multiple input files (-m) ? \n", + forceOverwrite ? "Warning" : "Error", + argument); + if (!forceOverwrite) exit(1); } DISPLAYLEVEL(3, WELCOME_MESSAGE); @@ -617,7 +621,7 @@ int main(int argc, const char** argv) input_filename = inFileNames[0]; #ifdef UTIL_HAS_CREATEFILELIST if (recursive) { /* at this stage, filenameTable is a list of paths, which can contain both files and directories */ - extendedFileList = UTIL_createFileList(inFileNames, ifnIdx, &fileNamesBuf, &fileNamesNb); + const char** extendedFileList = UTIL_createFileList(inFileNames, ifnIdx, &fileNamesBuf, &fileNamesNb); if (extendedFileList) { unsigned u; for (u=0; u<fileNamesNb; u++) DISPLAYLEVEL(4, "%u %s\n", u, extendedFileList[u]); @@ -649,27 +653,19 @@ int main(int argc, const char** argv) mode = om_decompress; /* defer to decompress */ } - /* compress or decompress */ + /* No input provided => use stdin */ if (!input_filename) input_filename = stdinmark; - /* Check if input is defined as console; trigger an error in this case */ + + /* Refuse to use the console as input */ if (!strcmp(input_filename, stdinmark) && IS_CONSOLE(stdin) ) { DISPLAYLEVEL(1, "refusing to read from a console\n"); exit(1); } + if (!strcmp(input_filename, stdinmark)) { /* if input==stdin and no output defined, stdout becomes default output */ if (!output_filename) output_filename = stdoutmark; } - else{ -#ifdef UTIL_HAS_CREATEFILELIST - if (!recursive && !UTIL_isRegFile(input_filename)) { -#else - if (!UTIL_isRegFile(input_filename)) { -#endif - DISPLAYLEVEL(1, "%s: is not a regular file \n", input_filename); - exit(1); - } - } /* No output filename ==> try to select one automatically (when possible) */ while ((!output_filename) && (multiple_inputs==0)) { @@ -679,7 +675,7 @@ int main(int argc, const char** argv) * To ensure `stdout` is explicitly selected, use `-c` command flag. * Conversely, to ensure output will not become `stdout`, use `-m` command flag */ DISPLAYLEVEL(1, "Warning : using stdout as default output. Do not rely on this behavior: use explicit `-c` instead ! \n"); - output_filename=stdoutmark; + output_filename = stdoutmark; break; } if (mode == om_auto) { /* auto-determine compression or decompression, based on file extension */ @@ -695,7 +691,7 @@ int main(int argc, const char** argv) DISPLAYLEVEL(2, "Compressed filename will be : %s \n", output_filename); break; } - if (mode == om_decompress) {/* decompression to file (automatic name will work only if input filename has correct format extension) */ + if (mode == om_decompress) {/* decompress to file (automatic output name only works if input filename has correct format extension) */ size_t outl; size_t const inl = strlen(input_filename); dynNameSpace = (char*)calloc(1,inl+1); @@ -704,20 +700,17 @@ int main(int argc, const char** argv) outl = inl; if (inl>4) while ((outl >= inl-4) && (input_filename[outl] == extension[outl-inl+4])) dynNameSpace[outl--]=0; - if (outl != inl-5) { DISPLAYLEVEL(1, "Cannot determine an output filename\n"); badusage(exeName); } + if (outl != inl-5) { DISPLAYLEVEL(1, "Cannot determine an output filename \n"); badusage(exeName); } output_filename = dynNameSpace; DISPLAYLEVEL(2, "Decoding file %s \n", output_filename); } break; } - if (mode == om_list){ - if(!multiple_inputs){ - inFileNames[ifnIdx++] = input_filename; - } - } - else{ - if (multiple_inputs==0) assert(output_filename); + if (mode == om_list) { + if (!multiple_inputs) inFileNames[ifnIdx++] = input_filename; + } else { + if (!multiple_inputs) assert(output_filename != NULL); } /* when multiple_inputs==1, output_filename may simply be useless, * however, output_filename must be !NULL for next strcmp() tests */ @@ -745,8 +738,10 @@ int main(int argc, const char** argv) if (ifnIdx == 0) multiple_inputs = 0; if (mode == om_decompress) { if (multiple_inputs) { - const char* const dec_extension = !strcmp(output_filename,stdoutmark) ? stdoutmark : LZ4_EXTENSION; - assert(ifnIdx <= INT_MAX); + const char* dec_extension = LZ4_EXTENSION; + if (!strcmp(output_filename, stdoutmark)) dec_extension = stdoutmark; + if (!strcmp(output_filename, nulmark)) dec_extension = nulmark; + assert(ifnIdx < INT_MAX); operationResult = LZ4IO_decompressMultipleFilenames(inFileNames, (int)ifnIdx, dec_extension, prefs); } else { operationResult = DEFAULT_DECOMPRESSOR(input_filename, output_filename, prefs); @@ -774,12 +769,7 @@ int main(int argc, const char** argv) _cleanup: if (main_pause) waitEnter(); free(dynNameSpace); -#ifdef UTIL_HAS_CREATEFILELIST - if (extendedFileList) { - UTIL_freeFileList(extendedFileList, fileNamesBuf); - inFileNames = NULL; - } -#endif + free(fileNamesBuf); LZ4IO_freePreferences(prefs); free((void*)inFileNames); return operationResult; diff --git a/programs/lz4io.c b/programs/lz4io.c index 6f636b5..36736c2 100644 --- a/programs/lz4io.c +++ b/programs/lz4io.c @@ -103,29 +103,9 @@ static int g_displayLevel = 0; /* 0 : no display ; 1: errors ; 2 : + result } } static const clock_t refreshRate = CLOCKS_PER_SEC / 6; static clock_t g_time = 0; -#define LZ4IO_STATIC_ASSERT(c) { enum { LZ4IO_static_assert = 1/(int)(!!(c)) }; } /* use after variable declarations */ - -/************************************** -* Local Parameters -**************************************/ +#define LZ4IO_STATIC_ASSERT(c) { enum { LZ4IO_static_assert = 1/(int)(!!(c)) }; } /* use after variable declarations */ -struct LZ4IO_prefs_s { - int passThrough; - int overwrite; - int testMode; - int blockSizeId; - size_t blockSize; - int blockChecksum; - int streamChecksum; - int blockIndependence; - int sparseFileSupport; - int contentSizeFlag; - int useDictionary; - unsigned favorDecSpeed; - const char* dictionaryFilename; - int removeSrcFile; -}; /************************************** * Exceptions @@ -134,7 +114,7 @@ struct LZ4IO_prefs_s { # define DEBUG 0 #endif #define DEBUGOUTPUT(...) if (DEBUG) DISPLAY(__VA_ARGS__); -#define EXM_THROW(error, ...) \ +#define END_PROCESS(error, ...) \ { \ DEBUGOUTPUT("Error defined at %s, line %i : \n", __FILE__, __LINE__); \ DISPLAYLEVEL(1, "Error %i : ", error); \ @@ -144,20 +124,31 @@ struct LZ4IO_prefs_s { } -/************************************** -* Version modifiers -**************************************/ -#define DEFAULT_DECOMPRESSOR LZ4IO_decompressLZ4F - - /* ************************************************** */ /* ****************** Parameters ******************** */ /* ************************************************** */ +struct LZ4IO_prefs_s { + int passThrough; + int overwrite; + int testMode; + int blockSizeId; + size_t blockSize; + int blockChecksum; + int streamChecksum; + int blockIndependence; + int sparseFileSupport; + int contentSizeFlag; + int useDictionary; + unsigned favorDecSpeed; + const char* dictionaryFilename; + int removeSrcFile; +}; + LZ4IO_prefs_t* LZ4IO_defaultPreferences(void) { LZ4IO_prefs_t* const ret = (LZ4IO_prefs_t*)malloc(sizeof(*ret)); - if (!ret) EXM_THROW(21, "Allocation error : not enough memory"); + if (!ret) END_PROCESS(21, "Allocation error : not enough memory"); ret->passThrough = 0; ret->overwrite = 1; ret->testMode = 0; @@ -295,6 +286,26 @@ void LZ4IO_setRemoveSrcFile(LZ4IO_prefs_t* const prefs, unsigned flag) /* ************************************************************************ ** +** ********************** String functions ********************* ** +** ************************************************************************ */ + +static int LZ4IO_isDevNull(const char* s) +{ + return UTIL_sameString(s, nulmark); +} + +static int LZ4IO_isStdin(const char* s) +{ + return UTIL_sameString(s, stdinmark); +} + +static int LZ4IO_isStdout(const char* s) +{ + return UTIL_sameString(s, stdoutmark); +} + + +/* ************************************************************************ ** ** ********************** LZ4 File / Pipe compression ********************* ** ** ************************************************************************ */ @@ -310,13 +321,13 @@ static FILE* LZ4IO_openSrcFile(const char* srcFileName) { FILE* f; - if (!strcmp (srcFileName, stdinmark)) { - DISPLAYLEVEL(4,"Using stdin for input\n"); + if (LZ4IO_isStdin(srcFileName)) { + DISPLAYLEVEL(4,"Using stdin for input \n"); f = stdin; SET_BINARY_MODE(stdin); } else { f = fopen(srcFileName, "rb"); - if ( f==NULL ) DISPLAYLEVEL(1, "%s: %s \n", srcFileName, strerror(errno)); + if (f==NULL) DISPLAYLEVEL(1, "%s: %s \n", srcFileName, strerror(errno)); } return f; @@ -331,7 +342,7 @@ static FILE* LZ4IO_openDstFile(const char* dstFileName, const LZ4IO_prefs_t* con FILE* f; assert(dstFileName != NULL); - if (!strcmp (dstFileName, stdoutmark)) { + if (LZ4IO_isStdout(dstFileName)) { DISPLAYLEVEL(4, "Using stdout for output \n"); f = stdout; SET_BINARY_MODE(stdout); @@ -340,7 +351,8 @@ static FILE* LZ4IO_openDstFile(const char* dstFileName, const LZ4IO_prefs_t* con " to force-enable it, add --sparse command \n"); } } else { - if (!prefs->overwrite && strcmp (dstFileName, nulmark)) { /* Check if destination file already exists */ + if (!prefs->overwrite && !LZ4IO_isDevNull(dstFileName)) { + /* Check if destination file already exists */ FILE* const testf = fopen( dstFileName, "rb" ); if (testf != NULL) { /* dest exists, prompt for overwrite authorization */ fclose(testf); @@ -348,7 +360,7 @@ static FILE* LZ4IO_openDstFile(const char* dstFileName, const LZ4IO_prefs_t* con DISPLAY("%s already exists; not overwritten \n", dstFileName); return NULL; } - DISPLAY("%s already exists; do you wish to overwrite (y/N) ? ", dstFileName); + DISPLAY("%s already exists; do you want to overwrite (y/N) ? ", dstFileName); { int ch = getchar(); if ((ch!='Y') && (ch!='y')) { DISPLAY(" not overwritten \n"); @@ -414,24 +426,24 @@ int LZ4IO_compressFilename_Legacy(const char* input_filename, const char* output /* Init */ clock_t const clockStart = clock(); if (finput == NULL) - EXM_THROW(20, "%s : open file error ", input_filename); + END_PROCESS(20, "%s : open file error ", input_filename); foutput = LZ4IO_openDstFile(output_filename, prefs); if (foutput == NULL) { fclose(finput); - EXM_THROW(20, "%s : open file error ", input_filename); + END_PROCESS(20, "%s : open file error ", input_filename); } /* Allocate Memory */ in_buff = (char*)malloc(LEGACY_BLOCKSIZE); out_buff = (char*)malloc((size_t)outBuffSize + 4); if (!in_buff || !out_buff) - EXM_THROW(21, "Allocation error : not enough memory"); + END_PROCESS(21, "Allocation error : not enough memory"); /* Write Archive Header */ LZ4IO_writeLE32(out_buff, LEGACY_MAGICNUMBER); if (fwrite(out_buff, 1, MAGICNUMBER_SIZE, foutput) != MAGICNUMBER_SIZE) - EXM_THROW(22, "Write error : cannot write header"); + END_PROCESS(22, "Write error : cannot write header"); /* Main Loop */ while (1) { @@ -454,13 +466,13 @@ int LZ4IO_compressFilename_Legacy(const char* input_filename, const char* output assert(outSize < outBuffSize); LZ4IO_writeLE32(out_buff, (unsigned)outSize); if (fwrite(out_buff, 1, (size_t)outSize+4, foutput) != (size_t)(outSize+4)) { - EXM_THROW(24, "Write error : cannot write compressed block"); + END_PROCESS(24, "Write error : cannot write compressed block"); } } - if (ferror(finput)) EXM_THROW(25, "Error while reading %s ", input_filename); + if (ferror(finput)) END_PROCESS(24, "Error while reading %s ", input_filename); /* Status */ clockEnd = clock(); - if (clockEnd==clockStart) clockEnd+=1; /* avoid division by zero (speed) */ + clockEnd += (clockEnd==clockStart); /* avoid division by zero (speed) */ filesize += !filesize; /* avoid division by zero (ratio) */ DISPLAYLEVEL(2, "\r%79s\r", ""); /* blank line */ DISPLAYLEVEL(2,"Compressed %llu bytes into %llu bytes ==> %.2f%%\n", @@ -474,7 +486,7 @@ int LZ4IO_compressFilename_Legacy(const char* input_filename, const char* output free(in_buff); free(out_buff); fclose(finput); - if (strcmp(output_filename,stdoutmark)) fclose(foutput); /* do not close stdout */ + if (!LZ4IO_isStdout(output_filename)) fclose(foutput); /* do not close stdout */ return 0; } @@ -499,7 +511,7 @@ int LZ4IO_compressMultipleFilenames_Legacy( /* loop on each file */ for (i=0; i<ifntSize; i++) { size_t const ifnSize = strlen(inFileNamesTable[i]); - if (!strcmp(suffix, stdoutmark)) { + if (LZ4IO_isStdout(suffix)) { missed_files += LZ4IO_compressFilename_Legacy( inFileNamesTable[i], stdoutmark, compressionLevel, prefs); @@ -531,7 +543,6 @@ int LZ4IO_compressMultipleFilenames_Legacy( /********************************************* * Compression using Frame format *********************************************/ - typedef struct { void* srcBuffer; size_t srcBufferSize; @@ -552,15 +563,15 @@ static void* LZ4IO_createDict(size_t* dictSize, const char* const dictFilename) char* dictBuf; FILE* dictFile; - if (!circularBuf) EXM_THROW(25, "Allocation error : not enough memory for circular buffer"); - if (!dictFilename) EXM_THROW(25, "Dictionary error : no filename provided"); + if (!circularBuf) END_PROCESS(25, "Allocation error : not enough memory for circular buffer"); + if (!dictFilename) END_PROCESS(26, "Dictionary error : no filename provided"); dictFile = LZ4IO_openSrcFile(dictFilename); - if (!dictFile) EXM_THROW(25, "Dictionary error : could not open dictionary file"); + if (!dictFile) END_PROCESS(27, "Dictionary error : could not open dictionary file"); - /* opportunistically seek to the part of the file we care about. If this */ - /* fails it's not a problem since we'll just read everything anyways. */ - if (strcmp(dictFilename, stdinmark)) { + /* opportunistically seek to the part of the file we care about. + * If this fails it's not a problem since we'll just read everything anyways. */ + if (!LZ4IO_isStdin(dictFilename)) { (void)UTIL_fseek(dictFile, -LZ4_MAX_DICT_SIZE, SEEK_END); } @@ -585,7 +596,7 @@ static void* LZ4IO_createDict(size_t* dictSize, const char* const dictFilename) } else { /* Otherwise, we will alloc a new buffer and copy our dict into that. */ dictBuf = (char *)malloc(dictLen ? dictLen : 1); - if (!dictBuf) EXM_THROW(25, "Allocation error : not enough memory"); + if (!dictBuf) END_PROCESS(28, "Allocation error : not enough memory"); memcpy(dictBuf, circularBuf + dictStart, circularBufSize - dictStart); memcpy(dictBuf + circularBufSize - dictStart, circularBuf, dictLen - (circularBufSize - dictStart)); @@ -604,7 +615,7 @@ static LZ4F_CDict* LZ4IO_createCDict(const LZ4IO_prefs_t* const prefs) LZ4F_CDict* cdict; if (!prefs->useDictionary) return NULL; dictionaryBuffer = LZ4IO_createDict(&dictionarySize, prefs->dictionaryFilename); - if (!dictionaryBuffer) EXM_THROW(25, "Dictionary error : could not create dictionary"); + if (!dictionaryBuffer) END_PROCESS(29, "Dictionary error : could not create dictionary"); cdict = LZ4F_createCDict(dictionaryBuffer, dictionarySize); free(dictionaryBuffer); return cdict; @@ -616,14 +627,14 @@ static cRess_t LZ4IO_createCResources(const LZ4IO_prefs_t* const prefs) cRess_t ress; LZ4F_errorCode_t const errorCode = LZ4F_createCompressionContext(&(ress.ctx), LZ4F_VERSION); - if (LZ4F_isError(errorCode)) EXM_THROW(30, "Allocation error : can't create LZ4F context : %s", LZ4F_getErrorName(errorCode)); + if (LZ4F_isError(errorCode)) END_PROCESS(30, "Allocation error : can't create LZ4F context : %s", LZ4F_getErrorName(errorCode)); /* Allocate Memory */ ress.srcBuffer = malloc(blockSize); ress.srcBufferSize = blockSize; ress.dstBufferSize = LZ4F_compressFrameBound(blockSize, NULL); /* cover worst case */ ress.dstBuffer = malloc(ress.dstBufferSize); - if (!ress.srcBuffer || !ress.dstBuffer) EXM_THROW(31, "Allocation error : not enough memory"); + if (!ress.srcBuffer || !ress.dstBuffer) END_PROCESS(31, "Allocation error : not enough memory"); ress.cdict = LZ4IO_createCDict(prefs); @@ -639,7 +650,7 @@ static void LZ4IO_freeCResources(cRess_t ress) ress.cdict = NULL; { LZ4F_errorCode_t const errorCode = LZ4F_freeCompressionContext(ress.ctx); - if (LZ4F_isError(errorCode)) EXM_THROW(38, "Error : can't free LZ4F context resource : %s", LZ4F_getErrorName(errorCode)); } + if (LZ4F_isError(errorCode)) END_PROCESS(35, "Error : can't free LZ4F context resource : %s", LZ4F_getErrorName(errorCode)); } } /* @@ -687,7 +698,7 @@ LZ4IO_compressFilename_extRess(cRess_t ress, /* read first block */ readSize = fread(srcBuffer, (size_t)1, blockSize, srcFile); - if (ferror(srcFile)) EXM_THROW(30, "Error reading %s ", srcFileName); + if (ferror(srcFile)) END_PROCESS(40, "Error reading %s ", srcFileName); filesize += readSize; /* single-block file */ @@ -695,14 +706,14 @@ LZ4IO_compressFilename_extRess(cRess_t ress, /* Compress in single pass */ size_t const cSize = LZ4F_compressFrame_usingCDict(ctx, dstBuffer, dstBufferSize, srcBuffer, readSize, ress.cdict, &prefs); if (LZ4F_isError(cSize)) - EXM_THROW(31, "Compression failed : %s", LZ4F_getErrorName(cSize)); + END_PROCESS(41, "Compression failed : %s", LZ4F_getErrorName(cSize)); compressedfilesize = cSize; DISPLAYUPDATE(2, "\rRead : %u MiB ==> %.2f%% ", (unsigned)(filesize>>20), (double)compressedfilesize/(filesize+!filesize)*100); /* avoid division by zero */ /* Write Block */ if (fwrite(dstBuffer, 1, cSize, dstFile) != cSize) { - EXM_THROW(32, "Write error : failed writing single-block compressed frame"); + END_PROCESS(42, "Write error : failed writing single-block compressed frame"); } } else @@ -711,55 +722,55 @@ LZ4IO_compressFilename_extRess(cRess_t ress, { /* Write Frame Header */ size_t const headerSize = LZ4F_compressBegin_usingCDict(ctx, dstBuffer, dstBufferSize, ress.cdict, &prefs); - if (LZ4F_isError(headerSize)) EXM_THROW(33, "File header generation failed : %s", LZ4F_getErrorName(headerSize)); + if (LZ4F_isError(headerSize)) END_PROCESS(43, "File header generation failed : %s", LZ4F_getErrorName(headerSize)); if (fwrite(dstBuffer, 1, headerSize, dstFile) != headerSize) - EXM_THROW(34, "Write error : cannot write header"); + END_PROCESS(44, "Write error : cannot write header"); compressedfilesize += headerSize; /* Main Loop - one block at a time */ while (readSize>0) { size_t const outSize = LZ4F_compressUpdate(ctx, dstBuffer, dstBufferSize, srcBuffer, readSize, NULL); if (LZ4F_isError(outSize)) - EXM_THROW(35, "Compression failed : %s", LZ4F_getErrorName(outSize)); + END_PROCESS(45, "Compression failed : %s", LZ4F_getErrorName(outSize)); compressedfilesize += outSize; DISPLAYUPDATE(2, "\rRead : %u MiB ==> %.2f%% ", (unsigned)(filesize>>20), (double)compressedfilesize/filesize*100); /* Write Block */ if (fwrite(dstBuffer, 1, outSize, dstFile) != outSize) - EXM_THROW(36, "Write error : cannot write compressed block"); + END_PROCESS(46, "Write error : cannot write compressed block"); /* Read next block */ readSize = fread(srcBuffer, (size_t)1, (size_t)blockSize, srcFile); filesize += readSize; } - if (ferror(srcFile)) EXM_THROW(37, "Error reading %s ", srcFileName); + if (ferror(srcFile)) END_PROCESS(47, "Error reading %s ", srcFileName); /* End of Frame mark */ { size_t const endSize = LZ4F_compressEnd(ctx, dstBuffer, dstBufferSize, NULL); if (LZ4F_isError(endSize)) - EXM_THROW(38, "End of frame error : %s", LZ4F_getErrorName(endSize)); + END_PROCESS(48, "End of frame error : %s", LZ4F_getErrorName(endSize)); if (fwrite(dstBuffer, 1, endSize, dstFile) != endSize) - EXM_THROW(39, "Write error : cannot write end of frame"); + END_PROCESS(49, "Write error : cannot write end of frame"); compressedfilesize += endSize; } } /* Release file handlers */ fclose (srcFile); - if (strcmp(dstFileName,stdoutmark)) fclose (dstFile); /* do not close stdout */ + if (!LZ4IO_isStdout(dstFileName)) fclose(dstFile); /* do not close stdout */ /* Copy owner, file permissions and modification time */ { stat_t statbuf; - if (strcmp (srcFileName, stdinmark) - && strcmp (dstFileName, stdoutmark) - && strcmp (dstFileName, nulmark) + if (!LZ4IO_isStdin(srcFileName) + && !LZ4IO_isStdout(dstFileName) + && !LZ4IO_isDevNull(dstFileName) && UTIL_getFileStat(srcFileName, &statbuf)) { UTIL_setFileStat(dstFileName, &statbuf); } } if (io_prefs->removeSrcFile) { /* remove source file : --rm */ if (remove(srcFileName)) - EXM_THROW(40, "Remove error : %s: %s", srcFileName, strerror(errno)); + END_PROCESS(50, "Remove error : %s: %s", srcFileName, strerror(errno)); } /* Final Status */ @@ -815,12 +826,13 @@ int LZ4IO_compressMultipleFilenames( /* loop on each file */ for (i=0; i<ifntSize; i++) { size_t const ifnSize = strlen(inFileNamesTable[i]); - if (!strcmp(suffix, stdoutmark)) { + if (LZ4IO_isStdout(suffix)) { missed_files += LZ4IO_compressFilename_extRess(ress, inFileNamesTable[i], stdoutmark, compressionLevel, prefs); continue; } + /* suffix != stdout => compress into a file => generate its name */ if (ofnSize <= ifnSize+suffixSize+1) { free(dstFileName); ofnSize = ifnSize + 20; @@ -878,14 +890,14 @@ LZ4IO_fwriteSparse(FILE* file, if (!sparseMode) { /* normal write */ size_t const sizeCheck = fwrite(buffer, 1, bufferSize, file); - if (sizeCheck != bufferSize) EXM_THROW(70, "Write error : cannot write decoded block"); + if (sizeCheck != bufferSize) END_PROCESS(70, "Write error : cannot write decoded block"); return 0; } /* avoid int overflow */ if (storedSkips > 1 GB) { int const seekResult = UTIL_fseek(file, 1 GB, SEEK_CUR); - if (seekResult != 0) EXM_THROW(71, "1 GB skip error (sparse file support)"); + if (seekResult != 0) END_PROCESS(71, "1 GB skip error (sparse file support)"); storedSkips -= 1 GB; } @@ -902,13 +914,13 @@ LZ4IO_fwriteSparse(FILE* file, if (nb0T != seg0SizeT) { /* not all 0s */ errno = 0; { int const seekResult = UTIL_fseek(file, storedSkips, SEEK_CUR); - if (seekResult) EXM_THROW(72, "Sparse skip error(%d): %s ; try --no-sparse", (int)errno, strerror(errno)); + if (seekResult) END_PROCESS(72, "Sparse skip error(%d): %s ; try --no-sparse", (int)errno, strerror(errno)); } storedSkips = 0; seg0SizeT -= nb0T; ptrT += nb0T; { size_t const sizeCheck = fwrite(ptrT, sizeT, seg0SizeT, file); - if (sizeCheck != seg0SizeT) EXM_THROW(73, "Write error : cannot write decoded block"); + if (sizeCheck != seg0SizeT) END_PROCESS(73, "Write error : cannot write decoded block"); } } ptrT += seg0SizeT; } @@ -922,10 +934,10 @@ LZ4IO_fwriteSparse(FILE* file, storedSkips += (unsigned) (restPtr - restStart); if (restPtr != restEnd) { int const seekResult = UTIL_fseek(file, storedSkips, SEEK_CUR); - if (seekResult) EXM_THROW(74, "Sparse skip error ; try --no-sparse"); + if (seekResult) END_PROCESS(74, "Sparse skip error ; try --no-sparse"); storedSkips = 0; { size_t const sizeCheck = fwrite(restPtr, 1, (size_t)(restEnd - restPtr), file); - if (sizeCheck != (size_t)(restEnd - restPtr)) EXM_THROW(75, "Write error : cannot write decoded end of block"); + if (sizeCheck != (size_t)(restEnd - restPtr)) END_PROCESS(75, "Write error : cannot write decoded end of block"); } } } @@ -937,9 +949,9 @@ static void LZ4IO_fwriteSparseEnd(FILE* file, unsigned storedSkips) if (storedSkips>0) { /* implies sparseFileSupport>0 */ const char lastZeroByte[1] = { 0 }; if (UTIL_fseek(file, storedSkips-1, SEEK_CUR) != 0) - EXM_THROW(69, "Final skip error (sparse file)\n"); + END_PROCESS(68, "Final skip error (sparse file)\n"); if (fwrite(lastZeroByte, 1, 1, file) != 1) - EXM_THROW(69, "Write error : cannot write last zero\n"); + END_PROCESS(69, "Write error : cannot write last zero\n"); } } @@ -955,7 +967,7 @@ LZ4IO_decodeLegacyStream(FILE* finput, FILE* foutput, const LZ4IO_prefs_t* prefs /* Allocate Memory */ char* const in_buff = (char*)malloc((size_t)LZ4_compressBound(LEGACY_BLOCKSIZE)); char* const out_buff = (char*)malloc(LEGACY_BLOCKSIZE); - if (!in_buff || !out_buff) EXM_THROW(51, "Allocation error : not enough memory"); + if (!in_buff || !out_buff) END_PROCESS(51, "Allocation error : not enough memory"); /* Main Loop */ while (1) { @@ -964,7 +976,7 @@ LZ4IO_decodeLegacyStream(FILE* finput, FILE* foutput, const LZ4IO_prefs_t* prefs /* Block Size */ { size_t const sizeCheck = fread(in_buff, 1, LZ4IO_LEGACY_BLOCK_HEADER_SIZE, finput); if (sizeCheck == 0) break; /* Nothing to read : file read is completed */ - if (sizeCheck != LZ4IO_LEGACY_BLOCK_HEADER_SIZE) EXM_THROW(52, "Read error : cannot access block size "); + if (sizeCheck != LZ4IO_LEGACY_BLOCK_HEADER_SIZE) END_PROCESS(52, "Read error : cannot access block size "); } blockSize = LZ4IO_readLE32(in_buff); /* Convert to Little Endian */ if (blockSize > LZ4_COMPRESSBOUND(LEGACY_BLOCKSIZE)) { @@ -975,16 +987,16 @@ LZ4IO_decodeLegacyStream(FILE* finput, FILE* foutput, const LZ4IO_prefs_t* prefs /* Read Block */ { size_t const sizeCheck = fread(in_buff, 1, blockSize, finput); - if (sizeCheck != blockSize) EXM_THROW(52, "Read error : cannot access compressed block !"); } + if (sizeCheck != blockSize) END_PROCESS(53, "Read error : cannot access compressed block !"); } /* Decode Block */ { int const decodeSize = LZ4_decompress_safe(in_buff, out_buff, (int)blockSize, LEGACY_BLOCKSIZE); - if (decodeSize < 0) EXM_THROW(53, "Decoding Failed ! Corrupted input detected !"); + if (decodeSize < 0) END_PROCESS(54, "Decoding Failed ! Corrupted input detected !"); streamSize += (unsigned long long)decodeSize; /* Write Block */ storedSkips = LZ4IO_fwriteSparse(foutput, out_buff, (size_t)decodeSize, prefs->sparseFileSupport, storedSkips); /* success or die */ } } - if (ferror(finput)) EXM_THROW(54, "Read error : ferror"); + if (ferror(finput)) END_PROCESS(55, "Read error : ferror"); LZ4IO_fwriteSparseEnd(foutput, storedSkips); @@ -1017,7 +1029,7 @@ static void LZ4IO_loadDDict(dRess_t* ress, const LZ4IO_prefs_t* const prefs) } ress->dictBuffer = LZ4IO_createDict(&ress->dictBufferSize, prefs->dictionaryFilename); - if (!ress->dictBuffer) EXM_THROW(25, "Dictionary error : could not create dictionary"); + if (!ress->dictBuffer) END_PROCESS(25, "Dictionary error : could not create dictionary"); } static const size_t LZ4IO_dBufferSize = 64 KB; @@ -1027,14 +1039,14 @@ static dRess_t LZ4IO_createDResources(const LZ4IO_prefs_t* const prefs) /* init */ LZ4F_errorCode_t const errorCode = LZ4F_createDecompressionContext(&ress.dCtx, LZ4F_VERSION); - if (LZ4F_isError(errorCode)) EXM_THROW(60, "Can't create LZ4F context : %s", LZ4F_getErrorName(errorCode)); + if (LZ4F_isError(errorCode)) END_PROCESS(60, "Can't create LZ4F context : %s", LZ4F_getErrorName(errorCode)); /* Allocate Memory */ ress.srcBufferSize = LZ4IO_dBufferSize; ress.srcBuffer = malloc(ress.srcBufferSize); ress.dstBufferSize = LZ4IO_dBufferSize; ress.dstBuffer = malloc(ress.dstBufferSize); - if (!ress.srcBuffer || !ress.dstBuffer) EXM_THROW(61, "Allocation error : not enough memory"); + if (!ress.srcBuffer || !ress.dstBuffer) END_PROCESS(61, "Allocation error : not enough memory"); LZ4IO_loadDDict(&ress, prefs); @@ -1045,7 +1057,7 @@ static dRess_t LZ4IO_createDResources(const LZ4IO_prefs_t* const prefs) static void LZ4IO_freeDResources(dRess_t ress) { LZ4F_errorCode_t errorCode = LZ4F_freeDecompressionContext(ress.dCtx); - if (LZ4F_isError(errorCode)) EXM_THROW(69, "Error : can't free LZ4F context resource : %s", LZ4F_getErrorName(errorCode)); + if (LZ4F_isError(errorCode)) END_PROCESS(69, "Error : can't free LZ4F context resource : %s", LZ4F_getErrorName(errorCode)); free(ress.srcBuffer); free(ress.dstBuffer); free(ress.dictBuffer); @@ -1066,7 +1078,7 @@ LZ4IO_decompressLZ4F(dRess_t ress, size_t outSize= 0; LZ4IO_writeLE32(ress.srcBuffer, LZ4IO_MAGICNUMBER); nextToLoad = LZ4F_decompress_usingDict(ress.dCtx, ress.dstBuffer, &outSize, ress.srcBuffer, &inSize, ress.dictBuffer, ress.dictBufferSize, NULL); - if (LZ4F_isError(nextToLoad)) EXM_THROW(62, "Header error : %s", LZ4F_getErrorName(nextToLoad)); + if (LZ4F_isError(nextToLoad)) END_PROCESS(62, "Header error : %s", LZ4F_getErrorName(nextToLoad)); } /* Main Loop */ @@ -1085,7 +1097,7 @@ LZ4IO_decompressLZ4F(dRess_t ress, size_t remaining = readSize - pos; decodedBytes = ress.dstBufferSize; nextToLoad = LZ4F_decompress_usingDict(ress.dCtx, ress.dstBuffer, &decodedBytes, (char*)(ress.srcBuffer)+pos, &remaining, ress.dictBuffer, ress.dictBufferSize, NULL); - if (LZ4F_isError(nextToLoad)) EXM_THROW(66, "Decompression error : %s", LZ4F_getErrorName(nextToLoad)); + if (LZ4F_isError(nextToLoad)) END_PROCESS(66, "Decompression error : %s", LZ4F_getErrorName(nextToLoad)); pos += remaining; /* Write Block */ @@ -1100,10 +1112,10 @@ LZ4IO_decompressLZ4F(dRess_t ress, } } /* can be out because readSize == 0, which could be an fread() error */ - if (ferror(srcFile)) EXM_THROW(67, "Read error"); + if (ferror(srcFile)) END_PROCESS(67, "Read error"); if (!prefs->testMode) LZ4IO_fwriteSparseEnd(dstFile, storedSkips); - if (nextToLoad!=0) EXM_THROW(68, "Unfinished stream"); + if (nextToLoad!=0) END_PROCESS(68, "Unfinished stream"); return filesize; } @@ -1127,14 +1139,14 @@ LZ4IO_passThrough(FILE* finput, FILE* foutput, unsigned storedSkips = 0; if (fwrite(MNstore, 1, MAGICNUMBER_SIZE, foutput) != MAGICNUMBER_SIZE) { - EXM_THROW(50, "Pass-through write error"); + END_PROCESS(50, "Pass-through write error"); } while (readBytes) { readBytes = fread(buffer, 1, sizeof(buffer), finput); total += readBytes; storedSkips = LZ4IO_fwriteSparse(foutput, buffer, readBytes, sparseFileSupport, storedSkips); } - if (ferror(finput)) EXM_THROW(51, "Read Error"); + if (ferror(finput)) END_PROCESS(51, "Read Error"); LZ4IO_fwriteSparseEnd(foutput, storedSkips); return total; @@ -1180,7 +1192,7 @@ selectDecoder(dRess_t ress, size_t const nbReadBytes = fread(MNstore, 1, MAGICNUMBER_SIZE, finput); if (nbReadBytes==0) { nbFrames = 0; return ENDOFSTREAM; } /* EOF */ if (nbReadBytes != MAGICNUMBER_SIZE) - EXM_THROW(40, "Unrecognized header : Magic Number unreadable"); + END_PROCESS(40, "Unrecognized header : Magic Number unreadable"); magicNumber = LZ4IO_readLE32(MNstore); /* Little Endian format */ } if (LZ4IO_isSkippableMagicNumber(magicNumber)) @@ -1197,12 +1209,12 @@ selectDecoder(dRess_t ress, DISPLAYLEVEL(4, "Skipping detected skippable area \n"); { size_t const nbReadBytes = fread(MNstore, 1, 4, finput); if (nbReadBytes != 4) - EXM_THROW(42, "Stream error : skippable size unreadable"); + END_PROCESS(42, "Stream error : skippable size unreadable"); } { unsigned const size = LZ4IO_readLE32(MNstore); int const errorNb = fseek_u32(finput, size, SEEK_CUR); if (errorNb != 0) - EXM_THROW(43, "Stream error : cannot skip skippable area"); + END_PROCESS(43, "Stream error : cannot skip skippable area"); } return 0; default: @@ -1212,7 +1224,7 @@ selectDecoder(dRess_t ress, nbFrames = 0; return LZ4IO_passThrough(finput, foutput, MNstore, prefs->sparseFileSupport); } - EXM_THROW(44,"Unrecognized header : file cannot be decoded"); + END_PROCESS(44,"Unrecognized header : file cannot be decoded"); } { long int const position = ftell(finput); /* only works for files < 2 GB */ DISPLAYLEVEL(2, "Stream followed by undecodable data "); @@ -1252,7 +1264,7 @@ LZ4IO_decompressSrcFile(dRess_t ress, fclose(finput); if (prefs->removeSrcFile) { /* --rm */ if (remove(input_filename)) - EXM_THROW(45, "Remove error : %s: %s", input_filename, strerror(errno)); + END_PROCESS(45, "Remove error : %s: %s", input_filename, strerror(errno)); } /* Final Status */ @@ -1275,7 +1287,7 @@ LZ4IO_decompressDstFile(dRess_t ress, FILE* const foutput = LZ4IO_openDstFile(output_filename, prefs); if (foutput==NULL) return 1; /* failure */ - if ( strcmp(input_filename, stdinmark) + if ( !LZ4IO_isStdin(input_filename) && UTIL_getFileStat(input_filename, &statbuf)) stat_result = 1; @@ -1286,8 +1298,8 @@ LZ4IO_decompressDstFile(dRess_t ress, /* Copy owner, file permissions and modification time */ if ( stat_result != 0 - && strcmp (output_filename, stdoutmark) - && strcmp (output_filename, nulmark)) { + && !LZ4IO_isStdout(output_filename) + && !LZ4IO_isDevNull(output_filename)) { UTIL_setFileStat(output_filename, &statbuf); /* should return value be read ? or is silent fail good enough ? */ } @@ -1325,23 +1337,23 @@ int LZ4IO_decompressMultipleFilenames( size_t const suffixSize = strlen(suffix); dRess_t ress = LZ4IO_createDResources(prefs); - if (outFileName==NULL) EXM_THROW(70, "Memory allocation error"); + if (outFileName==NULL) END_PROCESS(70, "Memory allocation error"); ress.dstFile = LZ4IO_openDstFile(stdoutmark, prefs); for (i=0; i<ifntSize; i++) { size_t const ifnSize = strlen(inFileNamesTable[i]); const char* const suffixPtr = inFileNamesTable[i] + ifnSize - suffixSize; - if (!strcmp(suffix, stdoutmark)) { - missingFiles += LZ4IO_decompressSrcFile(ress, inFileNamesTable[i], stdoutmark, prefs); + if (LZ4IO_isStdout(suffix) || LZ4IO_isDevNull(suffix)) { + missingFiles += LZ4IO_decompressSrcFile(ress, inFileNamesTable[i], suffix, prefs); continue; } if (ofnSize <= ifnSize-suffixSize+1) { free(outFileName); ofnSize = ifnSize + 20; outFileName = (char*)malloc(ofnSize); - if (outFileName==NULL) EXM_THROW(71, "Memory allocation error"); + if (outFileName==NULL) END_PROCESS(71, "Memory allocation error"); } - if (ifnSize <= suffixSize || strcmp(suffixPtr, suffix) != 0) { + if (ifnSize <= suffixSize || !UTIL_sameString(suffixPtr, suffix) ) { DISPLAYLEVEL(1, "File extension doesn't match expected LZ4_EXTENSION (%4s); will not process file: %s\n", suffix, inFileNamesTable[i]); skippedFiles++; continue; @@ -1459,7 +1471,7 @@ static unsigned long long LZ4IO_skipLegacyBlocksData(FILE* finput) || LZ4IO_isSkippableMagicNumber(nextCBlockSize) ) { /* Rewind back. we want cursor at the beginning of next frame */ if (UTIL_fseek(finput, -LZ4IO_LEGACY_BLOCK_HEADER_SIZE, SEEK_CUR) != 0) { - EXM_THROW(37, "impossible to skip backward"); + END_PROCESS(37, "impossible to skip backward"); } break; } @@ -1531,7 +1543,7 @@ LZ4IO_getCompressedFileInfo(LZ4IO_cFileInfo_t* cfinfo, const char* input_filenam if (nbReadBytes == 0) { break; } /* EOF */ result = LZ4IO_format_not_known; /* default result (error) */ if (nbReadBytes != MAGICNUMBER_SIZE) { - EXM_THROW(40, "Unrecognized header : Magic Number unreadable"); + END_PROCESS(40, "Unrecognized header : Magic Number unreadable"); } } magicNumber = LZ4IO_readLE32(buffer); /* Little Endian format */ if (LZ4IO_isSkippableMagicNumber(magicNumber)) @@ -1542,14 +1554,14 @@ LZ4IO_getCompressedFileInfo(LZ4IO_cFileInfo_t* cfinfo, const char* input_filenam if (cfinfo->frameSummary.frameType != lz4Frame) cfinfo->eqFrameTypes = 0; /* Get frame info */ { const size_t readBytes = fread(buffer + MAGICNUMBER_SIZE, 1, LZ4F_HEADER_SIZE_MIN - MAGICNUMBER_SIZE, finput); - if (!readBytes || ferror(finput)) EXM_THROW(71, "Error reading %s", input_filename); + if (!readBytes || ferror(finput)) END_PROCESS(71, "Error reading %s", input_filename); } { size_t hSize = LZ4F_headerSize(&buffer, LZ4F_HEADER_SIZE_MIN); if (LZ4F_isError(hSize)) break; if (hSize > (LZ4F_HEADER_SIZE_MIN + MAGICNUMBER_SIZE)) { /* We've already read LZ4F_HEADER_SIZE_MIN so read any extra until hSize*/ const size_t readBytes = fread(buffer + LZ4F_HEADER_SIZE_MIN, 1, hSize - LZ4F_HEADER_SIZE_MIN, finput); - if (!readBytes || ferror(finput)) EXM_THROW(72, "Error reading %s", input_filename); + if (!readBytes || ferror(finput)) END_PROCESS(72, "Error reading %s", input_filename); } /* Create decompression context */ { LZ4F_dctx* dctx; @@ -1617,12 +1629,12 @@ LZ4IO_getCompressedFileInfo(LZ4IO_cFileInfo_t* cfinfo, const char* input_filenam cfinfo->allContentSize = 0; { size_t const nbReadBytes = fread(buffer, 1, 4, finput); if (nbReadBytes != 4) - EXM_THROW(42, "Stream error : skippable size unreadable"); + END_PROCESS(42, "Stream error : skippable size unreadable"); } { unsigned const size = LZ4IO_readLE32(buffer); int const errorNb = fseek_u32(finput, size, SEEK_CUR); if (errorNb != 0) - EXM_THROW(43, "Stream error : cannot skip skippable area"); + END_PROCESS(43, "Stream error : cannot skip skippable area"); DISPLAYLEVEL(3, " %6llu %14s %5s %8s %20u %20s %9s\n", cfinfo->frameCount + 1, "SkippableFrame", @@ -1662,7 +1674,7 @@ int LZ4IO_displayCompressedFilesInfo(const char** inFileNames, size_t ifnIdx) /* Get file info */ LZ4IO_cFileInfo_t cfinfo = LZ4IO_INIT_CFILEINFO; cfinfo.fileName = LZ4IO_baseName(inFileNames[idx]); - if ((strcmp(inFileNames[idx], stdinmark) == 0) ? !UTIL_isRegFD(0) : !UTIL_isRegFile(inFileNames[idx])) { + if (LZ4IO_isStdin(inFileNames[idx]) ? !UTIL_isRegFD(0) : !UTIL_isRegFile(inFileNames[idx])) { DISPLAYLEVEL(1, "lz4: %s is not a regular file \n", inFileNames[idx]); return 1; } diff --git a/programs/util.h b/programs/util.h index 2840179..3192ddc 100644 --- a/programs/util.h +++ b/programs/util.h @@ -175,6 +175,39 @@ extern "C" { #endif + +/*-**************************************** +* Allocation functions +******************************************/ +/* + * A modified version of realloc(). + * If UTIL_realloc() fails the original block is freed. +*/ +UTIL_STATIC void* UTIL_realloc(void* ptr, size_t size) +{ + void* const newptr = realloc(ptr, size); + if (newptr) return newptr; + free(ptr); + return NULL; +} + + +/*-**************************************** +* String functions +******************************************/ +/* + * A modified version of realloc(). + * If UTIL_realloc() fails the original block is freed. +*/ +UTIL_STATIC int UTIL_sameString(const char* a, const char* b) +{ + assert(a!=NULL && b!=NULL); /* unsupported scenario */ + if (a==NULL) return 0; + if (b==NULL) return 0; + return !strcmp(a,b); +} + + /*-**************************************** * Time functions ******************************************/ @@ -451,19 +484,6 @@ UTIL_STATIC U64 UTIL_getTotalFileSize(const char** fileNamesTable, unsigned nbFi } -/* - * A modified version of realloc(). - * If UTIL_realloc() fails the original block is freed. -*/ -UTIL_STATIC void* UTIL_realloc(void* ptr, size_t size) -{ - void* const newptr = realloc(ptr, size); - if (newptr) return newptr; - free(ptr); - return NULL; -} - - #ifdef _WIN32 # define UTIL_HAS_CREATEFILELIST @@ -665,8 +685,8 @@ UTIL_createFileList(const char** inputNames, unsigned inputNamesNb, UTIL_STATIC void UTIL_freeFileList(const char** filenameTable, char* allocatedBuffer) { - if (allocatedBuffer) free(allocatedBuffer); - if (filenameTable) free((void*)filenameTable); + free(allocatedBuffer); + free((void*)filenameTable); } diff --git a/tests/Makefile b/tests/Makefile index 9f83f06..b67f135 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -154,6 +154,7 @@ endif # note : we should probably settle on a single compare utility CMP:=cmp +GREP:=grep DIFF:=diff ifneq (,$(filter $(shell $(UNAME)),SunOS)) DIFF:=gdiff @@ -289,6 +290,11 @@ test-lz4-multiple: lz4 datagen $(CMP) tmp-tlm-concat1 tmp-tlm-concat2 # must be equivalent # compress multiple files, one of which is absent (must fail) ! $(LZ4) -f -m tmp-tlm-concat1 notHere tmp-tlm-concat2 # must fail : notHere not present + # test lz4-compressed file + $(LZ4) -tm tmp-tlm-concat1.lz4 + $(LZ4) -tm tmp-tlm-concat1.lz4 tmp-tlm-concat2.lz4 + # test multiple lz4 files, one of which is absent (must fail) + ! $(LZ4) -tm tmp-tlm-concat1.lz4 notHere.lz4 tmp-tlm-concat2.lz4 @$(RM) tmp-tlm* test-lz4-multiple-legacy: lz4 datagen @@ -347,8 +353,7 @@ test-lz4-basic: lz4 datagen unlz4 lz4cat $(LZ4) --rm -f tmp-tlb-hw tmp-tlb-hw.lz4 test ! -f tmp-tlb-hw # must fail (--rm) test -f tmp-tlb-hw.lz4 - $(PRGDIR)/lz4cat tmp-tlb-hw.lz4 # must display hello world - test -f tmp-tlb-hw.lz4 + $(PRGDIR)/lz4cat tmp-tlb-hw.lz4 | $(GREP) "hello world" $(PRGDIR)/unlz4 --rm tmp-tlb-hw.lz4 tmp-tlb-hw test -f tmp-tlb-hw test ! -f tmp-tlb-hw.lz4 # must fail (--rm) @@ -369,7 +374,8 @@ test-lz4-basic: lz4 datagen unlz4 lz4cat $(LZ4) -d --rm -- -z tmp-tlb4 # uncompresses ./-z into tmp-tlb4 test ! -f ./-z $(DIFF) -q tmp-tlb-hw tmp-tlb4 - $(LZ4) -f tmp-tlb-hw + ! $(LZ4) tmp-tlb2 tmp-tlb3 tmp-tlb4 # must fail: refuse to handle 3+ file names + $(LZ4) -f tmp-tlb-hw # create tmp-tlb-hw.lz4, for next tests $(LZ4) --list tmp-tlb-hw.lz4 # test --list on valid single-frame file $(LZ4) --list < tmp-tlb-hw.lz4 # test --list from stdin (file only) $(CAT) tmp-tlb-hw >> tmp-tlb-hw.lz4 @@ -392,7 +398,6 @@ test-lz4-basic: lz4 datagen unlz4 lz4cat @$(RM) tmp-tlb* - test-lz4-dict: lz4 datagen @echo "\n ---- test lz4 compression/decompression with dictionary ----" $(DATAGEN) -g16KB > tmp-dict @@ -415,7 +420,6 @@ test-lz4-dict: lz4 datagen < tmp-dict-$$l $(LZ4) -D stdin tmp-dict-data-128KB -c | $(LZ4) -dD tmp-dict-$$l-tail | $(DIFF) - tmp-dict-data-128KB; \ < tmp-dict-$$l-tail $(LZ4) -D stdin tmp-dict-data-128KB -c | $(LZ4) -dD tmp-dict-$$l | $(DIFF) - tmp-dict-data-128KB; \ done - @$(RM) tmp-dict* test-lz4-hugefile: lz4 datagen |