2016-08-30 17:04:33 +00:00
/**
* Copyright ( c ) 2016 - present , Yann Collet , Facebook , Inc .
* All rights reserved .
*
* This source code is licensed under the BSD - style license found in the
* LICENSE file in the root directory of this source tree . An additional grant
* of patent rights can be found in the PATENTS file in the same directory .
*/
2016-08-28 17:00:49 +00:00
2016-05-29 03:16:05 +00:00
2016-07-13 12:15:08 +00:00
/*-************************************
* Tuning parameters
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-07-13 13:16:00 +00:00
# ifndef ZSTDCLI_CLEVEL_DEFAULT
# define ZSTDCLI_CLEVEL_DEFAULT 3
2016-07-13 12:15:08 +00:00
# endif
2016-08-12 16:04:15 +00:00
# ifndef ZSTDCLI_CLEVEL_MAX
2016-09-21 10:24:43 +00:00
# define ZSTDCLI_CLEVEL_MAX 19 /* when not using --ultra */
2016-08-12 16:04:15 +00:00
# endif
2016-07-13 12:15:08 +00:00
2017-01-26 01:01:13 +00:00
2016-05-29 03:16:05 +00:00
/*-************************************
2016-11-16 16:50:54 +00:00
* Dependencies
2016-05-29 03:16:05 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-12-21 14:08:44 +00:00
# include "platform.h" /* IS_CONSOLE, PLATFORM_POSIX_VERSION */
# include "util.h" /* UTIL_HAS_CREATEFILELIST, UTIL_createFileList */
2016-05-29 03:16:05 +00:00
# include <string.h> /* strcmp, strlen */
2016-07-04 16:16:16 +00:00
# include <errno.h> /* errno */
2016-05-29 03:16:05 +00:00
# include "fileio.h"
# ifndef ZSTD_NOBENCH
2016-11-03 10:38:01 +00:00
# include "bench.h" /* BMK_benchFiles, BMK_SetNbSeconds */
2016-05-29 03:16:05 +00:00
# endif
# ifndef ZSTD_NODICT
# include "dibio.h"
# endif
2016-06-04 17:47:02 +00:00
# define ZSTD_STATIC_LINKING_ONLY /* ZSTD_maxCLevel */
# include "zstd.h" /* ZSTD_VERSION_STRING */
2016-05-29 03:16:05 +00:00
/*-************************************
* Constants
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# define COMPRESSOR_NAME "zstd command line interface"
# ifndef ZSTD_VERSION
# define ZSTD_VERSION "v" ZSTD_VERSION_STRING
# endif
# define AUTHOR "Yann Collet"
# define WELCOME_MESSAGE "*** %s %i-bits %s, by %s ***\n", COMPRESSOR_NAME, (int)(sizeof(size_t)*8), ZSTD_VERSION, AUTHOR
2017-02-08 16:37:14 +00:00
# define GZ_EXTENSION ".gz"
2016-05-29 03:16:05 +00:00
# define ZSTD_EXTENSION ".zst"
# define ZSTD_UNZSTD "unzstd"
2017-02-14 18:45:19 +00:00
# define ZSTD_CAT "zstdcat"
# define ZSTD_GZ "gzip"
# define ZSTD_GUNZIP "gunzip"
# define ZSTD_GZCAT "gzcat"
2016-05-29 03:16:05 +00:00
# define KB *(1 <<10)
# define MB *(1 <<20)
# define GB *(1U<<30)
2016-08-12 21:49:05 +00:00
# define DEFAULT_DISPLAY_LEVEL 2
2016-05-29 03:16:05 +00:00
static const char * g_defaultDictName = " dictionary " ;
static const unsigned g_defaultMaxDictSize = 110 KB ;
2016-09-01 22:05:57 +00:00
static const int g_defaultDictCLevel = 3 ;
2016-05-29 03:16:05 +00:00
static const unsigned g_defaultSelectivityLevel = 9 ;
2017-01-30 22:37:08 +00:00
# define OVERLAP_LOG_DEFAULT 9999
static U32 g_overlapLog = OVERLAP_LOG_DEFAULT ;
2016-05-29 03:16:05 +00:00
/*-************************************
* Display Macros
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# define DISPLAY(...) fprintf(displayOut, __VA_ARGS__)
# define DISPLAYLEVEL(l, ...) if (displayLevel>=l) { DISPLAY(__VA_ARGS__); }
static FILE * displayOut ;
2016-08-12 21:49:05 +00:00
static unsigned displayLevel = DEFAULT_DISPLAY_LEVEL ; /* 0 : no display, 1: errors, 2 : + result + interaction + warnings, 3 : + progression, 4 : + information */
2016-05-29 03:16:05 +00:00
/*-************************************
* Command Line
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int usage ( const char * programName )
{
DISPLAY ( " Usage : \n " ) ;
DISPLAY ( " %s [args] [FILE(s)] [-o file] \n " , programName ) ;
DISPLAY ( " \n " ) ;
DISPLAY ( " FILE : a filename \n " ) ;
DISPLAY ( " with no FILE, or when FILE is - , read standard input \n " ) ;
DISPLAY ( " Arguments : \n " ) ;
# ifndef ZSTD_NOCOMPRESS
2016-08-18 07:00:25 +00:00
DISPLAY ( " -# : # compression level (1-%d, default:%d) \n " , ZSTDCLI_CLEVEL_MAX , ZSTDCLI_CLEVEL_DEFAULT ) ;
2016-05-29 03:16:05 +00:00
# endif
# ifndef ZSTD_NODECOMPRESS
DISPLAY ( " -d : decompression \n " ) ;
# endif
DISPLAY ( " -D file: use `file` as Dictionary \n " ) ;
DISPLAY ( " -o file: result stored into `file` (only if 1 input file) \n " ) ;
DISPLAY ( " -f : overwrite output without prompting \n " ) ;
2016-07-01 22:37:32 +00:00
DISPLAY ( " --rm : remove source file(s) after successful de/compression \n " ) ;
2016-07-03 22:42:58 +00:00
DISPLAY ( " -k : preserve source file(s) (default) \n " ) ;
2016-05-29 03:16:05 +00:00
DISPLAY ( " -h/-H : display help/long help and exit \n " ) ;
return 0 ;
}
static int usage_advanced ( const char * programName )
{
DISPLAY ( WELCOME_MESSAGE ) ;
usage ( programName ) ;
DISPLAY ( " \n " ) ;
DISPLAY ( " Advanced arguments : \n " ) ;
DISPLAY ( " -V : display Version number and exit \n " ) ;
2016-08-12 21:49:05 +00:00
DISPLAY ( " -v : verbose mode; specify multiple times to increase log level (default:%d) \n " , DEFAULT_DISPLAY_LEVEL ) ;
2016-05-29 03:16:05 +00:00
DISPLAY ( " -q : suppress warnings; specify twice to suppress errors too \n " ) ;
DISPLAY ( " -c : force write to standard output, even if it is the console \n " ) ;
# ifdef UTIL_HAS_CREATEFILELIST
2017-01-20 00:59:56 +00:00
DISPLAY ( " -r : operate recursively on directories \n " ) ;
2016-05-29 03:16:05 +00:00
# endif
# ifndef ZSTD_NOCOMPRESS
2016-08-12 16:04:15 +00:00
DISPLAY ( " --ultra : enable levels beyond %i, up to %i (requires more memory) \n " , ZSTDCLI_CLEVEL_MAX , ZSTD_maxCLevel ( ) ) ;
2016-06-09 20:59:51 +00:00
DISPLAY ( " --no-dictID : don't write dictID into header (dictionary compression) \n " ) ;
2017-01-20 00:59:56 +00:00
DISPLAY ( " --[no-]check : integrity check (default:enabled) \n " ) ;
# ifdef ZSTD_MULTITHREAD
DISPLAY ( " -T# : use # threads for compression (default:1) \n " ) ;
2017-01-25 01:02:26 +00:00
DISPLAY ( " -B# : select size of independent sections (default:0==automatic) \n " ) ;
2017-01-20 00:59:56 +00:00
# endif
2017-02-08 14:17:55 +00:00
# ifdef ZSTD_GZCOMPRESS
2017-02-08 17:08:09 +00:00
DISPLAY ( " --format=gzip : compress files to the .gz format \n " ) ;
2017-02-08 14:17:55 +00:00
# endif
2016-05-29 03:16:05 +00:00
# endif
2016-05-31 00:29:45 +00:00
# ifndef ZSTD_NODECOMPRESS
2016-06-02 15:05:50 +00:00
DISPLAY ( " --test : test compressed file integrity \n " ) ;
2016-06-09 20:59:51 +00:00
DISPLAY ( " --[no-]sparse : sparse mode (default:enabled on file, disabled on stdout) \n " ) ;
2016-05-31 00:29:45 +00:00
# endif
2016-10-14 20:13:13 +00:00
DISPLAY ( " -M# : Set a memory usage limit for decompression \n " ) ;
2016-09-16 16:52:52 +00:00
DISPLAY ( " -- : All arguments after \" -- \" are treated as files \n " ) ;
2016-05-29 03:16:05 +00:00
# ifndef ZSTD_NODICT
DISPLAY ( " \n " ) ;
DISPLAY ( " Dictionary builder : \n " ) ;
2016-06-09 20:59:51 +00:00
DISPLAY ( " --train ## : create a dictionary from a training set of files \n " ) ;
2017-01-01 05:08:24 +00:00
DISPLAY ( " --cover=k=#,d=# : use the cover algorithm with parameters k and d \n " ) ;
DISPLAY ( " --optimize-cover[=steps=#,k=#,d=#] : optimize cover parameters with optional parameters \n " ) ;
2016-06-09 20:59:51 +00:00
DISPLAY ( " -o file : `file` is dictionary name (default: %s) \n " , g_defaultDictName ) ;
DISPLAY ( " --maxdict ## : limit dictionary to specified size (default : %u) \n " , g_defaultMaxDictSize ) ;
2016-05-29 03:16:05 +00:00
DISPLAY ( " -s# : dictionary selectivity level (default: %u) \n " , g_defaultSelectivityLevel ) ;
2016-06-09 20:59:51 +00:00
DISPLAY ( " --dictID ## : force dictionary ID to specified value (default: random) \n " ) ;
2016-05-29 03:16:05 +00:00
# endif
# ifndef ZSTD_NOBENCH
DISPLAY ( " \n " ) ;
DISPLAY ( " Benchmark arguments : \n " ) ;
DISPLAY ( " -b# : benchmark file(s), using # compression level (default : 1) \n " ) ;
DISPLAY ( " -e# : test all compression levels from -bX to # (default: 1) \n " ) ;
2016-08-01 11:37:17 +00:00
DISPLAY ( " -i# : minimum evaluation time in seconds (default : 3s) \n " ) ;
2016-05-29 03:16:05 +00:00
DISPLAY ( " -B# : cut file into independent blocks of size # (default: no block) \n " ) ;
2017-02-08 12:49:06 +00:00
DISPLAY ( " --priority=rt : set process priority to real-time \n " ) ;
2016-05-29 03:16:05 +00:00
# endif
return 0 ;
}
static int badusage ( const char * programName )
{
DISPLAYLEVEL ( 1 , " Incorrect parameters \n " ) ;
if ( displayLevel > = 1 ) usage ( programName ) ;
return 1 ;
}
static void waitEnter ( void )
{
int unused ;
DISPLAY ( " Press enter to continue... \n " ) ;
unused = getchar ( ) ;
( void ) unused ;
}
2016-06-03 13:14:09 +00:00
/*! readU32FromChar() :
2016-10-14 20:13:13 +00:00
@ return : unsigned integer value read from input in ` char ` format
allows and interprets K , KB , KiB , M , MB and MiB suffix .
2016-06-03 13:14:09 +00:00
Will also modify ` * stringPtr ` , advancing it to position where it stopped reading .
2016-10-14 20:13:13 +00:00
Note : function result can overflow if digit string > MAX_UINT */
2016-06-03 13:14:09 +00:00
static unsigned readU32FromChar ( const char * * stringPtr )
{
unsigned result = 0 ;
while ( ( * * stringPtr > = ' 0 ' ) & & ( * * stringPtr < = ' 9 ' ) )
result * = 10 , result + = * * stringPtr - ' 0 ' , ( * stringPtr ) + + ;
2016-10-18 00:48:48 +00:00
if ( ( * * stringPtr = = ' K ' ) | | ( * * stringPtr = = ' M ' ) ) {
result < < = 10 ;
if ( * * stringPtr = = ' M ' ) result < < = 10 ;
( * stringPtr ) + + ;
if ( * * stringPtr = = ' i ' ) ( * stringPtr ) + + ;
if ( * * stringPtr = = ' B ' ) ( * stringPtr ) + + ;
}
2016-06-03 13:14:09 +00:00
return result ;
}
2016-12-02 23:18:57 +00:00
/** longCommandWArg() :
2017-01-30 21:07:24 +00:00
* check if * stringPtr is the same as longCommand .
2016-12-02 23:18:57 +00:00
* If yes , @ return 1 and advances * stringPtr to the position which immediately follows longCommand .
* @ return 0 and doesn ' t modify * stringPtr otherwise .
*/
2016-10-14 21:41:17 +00:00
static unsigned longCommandWArg ( const char * * stringPtr , const char * longCommand )
{
size_t const comSize = strlen ( longCommand ) ;
2016-12-02 23:18:57 +00:00
int const result = ! strncmp ( * stringPtr , longCommand , comSize ) ;
2016-10-14 21:41:17 +00:00
if ( result ) * stringPtr + = comSize ;
return result ;
}
2016-12-13 11:18:07 +00:00
2017-01-01 05:08:24 +00:00
# ifndef ZSTD_NODICT
/**
* parseCoverParameters ( ) :
* reads cover parameters from * stringPtr ( e . g . " --cover=smoothing=100,kmin=48,kstep=4,kmax=64,d=8 " ) into * params
* @ return 1 means that cover parameters were correct
* @ return 0 in case of malformed parameters
*/
static unsigned parseCoverParameters ( const char * stringPtr , COVER_params_t * params )
{
memset ( params , 0 , sizeof ( * params ) ) ;
for ( ; ; ) {
2017-01-02 20:40:43 +00:00
if ( longCommandWArg ( & stringPtr , " k= " ) ) { params - > k = readU32FromChar ( & stringPtr ) ; if ( stringPtr [ 0 ] = = ' , ' ) { stringPtr + + ; continue ; } else break ; }
2017-01-01 05:08:24 +00:00
if ( longCommandWArg ( & stringPtr , " d= " ) ) { params - > d = readU32FromChar ( & stringPtr ) ; if ( stringPtr [ 0 ] = = ' , ' ) { stringPtr + + ; continue ; } else break ; }
2017-01-02 20:40:43 +00:00
if ( longCommandWArg ( & stringPtr , " steps= " ) ) { params - > steps = readU32FromChar ( & stringPtr ) ; if ( stringPtr [ 0 ] = = ' , ' ) { stringPtr + + ; continue ; } else break ; }
2017-01-01 05:08:24 +00:00
return 0 ;
}
if ( stringPtr [ 0 ] ! = 0 ) return 0 ;
2017-01-02 20:40:43 +00:00
DISPLAYLEVEL ( 4 , " k=%u \n d=%u \n steps=%u \n " , params - > k , params - > d , params - > steps ) ;
2017-01-01 05:08:24 +00:00
return 1 ;
}
# endif
2017-01-30 21:07:24 +00:00
2016-12-13 11:18:07 +00:00
/** parseCompressionParameters() :
* reads compression parameters from * stringPtr ( e . g . " --zstd=wlog=23,clog=23,hlog=22,slog=6,slen=3,tlen=48,strat=6 " ) into * params
* @ return 1 means that compression parameters were correct
* @ return 0 in case of malformed parameters
*/
static unsigned parseCompressionParameters ( const char * stringPtr , ZSTD_compressionParameters * params )
{
for ( ; ; ) {
if ( longCommandWArg ( & stringPtr , " windowLog= " ) | | longCommandWArg ( & stringPtr , " wlog= " ) ) { params - > windowLog = readU32FromChar ( & stringPtr ) ; if ( stringPtr [ 0 ] = = ' , ' ) { stringPtr + + ; continue ; } else break ; }
if ( longCommandWArg ( & stringPtr , " chainLog= " ) | | longCommandWArg ( & stringPtr , " clog= " ) ) { params - > chainLog = readU32FromChar ( & stringPtr ) ; if ( stringPtr [ 0 ] = = ' , ' ) { stringPtr + + ; continue ; } else break ; }
if ( longCommandWArg ( & stringPtr , " hashLog= " ) | | longCommandWArg ( & stringPtr , " hlog= " ) ) { params - > hashLog = readU32FromChar ( & stringPtr ) ; if ( stringPtr [ 0 ] = = ' , ' ) { stringPtr + + ; continue ; } else break ; }
if ( longCommandWArg ( & stringPtr , " searchLog= " ) | | longCommandWArg ( & stringPtr , " slog= " ) ) { params - > searchLog = readU32FromChar ( & stringPtr ) ; if ( stringPtr [ 0 ] = = ' , ' ) { stringPtr + + ; continue ; } else break ; }
if ( longCommandWArg ( & stringPtr , " searchLength= " ) | | longCommandWArg ( & stringPtr , " slen= " ) ) { params - > searchLength = readU32FromChar ( & stringPtr ) ; if ( stringPtr [ 0 ] = = ' , ' ) { stringPtr + + ; continue ; } else break ; }
if ( longCommandWArg ( & stringPtr , " targetLength= " ) | | longCommandWArg ( & stringPtr , " tlen= " ) ) { params - > targetLength = readU32FromChar ( & stringPtr ) ; if ( stringPtr [ 0 ] = = ' , ' ) { stringPtr + + ; continue ; } else break ; }
2016-12-13 19:04:32 +00:00
if ( longCommandWArg ( & stringPtr , " strategy= " ) | | longCommandWArg ( & stringPtr , " strat= " ) ) { params - > strategy = ( ZSTD_strategy ) ( 1 + readU32FromChar ( & stringPtr ) ) ; if ( stringPtr [ 0 ] = = ' , ' ) { stringPtr + + ; continue ; } else break ; }
2017-01-30 21:07:24 +00:00
if ( longCommandWArg ( & stringPtr , " overlapLog= " ) | | longCommandWArg ( & stringPtr , " ovlog= " ) ) { g_overlapLog = readU32FromChar ( & stringPtr ) ; if ( stringPtr [ 0 ] = = ' , ' ) { stringPtr + + ; continue ; } else break ; }
2016-12-13 11:18:07 +00:00
return 0 ;
}
if ( stringPtr [ 0 ] ! = 0 ) return 0 ; /* check the end of string */
2016-12-13 12:03:41 +00:00
DISPLAYLEVEL ( 4 , " windowLog=%d \n chainLog=%d \n hashLog=%d \n searchLog=%d \n " , params - > windowLog , params - > chainLog , params - > hashLog , params - > searchLog ) ;
DISPLAYLEVEL ( 4 , " searchLength=%d \n targetLength=%d \n strategy=%d \n " , params - > searchLength , params - > targetLength , params - > strategy ) ;
2016-12-13 11:18:07 +00:00
return 1 ;
}
2016-10-28 20:58:31 +00:00
typedef enum { zom_compress , zom_decompress , zom_test , zom_bench , zom_train } zstd_operation_mode ;
2016-05-29 03:16:05 +00:00
# define CLEAN_RETURN(i) { operationResult = (i); goto _end; }
2016-09-21 10:24:43 +00:00
int main ( int argCount , const char * argv [ ] )
2016-05-29 03:16:05 +00:00
{
int argNb ,
forceStdout = 0 ,
main_pause = 0 ,
nextEntryIsDictionary = 0 ,
operationResult = 0 ,
nextArgumentIsOutFileName = 0 ,
2016-05-30 19:18:52 +00:00
nextArgumentIsMaxDict = 0 ,
2016-07-04 16:16:16 +00:00
nextArgumentIsDictID = 0 ,
2016-12-02 23:18:57 +00:00
nextArgumentsAreFiles = 0 ,
2016-09-21 12:20:56 +00:00
ultra = 0 ,
2017-01-20 00:59:56 +00:00
lastCommand = 0 ,
2017-02-07 15:48:01 +00:00
nbThreads = 1 ,
setRealTimePrio = 0 ;
2017-01-20 00:59:56 +00:00
unsigned bench_nbSeconds = 3 ; /* would be better if this value was synchronized from bench */
size_t blockSize = 0 ;
2016-10-28 20:58:31 +00:00
zstd_operation_mode operation = zom_compress ;
2016-12-13 11:18:07 +00:00
ZSTD_compressionParameters compressionParams ;
2016-07-27 13:09:11 +00:00
int cLevel = ZSTDCLI_CLEVEL_DEFAULT ;
int cLevelLast = 1 ;
2016-05-29 03:16:05 +00:00
unsigned recursive = 0 ;
2016-10-14 20:13:13 +00:00
unsigned memLimit = 0 ;
2016-05-29 03:16:05 +00:00
const char * * filenameTable = ( const char * * ) malloc ( argCount * sizeof ( const char * ) ) ; /* argCount >= 1 */
unsigned filenameIdx = 0 ;
const char * programName = argv [ 0 ] ;
const char * outFileName = NULL ;
const char * dictFileName = NULL ;
2017-02-08 16:37:14 +00:00
const char * suffix = ZSTD_EXTENSION ;
2016-05-29 03:16:05 +00:00
unsigned maxDictSize = g_defaultMaxDictSize ;
2016-05-30 19:18:52 +00:00
unsigned dictID = 0 ;
2016-07-27 13:09:11 +00:00
int dictCLevel = g_defaultDictCLevel ;
2016-05-29 03:16:05 +00:00
unsigned dictSelect = g_defaultSelectivityLevel ;
# ifdef UTIL_HAS_CREATEFILELIST
2016-09-21 10:24:43 +00:00
const char * * extendedFileList = NULL ;
2016-05-29 03:16:05 +00:00
char * fileNamesBuf = NULL ;
unsigned fileNamesNb ;
# endif
2017-01-01 05:08:24 +00:00
# ifndef ZSTD_NODICT
COVER_params_t coverParams ;
int cover = 0 ;
# endif
2016-05-29 03:16:05 +00:00
/* init */
2016-06-04 23:05:01 +00:00
( void ) recursive ; ( void ) cLevelLast ; /* not used when ZSTD_NOBENCH set */
2016-11-03 22:52:01 +00:00
( void ) dictCLevel ; ( void ) dictSelect ; ( void ) dictID ; ( void ) maxDictSize ; /* not used when ZSTD_NODICT set */
( void ) ultra ; ( void ) cLevel ; /* not used when ZSTD_NOCOMPRESS set */
( void ) memLimit ; /* not used when ZSTD_NODECOMPRESS set */
2016-07-03 22:42:58 +00:00
if ( filenameTable = = NULL ) { DISPLAY ( " zstd: %s \n " , strerror ( errno ) ) ; exit ( 1 ) ; }
2016-05-29 03:16:05 +00:00
filenameTable [ 0 ] = stdinmark ;
displayOut = stderr ;
/* Pick out program name from path. Don't rely on stdlib because of conflicting behavior */
{ size_t pos ;
for ( pos = ( int ) strlen ( programName ) ; pos > 0 ; pos - - ) { if ( programName [ pos ] = = ' / ' ) { pos + + ; break ; } }
programName + = pos ;
}
/* preset behaviors */
2016-10-28 20:58:31 +00:00
if ( ! strcmp ( programName , ZSTD_UNZSTD ) ) operation = zom_decompress ;
2016-12-02 23:18:57 +00:00
if ( ! strcmp ( programName , ZSTD_CAT ) ) { operation = zom_decompress ; forceStdout = 1 ; FIO_overwriteMode ( ) ; outFileName = stdoutmark ; displayLevel = 1 ; }
2017-02-14 18:45:19 +00:00
if ( ! strcmp ( programName , ZSTD_GZ ) ) { suffix = GZ_EXTENSION ; FIO_setCompressionType ( FIO_gzipCompression ) ; FIO_setRemoveSrcFile ( 1 ) ; } /* behave like gzip */
if ( ! strcmp ( programName , ZSTD_GUNZIP ) ) { operation = zom_decompress ; FIO_setRemoveSrcFile ( 1 ) ; } /* behave like gunzip */
if ( ! strcmp ( programName , ZSTD_GZCAT ) ) { operation = zom_decompress ; forceStdout = 1 ; FIO_overwriteMode ( ) ; outFileName = stdoutmark ; displayLevel = 1 ; } /* behave like gzcat */
2016-12-13 11:18:07 +00:00
memset ( & compressionParams , 0 , sizeof ( compressionParams ) ) ;
2016-05-29 03:16:05 +00:00
/* command switches */
2016-10-14 21:07:11 +00:00
for ( argNb = 1 ; argNb < argCount ; argNb + + ) {
2016-05-29 03:16:05 +00:00
const char * argument = argv [ argNb ] ;
if ( ! argument ) continue ; /* Protection if argument empty */
2016-12-02 23:18:57 +00:00
if ( nextArgumentsAreFiles = = 0 ) {
/* "-" means stdin/stdout */
2016-07-04 16:16:16 +00:00
if ( ! strcmp ( argument , " - " ) ) {
if ( ! filenameIdx ) {
filenameIdx = 1 , filenameTable [ 0 ] = stdinmark ;
outFileName = stdoutmark ;
displayLevel - = ( displayLevel = = 2 ) ;
continue ;
} }
2016-05-29 03:16:05 +00:00
2016-07-04 16:16:16 +00:00
/* Decode commands (note : aggregated commands are allowed) */
if ( argument [ 0 ] = = ' - ' ) {
2016-05-29 03:16:05 +00:00
2016-12-02 23:18:57 +00:00
if ( argument [ 1 ] = = ' - ' ) {
/* long commands (--long-word) */
if ( ! strcmp ( argument , " -- " ) ) { nextArgumentsAreFiles = 1 ; continue ; } /* only file names allowed from now on */
if ( ! strcmp ( argument , " --compress " ) ) { operation = zom_compress ; continue ; }
if ( ! strcmp ( argument , " --decompress " ) ) { operation = zom_decompress ; continue ; }
if ( ! strcmp ( argument , " --uncompress " ) ) { operation = zom_decompress ; continue ; }
if ( ! strcmp ( argument , " --force " ) ) { FIO_overwriteMode ( ) ; continue ; }
if ( ! strcmp ( argument , " --version " ) ) { displayOut = stdout ; DISPLAY ( WELCOME_MESSAGE ) ; CLEAN_RETURN ( 0 ) ; }
if ( ! strcmp ( argument , " --help " ) ) { displayOut = stdout ; CLEAN_RETURN ( usage_advanced ( programName ) ) ; }
if ( ! strcmp ( argument , " --verbose " ) ) { displayLevel + + ; continue ; }
if ( ! strcmp ( argument , " --quiet " ) ) { displayLevel - - ; continue ; }
if ( ! strcmp ( argument , " --stdout " ) ) { forceStdout = 1 ; outFileName = stdoutmark ; displayLevel - = ( displayLevel = = 2 ) ; continue ; }
if ( ! strcmp ( argument , " --ultra " ) ) { ultra = 1 ; continue ; }
if ( ! strcmp ( argument , " --check " ) ) { FIO_setChecksumFlag ( 2 ) ; continue ; }
if ( ! strcmp ( argument , " --no-check " ) ) { FIO_setChecksumFlag ( 0 ) ; continue ; }
if ( ! strcmp ( argument , " --sparse " ) ) { FIO_setSparseWrite ( 2 ) ; continue ; }
if ( ! strcmp ( argument , " --no-sparse " ) ) { FIO_setSparseWrite ( 0 ) ; continue ; }
if ( ! strcmp ( argument , " --test " ) ) { operation = zom_test ; continue ; }
if ( ! strcmp ( argument , " --train " ) ) { operation = zom_train ; outFileName = g_defaultDictName ; continue ; }
if ( ! strcmp ( argument , " --maxdict " ) ) { nextArgumentIsMaxDict = 1 ; lastCommand = 1 ; continue ; }
if ( ! strcmp ( argument , " --dictID " ) ) { nextArgumentIsDictID = 1 ; lastCommand = 1 ; continue ; }
if ( ! strcmp ( argument , " --no-dictID " ) ) { FIO_setDictIDFlag ( 0 ) ; continue ; }
if ( ! strcmp ( argument , " --keep " ) ) { FIO_setRemoveSrcFile ( 0 ) ; continue ; }
if ( ! strcmp ( argument , " --rm " ) ) { FIO_setRemoveSrcFile ( 1 ) ; continue ; }
2017-02-07 19:12:59 +00:00
if ( ! strcmp ( argument , " --priority=rt " ) ) { setRealTimePrio = 1 ; continue ; }
2017-02-14 08:47:29 +00:00
if ( ! strcmp ( argument , " --format=gzip " ) ) { suffix = GZ_EXTENSION ; FIO_setCompressionType ( FIO_gzipCompression ) ; continue ; }
2016-12-02 23:18:57 +00:00
/* long commands with arguments */
2017-01-01 05:08:24 +00:00
# ifndef ZSTD_NODICT
if ( longCommandWArg ( & argument , " --cover= " ) ) {
cover = 1 ; if ( ! parseCoverParameters ( argument , & coverParams ) ) CLEAN_RETURN ( badusage ( programName ) ) ;
continue ;
}
if ( longCommandWArg ( & argument , " --optimize-cover " ) ) {
cover = 2 ;
/* Allow optional arguments following an = */
if ( * argument = = 0 ) { memset ( & coverParams , 0 , sizeof ( coverParams ) ) ; }
else if ( * argument + + ! = ' = ' ) { CLEAN_RETURN ( badusage ( programName ) ) ; }
else if ( ! parseCoverParameters ( argument , & coverParams ) ) { CLEAN_RETURN ( badusage ( programName ) ) ; }
continue ;
}
# endif
2016-12-02 23:18:57 +00:00
if ( longCommandWArg ( & argument , " --memlimit= " ) ) { memLimit = readU32FromChar ( & argument ) ; continue ; }
if ( longCommandWArg ( & argument , " --memory= " ) ) { memLimit = readU32FromChar ( & argument ) ; continue ; }
if ( longCommandWArg ( & argument , " --memlimit-decompress= " ) ) { memLimit = readU32FromChar ( & argument ) ; continue ; }
2017-01-30 19:17:26 +00:00
if ( longCommandWArg ( & argument , " --block-size= " ) ) { blockSize = readU32FromChar ( & argument ) ; continue ; }
2016-12-13 11:18:07 +00:00
if ( longCommandWArg ( & argument , " --zstd= " ) ) { if ( ! parseCompressionParameters ( argument , & compressionParams ) ) CLEAN_RETURN ( badusage ( programName ) ) ; continue ; }
2016-12-02 23:18:57 +00:00
/* fall-through, will trigger bad_usage() later on */
}
argument + + ;
2016-07-04 16:16:16 +00:00
while ( argument [ 0 ] ! = 0 ) {
2016-09-21 12:20:56 +00:00
if ( lastCommand ) {
DISPLAY ( " error : command must be followed by argument \n " ) ;
2017-02-21 17:17:24 +00:00
CLEAN_RETURN ( 1 ) ;
2016-09-21 12:20:56 +00:00
}
2016-09-01 22:05:57 +00:00
# ifndef ZSTD_NOCOMPRESS
2016-07-04 16:16:16 +00:00
/* compression Level */
if ( ( * argument > = ' 0 ' ) & & ( * argument < = ' 9 ' ) ) {
2016-08-12 16:04:15 +00:00
dictCLevel = cLevel = readU32FromChar ( & argument ) ;
2016-07-04 16:16:16 +00:00
continue ;
}
2016-09-01 22:05:57 +00:00
# endif
2016-05-29 03:16:05 +00:00
2016-07-04 16:16:16 +00:00
switch ( argument [ 0 ] )
{
/* Display help */
case ' V ' : displayOut = stdout ; DISPLAY ( WELCOME_MESSAGE ) ; CLEAN_RETURN ( 0 ) ; /* Version Only */
case ' H ' :
case ' h ' : displayOut = stdout ; CLEAN_RETURN ( usage_advanced ( programName ) ) ;
2016-05-29 03:16:05 +00:00
2016-10-28 20:58:31 +00:00
/* Compress */
case ' z ' : operation = zom_compress ; argument + + ; break ;
2016-07-04 16:16:16 +00:00
/* Decoding */
2016-12-07 01:56:20 +00:00
case ' d ' :
# ifndef ZSTD_NOBENCH
2016-12-28 15:11:09 +00:00
if ( operation = = zom_bench ) { BMK_setDecodeOnlyMode ( 1 ) ; argument + + ; break ; } /* benchmark decode (hidden option) */
2016-12-07 01:56:20 +00:00
# endif
2016-12-07 00:49:23 +00:00
operation = zom_decompress ; argument + + ; break ;
2016-05-29 03:16:05 +00:00
2016-07-04 16:16:16 +00:00
/* Force stdout, even if stdout==console */
2016-08-12 16:04:15 +00:00
case ' c ' : forceStdout = 1 ; outFileName = stdoutmark ; argument + + ; break ;
2016-05-29 03:16:05 +00:00
2016-07-04 16:16:16 +00:00
/* Use file content as dictionary */
2016-09-21 12:20:56 +00:00
case ' D ' : nextEntryIsDictionary = 1 ; lastCommand = 1 ; argument + + ; break ;
2016-05-29 03:16:05 +00:00
2016-07-04 16:16:16 +00:00
/* Overwrite */
case ' f ' : FIO_overwriteMode ( ) ; forceStdout = 1 ; argument + + ; break ;
2016-05-29 03:16:05 +00:00
2016-07-04 16:16:16 +00:00
/* Verbose mode */
2016-07-15 17:43:30 +00:00
case ' v ' : displayLevel + + ; argument + + ; break ;
2016-05-29 03:16:05 +00:00
2016-07-04 16:16:16 +00:00
/* Quiet mode */
case ' q ' : displayLevel - - ; argument + + ; break ;
2016-05-29 03:16:05 +00:00
2016-07-04 16:16:16 +00:00
/* keep source file (default); for gzip/xz compatibility */
case ' k ' : FIO_setRemoveSrcFile ( 0 ) ; argument + + ; break ;
2016-05-29 03:16:05 +00:00
2016-07-04 16:16:16 +00:00
/* Checksum */
case ' C ' : argument + + ; FIO_setChecksumFlag ( 2 ) ; break ;
2016-06-02 15:05:50 +00:00
2016-07-04 16:16:16 +00:00
/* test compressed file */
2016-10-28 20:58:31 +00:00
case ' t ' : operation = zom_test ; argument + + ; break ;
2016-05-29 03:16:05 +00:00
2016-07-13 12:15:08 +00:00
/* destination file name */
2016-09-21 12:20:56 +00:00
case ' o ' : nextArgumentIsOutFileName = 1 ; lastCommand = 1 ; argument + + ; break ;
2016-05-29 03:16:05 +00:00
2016-10-14 20:13:13 +00:00
/* limit decompression memory */
case ' M ' :
argument + + ;
memLimit = readU32FromChar ( & argument ) ;
break ;
2016-09-13 15:50:08 +00:00
# ifdef UTIL_HAS_CREATEFILELIST
2016-07-04 16:16:16 +00:00
/* recursive */
case ' r ' : recursive = 1 ; argument + + ; break ;
2016-09-13 15:50:08 +00:00
# endif
2016-05-29 03:16:05 +00:00
2016-09-01 22:05:57 +00:00
# ifndef ZSTD_NOBENCH
2016-07-04 16:16:16 +00:00
/* Benchmark */
2017-01-20 00:59:56 +00:00
case ' b ' :
operation = zom_bench ;
argument + + ;
break ;
2016-05-29 03:16:05 +00:00
2016-07-04 16:16:16 +00:00
/* range bench (benchmark only) */
case ' e ' :
2017-01-20 00:59:56 +00:00
/* compression Level */
argument + + ;
cLevelLast = readU32FromChar ( & argument ) ;
break ;
2016-07-04 16:16:16 +00:00
/* Modify Nb Iterations (benchmark only) */
case ' i ' :
2016-05-29 03:16:05 +00:00
argument + + ;
2017-01-20 00:59:56 +00:00
bench_nbSeconds = readU32FromChar ( & argument ) ;
2016-05-29 03:16:05 +00:00
break ;
2016-07-04 16:16:16 +00:00
/* cut input into blocks (benchmark only) */
case ' B ' :
argument + + ;
2017-01-20 00:59:56 +00:00
blockSize = readU32FromChar ( & argument ) ;
2016-07-04 16:16:16 +00:00
break ;
2017-01-02 01:05:45 +00:00
2017-01-20 00:59:56 +00:00
# endif /* ZSTD_NOBENCH */
2017-01-02 01:05:45 +00:00
/* nb of threads (hidden option) */
case ' T ' :
argument + + ;
2017-01-20 00:59:56 +00:00
nbThreads = readU32FromChar ( & argument ) ;
2017-01-02 01:05:45 +00:00
break ;
2016-05-29 03:16:05 +00:00
2016-07-04 16:16:16 +00:00
/* Dictionary Selection level */
case ' s ' :
argument + + ;
dictSelect = readU32FromChar ( & argument ) ;
break ;
2016-05-29 03:16:05 +00:00
2016-07-04 16:16:16 +00:00
/* Pause at the end (-p) or set an additional param (-p#) (hidden option) */
case ' p ' : argument + + ;
2016-09-01 22:05:57 +00:00
# ifndef ZSTD_NOBENCH
2016-07-04 16:16:16 +00:00
if ( ( * argument > = ' 0 ' ) & & ( * argument < = ' 9 ' ) ) {
BMK_setAdditionalParam ( readU32FromChar ( & argument ) ) ;
} else
2016-09-01 22:05:57 +00:00
# endif
2016-07-04 16:16:16 +00:00
main_pause = 1 ;
break ;
/* unknown command */
default : CLEAN_RETURN ( badusage ( programName ) ) ;
}
2016-05-29 03:16:05 +00:00
}
2016-07-04 16:16:16 +00:00
continue ;
} /* if (argument[0]=='-') */
if ( nextArgumentIsMaxDict ) {
nextArgumentIsMaxDict = 0 ;
2016-09-21 12:20:56 +00:00
lastCommand = 0 ;
2016-07-04 16:16:16 +00:00
maxDictSize = readU32FromChar ( & argument ) ;
continue ;
2016-05-29 03:16:05 +00:00
}
2016-07-04 16:16:16 +00:00
if ( nextArgumentIsDictID ) {
nextArgumentIsDictID = 0 ;
2016-09-21 12:20:56 +00:00
lastCommand = 0 ;
2016-07-04 16:16:16 +00:00
dictID = readU32FromChar ( & argument ) ;
continue ;
}
} /* if (nextArgumentIsAFile==0) */
2016-05-29 03:16:05 +00:00
if ( nextEntryIsDictionary ) {
nextEntryIsDictionary = 0 ;
2016-09-21 12:20:56 +00:00
lastCommand = 0 ;
2016-05-29 03:16:05 +00:00
dictFileName = argument ;
continue ;
}
if ( nextArgumentIsOutFileName ) {
nextArgumentIsOutFileName = 0 ;
2016-09-21 12:20:56 +00:00
lastCommand = 0 ;
2016-05-29 03:16:05 +00:00
outFileName = argument ;
if ( ! strcmp ( outFileName , " - " ) ) outFileName = stdoutmark ;
continue ;
}
/* add filename to list */
filenameTable [ filenameIdx + + ] = argument ;
}
2017-02-21 17:17:24 +00:00
if ( lastCommand ) { DISPLAY ( " error : command must be followed by argument \n " ) ; CLEAN_RETURN ( 1 ) ; } /* forgotten argument */
2016-09-21 14:05:03 +00:00
2016-05-29 03:16:05 +00:00
/* Welcome message (if verbose) */
DISPLAYLEVEL ( 3 , WELCOME_MESSAGE ) ;
2016-12-16 14:41:18 +00:00
# ifdef _POSIX_C_SOURCE
DISPLAYLEVEL ( 4 , " _POSIX_C_SOURCE defined: %ldL \n " , ( long ) _POSIX_C_SOURCE ) ;
# endif
# ifdef _POSIX_VERSION
DISPLAYLEVEL ( 4 , " _POSIX_VERSION defined: %ldL \n " , ( long ) _POSIX_VERSION ) ;
# endif
# ifdef PLATFORM_POSIX_VERSION
DISPLAYLEVEL ( 4 , " PLATFORM_POSIX_VERSION defined: %ldL \n " , ( long ) PLATFORM_POSIX_VERSION ) ;
# endif
2016-05-29 03:16:05 +00:00
# ifdef UTIL_HAS_CREATEFILELIST
2016-09-21 10:24:43 +00:00
if ( recursive ) { /* at this stage, filenameTable is a list of paths, which can contain both files and directories */
extendedFileList = UTIL_createFileList ( filenameTable , filenameIdx , & fileNamesBuf , & fileNamesNb ) ;
if ( extendedFileList ) {
2016-08-01 12:26:49 +00:00
unsigned u ;
2016-09-21 10:24:43 +00:00
for ( u = 0 ; u < fileNamesNb ; u + + ) DISPLAYLEVEL ( 4 , " %u %s \n " , u , extendedFileList [ u ] ) ;
2016-05-29 03:16:05 +00:00
free ( ( void * ) filenameTable ) ;
2016-09-21 10:24:43 +00:00
filenameTable = extendedFileList ;
2016-05-29 03:16:05 +00:00
filenameIdx = fileNamesNb ;
}
}
# endif
/* Check if benchmark is selected */
2016-10-28 20:58:31 +00:00
if ( operation = = zom_bench ) {
2016-05-29 03:16:05 +00:00
# ifndef ZSTD_NOBENCH
BMK_setNotificationLevel ( displayLevel ) ;
2017-01-20 00:59:56 +00:00
BMK_setBlockSize ( blockSize ) ;
BMK_setNbThreads ( nbThreads ) ;
BMK_setNbSeconds ( bench_nbSeconds ) ;
2017-02-07 15:48:01 +00:00
BMK_benchFiles ( filenameTable , filenameIdx , dictFileName , cLevel , cLevelLast , & compressionParams , setRealTimePrio ) ;
2016-05-29 03:16:05 +00:00
# endif
2017-02-03 00:19:09 +00:00
( void ) bench_nbSeconds ;
2016-05-29 03:16:05 +00:00
goto _end ;
}
/* Check if dictionary builder is selected */
2016-10-28 20:58:31 +00:00
if ( operation = = zom_train ) {
2016-05-29 03:16:05 +00:00
# ifndef ZSTD_NODICT
2017-01-01 05:08:24 +00:00
if ( cover ) {
2017-01-27 19:56:02 +00:00
coverParams . nbThreads = nbThreads ;
2017-01-01 05:08:24 +00:00
coverParams . compressionLevel = dictCLevel ;
coverParams . notificationLevel = displayLevel ;
coverParams . dictID = dictID ;
DiB_trainFromFiles ( outFileName , maxDictSize , filenameTable , filenameIdx , NULL , & coverParams , cover - 1 ) ;
} else {
ZDICT_params_t dictParams ;
memset ( & dictParams , 0 , sizeof ( dictParams ) ) ;
dictParams . compressionLevel = dictCLevel ;
dictParams . selectivityLevel = dictSelect ;
dictParams . notificationLevel = displayLevel ;
dictParams . dictID = dictID ;
DiB_trainFromFiles ( outFileName , maxDictSize , filenameTable , filenameIdx , & dictParams , NULL , 0 ) ;
}
2016-05-29 03:16:05 +00:00
# endif
goto _end ;
}
/* No input filename ==> use stdin and stdout */
2016-08-25 23:43:47 +00:00
filenameIdx + = ! filenameIdx ; /* filenameTable[0] is stdin by default */
if ( ! strcmp ( filenameTable [ 0 ] , stdinmark ) & & ! outFileName ) outFileName = stdoutmark ; /* when input is stdin, default output is stdout */
2016-05-29 03:16:05 +00:00
/* Check if input/output defined as console; trigger an error in this case */
if ( ! strcmp ( filenameTable [ 0 ] , stdinmark ) & & IS_CONSOLE ( stdin ) ) CLEAN_RETURN ( badusage ( programName ) ) ;
2016-10-28 20:58:31 +00:00
if ( outFileName & & ! strcmp ( outFileName , stdoutmark ) & & IS_CONSOLE ( stdout ) & & strcmp ( filenameTable [ 0 ] , stdinmark ) & & ! ( forceStdout & & ( operation = = zom_decompress ) ) )
2016-05-29 03:16:05 +00:00
CLEAN_RETURN ( badusage ( programName ) ) ;
/* user-selected output filename, only possible with a single file */
if ( outFileName & & strcmp ( outFileName , stdoutmark ) & & strcmp ( outFileName , nulmark ) & & ( filenameIdx > 1 ) ) {
DISPLAY ( " Too many files (%u) on the command line. \n " , filenameIdx ) ;
CLEAN_RETURN ( filenameIdx ) ;
}
2016-10-05 09:56:22 +00:00
# ifndef ZSTD_NOCOMPRESS
2016-08-12 16:04:15 +00:00
/* check compression level limits */
{ int const maxCLevel = ultra ? ZSTD_maxCLevel ( ) : ZSTDCLI_CLEVEL_MAX ;
if ( cLevel > maxCLevel ) {
DISPLAYLEVEL ( 2 , " Warning : compression level higher than max, reduced to %i \n " , maxCLevel ) ;
cLevel = maxCLevel ;
} }
2016-10-05 09:56:22 +00:00
# endif
2016-08-12 16:04:15 +00:00
2017-01-19 21:46:30 +00:00
/* No status message in pipe mode (stdin - stdout) or multi-files mode */
2016-05-29 03:16:05 +00:00
if ( ! strcmp ( filenameTable [ 0 ] , stdinmark ) & & outFileName & & ! strcmp ( outFileName , stdoutmark ) & & ( displayLevel = = 2 ) ) displayLevel = 1 ;
2016-07-18 02:06:43 +00:00
if ( ( filenameIdx > 1 ) & ( displayLevel = = 2 ) ) displayLevel = 1 ;
2016-05-29 03:16:05 +00:00
/* IO Stream/File */
FIO_setNotificationLevel ( displayLevel ) ;
2016-10-28 20:58:31 +00:00
if ( operation = = zom_compress ) {
2016-09-21 10:24:43 +00:00
# ifndef ZSTD_NOCOMPRESS
2017-01-20 00:59:56 +00:00
FIO_setNbThreads ( nbThreads ) ;
2017-01-25 01:02:26 +00:00
FIO_setBlockSize ( ( U32 ) blockSize ) ;
2017-01-30 22:37:08 +00:00
if ( g_overlapLog ! = OVERLAP_LOG_DEFAULT ) FIO_setOverlapLog ( g_overlapLog ) ;
2016-09-21 14:46:08 +00:00
if ( ( filenameIdx = = 1 ) & & outFileName )
2016-12-13 12:24:59 +00:00
operationResult = FIO_compressFilename ( outFileName , filenameTable [ 0 ] , dictFileName , cLevel , & compressionParams ) ;
2016-05-29 03:16:05 +00:00
else
2017-02-08 16:37:14 +00:00
operationResult = FIO_compressMultipleFilenames ( filenameTable , filenameIdx , outFileName ? outFileName : suffix , dictFileName , cLevel , & compressionParams ) ;
2016-09-21 10:24:43 +00:00
# else
DISPLAY ( " Compression not supported \n " ) ;
2016-05-29 03:16:05 +00:00
# endif
2016-10-28 20:58:31 +00:00
} else { /* decompression or test */
2016-05-29 03:16:05 +00:00
# ifndef ZSTD_NODECOMPRESS
2016-10-28 20:58:31 +00:00
if ( operation = = zom_test ) { outFileName = nulmark ; FIO_setRemoveSrcFile ( 0 ) ; } /* test mode */
2016-10-14 20:13:13 +00:00
FIO_setMemLimit ( memLimit ) ;
2016-05-29 03:16:05 +00:00
if ( filenameIdx = = 1 & & outFileName )
operationResult = FIO_decompressFilename ( outFileName , filenameTable [ 0 ] , dictFileName ) ;
else
operationResult = FIO_decompressMultipleFilenames ( filenameTable , filenameIdx , outFileName ? outFileName : ZSTD_EXTENSION , dictFileName ) ;
# else
DISPLAY ( " Decompression not supported \n " ) ;
# endif
}
_end :
if ( main_pause ) waitEnter ( ) ;
# ifdef UTIL_HAS_CREATEFILELIST
2016-09-21 10:24:43 +00:00
if ( extendedFileList )
UTIL_freeFileList ( extendedFileList , fileNamesBuf ) ;
2016-05-29 03:16:05 +00:00
else
# endif
free ( ( void * ) filenameTable ) ;
return operationResult ;
}