Add --list option to display compressed file information.
authorgabrielstedman <gabriwinter@gmail.com>
Sat, 20 Apr 2019 21:06:10 +0000 (22:06 +0100)
committergabrielstedman <gabriwinter@gmail.com>
Sat, 20 Apr 2019 23:01:03 +0000 (00:01 +0100)
programs/lz4cli.c
programs/lz4io.c
programs/lz4io.h

index 8bd7042..adfabc3 100644 (file)
@@ -40,6 +40,7 @@
 #include <stdlib.h>   /* exit, calloc, free */
 #include <string.h>   /* 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<ifnIdx; i++){
+            /* Get file info */
+            if (!LZ4IO_getCompressedFileInfo(inFileNames[i], &cfinfo)){
+                DISPLAYLEVEL(1, "Failed to get frame info.\n");
+                if (!multiple_inputs){
+                    return 1;
+                }
+                continue;
+            }
+            if(cfinfo.frameInfo.contentSize){
+                double 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);
+            }
+            else{
+                DISPLAY("%-16d\t%-20llu\t%-20s\t%-10s\t%s\n",cfinfo.frameInfo.blockChecksumFlag,cfinfo.fileSize, "-", "-", cfinfo.fileName);
+            }
+            free(cfinfo.fileName);
+        }
+        free(inFileNames);
+        return 0;
+    } 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);
index 121bd44..e62e56f 100644 (file)
 #include <time.h>      /* clock */
 #include <sys/types.h> /* stat64 */
 #include <sys/stat.h>  /* 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;
+}
index 54d49be..bf1fa76 100644 (file)
@@ -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);