xref: /aosp_15_r20/external/lz4/programs/lz4cli.c (revision 27162e4e17433d5aa7cb38e7b6a433a09405fc7f)
1*27162e4eSAndroid Build Coastguard Worker /*
2*27162e4eSAndroid Build Coastguard Worker   LZ4cli - LZ4 Command Line Interface
3*27162e4eSAndroid Build Coastguard Worker   Copyright (C) Yann Collet 2011-2023
4*27162e4eSAndroid Build Coastguard Worker 
5*27162e4eSAndroid Build Coastguard Worker   GPL v2 License
6*27162e4eSAndroid Build Coastguard Worker 
7*27162e4eSAndroid Build Coastguard Worker   This program is free software; you can redistribute it and/or modify
8*27162e4eSAndroid Build Coastguard Worker   it under the terms of the GNU General Public License as published by
9*27162e4eSAndroid Build Coastguard Worker   the Free Software Foundation; either version 2 of the License, or
10*27162e4eSAndroid Build Coastguard Worker   (at your option) any later version.
11*27162e4eSAndroid Build Coastguard Worker 
12*27162e4eSAndroid Build Coastguard Worker   This program is distributed in the hope that it will be useful,
13*27162e4eSAndroid Build Coastguard Worker   but WITHOUT ANY WARRANTY; without even the implied warranty of
14*27162e4eSAndroid Build Coastguard Worker   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*27162e4eSAndroid Build Coastguard Worker   GNU General Public License for more details.
16*27162e4eSAndroid Build Coastguard Worker 
17*27162e4eSAndroid Build Coastguard Worker   You should have received a copy of the GNU General Public License along
18*27162e4eSAndroid Build Coastguard Worker   with this program; if not, write to the Free Software Foundation, Inc.,
19*27162e4eSAndroid Build Coastguard Worker   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20*27162e4eSAndroid Build Coastguard Worker 
21*27162e4eSAndroid Build Coastguard Worker   You can contact the author at :
22*27162e4eSAndroid Build Coastguard Worker   - LZ4 source repository : https://github.com/lz4/lz4
23*27162e4eSAndroid Build Coastguard Worker   - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
24*27162e4eSAndroid Build Coastguard Worker */
25*27162e4eSAndroid Build Coastguard Worker /*
26*27162e4eSAndroid Build Coastguard Worker   Note : this is stand-alone program.
27*27162e4eSAndroid Build Coastguard Worker   It is not part of LZ4 compression library, it is a user program of the LZ4 library.
28*27162e4eSAndroid Build Coastguard Worker   The license of LZ4 library is BSD.
29*27162e4eSAndroid Build Coastguard Worker   The license of xxHash library is BSD.
30*27162e4eSAndroid Build Coastguard Worker   The license of this compression CLI program is GPLv2.
31*27162e4eSAndroid Build Coastguard Worker */
32*27162e4eSAndroid Build Coastguard Worker 
33*27162e4eSAndroid Build Coastguard Worker 
34*27162e4eSAndroid Build Coastguard Worker /*-************************************
35*27162e4eSAndroid Build Coastguard Worker *  Compiler options
36*27162e4eSAndroid Build Coastguard Worker **************************************/
37*27162e4eSAndroid Build Coastguard Worker #ifdef _MSC_VER    /* Visual Studio */
38*27162e4eSAndroid Build Coastguard Worker #  pragma warning(disable : 4127)    /* disable: C4127: conditional expression is constant */
39*27162e4eSAndroid Build Coastguard Worker #endif
40*27162e4eSAndroid Build Coastguard Worker 
41*27162e4eSAndroid Build Coastguard Worker 
42*27162e4eSAndroid Build Coastguard Worker /****************************
43*27162e4eSAndroid Build Coastguard Worker *  Includes
44*27162e4eSAndroid Build Coastguard Worker *****************************/
45*27162e4eSAndroid Build Coastguard Worker #include "platform.h" /* Compiler options, IS_CONSOLE */
46*27162e4eSAndroid Build Coastguard Worker #include "util.h"     /* UTIL_HAS_CREATEFILELIST, UTIL_createFileList */
47*27162e4eSAndroid Build Coastguard Worker #include <stdio.h>    /* fprintf, getchar */
48*27162e4eSAndroid Build Coastguard Worker #include <stdlib.h>   /* exit, calloc, free */
49*27162e4eSAndroid Build Coastguard Worker #include <string.h>   /* strcmp, strlen */
50*27162e4eSAndroid Build Coastguard Worker #include "lz4conf.h"  /* compile-time constants */
51*27162e4eSAndroid Build Coastguard Worker #include "bench.h"    /* BMK_benchFile, BMK_SetNbIterations, BMK_SetBlocksize, BMK_SetPause */
52*27162e4eSAndroid Build Coastguard Worker #include "lz4io.h"    /* LZ4IO_compressFilename, LZ4IO_decompressFilename, LZ4IO_compressMultipleFilenames */
53*27162e4eSAndroid Build Coastguard Worker #include "lz4hc.h"    /* LZ4HC_CLEVEL_MAX */
54*27162e4eSAndroid Build Coastguard Worker #include "lz4.h"      /* LZ4_VERSION_STRING */
55*27162e4eSAndroid Build Coastguard Worker 
56*27162e4eSAndroid Build Coastguard Worker 
57*27162e4eSAndroid Build Coastguard Worker /*****************************
58*27162e4eSAndroid Build Coastguard Worker *  Constants
59*27162e4eSAndroid Build Coastguard Worker ******************************/
60*27162e4eSAndroid Build Coastguard Worker #if LZ4IO_MULTITHREAD
61*27162e4eSAndroid Build Coastguard Worker # define IO_MT "multithread"
62*27162e4eSAndroid Build Coastguard Worker #else
63*27162e4eSAndroid Build Coastguard Worker # define IO_MT "single-thread"
64*27162e4eSAndroid Build Coastguard Worker #endif
65*27162e4eSAndroid Build Coastguard Worker #define COMPRESSOR_NAME "lz4"
66*27162e4eSAndroid Build Coastguard Worker #define AUTHOR "Yann Collet"
67*27162e4eSAndroid Build Coastguard Worker #define WELCOME_MESSAGE "*** %s v%s %i-bit %s, by %s ***\n", COMPRESSOR_NAME, LZ4_versionString(), (int)(sizeof(void*)*8), IO_MT, AUTHOR
68*27162e4eSAndroid Build Coastguard Worker #define LZ4_EXTENSION ".lz4"
69*27162e4eSAndroid Build Coastguard Worker #define LZ4CAT "lz4cat"
70*27162e4eSAndroid Build Coastguard Worker #define UNLZ4 "unlz4"
71*27162e4eSAndroid Build Coastguard Worker #define LZ4_LEGACY "lz4c"
72*27162e4eSAndroid Build Coastguard Worker static int g_lz4c_legacy_commands = 0;
73*27162e4eSAndroid Build Coastguard Worker 
74*27162e4eSAndroid Build Coastguard Worker #define KB *(1U<<10)
75*27162e4eSAndroid Build Coastguard Worker #define MB *(1U<<20)
76*27162e4eSAndroid Build Coastguard Worker #define GB *(1U<<30)
77*27162e4eSAndroid Build Coastguard Worker 
78*27162e4eSAndroid Build Coastguard Worker 
79*27162e4eSAndroid Build Coastguard Worker /*-************************************
80*27162e4eSAndroid Build Coastguard Worker *  Macros
81*27162e4eSAndroid Build Coastguard Worker ***************************************/
82*27162e4eSAndroid Build Coastguard Worker #define DISPLAYOUT(...)        fprintf(stdout, __VA_ARGS__)
83*27162e4eSAndroid Build Coastguard Worker #define DISPLAY(...)           fprintf(stderr, __VA_ARGS__)
84*27162e4eSAndroid Build Coastguard Worker #define DISPLAYLEVEL(l, ...)   do { if (displayLevel>=l) DISPLAY(__VA_ARGS__); } while (0)
85*27162e4eSAndroid Build Coastguard Worker static unsigned displayLevel = 2;   /* 0 : no display ; 1: errors only ; 2 : downgradable normal ; 3 : non-downgradable normal; 4 : + information */
86*27162e4eSAndroid Build Coastguard Worker 
87*27162e4eSAndroid Build Coastguard Worker 
88*27162e4eSAndroid Build Coastguard Worker /*-************************************
89*27162e4eSAndroid Build Coastguard Worker *  Errors and Messages
90*27162e4eSAndroid Build Coastguard Worker ***************************************/
91*27162e4eSAndroid Build Coastguard Worker #ifndef DEBUG
92*27162e4eSAndroid Build Coastguard Worker #  define DEBUG 0
93*27162e4eSAndroid Build Coastguard Worker #endif
94*27162e4eSAndroid Build Coastguard Worker #define DEBUGOUTPUT(...) do { if (DEBUG) DISPLAY(__VA_ARGS__); } while (0)
95*27162e4eSAndroid Build Coastguard Worker #define END_PROCESS(error, ...)                                   \
96*27162e4eSAndroid Build Coastguard Worker do {                                                              \
97*27162e4eSAndroid Build Coastguard Worker     DEBUGOUTPUT("Error in %s, line %i : \n", __FILE__, __LINE__); \
98*27162e4eSAndroid Build Coastguard Worker     DISPLAYLEVEL(1, "Error %i : ", error);                        \
99*27162e4eSAndroid Build Coastguard Worker     DISPLAYLEVEL(1, __VA_ARGS__);                                 \
100*27162e4eSAndroid Build Coastguard Worker     DISPLAYLEVEL(1, "\n");                                        \
101*27162e4eSAndroid Build Coastguard Worker     exit(error);                                                  \
102*27162e4eSAndroid Build Coastguard Worker } while (0)
103*27162e4eSAndroid Build Coastguard Worker 
errorOut(const char * msg)104*27162e4eSAndroid Build Coastguard Worker static void errorOut(const char* msg)
105*27162e4eSAndroid Build Coastguard Worker {
106*27162e4eSAndroid Build Coastguard Worker     DISPLAYLEVEL(1, "%s \n", msg); exit(1);
107*27162e4eSAndroid Build Coastguard Worker }
108*27162e4eSAndroid Build Coastguard Worker 
109*27162e4eSAndroid Build Coastguard Worker 
110*27162e4eSAndroid Build Coastguard Worker /*-************************************
111*27162e4eSAndroid Build Coastguard Worker *  Version modifiers
112*27162e4eSAndroid Build Coastguard Worker ***************************************/
113*27162e4eSAndroid Build Coastguard Worker #define DEFAULT_COMPRESSOR   LZ4IO_compressFilename
114*27162e4eSAndroid Build Coastguard Worker #define DEFAULT_DECOMPRESSOR LZ4IO_decompressFilename
115*27162e4eSAndroid Build Coastguard Worker int LZ4IO_compressFilename_Legacy(const char* input_filename, const char* output_filename, int compressionlevel, const LZ4IO_prefs_t* prefs);   /* hidden function */
116*27162e4eSAndroid Build Coastguard Worker int LZ4IO_compressMultipleFilenames_Legacy(
117*27162e4eSAndroid Build Coastguard Worker                             const char** inFileNamesTable, int ifntSize,
118*27162e4eSAndroid Build Coastguard Worker                             const char* suffix,
119*27162e4eSAndroid Build Coastguard Worker                             int compressionLevel, const LZ4IO_prefs_t* prefs);
120*27162e4eSAndroid Build Coastguard Worker 
121*27162e4eSAndroid Build Coastguard Worker /*-***************************
122*27162e4eSAndroid Build Coastguard Worker *  Functions
123*27162e4eSAndroid Build Coastguard Worker *****************************/
usage(const char * exeName)124*27162e4eSAndroid Build Coastguard Worker static int usage(const char* exeName)
125*27162e4eSAndroid Build Coastguard Worker {
126*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "Usage : \n");
127*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "      %s [arg] [input] [output] \n", exeName);
128*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "\n");
129*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "input   : a filename \n");
130*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "          with no FILE, or when FILE is - or %s, read standard input\n", stdinmark);
131*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "Arguments : \n");
132*27162e4eSAndroid Build Coastguard Worker     DISPLAY( " -1     : fast compression (default) \n");
133*27162e4eSAndroid Build Coastguard Worker     DISPLAY( " -%2d    : slowest compression level \n", LZ4HC_CLEVEL_MAX);
134*27162e4eSAndroid Build Coastguard Worker     DISPLAY( " -T#    : use # threads for compression (default:%i==auto) \n", LZ4_NBWORKERS_DEFAULT);
135*27162e4eSAndroid Build Coastguard Worker     DISPLAY( " -d     : decompression (default for %s extension)\n", LZ4_EXTENSION);
136*27162e4eSAndroid Build Coastguard Worker     DISPLAY( " -f     : overwrite output without prompting \n");
137*27162e4eSAndroid Build Coastguard Worker     DISPLAY( " -k     : preserve source files(s)  (default) \n");
138*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "--rm    : remove source file(s) after successful de/compression \n");
139*27162e4eSAndroid Build Coastguard Worker     DISPLAY( " -h/-H  : display help/long help and exit \n");
140*27162e4eSAndroid Build Coastguard Worker     return 0;
141*27162e4eSAndroid Build Coastguard Worker }
142*27162e4eSAndroid Build Coastguard Worker 
usage_advanced(const char * exeName)143*27162e4eSAndroid Build Coastguard Worker static int usage_advanced(const char* exeName)
144*27162e4eSAndroid Build Coastguard Worker {
145*27162e4eSAndroid Build Coastguard Worker     DISPLAY(WELCOME_MESSAGE);
146*27162e4eSAndroid Build Coastguard Worker     usage(exeName);
147*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "\n");
148*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "Advanced arguments :\n");
149*27162e4eSAndroid Build Coastguard Worker     DISPLAY( " -V     : display Version number and exit \n");
150*27162e4eSAndroid Build Coastguard Worker     DISPLAY( " -v     : verbose mode \n");
151*27162e4eSAndroid Build Coastguard Worker     DISPLAY( " -q     : suppress warnings; specify twice to suppress errors too\n");
152*27162e4eSAndroid Build Coastguard Worker     DISPLAY( " -c     : force write to standard output, even if it is the console\n");
153*27162e4eSAndroid Build Coastguard Worker     DISPLAY( " -t     : test compressed file integrity\n");
154*27162e4eSAndroid Build Coastguard Worker     DISPLAY( " -m     : multiple input files (implies automatic output filenames)\n");
155*27162e4eSAndroid Build Coastguard Worker #ifdef UTIL_HAS_CREATEFILELIST
156*27162e4eSAndroid Build Coastguard Worker     DISPLAY( " -r     : operate recursively on directories (sets also -m) \n");
157*27162e4eSAndroid Build Coastguard Worker #endif
158*27162e4eSAndroid Build Coastguard Worker     DISPLAY( " -l     : compress using Legacy format (Linux kernel compression)\n");
159*27162e4eSAndroid Build Coastguard Worker     DISPLAY( " -z     : force compression \n");
160*27162e4eSAndroid Build Coastguard Worker     DISPLAY( " -D FILE: use FILE as dictionary (compression & decompression)\n");
161*27162e4eSAndroid Build Coastguard Worker     DISPLAY( " -B#    : cut file into blocks of size # bytes [32+] \n");
162*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "                     or predefined block size [4-7] (default: %i) \n", LZ4_BLOCKSIZEID_DEFAULT);
163*27162e4eSAndroid Build Coastguard Worker     DISPLAY( " -BI    : Block Independence (default) \n");
164*27162e4eSAndroid Build Coastguard Worker     DISPLAY( " -BD    : Block dependency (improves compression ratio) \n");
165*27162e4eSAndroid Build Coastguard Worker     DISPLAY( " -BX    : enable block checksum (default:disabled) \n");
166*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "--no-frame-crc : disable stream checksum (default:enabled) \n");
167*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "--content-size : compressed frame includes original size (default:not present)\n");
168*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "--list FILE : lists information about .lz4 files (useful for files compressed with --content-size flag)\n");
169*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "--[no-]sparse  : sparse mode (default:enabled on file, disabled on stdout)\n");
170*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "--favor-decSpeed: compressed files decompress faster, but are less compressed \n");
171*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "--fast[=#]: switch to ultra fast compression level (default: %i)\n", 1);
172*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "--best  : same as -%d\n", LZ4HC_CLEVEL_MAX);
173*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "Benchmark arguments : \n");
174*27162e4eSAndroid Build Coastguard Worker     DISPLAY( " -b#    : benchmark file(s), using # compression level (default : 1) \n");
175*27162e4eSAndroid Build Coastguard Worker     DISPLAY( " -e#    : test all compression levels from -bX to # (default : 1)\n");
176*27162e4eSAndroid Build Coastguard Worker     DISPLAY( " -i#    : minimum evaluation time in seconds (default : 3s) \n");
177*27162e4eSAndroid Build Coastguard Worker     if (g_lz4c_legacy_commands) {
178*27162e4eSAndroid Build Coastguard Worker         DISPLAY( "Legacy arguments : \n");
179*27162e4eSAndroid Build Coastguard Worker         DISPLAY( " -c0    : fast compression \n");
180*27162e4eSAndroid Build Coastguard Worker         DISPLAY( " -c1    : high compression \n");
181*27162e4eSAndroid Build Coastguard Worker         DISPLAY( " -c2,-hc: very high compression \n");
182*27162e4eSAndroid Build Coastguard Worker         DISPLAY( " -y     : overwrite output without prompting \n");
183*27162e4eSAndroid Build Coastguard Worker     }
184*27162e4eSAndroid Build Coastguard Worker     return 0;
185*27162e4eSAndroid Build Coastguard Worker }
186*27162e4eSAndroid Build Coastguard Worker 
usage_longhelp(const char * exeName)187*27162e4eSAndroid Build Coastguard Worker static int usage_longhelp(const char* exeName)
188*27162e4eSAndroid Build Coastguard Worker {
189*27162e4eSAndroid Build Coastguard Worker     usage_advanced(exeName);
190*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "\n");
191*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "****************************\n");
192*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "***** Advanced comment *****\n");
193*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "****************************\n");
194*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "\n");
195*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "Which values can [output] have ? \n");
196*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "---------------------------------\n");
197*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "[output] : a filename \n");
198*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "          '%s', or '-' for standard output (pipe mode)\n", stdoutmark);
199*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "          '%s' to discard output (test mode) \n", NULL_OUTPUT);
200*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "[output] can be left empty. In this case, it receives the following value :\n");
201*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "          - if stdout is not the console, then [output] = stdout \n");
202*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "          - if stdout is console : \n");
203*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "               + for compression, output to filename%s \n", LZ4_EXTENSION);
204*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "               + for decompression, output to filename without '%s'\n", LZ4_EXTENSION);
205*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "                    > if input filename has no '%s' extension : error \n", LZ4_EXTENSION);
206*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "\n");
207*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "Compression levels : \n");
208*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "---------------------\n");
209*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "-0 ... -2  => Fast compression, all identical\n");
210*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "-3 ... -%d => High compression; higher number == more compression but slower\n", LZ4HC_CLEVEL_MAX);
211*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "\n");
212*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "stdin, stdout and the console : \n");
213*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "--------------------------------\n");
214*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "To protect the console from binary flooding (bad argument mistake)\n");
215*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "%s will refuse to read from console, or write to console \n", exeName);
216*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "except if '-c' command is specified, to force output to console \n");
217*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "\n");
218*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "Simple example :\n");
219*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "----------------\n");
220*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "1 : compress 'filename' fast, using default output name 'filename.lz4'\n");
221*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "          %s filename\n", exeName);
222*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "\n");
223*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "Short arguments can be aggregated. For example :\n");
224*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "----------------------------------\n");
225*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "2 : compress 'filename' in high compression mode, overwrite output if exists\n");
226*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "          %s -9 -f filename \n", exeName);
227*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "    is equivalent to :\n");
228*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "          %s -9f filename \n", exeName);
229*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "\n");
230*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "%s can be used in 'pure pipe mode'. For example :\n", exeName);
231*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "-------------------------------------\n");
232*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "3 : compress data stream from 'generator', send result to 'consumer'\n");
233*27162e4eSAndroid Build Coastguard Worker     DISPLAY( "          generator | %s | consumer \n", exeName);
234*27162e4eSAndroid Build Coastguard Worker     if (g_lz4c_legacy_commands) {
235*27162e4eSAndroid Build Coastguard Worker         DISPLAY( "\n");
236*27162e4eSAndroid Build Coastguard Worker         DISPLAY( "***** Warning  ***** \n");
237*27162e4eSAndroid Build Coastguard Worker         DISPLAY( "Legacy arguments take precedence. Therefore : \n");
238*27162e4eSAndroid Build Coastguard Worker         DISPLAY( "--------------------------------- \n");
239*27162e4eSAndroid Build Coastguard Worker         DISPLAY( "          %s -hc filename \n", exeName);
240*27162e4eSAndroid Build Coastguard Worker         DISPLAY( "means 'compress filename in high compression mode' \n");
241*27162e4eSAndroid Build Coastguard Worker         DISPLAY( "It is not equivalent to : \n");
242*27162e4eSAndroid Build Coastguard Worker         DISPLAY( "          %s -h -c filename \n", exeName);
243*27162e4eSAndroid Build Coastguard Worker         DISPLAY( "which displays help text and exits \n");
244*27162e4eSAndroid Build Coastguard Worker     }
245*27162e4eSAndroid Build Coastguard Worker     return 0;
246*27162e4eSAndroid Build Coastguard Worker }
247*27162e4eSAndroid Build Coastguard Worker 
badusage(const char * exeName)248*27162e4eSAndroid Build Coastguard Worker static int badusage(const char* exeName)
249*27162e4eSAndroid Build Coastguard Worker {
250*27162e4eSAndroid Build Coastguard Worker     DISPLAYLEVEL(1, "Incorrect parameters\n");
251*27162e4eSAndroid Build Coastguard Worker     if (displayLevel >= 1) usage(exeName);
252*27162e4eSAndroid Build Coastguard Worker     exit(1);
253*27162e4eSAndroid Build Coastguard Worker }
254*27162e4eSAndroid Build Coastguard Worker 
255*27162e4eSAndroid Build Coastguard Worker 
waitEnter(void)256*27162e4eSAndroid Build Coastguard Worker static void waitEnter(void)
257*27162e4eSAndroid Build Coastguard Worker {
258*27162e4eSAndroid Build Coastguard Worker     DISPLAY("Press enter to continue...\n");
259*27162e4eSAndroid Build Coastguard Worker     (void)getchar();
260*27162e4eSAndroid Build Coastguard Worker }
261*27162e4eSAndroid Build Coastguard Worker 
lastNameFromPath(const char * path)262*27162e4eSAndroid Build Coastguard Worker static const char* lastNameFromPath(const char* path)
263*27162e4eSAndroid Build Coastguard Worker {
264*27162e4eSAndroid Build Coastguard Worker     const char* name = path;
265*27162e4eSAndroid Build Coastguard Worker     if (strrchr(name, '/')) name = strrchr(name, '/') + 1;
266*27162e4eSAndroid Build Coastguard Worker     if (strrchr(name, '\\')) name = strrchr(name, '\\') + 1; /* windows */
267*27162e4eSAndroid Build Coastguard Worker     return name;
268*27162e4eSAndroid Build Coastguard Worker }
269*27162e4eSAndroid Build Coastguard Worker 
270*27162e4eSAndroid Build Coastguard Worker /*! exeNameMatch() :
271*27162e4eSAndroid Build Coastguard Worker     @return : a non-zero value if exeName matches test, excluding the extension
272*27162e4eSAndroid Build Coastguard Worker    */
exeNameMatch(const char * exeName,const char * test)273*27162e4eSAndroid Build Coastguard Worker static int exeNameMatch(const char* exeName, const char* test)
274*27162e4eSAndroid Build Coastguard Worker {
275*27162e4eSAndroid Build Coastguard Worker     return !strncmp(exeName, test, strlen(test)) &&
276*27162e4eSAndroid Build Coastguard Worker         (exeName[strlen(test)] == '\0' || exeName[strlen(test)] == '.');
277*27162e4eSAndroid Build Coastguard Worker }
278*27162e4eSAndroid Build Coastguard Worker 
279*27162e4eSAndroid Build Coastguard Worker /*! readU32FromChar() :
280*27162e4eSAndroid Build Coastguard Worker  * @return : unsigned integer value read from input in `char` format
281*27162e4eSAndroid Build Coastguard Worker  *  allows and interprets K, KB, KiB, M, MB and MiB suffix.
282*27162e4eSAndroid Build Coastguard Worker  *  Will also modify `*stringPtr`, advancing it to position where it stopped reading.
283*27162e4eSAndroid Build Coastguard Worker  *  Note : function result can overflow if digit string > MAX_UINT */
readU32FromChar(const char ** stringPtr)284*27162e4eSAndroid Build Coastguard Worker static unsigned readU32FromChar(const char** stringPtr)
285*27162e4eSAndroid Build Coastguard Worker {
286*27162e4eSAndroid Build Coastguard Worker     unsigned result = 0;
287*27162e4eSAndroid Build Coastguard Worker     while ((**stringPtr >='0') && (**stringPtr <='9')) {
288*27162e4eSAndroid Build Coastguard Worker         result *= 10;
289*27162e4eSAndroid Build Coastguard Worker         result += (unsigned)(**stringPtr - '0');
290*27162e4eSAndroid Build Coastguard Worker         (*stringPtr)++ ;
291*27162e4eSAndroid Build Coastguard Worker     }
292*27162e4eSAndroid Build Coastguard Worker     if ((**stringPtr=='K') || (**stringPtr=='M')) {
293*27162e4eSAndroid Build Coastguard Worker         result <<= 10;
294*27162e4eSAndroid Build Coastguard Worker         if (**stringPtr=='M') result <<= 10;
295*27162e4eSAndroid Build Coastguard Worker         (*stringPtr)++ ;
296*27162e4eSAndroid Build Coastguard Worker         if (**stringPtr=='i') (*stringPtr)++;
297*27162e4eSAndroid Build Coastguard Worker         if (**stringPtr=='B') (*stringPtr)++;
298*27162e4eSAndroid Build Coastguard Worker     }
299*27162e4eSAndroid Build Coastguard Worker     return result;
300*27162e4eSAndroid Build Coastguard Worker }
301*27162e4eSAndroid Build Coastguard Worker 
302*27162e4eSAndroid Build Coastguard Worker #define CLEAN_RETURN(i) { operationResult = (i); goto _cleanup; }
303*27162e4eSAndroid Build Coastguard Worker 
304*27162e4eSAndroid Build Coastguard Worker #define NEXT_FIELD(ptr) {         \
305*27162e4eSAndroid Build Coastguard Worker     if (*argument == '=') {       \
306*27162e4eSAndroid Build Coastguard Worker         ptr = ++argument;         \
307*27162e4eSAndroid Build Coastguard Worker         argument += strlen(ptr);  \
308*27162e4eSAndroid Build Coastguard Worker     } else {                      \
309*27162e4eSAndroid Build Coastguard Worker         argNb++;                  \
310*27162e4eSAndroid Build Coastguard Worker         if (argNb >= argCount) {  \
311*27162e4eSAndroid Build Coastguard Worker             DISPLAYLEVEL(1, "error: missing command argument \n"); \
312*27162e4eSAndroid Build Coastguard Worker             CLEAN_RETURN(1);      \
313*27162e4eSAndroid Build Coastguard Worker         }                         \
314*27162e4eSAndroid Build Coastguard Worker         ptr = argv[argNb];        \
315*27162e4eSAndroid Build Coastguard Worker         assert(ptr != NULL);      \
316*27162e4eSAndroid Build Coastguard Worker         if (ptr[0]=='-') {        \
317*27162e4eSAndroid Build Coastguard Worker             DISPLAYLEVEL(1, "error: command cannot be separated from its argument by another command \n"); \
318*27162e4eSAndroid Build Coastguard Worker             CLEAN_RETURN(1);      \
319*27162e4eSAndroid Build Coastguard Worker }   }   }
320*27162e4eSAndroid Build Coastguard Worker 
321*27162e4eSAndroid Build Coastguard Worker #define NEXT_UINT32(val32) {      \
322*27162e4eSAndroid Build Coastguard Worker     const char* __nb;             \
323*27162e4eSAndroid Build Coastguard Worker     NEXT_FIELD(__nb);             \
324*27162e4eSAndroid Build Coastguard Worker     val32 = readU32FromChar(&__nb); \
325*27162e4eSAndroid Build Coastguard Worker     if(*__nb != 0) {              \
326*27162e4eSAndroid Build Coastguard Worker         errorOut("error: only numeric values with optional suffixes K, KB, KiB, M, MB, MiB are allowed"); \
327*27162e4eSAndroid Build Coastguard Worker     }                             \
328*27162e4eSAndroid Build Coastguard Worker }
329*27162e4eSAndroid Build Coastguard Worker 
330*27162e4eSAndroid Build Coastguard Worker /** longCommandWArg() :
331*27162e4eSAndroid Build Coastguard Worker  *  check if *stringPtr is the same as longCommand.
332*27162e4eSAndroid Build Coastguard Worker  *  If yes, @return 1 and advances *stringPtr to the position which immediately follows longCommand.
333*27162e4eSAndroid Build Coastguard Worker  * @return 0 and doesn't modify *stringPtr otherwise.
334*27162e4eSAndroid Build Coastguard Worker  */
longCommandWArg(const char ** stringPtr,const char * longCommand)335*27162e4eSAndroid Build Coastguard Worker static int longCommandWArg(const char** stringPtr, const char* longCommand)
336*27162e4eSAndroid Build Coastguard Worker {
337*27162e4eSAndroid Build Coastguard Worker     size_t const comSize = strlen(longCommand);
338*27162e4eSAndroid Build Coastguard Worker     int const result = !strncmp(*stringPtr, longCommand, comSize);
339*27162e4eSAndroid Build Coastguard Worker     if (result) *stringPtr += comSize;
340*27162e4eSAndroid Build Coastguard Worker     return result;
341*27162e4eSAndroid Build Coastguard Worker }
342*27162e4eSAndroid Build Coastguard Worker 
343*27162e4eSAndroid Build Coastguard Worker typedef enum { om_auto, om_compress, om_decompress, om_test, om_bench, om_list } operationMode_e;
344*27162e4eSAndroid Build Coastguard Worker 
345*27162e4eSAndroid Build Coastguard Worker /** determineOpMode() :
346*27162e4eSAndroid Build Coastguard Worker  *  auto-determine operation mode, based on input filename extension
347*27162e4eSAndroid Build Coastguard Worker  *  @return `om_decompress` if input filename has .lz4 extension and `om_compress` otherwise.
348*27162e4eSAndroid Build Coastguard Worker  */
determineOpMode(const char * inputFilename)349*27162e4eSAndroid Build Coastguard Worker static operationMode_e determineOpMode(const char* inputFilename)
350*27162e4eSAndroid Build Coastguard Worker {
351*27162e4eSAndroid Build Coastguard Worker     size_t const inSize  = strlen(inputFilename);
352*27162e4eSAndroid Build Coastguard Worker     size_t const extSize = strlen(LZ4_EXTENSION);
353*27162e4eSAndroid Build Coastguard Worker     size_t const extStart= (inSize > extSize) ? inSize-extSize : 0;
354*27162e4eSAndroid Build Coastguard Worker     if (!strcmp(inputFilename+extStart, LZ4_EXTENSION)) return om_decompress;
355*27162e4eSAndroid Build Coastguard Worker     else return om_compress;
356*27162e4eSAndroid Build Coastguard Worker }
357*27162e4eSAndroid Build Coastguard Worker 
358*27162e4eSAndroid Build Coastguard Worker #define ENV_NBTHREADS "LZ4_NBWORKERS"
359*27162e4eSAndroid Build Coastguard Worker 
init_nbWorkers(void)360*27162e4eSAndroid Build Coastguard Worker static unsigned init_nbWorkers(void)
361*27162e4eSAndroid Build Coastguard Worker {
362*27162e4eSAndroid Build Coastguard Worker     const char* const env = getenv(ENV_NBTHREADS);
363*27162e4eSAndroid Build Coastguard Worker     if (env != NULL) {
364*27162e4eSAndroid Build Coastguard Worker         const char* ptr = env;
365*27162e4eSAndroid Build Coastguard Worker         if ((*ptr>='0') && (*ptr<='9')) {
366*27162e4eSAndroid Build Coastguard Worker             return readU32FromChar(&ptr);
367*27162e4eSAndroid Build Coastguard Worker         }
368*27162e4eSAndroid Build Coastguard Worker         DISPLAYLEVEL(2, "Ignore environment variable setting %s=%s: not a valid unsigned value \n", ENV_NBTHREADS, env);
369*27162e4eSAndroid Build Coastguard Worker     }
370*27162e4eSAndroid Build Coastguard Worker     return LZ4_NBWORKERS_DEFAULT;
371*27162e4eSAndroid Build Coastguard Worker }
372*27162e4eSAndroid Build Coastguard Worker 
373*27162e4eSAndroid Build Coastguard Worker #define ENV_CLEVEL "LZ4_CLEVEL"
374*27162e4eSAndroid Build Coastguard Worker 
init_cLevel(void)375*27162e4eSAndroid Build Coastguard Worker static int init_cLevel(void)
376*27162e4eSAndroid Build Coastguard Worker {
377*27162e4eSAndroid Build Coastguard Worker     const char* const env = getenv(ENV_CLEVEL);
378*27162e4eSAndroid Build Coastguard Worker     if (env != NULL) {
379*27162e4eSAndroid Build Coastguard Worker         const char* ptr = env;
380*27162e4eSAndroid Build Coastguard Worker         if ((*ptr>='0') && (*ptr<='9')) {
381*27162e4eSAndroid Build Coastguard Worker             return (int)readU32FromChar(&ptr);
382*27162e4eSAndroid Build Coastguard Worker         }
383*27162e4eSAndroid Build Coastguard Worker         DISPLAYLEVEL(2, "Ignore environment variable setting %s=%s: not a valid unsigned value \n", ENV_CLEVEL, env);
384*27162e4eSAndroid Build Coastguard Worker     }
385*27162e4eSAndroid Build Coastguard Worker     return LZ4_CLEVEL_DEFAULT;
386*27162e4eSAndroid Build Coastguard Worker }
387*27162e4eSAndroid Build Coastguard Worker 
main(int argCount,const char ** argv)388*27162e4eSAndroid Build Coastguard Worker int main(int argCount, const char** argv)
389*27162e4eSAndroid Build Coastguard Worker {
390*27162e4eSAndroid Build Coastguard Worker     int argNb,
391*27162e4eSAndroid Build Coastguard Worker         cLevel=init_cLevel(),
392*27162e4eSAndroid Build Coastguard Worker         cLevelLast=-10000,
393*27162e4eSAndroid Build Coastguard Worker         legacy_format=0,
394*27162e4eSAndroid Build Coastguard Worker         forceStdout=0,
395*27162e4eSAndroid Build Coastguard Worker         forceOverwrite=0,
396*27162e4eSAndroid Build Coastguard Worker         main_pause=0,
397*27162e4eSAndroid Build Coastguard Worker         multiple_inputs=0,
398*27162e4eSAndroid Build Coastguard Worker         all_arguments_are_files=0,
399*27162e4eSAndroid Build Coastguard Worker         operationResult=0;
400*27162e4eSAndroid Build Coastguard Worker     unsigned nbWorkers = init_nbWorkers();
401*27162e4eSAndroid Build Coastguard Worker     operationMode_e mode = om_auto;
402*27162e4eSAndroid Build Coastguard Worker     const char* input_filename = NULL;
403*27162e4eSAndroid Build Coastguard Worker     const char* output_filename= NULL;
404*27162e4eSAndroid Build Coastguard Worker     const char* dictionary_filename = NULL;
405*27162e4eSAndroid Build Coastguard Worker     char* dynNameSpace = NULL;
406*27162e4eSAndroid Build Coastguard Worker     const char** inFileNames = (const char**)calloc((size_t)argCount, sizeof(char*));
407*27162e4eSAndroid Build Coastguard Worker     unsigned ifnIdx=0;
408*27162e4eSAndroid Build Coastguard Worker     LZ4IO_prefs_t* const prefs = LZ4IO_defaultPreferences();
409*27162e4eSAndroid Build Coastguard Worker     const char nullOutput[] = NULL_OUTPUT;
410*27162e4eSAndroid Build Coastguard Worker     const char extension[] = LZ4_EXTENSION;
411*27162e4eSAndroid Build Coastguard Worker     size_t blockSize = LZ4IO_setBlockSizeID(prefs, LZ4_BLOCKSIZEID_DEFAULT);
412*27162e4eSAndroid Build Coastguard Worker     const char* const exeName = lastNameFromPath(argv[0]);
413*27162e4eSAndroid Build Coastguard Worker     char* fileNamesBuf = NULL;
414*27162e4eSAndroid Build Coastguard Worker #ifdef UTIL_HAS_CREATEFILELIST
415*27162e4eSAndroid Build Coastguard Worker     unsigned fileNamesNb, recursive=0;
416*27162e4eSAndroid Build Coastguard Worker #endif
417*27162e4eSAndroid Build Coastguard Worker 
418*27162e4eSAndroid Build Coastguard Worker     /* Init */
419*27162e4eSAndroid Build Coastguard Worker     if (inFileNames==NULL) {
420*27162e4eSAndroid Build Coastguard Worker         DISPLAY("Allocation error : not enough memory \n");
421*27162e4eSAndroid Build Coastguard Worker         operationResult = 1;
422*27162e4eSAndroid Build Coastguard Worker         goto _cleanup;
423*27162e4eSAndroid Build Coastguard Worker     }
424*27162e4eSAndroid Build Coastguard Worker     inFileNames[0] = stdinmark;
425*27162e4eSAndroid Build Coastguard Worker     LZ4IO_setOverwrite(prefs, 0);
426*27162e4eSAndroid Build Coastguard Worker 
427*27162e4eSAndroid Build Coastguard Worker     /* predefined behaviors, based on binary/link name */
428*27162e4eSAndroid Build Coastguard Worker     if (exeNameMatch(exeName, LZ4CAT)) {
429*27162e4eSAndroid Build Coastguard Worker         mode = om_decompress;
430*27162e4eSAndroid Build Coastguard Worker         LZ4IO_setOverwrite(prefs, 1);
431*27162e4eSAndroid Build Coastguard Worker         LZ4IO_setPassThrough(prefs, 1);
432*27162e4eSAndroid Build Coastguard Worker         LZ4IO_setRemoveSrcFile(prefs, 0);
433*27162e4eSAndroid Build Coastguard Worker         forceStdout=1;
434*27162e4eSAndroid Build Coastguard Worker         output_filename=stdoutmark;
435*27162e4eSAndroid Build Coastguard Worker         displayLevel=1;
436*27162e4eSAndroid Build Coastguard Worker         multiple_inputs=1;
437*27162e4eSAndroid Build Coastguard Worker     }
438*27162e4eSAndroid Build Coastguard Worker     if (exeNameMatch(exeName, UNLZ4)) { mode = om_decompress; }
439*27162e4eSAndroid Build Coastguard Worker     if (exeNameMatch(exeName, LZ4_LEGACY)) { g_lz4c_legacy_commands=1; }
440*27162e4eSAndroid Build Coastguard Worker 
441*27162e4eSAndroid Build Coastguard Worker     /* command switches */
442*27162e4eSAndroid Build Coastguard Worker     for(argNb=1; argNb<argCount; argNb++) {
443*27162e4eSAndroid Build Coastguard Worker         const char* argument = argv[argNb];
444*27162e4eSAndroid Build Coastguard Worker 
445*27162e4eSAndroid Build Coastguard Worker         if(!argument) continue;   /* Protection if argument empty */
446*27162e4eSAndroid Build Coastguard Worker 
447*27162e4eSAndroid Build Coastguard Worker         /* Short commands (note : aggregated short commands are allowed) */
448*27162e4eSAndroid Build Coastguard Worker         if (!all_arguments_are_files && argument[0]=='-') {
449*27162e4eSAndroid Build Coastguard Worker             /* '-' means stdin/stdout */
450*27162e4eSAndroid Build Coastguard Worker             if (argument[1]==0) {
451*27162e4eSAndroid Build Coastguard Worker                 if (!input_filename) input_filename=stdinmark;
452*27162e4eSAndroid Build Coastguard Worker                 else output_filename=stdoutmark;
453*27162e4eSAndroid Build Coastguard Worker                 continue;
454*27162e4eSAndroid Build Coastguard Worker             }
455*27162e4eSAndroid Build Coastguard Worker 
456*27162e4eSAndroid Build Coastguard Worker             /* long commands (--long-word) */
457*27162e4eSAndroid Build Coastguard Worker             if (argument[1]=='-') {
458*27162e4eSAndroid Build Coastguard Worker                 if (!strcmp(argument,  "--")) { all_arguments_are_files = 1; continue; }
459*27162e4eSAndroid Build Coastguard Worker                 if (!strcmp(argument,  "--compress")) { mode = om_compress; continue; }
460*27162e4eSAndroid Build Coastguard Worker                 if ( (!strcmp(argument, "--decompress"))
461*27162e4eSAndroid Build Coastguard Worker                   || (!strcmp(argument, "--uncompress"))) {
462*27162e4eSAndroid Build Coastguard Worker                       if (mode != om_bench) mode = om_decompress;
463*27162e4eSAndroid Build Coastguard Worker                       BMK_setDecodeOnlyMode(1);
464*27162e4eSAndroid Build Coastguard Worker                       continue;
465*27162e4eSAndroid Build Coastguard Worker                   }
466*27162e4eSAndroid Build Coastguard Worker                 if (!strcmp(argument,  "--multiple")) { multiple_inputs = 1; continue; }
467*27162e4eSAndroid Build Coastguard Worker                 if (!strcmp(argument,  "--test")) { mode = om_test; continue; }
468*27162e4eSAndroid Build Coastguard Worker                 if (!strcmp(argument,  "--force")) { LZ4IO_setOverwrite(prefs, 1); continue; }
469*27162e4eSAndroid Build Coastguard Worker                 if (!strcmp(argument,  "--no-force")) { LZ4IO_setOverwrite(prefs, 0); continue; }
470*27162e4eSAndroid Build Coastguard Worker                 if ((!strcmp(argument, "--stdout"))
471*27162e4eSAndroid Build Coastguard Worker                     || (!strcmp(argument, "--to-stdout"))) { forceStdout=1; output_filename=stdoutmark; continue; }
472*27162e4eSAndroid Build Coastguard Worker                 if (!strcmp(argument,  "--frame-crc")) { LZ4IO_setStreamChecksumMode(prefs, 1); BMK_skipChecksums(0); continue; }
473*27162e4eSAndroid Build Coastguard Worker                 if (!strcmp(argument,  "--no-frame-crc")) { LZ4IO_setStreamChecksumMode(prefs, 0); BMK_skipChecksums(1); continue; }
474*27162e4eSAndroid Build Coastguard Worker                 if (!strcmp(argument,  "--no-crc")) { LZ4IO_setStreamChecksumMode(prefs, 0); LZ4IO_setBlockChecksumMode(prefs, 0); BMK_skipChecksums(1); continue; }
475*27162e4eSAndroid Build Coastguard Worker                 if (!strcmp(argument,  "--content-size")) { LZ4IO_setContentSize(prefs, 1); continue; }
476*27162e4eSAndroid Build Coastguard Worker                 if (!strcmp(argument,  "--no-content-size")) { LZ4IO_setContentSize(prefs, 0); continue; }
477*27162e4eSAndroid Build Coastguard Worker                 if (!strcmp(argument,  "--list")) { mode = om_list; multiple_inputs = 1; continue; }
478*27162e4eSAndroid Build Coastguard Worker                 if (!strcmp(argument,  "--sparse")) { LZ4IO_setSparseFile(prefs, 2); continue; }
479*27162e4eSAndroid Build Coastguard Worker                 if (!strcmp(argument,  "--no-sparse")) { LZ4IO_setSparseFile(prefs, 0); continue; }
480*27162e4eSAndroid Build Coastguard Worker                 if (!strcmp(argument,  "--favor-decSpeed")) { LZ4IO_favorDecSpeed(prefs, 1); continue; }
481*27162e4eSAndroid Build Coastguard Worker                 if (!strcmp(argument,  "--verbose")) { displayLevel++; continue; }
482*27162e4eSAndroid Build Coastguard Worker                 if (!strcmp(argument,  "--quiet")) { if (displayLevel) displayLevel--; continue; }
483*27162e4eSAndroid Build Coastguard Worker                 if (!strcmp(argument,  "--version")) { DISPLAYOUT(WELCOME_MESSAGE); goto _cleanup; }
484*27162e4eSAndroid Build Coastguard Worker                 if (!strcmp(argument,  "--help")) { usage_advanced(exeName); goto _cleanup; }
485*27162e4eSAndroid Build Coastguard Worker                 if (!strcmp(argument,  "--keep")) { LZ4IO_setRemoveSrcFile(prefs, 0); continue; }   /* keep source file (default) */
486*27162e4eSAndroid Build Coastguard Worker                 if (!strcmp(argument,  "--rm")) { LZ4IO_setRemoveSrcFile(prefs, 1); continue; }
487*27162e4eSAndroid Build Coastguard Worker 
488*27162e4eSAndroid Build Coastguard Worker                 if (longCommandWArg(&argument, "--threads")) {
489*27162e4eSAndroid Build Coastguard Worker                     NEXT_UINT32(nbWorkers);
490*27162e4eSAndroid Build Coastguard Worker                     continue;
491*27162e4eSAndroid Build Coastguard Worker                 }
492*27162e4eSAndroid Build Coastguard Worker                 if (longCommandWArg(&argument, "--fast")) {
493*27162e4eSAndroid Build Coastguard Worker                     /* Parse optional acceleration factor */
494*27162e4eSAndroid Build Coastguard Worker                     if (*argument == '=') {
495*27162e4eSAndroid Build Coastguard Worker                         U32 fastLevel;
496*27162e4eSAndroid Build Coastguard Worker                         ++argument;
497*27162e4eSAndroid Build Coastguard Worker                         fastLevel = readU32FromChar(&argument);
498*27162e4eSAndroid Build Coastguard Worker                         if (fastLevel) {
499*27162e4eSAndroid Build Coastguard Worker                             cLevel = -(int)fastLevel;
500*27162e4eSAndroid Build Coastguard Worker                         } else {
501*27162e4eSAndroid Build Coastguard Worker                             badusage(exeName);
502*27162e4eSAndroid Build Coastguard Worker                         }
503*27162e4eSAndroid Build Coastguard Worker                     } else if (*argument != 0) {
504*27162e4eSAndroid Build Coastguard Worker                         /* Invalid character following --fast */
505*27162e4eSAndroid Build Coastguard Worker                         badusage(exeName);
506*27162e4eSAndroid Build Coastguard Worker                     } else {
507*27162e4eSAndroid Build Coastguard Worker                         cLevel = -1;  /* default for --fast */
508*27162e4eSAndroid Build Coastguard Worker                     }
509*27162e4eSAndroid Build Coastguard Worker                     continue;
510*27162e4eSAndroid Build Coastguard Worker                 }
511*27162e4eSAndroid Build Coastguard Worker 
512*27162e4eSAndroid Build Coastguard Worker                 /* For gzip(1) compatibility */
513*27162e4eSAndroid Build Coastguard Worker                 if (!strcmp(argument,  "--best")) { cLevel=LZ4HC_CLEVEL_MAX; continue; }
514*27162e4eSAndroid Build Coastguard Worker             }
515*27162e4eSAndroid Build Coastguard Worker 
516*27162e4eSAndroid Build Coastguard Worker             while (argument[1]!=0) {
517*27162e4eSAndroid Build Coastguard Worker                 argument ++;
518*27162e4eSAndroid Build Coastguard Worker 
519*27162e4eSAndroid Build Coastguard Worker                 if (g_lz4c_legacy_commands) {
520*27162e4eSAndroid Build Coastguard Worker                     /* Legacy commands (-c0, -c1, -hc, -y) */
521*27162e4eSAndroid Build Coastguard Worker                     if (!strcmp(argument,  "c0")) { cLevel=0; argument++; continue; }  /* -c0 (fast compression) */
522*27162e4eSAndroid Build Coastguard Worker                     if (!strcmp(argument,  "c1")) { cLevel=9; argument++; continue; }  /* -c1 (high compression) */
523*27162e4eSAndroid Build Coastguard Worker                     if (!strcmp(argument,  "c2")) { cLevel=12; argument++; continue; } /* -c2 (very high compression) */
524*27162e4eSAndroid Build Coastguard Worker                     if (!strcmp(argument,  "hc")) { cLevel=12; argument++; continue; } /* -hc (very high compression) */
525*27162e4eSAndroid Build Coastguard Worker                     if (!strcmp(argument,  "y"))  { LZ4IO_setOverwrite(prefs, 1); continue; } /* -y (answer 'yes' to overwrite permission) */
526*27162e4eSAndroid Build Coastguard Worker                 }
527*27162e4eSAndroid Build Coastguard Worker 
528*27162e4eSAndroid Build Coastguard Worker                 if ((*argument>='0') && (*argument<='9')) {
529*27162e4eSAndroid Build Coastguard Worker                     cLevel = (int)readU32FromChar(&argument);
530*27162e4eSAndroid Build Coastguard Worker                     argument--;
531*27162e4eSAndroid Build Coastguard Worker                     continue;
532*27162e4eSAndroid Build Coastguard Worker                 }
533*27162e4eSAndroid Build Coastguard Worker 
534*27162e4eSAndroid Build Coastguard Worker 
535*27162e4eSAndroid Build Coastguard Worker                 switch(argument[0])
536*27162e4eSAndroid Build Coastguard Worker                 {
537*27162e4eSAndroid Build Coastguard Worker                     /* Display help */
538*27162e4eSAndroid Build Coastguard Worker                 case 'V': DISPLAYOUT(WELCOME_MESSAGE); goto _cleanup;   /* Version */
539*27162e4eSAndroid Build Coastguard Worker                 case 'h': usage_advanced(exeName); goto _cleanup;
540*27162e4eSAndroid Build Coastguard Worker                 case 'H': usage_longhelp(exeName); goto _cleanup;
541*27162e4eSAndroid Build Coastguard Worker 
542*27162e4eSAndroid Build Coastguard Worker                 case 'e':
543*27162e4eSAndroid Build Coastguard Worker                     argument++;
544*27162e4eSAndroid Build Coastguard Worker                     cLevelLast = (int)readU32FromChar(&argument);
545*27162e4eSAndroid Build Coastguard Worker                     argument--;
546*27162e4eSAndroid Build Coastguard Worker                     break;
547*27162e4eSAndroid Build Coastguard Worker 
548*27162e4eSAndroid Build Coastguard Worker                     /* Compression (default) */
549*27162e4eSAndroid Build Coastguard Worker                 case 'z': mode = om_compress; break;
550*27162e4eSAndroid Build Coastguard Worker 
551*27162e4eSAndroid Build Coastguard Worker                     /* Modify Nb Worker threads (compression only) */
552*27162e4eSAndroid Build Coastguard Worker                 case 'T':
553*27162e4eSAndroid Build Coastguard Worker                     {   argument++;
554*27162e4eSAndroid Build Coastguard Worker                         nbWorkers = readU32FromChar(&argument);
555*27162e4eSAndroid Build Coastguard Worker                         argument--;
556*27162e4eSAndroid Build Coastguard Worker                     }
557*27162e4eSAndroid Build Coastguard Worker                     break;
558*27162e4eSAndroid Build Coastguard Worker 
559*27162e4eSAndroid Build Coastguard Worker                 case 'D':
560*27162e4eSAndroid Build Coastguard Worker                     if (argument[1] == '\0') {
561*27162e4eSAndroid Build Coastguard Worker                         /* path is next arg */
562*27162e4eSAndroid Build Coastguard Worker                         if (argNb + 1 == argCount) {
563*27162e4eSAndroid Build Coastguard Worker                             /* there is no next arg */
564*27162e4eSAndroid Build Coastguard Worker                             badusage(exeName);
565*27162e4eSAndroid Build Coastguard Worker                         }
566*27162e4eSAndroid Build Coastguard Worker                         dictionary_filename = argv[++argNb];
567*27162e4eSAndroid Build Coastguard Worker                     } else {
568*27162e4eSAndroid Build Coastguard Worker                         /* path follows immediately */
569*27162e4eSAndroid Build Coastguard Worker                         dictionary_filename = argument + 1;
570*27162e4eSAndroid Build Coastguard Worker                     }
571*27162e4eSAndroid Build Coastguard Worker                     /* skip to end of argument so that we jump to parsing next argument */
572*27162e4eSAndroid Build Coastguard Worker                     argument += strlen(argument) - 1;
573*27162e4eSAndroid Build Coastguard Worker                     break;
574*27162e4eSAndroid Build Coastguard Worker 
575*27162e4eSAndroid Build Coastguard Worker                     /* Use Legacy format (ex : Linux kernel compression) */
576*27162e4eSAndroid Build Coastguard Worker                 case 'l': legacy_format = 1; blockSize = 8 MB; break;
577*27162e4eSAndroid Build Coastguard Worker 
578*27162e4eSAndroid Build Coastguard Worker                     /* Decoding */
579*27162e4eSAndroid Build Coastguard Worker                 case 'd':
580*27162e4eSAndroid Build Coastguard Worker                     if (mode != om_bench) mode = om_decompress;
581*27162e4eSAndroid Build Coastguard Worker                     BMK_setDecodeOnlyMode(1);
582*27162e4eSAndroid Build Coastguard Worker                     break;
583*27162e4eSAndroid Build Coastguard Worker 
584*27162e4eSAndroid Build Coastguard Worker                     /* Force stdout, even if stdout==console */
585*27162e4eSAndroid Build Coastguard Worker                 case 'c':
586*27162e4eSAndroid Build Coastguard Worker                   forceStdout=1;
587*27162e4eSAndroid Build Coastguard Worker                   output_filename=stdoutmark;
588*27162e4eSAndroid Build Coastguard Worker                   LZ4IO_setPassThrough(prefs, 1);
589*27162e4eSAndroid Build Coastguard Worker                   break;
590*27162e4eSAndroid Build Coastguard Worker 
591*27162e4eSAndroid Build Coastguard Worker                     /* Test integrity */
592*27162e4eSAndroid Build Coastguard Worker                 case 't': mode = om_test; break;
593*27162e4eSAndroid Build Coastguard Worker 
594*27162e4eSAndroid Build Coastguard Worker                     /* Overwrite */
595*27162e4eSAndroid Build Coastguard Worker                 case 'f': forceOverwrite=1; LZ4IO_setOverwrite(prefs, 1); break;
596*27162e4eSAndroid Build Coastguard Worker 
597*27162e4eSAndroid Build Coastguard Worker                     /* Verbose mode */
598*27162e4eSAndroid Build Coastguard Worker                 case 'v': displayLevel++; break;
599*27162e4eSAndroid Build Coastguard Worker 
600*27162e4eSAndroid Build Coastguard Worker                     /* Quiet mode */
601*27162e4eSAndroid Build Coastguard Worker                 case 'q': if (displayLevel) displayLevel--; break;
602*27162e4eSAndroid Build Coastguard Worker 
603*27162e4eSAndroid Build Coastguard Worker                     /* keep source file (default anyway, so useless) (for xz/lzma compatibility) */
604*27162e4eSAndroid Build Coastguard Worker                 case 'k': LZ4IO_setRemoveSrcFile(prefs, 0); break;
605*27162e4eSAndroid Build Coastguard Worker 
606*27162e4eSAndroid Build Coastguard Worker                     /* Modify Block Properties */
607*27162e4eSAndroid Build Coastguard Worker                 case 'B':
608*27162e4eSAndroid Build Coastguard Worker                     while (argument[1]!=0) {
609*27162e4eSAndroid Build Coastguard Worker                         int exitBlockProperties=0;
610*27162e4eSAndroid Build Coastguard Worker                         switch(argument[1])
611*27162e4eSAndroid Build Coastguard Worker                         {
612*27162e4eSAndroid Build Coastguard Worker                         case 'D': LZ4IO_setBlockMode(prefs, LZ4IO_blockLinked); argument++; break;
613*27162e4eSAndroid Build Coastguard Worker                         case 'I': LZ4IO_setBlockMode(prefs, LZ4IO_blockIndependent); argument++; break;
614*27162e4eSAndroid Build Coastguard Worker                         case 'X': LZ4IO_setBlockChecksumMode(prefs, 1); argument ++; break;   /* disabled by default */
615*27162e4eSAndroid Build Coastguard Worker                         default :
616*27162e4eSAndroid Build Coastguard Worker                             if (argument[1] < '0' || argument[1] > '9') {
617*27162e4eSAndroid Build Coastguard Worker                                 exitBlockProperties=1;
618*27162e4eSAndroid Build Coastguard Worker                                 break;
619*27162e4eSAndroid Build Coastguard Worker                             } else {
620*27162e4eSAndroid Build Coastguard Worker                                 unsigned B;
621*27162e4eSAndroid Build Coastguard Worker                                 argument++;
622*27162e4eSAndroid Build Coastguard Worker                                 B = readU32FromChar(&argument);
623*27162e4eSAndroid Build Coastguard Worker                                 argument--;
624*27162e4eSAndroid Build Coastguard Worker                                 if (B < 4) badusage(exeName);
625*27162e4eSAndroid Build Coastguard Worker                                 if (B <= 7) {
626*27162e4eSAndroid Build Coastguard Worker                                     blockSize = LZ4IO_setBlockSizeID(prefs, B);
627*27162e4eSAndroid Build Coastguard Worker                                     BMK_setBlockSize(blockSize);
628*27162e4eSAndroid Build Coastguard Worker                                     DISPLAYLEVEL(2, "using blocks of size %u KB \n", (U32)(blockSize>>10));
629*27162e4eSAndroid Build Coastguard Worker                                 } else {
630*27162e4eSAndroid Build Coastguard Worker                                     if (B < 32) badusage(exeName);
631*27162e4eSAndroid Build Coastguard Worker                                     blockSize = LZ4IO_setBlockSize(prefs, B);
632*27162e4eSAndroid Build Coastguard Worker                                     BMK_setBlockSize(blockSize);
633*27162e4eSAndroid Build Coastguard Worker                                     if (blockSize >= 1024) {
634*27162e4eSAndroid Build Coastguard Worker                                         DISPLAYLEVEL(2, "using blocks of size %u KB \n", (U32)(blockSize>>10));
635*27162e4eSAndroid Build Coastguard Worker                                     } else {
636*27162e4eSAndroid Build Coastguard Worker                                         DISPLAYLEVEL(2, "using blocks of size %u bytes \n", (U32)(blockSize));
637*27162e4eSAndroid Build Coastguard Worker                                     }
638*27162e4eSAndroid Build Coastguard Worker                                 }
639*27162e4eSAndroid Build Coastguard Worker                                 break;
640*27162e4eSAndroid Build Coastguard Worker                             }
641*27162e4eSAndroid Build Coastguard Worker                         }
642*27162e4eSAndroid Build Coastguard Worker                         if (exitBlockProperties) break;
643*27162e4eSAndroid Build Coastguard Worker                     }
644*27162e4eSAndroid Build Coastguard Worker                     break;
645*27162e4eSAndroid Build Coastguard Worker 
646*27162e4eSAndroid Build Coastguard Worker                     /* Benchmark */
647*27162e4eSAndroid Build Coastguard Worker                 case 'b': mode = om_bench; multiple_inputs=1;
648*27162e4eSAndroid Build Coastguard Worker                     break;
649*27162e4eSAndroid Build Coastguard Worker 
650*27162e4eSAndroid Build Coastguard Worker                     /* hidden command : benchmark files, but do not fuse result */
651*27162e4eSAndroid Build Coastguard Worker                 case 'S': BMK_setBenchSeparately(1);
652*27162e4eSAndroid Build Coastguard Worker                     break;
653*27162e4eSAndroid Build Coastguard Worker 
654*27162e4eSAndroid Build Coastguard Worker #ifdef UTIL_HAS_CREATEFILELIST
655*27162e4eSAndroid Build Coastguard Worker                     /* recursive */
656*27162e4eSAndroid Build Coastguard Worker                 case 'r': recursive=1;
657*27162e4eSAndroid Build Coastguard Worker #endif
658*27162e4eSAndroid Build Coastguard Worker                     /* fall-through */
659*27162e4eSAndroid Build Coastguard Worker                     /* Treat non-option args as input files.  See https://code.google.com/p/lz4/issues/detail?id=151 */
660*27162e4eSAndroid Build Coastguard Worker                 case 'm': multiple_inputs=1;
661*27162e4eSAndroid Build Coastguard Worker                     break;
662*27162e4eSAndroid Build Coastguard Worker 
663*27162e4eSAndroid Build Coastguard Worker                     /* Modify Nb Seconds (benchmark only) */
664*27162e4eSAndroid Build Coastguard Worker                 case 'i':
665*27162e4eSAndroid Build Coastguard Worker                     {   unsigned iters;
666*27162e4eSAndroid Build Coastguard Worker                         argument++;
667*27162e4eSAndroid Build Coastguard Worker                         iters = readU32FromChar(&argument);
668*27162e4eSAndroid Build Coastguard Worker                         argument--;
669*27162e4eSAndroid Build Coastguard Worker                         BMK_setNotificationLevel(displayLevel);
670*27162e4eSAndroid Build Coastguard Worker                         BMK_setNbSeconds(iters);   /* notification if displayLevel >= 3 */
671*27162e4eSAndroid Build Coastguard Worker                     }
672*27162e4eSAndroid Build Coastguard Worker                     break;
673*27162e4eSAndroid Build Coastguard Worker 
674*27162e4eSAndroid Build Coastguard Worker                     /* Pause at the end (hidden option) */
675*27162e4eSAndroid Build Coastguard Worker                 case 'p': main_pause=1; break;
676*27162e4eSAndroid Build Coastguard Worker 
677*27162e4eSAndroid Build Coastguard Worker                     /* Unrecognised command */
678*27162e4eSAndroid Build Coastguard Worker                 default : badusage(exeName);
679*27162e4eSAndroid Build Coastguard Worker                 }
680*27162e4eSAndroid Build Coastguard Worker             }
681*27162e4eSAndroid Build Coastguard Worker             continue;
682*27162e4eSAndroid Build Coastguard Worker         }
683*27162e4eSAndroid Build Coastguard Worker 
684*27162e4eSAndroid Build Coastguard Worker         /* Store in *inFileNames[] if -m is used. */
685*27162e4eSAndroid Build Coastguard Worker         if (multiple_inputs) { inFileNames[ifnIdx++] = argument; continue; }
686*27162e4eSAndroid Build Coastguard Worker 
687*27162e4eSAndroid Build Coastguard Worker         /* original cli logic : lz4 input output */
688*27162e4eSAndroid Build Coastguard Worker         /* First non-option arg is input_filename. */
689*27162e4eSAndroid Build Coastguard Worker         if (!input_filename) { input_filename = argument; continue; }
690*27162e4eSAndroid Build Coastguard Worker 
691*27162e4eSAndroid Build Coastguard Worker         /* Second non-option arg is output_filename */
692*27162e4eSAndroid Build Coastguard Worker         if (!output_filename) {
693*27162e4eSAndroid Build Coastguard Worker             output_filename = argument;
694*27162e4eSAndroid Build Coastguard Worker             if (!strcmp (output_filename, nullOutput)) output_filename = nulmark;
695*27162e4eSAndroid Build Coastguard Worker             continue;
696*27162e4eSAndroid Build Coastguard Worker         }
697*27162e4eSAndroid Build Coastguard Worker 
698*27162e4eSAndroid Build Coastguard Worker         /* 3rd+ non-option arg should not exist */
699*27162e4eSAndroid Build Coastguard Worker         DISPLAYLEVEL(1, "%s : %s won't be used ! Do you want multiple input files (-m) ? \n",
700*27162e4eSAndroid Build Coastguard Worker             forceOverwrite ? "Warning" : "Error",
701*27162e4eSAndroid Build Coastguard Worker             argument);
702*27162e4eSAndroid Build Coastguard Worker         if (!forceOverwrite) exit(1);
703*27162e4eSAndroid Build Coastguard Worker     }
704*27162e4eSAndroid Build Coastguard Worker 
705*27162e4eSAndroid Build Coastguard Worker     DISPLAYLEVEL(3, WELCOME_MESSAGE);
706*27162e4eSAndroid Build Coastguard Worker #ifdef _POSIX_C_SOURCE
707*27162e4eSAndroid Build Coastguard Worker     DISPLAYLEVEL(4, "_POSIX_C_SOURCE defined: %ldL\n", (long) _POSIX_C_SOURCE);
708*27162e4eSAndroid Build Coastguard Worker #endif
709*27162e4eSAndroid Build Coastguard Worker #ifdef _POSIX_VERSION
710*27162e4eSAndroid Build Coastguard Worker     DISPLAYLEVEL(4, "_POSIX_VERSION defined: %ldL\n", (long) _POSIX_VERSION);
711*27162e4eSAndroid Build Coastguard Worker #endif
712*27162e4eSAndroid Build Coastguard Worker #ifdef PLATFORM_POSIX_VERSION
713*27162e4eSAndroid Build Coastguard Worker     DISPLAYLEVEL(4, "PLATFORM_POSIX_VERSION defined: %ldL\n", (long) PLATFORM_POSIX_VERSION);
714*27162e4eSAndroid Build Coastguard Worker #endif
715*27162e4eSAndroid Build Coastguard Worker #ifdef _FILE_OFFSET_BITS
716*27162e4eSAndroid Build Coastguard Worker     DISPLAYLEVEL(5, "_FILE_OFFSET_BITS defined: %ldL\n", (long) _FILE_OFFSET_BITS);
717*27162e4eSAndroid Build Coastguard Worker #endif
718*27162e4eSAndroid Build Coastguard Worker #if !LZ4IO_MULTITHREAD
719*27162e4eSAndroid Build Coastguard Worker     if (nbWorkers > 1) {
720*27162e4eSAndroid Build Coastguard Worker         DISPLAYLEVEL(2, "warning: this executable doesn't support multithreading \n");
721*27162e4eSAndroid Build Coastguard Worker     }
722*27162e4eSAndroid Build Coastguard Worker #endif
723*27162e4eSAndroid Build Coastguard Worker     if ((mode == om_compress) || (mode == om_bench)) {
724*27162e4eSAndroid Build Coastguard Worker         DISPLAYLEVEL(4, "Blocks size : %u KB\n", (U32)(blockSize>>10));
725*27162e4eSAndroid Build Coastguard Worker     }
726*27162e4eSAndroid Build Coastguard Worker 
727*27162e4eSAndroid Build Coastguard Worker     if (multiple_inputs) {
728*27162e4eSAndroid Build Coastguard Worker         input_filename = inFileNames[0];
729*27162e4eSAndroid Build Coastguard Worker #ifdef UTIL_HAS_CREATEFILELIST
730*27162e4eSAndroid Build Coastguard Worker         if (recursive) {  /* at this stage, filenameTable is a list of paths, which can contain both files and directories */
731*27162e4eSAndroid Build Coastguard Worker             const char** extendedFileList = UTIL_createFileList(inFileNames, ifnIdx, &fileNamesBuf, &fileNamesNb);
732*27162e4eSAndroid Build Coastguard Worker             if (extendedFileList) {
733*27162e4eSAndroid Build Coastguard Worker                 unsigned u;
734*27162e4eSAndroid Build Coastguard Worker                 for (u=0; u<fileNamesNb; u++) DISPLAYLEVEL(4, "%u %s\n", u, extendedFileList[u]);
735*27162e4eSAndroid Build Coastguard Worker                 free((void*)inFileNames);
736*27162e4eSAndroid Build Coastguard Worker                 inFileNames = extendedFileList;
737*27162e4eSAndroid Build Coastguard Worker                 ifnIdx = fileNamesNb;
738*27162e4eSAndroid Build Coastguard Worker         }   }
739*27162e4eSAndroid Build Coastguard Worker #endif
740*27162e4eSAndroid Build Coastguard Worker     }
741*27162e4eSAndroid Build Coastguard Worker 
742*27162e4eSAndroid Build Coastguard Worker     if (dictionary_filename) {
743*27162e4eSAndroid Build Coastguard Worker         if (!strcmp(dictionary_filename, stdinmark) && IS_CONSOLE(stdin)) {
744*27162e4eSAndroid Build Coastguard Worker             DISPLAYLEVEL(1, "refusing to read from a console\n");
745*27162e4eSAndroid Build Coastguard Worker             exit(1);
746*27162e4eSAndroid Build Coastguard Worker         }
747*27162e4eSAndroid Build Coastguard Worker         LZ4IO_setDictionaryFilename(prefs, dictionary_filename);
748*27162e4eSAndroid Build Coastguard Worker     }
749*27162e4eSAndroid Build Coastguard Worker 
750*27162e4eSAndroid Build Coastguard Worker     /* benchmark and test modes */
751*27162e4eSAndroid Build Coastguard Worker     if (mode == om_bench) {
752*27162e4eSAndroid Build Coastguard Worker         BMK_setNotificationLevel(displayLevel);
753*27162e4eSAndroid Build Coastguard Worker         operationResult = BMK_benchFiles(inFileNames, ifnIdx, cLevel, cLevelLast, dictionary_filename);
754*27162e4eSAndroid Build Coastguard Worker         goto _cleanup;
755*27162e4eSAndroid Build Coastguard Worker     }
756*27162e4eSAndroid Build Coastguard Worker 
757*27162e4eSAndroid Build Coastguard Worker     if (mode == om_test) {
758*27162e4eSAndroid Build Coastguard Worker         LZ4IO_setTestMode(prefs, 1);
759*27162e4eSAndroid Build Coastguard Worker         output_filename = nulmark;
760*27162e4eSAndroid Build Coastguard Worker         mode = om_decompress;   /* defer to decompress */
761*27162e4eSAndroid Build Coastguard Worker     }
762*27162e4eSAndroid Build Coastguard Worker 
763*27162e4eSAndroid Build Coastguard Worker     /* No input provided => use stdin */
764*27162e4eSAndroid Build Coastguard Worker     if (!input_filename) input_filename = stdinmark;
765*27162e4eSAndroid Build Coastguard Worker 
766*27162e4eSAndroid Build Coastguard Worker     /* Refuse to use the console as input */
767*27162e4eSAndroid Build Coastguard Worker     if (!strcmp(input_filename, stdinmark) && IS_CONSOLE(stdin) ) {
768*27162e4eSAndroid Build Coastguard Worker         DISPLAYLEVEL(1, "refusing to read from a console\n");
769*27162e4eSAndroid Build Coastguard Worker         exit(1);
770*27162e4eSAndroid Build Coastguard Worker     }
771*27162e4eSAndroid Build Coastguard Worker 
772*27162e4eSAndroid Build Coastguard Worker     if (!strcmp(input_filename, stdinmark)) {
773*27162e4eSAndroid Build Coastguard Worker         /* if input==stdin and no output defined, stdout becomes default output */
774*27162e4eSAndroid Build Coastguard Worker         if (!output_filename) output_filename = stdoutmark;
775*27162e4eSAndroid Build Coastguard Worker     }
776*27162e4eSAndroid Build Coastguard Worker 
777*27162e4eSAndroid Build Coastguard Worker     /* No output filename ==> try to select one automatically (when possible) */
778*27162e4eSAndroid Build Coastguard Worker     if ((!output_filename) && (multiple_inputs==0)) {
779*27162e4eSAndroid Build Coastguard Worker         if (mode == om_auto) {  /* auto-determine compression or decompression, based on file extension */
780*27162e4eSAndroid Build Coastguard Worker             mode = determineOpMode(input_filename);
781*27162e4eSAndroid Build Coastguard Worker         }
782*27162e4eSAndroid Build Coastguard Worker         if (mode == om_compress) {   /* compression to file */
783*27162e4eSAndroid Build Coastguard Worker             size_t const l = strlen(input_filename);
784*27162e4eSAndroid Build Coastguard Worker             dynNameSpace = (char*)calloc(1,l+5);
785*27162e4eSAndroid Build Coastguard Worker             if (dynNameSpace==NULL) { perror(exeName); exit(1); }
786*27162e4eSAndroid Build Coastguard Worker             strcpy(dynNameSpace, input_filename);
787*27162e4eSAndroid Build Coastguard Worker             strcat(dynNameSpace, LZ4_EXTENSION);
788*27162e4eSAndroid Build Coastguard Worker             output_filename = dynNameSpace;
789*27162e4eSAndroid Build Coastguard Worker             DISPLAYLEVEL(2, "Compressed filename will be : %s \n", output_filename);
790*27162e4eSAndroid Build Coastguard Worker         }
791*27162e4eSAndroid Build Coastguard Worker         if (mode == om_decompress) {
792*27162e4eSAndroid Build Coastguard Worker             /* decompress to file (automatic output name only works if input filename has correct format extension) */
793*27162e4eSAndroid Build Coastguard Worker             size_t outl;
794*27162e4eSAndroid Build Coastguard Worker             size_t const inl = strlen(input_filename);
795*27162e4eSAndroid Build Coastguard Worker             dynNameSpace = (char*)calloc(1,inl+1);
796*27162e4eSAndroid Build Coastguard Worker             if (dynNameSpace==NULL) { perror(exeName); exit(1); }
797*27162e4eSAndroid Build Coastguard Worker             strcpy(dynNameSpace, input_filename);
798*27162e4eSAndroid Build Coastguard Worker             outl = inl;
799*27162e4eSAndroid Build Coastguard Worker             if (inl>4)
800*27162e4eSAndroid Build Coastguard Worker                 while ((outl >= inl-4) && (input_filename[outl] ==  extension[outl-inl+4])) dynNameSpace[outl--]=0;
801*27162e4eSAndroid Build Coastguard Worker             if (outl != inl-5) { DISPLAYLEVEL(1, "Cannot determine an output filename \n"); badusage(exeName); }
802*27162e4eSAndroid Build Coastguard Worker             output_filename = dynNameSpace;
803*27162e4eSAndroid Build Coastguard Worker             DISPLAYLEVEL(2, "Decoding file %s \n", output_filename);
804*27162e4eSAndroid Build Coastguard Worker         }
805*27162e4eSAndroid Build Coastguard Worker     }
806*27162e4eSAndroid Build Coastguard Worker 
807*27162e4eSAndroid Build Coastguard Worker     if (mode == om_list) {
808*27162e4eSAndroid Build Coastguard Worker         if (!multiple_inputs) inFileNames[ifnIdx++] = input_filename;
809*27162e4eSAndroid Build Coastguard Worker     } else {
810*27162e4eSAndroid Build Coastguard Worker         if (!multiple_inputs) assert(output_filename != NULL);
811*27162e4eSAndroid Build Coastguard Worker     }
812*27162e4eSAndroid Build Coastguard Worker     /* when multiple_inputs==1, output_filename may simply be useless,
813*27162e4eSAndroid Build Coastguard Worker      * however, output_filename must be !NULL for next strcmp() tests */
814*27162e4eSAndroid Build Coastguard Worker     if (!output_filename) output_filename = "*\\dummy^!//";
815*27162e4eSAndroid Build Coastguard Worker 
816*27162e4eSAndroid Build Coastguard Worker     /* Check if output is defined as console; trigger an error in this case */
817*27162e4eSAndroid Build Coastguard Worker     if ( !strcmp(output_filename,stdoutmark)
818*27162e4eSAndroid Build Coastguard Worker       && mode != om_list
819*27162e4eSAndroid Build Coastguard Worker       && IS_CONSOLE(stdout)
820*27162e4eSAndroid Build Coastguard Worker       && !forceStdout) {
821*27162e4eSAndroid Build Coastguard Worker         DISPLAYLEVEL(1, "refusing to write to console without -c \n");
822*27162e4eSAndroid Build Coastguard Worker         exit(1);
823*27162e4eSAndroid Build Coastguard Worker     }
824*27162e4eSAndroid Build Coastguard Worker     /* Downgrade notification level in stdout and multiple file mode */
825*27162e4eSAndroid Build Coastguard Worker     if (!strcmp(output_filename,stdoutmark) && (displayLevel==2)) displayLevel=1;
826*27162e4eSAndroid Build Coastguard Worker     if ((multiple_inputs) && (displayLevel==2)) displayLevel=1;
827*27162e4eSAndroid Build Coastguard Worker 
828*27162e4eSAndroid Build Coastguard Worker     /* Auto-determine compression or decompression, based on file extension */
829*27162e4eSAndroid Build Coastguard Worker     if (mode == om_auto) {
830*27162e4eSAndroid Build Coastguard Worker         mode = determineOpMode(input_filename);
831*27162e4eSAndroid Build Coastguard Worker     }
832*27162e4eSAndroid Build Coastguard Worker 
833*27162e4eSAndroid Build Coastguard Worker     /* IO Stream/File */
834*27162e4eSAndroid Build Coastguard Worker     LZ4IO_setNotificationLevel((int)displayLevel);
835*27162e4eSAndroid Build Coastguard Worker     if (ifnIdx == 0) multiple_inputs = 0;
836*27162e4eSAndroid Build Coastguard Worker     if (mode == om_decompress) {
837*27162e4eSAndroid Build Coastguard Worker         if (multiple_inputs) {
838*27162e4eSAndroid Build Coastguard Worker             const char* dec_extension = LZ4_EXTENSION;
839*27162e4eSAndroid Build Coastguard Worker             if (!strcmp(output_filename, stdoutmark)) dec_extension = stdoutmark;
840*27162e4eSAndroid Build Coastguard Worker             if (!strcmp(output_filename, nulmark)) dec_extension = nulmark;
841*27162e4eSAndroid Build Coastguard Worker             assert(ifnIdx < INT_MAX);
842*27162e4eSAndroid Build Coastguard Worker             operationResult = LZ4IO_decompressMultipleFilenames(inFileNames, (int)ifnIdx, dec_extension, prefs);
843*27162e4eSAndroid Build Coastguard Worker         } else {
844*27162e4eSAndroid Build Coastguard Worker             operationResult = DEFAULT_DECOMPRESSOR(input_filename, output_filename, prefs);
845*27162e4eSAndroid Build Coastguard Worker         }
846*27162e4eSAndroid Build Coastguard Worker     } else if (mode == om_list){
847*27162e4eSAndroid Build Coastguard Worker         operationResult = LZ4IO_displayCompressedFilesInfo(inFileNames, ifnIdx);
848*27162e4eSAndroid Build Coastguard Worker     } else {   /* compression is default action */
849*27162e4eSAndroid Build Coastguard Worker #if LZ4IO_MULTITHREAD
850*27162e4eSAndroid Build Coastguard Worker         if (nbWorkers != 1) {
851*27162e4eSAndroid Build Coastguard Worker             if (nbWorkers==0)
852*27162e4eSAndroid Build Coastguard Worker                 nbWorkers = (unsigned)LZ4IO_defaultNbWorkers();
853*27162e4eSAndroid Build Coastguard Worker             if (nbWorkers > LZ4_NBWORKERS_MAX) {
854*27162e4eSAndroid Build Coastguard Worker                 DISPLAYLEVEL(3, "Requested %u threads too large => automatically reduced to %u \n",
855*27162e4eSAndroid Build Coastguard Worker                             nbWorkers, LZ4_NBWORKERS_MAX);
856*27162e4eSAndroid Build Coastguard Worker                 nbWorkers = LZ4_NBWORKERS_MAX;
857*27162e4eSAndroid Build Coastguard Worker             } else {
858*27162e4eSAndroid Build Coastguard Worker                 DISPLAYLEVEL(3, "Using %u threads for compression \n", nbWorkers);
859*27162e4eSAndroid Build Coastguard Worker             }
860*27162e4eSAndroid Build Coastguard Worker         }
861*27162e4eSAndroid Build Coastguard Worker         LZ4IO_setNbWorkers(prefs, (int)nbWorkers);
862*27162e4eSAndroid Build Coastguard Worker #endif
863*27162e4eSAndroid Build Coastguard Worker         if (legacy_format) {
864*27162e4eSAndroid Build Coastguard Worker             DISPLAYLEVEL(3, "! Generating LZ4 Legacy format (deprecated) ! \n");
865*27162e4eSAndroid Build Coastguard Worker             if(multiple_inputs){
866*27162e4eSAndroid Build Coastguard Worker                 const char* const leg_extension = !strcmp(output_filename,stdoutmark) ? stdoutmark : LZ4_EXTENSION;
867*27162e4eSAndroid Build Coastguard Worker                 operationResult = LZ4IO_compressMultipleFilenames_Legacy(inFileNames, (int)ifnIdx, leg_extension, cLevel, prefs);
868*27162e4eSAndroid Build Coastguard Worker             } else {
869*27162e4eSAndroid Build Coastguard Worker                 operationResult = LZ4IO_compressFilename_Legacy(input_filename, output_filename, cLevel, prefs);
870*27162e4eSAndroid Build Coastguard Worker             }
871*27162e4eSAndroid Build Coastguard Worker         } else {
872*27162e4eSAndroid Build Coastguard Worker             if (multiple_inputs) {
873*27162e4eSAndroid Build Coastguard Worker                 const char* const comp_extension = !strcmp(output_filename,stdoutmark) ? stdoutmark : LZ4_EXTENSION;
874*27162e4eSAndroid Build Coastguard Worker                 assert(ifnIdx <= INT_MAX);
875*27162e4eSAndroid Build Coastguard Worker                 operationResult = LZ4IO_compressMultipleFilenames(inFileNames, (int)ifnIdx, comp_extension, cLevel, prefs);
876*27162e4eSAndroid Build Coastguard Worker             } else {
877*27162e4eSAndroid Build Coastguard Worker                 operationResult = DEFAULT_COMPRESSOR(input_filename, output_filename, cLevel, prefs);
878*27162e4eSAndroid Build Coastguard Worker     }   }   }
879*27162e4eSAndroid Build Coastguard Worker 
880*27162e4eSAndroid Build Coastguard Worker _cleanup:
881*27162e4eSAndroid Build Coastguard Worker     if (main_pause) waitEnter();
882*27162e4eSAndroid Build Coastguard Worker     free(dynNameSpace);
883*27162e4eSAndroid Build Coastguard Worker     free(fileNamesBuf);
884*27162e4eSAndroid Build Coastguard Worker     LZ4IO_freePreferences(prefs);
885*27162e4eSAndroid Build Coastguard Worker     free((void*)inFileNames);
886*27162e4eSAndroid Build Coastguard Worker     return operationResult;
887*27162e4eSAndroid Build Coastguard Worker }
888