blob: 281301bd1cd2c912be1e090cb169c97aafe15bd3 [file] [log] [blame]
Yann Collet4ded9e52016-08-30 10:04:33 -07001/**
2 * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
3 * All rights reserved.
4 *
5 * This source code is licensed under the BSD-style license found in the
6 * LICENSE file in the root directory of this source tree. An additional grant
7 * of patent rights can be found in the PATENTS file in the same directory.
8 */
Yann Collet5f53b032016-08-28 10:00:49 -07009
Yann Colletfcf20872016-05-29 05:16:05 +020010
Yann Colletfcf20872016-05-29 05:16:05 +020011/*-************************************
Yann Collet2cac5b32016-07-13 14:15:08 +020012* Tuning parameters
13**************************************/
Yann Collet2b1a3632016-07-13 15:16:00 +020014#ifndef ZSTDCLI_CLEVEL_DEFAULT
15# define ZSTDCLI_CLEVEL_DEFAULT 3
Yann Collet2cac5b32016-07-13 14:15:08 +020016#endif
17
Yann Colletfe0590f2016-08-12 18:04:15 +020018#ifndef ZSTDCLI_CLEVEL_MAX
Yann Collet0977f7e2016-09-21 12:24:43 +020019# define ZSTDCLI_CLEVEL_MAX 19 /* when not using --ultra */
Yann Colletfe0590f2016-08-12 18:04:15 +020020#endif
21
Yann Collet2cac5b32016-07-13 14:15:08 +020022
Yann Collet8dafb1a2017-01-25 17:01:13 -080023
Yann Collet2cac5b32016-07-13 14:15:08 +020024/*-************************************
Yann Collet52afb392016-11-16 08:50:54 -080025* Dependencies
Yann Colletfcf20872016-05-29 05:16:05 +020026**************************************/
Przemyslaw Skibinski7a8a03c2016-12-21 15:08:44 +010027#include "platform.h" /* IS_CONSOLE, PLATFORM_POSIX_VERSION */
28#include "util.h" /* UTIL_HAS_CREATEFILELIST, UTIL_createFileList */
Yann Colletfcf20872016-05-29 05:16:05 +020029#include <string.h> /* strcmp, strlen */
Yann Colletf9cac7a2016-07-04 18:16:16 +020030#include <errno.h> /* errno */
Yann Colletfcf20872016-05-29 05:16:05 +020031#include "fileio.h"
32#ifndef ZSTD_NOBENCH
Przemyslaw Skibinski26306fc2016-11-03 11:38:01 +010033# include "bench.h" /* BMK_benchFiles, BMK_SetNbSeconds */
Yann Colletfcf20872016-05-29 05:16:05 +020034#endif
Yann Colletfcf20872016-05-29 05:16:05 +020035#ifndef ZSTD_NODICT
36# include "dibio.h"
37#endif
Yann Colletd3b7f8d2016-06-04 19:47:02 +020038#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_maxCLevel */
39#include "zstd.h" /* ZSTD_VERSION_STRING */
Yann Colletfcf20872016-05-29 05:16:05 +020040
41
Yann Colletfcf20872016-05-29 05:16:05 +020042/*-************************************
Yann Colletfcf20872016-05-29 05:16:05 +020043* Constants
44**************************************/
45#define COMPRESSOR_NAME "zstd command line interface"
46#ifndef ZSTD_VERSION
47# define ZSTD_VERSION "v" ZSTD_VERSION_STRING
48#endif
49#define AUTHOR "Yann Collet"
50#define WELCOME_MESSAGE "*** %s %i-bits %s, by %s ***\n", COMPRESSOR_NAME, (int)(sizeof(size_t)*8), ZSTD_VERSION, AUTHOR
51
Yann Colletfcf20872016-05-29 05:16:05 +020052#define ZSTD_UNZSTD "unzstd"
Yann Colletc09d16b2017-02-14 10:45:19 -080053#define ZSTD_CAT "zstdcat"
54#define ZSTD_GZ "gzip"
55#define ZSTD_GUNZIP "gunzip"
56#define ZSTD_GZCAT "gzcat"
Nick Terrellaa8bcf32017-03-13 18:11:07 -070057#define ZSTD_LZMA "lzma"
58#define ZSTD_XZ "xz"
Yann Colletfcf20872016-05-29 05:16:05 +020059
60#define KB *(1 <<10)
61#define MB *(1 <<20)
62#define GB *(1U<<30)
63
David Lamac43e952016-08-12 14:49:05 -070064#define DEFAULT_DISPLAY_LEVEL 2
65
Yann Colletfcf20872016-05-29 05:16:05 +020066static const char* g_defaultDictName = "dictionary";
67static const unsigned g_defaultMaxDictSize = 110 KB;
Yann Colletc8431422016-09-01 15:05:57 -070068static const int g_defaultDictCLevel = 3;
Yann Colletfcf20872016-05-29 05:16:05 +020069static const unsigned g_defaultSelectivityLevel = 9;
Yann Collet8d8513f2017-01-30 14:37:08 -080070#define OVERLAP_LOG_DEFAULT 9999
71static U32 g_overlapLog = OVERLAP_LOG_DEFAULT;
Yann Colletfcf20872016-05-29 05:16:05 +020072
73
74/*-************************************
75* Display Macros
76**************************************/
Sean Purcell042ba122017-03-23 11:13:52 -070077#define DISPLAY(...) fprintf(g_displayOut, __VA_ARGS__)
78#define DISPLAYLEVEL(l, ...) { if (g_displayLevel>=l) { DISPLAY(__VA_ARGS__); } }
79static int g_displayLevel = DEFAULT_DISPLAY_LEVEL; /* 0 : no display, 1: errors, 2 : + result + interaction + warnings, 3 : + progression, 4 : + information */
80static FILE* g_displayOut;
Yann Colletfcf20872016-05-29 05:16:05 +020081
82
83/*-************************************
84* Command Line
85**************************************/
86static int usage(const char* programName)
87{
88 DISPLAY( "Usage :\n");
89 DISPLAY( " %s [args] [FILE(s)] [-o file]\n", programName);
90 DISPLAY( "\n");
91 DISPLAY( "FILE : a filename\n");
92 DISPLAY( " with no FILE, or when FILE is - , read standard input\n");
93 DISPLAY( "Arguments :\n");
94#ifndef ZSTD_NOCOMPRESS
inikep5a548702016-08-18 09:00:25 +020095 DISPLAY( " -# : # compression level (1-%d, default:%d) \n", ZSTDCLI_CLEVEL_MAX, ZSTDCLI_CLEVEL_DEFAULT);
Yann Colletfcf20872016-05-29 05:16:05 +020096#endif
97#ifndef ZSTD_NODECOMPRESS
98 DISPLAY( " -d : decompression \n");
99#endif
100 DISPLAY( " -D file: use `file` as Dictionary \n");
101 DISPLAY( " -o file: result stored into `file` (only if 1 input file) \n");
Sean Purcell680e4e02017-03-23 11:52:09 -0700102 DISPLAY( " -f : overwrite output without prompting and (de)compress links \n");
Yann Colleta7a5d772016-07-02 00:37:32 +0200103 DISPLAY( "--rm : remove source file(s) after successful de/compression \n");
Yann Colletd916c902016-07-04 00:42:58 +0200104 DISPLAY( " -k : preserve source file(s) (default) \n");
Yann Colletfcf20872016-05-29 05:16:05 +0200105 DISPLAY( " -h/-H : display help/long help and exit\n");
106 return 0;
107}
108
109static int usage_advanced(const char* programName)
110{
111 DISPLAY(WELCOME_MESSAGE);
112 usage(programName);
113 DISPLAY( "\n");
114 DISPLAY( "Advanced arguments :\n");
115 DISPLAY( " -V : display Version number and exit\n");
David Lamac43e952016-08-12 14:49:05 -0700116 DISPLAY( " -v : verbose mode; specify multiple times to increase log level (default:%d)\n", DEFAULT_DISPLAY_LEVEL);
Yann Colletfcf20872016-05-29 05:16:05 +0200117 DISPLAY( " -q : suppress warnings; specify twice to suppress errors too\n");
118 DISPLAY( " -c : force write to standard output, even if it is the console\n");
119#ifdef UTIL_HAS_CREATEFILELIST
Yann Collet500014a2017-01-19 16:59:56 -0800120 DISPLAY( " -r : operate recursively on directories \n");
Yann Colletfcf20872016-05-29 05:16:05 +0200121#endif
122#ifndef ZSTD_NOCOMPRESS
Yann Colletfe0590f2016-08-12 18:04:15 +0200123 DISPLAY( "--ultra : enable levels beyond %i, up to %i (requires more memory)\n", ZSTDCLI_CLEVEL_MAX, ZSTD_maxCLevel());
Yann Colletb09b12c2016-06-09 22:59:51 +0200124 DISPLAY( "--no-dictID : don't write dictID into header (dictionary compression)\n");
Yann Collet500014a2017-01-19 16:59:56 -0800125 DISPLAY( "--[no-]check : integrity check (default:enabled) \n");
126#ifdef ZSTD_MULTITHREAD
127 DISPLAY( " -T# : use # threads for compression (default:1) \n");
Yann Collet512cbe82017-01-24 17:02:26 -0800128 DISPLAY( " -B# : select size of independent sections (default:0==automatic) \n");
Yann Collet500014a2017-01-19 16:59:56 -0800129#endif
Przemyslaw Skibinskicfd4dc22017-02-08 15:17:55 +0100130#ifdef ZSTD_GZCOMPRESS
Przemyslaw Skibinski4f9eaa72017-02-08 18:08:09 +0100131 DISPLAY( "--format=gzip : compress files to the .gz format \n");
Przemyslaw Skibinskicfd4dc22017-02-08 15:17:55 +0100132#endif
Nick Terrellaa8bcf32017-03-13 18:11:07 -0700133#ifdef ZSTD_LZMACOMPRESS
134 DISPLAY( "--format=xz : compress files to the .xz format \n");
135 DISPLAY( "--format=lzma : compress files to the .lzma format \n");
136#endif
Yann Colletfcf20872016-05-29 05:16:05 +0200137#endif
Yann Collet6381e992016-05-31 02:29:45 +0200138#ifndef ZSTD_NODECOMPRESS
Yann Collet2c4acda2016-06-02 17:05:50 +0200139 DISPLAY( "--test : test compressed file integrity \n");
Yann Colletb09b12c2016-06-09 22:59:51 +0200140 DISPLAY( "--[no-]sparse : sparse mode (default:enabled on file, disabled on stdout)\n");
Yann Collet6381e992016-05-31 02:29:45 +0200141#endif
Yann Colletd4cda272016-10-14 13:13:13 -0700142 DISPLAY( " -M# : Set a memory usage limit for decompression \n");
Yann Collet60038942016-09-16 18:52:52 +0200143 DISPLAY( "-- : All arguments after \"--\" are treated as files \n");
Yann Colletfcf20872016-05-29 05:16:05 +0200144#ifndef ZSTD_NODICT
145 DISPLAY( "\n");
146 DISPLAY( "Dictionary builder :\n");
Yann Colletb09b12c2016-06-09 22:59:51 +0200147 DISPLAY( "--train ## : create a dictionary from a training set of files \n");
Nick Terrelldf8415c2016-12-31 21:08:24 -0800148 DISPLAY( "--cover=k=#,d=# : use the cover algorithm with parameters k and d \n");
149 DISPLAY( "--optimize-cover[=steps=#,k=#,d=#] : optimize cover parameters with optional parameters\n");
Yann Colletb09b12c2016-06-09 22:59:51 +0200150 DISPLAY( " -o file : `file` is dictionary name (default: %s) \n", g_defaultDictName);
151 DISPLAY( "--maxdict ## : limit dictionary to specified size (default : %u) \n", g_defaultMaxDictSize);
Yann Colletfcf20872016-05-29 05:16:05 +0200152 DISPLAY( " -s# : dictionary selectivity level (default: %u)\n", g_defaultSelectivityLevel);
Yann Colletb09b12c2016-06-09 22:59:51 +0200153 DISPLAY( "--dictID ## : force dictionary ID to specified value (default: random)\n");
Yann Colletfcf20872016-05-29 05:16:05 +0200154#endif
155#ifndef ZSTD_NOBENCH
156 DISPLAY( "\n");
157 DISPLAY( "Benchmark arguments :\n");
158 DISPLAY( " -b# : benchmark file(s), using # compression level (default : 1) \n");
159 DISPLAY( " -e# : test all compression levels from -bX to # (default: 1)\n");
Yann Colleta9febe82016-08-01 13:37:17 +0200160 DISPLAY( " -i# : minimum evaluation time in seconds (default : 3s)\n");
Yann Colletfcf20872016-05-29 05:16:05 +0200161 DISPLAY( " -B# : cut file into independent blocks of size # (default: no block)\n");
Przemyslaw Skibinski40580ff2017-02-08 13:49:06 +0100162 DISPLAY( "--priority=rt : set process priority to real-time\n");
Yann Colletfcf20872016-05-29 05:16:05 +0200163#endif
164 return 0;
165}
166
167static int badusage(const char* programName)
168{
169 DISPLAYLEVEL(1, "Incorrect parameters\n");
Sean Purcell042ba122017-03-23 11:13:52 -0700170 if (g_displayLevel >= 2) usage(programName);
Yann Colletfcf20872016-05-29 05:16:05 +0200171 return 1;
172}
173
Yann Colletfcf20872016-05-29 05:16:05 +0200174static void waitEnter(void)
175{
176 int unused;
177 DISPLAY("Press enter to continue...\n");
178 unused = getchar();
179 (void)unused;
180}
181
Yann Collet1dd79612016-06-03 15:14:09 +0200182/*! readU32FromChar() :
Yann Colletd4cda272016-10-14 13:13:13 -0700183 @return : unsigned integer value read from input in `char` format
184 allows and interprets K, KB, KiB, M, MB and MiB suffix.
Yann Collet1dd79612016-06-03 15:14:09 +0200185 Will also modify `*stringPtr`, advancing it to position where it stopped reading.
Yann Colletd4cda272016-10-14 13:13:13 -0700186 Note : function result can overflow if digit string > MAX_UINT */
Yann Collet1dd79612016-06-03 15:14:09 +0200187static unsigned readU32FromChar(const char** stringPtr)
188{
189 unsigned result = 0;
190 while ((**stringPtr >='0') && (**stringPtr <='9'))
191 result *= 10, result += **stringPtr - '0', (*stringPtr)++ ;
Yann Collet33fdd092016-10-17 17:48:48 -0700192 if ((**stringPtr=='K') || (**stringPtr=='M')) {
193 result <<= 10;
194 if (**stringPtr=='M') result <<= 10;
195 (*stringPtr)++ ;
196 if (**stringPtr=='i') (*stringPtr)++;
197 if (**stringPtr=='B') (*stringPtr)++;
198 }
Yann Collet1dd79612016-06-03 15:14:09 +0200199 return result;
200}
201
Yann Collet743b33f2016-12-02 15:18:57 -0800202/** longCommandWArg() :
Yann Collet6ccd37c2017-01-30 13:07:24 -0800203 * check if *stringPtr is the same as longCommand.
Yann Collet743b33f2016-12-02 15:18:57 -0800204 * If yes, @return 1 and advances *stringPtr to the position which immediately follows longCommand.
205 * @return 0 and doesn't modify *stringPtr otherwise.
206 */
Yann Collet70077bc2016-10-14 14:41:17 -0700207static unsigned longCommandWArg(const char** stringPtr, const char* longCommand)
208{
209 size_t const comSize = strlen(longCommand);
Yann Collet743b33f2016-12-02 15:18:57 -0800210 int const result = !strncmp(*stringPtr, longCommand, comSize);
Yann Collet70077bc2016-10-14 14:41:17 -0700211 if (result) *stringPtr += comSize;
212 return result;
213}
214
Przemyslaw Skibinski671f28d2016-12-13 12:18:07 +0100215
Nick Terrelldf8415c2016-12-31 21:08:24 -0800216#ifndef ZSTD_NODICT
217/**
218 * parseCoverParameters() :
219 * reads cover parameters from *stringPtr (e.g. "--cover=smoothing=100,kmin=48,kstep=4,kmax=64,d=8") into *params
220 * @return 1 means that cover parameters were correct
221 * @return 0 in case of malformed parameters
222 */
223static unsigned parseCoverParameters(const char* stringPtr, COVER_params_t *params)
224{
225 memset(params, 0, sizeof(*params));
226 for (; ;) {
Nick Terrell3a1fefc2017-01-02 12:40:43 -0800227 if (longCommandWArg(&stringPtr, "k=")) { params->k = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
Nick Terrelldf8415c2016-12-31 21:08:24 -0800228 if (longCommandWArg(&stringPtr, "d=")) { params->d = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
Nick Terrell3a1fefc2017-01-02 12:40:43 -0800229 if (longCommandWArg(&stringPtr, "steps=")) { params->steps = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
Nick Terrelldf8415c2016-12-31 21:08:24 -0800230 return 0;
231 }
232 if (stringPtr[0] != 0) return 0;
Nick Terrell3a1fefc2017-01-02 12:40:43 -0800233 DISPLAYLEVEL(4, "k=%u\nd=%u\nsteps=%u\n", params->k, params->d, params->steps);
Nick Terrelldf8415c2016-12-31 21:08:24 -0800234 return 1;
235}
236#endif
Yann Collet6ccd37c2017-01-30 13:07:24 -0800237
238
Przemyslaw Skibinski671f28d2016-12-13 12:18:07 +0100239/** parseCompressionParameters() :
240 * reads compression parameters from *stringPtr (e.g. "--zstd=wlog=23,clog=23,hlog=22,slog=6,slen=3,tlen=48,strat=6") into *params
241 * @return 1 means that compression parameters were correct
242 * @return 0 in case of malformed parameters
243 */
244static unsigned parseCompressionParameters(const char* stringPtr, ZSTD_compressionParameters* params)
245{
246 for ( ; ;) {
Przemyslaw Skibinski671f28d2016-12-13 12:18:07 +0100247 if (longCommandWArg(&stringPtr, "windowLog=") || longCommandWArg(&stringPtr, "wlog=")) { params->windowLog = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
248 if (longCommandWArg(&stringPtr, "chainLog=") || longCommandWArg(&stringPtr, "clog=")) { params->chainLog = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
249 if (longCommandWArg(&stringPtr, "hashLog=") || longCommandWArg(&stringPtr, "hlog=")) { params->hashLog = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
250 if (longCommandWArg(&stringPtr, "searchLog=") || longCommandWArg(&stringPtr, "slog=")) { params->searchLog = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
251 if (longCommandWArg(&stringPtr, "searchLength=") || longCommandWArg(&stringPtr, "slen=")) { params->searchLength = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
252 if (longCommandWArg(&stringPtr, "targetLength=") || longCommandWArg(&stringPtr, "tlen=")) { params->targetLength = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
Przemyslaw Skibinskic71e5522016-12-13 20:04:32 +0100253 if (longCommandWArg(&stringPtr, "strategy=") || longCommandWArg(&stringPtr, "strat=")) { params->strategy = (ZSTD_strategy)(1 + readU32FromChar(&stringPtr)); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
Yann Collet6ccd37c2017-01-30 13:07:24 -0800254 if (longCommandWArg(&stringPtr, "overlapLog=") || longCommandWArg(&stringPtr, "ovlog=")) { g_overlapLog = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }
Przemyslaw Skibinski671f28d2016-12-13 12:18:07 +0100255 return 0;
256 }
257
258 if (stringPtr[0] != 0) return 0; /* check the end of string */
Przemyslaw Skibinski897b8bb2016-12-13 13:03:41 +0100259 DISPLAYLEVEL(4, "windowLog=%d\nchainLog=%d\nhashLog=%d\nsearchLog=%d\n", params->windowLog, params->chainLog, params->hashLog, params->searchLog);
260 DISPLAYLEVEL(4, "searchLength=%d\ntargetLength=%d\nstrategy=%d\n", params->searchLength, params->targetLength, params->strategy);
Przemyslaw Skibinski671f28d2016-12-13 12:18:07 +0100261 return 1;
262}
263
264
Yann Collet22de81e2016-10-28 13:58:31 -0700265typedef enum { zom_compress, zom_decompress, zom_test, zom_bench, zom_train } zstd_operation_mode;
Yann Colletfcf20872016-05-29 05:16:05 +0200266
267#define CLEAN_RETURN(i) { operationResult = (i); goto _end; }
268
Yann Collet0977f7e2016-09-21 12:24:43 +0200269int main(int argCount, const char* argv[])
Yann Colletfcf20872016-05-29 05:16:05 +0200270{
271 int argNb,
Yann Colletfcf20872016-05-29 05:16:05 +0200272 forceStdout=0,
Sean Purcell680e4e02017-03-23 11:52:09 -0700273 followLinks=0,
Yann Colletfcf20872016-05-29 05:16:05 +0200274 main_pause=0,
275 nextEntryIsDictionary=0,
276 operationResult=0,
Yann Colletfcf20872016-05-29 05:16:05 +0200277 nextArgumentIsOutFileName=0,
Yann Collet290aaa72016-05-30 21:18:52 +0200278 nextArgumentIsMaxDict=0,
Yann Colletf9cac7a2016-07-04 18:16:16 +0200279 nextArgumentIsDictID=0,
Yann Collet743b33f2016-12-02 15:18:57 -0800280 nextArgumentsAreFiles=0,
Yann Collet27b5ac62016-09-21 14:20:56 +0200281 ultra=0,
Yann Collet500014a2017-01-19 16:59:56 -0800282 lastCommand = 0,
Przemyslaw Skibinskid05014c2017-02-07 16:48:01 +0100283 nbThreads = 1,
284 setRealTimePrio = 0;
Yann Collet500014a2017-01-19 16:59:56 -0800285 unsigned bench_nbSeconds = 3; /* would be better if this value was synchronized from bench */
286 size_t blockSize = 0;
Yann Collet22de81e2016-10-28 13:58:31 -0700287 zstd_operation_mode operation = zom_compress;
Przemyslaw Skibinski671f28d2016-12-13 12:18:07 +0100288 ZSTD_compressionParameters compressionParams;
Yann Collet41105342016-07-27 15:09:11 +0200289 int cLevel = ZSTDCLI_CLEVEL_DEFAULT;
290 int cLevelLast = 1;
Yann Colletfcf20872016-05-29 05:16:05 +0200291 unsigned recursive = 0;
Yann Colletd4cda272016-10-14 13:13:13 -0700292 unsigned memLimit = 0;
Yann Colletfcf20872016-05-29 05:16:05 +0200293 const char** filenameTable = (const char**)malloc(argCount * sizeof(const char*)); /* argCount >= 1 */
294 unsigned filenameIdx = 0;
295 const char* programName = argv[0];
296 const char* outFileName = NULL;
297 const char* dictFileName = NULL;
Przemyslaw Skibinskicb563062017-02-08 17:37:14 +0100298 const char* suffix = ZSTD_EXTENSION;
Yann Colletfcf20872016-05-29 05:16:05 +0200299 unsigned maxDictSize = g_defaultMaxDictSize;
Yann Collet290aaa72016-05-30 21:18:52 +0200300 unsigned dictID = 0;
Yann Collet41105342016-07-27 15:09:11 +0200301 int dictCLevel = g_defaultDictCLevel;
Yann Colletfcf20872016-05-29 05:16:05 +0200302 unsigned dictSelect = g_defaultSelectivityLevel;
303#ifdef UTIL_HAS_CREATEFILELIST
Yann Collet0977f7e2016-09-21 12:24:43 +0200304 const char** extendedFileList = NULL;
Yann Colletfcf20872016-05-29 05:16:05 +0200305 char* fileNamesBuf = NULL;
306 unsigned fileNamesNb;
307#endif
Nick Terrelldf8415c2016-12-31 21:08:24 -0800308#ifndef ZSTD_NODICT
309 COVER_params_t coverParams;
310 int cover = 0;
311#endif
Yann Colletfcf20872016-05-29 05:16:05 +0200312
313 /* init */
Yann Colletf3a1a842016-06-05 01:05:01 +0200314 (void)recursive; (void)cLevelLast; /* not used when ZSTD_NOBENCH set */
Yann Collet407a11f2016-11-03 15:52:01 -0700315 (void)dictCLevel; (void)dictSelect; (void)dictID; (void)maxDictSize; /* not used when ZSTD_NODICT set */
316 (void)ultra; (void)cLevel; /* not used when ZSTD_NOCOMPRESS set */
317 (void)memLimit; /* not used when ZSTD_NODECOMPRESS set */
Yann Colletd916c902016-07-04 00:42:58 +0200318 if (filenameTable==NULL) { DISPLAY("zstd: %s \n", strerror(errno)); exit(1); }
Yann Colletfcf20872016-05-29 05:16:05 +0200319 filenameTable[0] = stdinmark;
Sean Purcell042ba122017-03-23 11:13:52 -0700320 g_displayOut = stderr;
Yann Colletfcf20872016-05-29 05:16:05 +0200321 /* Pick out program name from path. Don't rely on stdlib because of conflicting behavior */
322 { size_t pos;
323 for (pos = (int)strlen(programName); pos > 0; pos--) { if (programName[pos] == '/') { pos++; break; } }
324 programName += pos;
325 }
326
327 /* preset behaviors */
Yann Collet22de81e2016-10-28 13:58:31 -0700328 if (!strcmp(programName, ZSTD_UNZSTD)) operation=zom_decompress;
Sean Purcell042ba122017-03-23 11:13:52 -0700329 if (!strcmp(programName, ZSTD_CAT)) { operation=zom_decompress; forceStdout=1; FIO_overwriteMode(); outFileName=stdoutmark; g_displayLevel=1; }
Yann Colletc09d16b2017-02-14 10:45:19 -0800330 if (!strcmp(programName, ZSTD_GZ)) { suffix = GZ_EXTENSION; FIO_setCompressionType(FIO_gzipCompression); FIO_setRemoveSrcFile(1); } /* behave like gzip */
331 if (!strcmp(programName, ZSTD_GUNZIP)) { operation=zom_decompress; FIO_setRemoveSrcFile(1); } /* behave like gunzip */
Sean Purcell042ba122017-03-23 11:13:52 -0700332 if (!strcmp(programName, ZSTD_GZCAT)) { operation=zom_decompress; forceStdout=1; FIO_overwriteMode(); outFileName=stdoutmark; g_displayLevel=1; } /* behave like gzcat */
Nick Terrellaa8bcf32017-03-13 18:11:07 -0700333 if (!strcmp(programName, ZSTD_LZMA)) { suffix = LZMA_EXTENSION; FIO_setCompressionType(FIO_lzmaCompression); FIO_setRemoveSrcFile(1); } /* behave like lzma */
334 if (!strcmp(programName, ZSTD_XZ)) { suffix = XZ_EXTENSION; FIO_setCompressionType(FIO_xzCompression); FIO_setRemoveSrcFile(1); } /* behave like xz */
Przemyslaw Skibinski671f28d2016-12-13 12:18:07 +0100335 memset(&compressionParams, 0, sizeof(compressionParams));
Yann Colletfcf20872016-05-29 05:16:05 +0200336
337 /* command switches */
Yann Collet11223492016-10-14 14:07:11 -0700338 for (argNb=1; argNb<argCount; argNb++) {
Yann Colletfcf20872016-05-29 05:16:05 +0200339 const char* argument = argv[argNb];
340 if(!argument) continue; /* Protection if argument empty */
341
Yann Collet743b33f2016-12-02 15:18:57 -0800342 if (nextArgumentsAreFiles==0) {
343 /* "-" means stdin/stdout */
Yann Colletf9cac7a2016-07-04 18:16:16 +0200344 if (!strcmp(argument, "-")){
345 if (!filenameIdx) {
346 filenameIdx=1, filenameTable[0]=stdinmark;
347 outFileName=stdoutmark;
Sean Purcell042ba122017-03-23 11:13:52 -0700348 g_displayLevel-=(g_displayLevel==2);
Yann Colletfcf20872016-05-29 05:16:05 +0200349 continue;
Yann Colletf9cac7a2016-07-04 18:16:16 +0200350 } }
Yann Colletfcf20872016-05-29 05:16:05 +0200351
Yann Colletf9cac7a2016-07-04 18:16:16 +0200352 /* Decode commands (note : aggregated commands are allowed) */
353 if (argument[0]=='-') {
Yann Colletfcf20872016-05-29 05:16:05 +0200354
Yann Collet743b33f2016-12-02 15:18:57 -0800355 if (argument[1]=='-') {
356 /* long commands (--long-word) */
357 if (!strcmp(argument, "--")) { nextArgumentsAreFiles=1; continue; } /* only file names allowed from now on */
358 if (!strcmp(argument, "--compress")) { operation=zom_compress; continue; }
359 if (!strcmp(argument, "--decompress")) { operation=zom_decompress; continue; }
360 if (!strcmp(argument, "--uncompress")) { operation=zom_decompress; continue; }
Sean Purcell680e4e02017-03-23 11:52:09 -0700361 if (!strcmp(argument, "--force")) { FIO_overwriteMode(); forceStdout=1; followLinks=1; continue; }
Sean Purcell042ba122017-03-23 11:13:52 -0700362 if (!strcmp(argument, "--version")) { g_displayOut=stdout; DISPLAY(WELCOME_MESSAGE); CLEAN_RETURN(0); }
363 if (!strcmp(argument, "--help")) { g_displayOut=stdout; CLEAN_RETURN(usage_advanced(programName)); }
364 if (!strcmp(argument, "--verbose")) { g_displayLevel++; continue; }
365 if (!strcmp(argument, "--quiet")) { g_displayLevel--; continue; }
366 if (!strcmp(argument, "--stdout")) { forceStdout=1; outFileName=stdoutmark; g_displayLevel-=(g_displayLevel==2); continue; }
Yann Collet743b33f2016-12-02 15:18:57 -0800367 if (!strcmp(argument, "--ultra")) { ultra=1; continue; }
368 if (!strcmp(argument, "--check")) { FIO_setChecksumFlag(2); continue; }
369 if (!strcmp(argument, "--no-check")) { FIO_setChecksumFlag(0); continue; }
370 if (!strcmp(argument, "--sparse")) { FIO_setSparseWrite(2); continue; }
371 if (!strcmp(argument, "--no-sparse")) { FIO_setSparseWrite(0); continue; }
372 if (!strcmp(argument, "--test")) { operation=zom_test; continue; }
373 if (!strcmp(argument, "--train")) { operation=zom_train; outFileName=g_defaultDictName; continue; }
374 if (!strcmp(argument, "--maxdict")) { nextArgumentIsMaxDict=1; lastCommand=1; continue; }
375 if (!strcmp(argument, "--dictID")) { nextArgumentIsDictID=1; lastCommand=1; continue; }
376 if (!strcmp(argument, "--no-dictID")) { FIO_setDictIDFlag(0); continue; }
377 if (!strcmp(argument, "--keep")) { FIO_setRemoveSrcFile(0); continue; }
378 if (!strcmp(argument, "--rm")) { FIO_setRemoveSrcFile(1); continue; }
Przemyslaw Skibinski0665a352017-02-07 20:12:59 +0100379 if (!strcmp(argument, "--priority=rt")) { setRealTimePrio = 1; continue; }
Yann Colletc1c040e2017-03-01 16:49:20 -0800380#ifdef ZSTD_GZCOMPRESS
Przemyslaw Skibinski97041952017-02-14 09:47:29 +0100381 if (!strcmp(argument, "--format=gzip")) { suffix = GZ_EXTENSION; FIO_setCompressionType(FIO_gzipCompression); continue; }
Yann Colletc1c040e2017-03-01 16:49:20 -0800382#endif
Nick Terrellaa8bcf32017-03-13 18:11:07 -0700383#ifdef ZSTD_LZMACOMPRESS
384 if (!strcmp(argument, "--format=lzma")) { suffix = LZMA_EXTENSION; FIO_setCompressionType(FIO_lzmaCompression); continue; }
385 if (!strcmp(argument, "--format=xz")) { suffix = XZ_EXTENSION; FIO_setCompressionType(FIO_xzCompression); continue; }
386#endif
Yann Collet743b33f2016-12-02 15:18:57 -0800387
388 /* long commands with arguments */
Yann Colletc1c040e2017-03-01 16:49:20 -0800389#ifndef ZSTD_NODICT
Nick Terrelldf8415c2016-12-31 21:08:24 -0800390 if (longCommandWArg(&argument, "--cover=")) {
391 cover=1; if (!parseCoverParameters(argument, &coverParams)) CLEAN_RETURN(badusage(programName));
392 continue;
393 }
394 if (longCommandWArg(&argument, "--optimize-cover")) {
395 cover=2;
396 /* Allow optional arguments following an = */
397 if (*argument == 0) { memset(&coverParams, 0, sizeof(coverParams)); }
398 else if (*argument++ != '=') { CLEAN_RETURN(badusage(programName)); }
399 else if (!parseCoverParameters(argument, &coverParams)) { CLEAN_RETURN(badusage(programName)); }
400 continue;
401 }
402#endif
Yann Collet743b33f2016-12-02 15:18:57 -0800403 if (longCommandWArg(&argument, "--memlimit=")) { memLimit = readU32FromChar(&argument); continue; }
404 if (longCommandWArg(&argument, "--memory=")) { memLimit = readU32FromChar(&argument); continue; }
405 if (longCommandWArg(&argument, "--memlimit-decompress=")) { memLimit = readU32FromChar(&argument); continue; }
Yann Collet6be23372017-01-30 11:17:26 -0800406 if (longCommandWArg(&argument, "--block-size=")) { blockSize = readU32FromChar(&argument); continue; }
Przemyslaw Skibinski671f28d2016-12-13 12:18:07 +0100407 if (longCommandWArg(&argument, "--zstd=")) { if (!parseCompressionParameters(argument, &compressionParams)) CLEAN_RETURN(badusage(programName)); continue; }
Yann Collet743b33f2016-12-02 15:18:57 -0800408 /* fall-through, will trigger bad_usage() later on */
409 }
410
411 argument++;
Yann Colletf9cac7a2016-07-04 18:16:16 +0200412 while (argument[0]!=0) {
Yann Collet27b5ac62016-09-21 14:20:56 +0200413 if (lastCommand) {
414 DISPLAY("error : command must be followed by argument \n");
Przemyslaw Skibinski684858e2017-02-21 18:17:24 +0100415 CLEAN_RETURN(1);
Yann Collet27b5ac62016-09-21 14:20:56 +0200416 }
Yann Colletc8431422016-09-01 15:05:57 -0700417#ifndef ZSTD_NOCOMPRESS
Yann Colletf9cac7a2016-07-04 18:16:16 +0200418 /* compression Level */
419 if ((*argument>='0') && (*argument<='9')) {
Yann Colletfe0590f2016-08-12 18:04:15 +0200420 dictCLevel = cLevel = readU32FromChar(&argument);
Yann Colletf9cac7a2016-07-04 18:16:16 +0200421 continue;
422 }
Yann Colletc8431422016-09-01 15:05:57 -0700423#endif
Yann Colletfcf20872016-05-29 05:16:05 +0200424
Yann Colletf9cac7a2016-07-04 18:16:16 +0200425 switch(argument[0])
426 {
427 /* Display help */
Sean Purcell042ba122017-03-23 11:13:52 -0700428 case 'V': g_displayOut=stdout; DISPLAY(WELCOME_MESSAGE); CLEAN_RETURN(0); /* Version Only */
Yann Colletf9cac7a2016-07-04 18:16:16 +0200429 case 'H':
Sean Purcell042ba122017-03-23 11:13:52 -0700430 case 'h': g_displayOut=stdout; CLEAN_RETURN(usage_advanced(programName));
Yann Colletfcf20872016-05-29 05:16:05 +0200431
Yann Collet22de81e2016-10-28 13:58:31 -0700432 /* Compress */
433 case 'z': operation=zom_compress; argument++; break;
434
Yann Colletf9cac7a2016-07-04 18:16:16 +0200435 /* Decoding */
Yann Collet2a826e52016-12-06 17:56:20 -0800436 case 'd':
437#ifndef ZSTD_NOBENCH
Yann Colletab7a5792016-12-28 16:11:09 +0100438 if (operation==zom_bench) { BMK_setDecodeOnlyMode(1); argument++; break; } /* benchmark decode (hidden option) */
Yann Collet2a826e52016-12-06 17:56:20 -0800439#endif
Yann Colletd9465012016-12-06 16:49:23 -0800440 operation=zom_decompress; argument++; break;
Yann Colletfcf20872016-05-29 05:16:05 +0200441
Yann Colletf9cac7a2016-07-04 18:16:16 +0200442 /* Force stdout, even if stdout==console */
Yann Colletfe0590f2016-08-12 18:04:15 +0200443 case 'c': forceStdout=1; outFileName=stdoutmark; argument++; break;
Yann Colletfcf20872016-05-29 05:16:05 +0200444
Yann Colletf9cac7a2016-07-04 18:16:16 +0200445 /* Use file content as dictionary */
Yann Collet27b5ac62016-09-21 14:20:56 +0200446 case 'D': nextEntryIsDictionary = 1; lastCommand = 1; argument++; break;
Yann Colletfcf20872016-05-29 05:16:05 +0200447
Yann Colletf9cac7a2016-07-04 18:16:16 +0200448 /* Overwrite */
Sean Purcell680e4e02017-03-23 11:52:09 -0700449 case 'f': FIO_overwriteMode(); forceStdout=1; followLinks=1; argument++; break;
Yann Colletfcf20872016-05-29 05:16:05 +0200450
Yann Colletf9cac7a2016-07-04 18:16:16 +0200451 /* Verbose mode */
Sean Purcell042ba122017-03-23 11:13:52 -0700452 case 'v': g_displayLevel++; argument++; break;
Yann Colletfcf20872016-05-29 05:16:05 +0200453
Yann Colletf9cac7a2016-07-04 18:16:16 +0200454 /* Quiet mode */
Sean Purcell042ba122017-03-23 11:13:52 -0700455 case 'q': g_displayLevel--; argument++; break;
Yann Collet2c4acda2016-06-02 17:05:50 +0200456
Yann Colletf9cac7a2016-07-04 18:16:16 +0200457 /* keep source file (default); for gzip/xz compatibility */
458 case 'k': FIO_setRemoveSrcFile(0); argument++; break;
Yann Colletfcf20872016-05-29 05:16:05 +0200459
Yann Colletf9cac7a2016-07-04 18:16:16 +0200460 /* Checksum */
461 case 'C': argument++; FIO_setChecksumFlag(2); break;
Yann Colletfcf20872016-05-29 05:16:05 +0200462
Yann Colletf9cac7a2016-07-04 18:16:16 +0200463 /* test compressed file */
Yann Collet22de81e2016-10-28 13:58:31 -0700464 case 't': operation=zom_test; argument++; break;
Yann Colletfcf20872016-05-29 05:16:05 +0200465
Yann Collet2cac5b32016-07-13 14:15:08 +0200466 /* destination file name */
Yann Collet27b5ac62016-09-21 14:20:56 +0200467 case 'o': nextArgumentIsOutFileName=1; lastCommand=1; argument++; break;
Yann Colletfcf20872016-05-29 05:16:05 +0200468
Yann Colletd4cda272016-10-14 13:13:13 -0700469 /* limit decompression memory */
470 case 'M':
471 argument++;
472 memLimit = readU32FromChar(&argument);
473 break;
474
Yann Colletc4cc9bf2016-09-13 17:50:08 +0200475#ifdef UTIL_HAS_CREATEFILELIST
Yann Colletf9cac7a2016-07-04 18:16:16 +0200476 /* recursive */
477 case 'r': recursive=1; argument++; break;
Yann Colletc4cc9bf2016-09-13 17:50:08 +0200478#endif
Yann Colletf9cac7a2016-07-04 18:16:16 +0200479
Yann Colletc8431422016-09-01 15:05:57 -0700480#ifndef ZSTD_NOBENCH
Yann Colletf9cac7a2016-07-04 18:16:16 +0200481 /* Benchmark */
Yann Collet500014a2017-01-19 16:59:56 -0800482 case 'b':
483 operation=zom_bench;
484 argument++;
485 break;
Yann Colletf9cac7a2016-07-04 18:16:16 +0200486
487 /* range bench (benchmark only) */
488 case 'e':
Yann Collet500014a2017-01-19 16:59:56 -0800489 /* compression Level */
490 argument++;
491 cLevelLast = readU32FromChar(&argument);
492 break;
Yann Colletf9cac7a2016-07-04 18:16:16 +0200493
494 /* Modify Nb Iterations (benchmark only) */
495 case 'i':
Yann Colletfcf20872016-05-29 05:16:05 +0200496 argument++;
Yann Collet500014a2017-01-19 16:59:56 -0800497 bench_nbSeconds = readU32FromChar(&argument);
Yann Colletfcf20872016-05-29 05:16:05 +0200498 break;
499
Yann Colletf9cac7a2016-07-04 18:16:16 +0200500 /* cut input into blocks (benchmark only) */
501 case 'B':
502 argument++;
Yann Collet500014a2017-01-19 16:59:56 -0800503 blockSize = readU32FromChar(&argument);
Yann Colletf9cac7a2016-07-04 18:16:16 +0200504 break;
Yann Collet74745262017-01-02 02:05:45 +0100505
Yann Collet500014a2017-01-19 16:59:56 -0800506#endif /* ZSTD_NOBENCH */
507
Yann Collet74745262017-01-02 02:05:45 +0100508 /* nb of threads (hidden option) */
509 case 'T':
510 argument++;
Yann Collet500014a2017-01-19 16:59:56 -0800511 nbThreads = readU32FromChar(&argument);
Yann Collet74745262017-01-02 02:05:45 +0100512 break;
Yann Colletf9cac7a2016-07-04 18:16:16 +0200513
514 /* Dictionary Selection level */
515 case 's':
516 argument++;
517 dictSelect = readU32FromChar(&argument);
518 break;
519
520 /* Pause at the end (-p) or set an additional param (-p#) (hidden option) */
521 case 'p': argument++;
Yann Colletc8431422016-09-01 15:05:57 -0700522#ifndef ZSTD_NOBENCH
Yann Colletf9cac7a2016-07-04 18:16:16 +0200523 if ((*argument>='0') && (*argument<='9')) {
524 BMK_setAdditionalParam(readU32FromChar(&argument));
525 } else
Yann Colletc8431422016-09-01 15:05:57 -0700526#endif
Yann Colletf9cac7a2016-07-04 18:16:16 +0200527 main_pause=1;
528 break;
529 /* unknown command */
530 default : CLEAN_RETURN(badusage(programName));
Yann Colletfcf20872016-05-29 05:16:05 +0200531 }
Yann Colletfcf20872016-05-29 05:16:05 +0200532 }
Yann Colletf9cac7a2016-07-04 18:16:16 +0200533 continue;
534 } /* if (argument[0]=='-') */
535
536 if (nextArgumentIsMaxDict) {
537 nextArgumentIsMaxDict = 0;
Yann Collet27b5ac62016-09-21 14:20:56 +0200538 lastCommand = 0;
Yann Colletf9cac7a2016-07-04 18:16:16 +0200539 maxDictSize = readU32FromChar(&argument);
Yann Colletf9cac7a2016-07-04 18:16:16 +0200540 continue;
Yann Colletfcf20872016-05-29 05:16:05 +0200541 }
Yann Colletf9cac7a2016-07-04 18:16:16 +0200542
543 if (nextArgumentIsDictID) {
544 nextArgumentIsDictID = 0;
Yann Collet27b5ac62016-09-21 14:20:56 +0200545 lastCommand = 0;
Yann Colletf9cac7a2016-07-04 18:16:16 +0200546 dictID = readU32FromChar(&argument);
547 continue;
548 }
549
550 } /* if (nextArgumentIsAFile==0) */
Yann Colletfcf20872016-05-29 05:16:05 +0200551
552 if (nextEntryIsDictionary) {
553 nextEntryIsDictionary = 0;
Yann Collet27b5ac62016-09-21 14:20:56 +0200554 lastCommand = 0;
Yann Colletfcf20872016-05-29 05:16:05 +0200555 dictFileName = argument;
556 continue;
557 }
558
559 if (nextArgumentIsOutFileName) {
560 nextArgumentIsOutFileName = 0;
Yann Collet27b5ac62016-09-21 14:20:56 +0200561 lastCommand = 0;
Yann Colletfcf20872016-05-29 05:16:05 +0200562 outFileName = argument;
563 if (!strcmp(outFileName, "-")) outFileName = stdoutmark;
564 continue;
565 }
566
Yann Colletfcf20872016-05-29 05:16:05 +0200567 /* add filename to list */
568 filenameTable[filenameIdx++] = argument;
569 }
570
Przemyslaw Skibinski684858e2017-02-21 18:17:24 +0100571 if (lastCommand) { DISPLAY("error : command must be followed by argument \n"); CLEAN_RETURN(1); } /* forgotten argument */
Yann Collet714464f2016-09-21 16:05:03 +0200572
Yann Colletfcf20872016-05-29 05:16:05 +0200573 /* Welcome message (if verbose) */
574 DISPLAYLEVEL(3, WELCOME_MESSAGE);
Przemyslaw Skibinskib0f36632016-12-16 15:41:18 +0100575#ifdef _POSIX_C_SOURCE
576 DISPLAYLEVEL(4, "_POSIX_C_SOURCE defined: %ldL\n", (long) _POSIX_C_SOURCE);
577#endif
578#ifdef _POSIX_VERSION
579 DISPLAYLEVEL(4, "_POSIX_VERSION defined: %ldL\n", (long) _POSIX_VERSION);
580#endif
581#ifdef PLATFORM_POSIX_VERSION
582 DISPLAYLEVEL(4, "PLATFORM_POSIX_VERSION defined: %ldL\n", (long) PLATFORM_POSIX_VERSION);
583#endif
Yann Colletfcf20872016-05-29 05:16:05 +0200584
Sean Purcell680e4e02017-03-23 11:52:09 -0700585
Sean Purcelldee08ca2017-03-23 12:09:35 -0700586 g_utilDisplayLevel = g_displayLevel;
Sean Purcell680e4e02017-03-23 11:52:09 -0700587 if (!followLinks) {
588 unsigned u;
589 for (u=0, fileNamesNb=0; u<filenameIdx; u++) {
590 if (UTIL_isLink(filenameTable[u])) {
591 DISPLAYLEVEL(2, "Warning : %s is a symbolic link, ignoring\n", filenameTable[u]);
592 } else {
593 filenameTable[fileNamesNb++] = filenameTable[u];
594 }
595 }
596 filenameIdx = fileNamesNb;
597 }
Yann Colletfcf20872016-05-29 05:16:05 +0200598#ifdef UTIL_HAS_CREATEFILELIST
Yann Collet0977f7e2016-09-21 12:24:43 +0200599 if (recursive) { /* at this stage, filenameTable is a list of paths, which can contain both files and directories */
Sean Purcell680e4e02017-03-23 11:52:09 -0700600 extendedFileList = UTIL_createFileList(filenameTable, filenameIdx, &fileNamesBuf, &fileNamesNb, followLinks);
Yann Collet0977f7e2016-09-21 12:24:43 +0200601 if (extendedFileList) {
Yann Collet415251c2016-08-01 14:26:49 +0200602 unsigned u;
Yann Collet0977f7e2016-09-21 12:24:43 +0200603 for (u=0; u<fileNamesNb; u++) DISPLAYLEVEL(4, "%u %s\n", u, extendedFileList[u]);
Yann Colletfcf20872016-05-29 05:16:05 +0200604 free((void*)filenameTable);
Yann Collet0977f7e2016-09-21 12:24:43 +0200605 filenameTable = extendedFileList;
Yann Colletfcf20872016-05-29 05:16:05 +0200606 filenameIdx = fileNamesNb;
607 }
608 }
609#endif
610
611 /* Check if benchmark is selected */
Yann Collet22de81e2016-10-28 13:58:31 -0700612 if (operation==zom_bench) {
Yann Colletfcf20872016-05-29 05:16:05 +0200613#ifndef ZSTD_NOBENCH
Sean Purcell042ba122017-03-23 11:13:52 -0700614 BMK_setNotificationLevel(g_displayLevel);
Yann Collet500014a2017-01-19 16:59:56 -0800615 BMK_setBlockSize(blockSize);
616 BMK_setNbThreads(nbThreads);
617 BMK_setNbSeconds(bench_nbSeconds);
Przemyslaw Skibinskid05014c2017-02-07 16:48:01 +0100618 BMK_benchFiles(filenameTable, filenameIdx, dictFileName, cLevel, cLevelLast, &compressionParams, setRealTimePrio);
Yann Colletfcf20872016-05-29 05:16:05 +0200619#endif
Yann Collet3dc85ba2017-02-02 16:19:09 -0800620 (void)bench_nbSeconds;
Yann Colletfcf20872016-05-29 05:16:05 +0200621 goto _end;
622 }
623
624 /* Check if dictionary builder is selected */
Yann Collet22de81e2016-10-28 13:58:31 -0700625 if (operation==zom_train) {
Yann Colletfcf20872016-05-29 05:16:05 +0200626#ifndef ZSTD_NODICT
Nick Terrelldf8415c2016-12-31 21:08:24 -0800627 if (cover) {
Nick Terrell2fe91262017-01-27 11:56:02 -0800628 coverParams.nbThreads = nbThreads;
Nick Terrelldf8415c2016-12-31 21:08:24 -0800629 coverParams.compressionLevel = dictCLevel;
Sean Purcell042ba122017-03-23 11:13:52 -0700630 coverParams.notificationLevel = g_displayLevel;
Nick Terrelldf8415c2016-12-31 21:08:24 -0800631 coverParams.dictID = dictID;
Yann Colletf332ece2017-03-23 16:24:02 -0700632 operationResult = DiB_trainFromFiles(outFileName, maxDictSize, filenameTable, filenameIdx, NULL, &coverParams, cover - 1);
Nick Terrelldf8415c2016-12-31 21:08:24 -0800633 } else {
634 ZDICT_params_t dictParams;
635 memset(&dictParams, 0, sizeof(dictParams));
636 dictParams.compressionLevel = dictCLevel;
637 dictParams.selectivityLevel = dictSelect;
Sean Purcell042ba122017-03-23 11:13:52 -0700638 dictParams.notificationLevel = g_displayLevel;
Nick Terrelldf8415c2016-12-31 21:08:24 -0800639 dictParams.dictID = dictID;
Yann Colletf332ece2017-03-23 16:24:02 -0700640 operationResult = DiB_trainFromFiles(outFileName, maxDictSize, filenameTable, filenameIdx, &dictParams, NULL, 0);
Nick Terrelldf8415c2016-12-31 21:08:24 -0800641 }
Yann Colletfcf20872016-05-29 05:16:05 +0200642#endif
643 goto _end;
644 }
645
646 /* No input filename ==> use stdin and stdout */
Yann Collet87c18b22016-08-26 01:43:47 +0200647 filenameIdx += !filenameIdx; /* filenameTable[0] is stdin by default */
648 if (!strcmp(filenameTable[0], stdinmark) && !outFileName) outFileName = stdoutmark; /* when input is stdin, default output is stdout */
Yann Colletfcf20872016-05-29 05:16:05 +0200649
650 /* Check if input/output defined as console; trigger an error in this case */
651 if (!strcmp(filenameTable[0], stdinmark) && IS_CONSOLE(stdin) ) CLEAN_RETURN(badusage(programName));
Sean Purcellb8e52d32017-03-16 16:06:03 -0700652 if (outFileName && !strcmp(outFileName, stdoutmark) && IS_CONSOLE(stdout) && !strcmp(filenameTable[0], stdinmark) && !forceStdout && operation!=zom_decompress)
Yann Colletfcf20872016-05-29 05:16:05 +0200653 CLEAN_RETURN(badusage(programName));
654
655 /* user-selected output filename, only possible with a single file */
656 if (outFileName && strcmp(outFileName,stdoutmark) && strcmp(outFileName,nulmark) && (filenameIdx>1)) {
657 DISPLAY("Too many files (%u) on the command line. \n", filenameIdx);
658 CLEAN_RETURN(filenameIdx);
659 }
660
inikep23cec872016-10-05 11:56:22 +0200661#ifndef ZSTD_NOCOMPRESS
Yann Colletfe0590f2016-08-12 18:04:15 +0200662 /* check compression level limits */
663 { int const maxCLevel = ultra ? ZSTD_maxCLevel() : ZSTDCLI_CLEVEL_MAX;
664 if (cLevel > maxCLevel) {
665 DISPLAYLEVEL(2, "Warning : compression level higher than max, reduced to %i \n", maxCLevel);
666 cLevel = maxCLevel;
667 } }
inikep23cec872016-10-05 11:56:22 +0200668#endif
Yann Colletfe0590f2016-08-12 18:04:15 +0200669
Yann Colletf22adae2017-01-19 13:46:30 -0800670 /* No status message in pipe mode (stdin - stdout) or multi-files mode */
Sean Purcell042ba122017-03-23 11:13:52 -0700671 if (!strcmp(filenameTable[0], stdinmark) && outFileName && !strcmp(outFileName,stdoutmark) && (g_displayLevel==2)) g_displayLevel=1;
672 if ((filenameIdx>1) & (g_displayLevel==2)) g_displayLevel=1;
Yann Colletfcf20872016-05-29 05:16:05 +0200673
674 /* IO Stream/File */
Sean Purcell042ba122017-03-23 11:13:52 -0700675 FIO_setNotificationLevel(g_displayLevel);
Yann Collet22de81e2016-10-28 13:58:31 -0700676 if (operation==zom_compress) {
Yann Collet0977f7e2016-09-21 12:24:43 +0200677#ifndef ZSTD_NOCOMPRESS
Yann Collet500014a2017-01-19 16:59:56 -0800678 FIO_setNbThreads(nbThreads);
Yann Collet512cbe82017-01-24 17:02:26 -0800679 FIO_setBlockSize((U32)blockSize);
Yann Collet8d8513f2017-01-30 14:37:08 -0800680 if (g_overlapLog!=OVERLAP_LOG_DEFAULT) FIO_setOverlapLog(g_overlapLog);
Yann Collet993060e2016-09-21 16:46:08 +0200681 if ((filenameIdx==1) && outFileName)
Przemyslaw Skibinski8349d672016-12-13 13:24:59 +0100682 operationResult = FIO_compressFilename(outFileName, filenameTable[0], dictFileName, cLevel, &compressionParams);
Yann Colletfcf20872016-05-29 05:16:05 +0200683 else
Przemyslaw Skibinskicb563062017-02-08 17:37:14 +0100684 operationResult = FIO_compressMultipleFilenames(filenameTable, filenameIdx, outFileName ? outFileName : suffix, dictFileName, cLevel, &compressionParams);
Yann Collet0977f7e2016-09-21 12:24:43 +0200685#else
686 DISPLAY("Compression not supported\n");
Yann Colletfcf20872016-05-29 05:16:05 +0200687#endif
Yann Collet22de81e2016-10-28 13:58:31 -0700688 } else { /* decompression or test */
Yann Colletfcf20872016-05-29 05:16:05 +0200689#ifndef ZSTD_NODECOMPRESS
Yann Collet22de81e2016-10-28 13:58:31 -0700690 if (operation==zom_test) { outFileName=nulmark; FIO_setRemoveSrcFile(0); } /* test mode */
Yann Colletd4cda272016-10-14 13:13:13 -0700691 FIO_setMemLimit(memLimit);
Yann Colletfcf20872016-05-29 05:16:05 +0200692 if (filenameIdx==1 && outFileName)
693 operationResult = FIO_decompressFilename(outFileName, filenameTable[0], dictFileName);
694 else
695 operationResult = FIO_decompressMultipleFilenames(filenameTable, filenameIdx, outFileName ? outFileName : ZSTD_EXTENSION, dictFileName);
696#else
697 DISPLAY("Decompression not supported\n");
698#endif
699 }
700
701_end:
702 if (main_pause) waitEnter();
Yann Colletfcf20872016-05-29 05:16:05 +0200703#ifdef UTIL_HAS_CREATEFILELIST
Yann Collet0977f7e2016-09-21 12:24:43 +0200704 if (extendedFileList)
705 UTIL_freeFileList(extendedFileList, fileNamesBuf);
Yann Colletfcf20872016-05-29 05:16:05 +0200706 else
707#endif
708 free((void*)filenameTable);
709 return operationResult;
710}