From 55ab3c48aef50fbf56203eb15fd37d84be5cbd46 Mon Sep 17 00:00:00 2001 From: gabrielstedman Date: Sat, 20 Apr 2019 22:06:10 +0100 Subject: Add --list option to display compressed file information. --- programs/lz4cli.c | 34 ++++++++++++++++++++++++++++++++-- programs/lz4io.c | 40 +++++++++++++++++++++++++++++++++++++++- programs/lz4io.h | 11 +++++++++++ 3 files changed, 82 insertions(+), 3 deletions(-) diff --git a/programs/lz4cli.c b/programs/lz4cli.c index 8bd7042..adfabc3 100644 --- a/programs/lz4cli.c +++ b/programs/lz4cli.c @@ -40,6 +40,7 @@ #include /* exit, calloc, free */ #include /* strcmp, strlen */ #include "bench.h" /* BMK_benchFile, BMK_SetNbIterations, BMK_SetBlocksize, BMK_SetPause */ +#include "lz4frame.h" #include "lz4io.h" /* LZ4IO_compressFilename, LZ4IO_decompressFilename, LZ4IO_compressMultipleFilenames */ #include "lz4hc.h" /* LZ4HC_CLEVEL_MAX */ #include "lz4.h" /* LZ4_VERSION_STRING */ @@ -141,6 +142,7 @@ static int usage_advanced(const char* exeName) DISPLAY( " -BX : enable block checksum (default:disabled) \n"); DISPLAY( "--no-frame-crc : disable stream checksum (default:enabled) \n"); DISPLAY( "--content-size : compressed frame includes original size (default:not present)\n"); + DISPLAY( "--list : list information about .lz4 files. Only useful if compressed with --content-size flag.\n"); DISPLAY( "--[no-]sparse : sparse mode (default:enabled on file, disabled on stdout)\n"); DISPLAY( "--favor-decSpeed: compressed files decompress faster, but are less compressed \n"); DISPLAY( "--fast[=#]: switch to ultra fast compression level (default: %i)\n", 1); @@ -286,7 +288,7 @@ static int longCommandWArg(const char** stringPtr, const char* longCommand) return result; } -typedef enum { om_auto, om_compress, om_decompress, om_test, om_bench } operationMode_e; +typedef enum { om_auto, om_compress, om_decompress, om_test, om_bench, om_list } operationMode_e; /** determineOpMode() : * auto-determine operation mode, based on input filename extension @@ -383,6 +385,7 @@ int main(int argc, const char** argv) if (!strcmp(argument, "--no-frame-crc")) { LZ4IO_setStreamChecksumMode(prefs, 0); continue; } if (!strcmp(argument, "--content-size")) { LZ4IO_setContentSize(prefs, 1); continue; } if (!strcmp(argument, "--no-content-size")) { LZ4IO_setContentSize(prefs, 0); continue; } + if (!strcmp(argument, "--list")) { mode = om_list; continue; } if (!strcmp(argument, "--sparse")) { LZ4IO_setSparseFile(prefs, 2); continue; } if (!strcmp(argument, "--no-sparse")) { LZ4IO_setSparseFile(prefs, 0); continue; } if (!strcmp(argument, "--favor-decSpeed")) { LZ4IO_favorDecSpeed(prefs, 1); continue; } @@ -705,7 +708,34 @@ int main(int argc, const char** argv) operationResult = LZ4IO_decompressMultipleFilenames(prefs, inFileNames, ifnIdx, !strcmp(output_filename,stdoutmark) ? stdoutmark : LZ4_EXTENSION); else operationResult = DEFAULT_DECOMPRESSOR(prefs, input_filename, output_filename); - } else { /* compression is default action */ + } else if (mode == om_list){ + LZ4F_compFileInfo_t cfinfo; + if(!multiple_inputs){ + inFileNames[ifnIdx++] = input_filename; + } + DISPLAY("%16s\t%-20s\t%-20s\t%-10s\t%s\n","BlockChecksumFlag","Compressed", "Uncompressed", "Ratio", "Filename"); + for(i=0; i /* clock */ #include /* stat64 */ #include /* stat64 */ -#include "lz4io.h" #include "lz4.h" /* still required for legacy format */ #include "lz4hc.h" /* still required for legacy format */ #define LZ4F_STATIC_LINKING_ONLY #include "lz4frame.h" +#include "lz4io.h" /***************************** @@ -1265,3 +1265,41 @@ int LZ4IO_decompressMultipleFilenames(LZ4IO_prefs_t* const prefs, const char** i free(outFileName); return missingFiles + skippedFiles; } + +size_t LZ4IO_getCompressedFileInfo(const char* input_filename, LZ4F_compFileInfo_t* cfinfo){ + /* Get file size */ + stat_t statbuf; + if (!UTIL_getFileStat(input_filename, &statbuf)){ + EXM_THROW(60, "Can't stat file : %s", input_filename); + } + cfinfo->fileSize = statbuf.st_size; + /* Get basename without extension */ + const char *b = strrchr(input_filename, '/'); + if (b && b != input_filename){ + b++; + } else{ + b=input_filename; + } + const char *e = strrchr(b, '.'); + cfinfo->fileName = malloc( (e-b+1) * sizeof(char)); + strncpy(cfinfo->fileName, b, (e-b)); + cfinfo->fileName[e-b] = '\0'; + /* init */ + dRess_t ress; + 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)); + FILE* const finput = LZ4IO_openSrcFile(input_filename); + if (finput==NULL) return 1; + /* Allocate Memory */ + ress.srcBuffer = malloc(LZ4IO_dBufferSize); + size_t readSize = LZ4F_HEADER_SIZE_MAX; + if (!fread(ress.srcBuffer, readSize, 1, finput)){ + EXM_THROW(30, "Error reading %s ", input_filename); + } + cfinfo->frameInfo = (LZ4F_frameInfo_t) LZ4F_INIT_FRAMEINFO; + LZ4F_getFrameInfo(ress.dCtx, &cfinfo->frameInfo, ress.srcBuffer, &readSize); + /* Close input/free resources */ + fclose(finput); + free(ress.srcBuffer); + return readSize; +} diff --git a/programs/lz4io.h b/programs/lz4io.h index 54d49be..bf1fa76 100644 --- a/programs/lz4io.h +++ b/programs/lz4io.h @@ -54,6 +54,14 @@ static const char nulmark[] = "/dev/null"; typedef struct LZ4IO_prefs_s LZ4IO_prefs_t; +typedef struct { + LZ4F_frameInfo_t frameInfo; + char* fileName; + unsigned long long fileSize; + double compressionRatio; +} LZ4F_compFileInfo_t; + + LZ4IO_prefs_t* LZ4IO_defaultPreferences(void); void LZ4IO_freePreferences(LZ4IO_prefs_t* const prefs); @@ -116,6 +124,9 @@ int LZ4IO_setSparseFile(LZ4IO_prefs_t* const prefs, int enable); /* Default setting : 0 == no content size present in frame header */ int LZ4IO_setContentSize(LZ4IO_prefs_t* const prefs, int enable); +/* */ +size_t LZ4IO_getCompressedFileInfo(const char* input_filename, LZ4F_compFileInfo_t* cfinfo); + /* Default setting : 0 == src file preserved */ void LZ4IO_setRemoveSrcFile(LZ4IO_prefs_t* const prefs, unsigned flag); -- cgit v0.12 From 55484191c40a2909bf08eb23754a136199c134c2 Mon Sep 17 00:00:00 2001 From: gabrielstedman Date: Sun, 21 Apr 2019 00:20:38 +0100 Subject: correctly use unisgned int for index --- programs/lz4cli.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/programs/lz4cli.c b/programs/lz4cli.c index adfabc3..54d93f1 100644 --- a/programs/lz4cli.c +++ b/programs/lz4cli.c @@ -714,9 +714,9 @@ int main(int argc, const char** argv) inFileNames[ifnIdx++] = input_filename; } DISPLAY("%16s\t%-20s\t%-20s\t%-10s\t%s\n","BlockChecksumFlag","Compressed", "Uncompressed", "Ratio", "Filename"); - for(i=0; i Date: Sun, 21 Apr 2019 17:43:57 +0100 Subject: FR #598 Improve initial design, test mallocs, support C90. --- programs/lz4.1.md | 6 +++ programs/lz4cli.c | 26 ++----------- programs/lz4io.c | 112 ++++++++++++++++++++++++++++++++++++++---------------- programs/lz4io.h | 10 +++-- 4 files changed, 94 insertions(+), 60 deletions(-) diff --git a/programs/lz4.1.md b/programs/lz4.1.md index 10449a0..7db9f19 100644 --- a/programs/lz4.1.md +++ b/programs/lz4.1.md @@ -114,6 +114,11 @@ only the latest one will be applied. * `-b#`: Benchmark mode, using `#` compression level. +* `--list`: + List mode. + Lists information about .lz4 files. + Useful if compressed with --content-size flag. + ### Operation modifiers * `-#`: @@ -161,6 +166,7 @@ only the latest one will be applied. Multiple input files. Compressed file names will be appended a `.lz4` suffix. This mode also reduces notification level. + Can also be used to list multiple files. `lz4 -m` has a behavior equivalent to `gzip -k` (it preserves source files by default). diff --git a/programs/lz4cli.c b/programs/lz4cli.c index 54d93f1..23c4be7 100644 --- a/programs/lz4cli.c +++ b/programs/lz4cli.c @@ -142,7 +142,7 @@ static int usage_advanced(const char* exeName) DISPLAY( " -BX : enable block checksum (default:disabled) \n"); DISPLAY( "--no-frame-crc : disable stream checksum (default:enabled) \n"); DISPLAY( "--content-size : compressed frame includes original size (default:not present)\n"); - DISPLAY( "--list : list information about .lz4 files. Only useful if compressed with --content-size flag.\n"); + DISPLAY( "--list : lists information about .lz4 files. Useful if compressed with --content-size flag.\n"); DISPLAY( "--[no-]sparse : sparse mode (default:enabled on file, disabled on stdout)\n"); DISPLAY( "--favor-decSpeed: compressed files decompress faster, but are less compressed \n"); DISPLAY( "--fast[=#]: switch to ultra fast compression level (default: %i)\n", 1); @@ -709,31 +709,11 @@ int main(int argc, const char** argv) else operationResult = DEFAULT_DECOMPRESSOR(prefs, input_filename, output_filename); } else if (mode == om_list){ - LZ4F_compFileInfo_t cfinfo; if(!multiple_inputs){ inFileNames[ifnIdx++] = input_filename; } - DISPLAY("%16s\t%-20s\t%-20s\t%-10s\t%s\n","BlockChecksumFlag","Compressed", "Uncompressed", "Ratio", "Filename"); - for(unsigned int j=0; jfileSize = statbuf.st_size; - /* Get basename without extension */ - const char *b = strrchr(input_filename, '/'); - if (b && b != input_filename){ - b++; - } else{ - b=input_filename; + if(cfinfo.frameInfo.contentSize){ + DISPLAY("%-16d\t%-20llu\t%-20llu\t%-8.4f\t%s\n",cfinfo.frameInfo.blockChecksumFlag,cfinfo.fileSize,cfinfo.frameInfo.contentSize, cfinfo.ratio, cfinfo.fileName); } - const char *e = strrchr(b, '.'); - cfinfo->fileName = malloc( (e-b+1) * sizeof(char)); - strncpy(cfinfo->fileName, b, (e-b)); - cfinfo->fileName[e-b] = '\0'; - /* init */ - dRess_t ress; - 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)); - FILE* const finput = LZ4IO_openSrcFile(input_filename); - if (finput==NULL) return 1; - /* Allocate Memory */ - ress.srcBuffer = malloc(LZ4IO_dBufferSize); - size_t readSize = LZ4F_HEADER_SIZE_MAX; - if (!fread(ress.srcBuffer, readSize, 1, finput)){ - EXM_THROW(30, "Error reading %s ", input_filename); + else{ + DISPLAY("%-16d\t%-20llu\t%-20s\t%-10s\t%s\n",cfinfo.frameInfo.blockChecksumFlag,cfinfo.fileSize, "-", "-", cfinfo.fileName); } - cfinfo->frameInfo = (LZ4F_frameInfo_t) LZ4F_INIT_FRAMEINFO; - LZ4F_getFrameInfo(ress.dCtx, &cfinfo->frameInfo, ress.srcBuffer, &readSize); - /* Close input/free resources */ - fclose(finput); - free(ress.srcBuffer); - return readSize; + } + return op_result; +} + +int LZ4IO_getCompressedFileInfo(const char* input_filename, LZ4F_compFileInfo_t* cfinfo){ + const char *b, + *e; + char *t; + stat_t statbuf; + size_t readSize = LZ4F_HEADER_SIZE_MAX; + LZ4F_errorCode_t errorCode; + dRess_t ress; + /* Open file */ + FILE* const finput = LZ4IO_openSrcFile(input_filename); + if (finput==NULL) return 0; + *cfinfo = (LZ4F_compFileInfo_t) LZ4F_INIT_FILEINFO; + /* Get file size */ + if (!UTIL_getFileStat(input_filename, &statbuf)){ + EXM_THROW(60, "Can't stat file : %s", input_filename); + } + cfinfo->fileSize = statbuf.st_size; + + /* Get basename without extension */ + b = strrchr(input_filename, '/'); + if (!b){ + b = strrchr(input_filename, '\\'); + } + if (b && b != input_filename){ + b++; + } else{ + b=input_filename; + } + e = strrchr(b, '.'); + /* Allocate Memory */ + t = malloc( (e-b+1) * sizeof(char)); + ress.srcBuffer = malloc(LZ4IO_dBufferSize); + if (!t || !ress.srcBuffer) + EXM_THROW(21, "Allocation error : not enough memory"); + strncpy(t, b, (e-b)); + t[e-b] = '\0'; + cfinfo->fileName = t; + + /* init */ + errorCode = LZ4F_createDecompressionContext(&ress.dCtx, LZ4F_VERSION); + if (LZ4F_isError(errorCode)) EXM_THROW(60, "Can't create LZ4F context : %s", LZ4F_getErrorName(errorCode)); + + if (!fread(ress.srcBuffer, readSize, 1, finput)){ + EXM_THROW(30, "Error reading %s ", input_filename); + } + // cfinfo->frameInfo = (LZ4F_frameInfo_t) LZ4F_INIT_FRAMEINFO; + LZ4F_getFrameInfo(ress.dCtx, &cfinfo->frameInfo, ress.srcBuffer, &readSize); + if(cfinfo->frameInfo.contentSize){ + cfinfo->ratio = (double)cfinfo->fileSize / cfinfo->frameInfo.contentSize; + } else { + cfinfo->ratio = -1; + } + + /* Close input/free resources */ + fclose(finput); + free(ress.srcBuffer); + return 0; } diff --git a/programs/lz4io.h b/programs/lz4io.h index bf1fa76..707f233 100644 --- a/programs/lz4io.h +++ b/programs/lz4io.h @@ -56,11 +56,12 @@ typedef struct LZ4IO_prefs_s LZ4IO_prefs_t; typedef struct { LZ4F_frameInfo_t frameInfo; - char* fileName; + const char* fileName; unsigned long long fileSize; - double compressionRatio; + double ratio; } LZ4F_compFileInfo_t; +#define LZ4F_INIT_FILEINFO { (LZ4F_frameInfo_t) LZ4F_INIT_FRAMEINFO, NULL, 0ULL, -1.f } LZ4IO_prefs_t* LZ4IO_defaultPreferences(void); void LZ4IO_freePreferences(LZ4IO_prefs_t* const prefs); @@ -124,8 +125,9 @@ int LZ4IO_setSparseFile(LZ4IO_prefs_t* const prefs, int enable); /* Default setting : 0 == no content size present in frame header */ int LZ4IO_setContentSize(LZ4IO_prefs_t* const prefs, int enable); -/* */ -size_t LZ4IO_getCompressedFileInfo(const char* input_filename, LZ4F_compFileInfo_t* cfinfo); +int LZ4IO_getCompressedFilesInfo(const char** inFileNames,const size_t ifnIdx); + +int LZ4IO_getCompressedFileInfo(const char* input_filename, LZ4F_compFileInfo_t* cfinfo); /* Default setting : 0 == src file preserved */ void LZ4IO_setRemoveSrcFile(LZ4IO_prefs_t* const prefs, unsigned flag); -- cgit v0.12 From 2133366da080aaa2dbec2a33b52ad236cb493b01 Mon Sep 17 00:00:00 2001 From: gabrielstedman Date: Mon, 22 Apr 2019 09:00:20 +0100 Subject: FR #598 - Make LZ4IO_getCompressedFileInfo internal and reword func --- programs/lz4cli.c | 3 +- programs/lz4io.c | 132 ++++++++++++++++++++++++++---------------------------- programs/lz4io.h | 9 ++-- 3 files changed, 68 insertions(+), 76 deletions(-) diff --git a/programs/lz4cli.c b/programs/lz4cli.c index 23c4be7..9a74286 100644 --- a/programs/lz4cli.c +++ b/programs/lz4cli.c @@ -40,7 +40,6 @@ #include /* exit, calloc, free */ #include /* strcmp, strlen */ #include "bench.h" /* BMK_benchFile, BMK_SetNbIterations, BMK_SetBlocksize, BMK_SetPause */ -#include "lz4frame.h" #include "lz4io.h" /* LZ4IO_compressFilename, LZ4IO_decompressFilename, LZ4IO_compressMultipleFilenames */ #include "lz4hc.h" /* LZ4HC_CLEVEL_MAX */ #include "lz4.h" /* LZ4_VERSION_STRING */ @@ -712,7 +711,7 @@ int main(int argc, const char** argv) if(!multiple_inputs){ inFileNames[ifnIdx++] = input_filename; } - operationResult = LZ4IO_getCompressedFilesInfo(inFileNames, ifnIdx); + operationResult = LZ4IO_displayCompressedFilesInfo(inFileNames, ifnIdx); inFileNames=NULL; } else { /* compression is default action */ diff --git a/programs/lz4io.c b/programs/lz4io.c index 2e38d2f..61fa13f 100644 --- a/programs/lz4io.c +++ b/programs/lz4io.c @@ -1214,6 +1214,60 @@ static int LZ4IO_decompressDstFile(LZ4IO_prefs_t* const prefs, dRess_t ress, con } +static int LZ4IO_getCompressedFileInfo(const char* input_filename, LZ4F_compFileInfo_t* cfinfo){ + const char *b, + *e; + char *t; + size_t readSize = LZ4F_HEADER_SIZE_MAX; + LZ4F_errorCode_t errorCode; + dRess_t ress; + // LZ4F_compFileInfo_t cfinfo = (LZ4F_compFileInfo_t) LZ4F_INIT_FILEINFO; + /* Open file */ + FILE* const finput = LZ4IO_openSrcFile(input_filename); + if (finput==NULL) return 1; + + /* Get file size */ + if (!UTIL_getFileStat(input_filename, &cfinfo->fileStat)){ + EXM_THROW(60, "Can't stat file : %s", input_filename); + } + + /* Get basename without extension */ + b = strrchr(input_filename, '/'); + if (!b){ + b = strrchr(input_filename, '\\'); + } + if (b && b != input_filename){ + b++; + } else{ + b=input_filename; + } + e = strrchr(b, '.'); + + /* Allocate Memory */ + t = malloc( (e-b+1) * sizeof(char)); + ress.srcBuffer = malloc(LZ4IO_dBufferSize); + if (!t || !ress.srcBuffer) + EXM_THROW(21, "Allocation error : not enough memory"); + strncpy(t, b, (e-b)); + t[e-b] = '\0'; + cfinfo->fileName = t; + + /* init */ + errorCode = LZ4F_createDecompressionContext(&ress.dCtx, LZ4F_VERSION); + if (LZ4F_isError(errorCode)) EXM_THROW(60, "Can't create LZ4F context : %s", LZ4F_getErrorName(errorCode)); + + if (!fread(ress.srcBuffer, readSize, 1, finput)){ + EXM_THROW(30, "Error reading %s ", input_filename); + } + LZ4F_getFrameInfo(ress.dCtx, &cfinfo->frameInfo, ress.srcBuffer, &readSize); + + /* Close input/free resources */ + fclose(finput); + free(ress.srcBuffer); + return 0; +} + + int LZ4IO_decompressFilename(LZ4IO_prefs_t* const prefs, const char* input_filename, const char* output_filename) { dRess_t const ress = LZ4IO_createDResources(prefs); @@ -1266,86 +1320,28 @@ int LZ4IO_decompressMultipleFilenames(LZ4IO_prefs_t* const prefs, const char** i return missingFiles + skippedFiles; } -int LZ4IO_getCompressedFilesInfo(const char** inFileNames, const size_t ifnIdx){ + +int LZ4IO_displayCompressedFilesInfo(const char** inFileNames, const size_t ifnIdx){ size_t idx; int op_result=0; - LZ4F_compFileInfo_t cfinfo = (LZ4F_compFileInfo_t) LZ4F_INIT_FILEINFO; + double ratio; + LZ4F_compFileInfo_t cfinfo; DISPLAY("%16s\t%-20s\t%-20s\t%-10s\t%s\n","BlockChecksumFlag","Compressed", "Uncompressed", "Ratio", "Filename"); for(idx=0; idxfileSize = statbuf.st_size; - - /* Get basename without extension */ - b = strrchr(input_filename, '/'); - if (!b){ - b = strrchr(input_filename, '\\'); - } - if (b && b != input_filename){ - b++; - } else{ - b=input_filename; - } - e = strrchr(b, '.'); - /* Allocate Memory */ - t = malloc( (e-b+1) * sizeof(char)); - ress.srcBuffer = malloc(LZ4IO_dBufferSize); - if (!t || !ress.srcBuffer) - EXM_THROW(21, "Allocation error : not enough memory"); - strncpy(t, b, (e-b)); - t[e-b] = '\0'; - cfinfo->fileName = t; - - /* init */ - errorCode = LZ4F_createDecompressionContext(&ress.dCtx, LZ4F_VERSION); - if (LZ4F_isError(errorCode)) EXM_THROW(60, "Can't create LZ4F context : %s", LZ4F_getErrorName(errorCode)); - - if (!fread(ress.srcBuffer, readSize, 1, finput)){ - EXM_THROW(30, "Error reading %s ", input_filename); - } - // cfinfo->frameInfo = (LZ4F_frameInfo_t) LZ4F_INIT_FRAMEINFO; - LZ4F_getFrameInfo(ress.dCtx, &cfinfo->frameInfo, ress.srcBuffer, &readSize); - if(cfinfo->frameInfo.contentSize){ - cfinfo->ratio = (double)cfinfo->fileSize / cfinfo->frameInfo.contentSize; - } else { - cfinfo->ratio = -1; - } - - /* Close input/free resources */ - fclose(finput); - free(ress.srcBuffer); - return 0; -} diff --git a/programs/lz4io.h b/programs/lz4io.h index 707f233..3d37bd0 100644 --- a/programs/lz4io.h +++ b/programs/lz4io.h @@ -57,11 +57,10 @@ typedef struct LZ4IO_prefs_s LZ4IO_prefs_t; typedef struct { LZ4F_frameInfo_t frameInfo; const char* fileName; - unsigned long long fileSize; - double ratio; + stat_t fileStat; } LZ4F_compFileInfo_t; -#define LZ4F_INIT_FILEINFO { (LZ4F_frameInfo_t) LZ4F_INIT_FRAMEINFO, NULL, 0ULL, -1.f } +#define LZ4F_INIT_FILEINFO { (LZ4F_frameInfo_t) LZ4F_INIT_FRAMEINFO, NULL, stat_t() } LZ4IO_prefs_t* LZ4IO_defaultPreferences(void); void LZ4IO_freePreferences(LZ4IO_prefs_t* const prefs); @@ -125,9 +124,7 @@ int LZ4IO_setSparseFile(LZ4IO_prefs_t* const prefs, int enable); /* Default setting : 0 == no content size present in frame header */ int LZ4IO_setContentSize(LZ4IO_prefs_t* const prefs, int enable); -int LZ4IO_getCompressedFilesInfo(const char** inFileNames,const size_t ifnIdx); - -int LZ4IO_getCompressedFileInfo(const char* input_filename, LZ4F_compFileInfo_t* cfinfo); +int LZ4IO_displayCompressedFilesInfo(const char** inFileNames,const size_t ifnIdx); /* Default setting : 0 == src file preserved */ void LZ4IO_setRemoveSrcFile(LZ4IO_prefs_t* const prefs, unsigned flag); -- cgit v0.12 From 0acebbe53dd1b15071f2c48a7b060299b5d03622 Mon Sep 17 00:00:00 2001 From: gabrielstedman Date: Mon, 22 Apr 2019 09:58:26 +0100 Subject: FR #598 - Move LZ4F_compFileInfo_t def to lz4frame.h discard output_file assert if in om_list mode --- lib/lz4frame.h | 7 +++++++ programs/lz4cli.c | 13 ++++++++++--- programs/lz4io.c | 11 +++++++---- programs/lz4io.h | 8 -------- 4 files changed, 24 insertions(+), 15 deletions(-) diff --git a/lib/lz4frame.h b/lib/lz4frame.h index 742c252..5945647 100644 --- a/lib/lz4frame.h +++ b/lib/lz4frame.h @@ -193,6 +193,13 @@ typedef struct { #define LZ4F_INIT_PREFERENCES { LZ4F_INIT_FRAMEINFO, 0, 0u, 0u, { 0u, 0u, 0u } } /* v1.8.3+ */ +typedef struct { + LZ4F_frameInfo_t frameInfo; + const char* fileName; + unsigned long fileSize; +} LZ4F_compFileInfo_t; + +#define LZ4F_INIT_FILEINFO { (LZ4F_frameInfo_t) LZ4F_INIT_FRAMEINFO, NULL, 0UL } /*-********************************* * Simple compression function diff --git a/programs/lz4cli.c b/programs/lz4cli.c index 3315773..443e4b4 100644 --- a/programs/lz4cli.c +++ b/programs/lz4cli.c @@ -693,7 +693,7 @@ int main(int argc, const char** argv) break; } - if (multiple_inputs==0) assert(output_filename); + if (multiple_inputs==0 && mode != om_list) assert(output_filename); /* when multiple_inputs==1, output_filename may simply be useless, * however, output_filename must be !NULL for next strcmp() tests */ if (!output_filename) output_filename = "*\\dummy^!//"; @@ -721,7 +721,14 @@ int main(int argc, const char** argv) operationResult = LZ4IO_decompressMultipleFilenames(prefs, inFileNames, (int)ifnIdx, !strcmp(output_filename,stdoutmark) ? stdoutmark : LZ4_EXTENSION); } else { operationResult = DEFAULT_DECOMPRESSOR(prefs, input_filename, output_filename); - + } + } else if (mode == om_list){ + if(!multiple_inputs){ + inFileNames[ifnIdx++] = input_filename; + } + operationResult = LZ4IO_displayCompressedFilesInfo(inFileNames, ifnIdx); + inFileNames=NULL; + } else { /* compression is default action */ if (legacy_format) { DISPLAYLEVEL(3, "! Generating LZ4 Legacy format (deprecated) ! \n"); LZ4IO_compressFilename_Legacy(prefs, input_filename, output_filename, cLevel); @@ -745,4 +752,4 @@ _cleanup: LZ4IO_freePreferences(prefs); free((void*)inFileNames); return operationResult; -} +} \ No newline at end of file diff --git a/programs/lz4io.c b/programs/lz4io.c index 61fa13f..070e22a 100644 --- a/programs/lz4io.c +++ b/programs/lz4io.c @@ -1218,6 +1218,7 @@ static int LZ4IO_getCompressedFileInfo(const char* input_filename, LZ4F_compFil const char *b, *e; char *t; + stat_t statbuf; size_t readSize = LZ4F_HEADER_SIZE_MAX; LZ4F_errorCode_t errorCode; dRess_t ress; @@ -1227,10 +1228,12 @@ static int LZ4IO_getCompressedFileInfo(const char* input_filename, LZ4F_compFil if (finput==NULL) return 1; /* Get file size */ - if (!UTIL_getFileStat(input_filename, &cfinfo->fileStat)){ + if (!UTIL_getFileStat(input_filename, &statbuf)){ EXM_THROW(60, "Can't stat file : %s", input_filename); } + cfinfo->fileSize = statbuf.st_size; + /* Get basename without extension */ b = strrchr(input_filename, '/'); if (!b){ @@ -1336,11 +1339,11 @@ int LZ4IO_displayCompressedFilesInfo(const char** inFileNames, const size_t ifnI break; } if(cfinfo.frameInfo.contentSize){ - ratio = (double)cfinfo.fileStat.st_size / cfinfo.frameInfo.contentSize; - DISPLAY("%-16d\t%-20lu\t%-20llu\t%-8.4f\t%s\n",cfinfo.frameInfo.blockChecksumFlag,cfinfo.fileStat.st_size,cfinfo.frameInfo.contentSize, ratio, cfinfo.fileName); + ratio = (double)cfinfo.fileSize / cfinfo.frameInfo.contentSize; + DISPLAY("%-16d\t%-20lu\t%-20llu\t%-8.4f\t%s\n",cfinfo.frameInfo.blockChecksumFlag,cfinfo.fileSize,cfinfo.frameInfo.contentSize, ratio, cfinfo.fileName); } else{ - DISPLAY("%-16d\t%-20lu\t%-20s\t%-10s\t%s\n",cfinfo.frameInfo.blockChecksumFlag,cfinfo.fileStat.st_size, "-", "-", cfinfo.fileName); + DISPLAY("%-16d\t%-20lu\t%-20s\t%-10s\t%s\n",cfinfo.frameInfo.blockChecksumFlag,cfinfo.fileSize, "-", "-", cfinfo.fileName); } } return op_result; diff --git a/programs/lz4io.h b/programs/lz4io.h index fcda5f1..2008b55 100644 --- a/programs/lz4io.h +++ b/programs/lz4io.h @@ -52,14 +52,6 @@ static const char nulmark[] = "/dev/null"; /* ****************** Type Definitions ************** */ /* ************************************************** */ -typedef struct { - LZ4F_frameInfo_t frameInfo; - const char* fileName; - stat_t fileStat; -} LZ4F_compFileInfo_t; - -#define LZ4F_INIT_FILEINFO { (LZ4F_frameInfo_t) LZ4F_INIT_FRAMEINFO, NULL, stat_t() } - typedef struct LZ4IO_prefs_s LZ4IO_prefs_t; LZ4IO_prefs_t* LZ4IO_defaultPreferences(void); -- cgit v0.12 From e31b6dc03ca464de55ebb403fb0ef6470d99e1a0 Mon Sep 17 00:00:00 2001 From: gabrielstedman Date: Mon, 22 Apr 2019 10:35:29 +0100 Subject: FR #598 - Make fileSize unsigned long long --- lib/lz4frame.h | 4 ++-- programs/lz4io.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/lz4frame.h b/lib/lz4frame.h index 5945647..8c07e86 100644 --- a/lib/lz4frame.h +++ b/lib/lz4frame.h @@ -196,10 +196,10 @@ typedef struct { typedef struct { LZ4F_frameInfo_t frameInfo; const char* fileName; - unsigned long fileSize; + unsigned long long fileSize; } LZ4F_compFileInfo_t; -#define LZ4F_INIT_FILEINFO { (LZ4F_frameInfo_t) LZ4F_INIT_FRAMEINFO, NULL, 0UL } +#define LZ4F_INIT_FILEINFO { (LZ4F_frameInfo_t) LZ4F_INIT_FRAMEINFO, NULL, 0ULL } /*-********************************* * Simple compression function diff --git a/programs/lz4io.c b/programs/lz4io.c index 070e22a..9aa2b94 100644 --- a/programs/lz4io.c +++ b/programs/lz4io.c @@ -1340,10 +1340,10 @@ int LZ4IO_displayCompressedFilesInfo(const char** inFileNames, const size_t ifnI } if(cfinfo.frameInfo.contentSize){ ratio = (double)cfinfo.fileSize / cfinfo.frameInfo.contentSize; - DISPLAY("%-16d\t%-20lu\t%-20llu\t%-8.4f\t%s\n",cfinfo.frameInfo.blockChecksumFlag,cfinfo.fileSize,cfinfo.frameInfo.contentSize, ratio, cfinfo.fileName); + DISPLAY("%-16d\t%-20llu\t%-20llu\t%-8.4f\t%s\n",cfinfo.frameInfo.blockChecksumFlag,cfinfo.fileSize,cfinfo.frameInfo.contentSize, ratio, cfinfo.fileName); } else{ - DISPLAY("%-16d\t%-20lu\t%-20s\t%-10s\t%s\n",cfinfo.frameInfo.blockChecksumFlag,cfinfo.fileSize, "-", "-", cfinfo.fileName); + DISPLAY("%-16d\t%-20llu\t%-20s\t%-10s\t%s\n",cfinfo.frameInfo.blockChecksumFlag,cfinfo.fileSize, "-", "-", cfinfo.fileName); } } return op_result; -- cgit v0.12 From 84f978a2f3a787c7646ab3773fa7c41bddbb849e Mon Sep 17 00:00:00 2001 From: gabrielstedman Date: Mon, 22 Apr 2019 11:07:08 +0100 Subject: FR #598 - Correctly initialize cfinfo & cast malloc res to (char*) --- programs/lz4io.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/programs/lz4io.c b/programs/lz4io.c index 9aa2b94..175157e 100644 --- a/programs/lz4io.c +++ b/programs/lz4io.c @@ -1222,7 +1222,6 @@ static int LZ4IO_getCompressedFileInfo(const char* input_filename, LZ4F_compFil size_t readSize = LZ4F_HEADER_SIZE_MAX; LZ4F_errorCode_t errorCode; dRess_t ress; - // LZ4F_compFileInfo_t cfinfo = (LZ4F_compFileInfo_t) LZ4F_INIT_FILEINFO; /* Open file */ FILE* const finput = LZ4IO_openSrcFile(input_filename); if (finput==NULL) return 1; @@ -1247,7 +1246,7 @@ static int LZ4IO_getCompressedFileInfo(const char* input_filename, LZ4F_compFil e = strrchr(b, '.'); /* Allocate Memory */ - t = malloc( (e-b+1) * sizeof(char)); + t = (char*)malloc( (e-b+1) * sizeof(char)); ress.srcBuffer = malloc(LZ4IO_dBufferSize); if (!t || !ress.srcBuffer) EXM_THROW(21, "Allocation error : not enough memory"); @@ -1332,6 +1331,7 @@ int LZ4IO_displayCompressedFilesInfo(const char** inFileNames, const size_t ifnI DISPLAY("%16s\t%-20s\t%-20s\t%-10s\t%s\n","BlockChecksumFlag","Compressed", "Uncompressed", "Ratio", "Filename"); for(idx=0; idx Date: Mon, 22 Apr 2019 12:27:25 -0700 Subject: fixed C90 compliance re-structure code, have everything into a single section of lz4io.c --- lib/lz4frame.h | 7 --- programs/lz4cli.c | 2 +- programs/lz4io.c | 127 +++++++++++++++++++++++++++++------------------------- programs/lz4io.h | 6 ++- 4 files changed, 74 insertions(+), 68 deletions(-) diff --git a/lib/lz4frame.h b/lib/lz4frame.h index 8c07e86..742c252 100644 --- a/lib/lz4frame.h +++ b/lib/lz4frame.h @@ -193,13 +193,6 @@ typedef struct { #define LZ4F_INIT_PREFERENCES { LZ4F_INIT_FRAMEINFO, 0, 0u, 0u, { 0u, 0u, 0u } } /* v1.8.3+ */ -typedef struct { - LZ4F_frameInfo_t frameInfo; - const char* fileName; - unsigned long long fileSize; -} LZ4F_compFileInfo_t; - -#define LZ4F_INIT_FILEINFO { (LZ4F_frameInfo_t) LZ4F_INIT_FRAMEINFO, NULL, 0ULL } /*-********************************* * Simple compression function diff --git a/programs/lz4cli.c b/programs/lz4cli.c index 443e4b4..39ff1ea 100644 --- a/programs/lz4cli.c +++ b/programs/lz4cli.c @@ -752,4 +752,4 @@ _cleanup: LZ4IO_freePreferences(prefs); free((void*)inFileNames); return operationResult; -} \ No newline at end of file +} diff --git a/programs/lz4io.c b/programs/lz4io.c index 175157e..1e6efe1 100644 --- a/programs/lz4io.c +++ b/programs/lz4io.c @@ -1214,62 +1214,6 @@ static int LZ4IO_decompressDstFile(LZ4IO_prefs_t* const prefs, dRess_t ress, con } -static int LZ4IO_getCompressedFileInfo(const char* input_filename, LZ4F_compFileInfo_t* cfinfo){ - const char *b, - *e; - char *t; - stat_t statbuf; - size_t readSize = LZ4F_HEADER_SIZE_MAX; - LZ4F_errorCode_t errorCode; - dRess_t ress; - /* Open file */ - FILE* const finput = LZ4IO_openSrcFile(input_filename); - if (finput==NULL) return 1; - - /* Get file size */ - if (!UTIL_getFileStat(input_filename, &statbuf)){ - EXM_THROW(60, "Can't stat file : %s", input_filename); - } - - cfinfo->fileSize = statbuf.st_size; - - /* Get basename without extension */ - b = strrchr(input_filename, '/'); - if (!b){ - b = strrchr(input_filename, '\\'); - } - if (b && b != input_filename){ - b++; - } else{ - b=input_filename; - } - e = strrchr(b, '.'); - - /* Allocate Memory */ - t = (char*)malloc( (e-b+1) * sizeof(char)); - ress.srcBuffer = malloc(LZ4IO_dBufferSize); - if (!t || !ress.srcBuffer) - EXM_THROW(21, "Allocation error : not enough memory"); - strncpy(t, b, (e-b)); - t[e-b] = '\0'; - cfinfo->fileName = t; - - /* init */ - errorCode = LZ4F_createDecompressionContext(&ress.dCtx, LZ4F_VERSION); - if (LZ4F_isError(errorCode)) EXM_THROW(60, "Can't create LZ4F context : %s", LZ4F_getErrorName(errorCode)); - - if (!fread(ress.srcBuffer, readSize, 1, finput)){ - EXM_THROW(30, "Error reading %s ", input_filename); - } - LZ4F_getFrameInfo(ress.dCtx, &cfinfo->frameInfo, ress.srcBuffer, &readSize); - - /* Close input/free resources */ - fclose(finput); - free(ress.srcBuffer); - return 0; -} - - int LZ4IO_decompressFilename(LZ4IO_prefs_t* const prefs, const char* input_filename, const char* output_filename) { dRess_t const ress = LZ4IO_createDResources(prefs); @@ -1323,15 +1267,82 @@ int LZ4IO_decompressMultipleFilenames(LZ4IO_prefs_t* const prefs, const char** i } +/* ********************************************************************* */ +/* ********************** LZ4 --list command *********************** */ +/* ********************************************************************* */ + +typedef struct { + LZ4F_frameInfo_t frameInfo; + const char* fileName; + unsigned long long fileSize; +} LZ4F_compFileInfo_t; + +#define LZ4F_INIT_FILEINFO { LZ4F_INIT_FRAMEINFO, NULL, 0ULL } + + +static int LZ4IO_getCompressedFileInfo(const char* input_filename, LZ4F_compFileInfo_t* cfinfo){ + const char *b, + *e; + char *t; + stat_t statbuf; + size_t readSize = LZ4F_HEADER_SIZE_MAX; + LZ4F_errorCode_t errorCode; + dRess_t ress; + /* Open file */ + FILE* const finput = LZ4IO_openSrcFile(input_filename); + if (finput==NULL) return 1; + + /* Get file size */ + if (!UTIL_getFileStat(input_filename, &statbuf)){ + EXM_THROW(60, "Can't stat file : %s", input_filename); + } + + cfinfo->fileSize = (unsigned long long)statbuf.st_size; + + /* Get basename without extension */ + b = strrchr(input_filename, '/'); + if (!b){ + b = strrchr(input_filename, '\\'); + } + if (b && b != input_filename){ + b++; + } else{ + b=input_filename; + } + e = strrchr(b, '.'); + + /* Allocate Memory */ + t = (char*)malloc( (size_t)(e-b+1) * sizeof(char)); + ress.srcBuffer = malloc(LZ4IO_dBufferSize); + if (!t || !ress.srcBuffer) + EXM_THROW(21, "Allocation error : not enough memory"); + strncpy(t, b, (e-b)); + t[e-b] = '\0'; + cfinfo->fileName = t; + + /* init */ + errorCode = LZ4F_createDecompressionContext(&ress.dCtx, LZ4F_VERSION); + if (LZ4F_isError(errorCode)) EXM_THROW(60, "Can't create LZ4F context : %s", LZ4F_getErrorName(errorCode)); + + if (!fread(ress.srcBuffer, readSize, 1, finput)){ + EXM_THROW(30, "Error reading %s ", input_filename); + } + LZ4F_getFrameInfo(ress.dCtx, &cfinfo->frameInfo, ress.srcBuffer, &readSize); + + /* Close input/free resources */ + fclose(finput); + free(ress.srcBuffer); + return 0; +} + int LZ4IO_displayCompressedFilesInfo(const char** inFileNames, const size_t ifnIdx){ size_t idx; int op_result=0; double ratio; - LZ4F_compFileInfo_t cfinfo; DISPLAY("%16s\t%-20s\t%-20s\t%-10s\t%s\n","BlockChecksumFlag","Compressed", "Uncompressed", "Ratio", "Filename"); for(idx=0; idx Date: Mon, 22 Apr 2019 14:01:19 -0700 Subject: refactored --list function better handling of special conditions, better scoping of variables. Also : updated man page --- programs/lz4.1 | 24 ++++---- programs/lz4io.c | 176 ++++++++++++++++++++++++++++++------------------------- programs/lz4io.h | 3 +- tests/Makefile | 1 + 4 files changed, 111 insertions(+), 93 deletions(-) diff --git a/programs/lz4.1 b/programs/lz4.1 index 1576e45..eb82b68 100644 --- a/programs/lz4.1 +++ b/programs/lz4.1 @@ -1,5 +1,5 @@ . -.TH "LZ4" "1" "April 2019" "lz4 1.9.0" "User Commands" +.TH "LZ4" "1" "April 2019" "lz4 1.9.1" "User Commands" . .SH "NAME" \fBlz4\fR \- lz4, unlz4, lz4cat \- Compress or decompress \.lz4 files @@ -23,9 +23,6 @@ When writing scripts that need to decompress files, it is recommended to always \fBlz4\fR supports a command line syntax similar \fIbut not identical\fR to \fBgzip(1)\fR\. Differences are : . .IP "\(bu" 4 -\fBlz4\fR preserves original files -. -.IP "\(bu" 4 \fBlz4\fR compresses a single file by default (see \fB\-m\fR for multiple files) . .IP "\(bu" 4 @@ -35,19 +32,16 @@ When writing scripts that need to decompress files, it is recommended to always \fBlz4 file\.lz4\fR will default to decompression (use \fB\-z\fR to force compression) . .IP "\(bu" 4 -\fBlz4\fR shows real\-time notification statistics during compression or decompression of a single file (use \fB\-q\fR to silence them) -. -.IP "\(bu" 4 -If no destination name is provided, result is sent to \fBstdout\fR \fIexcept if stdout is the console\fR\. +\fBlz4\fR preserves original files . .IP "\(bu" 4 -If no destination name is provided, \fBand\fR if \fBstdout\fR is the console, \fBfile\fR is compressed into \fBfile\.lz4\fR\. +\fBlz4\fR shows real\-time notification statistics during compression or decompression of a single file (use \fB\-q\fR to silence them) . .IP "\(bu" 4 -As a consequence of previous rules, note the following example : \fBlz4 file | consumer\fR sends compressed data to \fBconsumer\fR through \fBstdout\fR, hence it does \fInot\fR create \fBfile\.lz4\fR\. +When no destination is specified, result is sent on implicit output, which depends on \fBstdout\fR status\. When \fBstdout\fR \fIis Not the console\fR, it becomes the implicit output\. Otherwise, if \fBstdout\fR is the console, the implicit output is \fBfilename\.lz4\fR\. . .IP "\(bu" 4 -Another consequence of those rules is that to run \fBlz4\fR under \fBnohup\fR, you should provide a destination file: \fBnohup lz4 file file\.lz4\fR, because \fBnohup\fR writes the specified command\'s output to a file\. +It is considered bad practice to rely on implicit output in scripts\. because the script\'s environment may change\. Always use explicit output in scripts\. \fB\-c\fR ensures that output will be \fBstdout\fR\. Conversely, providing a destination name, or using \fB\-m\fR ensures that the output will be either the specified name, or \fBfilename\.lz4\fR respectively\. . .IP "" 0 . @@ -55,7 +49,7 @@ Another consequence of those rules is that to run \fBlz4\fR under \fBnohup\fR, y Default behaviors can be modified by opt\-in commands, detailed below\. . .IP "\(bu" 4 -\fBlz4 \-m\fR makes it possible to provide multiple input filenames, which will be compressed into files using suffix \fB\.lz4\fR\. Progress notifications are also disabled by default (use \fB\-v\fR to enable them)\. This mode has a behavior which more closely mimics \fBgzip\fR command line, with the main remaining difference being that source files are preserved by default\. +\fBlz4 \-m\fR makes it possible to provide multiple input filenames, which will be compressed into files using suffix \fB\.lz4\fR\. Progress notifications become disabled by default (use \fB\-v\fR to enable them)\. This mode has a behavior which more closely mimics \fBgzip\fR command line, with the main remaining difference being that source files are preserved by default\. . .IP "\(bu" 4 Similarly, \fBlz4 \-m \-d\fR can decompress multiple \fB*\.lz4\fR files\. @@ -111,6 +105,10 @@ Test the integrity of compressed \fB\.lz4\fR files\. The decompressed data is di \fB\-b#\fR Benchmark mode, using \fB#\fR compression level\. . +.TP +\fB\-\-list\fR +List mode\. Lists information about \.lz4 files\. Useful if compressed with \-\-content\-size flag\. +. .SS "Operation modifiers" . .TP @@ -145,7 +143,7 @@ Force write to standard output, even if it is the console\. . .TP \fB\-m\fR \fB\-\-multiple\fR -Multiple input files\. Compressed file names will be appended a \fB\.lz4\fR suffix\. This mode also reduces notification level\. \fBlz4 \-m\fR has a behavior equivalent to \fBgzip \-k\fR (it preserves source files by default)\. +Multiple input files\. Compressed file names will be appended a \fB\.lz4\fR suffix\. This mode also reduces notification level\. Can also be used to list multiple files\. \fBlz4 \-m\fR has a behavior equivalent to \fBgzip \-k\fR (it preserves source files by default)\. . .TP \fB\-r\fR diff --git a/programs/lz4io.c b/programs/lz4io.c index 1e6efe1..e3eed93 100644 --- a/programs/lz4io.c +++ b/programs/lz4io.c @@ -1275,87 +1275,105 @@ typedef struct { LZ4F_frameInfo_t frameInfo; const char* fileName; unsigned long long fileSize; -} LZ4F_compFileInfo_t; - -#define LZ4F_INIT_FILEINFO { LZ4F_INIT_FRAMEINFO, NULL, 0ULL } - - -static int LZ4IO_getCompressedFileInfo(const char* input_filename, LZ4F_compFileInfo_t* cfinfo){ - const char *b, - *e; - char *t; - stat_t statbuf; - size_t readSize = LZ4F_HEADER_SIZE_MAX; - LZ4F_errorCode_t errorCode; - dRess_t ress; - /* Open file */ - FILE* const finput = LZ4IO_openSrcFile(input_filename); - if (finput==NULL) return 1; - - /* Get file size */ - if (!UTIL_getFileStat(input_filename, &statbuf)){ - EXM_THROW(60, "Can't stat file : %s", input_filename); - } - - cfinfo->fileSize = (unsigned long long)statbuf.st_size; - - /* Get basename without extension */ - b = strrchr(input_filename, '/'); - if (!b){ - b = strrchr(input_filename, '\\'); - } - if (b && b != input_filename){ - b++; - } else{ - b=input_filename; - } - e = strrchr(b, '.'); - - /* Allocate Memory */ - t = (char*)malloc( (size_t)(e-b+1) * sizeof(char)); - ress.srcBuffer = malloc(LZ4IO_dBufferSize); - if (!t || !ress.srcBuffer) - EXM_THROW(21, "Allocation error : not enough memory"); - strncpy(t, b, (e-b)); - t[e-b] = '\0'; - cfinfo->fileName = t; - - /* init */ - errorCode = LZ4F_createDecompressionContext(&ress.dCtx, LZ4F_VERSION); - if (LZ4F_isError(errorCode)) EXM_THROW(60, "Can't create LZ4F context : %s", LZ4F_getErrorName(errorCode)); - - if (!fread(ress.srcBuffer, readSize, 1, finput)){ - EXM_THROW(30, "Error reading %s ", input_filename); - } - LZ4F_getFrameInfo(ress.dCtx, &cfinfo->frameInfo, ress.srcBuffer, &readSize); - - /* Close input/free resources */ - fclose(finput); - free(ress.srcBuffer); - return 0; -} +} LZ4IO_cFileInfo_t; + +#define LZ4IO_INIT_CFILEINFO { LZ4F_INIT_FRAMEINFO, NULL, 0ULL } + + +/* This function is limited, + * it only works fine for a file consisting of a single valid frame. + * It will / may stop program execution if a single filename is wrong. + * It will not look at content beyond first frame header. + * + * Things to improve : + * - continue execution after an error, just report an error code, keep all memory clean + * - check the entire file for additional content after first frame + * + combine results from multiple frames, give total + * - Optional : + * + report nb of blocks, hence max. possible decompressed size (when not reported in header) + * + report block type (B4D, B7I, etc.) + */ +static int +LZ4IO_getCompressedFileInfo(LZ4IO_cFileInfo_t* cfinfo, const char* input_filename) +{ + /* Get file size */ + cfinfo->fileSize = UTIL_getFileSize(input_filename); /* returns 0 if cannot read information */ -int LZ4IO_displayCompressedFilesInfo(const char** inFileNames, const size_t ifnIdx){ - size_t idx; - int op_result=0; - double ratio; - DISPLAY("%16s\t%-20s\t%-20s\t%-10s\t%s\n","BlockChecksumFlag","Compressed", "Uncompressed", "Ratio", "Filename"); - for(idx=0; idxfileName = b; } - if(cfinfo.frameInfo.contentSize){ - ratio = (double)cfinfo.fileSize / cfinfo.frameInfo.contentSize; - DISPLAY("%-16d\t%-20llu\t%-20llu\t%-8.4f\t%s\n",cfinfo.frameInfo.blockChecksumFlag,cfinfo.fileSize,cfinfo.frameInfo.contentSize, ratio, cfinfo.fileName); + + /* Read file and extract header */ + { size_t readSize = LZ4F_HEADER_SIZE_MAX; + void* buffer = malloc(readSize); + LZ4F_dctx* dctx; + + if (!buffer) EXM_THROW(21, "Allocation error : not enough memory"); + { LZ4F_errorCode_t const errorCode = + LZ4F_createDecompressionContext(&dctx, LZ4F_VERSION); + if (LZ4F_isError(errorCode)) + EXM_THROW(60, "Can't create LZ4F context : %s", + LZ4F_getErrorName(errorCode)); + } + + { FILE* const finput = LZ4IO_openSrcFile(input_filename); + if (finput==NULL) return 1; + if (!fread(buffer, readSize, 1, finput)) { + EXM_THROW(30, "Error reading %s ", input_filename); + } + fclose(finput); + } + + { LZ4F_errorCode_t const errorCode = + LZ4F_getFrameInfo(dctx, &cfinfo->frameInfo, buffer, &readSize); + if (LZ4F_isError(errorCode)) + EXM_THROW(60, "Cannot interpret LZ4 frame : %s", + LZ4F_getErrorName(errorCode)); + } + + /* clean */ + free(buffer); + LZ4F_freeDecompressionContext(dctx); } - else{ - DISPLAY("%-16d\t%-20llu\t%-20s\t%-10s\t%s\n",cfinfo.frameInfo.blockChecksumFlag,cfinfo.fileSize, "-", "-", cfinfo.fileName); + + return 0; +} + +int LZ4IO_displayCompressedFilesInfo(const char** inFileNames, const size_t ifnIdx) +{ + size_t idx; + + DISPLAY("%16s\t%-20s\t%-20s\t%-10s\t%s\n", + "BlockChecksumFlag","Compressed", "Uncompressed", "Ratio", "Filename"); + + for (idx=0; idx> tmp-tlb-hw.lz4 $(LZ4) -f tmp-tlb-hw.lz4 # uncompress valid frame followed by invalid data $(LZ4) -BX tmp-tlb-hw -c -q | $(LZ4) -tv # test block checksum -- cgit v0.12 From f401f1de7eba98ee5acde5b8dd9681ff1aa76b56 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 22 Apr 2019 15:01:20 -0700 Subject: --list can resume after a failed file --- programs/lz4io.c | 103 ++++++++++++++++++++++++++++++++----------------------- programs/lz4io.h | 2 +- 2 files changed, 61 insertions(+), 44 deletions(-) diff --git a/programs/lz4io.c b/programs/lz4io.c index e3eed93..2a7b4b9 100644 --- a/programs/lz4io.c +++ b/programs/lz4io.c @@ -1230,7 +1230,9 @@ int LZ4IO_decompressFilename(LZ4IO_prefs_t* const prefs, const char* input_filen } -int LZ4IO_decompressMultipleFilenames(LZ4IO_prefs_t* const prefs, const char** inFileNamesTable, int ifntSize, const char* suffix) +int LZ4IO_decompressMultipleFilenames(LZ4IO_prefs_t* const prefs, + const char** inFileNamesTable, int ifntSize, + const char* suffix) { int i; int skippedFiles = 0; @@ -1250,7 +1252,12 @@ int LZ4IO_decompressMultipleFilenames(LZ4IO_prefs_t* const prefs, const char** i missingFiles += LZ4IO_decompressSrcFile(prefs, ress, inFileNamesTable[i], stdoutmark); continue; } - if (ofnSize <= ifnSize-suffixSize+1) { free(outFileName); ofnSize = ifnSize + 20; outFileName = (char*)malloc(ofnSize); if (outFileName==NULL) return ifntSize; } + if (ofnSize <= ifnSize-suffixSize+1) { + free(outFileName); + ofnSize = ifnSize + 20; + outFileName = (char*)malloc(ofnSize); + if (outFileName==NULL) return ifntSize; + } if (ifnSize <= suffixSize || strcmp(suffixPtr, suffix) != 0) { DISPLAYLEVEL(1, "File extension doesn't match expected LZ4_EXTENSION (%4s); will not process file: %s\n", suffix, inFileNamesTable[i]); skippedFiles++; @@ -1279,6 +1286,13 @@ typedef struct { #define LZ4IO_INIT_CFILEINFO { LZ4F_INIT_FRAMEINFO, NULL, 0ULL } +#define CHECK_Z_THROW(f) { \ + LZ4F_errorCode_t const ec = (f); \ + if (LZ4F_isError(ec)) \ + EXM_THROW(1, "LZ4F error : %s", LZ4F_getErrorName(ec)); \ +} + +typedef enum { LZ4IO_LZ4F_OK, LZ4IO_format_not_known, LZ4IO_not_a_file } LZ4IO_infoResult; /* This function is limited, * it only works fine for a file consisting of a single valid frame. @@ -1286,17 +1300,18 @@ typedef struct { * It will not look at content beyond first frame header. * * Things to improve : - * - continue execution after an error, just report an error code, keep all memory clean * - check the entire file for additional content after first frame * + combine results from multiple frames, give total * - Optional : * + report nb of blocks, hence max. possible decompressed size (when not reported in header) * + report block type (B4D, B7I, etc.) */ -static int +static LZ4IO_infoResult LZ4IO_getCompressedFileInfo(LZ4IO_cFileInfo_t* cfinfo, const char* input_filename) { - /* Get file size */ + LZ4IO_infoResult result = LZ4IO_format_not_known; /* default result (error) */ + + if (!UTIL_isRegFile(input_filename)) return LZ4IO_not_a_file; cfinfo->fileSize = UTIL_getFileSize(input_filename); /* returns 0 if cannot read information */ /* Get filename without path prefix */ @@ -1313,67 +1328,69 @@ LZ4IO_getCompressedFileInfo(LZ4IO_cFileInfo_t* cfinfo, const char* input_filenam } /* Read file and extract header */ - { size_t readSize = LZ4F_HEADER_SIZE_MAX; - void* buffer = malloc(readSize); - LZ4F_dctx* dctx; + { size_t const hSize = LZ4F_HEADER_SIZE_MAX; + size_t readSize=0; + void* const buffer = malloc(hSize); if (!buffer) EXM_THROW(21, "Allocation error : not enough memory"); - { LZ4F_errorCode_t const errorCode = - LZ4F_createDecompressionContext(&dctx, LZ4F_VERSION); - if (LZ4F_isError(errorCode)) - EXM_THROW(60, "Can't create LZ4F context : %s", - LZ4F_getErrorName(errorCode)); - } - { FILE* const finput = LZ4IO_openSrcFile(input_filename); - if (finput==NULL) return 1; - if (!fread(buffer, readSize, 1, finput)) { - EXM_THROW(30, "Error reading %s ", input_filename); - } - fclose(finput); - } + if (finput) { + readSize = fread(buffer, 1, hSize, finput); + fclose(finput); + } } - { LZ4F_errorCode_t const errorCode = - LZ4F_getFrameInfo(dctx, &cfinfo->frameInfo, buffer, &readSize); - if (LZ4F_isError(errorCode)) - EXM_THROW(60, "Cannot interpret LZ4 frame : %s", - LZ4F_getErrorName(errorCode)); + if (readSize > 0) { + LZ4F_dctx* dctx; + CHECK_Z_THROW(LZ4F_createDecompressionContext(&dctx, LZ4F_VERSION)); + if (!LZ4F_isError(LZ4F_getFrameInfo(dctx, &cfinfo->frameInfo, buffer, &readSize))) { + result = LZ4IO_LZ4F_OK; + } + LZ4F_freeDecompressionContext(dctx); } /* clean */ free(buffer); - LZ4F_freeDecompressionContext(dctx); } - return 0; + return result; } -int LZ4IO_displayCompressedFilesInfo(const char** inFileNames, const size_t ifnIdx) +int LZ4IO_displayCompressedFilesInfo(const char** inFileNames, size_t ifnIdx) { + int result = 0; size_t idx; - DISPLAY("%16s\t%-20s\t%-20s\t%-10s\t%s\n", - "BlockChecksumFlag","Compressed", "Uncompressed", "Ratio", "Filename"); + DISPLAY("%20s %20s %10s %7s %s\n", + "Compressed", "Uncompressed", "Ratio", "Check", "Filename"); for (idx=0; idx Date: Mon, 22 Apr 2019 15:14:53 -0700 Subject: --list gives block type --- programs/lz4.1 | 2 +- programs/lz4.1.md | 5 ++--- programs/lz4io.c | 26 +++++++++++++++++++++----- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/programs/lz4.1 b/programs/lz4.1 index eb82b68..ad0c12c 100644 --- a/programs/lz4.1 +++ b/programs/lz4.1 @@ -107,7 +107,7 @@ Benchmark mode, using \fB#\fR compression level\. . .TP \fB\-\-list\fR -List mode\. Lists information about \.lz4 files\. Useful if compressed with \-\-content\-size flag\. +List information about \.lz4 files\. note : current implementation is limited to single\-frame \.lz4 files\. . .SS "Operation modifiers" . diff --git a/programs/lz4.1.md b/programs/lz4.1.md index 62f672e..8874467 100644 --- a/programs/lz4.1.md +++ b/programs/lz4.1.md @@ -114,9 +114,8 @@ only the latest one will be applied. Benchmark mode, using `#` compression level. * `--list`: - List mode. - Lists information about .lz4 files. - Useful if compressed with --content-size flag. + List information about .lz4 files. + note : current implementation is limited to single-frame .lz4 files. ### Operation modifiers diff --git a/programs/lz4io.c b/programs/lz4io.c index 2a7b4b9..5393cd0 100644 --- a/programs/lz4io.c +++ b/programs/lz4io.c @@ -1304,7 +1304,6 @@ typedef enum { LZ4IO_LZ4F_OK, LZ4IO_format_not_known, LZ4IO_not_a_file } LZ4IO_i * + combine results from multiple frames, give total * - Optional : * + report nb of blocks, hence max. possible decompressed size (when not reported in header) - * + report block type (B4D, B7I, etc.) */ static LZ4IO_infoResult LZ4IO_getCompressedFileInfo(LZ4IO_cFileInfo_t* cfinfo, const char* input_filename) @@ -1355,13 +1354,26 @@ LZ4IO_getCompressedFileInfo(LZ4IO_cFileInfo_t* cfinfo, const char* input_filenam return result; } + +/* buffer : must be a valid memory area of at least 4 bytes */ +const char* LZ4IO_blockTypeID(int sizeID, int blockMode, char* buffer) +{ + buffer[0] = 'B'; + assert(sizeID >= 4); assert(sizeID <=7); + buffer[1] = (char)(sizeID + '0'); + buffer[2] = (blockMode == LZ4F_blockIndependent) ? 'I' : 'D'; + buffer[3] = 0; + return buffer; +} + + int LZ4IO_displayCompressedFilesInfo(const char** inFileNames, size_t ifnIdx) { int result = 0; size_t idx; - DISPLAY("%20s %20s %10s %7s %s\n", - "Compressed", "Uncompressed", "Ratio", "Check", "Filename"); + DISPLAY("%5s %20s %20s %10s %7s %s\n", + "Block", "Compressed", "Uncompressed", "Ratio", "Check", "Filename"); for (idx=0; idx Date: Mon, 22 Apr 2019 15:24:44 -0700 Subject: updated code comments --- programs/lz4io.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/programs/lz4io.c b/programs/lz4io.c index 5393cd0..105718d 100644 --- a/programs/lz4io.c +++ b/programs/lz4io.c @@ -1295,9 +1295,9 @@ typedef struct { typedef enum { LZ4IO_LZ4F_OK, LZ4IO_format_not_known, LZ4IO_not_a_file } LZ4IO_infoResult; /* This function is limited, - * it only works fine for a file consisting of a single valid frame. - * It will / may stop program execution if a single filename is wrong. + * it only works fine for a file consisting of a single valid frame using LZ4 Frame specification. * It will not look at content beyond first frame header. + * It's also unable to parse legacy frames, nor skippable ones. * * Things to improve : * - check the entire file for additional content after first frame @@ -1311,7 +1311,7 @@ LZ4IO_getCompressedFileInfo(LZ4IO_cFileInfo_t* cfinfo, const char* input_filenam LZ4IO_infoResult result = LZ4IO_format_not_known; /* default result (error) */ if (!UTIL_isRegFile(input_filename)) return LZ4IO_not_a_file; - cfinfo->fileSize = UTIL_getFileSize(input_filename); /* returns 0 if cannot read information */ + cfinfo->fileSize = UTIL_getFileSize(input_filename); /* Get filename without path prefix */ { const char* b = strrchr(input_filename, '/'); @@ -1329,9 +1329,10 @@ LZ4IO_getCompressedFileInfo(LZ4IO_cFileInfo_t* cfinfo, const char* input_filenam /* Read file and extract header */ { size_t const hSize = LZ4F_HEADER_SIZE_MAX; size_t readSize=0; - void* const buffer = malloc(hSize); + void* const buffer = malloc(hSize); if (!buffer) EXM_THROW(21, "Allocation error : not enough memory"); + { FILE* const finput = LZ4IO_openSrcFile(input_filename); if (finput) { readSize = fread(buffer, 1, hSize, finput); -- cgit v0.12 From 35b83a921f8030ee9b71cbb7324dc7aafaeb9878 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 22 Apr 2019 16:06:22 -0700 Subject: fix: no leak when LZ4F_dctx creation fails strange, because it previous implementation, it would `exit()`, so it should not matter ... --- programs/lz4io.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/programs/lz4io.c b/programs/lz4io.c index 105718d..960c451 100644 --- a/programs/lz4io.c +++ b/programs/lz4io.c @@ -1286,11 +1286,6 @@ typedef struct { #define LZ4IO_INIT_CFILEINFO { LZ4F_INIT_FRAMEINFO, NULL, 0ULL } -#define CHECK_Z_THROW(f) { \ - LZ4F_errorCode_t const ec = (f); \ - if (LZ4F_isError(ec)) \ - EXM_THROW(1, "LZ4F error : %s", LZ4F_getErrorName(ec)); \ -} typedef enum { LZ4IO_LZ4F_OK, LZ4IO_format_not_known, LZ4IO_not_a_file } LZ4IO_infoResult; @@ -1341,10 +1336,10 @@ LZ4IO_getCompressedFileInfo(LZ4IO_cFileInfo_t* cfinfo, const char* input_filenam if (readSize > 0) { LZ4F_dctx* dctx; - CHECK_Z_THROW(LZ4F_createDecompressionContext(&dctx, LZ4F_VERSION)); - if (!LZ4F_isError(LZ4F_getFrameInfo(dctx, &cfinfo->frameInfo, buffer, &readSize))) { - result = LZ4IO_LZ4F_OK; - } + if (!LZ4F_isError(LZ4F_createDecompressionContext(&dctx, LZ4F_VERSION))) { + if (!LZ4F_isError(LZ4F_getFrameInfo(dctx, &cfinfo->frameInfo, buffer, &readSize))) { + result = LZ4IO_LZ4F_OK; + } } LZ4F_freeDecompressionContext(dctx); } -- cgit v0.12