blob: 3f3c5cd51e33393787bfbac092eef629698f69d1 [file] [log] [blame]
Yann Collet4856a002015-01-24 01:58:16 +01001/*
2 zstdcli - Command Line Interface (cli) for zstd
Yann Collet44886612016-02-11 04:17:50 +01003 Copyright (C) Yann Collet 2014-2016
Yann Collet4856a002015-01-24 01:58:16 +01004
5 GPL v2 License
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
21 You can contact the author at :
Yann Collet44886612016-02-11 04:17:50 +010022 - zstd homepage : http://www.zstd.net/
Yann Collet4856a002015-01-24 01:58:16 +010023*/
24/*
25 Note : this is user program.
26 It is not part of zstd compression library.
27 The license of this compression CLI program is GPLv2.
28 The license of zstd library is BSD.
29*/
30
31
Yann Collet44886612016-02-11 04:17:50 +010032/*-************************************
Yann Collet4856a002015-01-24 01:58:16 +010033* Compiler Options
34**************************************/
35#define _CRT_SECURE_NO_WARNINGS /* Visual : removes warning from strcpy */
36#define _POSIX_SOURCE 1 /* triggers fileno() within <stdio.h> on unix */
37
38
Yann Collet44886612016-02-11 04:17:50 +010039/*-************************************
Yann Collet4856a002015-01-24 01:58:16 +010040* Includes
41**************************************/
42#include <stdio.h> /* fprintf, getchar */
43#include <stdlib.h> /* exit, calloc, free */
44#include <string.h> /* strcmp, strlen */
Yann Collet4856a002015-01-24 01:58:16 +010045#include "fileio.h"
Yann Collet7a3ab582015-12-15 11:25:12 +010046#ifndef ZSTD_NOBENCH
47# include "bench.h" /* BMK_benchFiles, BMK_SetNbIterations */
48#endif
Yann Colletdeb078b2015-12-17 20:30:14 +010049#include "zstd.h" /* ZSTD version numbers */
Yann Collet4856a002015-01-24 01:58:16 +010050
51
Yann Collet44886612016-02-11 04:17:50 +010052/*-************************************
Yann Collet4856a002015-01-24 01:58:16 +010053* OS-specific Includes
54**************************************/
55#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__)
Yann Collet7a3ab582015-12-15 11:25:12 +010056# include <fcntl.h> /* _O_BINARY */
57# include <io.h> /* _setmode, _isatty */
Yann Collet4856a002015-01-24 01:58:16 +010058# ifdef __MINGW32__
Yann Collete1e6f7d2015-01-25 15:50:24 +010059 /* int _fileno(FILE *stream); // seems no longer useful // MINGW somehow forgets to include this windows declaration into <stdio.h> */
Yann Collet4856a002015-01-24 01:58:16 +010060# endif
61# define SET_BINARY_MODE(file) _setmode(_fileno(file), _O_BINARY)
62# define IS_CONSOLE(stdStream) _isatty(_fileno(stdStream))
63#else
Yann Collet7a3ab582015-12-15 11:25:12 +010064# include <unistd.h> /* isatty */
Yann Collet4856a002015-01-24 01:58:16 +010065# define SET_BINARY_MODE(file)
66# define IS_CONSOLE(stdStream) isatty(fileno(stdStream))
67#endif
68
69
Yann Collet44886612016-02-11 04:17:50 +010070/*-************************************
Yann Collete1e6f7d2015-01-25 15:50:24 +010071* Constants
72**************************************/
Yann Collet4856a002015-01-24 01:58:16 +010073#define COMPRESSOR_NAME "zstd command line interface"
74#ifndef ZSTD_VERSION
Yann Colletdeb078b2015-12-17 20:30:14 +010075# define QUOTE(str) #str
76# define EXPAND_AND_QUOTE(str) QUOTE(str)
77# define ZSTD_VERSION "v" EXPAND_AND_QUOTE(ZSTD_VERSION_MAJOR) "." EXPAND_AND_QUOTE(ZSTD_VERSION_MINOR) "." EXPAND_AND_QUOTE(ZSTD_VERSION_RELEASE)
Yann Collet4856a002015-01-24 01:58:16 +010078#endif
79#define AUTHOR "Yann Collet"
Yann Collet521b0102016-02-08 01:27:59 +010080#define WELCOME_MESSAGE "*** %s %i-bits %s, by %s ***\n", COMPRESSOR_NAME, (int)(sizeof(void*)*8), ZSTD_VERSION, AUTHOR
Yann Collet4856a002015-01-24 01:58:16 +010081#define ZSTD_EXTENSION ".zst"
82#define ZSTD_CAT "zstdcat"
Johan Förberg273d0492015-03-24 20:15:56 +010083#define ZSTD_UNZSTD "unzstd"
Yann Collet4856a002015-01-24 01:58:16 +010084
85#define KB *(1 <<10)
86#define MB *(1 <<20)
87#define GB *(1U<<30)
88
89
Yann Collet44886612016-02-11 04:17:50 +010090/*-************************************
Yann Collet4856a002015-01-24 01:58:16 +010091* Display Macros
92**************************************/
Yann Colletf44b2b02015-08-25 23:32:45 +010093#define DISPLAY(...) fprintf(displayOut, __VA_ARGS__)
Yann Collet4856a002015-01-24 01:58:16 +010094#define DISPLAYLEVEL(l, ...) if (displayLevel>=l) { DISPLAY(__VA_ARGS__); }
Yann Colletf44b2b02015-08-25 23:32:45 +010095static FILE* displayOut;
Yann Collet44886612016-02-11 04:17:50 +010096static unsigned displayLevel = 2; /* 0 : no display, 1: errors, 2 : + result + interaction + warnings, 3 : + progression, 4 : + information */
Yann Collet4856a002015-01-24 01:58:16 +010097
98
Yann Collet44886612016-02-11 04:17:50 +010099/*-************************************
Yann Collet4856a002015-01-24 01:58:16 +0100100* Exceptions
101**************************************/
102#define DEBUG 0
103#define DEBUGOUTPUT(...) if (DEBUG) DISPLAY(__VA_ARGS__);
104#define EXM_THROW(error, ...) \
105{ \
106 DEBUGOUTPUT("Error defined at %s, line %i : \n", __FILE__, __LINE__); \
107 DISPLAYLEVEL(1, "Error %i : ", error); \
108 DISPLAYLEVEL(1, __VA_ARGS__); \
109 DISPLAYLEVEL(1, "\n"); \
110 exit(error); \
111}
112
113
Yann Collet44886612016-02-11 04:17:50 +0100114/*-************************************
Yann Collet4856a002015-01-24 01:58:16 +0100115* Command Line
116**************************************/
117static int usage(const char* programName)
118{
119 DISPLAY( "Usage :\n");
120 DISPLAY( " %s [arg] [input] [output]\n", programName);
121 DISPLAY( "\n");
122 DISPLAY( "input : a filename\n");
123 DISPLAY( " with no FILE, or when FILE is - , read standard input\n");
124 DISPLAY( "Arguments :\n");
Yann Colletf6f3d752015-12-13 13:35:21 +0100125 DISPLAY( " -# : # compression level (1-19, default:1) \n");
Yann Collet45ff4302016-02-05 15:24:57 +0100126 DISPLAY( " -d : decompression \n");
127 DISPLAY( " -D file: use `file` as Dictionary \n");
Yann Collet4856a002015-01-24 01:58:16 +0100128 DISPLAY( " -f : overwrite output without prompting \n");
129 DISPLAY( " -h/-H : display help/long help and exit\n");
130 return 0;
131}
132
133static int usage_advanced(const char* programName)
134{
135 DISPLAY(WELCOME_MESSAGE);
136 usage(programName);
137 DISPLAY( "\n");
138 DISPLAY( "Advanced arguments :\n");
139 DISPLAY( " -V : display Version number and exit\n");
140 DISPLAY( " -v : verbose mode\n");
141 DISPLAY( " -q : suppress warnings; specify twice to suppress errors too\n");
Yann Collet31683c02015-12-18 01:26:48 +0100142 DISPLAY( " -m : multiple input filenames mode \n");
Yann Collet4856a002015-01-24 01:58:16 +0100143 DISPLAY( " -c : force write to standard output, even if it is the console\n");
Yann Collet28e7cef2015-12-03 12:11:30 +0100144#ifndef ZSTD_NOBENCH
Yann Collet4856a002015-01-24 01:58:16 +0100145 DISPLAY( "Benchmark arguments :\n");
Yann Colletc776c462015-10-29 19:10:54 +0100146 DISPLAY( " -b# : benchmark file(s), using # compression level (default : 1) \n");
Yann Collet1c00dc32015-10-21 08:22:25 +0100147 DISPLAY( " -B# : cut file into independent blocks of size # (default : no block)\n");
Yann Colletf44b2b02015-08-25 23:32:45 +0100148 DISPLAY( " -i# : iteration loops [1-9](default : 3)\n");
Yann Colletc776c462015-10-29 19:10:54 +0100149 DISPLAY( " -r# : test all compression levels from 1 to # (default : disabled)\n");
Yann Collet28e7cef2015-12-03 12:11:30 +0100150#endif
Yann Collet4856a002015-01-24 01:58:16 +0100151 return 0;
152}
153
154static int badusage(const char* programName)
155{
156 DISPLAYLEVEL(1, "Incorrect parameters\n");
157 if (displayLevel >= 1) usage(programName);
158 return 1;
159}
160
161
162static void waitEnter(void)
163{
Yann Colletb5e06dc2015-07-04 23:20:56 -0800164 int unused;
Yann Collet4856a002015-01-24 01:58:16 +0100165 DISPLAY("Press enter to continue...\n");
Yann Colletb5e06dc2015-07-04 23:20:56 -0800166 unused = getchar();
167 (void)unused;
Yann Collet4856a002015-01-24 01:58:16 +0100168}
169
170
Yann Collet7f6e91f2015-11-11 14:39:50 +0100171int main(int argCount, const char** argv)
Yann Collet4856a002015-01-24 01:58:16 +0100172{
173 int i,
174 bench=0,
175 decode=0,
176 forceStdout=0,
Yann Colletf6f3d752015-12-13 13:35:21 +0100177 main_pause=0,
Yann Collet4f137032015-12-17 02:23:58 +0100178 nextEntryIsDictionary=0,
179 multiple=0,
180 operationResult=0;
Yann Collet44fe9912015-10-29 22:02:40 +0100181 unsigned cLevel = 1;
Yann Collet324a3e22015-12-18 03:19:27 +0100182 const char** filenameTable = (const char**)malloc(argCount * sizeof(const char*)); /* argCount >= 1 */
Yann Collet17d188f2015-12-18 02:14:46 +0100183 unsigned filenameIdx = 0;
Yann Collet4856a002015-01-24 01:58:16 +0100184 const char* programName = argv[0];
Yann Collet4856a002015-01-24 01:58:16 +0100185 const char* outFileName = NULL;
Yann Colletf6f3d752015-12-13 13:35:21 +0100186 const char* dictFileName = NULL;
Yann Collet4856a002015-01-24 01:58:16 +0100187 char* dynNameSpace = NULL;
Yann Collet50c5cdb2015-11-04 20:35:33 +0100188 const char extension[] = ZSTD_EXTENSION;
Yann Collet28e7cef2015-12-03 12:11:30 +0100189 int rangeBench = 1;
Yann Collet4856a002015-01-24 01:58:16 +0100190
Yann Collet28e7cef2015-12-03 12:11:30 +0100191 /* init */
Yann Collet17d188f2015-12-18 02:14:46 +0100192 (void)rangeBench; /* not used when ZSTD_NOBENCH set */
Yann Collet17d188f2015-12-18 02:14:46 +0100193 if (filenameTable==NULL) { DISPLAY("not enough memory\n"); exit(1); }
Yann Colletf44b2b02015-08-25 23:32:45 +0100194 displayOut = stderr;
Yann Collet17d188f2015-12-18 02:14:46 +0100195 /* Pick out program name from path. Don't rely on stdlib because of conflicting behavior */
Yann Colletd062f132015-12-01 01:31:17 +0100196 for (i = (int)strlen(programName); i > 0; i--) { if (programName[i] == '/') { i++; break; } }
Johan Förberg273d0492015-03-24 20:15:56 +0100197 programName += i;
198
Yann Colletd062f132015-12-01 01:31:17 +0100199 /* preset behaviors */
200 if (!strcmp(programName, ZSTD_UNZSTD)) decode=1;
Yann Collet4856a002015-01-24 01:58:16 +0100201 if (!strcmp(programName, ZSTD_CAT)) { decode=1; forceStdout=1; displayLevel=1; outFileName=stdoutmark; }
202
Yann Colletf44b2b02015-08-25 23:32:45 +0100203 /* command switches */
Yann Collet44886612016-02-11 04:17:50 +0100204 for(i=1; i<argCount; i++) {
Yann Collet7f6e91f2015-11-11 14:39:50 +0100205 const char* argument = argv[i];
Yann Colletf44b2b02015-08-25 23:32:45 +0100206 if(!argument) continue; /* Protection if argument empty */
207
208 /* long commands (--long-word) */
209 if (!strcmp(argument, "--version")) { displayOut=stdout; DISPLAY(WELCOME_MESSAGE); return 0; }
210 if (!strcmp(argument, "--help")) { displayOut=stdout; return usage_advanced(programName); }
Yann Colletdeb078b2015-12-17 20:30:14 +0100211 if (!strcmp(argument, "--multiple")) { multiple=1; continue; }
Yann Collet50b6f942015-08-26 10:32:17 +0100212 if (!strcmp(argument, "--verbose")) { displayLevel=4; continue; }
Yann Colletdeb078b2015-12-17 20:30:14 +0100213 if (!strcmp(argument, "--quiet")) { displayLevel--; continue; }
Yann Collet4856a002015-01-24 01:58:16 +0100214
215 /* Decode commands (note : aggregated commands are allowed) */
Yann Collet44886612016-02-11 04:17:50 +0100216 if (argument[0]=='-') {
Yann Collet4856a002015-01-24 01:58:16 +0100217 /* '-' means stdin/stdout */
Yann Collet44886612016-02-11 04:17:50 +0100218 if (argument[1]==0) {
Yann Collet17d188f2015-12-18 02:14:46 +0100219 if (!filenameIdx) { filenameIdx=1, filenameTable[0]=stdinmark; continue; }
220 outFileName=stdoutmark; continue;
Yann Collet4856a002015-01-24 01:58:16 +0100221 }
222
223 argument++;
224
225 while (argument[0]!=0)
226 {
Yann Colletf3eca252015-10-22 15:31:46 +0100227 /* compression Level */
228 if ((*argument>='0') && (*argument<='9'))
229 {
230 cLevel = 0;
231 while ((*argument >= '0') && (*argument <= '9'))
232 {
233 cLevel *= 10;
234 cLevel += *argument - '0';
235 argument++;
236 }
237 continue;
238 }
239
Yann Collet4856a002015-01-24 01:58:16 +0100240 switch(argument[0])
241 {
242 /* Display help */
Yann Colletf44b2b02015-08-25 23:32:45 +0100243 case 'V': displayOut=stdout; DISPLAY(WELCOME_MESSAGE); return 0; /* Version Only */
Yann Collet4856a002015-01-24 01:58:16 +0100244 case 'H':
Yann Colletf44b2b02015-08-25 23:32:45 +0100245 case 'h': displayOut=stdout; return usage_advanced(programName);
Yann Collet4856a002015-01-24 01:58:16 +0100246
Yann Collet44886612016-02-11 04:17:50 +0100247 /* Decoding */
Yann Collet4856a002015-01-24 01:58:16 +0100248 case 'd': decode=1; argument++; break;
249
Yann Collet4f137032015-12-17 02:23:58 +0100250 /* Multiple input files */
251 case 'm': multiple=1; argument++; break;
252
Yann Collet1c00dc32015-10-21 08:22:25 +0100253 /* Force stdout, even if stdout==console */
Yann Collet4856a002015-01-24 01:58:16 +0100254 case 'c': forceStdout=1; outFileName=stdoutmark; displayLevel=1; argument++; break;
255
Yann Colletf6f3d752015-12-13 13:35:21 +0100256 /* Use file content as dictionary */
257 case 'D': nextEntryIsDictionary = 1; argument++; break;
258
Yann Collet4856a002015-01-24 01:58:16 +0100259 /* Overwrite */
260 case 'f': FIO_overwriteMode(); argument++; break;
261
262 /* Verbose mode */
263 case 'v': displayLevel=4; argument++; break;
264
265 /* Quiet mode */
266 case 'q': displayLevel--; argument++; break;
267
Yann Colletf6f3d752015-12-13 13:35:21 +0100268 /* keep source file (default anyway, so useless; for gzip/xz compatibility) */
Yann Collet4856a002015-01-24 01:58:16 +0100269 case 'k': argument++; break;
270
Yann Collet28e7cef2015-12-03 12:11:30 +0100271#ifndef ZSTD_NOBENCH
Yann Collet4856a002015-01-24 01:58:16 +0100272 /* Benchmark */
273 case 'b': bench=1; argument++; break;
274
275 /* Modify Nb Iterations (benchmark only) */
276 case 'i':
277 {
278 int iters= 0;
279 argument++;
280 while ((*argument >='0') && (*argument <='9'))
281 iters *= 10, iters += *argument++ - '0';
282 BMK_SetNbIterations(iters);
283 }
284 break;
285
Yann Collet1c00dc32015-10-21 08:22:25 +0100286 /* cut input into blocks (benchmark only) */
287 case 'B':
288 {
289 size_t bSize = 0;
290 argument++;
291 while ((*argument >='0') && (*argument <='9'))
292 bSize *= 10, bSize += *argument++ - '0';
293 if (*argument=='K') bSize<<=10, argument++; /* allows using KB notation */
294 if (*argument=='M') bSize<<=20, argument++;
295 if (*argument=='B') argument++;
296 BMK_SetBlockSize(bSize);
297 }
298 break;
Yann Colletc776c462015-10-29 19:10:54 +0100299
300 /* range bench (benchmark only) */
301 case 'r':
302 rangeBench = -1;
303 argument++;
304 break;
Yann Collet28e7cef2015-12-03 12:11:30 +0100305#endif /* ZSTD_NOBENCH */
Yann Colletc776c462015-10-29 19:10:54 +0100306
307 /* Pause at the end (hidden option) */
Yann Collet4856a002015-01-24 01:58:16 +0100308 case 'p': main_pause=1; argument++; break;
309
310 /* unknown command */
311 default : return badusage(programName);
312 }
313 }
314 continue;
315 }
316
Yann Colletf6f3d752015-12-13 13:35:21 +0100317 /* dictionary */
Yann Collet44886612016-02-11 04:17:50 +0100318 if (nextEntryIsDictionary) {
Yann Colletf6f3d752015-12-13 13:35:21 +0100319 nextEntryIsDictionary = 0;
320 dictFileName = argument;
321 continue;
322 }
323
Yann Collet17d188f2015-12-18 02:14:46 +0100324 /* add filename to list */
325 filenameTable[filenameIdx++] = argument;
Yann Collet4856a002015-01-24 01:58:16 +0100326 }
327
328 /* Welcome message (if verbose) */
329 DISPLAYLEVEL(3, WELCOME_MESSAGE);
330
Yann Colletd062f132015-12-01 01:31:17 +0100331 /* Check if benchmark is selected */
Yann Collet44886612016-02-11 04:17:50 +0100332 if (bench) {
Yann Collet28e7cef2015-12-03 12:11:30 +0100333#ifndef ZSTD_NOBENCH
Yann Collet17d188f2015-12-18 02:14:46 +0100334 BMK_benchFiles(filenameTable, filenameIdx, dictFileName, cLevel*rangeBench);
Yann Collet28e7cef2015-12-03 12:11:30 +0100335#endif
336 goto _end;
337 }
Yann Colletd062f132015-12-01 01:31:17 +0100338
Yann Collet4856a002015-01-24 01:58:16 +0100339 /* No input filename ==> use stdin */
Yann Collet17d188f2015-12-18 02:14:46 +0100340 if(!filenameIdx) filenameIdx=1, filenameTable[0]=stdinmark;
Yann Collet4856a002015-01-24 01:58:16 +0100341
342 /* Check if input defined as console; trigger an error in this case */
Yann Collet17d188f2015-12-18 02:14:46 +0100343 if (!strcmp(filenameTable[0], stdinmark) && IS_CONSOLE(stdin) ) return badusage(programName);
Yann Collet4856a002015-01-24 01:58:16 +0100344
Yann Collet4856a002015-01-24 01:58:16 +0100345 /* No output filename ==> try to select one automatically (when possible) */
Yann Collet6a458352015-12-18 02:51:14 +0100346 if (filenameIdx>=2) outFileName = filenameTable[1];
Yann Collet44886612016-02-11 04:17:50 +0100347 while (!outFileName) { /* while : just to allow break statement */
Yann Collet4856a002015-01-24 01:58:16 +0100348 if (!IS_CONSOLE(stdout)) { outFileName=stdoutmark; break; } /* Default to stdout whenever possible (i.e. not a console) */
Yann Collet44886612016-02-11 04:17:50 +0100349 if (!decode) { /* compression to file */
Yann Collet17d188f2015-12-18 02:14:46 +0100350 size_t l = strlen(filenameTable[0]);
Yann Collet4856a002015-01-24 01:58:16 +0100351 dynNameSpace = (char*)calloc(1,l+5);
Yann Collet94f998b2015-07-04 23:10:40 -0800352 if (dynNameSpace==NULL) { DISPLAY("not enough memory\n"); exit(1); }
Yann Collet17d188f2015-12-18 02:14:46 +0100353 strcpy(dynNameSpace, filenameTable[0]);
Yann Collet4856a002015-01-24 01:58:16 +0100354 strcpy(dynNameSpace+l, ZSTD_EXTENSION);
355 outFileName = dynNameSpace;
356 DISPLAYLEVEL(2, "Compressed filename will be : %s \n", outFileName);
357 break;
358 }
359 /* decompression to file (automatic name will work only if input filename has correct format extension) */
360 {
Yann Collet17d188f2015-12-18 02:14:46 +0100361 size_t filenameSize = strlen(filenameTable[0]);
Yann Collet44886612016-02-11 04:17:50 +0100362 if (strcmp(filenameTable[0] + (filenameSize-4), extension)) {
Yann Collet50c5cdb2015-11-04 20:35:33 +0100363 DISPLAYLEVEL(1, "unknown suffix - cannot determine destination filename\n");
364 return badusage(programName);
365 }
366 dynNameSpace = (char*)calloc(1,filenameSize+1);
Yann Collet94f998b2015-07-04 23:10:40 -0800367 if (dynNameSpace==NULL) { DISPLAY("not enough memory\n"); exit(1); }
Yann Collet4856a002015-01-24 01:58:16 +0100368 outFileName = dynNameSpace;
Yann Collet17d188f2015-12-18 02:14:46 +0100369 strcpy(dynNameSpace, filenameTable[0]);
Yann Collet50c5cdb2015-11-04 20:35:33 +0100370 dynNameSpace[filenameSize-4]=0;
Yann Collet4856a002015-01-24 01:58:16 +0100371 DISPLAYLEVEL(2, "Decoding file %s \n", outFileName);
Yann Collet44886612016-02-11 04:17:50 +0100372 } }
Yann Collet4856a002015-01-24 01:58:16 +0100373
374 /* Check if output is defined as console; trigger an error in this case */
375 if (!strcmp(outFileName,stdoutmark) && IS_CONSOLE(stdout) && !forceStdout) return badusage(programName);
376
Yann Collet4f137032015-12-17 02:23:58 +0100377 /* No warning message in pure pipe mode (stdin + stdout) or multiple mode */
Yann Collet17d188f2015-12-18 02:14:46 +0100378 if (!strcmp(filenameTable[0], stdinmark) && !strcmp(outFileName,stdoutmark) && (displayLevel==2)) displayLevel=1;
Yann Collet4f137032015-12-17 02:23:58 +0100379 if (multiple && (displayLevel==2)) displayLevel=1;
Yann Collet4856a002015-01-24 01:58:16 +0100380
Yann Collet44886612016-02-11 04:17:50 +0100381 if ((!multiple) && (filenameIdx>2)) {
Yann Collet17d188f2015-12-18 02:14:46 +0100382 DISPLAY("Too many files on the command line (%u > 2). Do you mean -m ? \n", filenameIdx);
383 return filenameIdx;
Yann Colletdeb078b2015-12-17 20:30:14 +0100384 }
385
Yann Collet4856a002015-01-24 01:58:16 +0100386 /* IO Stream/File */
387 FIO_setNotificationLevel(displayLevel);
Yann Collet44886612016-02-11 04:17:50 +0100388 if (decode) {
Yann Colletdeb078b2015-12-17 20:30:14 +0100389 if (multiple)
Yann Collet17d188f2015-12-18 02:14:46 +0100390 operationResult = FIO_decompressMultipleFilenames(filenameTable, filenameIdx, ZSTD_EXTENSION, dictFileName);
Yann Colletdeb078b2015-12-17 20:30:14 +0100391 else
Yann Collet17d188f2015-12-18 02:14:46 +0100392 operationResult = FIO_decompressFilename(outFileName, filenameTable[0], dictFileName);
Yann Collet44886612016-02-11 04:17:50 +0100393 } else { /* compression */
Yann Collet4f137032015-12-17 02:23:58 +0100394 if (multiple)
Yann Collet17d188f2015-12-18 02:14:46 +0100395 operationResult = FIO_compressMultipleFilenames(filenameTable, filenameIdx, ZSTD_EXTENSION, dictFileName, cLevel);
Yann Collet4f137032015-12-17 02:23:58 +0100396 else
Yann Collet17d188f2015-12-18 02:14:46 +0100397 operationResult = FIO_compressFilename(outFileName, filenameTable[0], dictFileName, cLevel);
Yann Collet4f137032015-12-17 02:23:58 +0100398 }
Yann Collet4856a002015-01-24 01:58:16 +0100399
400_end:
401 if (main_pause) waitEnter();
402 free(dynNameSpace);
Yann Collet324a3e22015-12-18 03:19:27 +0100403 free((void*)filenameTable);
Yann Collet4f137032015-12-17 02:23:58 +0100404 return operationResult;
Yann Collet4856a002015-01-24 01:58:16 +0100405}