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-29 05:16:05 +02:00
2016-07-13 14:15:08 +02:00
/*-************************************
* Tuning parameters
**************************************/
2016-07-13 15:16:00 +02:00
#ifndef ZSTDCLI_CLEVEL_DEFAULT
# define ZSTDCLI_CLEVEL_DEFAULT 3
2016-07-13 14:15:08 +02:00
#endif
2016-08-12 18:04:15 +02:00
#ifndef ZSTDCLI_CLEVEL_MAX
2017-08-19 13:33:50 -07:00
# define ZSTDCLI_CLEVEL_MAX 19 /* without using --ultra */
2016-08-12 18:04:15 +02:00
#endif
2016-07-13 14:15:08 +02:00
2017-01-25 17:01:13 -08:00
2016-05-29 05:16:05 +02:00
/*-************************************
2016-11-16 08:50:54 -08:00
* Dependencies
2016-05-29 05:16:05 +02:00
**************************************/
2016-12-21 15:08:44 +01: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 */
2016-05-29 05:16:05 +02:00
#include <string.h> /* strcmp, strlen */
2016-07-04 18:16:16 +02:00
#include <errno.h> /* errno */
2017-08-19 13:33:50 -07:00
#include "fileio.h" /* stdinmark, stdoutmark, ZSTD_EXTENSION */
2016-05-29 05:16:05 +02:00
#ifndef ZSTD_NOBENCH
2016-11-03 11:38:01 +01:00
# include "bench.h" /* BMK_benchFiles, BMK_SetNbSeconds */
2016-05-29 05:16:05 +02:00
#endif
#ifndef ZSTD_NODICT
2017-08-19 13:33:50 -07:00
# include "dibio.h" /* ZDICT_cover_params_t, DiB_trainFromFiles() */
2016-05-29 05:16:05 +02:00
#endif
2016-06-04 19:47:02 +02:00
#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_maxCLevel */
#include "zstd.h" /* ZSTD_VERSION_STRING */
2016-05-29 05:16:05 +02: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-29 05:16:05 +02:00
#define ZSTD_UNZSTD "unzstd"
2017-02-14 10:45:19 -08:00
#define ZSTD_CAT "zstdcat"
#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"
2016-05-29 05:16:05 +02: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-29 05:16:05 +02: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-29 05:16:05 +02:00
static const unsigned g_defaultSelectivityLevel = 9 ;
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 ;
2017-09-02 21:10:36 -07:00
static U32 g_ldmHashEveryLog = LDM_PARAM_DEFAULT ;
static U32 g_ldmBucketSizeLog = LDM_PARAM_DEFAULT ;
2016-05-29 05:16:05 +02: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-29 05:16:05 +02: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-29 05:16:05 +02:00
DISPLAY ( " \n " );
2017-08-18 15:15:31 -07:00
DISPLAY ( "FILE : a filename \n " );
2016-05-29 05:16:05 +02: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-29 05:16:05 +02:00
#ifndef ZSTD_NOCOMPRESS
2016-08-18 09:00:25 +02:00
DISPLAY ( " -# : # compression level (1-%d, default:%d) \n " , ZSTDCLI_CLEVEL_MAX , ZSTDCLI_CLEVEL_DEFAULT );
2016-05-29 05:16:05 +02: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 " );
2017-03-23 11:52:09 -07:00
DISPLAY ( " -f : overwrite output without prompting and (de)compress links \n " );
2016-07-02 00:37:32 +02:00
DISPLAY ( "--rm : remove source file(s) after successful de/compression \n " );
2016-07-04 00:42:58 +02: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-29 05:16:05 +02: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-29 05:16:05 +02: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-29 05:16:05 +02:00
#ifndef ZSTD_NOCOMPRESS
2016-08-12 18:04:15 +02:00
DISPLAY ( "--ultra : enable levels beyond %i, up to %i (requires more memory) \n " , ZSTDCLI_CLEVEL_MAX , ZSTD_maxCLevel ());
2017-09-06 11:03:35 -07:00
DISPLAY ( "--long : enable long distance matching (requires more memory) \n " );
2017-01-19 16:59:56 -08:00
#ifdef ZSTD_MULTITHREAD
DISPLAY ( " -T# : use # threads for compression (default:1) \n " );
2017-04-01 00:36:31 -07:00
DISPLAY ( " -B# : select size of each job (default:0==automatic) \n " );
#endif
DISPLAY ( "--no-dictID : don't write dictID into header (dictionary compression) \n " );
DISPLAY ( "--[no-]check : integrity check (default:enabled) \n " );
#endif
#ifdef UTIL_HAS_CREATEFILELIST
DISPLAY ( " -r : operate recursively on directories \n " );
2017-01-19 16:59:56 -08:00
#endif
2017-02-08 15:17:55 +01:00
#ifdef ZSTD_GZCOMPRESS
2017-02-08 18:08:09 +01:00
DISPLAY ( "--format=gzip : compress files to the .gz format \n " );
2017-02-08 15:17:55 +01: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-31 02:29:45 +02:00
#ifndef ZSTD_NODECOMPRESS
2016-06-02 17:05:50 +02:00
DISPLAY ( "--test : test compressed file integrity \n " );
2017-03-31 15:16:43 -07:00
#if ZSTD_SPARSE_DEFAULT
2016-06-09 22:59:51 +02:00
DISPLAY ( "--[no-]sparse : sparse mode (default:enabled on file, disabled on stdout) \n " );
2017-03-31 15:16:43 -07:00
#else
DISPLAY ( "--[no-]sparse : sparse mode (default:disabled) \n " );
#endif
2016-05-31 02:29:45 +02:00
#endif
2016-10-14 13:13:13 -07:00
DISPLAY ( " -M# : Set a memory usage limit for decompression \n " );
2016-09-16 18:52:52 +02:00
DISPLAY ( "-- : All arguments after \" -- \" are treated as files \n " );
2016-05-29 05:16:05 +02:00
#ifndef ZSTD_NODICT
DISPLAY ( " \n " );
2017-08-18 15:15:31 -07:00
DISPLAY ( "Dictionary builder : \n " );
2016-06-09 22:59:51 +02:00
DISPLAY ( "--train ## : create a dictionary from a training set of files \n " );
2017-05-01 23:40:20 -07:00
DISPLAY ( "--train-cover[=k=#,d=#,steps=#] : use the cover algorithm with optional args \n " );
DISPLAY ( "--train-legacy[=s=#] : use the legacy algorithm with selectivity (default: %u) \n " , g_defaultSelectivityLevel );
2016-06-09 22:59:51 +02:00
DISPLAY ( " -o file : `file` is dictionary name (default: %s) \n " , g_defaultDictName );
2017-03-24 16:04:29 -07:00
DISPLAY ( "--maxdict=# : limit dictionary to specified size (default : %u) \n " , g_defaultMaxDictSize );
DISPLAY ( "--dictID=# : force dictionary ID to specified value (default: random) \n " );
2016-05-29 05:16:05 +02:00
#endif
#ifndef ZSTD_NOBENCH
DISPLAY ( " \n " );
2017-08-18 15:15:31 -07:00
DISPLAY ( "Benchmark arguments : \n " );
2016-05-29 05:16:05 +02:00
DISPLAY ( " -b# : benchmark file(s), using # compression level (default : 1) \n " );
DISPLAY ( " -e# : test all compression levels from -bX to # (default: 1) \n " );
2017-08-18 15:15:31 -07:00
DISPLAY ( " -i# : minimum evaluation time in seconds (default : 3s) \n " );
2016-05-29 05:16:05 +02: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-29 05:16:05 +02: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-29 05:16:05 +02: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 )] == '.' );
}
2016-06-03 15:14:09 +02:00
/*! readU32FromChar() :
2016-10-14 13:13:13 -07: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 15:14:09 +02:00
Will also modify `*stringPtr`, advancing it to position where it stopped reading.
2016-10-14 13:13:13 -07:00
Note : function result can overflow if digit string > MAX_UINT */
2016-06-03 15:14:09 +02:00
static unsigned readU32FromChar ( const char ** stringPtr )
{
unsigned result = 0 ;
while (( ** stringPtr >= '0' ) && ( ** stringPtr <= '9' ))
result *= 10 , result += ** stringPtr - '0' , ( * stringPtr ) ++ ;
2016-10-17 17:48:48 -07: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 15:14:09 +02: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.
* @return 0 and doesn't modify *stringPtr otherwise.
*/
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 12:18:07 +01:00
2016-12-31 21:08:24 -08:00
#ifndef ZSTD_NODICT
/**
* 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 ; }
2016-12-31 21:08:24 -08:00
return 0 ;
}
if ( stringPtr [ 0 ] != 0 ) return 0 ;
2017-05-01 23:40:20 -07:00
DISPLAYLEVEL ( 4 , "cover: k=%u \n d=%u \n steps=%u \n " , params -> k , params -> d , params -> steps );
2016-12-31 21:08:24 -08:00
return 1 ;
}
2017-05-01 23:40:20 -07:00
/**
* parseLegacyParameters() :
* reads legacy dictioanry builter parameters from *stringPtr (e.g. "--train-legacy=selectivity=8") into *selectivity
* @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 ;
return params ;
}
2016-12-31 21:08:24 -08:00
#endif
2017-01-30 13:07:24 -08:00
2016-12-13 12:18:07 +01: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 ; }
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 ; }
2017-09-05 21:11:18 -07:00
if ( longCommandWArg ( & stringPtr , "ldmHashLog=" ) || longCommandWArg ( & stringPtr , "ldmhlog=" )) { g_ldmHashLog = readU32FromChar ( & stringPtr ); if ( stringPtr [ 0 ] == ',' ) { stringPtr ++ ; continue ; } else break ; }
if ( longCommandWArg ( & stringPtr , "ldmSearchLength=" ) || longCommandWArg ( & stringPtr , "ldmslen=" )) { g_ldmMinMatch = readU32FromChar ( & stringPtr ); if ( stringPtr [ 0 ] == ',' ) { stringPtr ++ ; continue ; } else break ; }
if ( longCommandWArg ( & stringPtr , "ldmBucketSizeLog=" ) || longCommandWArg ( & stringPtr , "ldmblog" )) { g_ldmBucketSizeLog = readU32FromChar ( & stringPtr ); if ( stringPtr [ 0 ] == ',' ) { stringPtr ++ ; continue ; } else break ; }
if ( longCommandWArg ( & stringPtr , "ldmHashEveryLog=" ) || longCommandWArg ( & stringPtr , "ldmhevery" )) { g_ldmHashEveryLog = readU32FromChar ( & stringPtr ); if ( stringPtr [ 0 ] == ',' ) { stringPtr ++ ; continue ; } else break ; }
2016-12-13 12:18:07 +01:00
return 0 ;
}
if ( stringPtr [ 0 ] != 0 ) return 0 ; /* check the end of string */
2016-12-13 13:03:41 +01: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 12:18:07 +01:00
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 12:18:07 +01:00
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-29 05:16:05 +02:00
#define CLEAN_RETURN(i) { operationResult = (i); goto _end; }
2016-09-21 12:24:43 +02:00
int main ( int argCount , const char * argv [])
2016-05-29 05:16:05 +02:00
{
int argNb ,
forceStdout = 0 ,
2017-03-23 11:52:09 -07:00
followLinks = 0 ,
2016-05-29 05:16:05 +02:00
main_pause = 0 ,
nextEntryIsDictionary = 0 ,
operationResult = 0 ,
nextArgumentIsOutFileName = 0 ,
2016-05-30 21:18:52 +02:00
nextArgumentIsMaxDict = 0 ,
2016-07-04 18:16:16 +02:00
nextArgumentIsDictID = 0 ,
2016-12-02 15:18:57 -08:00
nextArgumentsAreFiles = 0 ,
2016-09-21 14:20:56 +02:00
ultra = 0 ,
2017-01-19 16:59:56 -08:00
lastCommand = 0 ,
2017-02-07 16:48:01 +01:00
nbThreads = 1 ,
2017-07-28 15:51:33 -07:00
setRealTimePrio = 0 ,
ldmFlag = 0 ;
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 ;
2016-10-28 13:58:31 -07:00
zstd_operation_mode operation = zom_compress ;
2016-12-13 12:18:07 +01:00
ZSTD_compressionParameters compressionParams ;
2016-07-27 15:09:11 +02:00
int cLevel = ZSTDCLI_CLEVEL_DEFAULT ;
int cLevelLast = 1 ;
2016-05-29 05:16:05 +02:00
unsigned recursive = 0 ;
2016-10-14 13:13:13 -07:00
unsigned memLimit = 0 ;
2016-05-29 05:16:05 +02: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 17:37:14 +01:00
const char * suffix = ZSTD_EXTENSION ;
2016-05-29 05:16:05 +02:00
unsigned maxDictSize = g_defaultMaxDictSize ;
2016-05-30 21:18:52 +02:00
unsigned dictID = 0 ;
2016-07-27 15:09:11 +02:00
int dictCLevel = g_defaultDictCLevel ;
2016-05-29 05:16:05 +02:00
unsigned dictSelect = g_defaultSelectivityLevel ;
#ifdef UTIL_HAS_CREATEFILELIST
2016-09-21 12:24:43 +02:00
const char ** extendedFileList = NULL ;
2016-05-29 05:16:05 +02: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 ();
2017-05-01 23:40:20 -07:00
int cover = 1 ;
2016-12-31 21:08:24 -08:00
#endif
2016-05-29 05:16:05 +02:00
/* init */
2016-06-05 01:05:01 +02:00
( void ) recursive ; ( void ) cLevelLast ; /* not used when ZSTD_NOBENCH set */
2016-11-03 15:52:01 -07:00
( void ) dictCLevel ; ( void ) dictSelect ; ( void ) dictID ; ( void ) maxDictSize ; /* not used when ZSTD_NODICT set */
2017-09-01 10:19:38 -07:00
( void ) ultra ; ( void ) cLevel ; ( void ) ldmFlag ; /* not used when ZSTD_NOCOMPRESS set */
2016-11-03 15:52:01 -07:00
( void ) memLimit ; /* not used when ZSTD_NODECOMPRESS set */
2016-07-04 00:42:58 +02:00
if ( filenameTable == NULL ) { DISPLAY ( "zstd: %s \n " , strerror ( errno )); exit ( 1 ); }
2016-05-29 05:16:05 +02:00
filenameTable [ 0 ] = stdinmark ;
2017-03-23 11:13:52 -07:00
g_displayOut = stderr ;
2017-03-24 17:06:09 -07:00
programName = lastNameFromPath ( programName );
2016-05-29 05:16:05 +02:00
/* preset behaviors */
2017-04-14 11:33:04 -07:00
if ( exeNameMatch ( programName , ZSTD_ZSTDMT )) nbThreads = 0 ;
2017-03-24 17:06:09 -07:00
if ( exeNameMatch ( programName , ZSTD_UNZSTD )) operation = zom_decompress ;
if ( exeNameMatch ( programName , ZSTD_CAT )) { operation = zom_decompress ; forceStdout = 1 ; FIO_overwriteMode (); outFileName = stdoutmark ; g_displayLevel = 1 ; }
if ( exeNameMatch ( programName , ZSTD_GZ )) { suffix = GZ_EXTENSION ; FIO_setCompressionType ( FIO_gzipCompression ); FIO_setRemoveSrcFile ( 1 ); } /* behave like gzip */
if ( exeNameMatch ( programName , ZSTD_GUNZIP )) { operation = zom_decompress ; FIO_setRemoveSrcFile ( 1 ); } /* behave like gunzip */
if ( exeNameMatch ( programName , ZSTD_GZCAT )) { operation = zom_decompress ; forceStdout = 1 ; FIO_overwriteMode (); outFileName = stdoutmark ; g_displayLevel = 1 ; } /* behave like gzcat */
if ( exeNameMatch ( programName , ZSTD_LZMA )) { suffix = LZMA_EXTENSION ; FIO_setCompressionType ( FIO_lzmaCompression ); FIO_setRemoveSrcFile ( 1 ); } /* behave like lzma */
2017-06-26 11:24:36 -07:00
if ( exeNameMatch ( programName , ZSTD_UNLZMA )) { operation = zom_decompress ; FIO_setCompressionType ( FIO_lzmaCompression ); FIO_setRemoveSrcFile ( 1 ); } /* behave like unlzma */
2017-03-24 17:06:09 -07:00
if ( exeNameMatch ( programName , ZSTD_XZ )) { suffix = XZ_EXTENSION ; FIO_setCompressionType ( FIO_xzCompression ); FIO_setRemoveSrcFile ( 1 ); } /* behave like xz */
2017-06-26 11:24:36 -07:00
if ( exeNameMatch ( programName , ZSTD_UNXZ )) { operation = zom_decompress ; FIO_setCompressionType ( FIO_xzCompression ); FIO_setRemoveSrcFile ( 1 ); } /* behave like unxz */
2016-12-13 12:18:07 +01:00
memset ( & compressionParams , 0 , sizeof ( compressionParams ));
2016-05-29 05:16:05 +02:00
/* command switches */
2016-10-14 14:07:11 -07:00
for ( argNb = 1 ; argNb < argCount ; argNb ++ ) {
2016-05-29 05:16:05 +02: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 18:16:16 +02: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 18:16:16 +02:00
continue ;
} }
2016-05-29 05:16:05 +02:00
2016-07-04 18:16:16 +02:00
/* Decode commands (note : aggregated commands are allowed) */
if ( argument [ 0 ] == '-' ) {
2016-05-29 05:16:05 +02: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 ; }
2017-03-23 11:52:09 -07:00
if ( ! strcmp ( argument , "--force" )) { FIO_overwriteMode (); 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 ; }
2017-09-01 10:19:38 -07:00
if ( ! strcmp ( argument , "--long" )) { ldmFlag = 1 ; continue ; }
2016-12-02 15:18:57 -08:00
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 ; }
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 */
2016-12-02 15:18:57 -08:00
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 20:12:59 +01:00
if ( ! strcmp ( argument , "--priority=rt" )) { setRealTimePrio = 1 ; continue ; }
2017-03-01 16:49:20 -08:00
#ifdef ZSTD_GZCOMPRESS
2017-02-14 09:47:29 +01:00
if ( ! strcmp ( argument , "--format=gzip" )) { suffix = GZ_EXTENSION ; FIO_setCompressionType ( FIO_gzipCompression ); continue ; }
2017-03-01 16:49:20 -08:00
#endif
2017-03-13 18:11:07 -07:00
#ifdef ZSTD_LZMACOMPRESS
if ( ! strcmp ( argument , "--format=lzma" )) { suffix = LZMA_EXTENSION ; FIO_setCompressionType ( FIO_lzmaCompression ); continue ; }
if ( ! strcmp ( argument , "--format=xz" )) { suffix = XZ_EXTENSION ; FIO_setCompressionType ( FIO_xzCompression ); continue ; }
#endif
2017-04-24 16:48:25 -07:00
#ifdef ZSTD_LZ4COMPRESS
if ( ! strcmp ( argument , "--format=lz4" )) { suffix = LZ4_EXTENSION ; FIO_setCompressionType ( FIO_lz4Compression ); continue ; }
#endif
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 ;
outFileName = g_defaultDictName ;
cover = 1 ;
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 ;
}
2017-05-01 23:40:20 -07:00
if ( longCommandWArg ( & argument , "--train-legacy" )) {
operation = zom_train ;
outFileName = g_defaultDictName ;
cover = 0 ;
/* 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
2017-04-21 11:38:13 -07:00
if ( longCommandWArg ( & argument , "--threads=" )) { nbThreads = 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 12:18:07 +01:00
if ( longCommandWArg ( & argument , "--zstd=" )) { if ( ! parseCompressionParameters ( argument , & compressionParams )) CLEAN_RETURN ( badusage ( programName )); continue ; }
2016-12-02 15:18:57 -08:00
/* fall-through, will trigger bad_usage() later on */
}
argument ++ ;
2016-07-04 18:16:16 +02:00
while ( argument [ 0 ] != 0 ) {
2016-09-21 14:20:56 +02:00
if ( lastCommand ) {
DISPLAY ( "error : command must be followed by argument \n " );
2017-02-21 18:17:24 +01:00
CLEAN_RETURN ( 1 );
2016-09-21 14:20:56 +02:00
}
2016-09-01 15:05:57 -07:00
#ifndef ZSTD_NOCOMPRESS
2016-07-04 18:16:16 +02:00
/* compression Level */
if (( * argument >= '0' ) && ( * argument <= '9' )) {
2016-08-12 18:04:15 +02:00
dictCLevel = cLevel = readU32FromChar ( & argument );
2016-07-04 18:16:16 +02:00
continue ;
}
2016-09-01 15:05:57 -07:00
#endif
2016-05-29 05:16:05 +02:00
2016-07-04 18:16:16 +02: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 18:16:16 +02:00
case 'H' :
2017-03-23 11:13:52 -07:00
case 'h' : g_displayOut = stdout ; CLEAN_RETURN ( usage_advanced ( programName ));
2016-05-29 05:16:05 +02:00
2016-10-28 13:58:31 -07:00
/* Compress */
case 'z' : operation = zom_compress ; argument ++ ; break ;
2016-07-04 18:16:16 +02:00
/* Decoding */
2016-12-06 17:56:20 -08:00
case 'd' :
#ifndef ZSTD_NOBENCH
2016-12-28 16:11:09 +01:00
if ( operation == zom_bench ) { BMK_setDecodeOnlyMode ( 1 ); 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-29 05:16:05 +02:00
2016-07-04 18:16:16 +02:00
/* Force stdout, even if stdout==console */
2016-08-12 18:04:15 +02:00
case 'c' : forceStdout = 1 ; outFileName = stdoutmark ; argument ++ ; break ;
2016-05-29 05:16:05 +02:00
2016-07-04 18:16:16 +02:00
/* Use file content as dictionary */
2016-09-21 14:20:56 +02:00
case 'D' : nextEntryIsDictionary = 1 ; lastCommand = 1 ; argument ++ ; break ;
2016-05-29 05:16:05 +02:00
2016-07-04 18:16:16 +02:00
/* Overwrite */
2017-03-23 11:52:09 -07:00
case 'f' : FIO_overwriteMode (); forceStdout = 1 ; followLinks = 1 ; argument ++ ; break ;
2016-05-29 05:16:05 +02:00
2016-07-04 18:16:16 +02:00
/* Verbose mode */
2017-03-23 11:13:52 -07:00
case 'v' : g_displayLevel ++ ; argument ++ ; break ;
2016-05-29 05:16:05 +02:00
2016-07-04 18:16:16 +02:00
/* Quiet mode */
2017-03-23 11:13:52 -07:00
case 'q' : g_displayLevel -- ; argument ++ ; break ;
2016-05-29 05:16:05 +02:00
2017-05-02 15:40:42 -07:00
/* keep source file (default) */
2016-07-04 18:16:16 +02:00
case 'k' : FIO_setRemoveSrcFile ( 0 ); argument ++ ; break ;
2016-05-29 05:16:05 +02:00
2016-07-04 18:16:16 +02:00
/* Checksum */
2017-05-02 15:40:42 -07:00
case 'C' : FIO_setChecksumFlag ( 2 ); argument ++ ; break ;
2016-06-02 17:05:50 +02:00
2016-07-04 18:16:16 +02:00
/* test compressed file */
2016-10-28 13:58:31 -07:00
case 't' : operation = zom_test ; argument ++ ; break ;
2016-05-29 05:16:05 +02:00
2016-07-13 14:15:08 +02:00
/* destination file name */
2016-09-21 14:20:56 +02:00
case 'o' : nextArgumentIsOutFileName = 1 ; lastCommand = 1 ; argument ++ ; break ;
2016-05-29 05:16:05 +02:00
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 17:50:08 +02:00
#ifdef UTIL_HAS_CREATEFILELIST
2016-07-04 18:16:16 +02:00
/* recursive */
case 'r' : recursive = 1 ; argument ++ ; break ;
2016-09-13 17:50:08 +02:00
#endif
2016-05-29 05:16:05 +02:00
2016-09-01 15:05:57 -07:00
#ifndef ZSTD_NOBENCH
2016-07-04 18:16:16 +02:00
/* Benchmark */
2017-01-19 16:59:56 -08:00
case 'b' :
operation = zom_bench ;
argument ++ ;
break ;
2016-05-29 05:16:05 +02:00
2016-07-04 18:16:16 +02: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 18:16:16 +02:00
/* Modify Nb Iterations (benchmark only) */
case 'i' :
2016-05-29 05:16:05 +02:00
argument ++ ;
2017-01-19 16:59:56 -08:00
bench_nbSeconds = readU32FromChar ( & argument );
2016-05-29 05:16:05 +02:00
break ;
2016-07-04 18:16:16 +02:00
/* cut input into blocks (benchmark only) */
case 'B' :
argument ++ ;
2017-01-19 16:59:56 -08:00
blockSize = readU32FromChar ( & argument );
2016-07-04 18:16:16 +02:00
break ;
2017-01-02 02:05:45 +01:00
2017-01-19 16:59:56 -08:00
#endif /* ZSTD_NOBENCH */
2017-01-02 02:05:45 +01:00
/* nb of threads (hidden option) */
case 'T' :
argument ++ ;
2017-01-19 16:59:56 -08:00
nbThreads = readU32FromChar ( & argument );
2017-01-02 02:05:45 +01:00
break ;
2016-05-29 05:16:05 +02:00
2016-07-04 18:16:16 +02:00
/* Dictionary Selection level */
case 's' :
argument ++ ;
dictSelect = readU32FromChar ( & argument );
break ;
2016-05-29 05:16:05 +02:00
2016-07-04 18:16:16 +02: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 18:16:16 +02:00
if (( * argument >= '0' ) && ( * argument <= '9' )) {
BMK_setAdditionalParam ( readU32FromChar ( & argument ));
} else
2016-09-01 15:05:57 -07:00
#endif
2016-07-04 18:16:16 +02:00
main_pause = 1 ;
break ;
/* unknown command */
default : CLEAN_RETURN ( badusage ( programName ));
}
2016-05-29 05:16:05 +02:00
}
2016-07-04 18:16:16 +02: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 18:16:16 +02:00
nextArgumentIsMaxDict = 0 ;
2016-09-21 14:20:56 +02:00
lastCommand = 0 ;
2016-07-04 18:16:16 +02:00
maxDictSize = readU32FromChar ( & argument );
continue ;
2016-05-29 05:16:05 +02:00
}
2016-07-04 18:16:16 +02: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 18:16:16 +02:00
nextArgumentIsDictID = 0 ;
2016-09-21 14:20:56 +02:00
lastCommand = 0 ;
2016-07-04 18:16:16 +02:00
dictID = readU32FromChar ( & argument );
continue ;
}
} /* if (nextArgumentIsAFile==0) */
2016-05-29 05:16:05 +02:00
if ( nextEntryIsDictionary ) {
nextEntryIsDictionary = 0 ;
2016-09-21 14:20:56 +02:00
lastCommand = 0 ;
2016-05-29 05:16:05 +02:00
dictFileName = argument ;
continue ;
}
if ( nextArgumentIsOutFileName ) {
nextArgumentIsOutFileName = 0 ;
2016-09-21 14:20:56 +02:00
lastCommand = 0 ;
2016-05-29 05:16:05 +02:00
outFileName = argument ;
if ( ! strcmp ( outFileName , "-" )) outFileName = stdoutmark ;
continue ;
}
/* 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 16:05:03 +02:00
2016-05-29 05:16:05 +02:00
/* Welcome message (if verbose) */
DISPLAYLEVEL ( 3 , WELCOME_MESSAGE );
2017-04-13 12:28:28 -07:00
if ( nbThreads == 0 ) {
/* try to guess */
nbThreads = UTIL_countPhysicalCores ();
2017-08-18 18:30:41 -07:00
DISPLAYLEVEL ( 3 , "Note: %d physical core(s) detected \n " , nbThreads );
2017-04-13 12:28:28 -07:00
}
2017-03-23 11:52:09 -07:00
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 ];
}
}
filenameIdx = fileNamesNb ;
}
2016-05-29 05:16:05 +02:00
#ifdef UTIL_HAS_CREATEFILELIST
2016-09-21 12:24:43 +02: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 12:24:43 +02:00
if ( extendedFileList ) {
2016-08-01 14:26:49 +02:00
unsigned u ;
2016-09-21 12:24:43 +02:00
for ( u = 0 ; u < fileNamesNb ; u ++ ) DISPLAYLEVEL ( 4 , "%u %s \n " , u , extendedFileList [ u ]);
2016-05-29 05:16:05 +02:00
free (( void * ) filenameTable );
2016-09-21 12:24:43 +02:00
filenameTable = extendedFileList ;
2016-05-29 05:16:05 +02:00
filenameIdx = fileNamesNb ;
}
}
#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-29 05:16:05 +02:00
/* Check if benchmark is selected */
2016-10-28 13:58:31 -07:00
if ( operation == zom_bench ) {
2016-05-29 05:16:05 +02:00
#ifndef ZSTD_NOBENCH
2017-03-23 11:13:52 -07:00
BMK_setNotificationLevel ( g_displayLevel );
2017-01-19 16:59:56 -08:00
BMK_setBlockSize ( blockSize );
BMK_setNbThreads ( nbThreads );
BMK_setNbSeconds ( bench_nbSeconds );
2017-07-28 15:51:33 -07:00
BMK_setLdmFlag ( ldmFlag );
2017-09-01 14:52:51 -07:00
BMK_setLdmMinMatch ( g_ldmMinMatch );
BMK_setLdmHashLog ( g_ldmHashLog );
2017-09-02 21:10:36 -07:00
if ( g_ldmBucketSizeLog != LDM_PARAM_DEFAULT ) {
BMK_setLdmBucketSizeLog ( g_ldmBucketSizeLog );
}
if ( g_ldmHashEveryLog != LDM_PARAM_DEFAULT ) {
BMK_setLdmHashEveryLog ( g_ldmHashEveryLog );
}
2017-02-07 16:48:01 +01:00
BMK_benchFiles ( filenameTable , filenameIdx , dictFileName , cLevel , cLevelLast , & compressionParams , setRealTimePrio );
2016-05-29 05:16:05 +02:00
#endif
2017-08-19 01:23:49 -07:00
( void ) bench_nbSeconds ; ( void ) blockSize ; ( void ) setRealTimePrio ;
2016-05-29 05:16:05 +02:00
goto _end ;
}
/* Check if dictionary builder is selected */
2016-10-28 13:58:31 -07:00
if ( operation == zom_train ) {
2016-05-29 05:16:05 +02: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 ;
2016-12-31 21:08:24 -08:00
if ( cover ) {
2017-05-01 23:40:20 -07:00
int const optimize = ! coverParams . k || ! coverParams . d ;
2017-01-27 11:56:02 -08:00
coverParams . nbThreads = nbThreads ;
2017-06-26 21:07:14 -07:00
coverParams . zParams = zParams ;
2017-09-14 16:45:10 -07:00
operationResult = DiB_trainFromFiles ( outFileName , maxDictSize , filenameTable , filenameIdx , blockSize , NULL , & coverParams , 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 ;
2017-09-14 16:45:10 -07:00
operationResult = DiB_trainFromFiles ( outFileName , maxDictSize , filenameTable , filenameIdx , blockSize , & dictParams , NULL , 0 );
2016-12-31 21:08:24 -08:00
}
2016-05-29 05:16:05 +02:00
#endif
goto _end ;
}
2017-07-18 14:45:49 -07:00
#ifndef ZSTD_NODECOMPRESS
if ( operation == zom_test ) { outFileName = nulmark ; FIO_setRemoveSrcFile ( 0 ); } /* test mode */
#endif
2016-05-29 05:16:05 +02:00
/* No input filename ==> use stdin and stdout */
2016-08-26 01:43:47 +02: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 05:16:05 +02: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 ));
2017-03-16 16:06:03 -07:00
if ( outFileName && ! strcmp ( outFileName , stdoutmark ) && IS_CONSOLE ( stdout ) && ! strcmp ( filenameTable [ 0 ], stdinmark ) && ! forceStdout && operation != zom_decompress )
2016-05-29 05:16:05 +02: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 11:56:22 +02:00
#ifndef ZSTD_NOCOMPRESS
2016-08-12 18:04:15 +02: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 11:56:22 +02:00
#endif
2016-08-12 18:04:15 +02: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-29 05:16:05 +02: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 12:24:43 +02:00
#ifndef ZSTD_NOCOMPRESS
2017-01-19 16:59:56 -08:00
FIO_setNbThreads ( nbThreads );
2017-01-24 17:02:26 -08:00
FIO_setBlockSize (( U32 ) blockSize );
2017-07-28 15:51:33 -07:00
FIO_setLdmFlag ( ldmFlag );
2017-09-01 14:52:51 -07:00
FIO_setLdmHashLog ( g_ldmHashLog );
FIO_setLdmMinMatch ( g_ldmMinMatch );
2017-09-02 21:10:36 -07:00
if ( g_ldmBucketSizeLog != LDM_PARAM_DEFAULT ) {
FIO_setLdmBucketSizeLog ( g_ldmBucketSizeLog );
}
if ( g_ldmHashEveryLog != LDM_PARAM_DEFAULT ) {
2017-09-01 14:52:51 -07:00
FIO_setLdmHashEveryLog ( g_ldmHashEveryLog );
}
2017-01-30 14:37:08 -08:00
if ( g_overlapLog != OVERLAP_LOG_DEFAULT ) FIO_setOverlapLog ( g_overlapLog );
2016-09-21 16:46:08 +02:00
if (( filenameIdx == 1 ) && outFileName )
2016-12-13 13:24:59 +01:00
operationResult = FIO_compressFilename ( outFileName , filenameTable [ 0 ], dictFileName , cLevel , & compressionParams );
2016-05-29 05:16:05 +02:00
else
2017-02-08 17:37:14 +01:00
operationResult = FIO_compressMultipleFilenames ( filenameTable , filenameIdx , outFileName ? outFileName : suffix , dictFileName , cLevel , & compressionParams );
2016-09-21 12:24:43 +02:00
#else
2017-08-19 01:23:49 -07:00
( void ) suffix ;
2016-09-21 12:24:43 +02:00
DISPLAY ( "Compression not supported \n " );
2016-05-29 05:16:05 +02:00
#endif
2016-10-28 13:58:31 -07:00
} else { /* decompression or test */
2016-05-29 05:16:05 +02:00
#ifndef ZSTD_NODECOMPRESS
2016-10-14 13:13:13 -07:00
FIO_setMemLimit ( memLimit );
2016-05-29 05:16:05 +02: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 12:24:43 +02:00
if ( extendedFileList )
UTIL_freeFileList ( extendedFileList , fileNamesBuf );
2016-05-29 05:16:05 +02:00
else
#endif
free (( void * ) filenameTable );
return operationResult ;
}