51 #define COMPRESSOR_NAME "LZ4 command line interface"
52 #define AUTHOR "Yann Collet"
53 #define WELCOME_MESSAGE "*** %s %i-bits v%s, by %s ***\n", COMPRESSOR_NAME, (int)(sizeof(void*)*8), LZ4_versionString(), AUTHOR
54 #define LZ4_EXTENSION ".lz4"
55 #define LZ4CAT "lz4cat"
57 #define LZ4_LEGACY "lz4c"
64 #define LZ4_BLOCKSIZEID_DEFAULT 7
70 #define DISPLAYOUT(...) fprintf(stdout, __VA_ARGS__)
71 #define DISPLAY(...) fprintf(stderr, __VA_ARGS__)
72 #define DISPLAYLEVEL(l, ...) if (displayLevel>=l) { DISPLAY(__VA_ARGS__); }
80 #define DEBUGOUTPUT(...) if (DEBUG) DISPLAY(__VA_ARGS__);
81 #define EXM_THROW(error, ...) \
83 DEBUGOUTPUT("Error defined at %s, line %i : \n", __FILE__, __LINE__); \
84 DISPLAYLEVEL(1, "Error %i : ", error); \
85 DISPLAYLEVEL(1, __VA_ARGS__); \
86 DISPLAYLEVEL(1, "\n"); \
94 #define DEFAULT_COMPRESSOR LZ4IO_compressFilename
95 #define DEFAULT_DECOMPRESSOR LZ4IO_decompressFilename
98 const char** inFileNamesTable,
int ifntSize,
105 static int usage(
const char* exeName)
108 DISPLAY(
" %s [arg] [input] [output] \n", exeName);
110 DISPLAY(
"input : a filename \n");
111 DISPLAY(
" with no FILE, or when FILE is - or %s, read standard input\n",
stdinmark);
113 DISPLAY(
" -1 : Fast compression (default) \n");
114 DISPLAY(
" -9 : High compression \n");
116 DISPLAY(
" -z : force compression \n");
117 DISPLAY(
" -D FILE: use FILE as dictionary \n");
118 DISPLAY(
" -f : overwrite output without prompting \n");
119 DISPLAY(
" -k : preserve source files(s) (default) \n");
120 DISPLAY(
"--rm : remove source file(s) after successful de/compression \n");
121 DISPLAY(
" -h/-H : display help/long help and exit \n");
130 DISPLAY(
"Advanced arguments :\n");
131 DISPLAY(
" -V : display Version number and exit \n");
132 DISPLAY(
" -v : verbose mode \n");
133 DISPLAY(
" -q : suppress warnings; specify twice to suppress errors too\n");
134 DISPLAY(
" -c : force write to standard output, even if it is the console\n");
135 DISPLAY(
" -t : test compressed file integrity\n");
136 DISPLAY(
" -m : multiple input files (implies automatic output filenames)\n");
137 #ifdef UTIL_HAS_CREATEFILELIST
138 DISPLAY(
" -r : operate recursively on directories (sets also -m) \n");
140 DISPLAY(
" -l : compress using Legacy format (Linux kernel compression)\n");
141 DISPLAY(
" -B# : cut file into blocks of size # bytes [32+] \n");
142 DISPLAY(
" or predefined block size [4-7] (default: 7) \n");
143 DISPLAY(
" -BI : Block Independence (default) \n");
144 DISPLAY(
" -BD : Block dependency (improves compression ratio) \n");
145 DISPLAY(
" -BX : enable block checksum (default:disabled) \n");
146 DISPLAY(
"--no-frame-crc : disable stream checksum (default:enabled) \n");
147 DISPLAY(
"--content-size : compressed frame includes original size (default:not present)\n");
148 DISPLAY(
"--list FILE : lists information about .lz4 files (useful for files compressed with --content-size flag)\n");
149 DISPLAY(
"--[no-]sparse : sparse mode (default:enabled on file, disabled on stdout)\n");
150 DISPLAY(
"--favor-decSpeed: compressed files decompress faster, but are less compressed \n");
151 DISPLAY(
"--fast[=#]: switch to ultra fast compression level (default: %i)\n", 1);
153 DISPLAY(
"Benchmark arguments : \n");
154 DISPLAY(
" -b# : benchmark file(s), using # compression level (default : 1) \n");
155 DISPLAY(
" -e# : test all compression levels from -bX to # (default : 1)\n");
156 DISPLAY(
" -i# : minimum evaluation time in seconds (default : 3s) \n");
158 DISPLAY(
"Legacy arguments : \n");
159 DISPLAY(
" -c0 : fast compression \n");
160 DISPLAY(
" -c1 : high compression \n");
161 DISPLAY(
" -c2,-hc: very high compression \n");
162 DISPLAY(
" -y : overwrite output without prompting \n");
171 DISPLAY(
"****************************\n");
172 DISPLAY(
"***** Advanced comment *****\n");
173 DISPLAY(
"****************************\n");
175 DISPLAY(
"Which values can [output] have ? \n");
176 DISPLAY(
"---------------------------------\n");
177 DISPLAY(
"[output] : a filename \n");
180 DISPLAY(
"[output] can be left empty. In this case, it receives the following value :\n");
181 DISPLAY(
" - if stdout is not the console, then [output] = stdout \n");
182 DISPLAY(
" - if stdout is console : \n");
187 DISPLAY(
"Compression levels : \n");
188 DISPLAY(
"---------------------\n");
189 DISPLAY(
"-0 ... -2 => Fast compression, all identicals\n");
192 DISPLAY(
"stdin, stdout and the console : \n");
193 DISPLAY(
"--------------------------------\n");
194 DISPLAY(
"To protect the console from binary flooding (bad argument mistake)\n");
195 DISPLAY(
"%s will refuse to read from console, or write to console \n", exeName);
196 DISPLAY(
"except if '-c' command is specified, to force output to console \n");
198 DISPLAY(
"Simple example :\n");
199 DISPLAY(
"----------------\n");
200 DISPLAY(
"1 : compress 'filename' fast, using default output name 'filename.lz4'\n");
201 DISPLAY(
" %s filename\n", exeName);
203 DISPLAY(
"Short arguments can be aggregated. For example :\n");
204 DISPLAY(
"----------------------------------\n");
205 DISPLAY(
"2 : compress 'filename' in high compression mode, overwrite output if exists\n");
206 DISPLAY(
" %s -9 -f filename \n", exeName);
207 DISPLAY(
" is equivalent to :\n");
208 DISPLAY(
" %s -9f filename \n", exeName);
210 DISPLAY(
"%s can be used in 'pure pipe mode'. For example :\n", exeName);
211 DISPLAY(
"-------------------------------------\n");
212 DISPLAY(
"3 : compress data stream from 'generator', send result to 'consumer'\n");
213 DISPLAY(
" generator | %s | consumer \n", exeName);
216 DISPLAY(
"***** Warning ***** \n");
217 DISPLAY(
"Legacy arguments take precedence. Therefore : \n");
218 DISPLAY(
"--------------------------------- \n");
219 DISPLAY(
" %s -hc filename \n", exeName);
220 DISPLAY(
"means 'compress filename in high compression mode' \n");
221 DISPLAY(
"It is not equivalent to : \n");
222 DISPLAY(
" %s -h -c filename \n", exeName);
223 DISPLAY(
"which displays help text and exits \n");
238 DISPLAY(
"Press enter to continue...\n");
246 if (strrchr(
name,
'\\'))
name = strrchr(
name,
'\\') + 1;
255 return !strncmp(exeName,
test, strlen(
test)) &&
256 (exeName[strlen(
test)] ==
'\0' || exeName[strlen(
test)] ==
'.');
267 while ((**stringPtr >=
'0') && (**stringPtr <=
'9')) {
269 result += (
unsigned)(**stringPtr -
'0');
272 if ((**stringPtr==
'K') || (**stringPtr==
'M')) {
274 if (**stringPtr==
'M') result <<= 10;
276 if (**stringPtr==
'i') (*stringPtr)++;
277 if (**stringPtr==
'B') (*stringPtr)++;
289 size_t const comSize = strlen(longCommand);
290 int const result = !strncmp(*stringPtr, longCommand, comSize);
291 if (result) *stringPtr += comSize;
303 size_t const inSize = strlen(inputFilename);
305 size_t const extStart= (inSize > extSize) ? inSize-extSize : 0;
319 all_arguments_are_files=0,
322 const char* input_filename =
NULL;
323 const char* output_filename=
NULL;
324 const char* dictionary_filename =
NULL;
325 char* dynNameSpace =
NULL;
326 const char** inFileNames = (
const char**)
calloc((
size_t)argc,
sizeof(
char*));
333 #ifdef UTIL_HAS_CREATEFILELIST
334 const char** extendedFileList =
NULL;
335 char* fileNamesBuf =
NULL;
336 unsigned fileNamesNb, recursive=0;
340 if (inFileNames==
NULL) {
341 DISPLAY(
"Allocation error : not enough memory \n");
362 for(
i=1;
i<argc;
i++) {
363 const char* argument =
argv[
i];
365 if(!argument)
continue;
368 if (!all_arguments_are_files && argument[0]==
'-') {
370 if (argument[1]==0) {
371 if (!input_filename) input_filename=
stdinmark;
377 if (argument[1]==
'-') {
378 if (!strcmp(argument,
"--")) { all_arguments_are_files = 1;
continue; }
380 if ((!strcmp(argument,
"--decompress"))
382 if (!strcmp(argument,
"--multiple")) { multiple_inputs = 1;
continue; }
383 if (!strcmp(argument,
"--test")) {
mode =
om_test;
continue; }
386 if ((!strcmp(argument,
"--stdout"))
387 || (!strcmp(argument,
"--to-stdout"))) { forceStdout=1; output_filename=
stdoutmark;
continue; }
392 if (!strcmp(argument,
"--list")) {
mode =
om_list;
continue; }
396 if (!strcmp(argument,
"--verbose")) {
displayLevel++;
continue; }
399 if (!strcmp(argument,
"--help")) {
usage_advanced(exeName);
goto _cleanup; }
404 if (*argument ==
'=') {
409 cLevel = -(
int)fastLevel;
413 }
else if (*argument != 0) {
426 while (argument[1]!=0) {
431 if (!strcmp(argument,
"c0")) { cLevel=0; argument++;
continue; }
432 if (!strcmp(argument,
"c1")) { cLevel=9; argument++;
continue; }
433 if (!strcmp(argument,
"c2")) { cLevel=12; argument++;
continue; }
434 if (!strcmp(argument,
"hc")) { cLevel=12; argument++;
continue; }
438 if ((*argument>=
'0') && (*argument<=
'9')) {
462 if (argument[1] ==
'\0') {
468 dictionary_filename =
argv[++
i];
471 dictionary_filename = argument + 1;
474 argument += strlen(argument) - 1;
478 case 'l': legacy_format = 1; blockSize = 8
MB;
break;
507 while (argument[1]!=0) {
508 int exitBlockProperties=0;
515 if (argument[1] <
'0' || argument[1] >
'9') {
516 exitBlockProperties=1;
527 DISPLAYLEVEL(2,
"using blocks of size %u KB \n", (
U32)(blockSize>>10));
532 if (blockSize >= 1024) {
533 DISPLAYLEVEL(2,
"using blocks of size %u KB \n", (
U32)(blockSize>>10));
541 if (exitBlockProperties)
break;
553 #ifdef UTIL_HAS_CREATEFILELIST
555 case 'r': recursive=1;
559 case 'm': multiple_inputs=1;
574 case 'p': main_pause=1;
break;
584 if (multiple_inputs) { inFileNames[ifnIdx++]=argument;
continue; }
587 if (!input_filename) { input_filename=argument;
continue; }
590 if (!output_filename) {
591 output_filename=argument;
592 if (!strcmp (output_filename, nullOutput)) output_filename =
nulmark;
597 DISPLAYLEVEL(1,
"Warning : %s won't be used ! Do you want multiple input files (-m) ? \n", argument);
601 #ifdef _POSIX_C_SOURCE
604 #ifdef _POSIX_VERSION
605 DISPLAYLEVEL(4,
"_POSIX_VERSION defined: %ldL\n", (
long) _POSIX_VERSION);
607 #ifdef PLATFORM_POSIX_VERSION
610 #ifdef _FILE_OFFSET_BITS
616 if (multiple_inputs) {
617 input_filename = inFileNames[0];
618 #ifdef UTIL_HAS_CREATEFILELIST
621 if (extendedFileList) {
623 for (u=0; u<fileNamesNb; u++)
DISPLAYLEVEL(4,
"%u %s\n", u, extendedFileList[u]);
624 free((
void*)inFileNames);
625 inFileNames = extendedFileList;
626 ifnIdx = fileNamesNb;
631 if (dictionary_filename) {
642 operationResult =
BMK_benchFiles(inFileNames, ifnIdx, cLevel, cLevelLast, dictionary_filename);
653 if (!input_filename) input_filename =
stdinmark;
659 if (!strcmp(input_filename,
stdinmark)) {
661 if (!output_filename) output_filename =
stdoutmark;
664 #ifdef UTIL_HAS_CREATEFILELIST
669 DISPLAYLEVEL(1,
"%s: is not a regular file \n", input_filename);
675 while ((!output_filename) && (multiple_inputs==0)) {
681 DISPLAYLEVEL(1,
"Warning : using stdout as default output. Do not rely on this behavior: use explicit `-c` instead ! \n");
689 size_t const l = strlen(input_filename);
690 dynNameSpace = (
char*)
calloc(1,l+5);
691 if (dynNameSpace==
NULL) { perror(exeName);
exit(1); }
692 strcpy(dynNameSpace, input_filename);
694 output_filename = dynNameSpace;
695 DISPLAYLEVEL(2,
"Compressed filename will be : %s \n", output_filename);
700 size_t const inl = strlen(input_filename);
701 dynNameSpace = (
char*)
calloc(1,inl+1);
702 if (dynNameSpace==
NULL) { perror(exeName);
exit(1); }
703 strcpy(dynNameSpace, input_filename);
706 while ((outl >= inl-4) && (input_filename[outl] == extension[outl-inl+4])) dynNameSpace[outl--]=0;
707 if (outl != inl-5) {
DISPLAYLEVEL(1,
"Cannot determine an output filename\n");
badusage(exeName); }
708 output_filename = dynNameSpace;
709 DISPLAYLEVEL(2,
"Decoding file %s \n", output_filename);
717 DISPLAYLEVEL(1,
"refusing to read from standard input in --list mode\n");
720 if(!multiple_inputs){
721 inFileNames[ifnIdx++] = input_filename;
725 if (multiple_inputs==0)
assert(output_filename);
729 if (!output_filename) output_filename =
"*\\dummy^!//";
733 DISPLAYLEVEL(1,
"refusing to write to console without -c \n");
747 if (ifnIdx == 0) multiple_inputs = 0;
749 if (multiple_inputs) {
760 DISPLAYLEVEL(3,
"! Generating LZ4 Legacy format (deprecated) ! \n");
768 if (multiple_inputs) {
779 #ifdef UTIL_HAS_CREATEFILELIST
780 if (extendedFileList) {
786 free((
void*)inFileNames);
787 return operationResult;
int BMK_benchFiles(const char **fileNamesTable, unsigned nbFiles, int cLevel, int cLevelLast, const char *dictFileName)
void BMK_setBlockSize(size_t blockSize)
void BMK_setBenchSeparately(int separate)
void BMK_setNotificationLevel(unsigned level)
void BMK_setNbSeconds(unsigned nbSeconds)
static static fork const void static count static fd const char const char static newpath const char static path const char path
unsigned char suffix[65536]
RZ_API void Ht_() free(HtName_(Ht) *ht)
void * calloc(size_t number, size_t size)
static static fork const void static count static fd const char const char static newpath char char argv
static void struct sockaddr socklen_t static fromlen static backlog static fork char char char static envp int struct rusage static rusage struct utsname static buf struct sembuf unsigned
UTIL_STATIC int UTIL_isRegFile(const char *infilename)
UTIL_STATIC void UTIL_freeFileList(const char **filenameTable, char *allocatedBuffer)
UTIL_STATIC const char ** UTIL_createFileList(const char **inputNames, unsigned inputNamesNb, char **allocatedBuffer, unsigned *allocatedNamesNb)
#define LZ4_BLOCKSIZEID_DEFAULT
int main(int argc, const char **argv)
int LZ4IO_compressMultipleFilenames_Legacy(const char **inFileNamesTable, int ifntSize, const char *suffix, int compressionLevel, const LZ4IO_prefs_t *prefs)
static int usage_longhelp(const char *exeName)
static int longCommandWArg(const char **stringPtr, const char *longCommand)
static operationMode_e determineOpMode(const char *inputFilename)
static const char * lastNameFromPath(const char *path)
static int exeNameMatch(const char *exeName, const char *test)
static unsigned displayLevel
static int badusage(const char *exeName)
#define DISPLAYLEVEL(l,...)
static int usage_advanced(const char *exeName)
#define DEFAULT_DECOMPRESSOR
static int g_lz4c_legacy_commands
int LZ4IO_compressFilename_Legacy(const char *input_filename, const char *output_filename, int compressionlevel, const LZ4IO_prefs_t *prefs)
static unsigned readU32FromChar(const char **stringPtr)
static void waitEnter(void)
#define DEFAULT_COMPRESSOR
static int usage(const char *exeName)
char int int compressionLevel
int LZ4IO_setPassThrough(LZ4IO_prefs_t *const prefs, int yes)
int LZ4IO_displayCompressedFilesInfo(const char **inFileNames, size_t ifnIdx)
int LZ4IO_setDictionaryFilename(LZ4IO_prefs_t *const prefs, const char *dictionaryFilename)
int LZ4IO_setBlockMode(LZ4IO_prefs_t *const prefs, LZ4IO_blockMode_t blockMode)
void LZ4IO_favorDecSpeed(LZ4IO_prefs_t *const prefs, int favor)
int LZ4IO_setStreamChecksumMode(LZ4IO_prefs_t *const prefs, int enable)
size_t LZ4IO_setBlockSize(LZ4IO_prefs_t *const prefs, size_t blockSize)
int LZ4IO_setOverwrite(LZ4IO_prefs_t *const prefs, int yes)
int LZ4IO_compressMultipleFilenames(const char **inFileNamesTable, int ifntSize, const char *suffix, int compressionLevel, const LZ4IO_prefs_t *prefs)
size_t LZ4IO_setBlockSizeID(LZ4IO_prefs_t *const prefs, unsigned bsid)
int LZ4IO_setSparseFile(LZ4IO_prefs_t *const prefs, int enable)
int LZ4IO_setBlockChecksumMode(LZ4IO_prefs_t *const prefs, int enable)
void LZ4IO_setRemoveSrcFile(LZ4IO_prefs_t *const prefs, unsigned flag)
LZ4IO_prefs_t * LZ4IO_defaultPreferences(void)
int LZ4IO_setTestMode(LZ4IO_prefs_t *const prefs, int yes)
void LZ4IO_freePreferences(LZ4IO_prefs_t *prefs)
int LZ4IO_decompressMultipleFilenames(const char **inFileNamesTable, int ifntSize, const char *suffix, const LZ4IO_prefs_t *prefs)
int LZ4IO_setNotificationLevel(int level)
int LZ4IO_setContentSize(LZ4IO_prefs_t *const prefs, int enable)
assert(limit<=UINT32_MAX/2)
#define _FILE_OFFSET_BITS
Miscellaneous utility functions.