2017-08-18 16:52:05 -07:00
/*
2016-08-30 10:04:33 -07:00
* Copyright ( c ) 2016 - present , Yann Collet , Facebook , Inc .
* All rights reserved .
*
2017-08-18 16:52:05 -07:00
* This source code is licensed under both the BSD - style license ( found in the
* LICENSE file in the root directory of this source tree ) and the GPLv2 ( found
* in the COPYING file in the root directory of this source tree ) .
2017-09-08 00:09:23 -07:00
* You may select , at your option , one of the above - listed licenses .
2016-08-30 10:04:33 -07:00
*/
2016-08-28 10:00:49 -07:00
2016-05-28 20:16:05 -07:00
2016-07-13 05:15:08 -07:00
/*-************************************
* Tuning parameters
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-07-13 06:16:00 -07:00
# ifndef ZSTDCLI_CLEVEL_DEFAULT
# define ZSTDCLI_CLEVEL_DEFAULT 3
2016-07-13 05:15:08 -07:00
# endif
2016-08-12 09:04:15 -07:00
# ifndef ZSTDCLI_CLEVEL_MAX
2017-08-19 13:33:50 -07:00
# define ZSTDCLI_CLEVEL_MAX 19 /* without using --ultra */
2016-08-12 09:04:15 -07:00
# endif
2016-07-13 05:15:08 -07:00
2017-01-25 17:01:13 -08:00
2016-05-28 20:16:05 -07:00
/*-************************************
2016-11-16 08:50:54 -08:00
* Dependencies
2016-05-28 20:16:05 -07:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-12-21 06:08:44 -08:00
# include "platform.h" /* IS_CONSOLE, PLATFORM_POSIX_VERSION */
# include "util.h" /* UTIL_HAS_CREATEFILELIST, UTIL_createFileList */
2017-08-19 13:33:50 -07:00
# include <stdio.h> /* fprintf(), stdin, stdout, stderr */
2018-12-19 13:26:27 -08:00
# include <stdlib.h> /* getenv */
2016-05-28 20:16:05 -07:00
# include <string.h> /* strcmp, strlen */
2016-07-04 09:16:16 -07:00
# include <errno.h> /* errno */
2017-08-19 13:33:50 -07:00
# include "fileio.h" /* stdinmark, stdoutmark, ZSTD_EXTENSION */
2016-05-28 20:16:05 -07:00
# ifndef ZSTD_NOBENCH
2018-11-13 11:01:59 -08:00
# include "benchzstd.h" /* BMK_benchFiles */
2016-05-28 20:16:05 -07:00
# endif
# ifndef ZSTD_NODICT
2017-08-19 13:33:50 -07:00
# include "dibio.h" /* ZDICT_cover_params_t, DiB_trainFromFiles() */
2016-05-28 20:16:05 -07:00
# endif
2018-09-22 16:10:10 -07:00
# define ZSTD_STATIC_LINKING_ONLY /* ZSTD_minCLevel */
# include "zstd.h" /* ZSTD_VERSION_STRING, ZSTD_maxCLevel */
2016-05-28 20:16:05 -07: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-04-14 11:33:04 -07:00
# define ZSTD_ZSTDMT "zstdmt"
2016-05-28 20:16:05 -07:00
# define ZSTD_UNZSTD "unzstd"
2017-02-14 10:45:19 -08:00
# define ZSTD_CAT "zstdcat"
2018-01-19 11:26:35 -08:00
# define ZSTD_ZCAT "zcat"
2017-02-14 10:45:19 -08:00
# define ZSTD_GZ "gzip"
# define ZSTD_GUNZIP "gunzip"
# define ZSTD_GZCAT "gzcat"
2017-03-13 18:11:07 -07:00
# define ZSTD_LZMA "lzma"
2017-06-26 11:24:36 -07:00
# define ZSTD_UNLZMA "unlzma"
2017-03-13 18:11:07 -07:00
# define ZSTD_XZ "xz"
2017-06-26 11:24:36 -07:00
# define ZSTD_UNXZ "unxz"
2017-09-28 16:18:15 -07:00
# define ZSTD_LZ4 "lz4"
# define ZSTD_UNLZ4 "unlz4"
2016-05-28 20:16:05 -07:00
# define KB *(1 <<10)
# define MB *(1 <<20)
# define GB *(1U<<30)
2017-08-19 13:33:50 -07:00
# define DISPLAY_LEVEL_DEFAULT 2
2016-08-12 14:49:05 -07:00
2016-05-28 20:16:05 -07:00
static const char * g_defaultDictName = " dictionary " ;
static const unsigned g_defaultMaxDictSize = 110 KB ;
2016-09-01 15:05:57 -07:00
static const int g_defaultDictCLevel = 3 ;
2016-05-28 20:16:05 -07:00
static const unsigned g_defaultSelectivityLevel = 9 ;
2017-09-22 14:04:39 -07:00
static const unsigned g_defaultMaxWindowLog = 27 ;
2017-01-30 14:37:08 -08:00
# define OVERLAP_LOG_DEFAULT 9999
2017-09-02 21:10:36 -07:00
# define LDM_PARAM_DEFAULT 9999 /* Default for parameters where 0 is valid */
2017-01-30 14:37:08 -08:00
static U32 g_overlapLog = OVERLAP_LOG_DEFAULT ;
2017-09-01 14:52:51 -07:00
static U32 g_ldmHashLog = 0 ;
static U32 g_ldmMinMatch = 0 ;
2018-11-21 14:36:57 -08:00
static U32 g_ldmHashRateLog = LDM_PARAM_DEFAULT ;
2017-09-02 21:10:36 -07:00
static U32 g_ldmBucketSizeLog = LDM_PARAM_DEFAULT ;
2016-05-28 20:16:05 -07:00
2018-08-23 12:06:20 -07:00
# define DEFAULT_ACCEL 1
typedef enum { cover , fastCover , legacy } dictType ;
2016-05-28 20:16:05 -07:00
/*-************************************
* Display Macros
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2017-03-23 11:13:52 -07:00
# define DISPLAY(...) fprintf(g_displayOut, __VA_ARGS__)
# define DISPLAYLEVEL(l, ...) { if (g_displayLevel>=l) { DISPLAY(__VA_ARGS__); } }
2017-08-19 13:33:50 -07:00
static int g_displayLevel = DISPLAY_LEVEL_DEFAULT ; /* 0 : no display, 1: errors, 2 : + result + interaction + warnings, 3 : + progression, 4 : + information */
2017-03-23 11:13:52 -07:00
static FILE * g_displayOut ;
2016-05-28 20:16:05 -07:00
/*-************************************
* Command Line
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int usage ( const char * programName )
{
2017-08-18 15:15:31 -07:00
DISPLAY ( " Usage : \n " ) ;
DISPLAY ( " %s [args] [FILE(s)] [-o file] \n " , programName ) ;
2016-05-28 20:16:05 -07:00
DISPLAY ( " \n " ) ;
2017-08-18 15:15:31 -07:00
DISPLAY ( " FILE : a filename \n " ) ;
2016-05-28 20:16:05 -07:00
DISPLAY ( " with no FILE, or when FILE is - , read standard input \n " ) ;
2017-08-18 15:15:31 -07:00
DISPLAY ( " Arguments : \n " ) ;
2016-05-28 20:16:05 -07:00
# ifndef ZSTD_NOCOMPRESS
2018-01-24 04:59:44 -08:00
DISPLAY ( " -# : # compression level (1-%d, default: %d) \n " , ZSTDCLI_CLEVEL_MAX , ZSTDCLI_CLEVEL_DEFAULT ) ;
2016-05-28 20:16:05 -07: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 " ) ;
2019-09-05 16:03:35 -07:00
DISPLAY ( " -O directory: result(s) stored into `directory`, creates one if non-existent \n " ) ;
2017-03-23 11:52:09 -07:00
DISPLAY ( " -f : overwrite output without prompting and (de)compress links \n " ) ;
2016-07-01 15:37:32 -07:00
DISPLAY ( " --rm : remove source file(s) after successful de/compression \n " ) ;
2016-07-03 15:42:58 -07:00
DISPLAY ( " -k : preserve source file(s) (default) \n " ) ;
2017-08-18 15:15:31 -07:00
DISPLAY ( " -h/-H : display help/long help and exit \n " ) ;
2016-05-28 20:16:05 -07:00
return 0 ;
}
static int usage_advanced ( const char * programName )
{
DISPLAY ( WELCOME_MESSAGE ) ;
usage ( programName ) ;
DISPLAY ( " \n " ) ;
2017-08-18 15:15:31 -07:00
DISPLAY ( " Advanced arguments : \n " ) ;
DISPLAY ( " -V : display Version number and exit \n " ) ;
2017-04-01 00:36:31 -07:00
DISPLAY ( " -v : verbose mode; specify multiple times to increase verbosity \n " ) ;
2016-05-28 20:16:05 -07: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 " ) ;
2017-08-18 15:15:31 -07:00
DISPLAY ( " -l : print information about zstd compressed files \n " ) ;
2016-05-28 20:16:05 -07:00
# ifndef ZSTD_NOCOMPRESS
2016-08-12 09:04:15 -07:00
DISPLAY ( " --ultra : enable levels beyond %i, up to %i (requires more memory) \n " , ZSTDCLI_CLEVEL_MAX , ZSTD_maxCLevel ( ) ) ;
2018-03-11 19:56:48 -07:00
DISPLAY ( " --long[=#]: enable long distance matching with given window log (default: %u) \n " , g_defaultMaxWindowLog ) ;
DISPLAY ( " --fast[=#]: switch to ultra fast compression level (default: %u) \n " , 1 ) ;
2018-09-24 18:16:08 -07:00
DISPLAY ( " --adapt : dynamically adapt compression level to I/O conditions \n " ) ;
2019-08-15 23:57:55 -07:00
DISPLAY ( " --stream-size=# : optimize compression parameters for streaming input of given number of bytes \n " ) ;
2019-08-19 08:52:08 -07:00
DISPLAY ( " --size-hint=# optimize compression parameters for streaming input of approximately this size \n " ) ;
2019-06-24 13:40:52 -07:00
DISPLAY ( " --target-compressed-block-size=# : make compressed block near targeted size \n " ) ;
2017-01-19 16:59:56 -08:00
# ifdef ZSTD_MULTITHREAD
2018-03-12 17:43:32 -07:00
DISPLAY ( " -T# : spawns # compression threads (default: 1, 0==# cores) \n " ) ;
2018-01-24 04:59:44 -08:00
DISPLAY ( " -B# : select size of each job (default: 0==automatic) \n " ) ;
2018-11-12 19:59:42 -08:00
DISPLAY ( " --rsyncable : compress using a rsync-friendly method (-B sets block size) \n " ) ;
2017-04-01 00:36:31 -07:00
# endif
DISPLAY ( " --no-dictID : don't write dictID into header (dictionary compression) \n " ) ;
2018-01-24 04:59:44 -08:00
DISPLAY ( " --[no-]check : integrity check (default: enabled) \n " ) ;
2019-02-15 14:15:36 -08:00
DISPLAY ( " --[no-]compress-literals : force (un)compressed literals \n " ) ;
2017-04-01 00:36:31 -07:00
# endif
# ifdef UTIL_HAS_CREATEFILELIST
DISPLAY ( " -r : operate recursively on directories \n " ) ;
2017-01-19 16:59:56 -08:00
# endif
2018-11-27 19:51:16 -08:00
DISPLAY ( " --format=zstd : compress files to the .zst format (default) \n " ) ;
2017-02-08 06:17:55 -08:00
# ifdef ZSTD_GZCOMPRESS
2017-02-08 09:08:09 -08:00
DISPLAY ( " --format=gzip : compress files to the .gz format \n " ) ;
2017-02-08 06:17:55 -08:00
# endif
2017-03-13 18:11:07 -07:00
# ifdef ZSTD_LZMACOMPRESS
DISPLAY ( " --format=xz : compress files to the .xz format \n " ) ;
DISPLAY ( " --format=lzma : compress files to the .lzma format \n " ) ;
# endif
2017-04-24 16:48:25 -07:00
# ifdef ZSTD_LZ4COMPRESS
DISPLAY ( " --format=lz4 : compress files to the .lz4 format \n " ) ;
# endif
2016-05-30 17:29:45 -07:00
# ifndef ZSTD_NODECOMPRESS
2016-06-02 08:05:50 -07:00
DISPLAY ( " --test : test compressed file integrity \n " ) ;
2017-03-31 15:16:43 -07:00
# if ZSTD_SPARSE_DEFAULT
2018-01-24 04:59:44 -08:00
DISPLAY ( " --[no-]sparse : sparse mode (default: enabled on file, disabled on stdout) \n " ) ;
2017-03-31 15:16:43 -07:00
# else
2018-01-24 04:59:44 -08:00
DISPLAY ( " --[no-]sparse : sparse mode (default: disabled) \n " ) ;
2017-03-31 15:16:43 -07:00
# endif
2016-05-30 17:29:45 -07:00
# endif
2016-10-14 13:13:13 -07:00
DISPLAY ( " -M# : Set a memory usage limit for decompression \n " ) ;
2018-12-13 17:17:32 -08:00
DISPLAY ( " --no-progress : do not display the progress bar \n " ) ;
2016-09-16 09:52:52 -07:00
DISPLAY ( " -- : All arguments after \" -- \" are treated as files \n " ) ;
2016-05-28 20:16:05 -07:00
# ifndef ZSTD_NODICT
DISPLAY ( " \n " ) ;
2017-08-18 15:15:31 -07:00
DISPLAY ( " Dictionary builder : \n " ) ;
2016-06-09 13:59:51 -07:00
DISPLAY ( " --train ## : create a dictionary from a training set of files \n " ) ;
2019-06-27 16:26:57 -07:00
DISPLAY ( " --train-cover[=k=#,d=#,steps=#,split=#,shrink[=#]] : use the cover algorithm with optional args \n " ) ;
DISPLAY ( " --train-fastcover[=k=#,d=#,f=#,steps=#,split=#,accel=#,shrink[=#]] : use the fast cover algorithm with optional args \n " ) ;
2017-05-01 23:40:20 -07:00
DISPLAY ( " --train-legacy[=s=#] : use the legacy algorithm with selectivity (default: %u) \n " , g_defaultSelectivityLevel ) ;
2016-06-09 13:59:51 -07:00
DISPLAY ( " -o file : `file` is dictionary name (default: %s) \n " , g_defaultDictName ) ;
2018-01-24 04:59:44 -08:00
DISPLAY ( " --maxdict=# : limit dictionary to specified size (default: %u) \n " , g_defaultMaxDictSize ) ;
2017-03-24 16:04:29 -07:00
DISPLAY ( " --dictID=# : force dictionary ID to specified value (default: random) \n " ) ;
2016-05-28 20:16:05 -07:00
# endif
# ifndef ZSTD_NOBENCH
DISPLAY ( " \n " ) ;
2017-08-18 15:15:31 -07:00
DISPLAY ( " Benchmark arguments : \n " ) ;
2018-01-24 04:59:44 -08:00
DISPLAY ( " -b# : benchmark file(s), using # compression level (default: %d) \n " , ZSTDCLI_CLEVEL_DEFAULT ) ;
2016-05-28 20:16:05 -07:00
DISPLAY ( " -e# : test all compression levels from -bX to # (default: 1) \n " ) ;
2018-01-24 04:59:44 -08:00
DISPLAY ( " -i# : minimum evaluation time in seconds (default: 3s) \n " ) ;
2016-05-28 20:16:05 -07:00
DISPLAY ( " -B# : cut file into independent blocks of size # (default: no block) \n " ) ;
2017-08-18 15:15:31 -07:00
DISPLAY ( " --priority=rt : set process priority to real-time \n " ) ;
2016-05-28 20:16:05 -07:00
# endif
return 0 ;
}
static int badusage ( const char * programName )
{
DISPLAYLEVEL ( 1 , " Incorrect parameters \n " ) ;
2017-03-23 11:13:52 -07:00
if ( g_displayLevel > = 2 ) usage ( programName ) ;
2016-05-28 20:16:05 -07:00
return 1 ;
}
static void waitEnter ( void )
{
int unused ;
DISPLAY ( " Press enter to continue... \n " ) ;
unused = getchar ( ) ;
( void ) unused ;
}
2017-03-24 17:06:09 -07:00
static const char * lastNameFromPath ( const char * path )
{
const char * name = path ;
if ( strrchr ( name , ' / ' ) ) name = strrchr ( name , ' / ' ) + 1 ;
if ( strrchr ( name , ' \\ ' ) ) name = strrchr ( name , ' \\ ' ) + 1 ; /* windows */
return name ;
}
/*! exeNameMatch() :
@ return : a non - zero value if exeName matches test , excluding the extension
*/
static int exeNameMatch ( const char * exeName , const char * test )
{
return ! strncmp ( exeName , test , strlen ( test ) ) & &
( exeName [ strlen ( test ) ] = = ' \0 ' | | exeName [ strlen ( test ) ] = = ' . ' ) ;
}
2018-05-12 14:29:33 -07:00
static void errorOut ( const char * msg )
{
DISPLAY ( " %s \n " , msg ) ; exit ( 1 ) ;
}
2018-12-19 23:41:18 -08:00
/*! readU32FromCharChecked() :
2018-12-19 16:45:42 -08:00
* @ return 0 if success , and store the result in * value .
2018-03-11 19:56:48 -07:00
* allows and interprets K , KB , KiB , M , MB and MiB suffix .
* Will also modify ` * stringPtr ` , advancing it to position where it stopped reading .
2018-12-19 16:45:42 -08:00
* @ return 1 if an overflow error occurs */
2018-12-19 23:41:18 -08:00
static int readU32FromCharChecked ( const char * * stringPtr , unsigned * value )
2016-06-03 06:14:09 -07:00
{
unsigned result = 0 ;
2018-05-12 14:29:33 -07:00
while ( ( * * stringPtr > = ' 0 ' ) & & ( * * stringPtr < = ' 9 ' ) ) {
2019-04-10 10:03:06 -07:00
unsigned const max = ( ( ( unsigned ) ( - 1 ) ) / 10 ) - 1 ;
if ( result > max ) return 1 ; /* overflow error */
result * = 10 ;
result + = ( unsigned ) ( * * stringPtr - ' 0 ' ) ;
( * stringPtr ) + + ;
2018-05-12 14:29:33 -07:00
}
2016-10-17 17:48:48 -07:00
if ( ( * * stringPtr = = ' K ' ) | | ( * * stringPtr = = ' M ' ) ) {
2018-05-12 14:29:33 -07:00
unsigned const maxK = ( ( unsigned ) ( - 1 ) ) > > 10 ;
2019-04-10 10:03:06 -07:00
if ( result > maxK ) return 1 ; /* overflow error */
2016-10-17 17:48:48 -07:00
result < < = 10 ;
2018-05-12 14:29:33 -07:00
if ( * * stringPtr = = ' M ' ) {
2019-04-10 10:03:06 -07:00
if ( result > maxK ) return 1 ; /* overflow error */
2018-05-12 14:29:33 -07:00
result < < = 10 ;
}
( * stringPtr ) + + ; /* skip `K` or `M` */
2016-10-17 17:48:48 -07:00
if ( * * stringPtr = = ' i ' ) ( * stringPtr ) + + ;
if ( * * stringPtr = = ' B ' ) ( * stringPtr ) + + ;
}
2018-12-19 16:45:42 -08:00
* value = result ;
return 0 ;
}
/*! readU32FromChar() :
* @ return : unsigned integer value read from input in ` char ` format .
* allows and interprets K , KB , KiB , M , MB and MiB suffix .
* Will also modify ` * stringPtr ` , advancing it to position where it stopped reading .
* Note : function will exit ( ) program if digit sequence overflows */
static unsigned readU32FromChar ( const char * * stringPtr ) {
static const char errorMsg [ ] = " error: numeric value too large " ;
unsigned result ;
2018-12-19 23:41:18 -08:00
if ( readU32FromCharChecked ( stringPtr , & result ) ) { errorOut ( errorMsg ) ; }
2016-06-03 06:14:09 -07:00
return result ;
}
2016-12-02 15:18:57 -08:00
/** longCommandWArg() :
2017-01-30 13:07:24 -08:00
* check if * stringPtr is the same as longCommand .
2016-12-02 15:18:57 -08:00
* If yes , @ return 1 and advances * stringPtr to the position which immediately follows longCommand .
2018-03-11 19:56:48 -07:00
* @ return 0 and doesn ' t modify * stringPtr otherwise .
2016-12-02 15:18:57 -08:00
*/
2016-10-14 14:41:17 -07:00
static unsigned longCommandWArg ( const char * * stringPtr , const char * longCommand )
{
size_t const comSize = strlen ( longCommand ) ;
2016-12-02 15:18:57 -08:00
int const result = ! strncmp ( * stringPtr , longCommand , comSize ) ;
2016-10-14 14:41:17 -07:00
if ( result ) * stringPtr + = comSize ;
return result ;
}
2016-12-13 03:18:07 -08:00
2016-12-31 21:08:24 -08:00
# ifndef ZSTD_NODICT
2019-07-18 11:44:59 -07:00
static const unsigned kDefaultRegression = 1 ;
2016-12-31 21:08:24 -08:00
/**
* parseCoverParameters ( ) :
2017-05-01 23:40:20 -07:00
* reads cover parameters from * stringPtr ( e . g . " --train-cover=k=48,d=8,steps=32 " ) into * params
2016-12-31 21:08:24 -08:00
* @ return 1 means that cover parameters were correct
* @ return 0 in case of malformed parameters
*/
2017-06-26 21:07:14 -07:00
static unsigned parseCoverParameters ( const char * stringPtr , ZDICT_cover_params_t * params )
2016-12-31 21:08:24 -08:00
{
memset ( params , 0 , sizeof ( * params ) ) ;
for ( ; ; ) {
2017-01-02 12:40:43 -08:00
if ( longCommandWArg ( & stringPtr , " k= " ) ) { params - > k = readU32FromChar ( & stringPtr ) ; if ( stringPtr [ 0 ] = = ' , ' ) { stringPtr + + ; continue ; } else break ; }
2016-12-31 21:08:24 -08:00
if ( longCommandWArg ( & stringPtr , " d= " ) ) { params - > d = readU32FromChar ( & stringPtr ) ; if ( stringPtr [ 0 ] = = ' , ' ) { stringPtr + + ; continue ; } else break ; }
2017-01-02 12:40:43 -08:00
if ( longCommandWArg ( & stringPtr , " steps= " ) ) { params - > steps = readU32FromChar ( & stringPtr ) ; if ( stringPtr [ 0 ] = = ' , ' ) { stringPtr + + ; continue ; } else break ; }
2018-06-29 17:54:41 -07:00
if ( longCommandWArg ( & stringPtr , " split= " ) ) {
2018-07-03 17:53:27 -07:00
unsigned splitPercentage = readU32FromChar ( & stringPtr ) ;
2018-06-29 17:54:41 -07:00
params - > splitPoint = ( double ) splitPercentage / 100.0 ;
if ( stringPtr [ 0 ] = = ' , ' ) { stringPtr + + ; continue ; } else break ;
}
2019-06-27 16:26:57 -07:00
if ( longCommandWArg ( & stringPtr , " shrink " ) ) {
params - > shrinkDictMaxRegression = kDefaultRegression ;
params - > shrinkDict = 1 ;
if ( stringPtr [ 0 ] = = ' = ' ) {
stringPtr + + ;
params - > shrinkDictMaxRegression = readU32FromChar ( & stringPtr ) ;
}
if ( stringPtr [ 0 ] = = ' , ' ) {
stringPtr + + ;
continue ;
}
else break ;
}
2016-12-31 21:08:24 -08:00
return 0 ;
}
if ( stringPtr [ 0 ] ! = 0 ) return 0 ;
2019-06-27 16:26:57 -07:00
DISPLAYLEVEL ( 4 , " cover: k=%u \n d=%u \n steps=%u \n split=%u \n shrink%u \n " , params - > k , params - > d , params - > steps , ( unsigned ) ( params - > splitPoint * 100 ) , params - > shrinkDictMaxRegression ) ;
2016-12-31 21:08:24 -08:00
return 1 ;
}
2017-05-01 23:40:20 -07:00
2018-08-23 12:06:20 -07:00
/**
* parseFastCoverParameters ( ) :
* reads fastcover parameters from * stringPtr ( e . g . " --train-fastcover=k=48,d=8,f=20,steps=32,accel=2 " ) into * params
* @ return 1 means that fastcover parameters were correct
* @ return 0 in case of malformed parameters
*/
static unsigned parseFastCoverParameters ( const char * stringPtr , ZDICT_fastCover_params_t * params )
{
memset ( params , 0 , sizeof ( * params ) ) ;
for ( ; ; ) {
if ( longCommandWArg ( & stringPtr , " k= " ) ) { params - > k = readU32FromChar ( & stringPtr ) ; if ( stringPtr [ 0 ] = = ' , ' ) { stringPtr + + ; continue ; } else break ; }
if ( longCommandWArg ( & stringPtr , " d= " ) ) { params - > d = readU32FromChar ( & stringPtr ) ; if ( stringPtr [ 0 ] = = ' , ' ) { stringPtr + + ; continue ; } else break ; }
if ( longCommandWArg ( & stringPtr , " f= " ) ) { params - > f = readU32FromChar ( & stringPtr ) ; if ( stringPtr [ 0 ] = = ' , ' ) { stringPtr + + ; continue ; } else break ; }
if ( longCommandWArg ( & stringPtr , " steps= " ) ) { params - > steps = readU32FromChar ( & stringPtr ) ; if ( stringPtr [ 0 ] = = ' , ' ) { stringPtr + + ; continue ; } else break ; }
if ( longCommandWArg ( & stringPtr , " accel= " ) ) { params - > accel = readU32FromChar ( & stringPtr ) ; if ( stringPtr [ 0 ] = = ' , ' ) { stringPtr + + ; continue ; } else break ; }
if ( longCommandWArg ( & stringPtr , " split= " ) ) {
unsigned splitPercentage = readU32FromChar ( & stringPtr ) ;
params - > splitPoint = ( double ) splitPercentage / 100.0 ;
if ( stringPtr [ 0 ] = = ' , ' ) { stringPtr + + ; continue ; } else break ;
}
2019-06-27 16:26:57 -07:00
if ( longCommandWArg ( & stringPtr , " shrink " ) ) {
params - > shrinkDictMaxRegression = kDefaultRegression ;
params - > shrinkDict = 1 ;
if ( stringPtr [ 0 ] = = ' = ' ) {
stringPtr + + ;
params - > shrinkDictMaxRegression = readU32FromChar ( & stringPtr ) ;
}
if ( stringPtr [ 0 ] = = ' , ' ) {
stringPtr + + ;
continue ;
}
else break ;
}
2018-08-23 12:06:20 -07:00
return 0 ;
}
if ( stringPtr [ 0 ] ! = 0 ) return 0 ;
2019-06-27 16:26:57 -07:00
DISPLAYLEVEL ( 4 , " cover: k=%u \n d=%u \n f=%u \n steps=%u \n split=%u \n accel=%u \n shrink=%u \n " , params - > k , params - > d , params - > f , params - > steps , ( unsigned ) ( params - > splitPoint * 100 ) , params - > accel , params - > shrinkDictMaxRegression ) ;
2018-08-23 12:06:20 -07:00
return 1 ;
}
2017-05-01 23:40:20 -07:00
/**
* parseLegacyParameters ( ) :
2019-04-12 11:18:11 -07:00
* reads legacy dictionary builder parameters from * stringPtr ( e . g . " --train-legacy=selectivity=8 " ) into * selectivity
2017-05-01 23:40:20 -07:00
* @ return 1 means that legacy dictionary builder parameters were correct
* @ return 0 in case of malformed parameters
*/
static unsigned parseLegacyParameters ( const char * stringPtr , unsigned * selectivity )
{
if ( ! longCommandWArg ( & stringPtr , " s= " ) & & ! longCommandWArg ( & stringPtr , " selectivity= " ) ) { return 0 ; }
* selectivity = readU32FromChar ( & stringPtr ) ;
if ( stringPtr [ 0 ] ! = 0 ) return 0 ;
DISPLAYLEVEL ( 4 , " legacy: selectivity=%u \n " , * selectivity ) ;
return 1 ;
}
2017-06-26 21:07:14 -07:00
static ZDICT_cover_params_t defaultCoverParams ( void )
2017-05-01 23:40:20 -07:00
{
2017-06-26 21:07:14 -07:00
ZDICT_cover_params_t params ;
2017-05-01 23:40:20 -07:00
memset ( & params , 0 , sizeof ( params ) ) ;
params . d = 8 ;
params . steps = 4 ;
2018-08-23 12:06:20 -07:00
params . splitPoint = 1.0 ;
2019-06-27 16:26:57 -07:00
params . shrinkDict = 0 ;
params . shrinkDictMaxRegression = kDefaultRegression ;
2018-08-23 12:06:20 -07:00
return params ;
}
static ZDICT_fastCover_params_t defaultFastCoverParams ( void )
{
ZDICT_fastCover_params_t params ;
memset ( & params , 0 , sizeof ( params ) ) ;
params . d = 8 ;
2018-09-04 17:12:35 -07:00
params . f = 20 ;
2018-08-23 12:06:20 -07:00
params . steps = 4 ;
params . splitPoint = 0.75 ; /* different from default splitPoint of cover */
params . accel = DEFAULT_ACCEL ;
2019-06-27 16:26:57 -07:00
params . shrinkDict = 0 ;
params . shrinkDictMaxRegression = kDefaultRegression ;
2017-05-01 23:40:20 -07:00
return params ;
}
2016-12-31 21:08:24 -08:00
# endif
2017-01-30 13:07:24 -08:00
2018-09-24 18:16:08 -07:00
/** parseAdaptParameters() :
* reads adapt parameters from * stringPtr ( e . g . " --zstd=min=1,max=19) and store them into adaptMinPtr and adaptMaxPtr.
* Both adaptMinPtr and adaptMaxPtr must be already allocated and correctly initialized .
* There is no guarantee that any of these values will be updated .
* @ return 1 means that parsing was successful ,
* @ return 0 in case of malformed parameters
*/
static unsigned parseAdaptParameters ( const char * stringPtr , int * adaptMinPtr , int * adaptMaxPtr )
{
for ( ; ; ) {
if ( longCommandWArg ( & stringPtr , " min= " ) ) { * adaptMinPtr = readU32FromChar ( & stringPtr ) ; if ( stringPtr [ 0 ] = = ' , ' ) { stringPtr + + ; continue ; } else break ; }
if ( longCommandWArg ( & stringPtr , " max= " ) ) { * adaptMaxPtr = readU32FromChar ( & stringPtr ) ; if ( stringPtr [ 0 ] = = ' , ' ) { stringPtr + + ; continue ; } else break ; }
DISPLAYLEVEL ( 4 , " invalid compression parameter \n " ) ;
return 0 ;
}
if ( stringPtr [ 0 ] ! = 0 ) return 0 ; /* check the end of string */
if ( * adaptMinPtr > * adaptMaxPtr ) {
DISPLAYLEVEL ( 4 , " incoherent adaptation limits \n " ) ;
return 0 ;
}
return 1 ;
}
2016-12-13 03:18:07 -08:00
/** parseCompressionParameters() :
2018-11-20 14:56:07 -08:00
* reads compression parameters from * stringPtr ( e . g . " --zstd=wlog=23,clog=23,hlog=22,slog=6,mml=3,tlen=48,strat=6 " ) into * params
2016-12-13 03:18:07 -08:00
* @ 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 ; }
2018-11-20 14:56:07 -08:00
if ( longCommandWArg ( & stringPtr , " minMatch= " ) | | longCommandWArg ( & stringPtr , " mml= " ) ) { params - > minMatch = readU32FromChar ( & stringPtr ) ; if ( stringPtr [ 0 ] = = ' , ' ) { stringPtr + + ; continue ; } else break ; }
2016-12-13 03:18:07 -08:00
if ( longCommandWArg ( & stringPtr , " targetLength= " ) | | longCommandWArg ( & stringPtr , " tlen= " ) ) { params - > targetLength = readU32FromChar ( & stringPtr ) ; if ( stringPtr [ 0 ] = = ' , ' ) { stringPtr + + ; continue ; } else break ; }
2017-06-20 14:11:49 -07:00
if ( longCommandWArg ( & stringPtr , " strategy= " ) | | longCommandWArg ( & stringPtr , " strat= " ) ) { params - > strategy = ( ZSTD_strategy ) ( readU32FromChar ( & stringPtr ) ) ; if ( stringPtr [ 0 ] = = ' , ' ) { stringPtr + + ; continue ; } else break ; }
2017-01-30 13:07:24 -08:00
if ( longCommandWArg ( & stringPtr , " overlapLog= " ) | | longCommandWArg ( & stringPtr , " ovlog= " ) ) { g_overlapLog = readU32FromChar ( & stringPtr ) ; if ( stringPtr [ 0 ] = = ' , ' ) { stringPtr + + ; continue ; } else break ; }
2018-11-20 14:56:07 -08:00
if ( longCommandWArg ( & stringPtr , " ldmHashLog= " ) | | longCommandWArg ( & stringPtr , " lhlog= " ) ) { g_ldmHashLog = readU32FromChar ( & stringPtr ) ; if ( stringPtr [ 0 ] = = ' , ' ) { stringPtr + + ; continue ; } else break ; }
if ( longCommandWArg ( & stringPtr , " ldmMinMatch= " ) | | longCommandWArg ( & stringPtr , " lmml= " ) ) { g_ldmMinMatch = readU32FromChar ( & stringPtr ) ; if ( stringPtr [ 0 ] = = ' , ' ) { stringPtr + + ; continue ; } else break ; }
if ( longCommandWArg ( & stringPtr , " ldmBucketSizeLog= " ) | | longCommandWArg ( & stringPtr , " lblog= " ) ) { g_ldmBucketSizeLog = readU32FromChar ( & stringPtr ) ; if ( stringPtr [ 0 ] = = ' , ' ) { stringPtr + + ; continue ; } else break ; }
2018-11-21 14:36:57 -08:00
if ( longCommandWArg ( & stringPtr , " ldmHashRateLog= " ) | | longCommandWArg ( & stringPtr , " lhrlog= " ) ) { g_ldmHashRateLog = readU32FromChar ( & stringPtr ) ; if ( stringPtr [ 0 ] = = ' , ' ) { stringPtr + + ; continue ; } else break ; }
2017-12-27 04:32:05 -08:00
DISPLAYLEVEL ( 4 , " invalid compression parameter \n " ) ;
2016-12-13 03:18:07 -08:00
return 0 ;
}
2017-12-27 04:32:05 -08:00
DISPLAYLEVEL ( 4 , " windowLog=%d, chainLog=%d, hashLog=%d, searchLog=%d \n " , params - > windowLog , params - > chainLog , params - > hashLog , params - > searchLog ) ;
2018-11-20 14:56:07 -08:00
DISPLAYLEVEL ( 4 , " minMatch=%d, targetLength=%d, strategy=%d \n " , params - > minMatch , params - > targetLength , params - > strategy ) ;
2016-12-13 03:18:07 -08:00
if ( stringPtr [ 0 ] ! = 0 ) return 0 ; /* check the end of string */
return 1 ;
}
2017-08-19 13:33:50 -07:00
static void printVersion ( void )
{
DISPLAY ( WELCOME_MESSAGE ) ;
/* format support */
DISPLAYLEVEL ( 3 , " *** supports: zstd " ) ;
# if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>0) && (ZSTD_LEGACY_SUPPORT<8)
DISPLAYLEVEL ( 3 , " , zstd legacy v0.%d+ " , ZSTD_LEGACY_SUPPORT ) ;
# endif
# ifdef ZSTD_GZCOMPRESS
DISPLAYLEVEL ( 3 , " , gzip " ) ;
# endif
# ifdef ZSTD_LZ4COMPRESS
DISPLAYLEVEL ( 3 , " , lz4 " ) ;
# endif
# ifdef ZSTD_LZMACOMPRESS
DISPLAYLEVEL ( 3 , " , lzma, xz " ) ;
# endif
DISPLAYLEVEL ( 3 , " \n " ) ;
/* posix support */
# 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-12-13 03:18:07 -08:00
2018-12-19 13:26:27 -08:00
/* Environment variables for parameter setting */
# define ENV_CLEVEL "ZSTD_CLEVEL"
/* functions that pick up environment variables */
2018-12-19 17:56:45 -08:00
static int init_cLevel ( void ) {
2018-12-19 16:45:42 -08:00
const char * const env = getenv ( ENV_CLEVEL ) ;
2018-12-19 13:26:27 -08:00
if ( env ) {
2018-12-19 16:45:42 -08:00
const char * ptr = env ;
2018-12-19 13:26:27 -08:00
int sign = 1 ;
2018-12-19 16:45:42 -08:00
if ( * ptr = = ' - ' ) {
2018-12-19 13:26:27 -08:00
sign = - 1 ;
2018-12-19 16:45:42 -08:00
ptr + + ;
} else if ( * ptr = = ' + ' ) {
ptr + + ;
}
if ( ( * ptr > = ' 0 ' ) & & ( * ptr < = ' 9 ' ) ) {
unsigned absLevel ;
2019-04-10 10:03:06 -07:00
if ( readU32FromCharChecked ( & ptr , & absLevel ) ) {
2018-12-19 23:41:18 -08:00
DISPLAYLEVEL ( 2 , " Ignore environment variable setting %s=%s: numeric value too large \n " , ENV_CLEVEL , env ) ;
2018-12-19 16:45:42 -08:00
return ZSTDCLI_CLEVEL_DEFAULT ;
} else if ( * ptr = = 0 ) {
return sign * absLevel ;
}
2018-12-19 13:26:27 -08:00
}
2018-12-19 23:41:18 -08:00
DISPLAYLEVEL ( 2 , " Ignore environment variable setting %s=%s: not a valid integer value \n " , ENV_CLEVEL , env ) ;
2018-12-19 13:26:27 -08:00
}
return ZSTDCLI_CLEVEL_DEFAULT ;
}
2017-06-05 14:45:31 -07:00
typedef enum { zom_compress , zom_decompress , zom_test , zom_bench , zom_train , zom_list } zstd_operation_mode ;
2016-05-28 20:16:05 -07:00
# define CLEAN_RETURN(i) { operationResult = (i); goto _end; }
2018-09-24 18:16:08 -07:00
# ifdef ZSTD_NOCOMPRESS
/* symbols from compression library are not defined and should not be invoked */
# define MINCLEVEL -50
# define MAXCLEVEL 22
# else
# define MINCLEVEL ZSTD_minCLevel()
# define MAXCLEVEL ZSTD_maxCLevel()
# endif
2016-09-21 03:24:43 -07:00
int main ( int argCount , const char * argv [ ] )
2016-05-28 20:16:05 -07:00
{
int argNb ,
2018-02-13 14:56:35 -08:00
followLinks = 0 ,
forceStdout = 0 ,
2018-02-09 15:53:27 -08:00
lastCommand = 0 ,
ldmFlag = 0 ,
2018-02-13 14:56:35 -08:00
main_pause = 0 ,
nbWorkers = 0 ,
2018-08-11 20:48:06 -07:00
adapt = 0 ,
2018-09-24 18:16:08 -07:00
adaptMin = MINCLEVEL ,
adaptMax = MAXCLEVEL ,
2018-11-12 19:59:42 -08:00
rsyncable = 0 ,
2018-02-13 14:56:35 -08:00
nextArgumentIsOutFileName = 0 ,
2019-09-05 16:03:35 -07:00
nextArgumentIsOutDirName = 0 ,
2018-02-13 14:56:35 -08:00
nextArgumentIsMaxDict = 0 ,
nextArgumentIsDictID = 0 ,
nextArgumentsAreFiles = 0 ,
nextEntryIsDictionary = 0 ,
operationResult = 0 ,
2017-11-17 00:22:55 -08:00
separateFiles = 0 ,
2018-02-09 15:53:27 -08:00
setRealTimePrio = 0 ,
2018-02-13 14:56:35 -08:00
singleThread = 0 ,
2018-02-09 15:53:27 -08:00
ultra = 0 ;
2018-06-19 10:58:22 -07:00
double compressibility = 0.5 ;
2017-01-19 16:59:56 -08:00
unsigned bench_nbSeconds = 3 ; /* would be better if this value was synchronized from bench */
size_t blockSize = 0 ;
2019-01-22 17:31:13 -08:00
FIO_prefs_t * const prefs = FIO_createPreferences ( ) ;
2016-10-28 13:58:31 -07:00
zstd_operation_mode operation = zom_compress ;
2016-12-13 03:18:07 -08:00
ZSTD_compressionParameters compressionParams ;
2018-12-19 17:49:04 -08:00
int cLevel ;
2018-03-21 15:50:05 -07:00
int cLevelLast = - 1000000000 ;
2016-05-28 20:16:05 -07:00
unsigned recursive = 0 ;
2016-10-14 13:13:13 -07:00
unsigned memLimit = 0 ;
2016-05-28 20:16:05 -07:00
const char * * filenameTable = ( const char * * ) malloc ( argCount * sizeof ( const char * ) ) ; /* argCount >= 1 */
2019-09-06 10:17:04 -07:00
char * * dstFilenameTable ;
2016-05-28 20:16:05 -07:00
unsigned filenameIdx = 0 ;
const char * programName = argv [ 0 ] ;
const char * outFileName = NULL ;
2019-09-05 16:03:35 -07:00
const char * outDirName = NULL ;
2016-05-28 20:16:05 -07:00
const char * dictFileName = NULL ;
2017-02-08 08:37:14 -08:00
const char * suffix = ZSTD_EXTENSION ;
2016-05-28 20:16:05 -07:00
unsigned maxDictSize = g_defaultMaxDictSize ;
2016-05-30 12:18:52 -07:00
unsigned dictID = 0 ;
2019-08-15 23:57:55 -07:00
size_t streamSrcSize = 0 ;
2019-06-24 13:40:52 -07:00
size_t targetCBlockSize = 0 ;
2019-08-19 08:52:08 -07:00
size_t srcSizeHint = 0 ;
2016-07-27 06:09:11 -07:00
int dictCLevel = g_defaultDictCLevel ;
2016-05-28 20:16:05 -07:00
unsigned dictSelect = g_defaultSelectivityLevel ;
# ifdef UTIL_HAS_CREATEFILELIST
2016-09-21 03:24:43 -07:00
const char * * extendedFileList = NULL ;
2016-05-28 20:16:05 -07:00
char * fileNamesBuf = NULL ;
unsigned fileNamesNb ;
# endif
2016-12-31 21:08:24 -08:00
# ifndef ZSTD_NODICT
2017-06-26 21:07:14 -07:00
ZDICT_cover_params_t coverParams = defaultCoverParams ( ) ;
2018-08-23 12:06:20 -07:00
ZDICT_fastCover_params_t fastCoverParams = defaultFastCoverParams ( ) ;
dictType dict = fastCover ;
2016-12-31 21:08:24 -08:00
# endif
2018-08-03 07:54:29 -07:00
# ifndef ZSTD_NOBENCH
BMK_advancedParams_t benchParams = BMK_initAdvancedParams ( ) ;
# endif
2019-02-15 15:24:55 -08:00
ZSTD_literalCompressionMode_e literalCompressionMode = ZSTD_lcm_auto ;
2016-05-28 20:16:05 -07:00
2017-10-01 12:10:26 -07:00
2016-05-28 20:16:05 -07:00
/* init */
2016-06-04 16:05:01 -07:00
( void ) recursive ; ( void ) cLevelLast ; /* not used when ZSTD_NOBENCH set */
2016-11-03 15:52:01 -07:00
( void ) memLimit ; /* not used when ZSTD_NODECOMPRESS set */
2016-07-03 15:42:58 -07:00
if ( filenameTable = = NULL ) { DISPLAY ( " zstd: %s \n " , strerror ( errno ) ) ; exit ( 1 ) ; }
2016-05-28 20:16:05 -07:00
filenameTable [ 0 ] = stdinmark ;
2018-12-19 17:49:04 -08:00
g_displayOut = stderr ;
cLevel = init_cLevel ( ) ;
2017-03-24 17:06:09 -07:00
programName = lastNameFromPath ( programName ) ;
2018-02-13 14:56:35 -08:00
# ifdef ZSTD_MULTITHREAD
nbWorkers = 1 ;
# endif
2016-05-28 20:16:05 -07:00
/* preset behaviors */
2018-06-29 17:10:56 -07:00
if ( exeNameMatch ( programName , ZSTD_ZSTDMT ) ) nbWorkers = 0 , singleThread = 0 ;
2017-03-24 17:06:09 -07:00
if ( exeNameMatch ( programName , ZSTD_UNZSTD ) ) operation = zom_decompress ;
2019-04-27 16:06:29 -07:00
if ( exeNameMatch ( programName , ZSTD_CAT ) ) { operation = zom_decompress ; FIO_overwriteMode ( prefs ) ; forceStdout = 1 ; followLinks = 1 ; outFileName = stdoutmark ; g_displayLevel = 1 ; } /* supports multiple formats */
if ( exeNameMatch ( programName , ZSTD_ZCAT ) ) { operation = zom_decompress ; FIO_overwriteMode ( prefs ) ; forceStdout = 1 ; followLinks = 1 ; outFileName = stdoutmark ; g_displayLevel = 1 ; } /* behave like zcat, also supports multiple formats */
2019-01-22 17:31:13 -08:00
if ( exeNameMatch ( programName , ZSTD_GZ ) ) { suffix = GZ_EXTENSION ; FIO_setCompressionType ( prefs , FIO_gzipCompression ) ; FIO_setRemoveSrcFile ( prefs , 1 ) ; } /* behave like gzip */
if ( exeNameMatch ( programName , ZSTD_GUNZIP ) ) { operation = zom_decompress ; FIO_setRemoveSrcFile ( prefs , 1 ) ; } /* behave like gunzip, also supports multiple formats */
2019-04-27 16:06:29 -07:00
if ( exeNameMatch ( programName , ZSTD_GZCAT ) ) { operation = zom_decompress ; FIO_overwriteMode ( prefs ) ; forceStdout = 1 ; followLinks = 1 ; outFileName = stdoutmark ; g_displayLevel = 1 ; } /* behave like gzcat, also supports multiple formats */
2019-01-22 17:31:13 -08:00
if ( exeNameMatch ( programName , ZSTD_LZMA ) ) { suffix = LZMA_EXTENSION ; FIO_setCompressionType ( prefs , FIO_lzmaCompression ) ; FIO_setRemoveSrcFile ( prefs , 1 ) ; } /* behave like lzma */
if ( exeNameMatch ( programName , ZSTD_UNLZMA ) ) { operation = zom_decompress ; FIO_setCompressionType ( prefs , FIO_lzmaCompression ) ; FIO_setRemoveSrcFile ( prefs , 1 ) ; } /* behave like unlzma, also supports multiple formats */
if ( exeNameMatch ( programName , ZSTD_XZ ) ) { suffix = XZ_EXTENSION ; FIO_setCompressionType ( prefs , FIO_xzCompression ) ; FIO_setRemoveSrcFile ( prefs , 1 ) ; } /* behave like xz */
if ( exeNameMatch ( programName , ZSTD_UNXZ ) ) { operation = zom_decompress ; FIO_setCompressionType ( prefs , FIO_xzCompression ) ; FIO_setRemoveSrcFile ( prefs , 1 ) ; } /* behave like unxz, also supports multiple formats */
if ( exeNameMatch ( programName , ZSTD_LZ4 ) ) { suffix = LZ4_EXTENSION ; FIO_setCompressionType ( prefs , FIO_lz4Compression ) ; } /* behave like lz4 */
if ( exeNameMatch ( programName , ZSTD_UNLZ4 ) ) { operation = zom_decompress ; FIO_setCompressionType ( prefs , FIO_lz4Compression ) ; } /* behave like unlz4, also supports multiple formats */
2016-12-13 03:18:07 -08:00
memset ( & compressionParams , 0 , sizeof ( compressionParams ) ) ;
2016-05-28 20:16:05 -07:00
2018-09-06 18:46:52 -07:00
/* init crash handler */
2018-09-11 11:56:50 -07:00
FIO_addAbortHandler ( ) ;
2018-09-06 18:46:52 -07:00
2016-05-28 20:16:05 -07:00
/* command switches */
2016-10-14 14:07:11 -07:00
for ( argNb = 1 ; argNb < argCount ; argNb + + ) {
2016-05-28 20:16:05 -07:00
const char * argument = argv [ argNb ] ;
if ( ! argument ) continue ; /* Protection if argument empty */
2016-12-02 15:18:57 -08:00
if ( nextArgumentsAreFiles = = 0 ) {
/* "-" means stdin/stdout */
2016-07-04 09:16:16 -07:00
if ( ! strcmp ( argument , " - " ) ) {
if ( ! filenameIdx ) {
filenameIdx = 1 , filenameTable [ 0 ] = stdinmark ;
outFileName = stdoutmark ;
2017-03-23 11:13:52 -07:00
g_displayLevel - = ( g_displayLevel = = 2 ) ;
2016-07-04 09:16:16 -07:00
continue ;
} }
2016-05-28 20:16:05 -07:00
2016-07-04 09:16:16 -07:00
/* Decode commands (note : aggregated commands are allowed) */
if ( argument [ 0 ] = = ' - ' ) {
2016-05-28 20:16:05 -07:00
2016-12-02 15:18:57 -08:00
if ( argument [ 1 ] = = ' - ' ) {
/* long commands (--long-word) */
if ( ! strcmp ( argument , " -- " ) ) { nextArgumentsAreFiles = 1 ; continue ; } /* only file names allowed from now on */
2017-06-15 15:07:54 -07:00
if ( ! strcmp ( argument , " --list " ) ) { operation = zom_list ; continue ; }
2016-12-02 15:18:57 -08:00
if ( ! strcmp ( argument , " --compress " ) ) { operation = zom_compress ; continue ; }
if ( ! strcmp ( argument , " --decompress " ) ) { operation = zom_decompress ; continue ; }
if ( ! strcmp ( argument , " --uncompress " ) ) { operation = zom_decompress ; continue ; }
2019-01-22 17:31:13 -08:00
if ( ! strcmp ( argument , " --force " ) ) { FIO_overwriteMode ( prefs ) ; forceStdout = 1 ; followLinks = 1 ; continue ; }
2017-03-23 11:13:52 -07:00
if ( ! strcmp ( argument , " --version " ) ) { g_displayOut = stdout ; DISPLAY ( WELCOME_MESSAGE ) ; CLEAN_RETURN ( 0 ) ; }
if ( ! strcmp ( argument , " --help " ) ) { g_displayOut = stdout ; CLEAN_RETURN ( usage_advanced ( programName ) ) ; }
if ( ! strcmp ( argument , " --verbose " ) ) { g_displayLevel + + ; continue ; }
if ( ! strcmp ( argument , " --quiet " ) ) { g_displayLevel - - ; continue ; }
if ( ! strcmp ( argument , " --stdout " ) ) { forceStdout = 1 ; outFileName = stdoutmark ; g_displayLevel - = ( g_displayLevel = = 2 ) ; continue ; }
2016-12-02 15:18:57 -08:00
if ( ! strcmp ( argument , " --ultra " ) ) { ultra = 1 ; continue ; }
2019-01-22 17:31:13 -08:00
if ( ! strcmp ( argument , " --check " ) ) { FIO_setChecksumFlag ( prefs , 2 ) ; continue ; }
if ( ! strcmp ( argument , " --no-check " ) ) { FIO_setChecksumFlag ( prefs , 0 ) ; continue ; }
if ( ! strcmp ( argument , " --sparse " ) ) { FIO_setSparseWrite ( prefs , 2 ) ; continue ; }
if ( ! strcmp ( argument , " --no-sparse " ) ) { FIO_setSparseWrite ( prefs , 0 ) ; continue ; }
2016-12-02 15:18:57 -08:00
if ( ! strcmp ( argument , " --test " ) ) { operation = zom_test ; continue ; }
2018-07-09 18:24:07 -07:00
if ( ! strcmp ( argument , " --train " ) ) { operation = zom_train ; if ( outFileName = = NULL ) outFileName = g_defaultDictName ; continue ; }
2017-03-24 16:04:29 -07:00
if ( ! strcmp ( argument , " --maxdict " ) ) { nextArgumentIsMaxDict = 1 ; lastCommand = 1 ; continue ; } /* kept available for compatibility with old syntax ; will be removed one day */
if ( ! strcmp ( argument , " --dictID " ) ) { nextArgumentIsDictID = 1 ; lastCommand = 1 ; continue ; } /* kept available for compatibility with old syntax ; will be removed one day */
2019-01-22 17:31:13 -08:00
if ( ! strcmp ( argument , " --no-dictID " ) ) { FIO_setDictIDFlag ( prefs , 0 ) ; continue ; }
if ( ! strcmp ( argument , " --keep " ) ) { FIO_setRemoveSrcFile ( prefs , 0 ) ; continue ; }
if ( ! strcmp ( argument , " --rm " ) ) { FIO_setRemoveSrcFile ( prefs , 1 ) ; continue ; }
2017-02-07 11:12:59 -08:00
if ( ! strcmp ( argument , " --priority=rt " ) ) { setRealTimePrio = 1 ; continue ; }
2018-08-11 20:48:06 -07:00
if ( ! strcmp ( argument , " --adapt " ) ) { adapt = 1 ; continue ; }
2018-09-24 18:16:08 -07:00
if ( longCommandWArg ( & argument , " --adapt= " ) ) { adapt = 1 ; if ( ! parseAdaptParameters ( argument , & adaptMin , & adaptMax ) ) CLEAN_RETURN ( badusage ( programName ) ) ; continue ; }
2018-02-13 14:56:35 -08:00
if ( ! strcmp ( argument , " --single-thread " ) ) { nbWorkers = 0 ; singleThread = 1 ; continue ; }
2019-01-22 17:31:13 -08:00
if ( ! strcmp ( argument , " --format=zstd " ) ) { suffix = ZSTD_EXTENSION ; FIO_setCompressionType ( prefs , FIO_zstdCompression ) ; continue ; }
2017-03-01 16:49:20 -08:00
# ifdef ZSTD_GZCOMPRESS
2019-01-22 17:31:13 -08:00
if ( ! strcmp ( argument , " --format=gzip " ) ) { suffix = GZ_EXTENSION ; FIO_setCompressionType ( prefs , FIO_gzipCompression ) ; continue ; }
2017-03-01 16:49:20 -08:00
# endif
2017-03-13 18:11:07 -07:00
# ifdef ZSTD_LZMACOMPRESS
2019-01-22 17:31:13 -08:00
if ( ! strcmp ( argument , " --format=lzma " ) ) { suffix = LZMA_EXTENSION ; FIO_setCompressionType ( prefs , FIO_lzmaCompression ) ; continue ; }
if ( ! strcmp ( argument , " --format=xz " ) ) { suffix = XZ_EXTENSION ; FIO_setCompressionType ( prefs , FIO_xzCompression ) ; continue ; }
2017-03-13 18:11:07 -07:00
# endif
2017-04-24 16:48:25 -07:00
# ifdef ZSTD_LZ4COMPRESS
2019-01-22 17:31:13 -08:00
if ( ! strcmp ( argument , " --format=lz4 " ) ) { suffix = LZ4_EXTENSION ; FIO_setCompressionType ( prefs , FIO_lz4Compression ) ; continue ; }
2017-04-24 16:48:25 -07:00
# endif
2018-11-12 19:59:42 -08:00
if ( ! strcmp ( argument , " --rsyncable " ) ) { rsyncable = 1 ; continue ; }
2019-02-15 15:24:55 -08:00
if ( ! strcmp ( argument , " --compress-literals " ) ) { literalCompressionMode = ZSTD_lcm_huffman ; continue ; }
if ( ! strcmp ( argument , " --no-compress-literals " ) ) { literalCompressionMode = ZSTD_lcm_uncompressed ; continue ; }
2018-12-13 17:17:32 -08:00
if ( ! strcmp ( argument , " --no-progress " ) ) { FIO_setNoProgress ( 1 ) ; continue ; }
2016-12-02 15:18:57 -08:00
/* long commands with arguments */
2017-03-01 16:49:20 -08:00
# ifndef ZSTD_NODICT
2017-05-01 23:40:20 -07:00
if ( longCommandWArg ( & argument , " --train-cover " ) ) {
operation = zom_train ;
2018-07-09 18:24:07 -07:00
if ( outFileName = = NULL )
outFileName = g_defaultDictName ;
2018-08-23 12:06:20 -07:00
dict = cover ;
2016-12-31 21:08:24 -08:00
/* 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 ;
}
2018-08-23 12:06:20 -07:00
if ( longCommandWArg ( & argument , " --train-fastcover " ) ) {
operation = zom_train ;
if ( outFileName = = NULL )
outFileName = g_defaultDictName ;
dict = fastCover ;
/* Allow optional arguments following an = */
if ( * argument = = 0 ) { memset ( & fastCoverParams , 0 , sizeof ( fastCoverParams ) ) ; }
else if ( * argument + + ! = ' = ' ) { CLEAN_RETURN ( badusage ( programName ) ) ; }
else if ( ! parseFastCoverParameters ( argument , & fastCoverParams ) ) { CLEAN_RETURN ( badusage ( programName ) ) ; }
continue ;
}
2017-05-01 23:40:20 -07:00
if ( longCommandWArg ( & argument , " --train-legacy " ) ) {
operation = zom_train ;
2018-07-09 18:24:07 -07:00
if ( outFileName = = NULL )
outFileName = g_defaultDictName ;
2018-08-23 12:06:20 -07:00
dict = legacy ;
2017-05-01 23:40:20 -07:00
/* Allow optional arguments following an = */
if ( * argument = = 0 ) { continue ; }
else if ( * argument + + ! = ' = ' ) { CLEAN_RETURN ( badusage ( programName ) ) ; }
else if ( ! parseLegacyParameters ( argument , & dictSelect ) ) { CLEAN_RETURN ( badusage ( programName ) ) ; }
continue ;
}
2016-12-31 21:08:24 -08:00
# endif
2018-02-01 19:29:30 -08:00
if ( longCommandWArg ( & argument , " --threads= " ) ) { nbWorkers = readU32FromChar ( & argument ) ; continue ; }
2016-12-02 15:18:57 -08: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 11:17:26 -08:00
if ( longCommandWArg ( & argument , " --block-size= " ) ) { blockSize = readU32FromChar ( & argument ) ; continue ; }
2017-03-24 16:04:29 -07:00
if ( longCommandWArg ( & argument , " --maxdict= " ) ) { maxDictSize = readU32FromChar ( & argument ) ; continue ; }
if ( longCommandWArg ( & argument , " --dictID= " ) ) { dictID = readU32FromChar ( & argument ) ; continue ; }
2016-12-13 03:18:07 -08:00
if ( longCommandWArg ( & argument , " --zstd= " ) ) { if ( ! parseCompressionParameters ( argument , & compressionParams ) ) CLEAN_RETURN ( badusage ( programName ) ) ; continue ; }
2019-08-15 23:57:55 -07:00
if ( longCommandWArg ( & argument , " --stream-size= " ) ) { streamSrcSize = readU32FromChar ( & argument ) ; continue ; }
2019-06-24 13:40:52 -07:00
if ( longCommandWArg ( & argument , " --target-compressed-block-size= " ) ) { targetCBlockSize = readU32FromChar ( & argument ) ; continue ; }
2019-08-19 08:52:08 -07:00
if ( longCommandWArg ( & argument , " --size-hint= " ) ) { srcSizeHint = readU32FromChar ( & argument ) ; continue ; }
2017-09-22 14:04:39 -07:00
if ( longCommandWArg ( & argument , " --long " ) ) {
unsigned ldmWindowLog = 0 ;
ldmFlag = 1 ;
/* Parse optional window log */
if ( * argument = = ' = ' ) {
+ + argument ;
ldmWindowLog = readU32FromChar ( & argument ) ;
} else if ( * argument ! = 0 ) {
/* Invalid character following --long */
CLEAN_RETURN ( badusage ( programName ) ) ;
}
/* Only set windowLog if not already set by --zstd */
if ( compressionParams . windowLog = = 0 )
compressionParams . windowLog = ldmWindowLog ;
continue ;
}
2018-09-22 17:21:39 -07:00
# ifndef ZSTD_NOCOMPRESS /* linking ZSTD_minCLevel() requires compression support */
2018-03-11 19:56:48 -07:00
if ( longCommandWArg ( & argument , " --fast " ) ) {
2018-06-27 16:27:45 -07:00
/* Parse optional acceleration factor */
2018-03-11 19:56:48 -07:00
if ( * argument = = ' = ' ) {
2018-09-22 16:10:10 -07:00
U32 const maxFast = ( U32 ) - ZSTD_minCLevel ( ) ;
2018-03-11 19:56:48 -07:00
U32 fastLevel ;
+ + argument ;
fastLevel = readU32FromChar ( & argument ) ;
2018-09-22 16:10:10 -07:00
if ( fastLevel > maxFast ) fastLevel = maxFast ;
2018-04-09 12:09:28 -07:00
if ( fastLevel ) {
dictCLevel = cLevel = - ( int ) fastLevel ;
2018-06-27 14:27:27 -07:00
} else {
CLEAN_RETURN ( badusage ( programName ) ) ;
2018-04-09 12:09:28 -07:00
}
2018-03-11 19:56:48 -07:00
} else if ( * argument ! = 0 ) {
/* Invalid character following --fast */
CLEAN_RETURN ( badusage ( programName ) ) ;
} else {
cLevel = - 1 ; /* default for --fast */
}
continue ;
}
2018-09-22 17:21:39 -07:00
# endif
2016-12-02 15:18:57 -08:00
/* fall-through, will trigger bad_usage() later on */
}
argument + + ;
2016-07-04 09:16:16 -07:00
while ( argument [ 0 ] ! = 0 ) {
2016-09-21 05:20:56 -07:00
if ( lastCommand ) {
DISPLAY ( " error : command must be followed by argument \n " ) ;
2017-02-21 09:17:24 -08:00
CLEAN_RETURN ( 1 ) ;
2016-09-21 05:20:56 -07:00
}
2016-09-01 15:05:57 -07:00
# ifndef ZSTD_NOCOMPRESS
2016-07-04 09:16:16 -07:00
/* compression Level */
if ( ( * argument > = ' 0 ' ) & & ( * argument < = ' 9 ' ) ) {
2016-08-12 09:04:15 -07:00
dictCLevel = cLevel = readU32FromChar ( & argument ) ;
2016-07-04 09:16:16 -07:00
continue ;
}
2016-09-01 15:05:57 -07:00
# endif
2016-05-28 20:16:05 -07:00
2016-07-04 09:16:16 -07:00
switch ( argument [ 0 ] )
{
/* Display help */
2017-08-19 13:33:50 -07:00
case ' V ' : g_displayOut = stdout ; printVersion ( ) ; CLEAN_RETURN ( 0 ) ; /* Version Only */
2016-07-04 09:16:16 -07:00
case ' H ' :
2017-03-23 11:13:52 -07:00
case ' h ' : g_displayOut = stdout ; CLEAN_RETURN ( usage_advanced ( programName ) ) ;
2016-05-28 20:16:05 -07:00
2016-10-28 13:58:31 -07:00
/* Compress */
case ' z ' : operation = zom_compress ; argument + + ; break ;
2016-07-04 09:16:16 -07:00
/* Decoding */
2016-12-06 17:56:20 -08:00
case ' d ' :
# ifndef ZSTD_NOBENCH
2018-08-03 07:54:29 -07:00
benchParams . mode = BMK_decodeOnly ;
2018-03-05 13:50:07 -08:00
if ( operation = = zom_bench ) { argument + + ; break ; } /* benchmark decode (hidden option) */
2016-12-06 17:56:20 -08:00
# endif
2016-12-06 16:49:23 -08:00
operation = zom_decompress ; argument + + ; break ;
2016-05-28 20:16:05 -07:00
2016-07-04 09:16:16 -07:00
/* Force stdout, even if stdout==console */
2016-08-12 09:04:15 -07:00
case ' c ' : forceStdout = 1 ; outFileName = stdoutmark ; argument + + ; break ;
2016-05-28 20:16:05 -07:00
2016-07-04 09:16:16 -07:00
/* Use file content as dictionary */
2016-09-21 05:20:56 -07:00
case ' D ' : nextEntryIsDictionary = 1 ; lastCommand = 1 ; argument + + ; break ;
2016-05-28 20:16:05 -07:00
2016-07-04 09:16:16 -07:00
/* Overwrite */
2019-01-22 17:31:13 -08:00
case ' f ' : FIO_overwriteMode ( prefs ) ; forceStdout = 1 ; followLinks = 1 ; argument + + ; break ;
2016-05-28 20:16:05 -07:00
2016-07-04 09:16:16 -07:00
/* Verbose mode */
2017-03-23 11:13:52 -07:00
case ' v ' : g_displayLevel + + ; argument + + ; break ;
2016-05-28 20:16:05 -07:00
2016-07-04 09:16:16 -07:00
/* Quiet mode */
2017-03-23 11:13:52 -07:00
case ' q ' : g_displayLevel - - ; argument + + ; break ;
2016-05-28 20:16:05 -07:00
2017-05-02 15:40:42 -07:00
/* keep source file (default) */
2019-01-22 17:31:13 -08:00
case ' k ' : FIO_setRemoveSrcFile ( prefs , 0 ) ; argument + + ; break ;
2016-05-28 20:16:05 -07:00
2016-07-04 09:16:16 -07:00
/* Checksum */
2019-01-22 17:31:13 -08:00
case ' C ' : FIO_setChecksumFlag ( prefs , 2 ) ; argument + + ; break ;
2016-06-02 08:05:50 -07:00
2016-07-04 09:16:16 -07:00
/* test compressed file */
2016-10-28 13:58:31 -07:00
case ' t ' : operation = zom_test ; argument + + ; break ;
2016-05-28 20:16:05 -07:00
2016-07-13 05:15:08 -07:00
/* destination file name */
2016-09-21 05:20:56 -07:00
case ' o ' : nextArgumentIsOutFileName = 1 ; lastCommand = 1 ; argument + + ; break ;
2016-05-28 20:16:05 -07:00
2019-09-05 16:03:35 -07:00
/* destination directory name */
case ' O ' : nextArgumentIsOutDirName = 1 ; lastCommand = 1 ; argument + + ; break ;
2016-10-14 13:13:13 -07:00
/* limit decompression memory */
case ' M ' :
argument + + ;
memLimit = readU32FromChar ( & argument ) ;
break ;
2017-06-05 14:45:31 -07:00
case ' l ' : operation = zom_list ; argument + + ; break ;
2016-09-13 08:50:08 -07:00
# ifdef UTIL_HAS_CREATEFILELIST
2016-07-04 09:16:16 -07:00
/* recursive */
case ' r ' : recursive = 1 ; argument + + ; break ;
2016-09-13 08:50:08 -07:00
# endif
2016-05-28 20:16:05 -07:00
2016-09-01 15:05:57 -07:00
# ifndef ZSTD_NOBENCH
2016-07-04 09:16:16 -07:00
/* Benchmark */
2017-01-19 16:59:56 -08:00
case ' b ' :
operation = zom_bench ;
argument + + ;
break ;
2016-05-28 20:16:05 -07:00
2016-07-04 09:16:16 -07:00
/* range bench (benchmark only) */
case ' e ' :
2017-01-19 16:59:56 -08:00
/* compression Level */
argument + + ;
cLevelLast = readU32FromChar ( & argument ) ;
break ;
2016-07-04 09:16:16 -07:00
/* Modify Nb Iterations (benchmark only) */
case ' i ' :
2016-05-28 20:16:05 -07:00
argument + + ;
2017-01-19 16:59:56 -08:00
bench_nbSeconds = readU32FromChar ( & argument ) ;
2016-05-28 20:16:05 -07:00
break ;
2016-07-04 09:16:16 -07:00
/* cut input into blocks (benchmark only) */
case ' B ' :
argument + + ;
2017-01-19 16:59:56 -08:00
blockSize = readU32FromChar ( & argument ) ;
2016-07-04 09:16:16 -07:00
break ;
2017-01-01 17:05:45 -08:00
2017-11-17 00:22:55 -08:00
/* benchmark files separately (hidden option) */
case ' S ' :
argument + + ;
separateFiles = 1 ;
break ;
2017-01-19 16:59:56 -08:00
# endif /* ZSTD_NOBENCH */
2017-01-01 17:05:45 -08:00
/* nb of threads (hidden option) */
case ' T ' :
argument + + ;
2018-02-01 19:29:30 -08:00
nbWorkers = readU32FromChar ( & argument ) ;
2017-01-01 17:05:45 -08:00
break ;
2016-05-28 20:16:05 -07:00
2016-07-04 09:16:16 -07:00
/* Dictionary Selection level */
case ' s ' :
argument + + ;
dictSelect = readU32FromChar ( & argument ) ;
break ;
2016-05-28 20:16:05 -07:00
2016-07-04 09:16:16 -07:00
/* Pause at the end (-p) or set an additional param (-p#) (hidden option) */
case ' p ' : argument + + ;
2016-09-01 15:05:57 -07:00
# ifndef ZSTD_NOBENCH
2016-07-04 09:16:16 -07:00
if ( ( * argument > = ' 0 ' ) & & ( * argument < = ' 9 ' ) ) {
2018-08-03 07:54:29 -07:00
benchParams . additionalParam = ( int ) readU32FromChar ( & argument ) ;
2016-07-04 09:16:16 -07:00
} else
2016-09-01 15:05:57 -07:00
# endif
2016-07-04 09:16:16 -07:00
main_pause = 1 ;
break ;
2018-06-19 10:58:22 -07:00
/* Select compressibility of synthetic sample */
2018-07-09 18:24:07 -07:00
case ' P ' :
2018-06-22 17:25:16 -07:00
{ argument + + ;
compressibility = ( double ) readU32FromChar ( & argument ) / 100 ;
2018-06-19 10:58:22 -07:00
}
break ;
2016-07-04 09:16:16 -07:00
/* unknown command */
default : CLEAN_RETURN ( badusage ( programName ) ) ;
}
2016-05-28 20:16:05 -07:00
}
2016-07-04 09:16:16 -07:00
continue ;
} /* if (argument[0]=='-') */
2017-03-24 16:04:29 -07:00
if ( nextArgumentIsMaxDict ) { /* kept available for compatibility with old syntax ; will be removed one day */
2016-07-04 09:16:16 -07:00
nextArgumentIsMaxDict = 0 ;
2016-09-21 05:20:56 -07:00
lastCommand = 0 ;
2016-07-04 09:16:16 -07:00
maxDictSize = readU32FromChar ( & argument ) ;
continue ;
2016-05-28 20:16:05 -07:00
}
2016-07-04 09:16:16 -07:00
2017-03-24 16:04:29 -07:00
if ( nextArgumentIsDictID ) { /* kept available for compatibility with old syntax ; will be removed one day */
2016-07-04 09:16:16 -07:00
nextArgumentIsDictID = 0 ;
2016-09-21 05:20:56 -07:00
lastCommand = 0 ;
2016-07-04 09:16:16 -07:00
dictID = readU32FromChar ( & argument ) ;
continue ;
}
} /* if (nextArgumentIsAFile==0) */
2016-05-28 20:16:05 -07:00
if ( nextEntryIsDictionary ) {
nextEntryIsDictionary = 0 ;
2016-09-21 05:20:56 -07:00
lastCommand = 0 ;
2016-05-28 20:16:05 -07:00
dictFileName = argument ;
continue ;
}
if ( nextArgumentIsOutFileName ) {
nextArgumentIsOutFileName = 0 ;
2016-09-21 05:20:56 -07:00
lastCommand = 0 ;
2016-05-28 20:16:05 -07:00
outFileName = argument ;
if ( ! strcmp ( outFileName , " - " ) ) outFileName = stdoutmark ;
continue ;
}
2019-09-05 16:03:35 -07:00
if ( nextArgumentIsOutDirName ) {
nextArgumentIsOutDirName = 0 ;
lastCommand = 0 ;
outDirName = argument ;
continue ;
}
2016-05-28 20:16:05 -07:00
/* add filename to list */
filenameTable [ filenameIdx + + ] = argument ;
}
2017-08-18 18:30:41 -07:00
if ( lastCommand ) { /* forgotten argument */
DISPLAY ( " error : command must be followed by argument \n " ) ;
CLEAN_RETURN ( 1 ) ;
}
2016-09-21 07:05:03 -07:00
2016-05-28 20:16:05 -07:00
/* Welcome message (if verbose) */
DISPLAYLEVEL ( 3 , WELCOME_MESSAGE ) ;
2018-02-13 14:56:35 -08:00
# ifdef ZSTD_MULTITHREAD
if ( ( nbWorkers = = 0 ) & & ( ! singleThread ) ) {
2018-02-01 19:29:30 -08:00
/* automatically set # workers based on # of reported cpus */
nbWorkers = UTIL_countPhysicalCores ( ) ;
DISPLAYLEVEL ( 3 , " Note: %d physical core(s) detected \n " , nbWorkers ) ;
2017-04-13 12:28:28 -07:00
}
2018-06-26 01:22:45 -07:00
# else
2018-06-29 17:10:56 -07:00
( void ) singleThread ; ( void ) nbWorkers ;
2018-02-13 14:56:35 -08:00
# endif
2017-03-23 11:52:09 -07:00
2018-06-26 01:22:45 -07:00
# ifdef UTIL_HAS_CREATEFILELIST
2017-03-23 12:09:35 -07:00
g_utilDisplayLevel = g_displayLevel ;
2017-03-23 11:52:09 -07:00
if ( ! followLinks ) {
unsigned u ;
for ( u = 0 , fileNamesNb = 0 ; u < filenameIdx ; u + + ) {
if ( UTIL_isLink ( filenameTable [ u ] ) ) {
DISPLAYLEVEL ( 2 , " Warning : %s is a symbolic link, ignoring \n " , filenameTable [ u ] ) ;
} else {
filenameTable [ fileNamesNb + + ] = filenameTable [ u ] ;
}
}
2019-02-11 15:07:32 -08:00
if ( fileNamesNb = = 0 & & filenameIdx > 0 )
CLEAN_RETURN ( 1 ) ;
2017-03-23 11:52:09 -07:00
filenameIdx = fileNamesNb ;
}
2016-09-21 03:24:43 -07:00
if ( recursive ) { /* at this stage, filenameTable is a list of paths, which can contain both files and directories */
2017-03-23 11:52:09 -07:00
extendedFileList = UTIL_createFileList ( filenameTable , filenameIdx , & fileNamesBuf , & fileNamesNb , followLinks ) ;
2016-09-21 03:24:43 -07:00
if ( extendedFileList ) {
2016-08-01 05:26:49 -07:00
unsigned u ;
2016-09-21 03:24:43 -07:00
for ( u = 0 ; u < fileNamesNb ; u + + ) DISPLAYLEVEL ( 4 , " %u %s \n " , u , extendedFileList [ u ] ) ;
2016-05-28 20:16:05 -07:00
free ( ( void * ) filenameTable ) ;
2016-09-21 03:24:43 -07:00
filenameTable = extendedFileList ;
2016-05-28 20:16:05 -07:00
filenameIdx = fileNamesNb ;
}
}
2018-06-26 01:22:45 -07:00
# else
( void ) followLinks ;
2016-05-28 20:16:05 -07:00
# endif
2017-08-18 18:30:41 -07:00
2017-06-15 17:46:49 -07:00
if ( operation = = zom_list ) {
2017-08-18 18:30:41 -07:00
# ifndef ZSTD_NODECOMPRESS
2017-06-20 12:43:10 -07:00
int const ret = FIO_listMultipleFiles ( filenameIdx , filenameTable , g_displayLevel ) ;
CLEAN_RETURN ( ret ) ;
2017-08-18 18:30:41 -07:00
# else
DISPLAY ( " file information is not supported \n " ) ;
CLEAN_RETURN ( 1 ) ;
# endif
2017-06-05 14:45:31 -07:00
}
2017-08-18 18:30:41 -07:00
2016-05-28 20:16:05 -07:00
/* Check if benchmark is selected */
2016-10-28 13:58:31 -07:00
if ( operation = = zom_bench ) {
2016-05-28 20:16:05 -07:00
# ifndef ZSTD_NOBENCH
2018-08-03 07:54:29 -07:00
benchParams . blockSize = blockSize ;
benchParams . nbWorkers = nbWorkers ;
benchParams . realTime = setRealTimePrio ;
benchParams . nbSeconds = bench_nbSeconds ;
benchParams . ldmFlag = ldmFlag ;
benchParams . ldmMinMatch = g_ldmMinMatch ;
benchParams . ldmHashLog = g_ldmHashLog ;
2017-09-02 21:10:36 -07:00
if ( g_ldmBucketSizeLog ! = LDM_PARAM_DEFAULT ) {
2018-08-03 07:54:29 -07:00
benchParams . ldmBucketSizeLog = g_ldmBucketSizeLog ;
2017-09-02 21:10:36 -07:00
}
2018-11-21 14:36:57 -08:00
if ( g_ldmHashRateLog ! = LDM_PARAM_DEFAULT ) {
benchParams . ldmHashRateLog = g_ldmHashRateLog ;
2017-09-02 21:10:36 -07:00
}
2019-02-15 15:24:55 -08:00
benchParams . literalCompressionMode = literalCompressionMode ;
2018-06-15 13:21:08 -07:00
2018-06-18 15:06:31 -07:00
if ( cLevel > ZSTD_maxCLevel ( ) ) cLevel = ZSTD_maxCLevel ( ) ;
if ( cLevelLast > ZSTD_maxCLevel ( ) ) cLevelLast = ZSTD_maxCLevel ( ) ;
if ( cLevelLast < cLevel ) cLevelLast = cLevel ;
2018-07-09 18:24:07 -07:00
if ( cLevelLast > cLevel )
2018-08-28 11:21:09 -07:00
DISPLAYLEVEL ( 3 , " Benchmarking levels from %d to %d \n " , cLevel , cLevelLast ) ;
2018-06-19 10:58:22 -07:00
if ( filenameIdx ) {
if ( separateFiles ) {
unsigned i ;
for ( i = 0 ; i < filenameIdx ; i + + ) {
int c ;
2018-08-28 11:21:09 -07:00
DISPLAYLEVEL ( 3 , " Benchmarking %s \n " , filenameTable [ i ] ) ;
2018-06-19 10:58:22 -07:00
for ( c = cLevel ; c < = cLevelLast ; c + + ) {
2018-08-03 07:54:29 -07:00
BMK_benchFilesAdvanced ( & filenameTable [ i ] , 1 , dictFileName , c , & compressionParams , g_displayLevel , & benchParams ) ;
2018-06-19 10:58:22 -07:00
}
2018-06-15 13:21:08 -07:00
}
2018-06-19 10:58:22 -07:00
} else {
for ( ; cLevel < = cLevelLast ; cLevel + + ) {
2018-08-03 07:54:29 -07:00
BMK_benchFilesAdvanced ( filenameTable , filenameIdx , dictFileName , cLevel , & compressionParams , g_displayLevel , & benchParams ) ;
2018-07-09 18:24:07 -07:00
}
2018-06-15 13:21:08 -07:00
}
2018-06-18 15:06:31 -07:00
} else {
for ( ; cLevel < = cLevelLast ; cLevel + + ) {
2018-08-03 07:54:29 -07:00
BMK_syntheticTest ( cLevel , compressibility , & compressionParams , g_displayLevel , & benchParams ) ;
2018-06-19 10:58:22 -07:00
}
2018-06-15 13:21:08 -07:00
}
2017-12-01 17:42:46 -08:00
# else
2018-08-03 08:30:01 -07:00
( void ) bench_nbSeconds ; ( void ) blockSize ; ( void ) setRealTimePrio ; ( void ) separateFiles ; ( void ) compressibility ;
2016-05-28 20:16:05 -07:00
# endif
goto _end ;
}
/* Check if dictionary builder is selected */
2016-10-28 13:58:31 -07:00
if ( operation = = zom_train ) {
2016-05-28 20:16:05 -07:00
# ifndef ZSTD_NODICT
2017-06-26 21:07:14 -07:00
ZDICT_params_t zParams ;
zParams . compressionLevel = dictCLevel ;
zParams . notificationLevel = g_displayLevel ;
zParams . dictID = dictID ;
2018-08-23 12:06:20 -07:00
if ( dict = = cover ) {
2017-05-01 23:40:20 -07:00
int const optimize = ! coverParams . k | | ! coverParams . d ;
2018-02-01 19:29:30 -08:00
coverParams . nbThreads = nbWorkers ;
2017-06-26 21:07:14 -07:00
coverParams . zParams = zParams ;
2018-08-23 12:06:20 -07:00
operationResult = DiB_trainFromFiles ( outFileName , maxDictSize , filenameTable , filenameIdx , blockSize , NULL , & coverParams , NULL , optimize ) ;
} else if ( dict = = fastCover ) {
int const optimize = ! fastCoverParams . k | | ! fastCoverParams . d ;
fastCoverParams . nbThreads = nbWorkers ;
fastCoverParams . zParams = zParams ;
operationResult = DiB_trainFromFiles ( outFileName , maxDictSize , filenameTable , filenameIdx , blockSize , NULL , NULL , & fastCoverParams , optimize ) ;
2016-12-31 21:08:24 -08:00
} else {
2017-06-26 21:07:14 -07:00
ZDICT_legacy_params_t dictParams ;
2016-12-31 21:08:24 -08:00
memset ( & dictParams , 0 , sizeof ( dictParams ) ) ;
dictParams . selectivityLevel = dictSelect ;
2017-06-26 21:07:14 -07:00
dictParams . zParams = zParams ;
2018-08-23 12:06:20 -07:00
operationResult = DiB_trainFromFiles ( outFileName , maxDictSize , filenameTable , filenameIdx , blockSize , & dictParams , NULL , NULL , 0 ) ;
2016-12-31 21:08:24 -08:00
}
2018-09-24 00:52:19 -07:00
# else
( void ) dictCLevel ; ( void ) dictSelect ; ( void ) dictID ; ( void ) maxDictSize ; /* not used when ZSTD_NODICT set */
DISPLAYLEVEL ( 1 , " training mode not available \n " ) ;
operationResult = 1 ;
2016-05-28 20:16:05 -07:00
# endif
goto _end ;
}
2017-07-18 14:45:49 -07:00
# ifndef ZSTD_NODECOMPRESS
2019-01-22 17:31:13 -08:00
if ( operation = = zom_test ) { outFileName = nulmark ; FIO_setRemoveSrcFile ( prefs , 0 ) ; } /* test mode */
2017-07-18 14:45:49 -07:00
# endif
2016-05-28 20:16:05 -07:00
/* No input filename ==> use stdin and stdout */
2016-08-25 16:43:47 -07:00
filenameIdx + = ! filenameIdx ; /* filenameTable[0] is stdin by default */
2018-03-11 19:56:48 -07:00
if ( ! strcmp ( filenameTable [ 0 ] , stdinmark ) & & ! outFileName )
outFileName = stdoutmark ; /* when input is stdin, default output is stdout */
2016-05-28 20:16:05 -07:00
/* Check if input/output defined as console; trigger an error in this case */
2018-03-11 19:56:48 -07:00
if ( ! strcmp ( filenameTable [ 0 ] , stdinmark ) & & IS_CONSOLE ( stdin ) )
CLEAN_RETURN ( badusage ( programName ) ) ;
if ( outFileName & & ! strcmp ( outFileName , stdoutmark )
& & IS_CONSOLE ( stdout )
& & ! strcmp ( filenameTable [ 0 ] , stdinmark )
& & ! forceStdout
& & operation ! = zom_decompress )
2016-05-28 20:16:05 -07:00
CLEAN_RETURN ( badusage ( programName ) ) ;
2016-10-05 02:56:22 -07:00
# ifndef ZSTD_NOCOMPRESS
2016-08-12 09:04:15 -07: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 02:56:22 -07:00
# endif
2016-08-12 09:04:15 -07:00
2017-01-19 13:46:30 -08:00
/* No status message in pipe mode (stdin - stdout) or multi-files mode */
2017-03-23 11:13:52 -07:00
if ( ! strcmp ( filenameTable [ 0 ] , stdinmark ) & & outFileName & & ! strcmp ( outFileName , stdoutmark ) & & ( g_displayLevel = = 2 ) ) g_displayLevel = 1 ;
if ( ( filenameIdx > 1 ) & ( g_displayLevel = = 2 ) ) g_displayLevel = 1 ;
2016-05-28 20:16:05 -07:00
/* IO Stream/File */
2017-03-23 11:13:52 -07:00
FIO_setNotificationLevel ( g_displayLevel ) ;
2016-10-28 13:58:31 -07:00
if ( operation = = zom_compress ) {
2016-09-21 03:24:43 -07:00
# ifndef ZSTD_NOCOMPRESS
2019-01-22 17:31:13 -08:00
FIO_setNbWorkers ( prefs , nbWorkers ) ;
FIO_setBlockSize ( prefs , ( U32 ) blockSize ) ;
if ( g_overlapLog ! = OVERLAP_LOG_DEFAULT ) FIO_setOverlapLog ( prefs , g_overlapLog ) ;
FIO_setLdmFlag ( prefs , ldmFlag ) ;
FIO_setLdmHashLog ( prefs , g_ldmHashLog ) ;
FIO_setLdmMinMatch ( prefs , g_ldmMinMatch ) ;
if ( g_ldmBucketSizeLog ! = LDM_PARAM_DEFAULT ) FIO_setLdmBucketSizeLog ( prefs , g_ldmBucketSizeLog ) ;
if ( g_ldmHashRateLog ! = LDM_PARAM_DEFAULT ) FIO_setLdmHashRateLog ( prefs , g_ldmHashRateLog ) ;
FIO_setAdaptiveMode ( prefs , adapt ) ;
FIO_setAdaptMin ( prefs , adaptMin ) ;
FIO_setAdaptMax ( prefs , adaptMax ) ;
FIO_setRsyncable ( prefs , rsyncable ) ;
2019-08-15 23:57:55 -07:00
FIO_setStreamSrcSize ( prefs , streamSrcSize ) ;
2019-06-24 13:40:52 -07:00
FIO_setTargetCBlockSize ( prefs , targetCBlockSize ) ;
2019-08-19 08:52:08 -07:00
FIO_setSrcSizeHint ( prefs , srcSizeHint ) ;
2019-02-15 15:24:55 -08:00
FIO_setLiteralCompressionMode ( prefs , literalCompressionMode ) ;
2018-09-24 18:16:08 -07:00
if ( adaptMin > cLevel ) cLevel = adaptMin ;
if ( adaptMax < cLevel ) cLevel = adaptMax ;
2017-09-01 14:52:51 -07:00
2019-09-06 10:17:04 -07:00
if ( outDirName ) {
2019-09-06 11:10:53 -07:00
printf ( " ok \n " ) ;
2019-09-06 10:17:04 -07:00
dstFilenameTable = ( char * * ) malloc ( filenameIdx * sizeof ( char * ) ) ;
2019-09-06 11:10:53 -07:00
UTIL_processMultipleFilenameDestinationDir ( dstFilenameTable , filenameTable , filenameIdx , outFileName , outDirName ) ;
2019-09-06 13:20:50 -07:00
} else {
dstFilenameTable = NULL ;
2019-09-06 10:17:04 -07:00
}
2019-09-05 17:56:24 -07:00
2016-09-21 07:46:08 -07:00
if ( ( filenameIdx = = 1 ) & & outFileName )
2019-01-22 17:31:13 -08:00
operationResult = FIO_compressFilename ( prefs , outFileName , filenameTable [ 0 ] , dictFileName , cLevel , compressionParams ) ;
2016-05-28 20:16:05 -07:00
else
2019-09-05 16:03:35 -07:00
operationResult = FIO_compressMultipleFilenames ( prefs , filenameTable , outDirName , dstFilenameTable , filenameIdx , outFileName , suffix , dictFileName , cLevel , compressionParams ) ;
2016-09-21 03:24:43 -07:00
# else
2019-08-22 11:51:41 -07:00
( void ) suffix ; ( void ) adapt ; ( void ) rsyncable ; ( void ) ultra ; ( void ) cLevel ; ( void ) ldmFlag ; ( void ) literalCompressionMode ; ( void ) targetCBlockSize ; ( void ) streamSrcSize ; ( void ) srcSizeHint ; /* not used when ZSTD_NOCOMPRESS set */
2018-09-24 16:56:45 -07:00
DISPLAY ( " Compression not supported \n " ) ;
2016-05-28 20:16:05 -07:00
# endif
2016-10-28 13:58:31 -07:00
} else { /* decompression or test */
2016-05-28 20:16:05 -07:00
# ifndef ZSTD_NODECOMPRESS
2017-09-22 14:04:39 -07:00
if ( memLimit = = 0 ) {
if ( compressionParams . windowLog = = 0 )
memLimit = ( U32 ) 1 < < g_defaultMaxWindowLog ;
else {
memLimit = ( U32 ) 1 < < ( compressionParams . windowLog & 31 ) ;
}
}
2019-01-22 17:31:13 -08:00
FIO_setMemLimit ( prefs , memLimit ) ;
2019-09-05 17:56:24 -07:00
2019-09-06 10:17:04 -07:00
if ( outDirName ) {
dstFilenameTable = ( char * * ) malloc ( filenameIdx * sizeof ( char * ) ) ;
2019-09-06 11:10:53 -07:00
UTIL_processMultipleFilenameDestinationDir ( dstFilenameTable , filenameTable , filenameIdx , outFileName , outDirName ) ;
2019-09-06 13:20:50 -07:00
} else {
dstFilenameTable = NULL ;
2019-09-06 10:17:04 -07:00
}
2019-09-06 13:20:50 -07:00
2016-05-28 20:16:05 -07:00
if ( filenameIdx = = 1 & & outFileName )
2019-01-22 17:31:13 -08:00
operationResult = FIO_decompressFilename ( prefs , outFileName , filenameTable [ 0 ] , dictFileName ) ;
2016-05-28 20:16:05 -07:00
else
2019-09-05 17:56:24 -07:00
operationResult = FIO_decompressMultipleFilenames ( prefs , filenameTable , filenameIdx , outDirName , dstFilenameTable , outFileName , dictFileName ) ;
2016-05-28 20:16:05 -07:00
# else
2018-09-24 16:56:45 -07:00
DISPLAY ( " Decompression not supported \n " ) ;
2016-05-28 20:16:05 -07:00
# endif
}
_end :
2019-01-22 17:31:13 -08:00
FIO_freePreferences ( prefs ) ;
2016-05-28 20:16:05 -07:00
if ( main_pause ) waitEnter ( ) ;
# ifdef UTIL_HAS_CREATEFILELIST
2016-09-21 03:24:43 -07:00
if ( extendedFileList )
UTIL_freeFileList ( extendedFileList , fileNamesBuf ) ;
2016-05-28 20:16:05 -07:00
else
# endif
free ( ( void * ) filenameTable ) ;
return operationResult ;
}