2013-12-30 17:16:52 +00:00
/*
2014-12-06 16:10:54 +00:00
LZ4cli - LZ4 Command Line Interface
2016-11-21 23:51:39 +00:00
Copyright ( C ) Yann Collet 2011 - 2016
2014-12-06 16:10:54 +00:00
2013-12-30 17:16:52 +00:00
GPL v2 License
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License along
with this program ; if not , write to the Free Software Foundation , Inc . ,
51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA .
You can contact the author at :
2016-11-03 14:12:57 +00:00
- LZ4 source repository : https : //github.com/lz4/lz4
2013-12-30 17:16:52 +00:00
- LZ4 public forum : https : //groups.google.com/forum/#!forum/lz4c
*/
/*
Note : this is stand - alone program .
It is not part of LZ4 compression library , it is a user program of the LZ4 library .
The license of LZ4 library is BSD .
The license of xxHash library is BSD .
The license of this compression CLI program is GPLv2 .
*/
2014-12-16 21:03:16 +00:00
/****************************
* Includes
* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-12-20 17:56:09 +00:00
# include "platform.h" /* Compiler options, IS_CONSOLE */
# include "util.h" /* UTIL_HAS_CREATEFILELIST, UTIL_createFileList */
2014-12-16 21:03:16 +00:00
# include <stdio.h> /* fprintf, getchar */
# include <stdlib.h> /* exit, calloc, free */
# include <string.h> /* strcmp, strlen */
# include "bench.h" /* BMK_benchFile, BMK_SetNbIterations, BMK_SetBlocksize, BMK_SetPause */
2015-03-21 12:34:55 +00:00
# include "lz4io.h" /* LZ4IO_compressFilename, LZ4IO_decompressFilename, LZ4IO_compressMultipleFilenames */
2017-04-29 12:16:51 +00:00
# include "lz4hc.h" /* LZ4HC_CLEVEL_MAX */
2016-09-03 02:32:06 +00:00
# include "lz4.h" /* LZ4_VERSION_STRING */
2013-12-30 17:16:52 +00:00
2014-12-16 21:03:16 +00:00
/*****************************
* Constants
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-06-29 10:54:23 +00:00
# define COMPRESSOR_NAME "LZ4 command line interface"
2013-12-30 17:16:52 +00:00
# define AUTHOR "Yann Collet"
2016-12-04 19:05:36 +00:00
# define WELCOME_MESSAGE "*** %s %i-bits v%s, by %s ***\n", COMPRESSOR_NAME, (int)(sizeof(void*)*8), LZ4_versionString(), AUTHOR
2013-12-30 17:16:52 +00:00
# define LZ4_EXTENSION ".lz4"
2015-03-21 12:34:55 +00:00
# define LZ4CAT "lz4cat"
# define UNLZ4 "unlz4"
2017-08-14 23:56:05 +00:00
# define LZ4_LEGACY "lz4c"
static int g_lz4c_legacy_commands = 0 ;
2013-12-30 17:16:52 +00:00
# define KB *(1U<<10)
# define MB *(1U<<20)
# define GB *(1U<<30)
2014-02-04 14:11:10 +00:00
# define LZ4_BLOCKSIZEID_DEFAULT 7
2013-12-30 17:16:52 +00:00
2016-06-29 10:54:23 +00:00
/*-************************************
2014-12-16 21:03:16 +00:00
* Macros
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2019-06-24 23:08:30 +00:00
# define DISPLAYOUT(...) fprintf(stdout, __VA_ARGS__)
2014-12-06 16:10:54 +00:00
# define DISPLAY(...) fprintf(stderr, __VA_ARGS__)
# define DISPLAYLEVEL(l, ...) if (displayLevel>=l) { DISPLAY(__VA_ARGS__); }
2015-04-16 06:16:48 +00:00
static unsigned displayLevel = 2 ; /* 0 : no display ; 1: errors only ; 2 : downgradable normal ; 3 : non-downgradable normal; 4 : + information */
2013-12-30 17:16:52 +00:00
2016-06-29 10:54:23 +00:00
/*-************************************
2014-12-16 21:03:16 +00:00
* Exceptions
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-12-30 17:16:52 +00:00
# define DEBUG 0
# define DEBUGOUTPUT(...) if (DEBUG) DISPLAY(__VA_ARGS__);
# define EXM_THROW(error, ...) \
{ \
DEBUGOUTPUT ( " Error defined at %s, line %i : \n " , __FILE__ , __LINE__ ) ; \
DISPLAYLEVEL ( 1 , " Error %i : " , error ) ; \
DISPLAYLEVEL ( 1 , __VA_ARGS__ ) ; \
DISPLAYLEVEL ( 1 , " \n " ) ; \
exit ( error ) ; \
}
2016-06-29 10:54:23 +00:00
/*-************************************
2014-12-16 21:03:16 +00:00
* Version modifiers
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2014-02-04 14:11:10 +00:00
# define DEFAULT_COMPRESSOR LZ4IO_compressFilename
# define DEFAULT_DECOMPRESSOR LZ4IO_decompressFilename
2019-01-11 04:40:00 +00:00
int LZ4IO_compressFilename_Legacy ( LZ4IO_prefs_t * const prefs , const char * input_filename , const char * output_filename , int compressionlevel ) ; /* hidden function */
2013-12-30 17:16:52 +00:00
2016-06-29 10:54:23 +00:00
/*-***************************
2014-12-16 21:03:16 +00:00
* Functions
* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-11-09 22:36:42 +00:00
static int usage ( const char * exeName )
2013-12-30 17:16:52 +00:00
{
2016-11-28 12:01:02 +00:00
DISPLAY ( " Usage : \n " ) ;
DISPLAY ( " %s [arg] [input] [output] \n " , exeName ) ;
2013-12-30 17:16:52 +00:00
DISPLAY ( " \n " ) ;
2016-11-28 12:01:02 +00:00
DISPLAY ( " input : a filename \n " ) ;
2013-12-30 17:16:52 +00:00
DISPLAY ( " with no FILE, or when FILE is - or %s, read standard input \n " , stdinmark ) ;
2016-11-28 12:01:02 +00:00
DISPLAY ( " Arguments : \n " ) ;
2013-12-30 17:16:52 +00:00
DISPLAY ( " -1 : Fast compression (default) \n " ) ;
DISPLAY ( " -9 : High compression \n " ) ;
DISPLAY ( " -d : decompression (default for %s extension) \n " , LZ4_EXTENSION ) ;
2016-11-28 12:01:02 +00:00
DISPLAY ( " -z : force compression \n " ) ;
2018-09-05 21:05:08 +00:00
DISPLAY ( " -D FILE: use FILE as dictionary \n " ) ;
2013-12-30 17:16:52 +00:00
DISPLAY ( " -f : overwrite output without prompting \n " ) ;
2016-11-28 12:01:02 +00:00
DISPLAY ( " -k : preserve source files(s) (default) \n " ) ;
2016-11-07 13:50:58 +00:00
DISPLAY ( " --rm : remove source file(s) after successful de/compression \n " ) ;
2016-11-28 12:01:02 +00:00
DISPLAY ( " -h/-H : display help/long help and exit \n " ) ;
2013-12-30 17:16:52 +00:00
return 0 ;
}
2016-11-09 22:36:42 +00:00
static int usage_advanced ( const char * exeName )
2013-12-30 17:16:52 +00:00
{
DISPLAY ( WELCOME_MESSAGE ) ;
2016-11-09 22:36:42 +00:00
usage ( exeName ) ;
2013-12-30 17:16:52 +00:00
DISPLAY ( " \n " ) ;
DISPLAY ( " Advanced arguments : \n " ) ;
2016-11-28 12:01:02 +00:00
DISPLAY ( " -V : display Version number and exit \n " ) ;
DISPLAY ( " -v : verbose mode \n " ) ;
2013-12-30 17:16:52 +00:00
DISPLAY ( " -q : suppress warnings; specify twice to suppress errors too \n " ) ;
DISPLAY ( " -c : force write to standard output, even if it is the console \n " ) ;
DISPLAY ( " -t : test compressed file integrity \n " ) ;
2015-03-22 12:42:00 +00:00
DISPLAY ( " -m : multiple input files (implies automatic output filenames) \n " ) ;
2016-11-04 12:30:09 +00:00
# ifdef UTIL_HAS_CREATEFILELIST
2016-11-28 12:01:02 +00:00
DISPLAY ( " -r : operate recursively on directories (sets also -m) \n " ) ;
2016-11-04 12:30:09 +00:00
# endif
2013-12-30 17:16:52 +00:00
DISPLAY ( " -l : compress using Legacy format (Linux kernel compression) \n " ) ;
2018-09-28 16:53:14 +00:00
DISPLAY ( " -B# : cut file into blocks of size # bytes [32+] \n " ) ;
2018-09-28 15:02:49 +00:00
DISPLAY ( " or predefined block size [4-7] (default: 7) \n " ) ;
2019-04-12 20:27:11 +00:00
DISPLAY ( " -BI : Block Independence (default) \n " ) ;
DISPLAY ( " -BD : Block dependency (improves compression ratio) \n " ) ;
2017-08-12 00:58:46 +00:00
DISPLAY ( " -BX : enable block checksum (default:disabled) \n " ) ;
2016-11-28 12:01:02 +00:00
DISPLAY ( " --no-frame-crc : disable stream checksum (default:enabled) \n " ) ;
2015-03-23 18:59:41 +00:00
DISPLAY ( " --content-size : compressed frame includes original size (default:not present) \n " ) ;
2019-05-16 14:12:00 +00:00
DISPLAY ( " --list FILE : lists information about .lz4 files (useful for files compressed with --content-size flag) \n " ) ;
2015-06-22 04:00:44 +00:00
DISPLAY ( " --[no-]sparse : sparse mode (default:enabled on file, disabled on stdout) \n " ) ;
2018-04-26 22:49:32 +00:00
DISPLAY ( " --favor-decSpeed: compressed files decompress faster, but are less compressed \n " ) ;
2018-09-18 23:08:17 +00:00
DISPLAY ( " --fast[=#]: switch to ultra fast compression level (default: %i) \n " , 1 ) ;
2019-07-23 05:37:11 +00:00
DISPLAY ( " --best : same as -%d \n " , LZ4HC_CLEVEL_MAX ) ;
2016-11-28 12:01:02 +00:00
DISPLAY ( " Benchmark arguments : \n " ) ;
2016-09-02 20:59:18 +00:00
DISPLAY ( " -b# : benchmark file(s), using # compression level (default : 1) \n " ) ;
2016-11-04 13:46:45 +00:00
DISPLAY ( " -e# : test all compression levels from -bX to # (default : 1) \n " ) ;
2016-11-28 12:01:02 +00:00
DISPLAY ( " -i# : minimum evaluation time in seconds (default : 3s) \n " ) ;
2017-08-14 23:56:05 +00:00
if ( g_lz4c_legacy_commands ) {
DISPLAY ( " Legacy arguments : \n " ) ;
DISPLAY ( " -c0 : fast compression \n " ) ;
DISPLAY ( " -c1 : high compression \n " ) ;
2017-10-15 06:50:07 +00:00
DISPLAY ( " -c2,-hc: very high compression \n " ) ;
2017-08-14 23:56:05 +00:00
DISPLAY ( " -y : overwrite output without prompting \n " ) ;
}
2013-12-30 17:16:52 +00:00
return 0 ;
}
2016-11-09 22:36:42 +00:00
static int usage_longhelp ( const char * exeName )
2013-12-30 17:16:52 +00:00
{
2016-11-09 22:36:42 +00:00
usage_advanced ( exeName ) ;
2013-12-30 17:16:52 +00:00
DISPLAY ( " \n " ) ;
2015-08-20 13:57:35 +00:00
DISPLAY ( " **************************** \n " ) ;
DISPLAY ( " ***** Advanced comment ***** \n " ) ;
DISPLAY ( " **************************** \n " ) ;
DISPLAY ( " \n " ) ;
DISPLAY ( " Which values can [output] have ? \n " ) ;
DISPLAY ( " --------------------------------- \n " ) ;
DISPLAY ( " [output] : a filename \n " ) ;
2013-12-30 17:16:52 +00:00
DISPLAY ( " '%s', or '-' for standard output (pipe mode) \n " , stdoutmark ) ;
2015-08-20 13:57:35 +00:00
DISPLAY ( " '%s' to discard output (test mode) \n " , NULL_OUTPUT ) ;
DISPLAY ( " [output] can be left empty. In this case, it receives the following value : \n " ) ;
2013-12-30 17:16:52 +00:00
DISPLAY ( " - if stdout is not the console, then [output] = stdout \n " ) ;
DISPLAY ( " - if stdout is console : \n " ) ;
2015-08-20 13:57:35 +00:00
DISPLAY ( " + for compression, output to filename%s \n " , LZ4_EXTENSION ) ;
DISPLAY ( " + for decompression, output to filename without '%s' \n " , LZ4_EXTENSION ) ;
DISPLAY ( " > if input filename has no '%s' extension : error \n " , LZ4_EXTENSION ) ;
2013-12-30 17:16:52 +00:00
DISPLAY ( " \n " ) ;
DISPLAY ( " Compression levels : \n " ) ;
2015-08-20 13:57:35 +00:00
DISPLAY ( " --------------------- \n " ) ;
DISPLAY ( " -0 ... -2 => Fast compression, all identicals \n " ) ;
2016-12-22 10:41:05 +00:00
DISPLAY ( " -3 ... -%d => High compression; higher number == more compression but slower \n " , LZ4HC_CLEVEL_MAX ) ;
2013-12-30 17:16:52 +00:00
DISPLAY ( " \n " ) ;
DISPLAY ( " stdin, stdout and the console : \n " ) ;
2015-08-20 13:57:35 +00:00
DISPLAY ( " -------------------------------- \n " ) ;
2013-12-30 17:16:52 +00:00
DISPLAY ( " To protect the console from binary flooding (bad argument mistake) \n " ) ;
2016-11-09 22:36:42 +00:00
DISPLAY ( " %s will refuse to read from console, or write to console \n " , exeName ) ;
2013-12-30 17:16:52 +00:00
DISPLAY ( " except if '-c' command is specified, to force output to console \n " ) ;
DISPLAY ( " \n " ) ;
DISPLAY ( " Simple example : \n " ) ;
2015-08-20 13:57:35 +00:00
DISPLAY ( " ---------------- \n " ) ;
2013-12-30 17:16:52 +00:00
DISPLAY ( " 1 : compress 'filename' fast, using default output name 'filename.lz4' \n " ) ;
2016-11-09 22:36:42 +00:00
DISPLAY ( " %s filename \n " , exeName ) ;
2013-12-30 17:16:52 +00:00
DISPLAY ( " \n " ) ;
2015-08-20 13:57:35 +00:00
DISPLAY ( " Short arguments can be aggregated. For example : \n " ) ;
DISPLAY ( " ---------------------------------- \n " ) ;
2013-12-30 17:16:52 +00:00
DISPLAY ( " 2 : compress 'filename' in high compression mode, overwrite output if exists \n " ) ;
2016-11-09 22:36:42 +00:00
DISPLAY ( " %s -9 -f filename \n " , exeName ) ;
2013-12-30 17:16:52 +00:00
DISPLAY ( " is equivalent to : \n " ) ;
2016-11-09 22:36:42 +00:00
DISPLAY ( " %s -9f filename \n " , exeName ) ;
2013-12-30 17:16:52 +00:00
DISPLAY ( " \n " ) ;
2016-11-09 22:36:42 +00:00
DISPLAY ( " %s can be used in 'pure pipe mode'. For example : \n " , exeName ) ;
2015-08-20 13:57:35 +00:00
DISPLAY ( " ------------------------------------- \n " ) ;
2013-12-30 17:16:52 +00:00
DISPLAY ( " 3 : compress data stream from 'generator', send result to 'consumer' \n " ) ;
2016-11-09 22:36:42 +00:00
DISPLAY ( " generator | %s | consumer \n " , exeName ) ;
2017-08-14 23:56:05 +00:00
if ( g_lz4c_legacy_commands ) {
DISPLAY ( " \n " ) ;
2017-10-15 06:50:07 +00:00
DISPLAY ( " ***** Warning ***** \n " ) ;
2017-08-14 23:56:05 +00:00
DISPLAY ( " Legacy arguments take precedence. Therefore : \n " ) ;
2017-10-15 06:50:07 +00:00
DISPLAY ( " --------------------------------- \n " ) ;
DISPLAY ( " %s -hc filename \n " , exeName ) ;
DISPLAY ( " means 'compress filename in high compression mode' \n " ) ;
DISPLAY ( " It is not equivalent to : \n " ) ;
DISPLAY ( " %s -h -c filename \n " , exeName ) ;
DISPLAY ( " which displays help text and exits \n " ) ;
2017-08-14 23:56:05 +00:00
}
2013-12-30 17:16:52 +00:00
return 0 ;
}
2016-11-09 22:36:42 +00:00
static int badusage ( const char * exeName )
2013-12-30 17:16:52 +00:00
{
DISPLAYLEVEL ( 1 , " Incorrect parameters \n " ) ;
2016-11-09 22:36:42 +00:00
if ( displayLevel > = 1 ) usage ( exeName ) ;
2013-12-30 17:16:52 +00:00
exit ( 1 ) ;
}
2014-12-13 14:05:46 +00:00
static void waitEnter ( void )
2013-12-30 17:16:52 +00:00
{
DISPLAY ( " Press enter to continue... \n " ) ;
2015-04-12 07:21:35 +00:00
( void ) getchar ( ) ;
2013-12-30 17:16:52 +00:00
}
2016-12-07 22:29:22 +00:00
static const char * lastNameFromPath ( const char * path )
{
2017-03-24 23:33:14 +00:00
const char * name = path ;
if ( strrchr ( name , ' / ' ) ) name = strrchr ( name , ' / ' ) + 1 ;
if ( strrchr ( name , ' \\ ' ) ) name = strrchr ( name , ' \\ ' ) + 1 ; /* windows */
return name ;
}
/*! exeNameMatch() :
@ return : a non - zero value if exeName matches test , excluding the extension
*/
static int exeNameMatch ( const char * exeName , const char * test )
{
return ! strncmp ( exeName , test , strlen ( test ) ) & &
( exeName [ strlen ( test ) ] = = ' \0 ' | | exeName [ strlen ( test ) ] = = ' . ' ) ;
2016-12-07 22:29:22 +00:00
}
2013-12-30 17:16:52 +00:00
2016-09-02 20:59:18 +00:00
/*! readU32FromChar() :
2019-04-12 20:27:11 +00:00
* @ return : unsigned integer value read from input in ` char ` format
* allows and interprets K , KB , KiB , M , MB and MiB suffix .
* Will also modify ` * stringPtr ` , advancing it to position where it stopped reading .
* Note : function result can overflow if digit string > MAX_UINT */
2016-09-02 20:59:18 +00:00
static unsigned readU32FromChar ( const char * * stringPtr )
{
unsigned result = 0 ;
2017-09-10 21:32:38 +00:00
while ( ( * * stringPtr > = ' 0 ' ) & & ( * * stringPtr < = ' 9 ' ) ) {
result * = 10 ;
2019-04-12 20:27:11 +00:00
result + = ( unsigned ) ( * * stringPtr - ' 0 ' ) ;
2017-09-10 21:32:38 +00:00
( * stringPtr ) + + ;
}
2017-05-26 21:38:47 +00:00
if ( ( * * stringPtr = = ' K ' ) | | ( * * stringPtr = = ' M ' ) ) {
result < < = 10 ;
if ( * * stringPtr = = ' M ' ) result < < = 10 ;
( * stringPtr ) + + ;
if ( * * stringPtr = = ' i ' ) ( * stringPtr ) + + ;
if ( * * stringPtr = = ' B ' ) ( * stringPtr ) + + ;
}
2016-09-02 20:59:18 +00:00
return result ;
}
2018-06-26 00:46:39 +00:00
/** longCommandWArg() :
* check if * stringPtr is the same as longCommand .
* If yes , @ return 1 and advances * stringPtr to the position which immediately follows longCommand .
* @ return 0 and doesn ' t modify * stringPtr otherwise .
*/
2019-04-12 20:27:11 +00:00
static int longCommandWArg ( const char * * stringPtr , const char * longCommand )
2018-06-26 00:46:39 +00:00
{
size_t const comSize = strlen ( longCommand ) ;
int const result = ! strncmp ( * stringPtr , longCommand , comSize ) ;
if ( result ) * stringPtr + = comSize ;
return result ;
}
2019-04-20 21:06:10 +00:00
typedef enum { om_auto , om_compress , om_decompress , om_test , om_bench , om_list } operationMode_e ;
2016-09-02 20:59:18 +00:00
2019-01-09 01:56:04 +00:00
/** determineOpMode() :
* auto - determine operation mode , based on input filename extension
* @ return ` om_decompress ` if input filename has . lz4 extension and ` om_compress ` otherwise .
*/
static operationMode_e determineOpMode ( const char * inputFilename )
{
size_t const inSize = strlen ( inputFilename ) ;
size_t const extSize = strlen ( LZ4_EXTENSION ) ;
size_t const extStart = ( inSize > extSize ) ? inSize - extSize : 0 ;
if ( ! strcmp ( inputFilename + extStart , LZ4_EXTENSION ) ) return om_decompress ;
else return om_compress ;
}
2016-06-29 10:54:23 +00:00
int main ( int argc , const char * * argv )
2013-12-30 17:16:52 +00:00
{
int i ,
2016-09-02 20:59:18 +00:00
cLevel = 1 ,
2018-06-26 00:46:39 +00:00
cLevelLast = - 10000 ,
2013-12-30 17:16:52 +00:00
legacy_format = 0 ,
forceStdout = 0 ,
2015-03-02 01:00:40 +00:00
main_pause = 0 ,
2015-04-12 23:41:55 +00:00
multiple_inputs = 0 ,
2017-03-23 03:48:51 +00:00
all_arguments_are_files = 0 ,
2015-04-13 19:43:54 +00:00
operationResult = 0 ;
2016-11-09 22:36:42 +00:00
operationMode_e mode = om_auto ;
2016-11-09 23:04:55 +00:00
const char * input_filename = NULL ;
const char * output_filename = NULL ;
2017-09-22 18:55:42 +00:00
const char * dictionary_filename = NULL ;
2016-11-09 23:04:55 +00:00
char * dynNameSpace = NULL ;
2019-04-12 20:27:11 +00:00
const char * * inFileNames = ( const char * * ) calloc ( ( size_t ) argc , sizeof ( char * ) ) ;
2015-03-07 12:23:00 +00:00
unsigned ifnIdx = 0 ;
2019-01-11 04:40:00 +00:00
LZ4IO_prefs_t * const prefs = LZ4IO_defaultPreferences ( ) ;
2016-11-09 22:36:42 +00:00
const char nullOutput [ ] = NULL_OUTPUT ;
const char extension [ ] = LZ4_EXTENSION ;
2019-01-10 23:27:47 +00:00
size_t blockSize = LZ4IO_setBlockSizeID ( prefs , LZ4_BLOCKSIZEID_DEFAULT ) ;
2016-12-07 22:29:22 +00:00
const char * const exeName = lastNameFromPath ( argv [ 0 ] ) ;
2016-11-04 12:30:09 +00:00
# ifdef UTIL_HAS_CREATEFILELIST
const char * * extendedFileList = NULL ;
char * fileNamesBuf = NULL ;
unsigned fileNamesNb , recursive = 0 ;
# endif
2013-12-30 17:16:52 +00:00
2014-12-16 21:03:16 +00:00
/* Init */
2016-11-15 22:01:37 +00:00
if ( inFileNames = = NULL ) {
DISPLAY ( " Allocation error : not enough memory \n " ) ;
return 1 ;
}
2016-12-08 22:17:40 +00:00
inFileNames [ 0 ] = stdinmark ;
2019-01-10 23:27:47 +00:00
LZ4IO_setOverwrite ( prefs , 0 ) ;
2013-12-30 17:16:52 +00:00
2017-08-14 23:56:05 +00:00
/* predefined behaviors, based on binary/link name */
2017-03-24 23:33:14 +00:00
if ( exeNameMatch ( exeName , LZ4CAT ) ) {
2016-11-10 00:57:33 +00:00
mode = om_decompress ;
2019-01-10 23:27:47 +00:00
LZ4IO_setOverwrite ( prefs , 1 ) ;
LZ4IO_setPassThrough ( prefs , 1 ) ;
LZ4IO_setRemoveSrcFile ( prefs , 0 ) ;
2016-11-10 00:57:33 +00:00
forceStdout = 1 ;
output_filename = stdoutmark ;
displayLevel = 1 ;
multiple_inputs = 1 ;
}
2017-03-24 23:33:14 +00:00
if ( exeNameMatch ( exeName , UNLZ4 ) ) { mode = om_decompress ; }
2017-08-14 23:56:05 +00:00
if ( exeNameMatch ( exeName , LZ4_LEGACY ) ) { g_lz4c_legacy_commands = 1 ; }
2014-03-23 11:15:37 +00:00
2014-12-16 21:03:16 +00:00
/* command switches */
2016-06-29 10:54:23 +00:00
for ( i = 1 ; i < argc ; i + + ) {
const char * argument = argv [ i ] ;
2013-12-30 17:16:52 +00:00
2014-12-16 21:03:16 +00:00
if ( ! argument ) continue ; /* Protection if argument empty */
2013-12-30 17:16:52 +00:00
2015-03-22 12:42:00 +00:00
/* Short commands (note : aggregated short commands are allowed) */
2017-03-23 03:48:51 +00:00
if ( ! all_arguments_are_files & & argument [ 0 ] = = ' - ' ) {
2014-12-16 21:03:16 +00:00
/* '-' means stdin/stdout */
2016-06-29 10:54:23 +00:00
if ( argument [ 1 ] = = 0 ) {
2013-12-30 17:16:52 +00:00
if ( ! input_filename ) input_filename = stdinmark ;
else output_filename = stdoutmark ;
2016-11-10 00:37:16 +00:00
continue ;
}
/* long commands (--long-word) */
if ( argument [ 1 ] = = ' - ' ) {
2017-03-23 03:48:51 +00:00
if ( ! strcmp ( argument , " -- " ) ) { all_arguments_are_files = 1 ; continue ; }
2016-11-10 00:37:16 +00:00
if ( ! strcmp ( argument , " --compress " ) ) { mode = om_compress ; continue ; }
if ( ( ! strcmp ( argument , " --decompress " ) )
| | ( ! strcmp ( argument , " --uncompress " ) ) ) { mode = om_decompress ; continue ; }
2016-11-15 22:01:37 +00:00
if ( ! strcmp ( argument , " --multiple " ) ) { multiple_inputs = 1 ; continue ; }
2016-11-10 00:37:16 +00:00
if ( ! strcmp ( argument , " --test " ) ) { mode = om_test ; continue ; }
2019-01-10 23:27:47 +00:00
if ( ! strcmp ( argument , " --force " ) ) { LZ4IO_setOverwrite ( prefs , 1 ) ; continue ; }
if ( ! strcmp ( argument , " --no-force " ) ) { LZ4IO_setOverwrite ( prefs , 0 ) ; continue ; }
2016-11-10 00:37:16 +00:00
if ( ( ! strcmp ( argument , " --stdout " ) )
| | ( ! strcmp ( argument , " --to-stdout " ) ) ) { forceStdout = 1 ; output_filename = stdoutmark ; continue ; }
2019-01-10 23:27:47 +00:00
if ( ! strcmp ( argument , " --frame-crc " ) ) { LZ4IO_setStreamChecksumMode ( prefs , 1 ) ; continue ; }
if ( ! strcmp ( argument , " --no-frame-crc " ) ) { LZ4IO_setStreamChecksumMode ( prefs , 0 ) ; continue ; }
if ( ! strcmp ( argument , " --content-size " ) ) { LZ4IO_setContentSize ( prefs , 1 ) ; continue ; }
if ( ! strcmp ( argument , " --no-content-size " ) ) { LZ4IO_setContentSize ( prefs , 0 ) ; continue ; }
2019-04-20 21:06:10 +00:00
if ( ! strcmp ( argument , " --list " ) ) { mode = om_list ; continue ; }
2019-01-10 23:27:47 +00:00
if ( ! strcmp ( argument , " --sparse " ) ) { LZ4IO_setSparseFile ( prefs , 2 ) ; continue ; }
if ( ! strcmp ( argument , " --no-sparse " ) ) { LZ4IO_setSparseFile ( prefs , 0 ) ; continue ; }
if ( ! strcmp ( argument , " --favor-decSpeed " ) ) { LZ4IO_favorDecSpeed ( prefs , 1 ) ; continue ; }
2016-11-10 00:37:16 +00:00
if ( ! strcmp ( argument , " --verbose " ) ) { displayLevel + + ; continue ; }
if ( ! strcmp ( argument , " --quiet " ) ) { if ( displayLevel ) displayLevel - - ; continue ; }
2019-06-24 23:08:30 +00:00
if ( ! strcmp ( argument , " --version " ) ) { DISPLAYOUT ( WELCOME_MESSAGE ) ; return 0 ; }
2016-11-14 04:50:58 +00:00
if ( ! strcmp ( argument , " --help " ) ) { usage_advanced ( exeName ) ; goto _cleanup ; }
2019-01-10 23:27:47 +00:00
if ( ! strcmp ( argument , " --keep " ) ) { LZ4IO_setRemoveSrcFile ( prefs , 0 ) ; continue ; } /* keep source file (default) */
if ( ! strcmp ( argument , " --rm " ) ) { LZ4IO_setRemoveSrcFile ( prefs , 1 ) ; continue ; }
2018-06-26 00:46:39 +00:00
if ( longCommandWArg ( & argument , " --fast " ) ) {
2018-06-27 00:31:15 +00:00
/* Parse optional acceleration factor */
2018-06-26 00:46:39 +00:00
if ( * argument = = ' = ' ) {
U32 fastLevel ;
+ + argument ;
fastLevel = readU32FromChar ( & argument ) ;
if ( fastLevel ) {
cLevel = - ( int ) fastLevel ;
2018-06-27 00:53:12 +00:00
} else {
2018-06-27 00:31:15 +00:00
badusage ( exeName ) ;
}
2018-06-26 00:46:39 +00:00
} else if ( * argument ! = 0 ) {
/* Invalid character following --fast */
2018-06-27 00:31:15 +00:00
badusage ( exeName ) ;
2018-06-26 00:46:39 +00:00
} else {
cLevel = - 1 ; /* default for --fast */
}
continue ;
}
2019-07-23 05:37:11 +00:00
/* For gzip(1) compatibility */
if ( ! strcmp ( argument , " --best " ) ) { cLevel = LZ4HC_CLEVEL_MAX ; continue ; }
2013-12-30 17:16:52 +00:00
}
2016-06-29 10:54:23 +00:00
while ( argument [ 1 ] ! = 0 ) {
2013-12-30 17:16:52 +00:00
argument + + ;
2017-08-14 23:56:05 +00:00
if ( g_lz4c_legacy_commands ) {
/* Legacy commands (-c0, -c1, -hc, -y) */
2017-10-15 06:50:07 +00:00
if ( ! strcmp ( argument , " c0 " ) ) { cLevel = 0 ; argument + + ; continue ; } /* -c0 (fast compression) */
if ( ! strcmp ( argument , " c1 " ) ) { cLevel = 9 ; argument + + ; continue ; } /* -c1 (high compression) */
if ( ! strcmp ( argument , " c2 " ) ) { cLevel = 12 ; argument + + ; continue ; } /* -c2 (very high compression) */
if ( ! strcmp ( argument , " hc " ) ) { cLevel = 12 ; argument + + ; continue ; } /* -hc (very high compression) */
2019-01-10 23:27:47 +00:00
if ( ! strcmp ( argument , " y " ) ) { LZ4IO_setOverwrite ( prefs , 1 ) ; continue ; } /* -y (answer 'yes' to overwrite permission) */
2017-08-14 23:56:05 +00:00
}
2013-12-30 17:16:52 +00:00
2016-06-29 10:54:23 +00:00
if ( ( * argument > = ' 0 ' ) & & ( * argument < = ' 9 ' ) ) {
2019-04-12 20:27:11 +00:00
cLevel = ( int ) readU32FromChar ( & argument ) ;
2014-06-11 21:02:46 +00:00
argument - - ;
continue ;
}
2016-09-02 20:59:18 +00:00
2013-12-30 17:16:52 +00:00
switch ( argument [ 0 ] )
{
2014-12-16 21:03:16 +00:00
/* Display help */
2019-06-24 23:08:30 +00:00
case ' V ' : DISPLAYOUT ( WELCOME_MESSAGE ) ; goto _cleanup ; /* Version */
2016-11-09 22:36:42 +00:00
case ' h ' : usage_advanced ( exeName ) ; goto _cleanup ;
case ' H ' : usage_longhelp ( exeName ) ; goto _cleanup ;
2013-12-30 17:16:52 +00:00
2016-09-02 20:59:18 +00:00
case ' e ' :
argument + + ;
2019-04-12 20:27:11 +00:00
cLevelLast = ( int ) readU32FromChar ( & argument ) ;
2016-09-02 20:59:18 +00:00
argument - - ;
break ;
2014-12-16 21:03:16 +00:00
/* Compression (default) */
2016-11-09 22:36:42 +00:00
case ' z ' : mode = om_compress ; break ;
2013-12-30 17:16:52 +00:00
2017-09-22 18:55:42 +00:00
case ' D ' :
if ( argument [ 1 ] = = ' \0 ' ) {
/* path is next arg */
if ( i + 1 = = argc ) {
/* there is no next arg */
badusage ( exeName ) ;
}
dictionary_filename = argv [ + + i ] ;
} else {
/* path follows immediately */
dictionary_filename = argument + 1 ;
}
/* skip to end of argument so that we jump to parsing next argument */
argument + = strlen ( argument ) - 1 ;
break ;
2014-12-16 21:03:16 +00:00
/* Use Legacy format (ex : Linux kernel compression) */
case ' l ' : legacy_format = 1 ; blockSize = 8 MB ; break ;
2013-12-30 17:16:52 +00:00
2014-12-16 21:03:16 +00:00
/* Decoding */
2016-11-09 22:36:42 +00:00
case ' d ' : mode = om_decompress ; break ;
2013-12-30 17:16:52 +00:00
2014-12-16 21:03:16 +00:00
/* Force stdout, even if stdout==console */
2019-01-10 18:20:17 +00:00
case ' c ' :
forceStdout = 1 ;
output_filename = stdoutmark ;
2019-01-10 23:27:47 +00:00
LZ4IO_setPassThrough ( prefs , 1 ) ;
2019-01-10 18:20:17 +00:00
break ;
2013-12-30 17:16:52 +00:00
2014-12-16 21:03:16 +00:00
/* Test integrity */
2016-11-09 22:36:42 +00:00
case ' t ' : mode = om_test ; break ;
2013-12-30 17:16:52 +00:00
2014-12-16 21:03:16 +00:00
/* Overwrite */
2019-01-10 23:27:47 +00:00
case ' f ' : LZ4IO_setOverwrite ( prefs , 1 ) ; break ;
2013-12-30 17:16:52 +00:00
2014-12-16 21:03:16 +00:00
/* Verbose mode */
2016-11-09 22:36:42 +00:00
case ' v ' : displayLevel + + ; break ;
2013-12-30 17:16:52 +00:00
2014-12-16 21:03:16 +00:00
/* Quiet mode */
2015-03-22 12:42:00 +00:00
case ' q ' : if ( displayLevel ) displayLevel - - ; break ;
2013-12-30 17:16:52 +00:00
2014-12-16 21:03:16 +00:00
/* keep source file (default anyway, so useless) (for xz/lzma compatibility) */
2019-01-10 23:27:47 +00:00
case ' k ' : LZ4IO_setRemoveSrcFile ( prefs , 0 ) ; break ;
2013-12-30 17:16:52 +00:00
2014-12-16 21:03:16 +00:00
/* Modify Block Properties */
2013-12-30 17:16:52 +00:00
case ' B ' :
2016-09-03 02:32:06 +00:00
while ( argument [ 1 ] ! = 0 ) {
2013-12-30 17:16:52 +00:00
int exitBlockProperties = 0 ;
switch ( argument [ 1 ] )
{
2019-01-10 23:27:47 +00:00
case ' D ' : LZ4IO_setBlockMode ( prefs , LZ4IO_blockLinked ) ; argument + + ; break ;
2019-04-12 20:27:11 +00:00
case ' I ' : LZ4IO_setBlockMode ( prefs , LZ4IO_blockIndependent ) ; argument + + ; break ;
2019-01-10 23:27:47 +00:00
case ' X ' : LZ4IO_setBlockChecksumMode ( prefs , 1 ) ; argument + + ; break ; /* disabled by default */
2016-11-10 15:31:10 +00:00
default :
if ( argument [ 1 ] < ' 0 ' | | argument [ 1 ] > ' 9 ' ) {
exitBlockProperties = 1 ;
break ;
} else {
unsigned B ;
2016-06-29 10:54:23 +00:00
argument + + ;
2016-11-10 15:31:10 +00:00
B = readU32FromChar ( & argument ) ;
argument - - ;
if ( B < 4 ) badusage ( exeName ) ;
if ( B < = 7 ) {
2019-01-10 23:27:47 +00:00
blockSize = LZ4IO_setBlockSizeID ( prefs , B ) ;
2018-03-20 00:19:25 +00:00
BMK_setBlockSize ( blockSize ) ;
2016-11-10 15:31:10 +00:00
DISPLAYLEVEL ( 2 , " using blocks of size %u KB \n " , ( U32 ) ( blockSize > > 10 ) ) ;
} else {
if ( B < 32 ) badusage ( exeName ) ;
2019-01-10 23:27:47 +00:00
blockSize = LZ4IO_setBlockSize ( prefs , B ) ;
2018-09-28 15:02:49 +00:00
BMK_setBlockSize ( blockSize ) ;
if ( blockSize > = 1024 ) {
DISPLAYLEVEL ( 2 , " using blocks of size %u KB \n " , ( U32 ) ( blockSize > > 10 ) ) ;
2016-11-10 15:31:10 +00:00
} else {
2018-09-28 15:02:49 +00:00
DISPLAYLEVEL ( 2 , " using blocks of size %u bytes \n " , ( U32 ) ( blockSize ) ) ;
2016-11-10 15:31:10 +00:00
}
}
2016-06-29 10:54:23 +00:00
break ;
}
2013-12-30 17:16:52 +00:00
}
if ( exitBlockProperties ) break ;
}
break ;
2014-12-16 21:03:16 +00:00
/* Benchmark */
2016-11-09 22:36:42 +00:00
case ' b ' : mode = om_bench ; multiple_inputs = 1 ;
2015-03-07 12:23:00 +00:00
break ;
2013-12-30 17:16:52 +00:00
2018-03-20 00:19:25 +00:00
/* hidden command : benchmark files, but do not fuse result */
case ' S ' : BMK_setBenchSeparately ( 1 ) ;
break ;
2016-11-04 12:30:09 +00:00
# ifdef UTIL_HAS_CREATEFILELIST
2016-12-08 22:17:40 +00:00
/* recursive */
2017-06-19 05:09:36 +00:00
case ' r ' : recursive = 1 ;
2016-11-04 12:30:09 +00:00
# endif
2017-06-19 05:09:36 +00:00
/* fall-through */
2015-03-07 12:23:00 +00:00
/* Treat non-option args as input files. See https://code.google.com/p/lz4/issues/detail?id=151 */
case ' m ' : multiple_inputs = 1 ;
break ;
2015-03-02 01:00:40 +00:00
2016-11-04 13:46:45 +00:00
/* Modify Nb Seconds (benchmark only) */
2013-12-30 17:16:52 +00:00
case ' i ' :
2016-09-03 02:32:06 +00:00
{ unsigned iters ;
argument + + ;
iters = readU32FromChar ( & argument ) ;
argument - - ;
2016-11-08 12:50:27 +00:00
BMK_setNotificationLevel ( displayLevel ) ;
2018-03-20 00:19:25 +00:00
BMK_setNbSeconds ( iters ) ; /* notification if displayLevel >= 3 */
2013-12-30 17:16:52 +00:00
}
break ;
2014-12-16 21:03:16 +00:00
/* Pause at the end (hidden option) */
2016-11-04 13:46:45 +00:00
case ' p ' : main_pause = 1 ; break ;
2015-02-12 06:46:02 +00:00
2014-12-16 21:03:16 +00:00
/* Unrecognised command */
2016-11-09 22:36:42 +00:00
default : badusage ( exeName ) ;
2013-12-30 17:16:52 +00:00
}
}
continue ;
}
2015-03-07 12:23:00 +00:00
/* Store in *inFileNames[] if -m is used. */
if ( multiple_inputs ) { inFileNames [ ifnIdx + + ] = argument ; continue ; }
2015-03-02 01:00:40 +00:00
/* Store first non-option arg in input_filename to preserve original cli logic. */
2015-03-07 12:23:00 +00:00
if ( ! input_filename ) { input_filename = argument ; continue ; }
2013-12-30 17:16:52 +00:00
2015-03-02 01:00:40 +00:00
/* Second non-option arg in output_filename to preserve original cli logic. */
2016-09-03 02:32:06 +00:00
if ( ! output_filename ) {
2013-12-30 17:16:52 +00:00
output_filename = argument ;
if ( ! strcmp ( output_filename , nullOutput ) ) output_filename = nulmark ;
continue ;
}
2015-03-07 12:23:00 +00:00
/* 3rd non-option arg should not exist */
DISPLAYLEVEL ( 1 , " Warning : %s won't be used ! Do you want multiple input files (-m) ? \n " , argument ) ;
2015-03-02 01:00:40 +00:00
}
2013-12-30 17:16:52 +00:00
2015-03-07 12:23:00 +00:00
DISPLAYLEVEL ( 3 , WELCOME_MESSAGE ) ;
2016-12-20 22:38:32 +00:00
# ifdef _POSIX_C_SOURCE
DISPLAYLEVEL ( 4 , " _POSIX_C_SOURCE defined: %ldL \n " , ( long ) _POSIX_C_SOURCE ) ;
# endif
# ifdef _POSIX_VERSION
DISPLAYLEVEL ( 4 , " _POSIX_VERSION defined: %ldL \n " , ( long ) _POSIX_VERSION ) ;
# endif
# ifdef PLATFORM_POSIX_VERSION
DISPLAYLEVEL ( 4 , " PLATFORM_POSIX_VERSION defined: %ldL \n " , ( long ) PLATFORM_POSIX_VERSION ) ;
2016-12-21 09:22:40 +00:00
# endif
# ifdef _FILE_OFFSET_BITS
DISPLAYLEVEL ( 4 , " _FILE_OFFSET_BITS defined: %ldL \n " , ( long ) _FILE_OFFSET_BITS ) ;
2016-12-20 22:38:32 +00:00
# endif
2017-08-14 23:56:05 +00:00
if ( ( mode = = om_compress ) | | ( mode = = om_bench ) )
DISPLAYLEVEL ( 4 , " Blocks size : %u KB \n " , ( U32 ) ( blockSize > > 10 ) ) ;
2013-12-30 17:16:52 +00:00
2016-11-04 12:30:09 +00:00
if ( multiple_inputs ) {
input_filename = inFileNames [ 0 ] ;
# ifdef UTIL_HAS_CREATEFILELIST
if ( recursive ) { /* at this stage, filenameTable is a list of paths, which can contain both files and directories */
extendedFileList = UTIL_createFileList ( inFileNames , ifnIdx , & fileNamesBuf , & fileNamesNb ) ;
if ( extendedFileList ) {
unsigned u ;
for ( u = 0 ; u < fileNamesNb ; u + + ) DISPLAYLEVEL ( 4 , " %u %s \n " , u , extendedFileList [ u ] ) ;
free ( ( void * ) inFileNames ) ;
inFileNames = extendedFileList ;
ifnIdx = fileNamesNb ;
2017-10-15 01:48:00 +00:00
} }
2016-11-04 12:30:09 +00:00
# endif
}
2013-12-30 17:16:52 +00:00
2016-11-09 22:36:42 +00:00
/* benchmark and test modes */
if ( mode = = om_bench ) {
2016-11-08 12:50:27 +00:00
BMK_setNotificationLevel ( displayLevel ) ;
2016-11-04 12:30:09 +00:00
operationResult = BMK_benchFiles ( inFileNames , ifnIdx , cLevel , cLevelLast ) ;
goto _cleanup ;
2015-04-08 08:20:21 +00:00
}
2015-03-02 01:00:40 +00:00
2016-11-09 22:36:42 +00:00
if ( mode = = om_test ) {
2019-01-10 23:27:47 +00:00
LZ4IO_setTestMode ( prefs , 1 ) ;
2016-11-10 00:57:33 +00:00
output_filename = nulmark ;
2016-11-09 22:36:42 +00:00
mode = om_decompress ; /* defer to decompress */
}
2017-09-22 18:55:42 +00:00
if ( dictionary_filename ) {
if ( ! strcmp ( dictionary_filename , stdinmark ) & & IS_CONSOLE ( stdin ) ) {
DISPLAYLEVEL ( 1 , " refusing to read from a console \n " ) ;
exit ( 1 ) ;
}
2019-01-10 23:27:47 +00:00
LZ4IO_setDictionaryFilename ( prefs , dictionary_filename ) ;
2017-09-22 18:55:42 +00:00
}
2016-11-09 22:36:42 +00:00
/* compress or decompress */
2016-11-10 00:57:33 +00:00
if ( ! input_filename ) input_filename = stdinmark ;
2016-11-09 23:04:55 +00:00
/* Check if input is defined as console; trigger an error in this case */
2016-11-10 00:37:16 +00:00
if ( ! strcmp ( input_filename , stdinmark ) & & IS_CONSOLE ( stdin ) ) {
2016-11-09 23:04:55 +00:00
DISPLAYLEVEL ( 1 , " refusing to read from a console \n " ) ;
exit ( 1 ) ;
}
2019-05-25 18:57:04 +00:00
if ( ! strcmp ( input_filename , stdinmark ) ) {
/* if input==stdin and no output defined, stdout becomes default output */
if ( ! output_filename ) output_filename = stdoutmark ;
}
else {
if ( ! recursive & & ! UTIL_isRegFile ( input_filename ) ) {
DISPLAYLEVEL ( 1 , " %s: is not a regular file \n " , input_filename ) ;
exit ( 1 ) ;
}
}
2016-11-09 23:04:55 +00:00
2015-03-07 12:23:00 +00:00
/* No output filename ==> try to select one automatically (when possible) */
2016-11-28 12:01:02 +00:00
while ( ( ! output_filename ) & & ( multiple_inputs = = 0 ) ) {
2019-04-20 00:08:40 +00:00
if ( ! IS_CONSOLE ( stdout ) ) {
/* Default to stdout whenever stdout is not the console.
2019-04-22 00:01:03 +00:00
* Note : this policy may change in the future , therefore don ' t rely on it !
* To ensure ` stdout ` is explicitly selected , use ` - c ` command flag .
* Conversely , to ensure output will not become ` stdout ` , use ` - m ` command flag */
2019-04-20 00:08:40 +00:00
DISPLAYLEVEL ( 1 , " Warning : using stdout as default output. Do not rely on this behavior: use explicit `-c` instead ! \n " ) ;
output_filename = stdoutmark ;
break ;
}
2016-11-09 22:36:42 +00:00
if ( mode = = om_auto ) { /* auto-determine compression or decompression, based on file extension */
2019-01-09 01:56:04 +00:00
mode = determineOpMode ( input_filename ) ;
2013-12-30 17:16:52 +00:00
}
2016-11-09 22:36:42 +00:00
if ( mode = = om_compress ) { /* compression to file */
2016-06-29 10:54:23 +00:00
size_t const l = strlen ( input_filename ) ;
2015-03-07 12:23:00 +00:00
dynNameSpace = ( char * ) calloc ( 1 , l + 5 ) ;
2016-11-09 22:36:42 +00:00
if ( dynNameSpace = = NULL ) { perror ( exeName ) ; exit ( 1 ) ; }
2015-03-21 12:34:55 +00:00
strcpy ( dynNameSpace , input_filename ) ;
strcat ( dynNameSpace , LZ4_EXTENSION ) ;
2015-03-07 12:23:00 +00:00
output_filename = dynNameSpace ;
DISPLAYLEVEL ( 2 , " Compressed filename will be : %s \n " , output_filename ) ;
break ;
}
2016-11-09 22:36:42 +00:00
if ( mode = = om_decompress ) { /* decompression to file (automatic name will work only if input filename has correct format extension) */
size_t outl ;
size_t const inl = strlen ( input_filename ) ;
2015-03-07 12:23:00 +00:00
dynNameSpace = ( char * ) calloc ( 1 , inl + 1 ) ;
2016-11-09 22:36:42 +00:00
if ( dynNameSpace = = NULL ) { perror ( exeName ) ; exit ( 1 ) ; }
2015-03-21 12:34:55 +00:00
strcpy ( dynNameSpace , input_filename ) ;
2015-03-07 12:23:00 +00:00
outl = inl ;
if ( inl > 4 )
2015-03-21 12:34:55 +00:00
while ( ( outl > = inl - 4 ) & & ( input_filename [ outl ] = = extension [ outl - inl + 4 ] ) ) dynNameSpace [ outl - - ] = 0 ;
2016-11-09 22:36:42 +00:00
if ( outl ! = inl - 5 ) { DISPLAYLEVEL ( 1 , " Cannot determine an output filename \n " ) ; badusage ( exeName ) ; }
2015-03-21 12:34:55 +00:00
output_filename = dynNameSpace ;
2015-03-07 12:23:00 +00:00
DISPLAYLEVEL ( 2 , " Decoding file %s \n " , output_filename ) ;
}
2016-11-09 22:36:42 +00:00
break ;
2015-03-07 12:23:00 +00:00
}
2013-12-30 17:16:52 +00:00
2019-05-16 14:12:00 +00:00
if ( mode = = om_list ) {
/* Exit if trying to read from stdin as this isn't supported in this mode */
if ( ! strcmp ( input_filename , stdinmark ) ) {
DISPLAYLEVEL ( 1 , " refusing to read from standard input in --list mode \n " ) ;
exit ( 1 ) ;
}
if ( ! multiple_inputs ) {
inFileNames [ ifnIdx + + ] = input_filename ;
}
}
else {
if ( multiple_inputs = = 0 ) assert ( output_filename ) ;
}
2019-04-20 00:08:40 +00:00
/* when multiple_inputs==1, output_filename may simply be useless,
* however , output_filename must be ! NULL for next strcmp ( ) tests */
2016-12-08 22:17:40 +00:00
if ( ! output_filename ) output_filename = " * \\ dummy^!// " ;
2019-04-20 00:08:40 +00:00
/* Check if output is defined as console; trigger an error in this case */
2016-06-29 10:54:23 +00:00
if ( ! strcmp ( output_filename , stdoutmark ) & & IS_CONSOLE ( stdout ) & & ! forceStdout ) {
2019-04-20 00:08:40 +00:00
DISPLAYLEVEL ( 1 , " refusing to write to console without -c \n " ) ;
2015-09-03 01:43:27 +00:00
exit ( 1 ) ;
}
2016-11-10 00:37:16 +00:00
/* Downgrade notification level in stdout and multiple file mode */
if ( ! strcmp ( output_filename , stdoutmark ) & & ( displayLevel = = 2 ) ) displayLevel = 1 ;
2015-04-16 06:16:48 +00:00
if ( ( multiple_inputs ) & & ( displayLevel = = 2 ) ) displayLevel = 1 ;
2013-12-30 17:16:52 +00:00
2019-01-09 01:56:04 +00:00
/* Auto-determine compression or decompression, based on file extension */
if ( mode = = om_auto ) {
mode = determineOpMode ( input_filename ) ;
}
2015-03-07 12:23:00 +00:00
/* IO Stream/File */
2019-04-12 20:27:11 +00:00
LZ4IO_setNotificationLevel ( ( int ) displayLevel ) ;
2016-12-08 22:17:40 +00:00
if ( ifnIdx = = 0 ) multiple_inputs = 0 ;
2016-11-09 22:36:42 +00:00
if ( mode = = om_decompress ) {
2019-04-20 00:08:40 +00:00
if ( multiple_inputs ) {
assert ( ifnIdx < = INT_MAX ) ;
operationResult = LZ4IO_decompressMultipleFilenames ( prefs , inFileNames , ( int ) ifnIdx , ! strcmp ( output_filename , stdoutmark ) ? stdoutmark : LZ4_EXTENSION ) ;
} else {
2019-01-10 23:27:47 +00:00
operationResult = DEFAULT_DECOMPRESSOR ( prefs , input_filename , output_filename ) ;
2019-04-22 08:58:26 +00:00
}
} else if ( mode = = om_list ) {
operationResult = LZ4IO_displayCompressedFilesInfo ( inFileNames , ifnIdx ) ;
} else { /* compression is default action */
2016-09-03 02:32:06 +00:00
if ( legacy_format ) {
2017-10-15 01:48:00 +00:00
DISPLAYLEVEL ( 3 , " ! Generating LZ4 Legacy format (deprecated) ! \n " ) ;
2019-01-10 23:27:47 +00:00
LZ4IO_compressFilename_Legacy ( prefs , input_filename , output_filename , cLevel ) ;
2016-09-03 02:32:06 +00:00
} else {
2019-04-20 00:08:40 +00:00
if ( multiple_inputs ) {
assert ( ifnIdx < = INT_MAX ) ;
operationResult = LZ4IO_compressMultipleFilenames ( prefs , inFileNames , ( int ) ifnIdx , ! strcmp ( output_filename , stdoutmark ) ? stdoutmark : LZ4_EXTENSION , cLevel ) ;
} else {
2019-01-10 23:27:47 +00:00
operationResult = DEFAULT_COMPRESSOR ( prefs , input_filename , output_filename , cLevel ) ;
2019-04-20 00:08:40 +00:00
} } }
2013-12-30 17:16:52 +00:00
2015-06-27 21:21:33 +00:00
_cleanup :
2014-11-30 22:32:12 +00:00
if ( main_pause ) waitEnter ( ) ;
2017-10-15 01:48:00 +00:00
free ( dynNameSpace ) ;
2016-11-04 12:30:09 +00:00
# ifdef UTIL_HAS_CREATEFILELIST
2017-10-15 01:48:00 +00:00
if ( extendedFileList ) {
2016-11-04 12:30:09 +00:00
UTIL_freeFileList ( extendedFileList , fileNamesBuf ) ;
2017-10-15 01:48:00 +00:00
inFileNames = NULL ;
}
2016-11-04 12:30:09 +00:00
# endif
2019-01-10 23:27:47 +00:00
LZ4IO_freePreferences ( prefs ) ;
2017-10-15 01:48:00 +00:00
free ( ( void * ) inFileNames ) ;
2015-06-27 21:21:33 +00:00
return operationResult ;
2019-04-22 19:27:25 +00:00
}