1*3117ece4Schristos /* 2*3117ece4Schristos * Copyright (c) Meta Platforms, Inc. and affiliates. 3*3117ece4Schristos * All rights reserved. 4*3117ece4Schristos * 5*3117ece4Schristos * This source code is licensed under both the BSD-style license (found in the 6*3117ece4Schristos * LICENSE file in the root directory of this source tree) and the GPLv2 (found 7*3117ece4Schristos * in the COPYING file in the root directory of this source tree). 8*3117ece4Schristos * You may select, at your option, one of the above-listed licenses. 9*3117ece4Schristos */ 10*3117ece4Schristos 11*3117ece4Schristos 12*3117ece4Schristos /*-************************************ 13*3117ece4Schristos * Tuning parameters 14*3117ece4Schristos **************************************/ 15*3117ece4Schristos #ifndef ZSTDCLI_CLEVEL_DEFAULT 16*3117ece4Schristos # define ZSTDCLI_CLEVEL_DEFAULT 3 17*3117ece4Schristos #endif 18*3117ece4Schristos 19*3117ece4Schristos #ifndef ZSTDCLI_CLEVEL_MAX 20*3117ece4Schristos # define ZSTDCLI_CLEVEL_MAX 19 /* without using --ultra */ 21*3117ece4Schristos #endif 22*3117ece4Schristos 23*3117ece4Schristos #ifndef ZSTDCLI_NBTHREADS_DEFAULT 24*3117ece4Schristos # define ZSTDCLI_NBTHREADS_DEFAULT 1 25*3117ece4Schristos #endif 26*3117ece4Schristos 27*3117ece4Schristos /*-************************************ 28*3117ece4Schristos * Dependencies 29*3117ece4Schristos **************************************/ 30*3117ece4Schristos #include "platform.h" /* PLATFORM_POSIX_VERSION */ 31*3117ece4Schristos #include "util.h" /* UTIL_HAS_CREATEFILELIST, UTIL_createFileList, UTIL_isConsole */ 32*3117ece4Schristos #include <stdlib.h> /* getenv */ 33*3117ece4Schristos #include <string.h> /* strcmp, strlen */ 34*3117ece4Schristos #include <stdio.h> /* fprintf(), stdin, stdout, stderr */ 35*3117ece4Schristos #include <errno.h> /* errno */ 36*3117ece4Schristos #include <assert.h> /* assert */ 37*3117ece4Schristos 38*3117ece4Schristos #include "fileio.h" /* stdinmark, stdoutmark, ZSTD_EXTENSION */ 39*3117ece4Schristos #ifndef ZSTD_NOBENCH 40*3117ece4Schristos # include "benchzstd.h" /* BMK_benchFilesAdvanced */ 41*3117ece4Schristos #endif 42*3117ece4Schristos #ifndef ZSTD_NODICT 43*3117ece4Schristos # include "dibio.h" /* ZDICT_cover_params_t, DiB_trainFromFiles() */ 44*3117ece4Schristos #endif 45*3117ece4Schristos #ifndef ZSTD_NOTRACE 46*3117ece4Schristos # include "zstdcli_trace.h" 47*3117ece4Schristos #endif 48*3117ece4Schristos #include "../lib/zstd.h" /* ZSTD_VERSION_STRING, ZSTD_minCLevel, ZSTD_maxCLevel */ 49*3117ece4Schristos #include "fileio_asyncio.h" 50*3117ece4Schristos 51*3117ece4Schristos 52*3117ece4Schristos /*-************************************ 53*3117ece4Schristos * Constants 54*3117ece4Schristos **************************************/ 55*3117ece4Schristos #define COMPRESSOR_NAME "Zstandard CLI" 56*3117ece4Schristos #ifndef ZSTD_VERSION 57*3117ece4Schristos # define ZSTD_VERSION "v" ZSTD_VERSION_STRING 58*3117ece4Schristos #endif 59*3117ece4Schristos #define AUTHOR "Yann Collet" 60*3117ece4Schristos #define WELCOME_MESSAGE "*** %s (%i-bit) %s, by %s ***\n", COMPRESSOR_NAME, (int)(sizeof(size_t)*8), ZSTD_VERSION, AUTHOR 61*3117ece4Schristos 62*3117ece4Schristos #define ZSTD_ZSTDMT "zstdmt" 63*3117ece4Schristos #define ZSTD_UNZSTD "unzstd" 64*3117ece4Schristos #define ZSTD_CAT "zstdcat" 65*3117ece4Schristos #define ZSTD_ZCAT "zcat" 66*3117ece4Schristos #define ZSTD_GZ "gzip" 67*3117ece4Schristos #define ZSTD_GUNZIP "gunzip" 68*3117ece4Schristos #define ZSTD_GZCAT "gzcat" 69*3117ece4Schristos #define ZSTD_LZMA "lzma" 70*3117ece4Schristos #define ZSTD_UNLZMA "unlzma" 71*3117ece4Schristos #define ZSTD_XZ "xz" 72*3117ece4Schristos #define ZSTD_UNXZ "unxz" 73*3117ece4Schristos #define ZSTD_LZ4 "lz4" 74*3117ece4Schristos #define ZSTD_UNLZ4 "unlz4" 75*3117ece4Schristos 76*3117ece4Schristos #define KB *(1 <<10) 77*3117ece4Schristos #define MB *(1 <<20) 78*3117ece4Schristos #define GB *(1U<<30) 79*3117ece4Schristos 80*3117ece4Schristos #define DISPLAY_LEVEL_DEFAULT 2 81*3117ece4Schristos 82*3117ece4Schristos static const char* g_defaultDictName = "dictionary"; 83*3117ece4Schristos static const unsigned g_defaultMaxDictSize = 110 KB; 84*3117ece4Schristos static const int g_defaultDictCLevel = 3; 85*3117ece4Schristos static const unsigned g_defaultSelectivityLevel = 9; 86*3117ece4Schristos static const unsigned g_defaultMaxWindowLog = 27; 87*3117ece4Schristos #define OVERLAP_LOG_DEFAULT 9999 88*3117ece4Schristos #define LDM_PARAM_DEFAULT 9999 /* Default for parameters where 0 is valid */ 89*3117ece4Schristos static U32 g_overlapLog = OVERLAP_LOG_DEFAULT; 90*3117ece4Schristos static U32 g_ldmHashLog = 0; 91*3117ece4Schristos static U32 g_ldmMinMatch = 0; 92*3117ece4Schristos static U32 g_ldmHashRateLog = LDM_PARAM_DEFAULT; 93*3117ece4Schristos static U32 g_ldmBucketSizeLog = LDM_PARAM_DEFAULT; 94*3117ece4Schristos 95*3117ece4Schristos 96*3117ece4Schristos #define DEFAULT_ACCEL 1 97*3117ece4Schristos 98*3117ece4Schristos typedef enum { cover, fastCover, legacy } dictType; 99*3117ece4Schristos 100*3117ece4Schristos /*-************************************ 101*3117ece4Schristos * Display Macros 102*3117ece4Schristos **************************************/ 103*3117ece4Schristos #define DISPLAY_F(f, ...) fprintf((f), __VA_ARGS__) 104*3117ece4Schristos #define DISPLAYOUT(...) DISPLAY_F(stdout, __VA_ARGS__) 105*3117ece4Schristos #define DISPLAY(...) DISPLAY_F(stderr, __VA_ARGS__) 106*3117ece4Schristos #define DISPLAYLEVEL(l, ...) { if (g_displayLevel>=l) { DISPLAY(__VA_ARGS__); } } 107*3117ece4Schristos static int g_displayLevel = DISPLAY_LEVEL_DEFAULT; /* 0 : no display, 1: errors, 2 : + result + interaction + warnings, 3 : + progression, 4 : + information */ 108*3117ece4Schristos 109*3117ece4Schristos 110*3117ece4Schristos /*-************************************ 111*3117ece4Schristos * Check Version (when CLI linked to dynamic library) 112*3117ece4Schristos **************************************/ 113*3117ece4Schristos 114*3117ece4Schristos /* Due to usage of experimental symbols and capabilities by the CLI, 115*3117ece4Schristos * the CLI must be linked against a dynamic library of same version */ 116*3117ece4Schristos static void checkLibVersion(void) 117*3117ece4Schristos { 118*3117ece4Schristos if (strcmp(ZSTD_VERSION_STRING, ZSTD_versionString())) { 119*3117ece4Schristos DISPLAYLEVEL(1, "Error : incorrect library version (expecting : %s ; actual : %s ) \n", 120*3117ece4Schristos ZSTD_VERSION_STRING, ZSTD_versionString()); 121*3117ece4Schristos DISPLAYLEVEL(1, "Please update library to version %s, or use stand-alone zstd binary \n", 122*3117ece4Schristos ZSTD_VERSION_STRING); 123*3117ece4Schristos exit(1); 124*3117ece4Schristos } 125*3117ece4Schristos } 126*3117ece4Schristos 127*3117ece4Schristos 128*3117ece4Schristos /*! exeNameMatch() : 129*3117ece4Schristos @return : a non-zero value if exeName matches test, excluding the extension 130*3117ece4Schristos */ 131*3117ece4Schristos static int exeNameMatch(const char* exeName, const char* test) 132*3117ece4Schristos { 133*3117ece4Schristos return !strncmp(exeName, test, strlen(test)) && 134*3117ece4Schristos (exeName[strlen(test)] == '\0' || exeName[strlen(test)] == '.'); 135*3117ece4Schristos } 136*3117ece4Schristos 137*3117ece4Schristos /*-************************************ 138*3117ece4Schristos * Command Line 139*3117ece4Schristos **************************************/ 140*3117ece4Schristos /* print help either in `stderr` or `stdout` depending on originating request 141*3117ece4Schristos * error (badUsage) => stderr 142*3117ece4Schristos * help (usageAdvanced) => stdout 143*3117ece4Schristos */ 144*3117ece4Schristos static void usage(FILE* f, const char* programName) 145*3117ece4Schristos { 146*3117ece4Schristos DISPLAY_F(f, "Compress or decompress the INPUT file(s); reads from STDIN if INPUT is `-` or not provided.\n\n"); 147*3117ece4Schristos DISPLAY_F(f, "Usage: %s [OPTIONS...] [INPUT... | -] [-o OUTPUT]\n\n", programName); 148*3117ece4Schristos DISPLAY_F(f, "Options:\n"); 149*3117ece4Schristos DISPLAY_F(f, " -o OUTPUT Write output to a single file, OUTPUT.\n"); 150*3117ece4Schristos DISPLAY_F(f, " -k, --keep Preserve INPUT file(s). [Default] \n"); 151*3117ece4Schristos DISPLAY_F(f, " --rm Remove INPUT file(s) after successful (de)compression.\n"); 152*3117ece4Schristos #ifdef ZSTD_GZCOMPRESS 153*3117ece4Schristos if (exeNameMatch(programName, ZSTD_GZ)) { /* behave like gzip */ 154*3117ece4Schristos DISPLAY_F(f, " -n, --no-name Do not store original filename when compressing.\n\n"); 155*3117ece4Schristos } 156*3117ece4Schristos #endif 157*3117ece4Schristos DISPLAY_F(f, "\n"); 158*3117ece4Schristos #ifndef ZSTD_NOCOMPRESS 159*3117ece4Schristos DISPLAY_F(f, " -# Desired compression level, where `#` is a number between 1 and %d;\n", ZSTDCLI_CLEVEL_MAX); 160*3117ece4Schristos DISPLAY_F(f, " lower numbers provide faster compression, higher numbers yield\n"); 161*3117ece4Schristos DISPLAY_F(f, " better compression ratios. [Default: %d]\n\n", ZSTDCLI_CLEVEL_DEFAULT); 162*3117ece4Schristos #endif 163*3117ece4Schristos #ifndef ZSTD_NODECOMPRESS 164*3117ece4Schristos DISPLAY_F(f, " -d, --decompress Perform decompression.\n"); 165*3117ece4Schristos #endif 166*3117ece4Schristos DISPLAY_F(f, " -D DICT Use DICT as the dictionary for compression or decompression.\n\n"); 167*3117ece4Schristos DISPLAY_F(f, " -f, --force Disable input and output checks. Allows overwriting existing files,\n"); 168*3117ece4Schristos DISPLAY_F(f, " receiving input from the console, printing output to STDOUT, and\n"); 169*3117ece4Schristos DISPLAY_F(f, " operating on links, block devices, etc. Unrecognized formats will be\n"); 170*3117ece4Schristos DISPLAY_F(f, " passed-through through as-is.\n\n"); 171*3117ece4Schristos 172*3117ece4Schristos DISPLAY_F(f, " -h Display short usage and exit.\n"); 173*3117ece4Schristos DISPLAY_F(f, " -H, --help Display full help and exit.\n"); 174*3117ece4Schristos DISPLAY_F(f, " -V, --version Display the program version and exit.\n"); 175*3117ece4Schristos DISPLAY_F(f, "\n"); 176*3117ece4Schristos } 177*3117ece4Schristos 178*3117ece4Schristos static void usageAdvanced(const char* programName) 179*3117ece4Schristos { 180*3117ece4Schristos DISPLAYOUT(WELCOME_MESSAGE); 181*3117ece4Schristos DISPLAYOUT("\n"); 182*3117ece4Schristos usage(stdout, programName); 183*3117ece4Schristos DISPLAYOUT("Advanced options:\n"); 184*3117ece4Schristos DISPLAYOUT(" -c, --stdout Write to STDOUT (even if it is a console) and keep the INPUT file(s).\n\n"); 185*3117ece4Schristos 186*3117ece4Schristos DISPLAYOUT(" -v, --verbose Enable verbose output; pass multiple times to increase verbosity.\n"); 187*3117ece4Schristos DISPLAYOUT(" -q, --quiet Suppress warnings; pass twice to suppress errors.\n"); 188*3117ece4Schristos #ifndef ZSTD_NOTRACE 189*3117ece4Schristos DISPLAYOUT(" --trace LOG Log tracing information to LOG.\n"); 190*3117ece4Schristos #endif 191*3117ece4Schristos DISPLAYOUT("\n"); 192*3117ece4Schristos DISPLAYOUT(" --[no-]progress Forcibly show/hide the progress counter. NOTE: Any (de)compressed\n"); 193*3117ece4Schristos DISPLAYOUT(" output to terminal will mix with progress counter text.\n\n"); 194*3117ece4Schristos 195*3117ece4Schristos #ifdef UTIL_HAS_CREATEFILELIST 196*3117ece4Schristos DISPLAYOUT(" -r Operate recursively on directories.\n"); 197*3117ece4Schristos DISPLAYOUT(" --filelist LIST Read a list of files to operate on from LIST.\n"); 198*3117ece4Schristos DISPLAYOUT(" --output-dir-flat DIR Store processed files in DIR.\n"); 199*3117ece4Schristos #endif 200*3117ece4Schristos 201*3117ece4Schristos #ifdef UTIL_HAS_MIRRORFILELIST 202*3117ece4Schristos DISPLAYOUT(" --output-dir-mirror DIR Store processed files in DIR, respecting original directory structure.\n"); 203*3117ece4Schristos #endif 204*3117ece4Schristos if (AIO_supported()) 205*3117ece4Schristos DISPLAYOUT(" --[no-]asyncio Use asynchronous IO. [Default: Enabled]\n"); 206*3117ece4Schristos 207*3117ece4Schristos DISPLAYOUT("\n"); 208*3117ece4Schristos #ifndef ZSTD_NOCOMPRESS 209*3117ece4Schristos DISPLAYOUT(" --[no-]check Add XXH64 integrity checksums during compression. [Default: Add, Validate]\n"); 210*3117ece4Schristos #ifndef ZSTD_NODECOMPRESS 211*3117ece4Schristos DISPLAYOUT(" If `-d` is present, ignore/validate checksums during decompression.\n"); 212*3117ece4Schristos #endif 213*3117ece4Schristos #else 214*3117ece4Schristos #ifdef ZSTD_NOCOMPRESS 215*3117ece4Schristos DISPLAYOUT(" --[no-]check Ignore/validate checksums during decompression. [Default: Validate]"); 216*3117ece4Schristos #endif 217*3117ece4Schristos #endif /* ZSTD_NOCOMPRESS */ 218*3117ece4Schristos 219*3117ece4Schristos DISPLAYOUT("\n"); 220*3117ece4Schristos DISPLAYOUT(" -- Treat remaining arguments after `--` as files.\n"); 221*3117ece4Schristos 222*3117ece4Schristos #ifndef ZSTD_NOCOMPRESS 223*3117ece4Schristos DISPLAYOUT("\n"); 224*3117ece4Schristos DISPLAYOUT("Advanced compression options:\n"); 225*3117ece4Schristos DISPLAYOUT(" --ultra Enable levels beyond %i, up to %i; requires more memory.\n", ZSTDCLI_CLEVEL_MAX, ZSTD_maxCLevel()); 226*3117ece4Schristos DISPLAYOUT(" --fast[=#] Use to very fast compression levels. [Default: %u]\n", 1); 227*3117ece4Schristos #ifdef ZSTD_GZCOMPRESS 228*3117ece4Schristos if (exeNameMatch(programName, ZSTD_GZ)) { /* behave like gzip */ 229*3117ece4Schristos DISPLAYOUT(" --best Compatibility alias for `-9`.\n"); 230*3117ece4Schristos } 231*3117ece4Schristos #endif 232*3117ece4Schristos DISPLAYOUT(" --adapt Dynamically adapt compression level to I/O conditions.\n"); 233*3117ece4Schristos DISPLAYOUT(" --long[=#] Enable long distance matching with window log #. [Default: %u]\n", g_defaultMaxWindowLog); 234*3117ece4Schristos DISPLAYOUT(" --patch-from=REF Use REF as the reference point for Zstandard's diff engine. \n\n"); 235*3117ece4Schristos # ifdef ZSTD_MULTITHREAD 236*3117ece4Schristos DISPLAYOUT(" -T# Spawn # compression threads. [Default: 1; pass 0 for core count.]\n"); 237*3117ece4Schristos DISPLAYOUT(" --single-thread Share a single thread for I/O and compression (slightly different than `-T1`).\n"); 238*3117ece4Schristos DISPLAYOUT(" --auto-threads={physical|logical}\n"); 239*3117ece4Schristos DISPLAYOUT(" Use physical/logical cores when using `-T0`. [Default: Physical]\n\n"); 240*3117ece4Schristos DISPLAYOUT(" -B# Set job size to #. [Default: 0 (automatic)]\n"); 241*3117ece4Schristos DISPLAYOUT(" --rsyncable Compress using a rsync-friendly method (`-B` sets block size). \n"); 242*3117ece4Schristos DISPLAYOUT("\n"); 243*3117ece4Schristos # endif 244*3117ece4Schristos DISPLAYOUT(" --exclude-compressed Only compress files that are not already compressed.\n\n"); 245*3117ece4Schristos 246*3117ece4Schristos DISPLAYOUT(" --stream-size=# Specify size of streaming input from STDIN.\n"); 247*3117ece4Schristos DISPLAYOUT(" --size-hint=# Optimize compression parameters for streaming input of approximately size #.\n"); 248*3117ece4Schristos DISPLAYOUT(" --target-compressed-block-size=#\n"); 249*3117ece4Schristos DISPLAYOUT(" Generate compressed blocks of approximately # size.\n\n"); 250*3117ece4Schristos DISPLAYOUT(" --no-dictID Don't write `dictID` into the header (dictionary compression only).\n"); 251*3117ece4Schristos DISPLAYOUT(" --[no-]compress-literals Force (un)compressed literals.\n"); 252*3117ece4Schristos DISPLAYOUT(" --[no-]row-match-finder Explicitly enable/disable the fast, row-based matchfinder for\n"); 253*3117ece4Schristos DISPLAYOUT(" the 'greedy', 'lazy', and 'lazy2' strategies.\n"); 254*3117ece4Schristos 255*3117ece4Schristos DISPLAYOUT("\n"); 256*3117ece4Schristos DISPLAYOUT(" --format=zstd Compress files to the `.zst` format. [Default]\n"); 257*3117ece4Schristos DISPLAYOUT(" --[no-]mmap-dict Memory-map dictionary file rather than mallocing and loading all at once\n"); 258*3117ece4Schristos #ifdef ZSTD_GZCOMPRESS 259*3117ece4Schristos DISPLAYOUT(" --format=gzip Compress files to the `.gz` format.\n"); 260*3117ece4Schristos #endif 261*3117ece4Schristos #ifdef ZSTD_LZMACOMPRESS 262*3117ece4Schristos DISPLAYOUT(" --format=xz Compress files to the `.xz` format.\n"); 263*3117ece4Schristos DISPLAYOUT(" --format=lzma Compress files to the `.lzma` format.\n"); 264*3117ece4Schristos #endif 265*3117ece4Schristos #ifdef ZSTD_LZ4COMPRESS 266*3117ece4Schristos DISPLAYOUT( " --format=lz4 Compress files to the `.lz4` format.\n"); 267*3117ece4Schristos #endif 268*3117ece4Schristos #endif /* !ZSTD_NOCOMPRESS */ 269*3117ece4Schristos 270*3117ece4Schristos #ifndef ZSTD_NODECOMPRESS 271*3117ece4Schristos DISPLAYOUT("\n"); 272*3117ece4Schristos DISPLAYOUT("Advanced decompression options:\n"); 273*3117ece4Schristos DISPLAYOUT(" -l Print information about Zstandard-compressed files.\n"); 274*3117ece4Schristos DISPLAYOUT(" --test Test compressed file integrity.\n"); 275*3117ece4Schristos DISPLAYOUT(" -M# Set the memory usage limit to # megabytes.\n"); 276*3117ece4Schristos # if ZSTD_SPARSE_DEFAULT 277*3117ece4Schristos DISPLAYOUT(" --[no-]sparse Enable sparse mode. [Default: Enabled for files, disabled for STDOUT.]\n"); 278*3117ece4Schristos # else 279*3117ece4Schristos DISPLAYOUT(" --[no-]sparse Enable sparse mode. [Default: Disabled]\n"); 280*3117ece4Schristos # endif 281*3117ece4Schristos { 282*3117ece4Schristos char const* passThroughDefault = "Disabled"; 283*3117ece4Schristos if (exeNameMatch(programName, ZSTD_CAT) || 284*3117ece4Schristos exeNameMatch(programName, ZSTD_ZCAT) || 285*3117ece4Schristos exeNameMatch(programName, ZSTD_GZCAT)) { 286*3117ece4Schristos passThroughDefault = "Enabled"; 287*3117ece4Schristos } 288*3117ece4Schristos DISPLAYOUT(" --[no-]pass-through Pass through uncompressed files as-is. [Default: %s]\n", passThroughDefault); 289*3117ece4Schristos } 290*3117ece4Schristos #endif /* ZSTD_NODECOMPRESS */ 291*3117ece4Schristos 292*3117ece4Schristos #ifndef ZSTD_NODICT 293*3117ece4Schristos DISPLAYOUT("\n"); 294*3117ece4Schristos DISPLAYOUT("Dictionary builder:\n"); 295*3117ece4Schristos DISPLAYOUT(" --train Create a dictionary from a training set of files.\n\n"); 296*3117ece4Schristos DISPLAYOUT(" --train-cover[=k=#,d=#,steps=#,split=#,shrink[=#]]\n"); 297*3117ece4Schristos DISPLAYOUT(" Use the cover algorithm (with optional arguments).\n"); 298*3117ece4Schristos DISPLAYOUT(" --train-fastcover[=k=#,d=#,f=#,steps=#,split=#,accel=#,shrink[=#]]\n"); 299*3117ece4Schristos DISPLAYOUT(" Use the fast cover algorithm (with optional arguments).\n\n"); 300*3117ece4Schristos DISPLAYOUT(" --train-legacy[=s=#] Use the legacy algorithm with selectivity #. [Default: %u]\n", g_defaultSelectivityLevel); 301*3117ece4Schristos DISPLAYOUT(" -o NAME Use NAME as dictionary name. [Default: %s]\n", g_defaultDictName); 302*3117ece4Schristos DISPLAYOUT(" --maxdict=# Limit dictionary to specified size #. [Default: %u]\n", g_defaultMaxDictSize); 303*3117ece4Schristos DISPLAYOUT(" --dictID=# Force dictionary ID to #. [Default: Random]\n"); 304*3117ece4Schristos #endif 305*3117ece4Schristos 306*3117ece4Schristos #ifndef ZSTD_NOBENCH 307*3117ece4Schristos DISPLAYOUT("\n"); 308*3117ece4Schristos DISPLAYOUT("Benchmark options:\n"); 309*3117ece4Schristos DISPLAYOUT(" -b# Perform benchmarking with compression level #. [Default: %d]\n", ZSTDCLI_CLEVEL_DEFAULT); 310*3117ece4Schristos DISPLAYOUT(" -e# Test all compression levels up to #; starting level is `-b#`. [Default: 1]\n"); 311*3117ece4Schristos DISPLAYOUT(" -i# Set the minimum evaluation to time # seconds. [Default: 3]\n"); 312*3117ece4Schristos DISPLAYOUT(" -B# Cut file into independent chunks of size #. [Default: No chunking]\n"); 313*3117ece4Schristos DISPLAYOUT(" -S Output one benchmark result per input file. [Default: Consolidated result]\n"); 314*3117ece4Schristos DISPLAYOUT(" --priority=rt Set process priority to real-time.\n"); 315*3117ece4Schristos #endif 316*3117ece4Schristos 317*3117ece4Schristos } 318*3117ece4Schristos 319*3117ece4Schristos static void badUsage(const char* programName, const char* parameter) 320*3117ece4Schristos { 321*3117ece4Schristos DISPLAYLEVEL(1, "Incorrect parameter: %s \n", parameter); 322*3117ece4Schristos if (g_displayLevel >= 2) usage(stderr, programName); 323*3117ece4Schristos } 324*3117ece4Schristos 325*3117ece4Schristos static void waitEnter(void) 326*3117ece4Schristos { 327*3117ece4Schristos int unused; 328*3117ece4Schristos DISPLAY("Press enter to continue... \n"); 329*3117ece4Schristos unused = getchar(); 330*3117ece4Schristos (void)unused; 331*3117ece4Schristos } 332*3117ece4Schristos 333*3117ece4Schristos static const char* lastNameFromPath(const char* path) 334*3117ece4Schristos { 335*3117ece4Schristos const char* name = path; 336*3117ece4Schristos if (strrchr(name, '/')) name = strrchr(name, '/') + 1; 337*3117ece4Schristos if (strrchr(name, '\\')) name = strrchr(name, '\\') + 1; /* windows */ 338*3117ece4Schristos return name; 339*3117ece4Schristos } 340*3117ece4Schristos 341*3117ece4Schristos static void errorOut(const char* msg) 342*3117ece4Schristos { 343*3117ece4Schristos DISPLAYLEVEL(1, "%s \n", msg); exit(1); 344*3117ece4Schristos } 345*3117ece4Schristos 346*3117ece4Schristos /*! readU32FromCharChecked() : 347*3117ece4Schristos * @return 0 if success, and store the result in *value. 348*3117ece4Schristos * allows and interprets K, KB, KiB, M, MB and MiB suffix. 349*3117ece4Schristos * Will also modify `*stringPtr`, advancing it to position where it stopped reading. 350*3117ece4Schristos * @return 1 if an overflow error occurs */ 351*3117ece4Schristos static int readU32FromCharChecked(const char** stringPtr, unsigned* value) 352*3117ece4Schristos { 353*3117ece4Schristos unsigned result = 0; 354*3117ece4Schristos while ((**stringPtr >='0') && (**stringPtr <='9')) { 355*3117ece4Schristos unsigned const max = ((unsigned)(-1)) / 10; 356*3117ece4Schristos unsigned last = result; 357*3117ece4Schristos if (result > max) return 1; /* overflow error */ 358*3117ece4Schristos result *= 10; 359*3117ece4Schristos result += (unsigned)(**stringPtr - '0'); 360*3117ece4Schristos if (result < last) return 1; /* overflow error */ 361*3117ece4Schristos (*stringPtr)++ ; 362*3117ece4Schristos } 363*3117ece4Schristos if ((**stringPtr=='K') || (**stringPtr=='M')) { 364*3117ece4Schristos unsigned const maxK = ((unsigned)(-1)) >> 10; 365*3117ece4Schristos if (result > maxK) return 1; /* overflow error */ 366*3117ece4Schristos result <<= 10; 367*3117ece4Schristos if (**stringPtr=='M') { 368*3117ece4Schristos if (result > maxK) return 1; /* overflow error */ 369*3117ece4Schristos result <<= 10; 370*3117ece4Schristos } 371*3117ece4Schristos (*stringPtr)++; /* skip `K` or `M` */ 372*3117ece4Schristos if (**stringPtr=='i') (*stringPtr)++; 373*3117ece4Schristos if (**stringPtr=='B') (*stringPtr)++; 374*3117ece4Schristos } 375*3117ece4Schristos *value = result; 376*3117ece4Schristos return 0; 377*3117ece4Schristos } 378*3117ece4Schristos 379*3117ece4Schristos /*! readU32FromChar() : 380*3117ece4Schristos * @return : unsigned integer value read from input in `char` format. 381*3117ece4Schristos * allows and interprets K, KB, KiB, M, MB and MiB suffix. 382*3117ece4Schristos * Will also modify `*stringPtr`, advancing it to position where it stopped reading. 383*3117ece4Schristos * Note : function will exit() program if digit sequence overflows */ 384*3117ece4Schristos static unsigned readU32FromChar(const char** stringPtr) { 385*3117ece4Schristos static const char errorMsg[] = "error: numeric value overflows 32-bit unsigned int"; 386*3117ece4Schristos unsigned result; 387*3117ece4Schristos if (readU32FromCharChecked(stringPtr, &result)) { errorOut(errorMsg); } 388*3117ece4Schristos return result; 389*3117ece4Schristos } 390*3117ece4Schristos 391*3117ece4Schristos /*! readIntFromChar() : 392*3117ece4Schristos * @return : signed integer value read from input in `char` format. 393*3117ece4Schristos * allows and interprets K, KB, KiB, M, MB and MiB suffix. 394*3117ece4Schristos * Will also modify `*stringPtr`, advancing it to position where it stopped reading. 395*3117ece4Schristos * Note : function will exit() program if digit sequence overflows */ 396*3117ece4Schristos static int readIntFromChar(const char** stringPtr) { 397*3117ece4Schristos static const char errorMsg[] = "error: numeric value overflows 32-bit int"; 398*3117ece4Schristos int sign = 1; 399*3117ece4Schristos unsigned result; 400*3117ece4Schristos if (**stringPtr=='-') { 401*3117ece4Schristos (*stringPtr)++; 402*3117ece4Schristos sign = -1; 403*3117ece4Schristos } 404*3117ece4Schristos if (readU32FromCharChecked(stringPtr, &result)) { errorOut(errorMsg); } 405*3117ece4Schristos return (int) result * sign; 406*3117ece4Schristos } 407*3117ece4Schristos 408*3117ece4Schristos /*! readSizeTFromCharChecked() : 409*3117ece4Schristos * @return 0 if success, and store the result in *value. 410*3117ece4Schristos * allows and interprets K, KB, KiB, M, MB and MiB suffix. 411*3117ece4Schristos * Will also modify `*stringPtr`, advancing it to position where it stopped reading. 412*3117ece4Schristos * @return 1 if an overflow error occurs */ 413*3117ece4Schristos static int readSizeTFromCharChecked(const char** stringPtr, size_t* value) 414*3117ece4Schristos { 415*3117ece4Schristos size_t result = 0; 416*3117ece4Schristos while ((**stringPtr >='0') && (**stringPtr <='9')) { 417*3117ece4Schristos size_t const max = ((size_t)(-1)) / 10; 418*3117ece4Schristos size_t last = result; 419*3117ece4Schristos if (result > max) return 1; /* overflow error */ 420*3117ece4Schristos result *= 10; 421*3117ece4Schristos result += (size_t)(**stringPtr - '0'); 422*3117ece4Schristos if (result < last) return 1; /* overflow error */ 423*3117ece4Schristos (*stringPtr)++ ; 424*3117ece4Schristos } 425*3117ece4Schristos if ((**stringPtr=='K') || (**stringPtr=='M')) { 426*3117ece4Schristos size_t const maxK = ((size_t)(-1)) >> 10; 427*3117ece4Schristos if (result > maxK) return 1; /* overflow error */ 428*3117ece4Schristos result <<= 10; 429*3117ece4Schristos if (**stringPtr=='M') { 430*3117ece4Schristos if (result > maxK) return 1; /* overflow error */ 431*3117ece4Schristos result <<= 10; 432*3117ece4Schristos } 433*3117ece4Schristos (*stringPtr)++; /* skip `K` or `M` */ 434*3117ece4Schristos if (**stringPtr=='i') (*stringPtr)++; 435*3117ece4Schristos if (**stringPtr=='B') (*stringPtr)++; 436*3117ece4Schristos } 437*3117ece4Schristos *value = result; 438*3117ece4Schristos return 0; 439*3117ece4Schristos } 440*3117ece4Schristos 441*3117ece4Schristos /*! readSizeTFromChar() : 442*3117ece4Schristos * @return : size_t value read from input in `char` format. 443*3117ece4Schristos * allows and interprets K, KB, KiB, M, MB and MiB suffix. 444*3117ece4Schristos * Will also modify `*stringPtr`, advancing it to position where it stopped reading. 445*3117ece4Schristos * Note : function will exit() program if digit sequence overflows */ 446*3117ece4Schristos static size_t readSizeTFromChar(const char** stringPtr) { 447*3117ece4Schristos static const char errorMsg[] = "error: numeric value overflows size_t"; 448*3117ece4Schristos size_t result; 449*3117ece4Schristos if (readSizeTFromCharChecked(stringPtr, &result)) { errorOut(errorMsg); } 450*3117ece4Schristos return result; 451*3117ece4Schristos } 452*3117ece4Schristos 453*3117ece4Schristos /** longCommandWArg() : 454*3117ece4Schristos * check if *stringPtr is the same as longCommand. 455*3117ece4Schristos * If yes, @return 1 and advances *stringPtr to the position which immediately follows longCommand. 456*3117ece4Schristos * @return 0 and doesn't modify *stringPtr otherwise. 457*3117ece4Schristos */ 458*3117ece4Schristos static int longCommandWArg(const char** stringPtr, const char* longCommand) 459*3117ece4Schristos { 460*3117ece4Schristos size_t const comSize = strlen(longCommand); 461*3117ece4Schristos int const result = !strncmp(*stringPtr, longCommand, comSize); 462*3117ece4Schristos if (result) *stringPtr += comSize; 463*3117ece4Schristos return result; 464*3117ece4Schristos } 465*3117ece4Schristos 466*3117ece4Schristos 467*3117ece4Schristos #ifndef ZSTD_NODICT 468*3117ece4Schristos 469*3117ece4Schristos static const unsigned kDefaultRegression = 1; 470*3117ece4Schristos /** 471*3117ece4Schristos * parseCoverParameters() : 472*3117ece4Schristos * reads cover parameters from *stringPtr (e.g. "--train-cover=k=48,d=8,steps=32") into *params 473*3117ece4Schristos * @return 1 means that cover parameters were correct 474*3117ece4Schristos * @return 0 in case of malformed parameters 475*3117ece4Schristos */ 476*3117ece4Schristos static unsigned parseCoverParameters(const char* stringPtr, ZDICT_cover_params_t* params) 477*3117ece4Schristos { 478*3117ece4Schristos memset(params, 0, sizeof(*params)); 479*3117ece4Schristos for (; ;) { 480*3117ece4Schristos if (longCommandWArg(&stringPtr, "k=")) { params->k = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; } 481*3117ece4Schristos if (longCommandWArg(&stringPtr, "d=")) { params->d = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; } 482*3117ece4Schristos if (longCommandWArg(&stringPtr, "steps=")) { params->steps = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; } 483*3117ece4Schristos if (longCommandWArg(&stringPtr, "split=")) { 484*3117ece4Schristos unsigned splitPercentage = readU32FromChar(&stringPtr); 485*3117ece4Schristos params->splitPoint = (double)splitPercentage / 100.0; 486*3117ece4Schristos if (stringPtr[0]==',') { stringPtr++; continue; } else break; 487*3117ece4Schristos } 488*3117ece4Schristos if (longCommandWArg(&stringPtr, "shrink")) { 489*3117ece4Schristos params->shrinkDictMaxRegression = kDefaultRegression; 490*3117ece4Schristos params->shrinkDict = 1; 491*3117ece4Schristos if (stringPtr[0]=='=') { 492*3117ece4Schristos stringPtr++; 493*3117ece4Schristos params->shrinkDictMaxRegression = readU32FromChar(&stringPtr); 494*3117ece4Schristos } 495*3117ece4Schristos if (stringPtr[0]==',') { 496*3117ece4Schristos stringPtr++; 497*3117ece4Schristos continue; 498*3117ece4Schristos } 499*3117ece4Schristos else break; 500*3117ece4Schristos } 501*3117ece4Schristos return 0; 502*3117ece4Schristos } 503*3117ece4Schristos if (stringPtr[0] != 0) return 0; 504*3117ece4Schristos DISPLAYLEVEL(4, "cover: k=%u\nd=%u\nsteps=%u\nsplit=%u\nshrink%u\n", params->k, params->d, params->steps, (unsigned)(params->splitPoint * 100), params->shrinkDictMaxRegression); 505*3117ece4Schristos return 1; 506*3117ece4Schristos } 507*3117ece4Schristos 508*3117ece4Schristos /** 509*3117ece4Schristos * parseFastCoverParameters() : 510*3117ece4Schristos * reads fastcover parameters from *stringPtr (e.g. "--train-fastcover=k=48,d=8,f=20,steps=32,accel=2") into *params 511*3117ece4Schristos * @return 1 means that fastcover parameters were correct 512*3117ece4Schristos * @return 0 in case of malformed parameters 513*3117ece4Schristos */ 514*3117ece4Schristos static unsigned parseFastCoverParameters(const char* stringPtr, ZDICT_fastCover_params_t* params) 515*3117ece4Schristos { 516*3117ece4Schristos memset(params, 0, sizeof(*params)); 517*3117ece4Schristos for (; ;) { 518*3117ece4Schristos if (longCommandWArg(&stringPtr, "k=")) { params->k = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; } 519*3117ece4Schristos if (longCommandWArg(&stringPtr, "d=")) { params->d = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; } 520*3117ece4Schristos if (longCommandWArg(&stringPtr, "f=")) { params->f = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; } 521*3117ece4Schristos if (longCommandWArg(&stringPtr, "steps=")) { params->steps = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; } 522*3117ece4Schristos if (longCommandWArg(&stringPtr, "accel=")) { params->accel = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; } 523*3117ece4Schristos if (longCommandWArg(&stringPtr, "split=")) { 524*3117ece4Schristos unsigned splitPercentage = readU32FromChar(&stringPtr); 525*3117ece4Schristos params->splitPoint = (double)splitPercentage / 100.0; 526*3117ece4Schristos if (stringPtr[0]==',') { stringPtr++; continue; } else break; 527*3117ece4Schristos } 528*3117ece4Schristos if (longCommandWArg(&stringPtr, "shrink")) { 529*3117ece4Schristos params->shrinkDictMaxRegression = kDefaultRegression; 530*3117ece4Schristos params->shrinkDict = 1; 531*3117ece4Schristos if (stringPtr[0]=='=') { 532*3117ece4Schristos stringPtr++; 533*3117ece4Schristos params->shrinkDictMaxRegression = readU32FromChar(&stringPtr); 534*3117ece4Schristos } 535*3117ece4Schristos if (stringPtr[0]==',') { 536*3117ece4Schristos stringPtr++; 537*3117ece4Schristos continue; 538*3117ece4Schristos } 539*3117ece4Schristos else break; 540*3117ece4Schristos } 541*3117ece4Schristos return 0; 542*3117ece4Schristos } 543*3117ece4Schristos if (stringPtr[0] != 0) return 0; 544*3117ece4Schristos DISPLAYLEVEL(4, "cover: k=%u\nd=%u\nf=%u\nsteps=%u\nsplit=%u\naccel=%u\nshrink=%u\n", params->k, params->d, params->f, params->steps, (unsigned)(params->splitPoint * 100), params->accel, params->shrinkDictMaxRegression); 545*3117ece4Schristos return 1; 546*3117ece4Schristos } 547*3117ece4Schristos 548*3117ece4Schristos /** 549*3117ece4Schristos * parseLegacyParameters() : 550*3117ece4Schristos * reads legacy dictionary builder parameters from *stringPtr (e.g. "--train-legacy=selectivity=8") into *selectivity 551*3117ece4Schristos * @return 1 means that legacy dictionary builder parameters were correct 552*3117ece4Schristos * @return 0 in case of malformed parameters 553*3117ece4Schristos */ 554*3117ece4Schristos static unsigned parseLegacyParameters(const char* stringPtr, unsigned* selectivity) 555*3117ece4Schristos { 556*3117ece4Schristos if (!longCommandWArg(&stringPtr, "s=") && !longCommandWArg(&stringPtr, "selectivity=")) { return 0; } 557*3117ece4Schristos *selectivity = readU32FromChar(&stringPtr); 558*3117ece4Schristos if (stringPtr[0] != 0) return 0; 559*3117ece4Schristos DISPLAYLEVEL(4, "legacy: selectivity=%u\n", *selectivity); 560*3117ece4Schristos return 1; 561*3117ece4Schristos } 562*3117ece4Schristos 563*3117ece4Schristos static ZDICT_cover_params_t defaultCoverParams(void) 564*3117ece4Schristos { 565*3117ece4Schristos ZDICT_cover_params_t params; 566*3117ece4Schristos memset(¶ms, 0, sizeof(params)); 567*3117ece4Schristos params.d = 8; 568*3117ece4Schristos params.steps = 4; 569*3117ece4Schristos params.splitPoint = 1.0; 570*3117ece4Schristos params.shrinkDict = 0; 571*3117ece4Schristos params.shrinkDictMaxRegression = kDefaultRegression; 572*3117ece4Schristos return params; 573*3117ece4Schristos } 574*3117ece4Schristos 575*3117ece4Schristos static ZDICT_fastCover_params_t defaultFastCoverParams(void) 576*3117ece4Schristos { 577*3117ece4Schristos ZDICT_fastCover_params_t params; 578*3117ece4Schristos memset(¶ms, 0, sizeof(params)); 579*3117ece4Schristos params.d = 8; 580*3117ece4Schristos params.f = 20; 581*3117ece4Schristos params.steps = 4; 582*3117ece4Schristos params.splitPoint = 0.75; /* different from default splitPoint of cover */ 583*3117ece4Schristos params.accel = DEFAULT_ACCEL; 584*3117ece4Schristos params.shrinkDict = 0; 585*3117ece4Schristos params.shrinkDictMaxRegression = kDefaultRegression; 586*3117ece4Schristos return params; 587*3117ece4Schristos } 588*3117ece4Schristos #endif 589*3117ece4Schristos 590*3117ece4Schristos 591*3117ece4Schristos /** parseAdaptParameters() : 592*3117ece4Schristos * reads adapt parameters from *stringPtr (e.g. "--adapt=min=1,max=19) and store them into adaptMinPtr and adaptMaxPtr. 593*3117ece4Schristos * Both adaptMinPtr and adaptMaxPtr must be already allocated and correctly initialized. 594*3117ece4Schristos * There is no guarantee that any of these values will be updated. 595*3117ece4Schristos * @return 1 means that parsing was successful, 596*3117ece4Schristos * @return 0 in case of malformed parameters 597*3117ece4Schristos */ 598*3117ece4Schristos static unsigned parseAdaptParameters(const char* stringPtr, int* adaptMinPtr, int* adaptMaxPtr) 599*3117ece4Schristos { 600*3117ece4Schristos for ( ; ;) { 601*3117ece4Schristos if (longCommandWArg(&stringPtr, "min=")) { *adaptMinPtr = readIntFromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; } 602*3117ece4Schristos if (longCommandWArg(&stringPtr, "max=")) { *adaptMaxPtr = readIntFromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; } 603*3117ece4Schristos DISPLAYLEVEL(4, "invalid compression parameter \n"); 604*3117ece4Schristos return 0; 605*3117ece4Schristos } 606*3117ece4Schristos if (stringPtr[0] != 0) return 0; /* check the end of string */ 607*3117ece4Schristos if (*adaptMinPtr > *adaptMaxPtr) { 608*3117ece4Schristos DISPLAYLEVEL(4, "incoherent adaptation limits \n"); 609*3117ece4Schristos return 0; 610*3117ece4Schristos } 611*3117ece4Schristos return 1; 612*3117ece4Schristos } 613*3117ece4Schristos 614*3117ece4Schristos 615*3117ece4Schristos /** parseCompressionParameters() : 616*3117ece4Schristos * reads compression parameters from *stringPtr (e.g. "--zstd=wlog=23,clog=23,hlog=22,slog=6,mml=3,tlen=48,strat=6") into *params 617*3117ece4Schristos * @return 1 means that compression parameters were correct 618*3117ece4Schristos * @return 0 in case of malformed parameters 619*3117ece4Schristos */ 620*3117ece4Schristos static unsigned parseCompressionParameters(const char* stringPtr, ZSTD_compressionParameters* params) 621*3117ece4Schristos { 622*3117ece4Schristos for ( ; ;) { 623*3117ece4Schristos if (longCommandWArg(&stringPtr, "windowLog=") || longCommandWArg(&stringPtr, "wlog=")) { params->windowLog = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; } 624*3117ece4Schristos if (longCommandWArg(&stringPtr, "chainLog=") || longCommandWArg(&stringPtr, "clog=")) { params->chainLog = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; } 625*3117ece4Schristos if (longCommandWArg(&stringPtr, "hashLog=") || longCommandWArg(&stringPtr, "hlog=")) { params->hashLog = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; } 626*3117ece4Schristos if (longCommandWArg(&stringPtr, "searchLog=") || longCommandWArg(&stringPtr, "slog=")) { params->searchLog = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; } 627*3117ece4Schristos if (longCommandWArg(&stringPtr, "minMatch=") || longCommandWArg(&stringPtr, "mml=")) { params->minMatch = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; } 628*3117ece4Schristos if (longCommandWArg(&stringPtr, "targetLength=") || longCommandWArg(&stringPtr, "tlen=")) { params->targetLength = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; } 629*3117ece4Schristos if (longCommandWArg(&stringPtr, "strategy=") || longCommandWArg(&stringPtr, "strat=")) { params->strategy = (ZSTD_strategy)(readU32FromChar(&stringPtr)); if (stringPtr[0]==',') { stringPtr++; continue; } else break; } 630*3117ece4Schristos if (longCommandWArg(&stringPtr, "overlapLog=") || longCommandWArg(&stringPtr, "ovlog=")) { g_overlapLog = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; } 631*3117ece4Schristos if (longCommandWArg(&stringPtr, "ldmHashLog=") || longCommandWArg(&stringPtr, "lhlog=")) { g_ldmHashLog = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; } 632*3117ece4Schristos if (longCommandWArg(&stringPtr, "ldmMinMatch=") || longCommandWArg(&stringPtr, "lmml=")) { g_ldmMinMatch = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; } 633*3117ece4Schristos if (longCommandWArg(&stringPtr, "ldmBucketSizeLog=") || longCommandWArg(&stringPtr, "lblog=")) { g_ldmBucketSizeLog = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; } 634*3117ece4Schristos if (longCommandWArg(&stringPtr, "ldmHashRateLog=") || longCommandWArg(&stringPtr, "lhrlog=")) { g_ldmHashRateLog = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; } 635*3117ece4Schristos DISPLAYLEVEL(4, "invalid compression parameter \n"); 636*3117ece4Schristos return 0; 637*3117ece4Schristos } 638*3117ece4Schristos 639*3117ece4Schristos DISPLAYLEVEL(4, "windowLog=%d, chainLog=%d, hashLog=%d, searchLog=%d \n", params->windowLog, params->chainLog, params->hashLog, params->searchLog); 640*3117ece4Schristos DISPLAYLEVEL(4, "minMatch=%d, targetLength=%d, strategy=%d \n", params->minMatch, params->targetLength, params->strategy); 641*3117ece4Schristos if (stringPtr[0] != 0) return 0; /* check the end of string */ 642*3117ece4Schristos return 1; 643*3117ece4Schristos } 644*3117ece4Schristos 645*3117ece4Schristos static void printVersion(void) 646*3117ece4Schristos { 647*3117ece4Schristos if (g_displayLevel < DISPLAY_LEVEL_DEFAULT) { 648*3117ece4Schristos DISPLAYOUT("%s\n", ZSTD_VERSION_STRING); 649*3117ece4Schristos return; 650*3117ece4Schristos } 651*3117ece4Schristos 652*3117ece4Schristos DISPLAYOUT(WELCOME_MESSAGE); 653*3117ece4Schristos if (g_displayLevel >= 3) { 654*3117ece4Schristos /* format support */ 655*3117ece4Schristos DISPLAYOUT("*** supports: zstd"); 656*3117ece4Schristos #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>0) && (ZSTD_LEGACY_SUPPORT<8) 657*3117ece4Schristos DISPLAYOUT(", zstd legacy v0.%d+", ZSTD_LEGACY_SUPPORT); 658*3117ece4Schristos #endif 659*3117ece4Schristos #ifdef ZSTD_GZCOMPRESS 660*3117ece4Schristos DISPLAYOUT(", gzip"); 661*3117ece4Schristos #endif 662*3117ece4Schristos #ifdef ZSTD_LZ4COMPRESS 663*3117ece4Schristos DISPLAYOUT(", lz4"); 664*3117ece4Schristos #endif 665*3117ece4Schristos #ifdef ZSTD_LZMACOMPRESS 666*3117ece4Schristos DISPLAYOUT(", lzma, xz "); 667*3117ece4Schristos #endif 668*3117ece4Schristos DISPLAYOUT("\n"); 669*3117ece4Schristos if (g_displayLevel >= 4) { 670*3117ece4Schristos /* library versions */ 671*3117ece4Schristos DISPLAYOUT("zlib version %s\n", FIO_zlibVersion()); 672*3117ece4Schristos DISPLAYOUT("lz4 version %s\n", FIO_lz4Version()); 673*3117ece4Schristos DISPLAYOUT("lzma version %s\n", FIO_lzmaVersion()); 674*3117ece4Schristos 675*3117ece4Schristos /* posix support */ 676*3117ece4Schristos #ifdef _POSIX_C_SOURCE 677*3117ece4Schristos DISPLAYOUT("_POSIX_C_SOURCE defined: %ldL\n", (long) _POSIX_C_SOURCE); 678*3117ece4Schristos #endif 679*3117ece4Schristos #ifdef _POSIX_VERSION 680*3117ece4Schristos DISPLAYOUT("_POSIX_VERSION defined: %ldL \n", (long) _POSIX_VERSION); 681*3117ece4Schristos #endif 682*3117ece4Schristos #ifdef PLATFORM_POSIX_VERSION 683*3117ece4Schristos DISPLAYOUT("PLATFORM_POSIX_VERSION defined: %ldL\n", (long) PLATFORM_POSIX_VERSION); 684*3117ece4Schristos #endif 685*3117ece4Schristos } } 686*3117ece4Schristos } 687*3117ece4Schristos 688*3117ece4Schristos #define ZSTD_NB_STRATEGIES 9 689*3117ece4Schristos static const char* ZSTD_strategyMap[ZSTD_NB_STRATEGIES + 1] = { "", "ZSTD_fast", 690*3117ece4Schristos "ZSTD_dfast", "ZSTD_greedy", "ZSTD_lazy", "ZSTD_lazy2", "ZSTD_btlazy2", 691*3117ece4Schristos "ZSTD_btopt", "ZSTD_btultra", "ZSTD_btultra2"}; 692*3117ece4Schristos 693*3117ece4Schristos #ifndef ZSTD_NOCOMPRESS 694*3117ece4Schristos 695*3117ece4Schristos static void printDefaultCParams(const char* filename, const char* dictFileName, int cLevel) { 696*3117ece4Schristos unsigned long long fileSize = UTIL_getFileSize(filename); 697*3117ece4Schristos const size_t dictSize = dictFileName != NULL ? (size_t)UTIL_getFileSize(dictFileName) : 0; 698*3117ece4Schristos const ZSTD_compressionParameters cParams = ZSTD_getCParams(cLevel, fileSize, dictSize); 699*3117ece4Schristos if (fileSize != UTIL_FILESIZE_UNKNOWN) DISPLAY("%s (%u bytes)\n", filename, (unsigned)fileSize); 700*3117ece4Schristos else DISPLAY("%s (src size unknown)\n", filename); 701*3117ece4Schristos DISPLAY(" - windowLog : %u\n", cParams.windowLog); 702*3117ece4Schristos DISPLAY(" - chainLog : %u\n", cParams.chainLog); 703*3117ece4Schristos DISPLAY(" - hashLog : %u\n", cParams.hashLog); 704*3117ece4Schristos DISPLAY(" - searchLog : %u\n", cParams.searchLog); 705*3117ece4Schristos DISPLAY(" - minMatch : %u\n", cParams.minMatch); 706*3117ece4Schristos DISPLAY(" - targetLength : %u\n", cParams.targetLength); 707*3117ece4Schristos assert(cParams.strategy < ZSTD_NB_STRATEGIES + 1); 708*3117ece4Schristos DISPLAY(" - strategy : %s (%u)\n", ZSTD_strategyMap[(int)cParams.strategy], (unsigned)cParams.strategy); 709*3117ece4Schristos } 710*3117ece4Schristos 711*3117ece4Schristos static void printActualCParams(const char* filename, const char* dictFileName, int cLevel, const ZSTD_compressionParameters* cParams) { 712*3117ece4Schristos unsigned long long fileSize = UTIL_getFileSize(filename); 713*3117ece4Schristos const size_t dictSize = dictFileName != NULL ? (size_t)UTIL_getFileSize(dictFileName) : 0; 714*3117ece4Schristos ZSTD_compressionParameters actualCParams = ZSTD_getCParams(cLevel, fileSize, dictSize); 715*3117ece4Schristos assert(g_displayLevel >= 4); 716*3117ece4Schristos actualCParams.windowLog = cParams->windowLog == 0 ? actualCParams.windowLog : cParams->windowLog; 717*3117ece4Schristos actualCParams.chainLog = cParams->chainLog == 0 ? actualCParams.chainLog : cParams->chainLog; 718*3117ece4Schristos actualCParams.hashLog = cParams->hashLog == 0 ? actualCParams.hashLog : cParams->hashLog; 719*3117ece4Schristos actualCParams.searchLog = cParams->searchLog == 0 ? actualCParams.searchLog : cParams->searchLog; 720*3117ece4Schristos actualCParams.minMatch = cParams->minMatch == 0 ? actualCParams.minMatch : cParams->minMatch; 721*3117ece4Schristos actualCParams.targetLength = cParams->targetLength == 0 ? actualCParams.targetLength : cParams->targetLength; 722*3117ece4Schristos actualCParams.strategy = cParams->strategy == 0 ? actualCParams.strategy : cParams->strategy; 723*3117ece4Schristos DISPLAY("--zstd=wlog=%d,clog=%d,hlog=%d,slog=%d,mml=%d,tlen=%d,strat=%d\n", 724*3117ece4Schristos actualCParams.windowLog, actualCParams.chainLog, actualCParams.hashLog, actualCParams.searchLog, 725*3117ece4Schristos actualCParams.minMatch, actualCParams.targetLength, actualCParams.strategy); 726*3117ece4Schristos } 727*3117ece4Schristos 728*3117ece4Schristos #endif 729*3117ece4Schristos 730*3117ece4Schristos /* Environment variables for parameter setting */ 731*3117ece4Schristos #define ENV_CLEVEL "ZSTD_CLEVEL" 732*3117ece4Schristos #define ENV_NBTHREADS "ZSTD_NBTHREADS" /* takes lower precedence than directly specifying -T# in the CLI */ 733*3117ece4Schristos 734*3117ece4Schristos /* pick up environment variable */ 735*3117ece4Schristos static int init_cLevel(void) { 736*3117ece4Schristos const char* const env = getenv(ENV_CLEVEL); 737*3117ece4Schristos if (env != NULL) { 738*3117ece4Schristos const char* ptr = env; 739*3117ece4Schristos int sign = 1; 740*3117ece4Schristos if (*ptr == '-') { 741*3117ece4Schristos sign = -1; 742*3117ece4Schristos ptr++; 743*3117ece4Schristos } else if (*ptr == '+') { 744*3117ece4Schristos ptr++; 745*3117ece4Schristos } 746*3117ece4Schristos 747*3117ece4Schristos if ((*ptr>='0') && (*ptr<='9')) { 748*3117ece4Schristos unsigned absLevel; 749*3117ece4Schristos if (readU32FromCharChecked(&ptr, &absLevel)) { 750*3117ece4Schristos DISPLAYLEVEL(2, "Ignore environment variable setting %s=%s: numeric value too large \n", ENV_CLEVEL, env); 751*3117ece4Schristos return ZSTDCLI_CLEVEL_DEFAULT; 752*3117ece4Schristos } else if (*ptr == 0) { 753*3117ece4Schristos return sign * (int)absLevel; 754*3117ece4Schristos } } 755*3117ece4Schristos 756*3117ece4Schristos DISPLAYLEVEL(2, "Ignore environment variable setting %s=%s: not a valid integer value \n", ENV_CLEVEL, env); 757*3117ece4Schristos } 758*3117ece4Schristos 759*3117ece4Schristos return ZSTDCLI_CLEVEL_DEFAULT; 760*3117ece4Schristos } 761*3117ece4Schristos 762*3117ece4Schristos #ifdef ZSTD_MULTITHREAD 763*3117ece4Schristos static unsigned init_nbThreads(void) { 764*3117ece4Schristos const char* const env = getenv(ENV_NBTHREADS); 765*3117ece4Schristos if (env != NULL) { 766*3117ece4Schristos const char* ptr = env; 767*3117ece4Schristos if ((*ptr>='0') && (*ptr<='9')) { 768*3117ece4Schristos unsigned nbThreads; 769*3117ece4Schristos if (readU32FromCharChecked(&ptr, &nbThreads)) { 770*3117ece4Schristos DISPLAYLEVEL(2, "Ignore environment variable setting %s=%s: numeric value too large \n", ENV_NBTHREADS, env); 771*3117ece4Schristos return ZSTDCLI_NBTHREADS_DEFAULT; 772*3117ece4Schristos } else if (*ptr == 0) { 773*3117ece4Schristos return nbThreads; 774*3117ece4Schristos } 775*3117ece4Schristos } 776*3117ece4Schristos DISPLAYLEVEL(2, "Ignore environment variable setting %s=%s: not a valid unsigned value \n", ENV_NBTHREADS, env); 777*3117ece4Schristos } 778*3117ece4Schristos 779*3117ece4Schristos return ZSTDCLI_NBTHREADS_DEFAULT; 780*3117ece4Schristos } 781*3117ece4Schristos #endif 782*3117ece4Schristos 783*3117ece4Schristos #define NEXT_FIELD(ptr) { \ 784*3117ece4Schristos if (*argument == '=') { \ 785*3117ece4Schristos ptr = ++argument; \ 786*3117ece4Schristos argument += strlen(ptr); \ 787*3117ece4Schristos } else { \ 788*3117ece4Schristos argNb++; \ 789*3117ece4Schristos if (argNb >= argCount) { \ 790*3117ece4Schristos DISPLAYLEVEL(1, "error: missing command argument \n"); \ 791*3117ece4Schristos CLEAN_RETURN(1); \ 792*3117ece4Schristos } \ 793*3117ece4Schristos ptr = argv[argNb]; \ 794*3117ece4Schristos assert(ptr != NULL); \ 795*3117ece4Schristos if (ptr[0]=='-') { \ 796*3117ece4Schristos DISPLAYLEVEL(1, "error: command cannot be separated from its argument by another command \n"); \ 797*3117ece4Schristos CLEAN_RETURN(1); \ 798*3117ece4Schristos } } } 799*3117ece4Schristos 800*3117ece4Schristos #define NEXT_UINT32(val32) { \ 801*3117ece4Schristos const char* __nb; \ 802*3117ece4Schristos NEXT_FIELD(__nb); \ 803*3117ece4Schristos val32 = readU32FromChar(&__nb); \ 804*3117ece4Schristos if(*__nb != 0) { \ 805*3117ece4Schristos errorOut("error: only numeric values with optional suffixes K, KB, KiB, M, MB, MiB are allowed"); \ 806*3117ece4Schristos } \ 807*3117ece4Schristos } 808*3117ece4Schristos 809*3117ece4Schristos #define NEXT_TSIZE(valTsize) { \ 810*3117ece4Schristos const char* __nb; \ 811*3117ece4Schristos NEXT_FIELD(__nb); \ 812*3117ece4Schristos valTsize = readSizeTFromChar(&__nb); \ 813*3117ece4Schristos if(*__nb != 0) { \ 814*3117ece4Schristos errorOut("error: only numeric values with optional suffixes K, KB, KiB, M, MB, MiB are allowed"); \ 815*3117ece4Schristos } \ 816*3117ece4Schristos } 817*3117ece4Schristos 818*3117ece4Schristos typedef enum { zom_compress, zom_decompress, zom_test, zom_bench, zom_train, zom_list } zstd_operation_mode; 819*3117ece4Schristos 820*3117ece4Schristos #define CLEAN_RETURN(i) { operationResult = (i); goto _end; } 821*3117ece4Schristos 822*3117ece4Schristos #ifdef ZSTD_NOCOMPRESS 823*3117ece4Schristos /* symbols from compression library are not defined and should not be invoked */ 824*3117ece4Schristos # define MINCLEVEL -99 825*3117ece4Schristos # define MAXCLEVEL 22 826*3117ece4Schristos #else 827*3117ece4Schristos # define MINCLEVEL ZSTD_minCLevel() 828*3117ece4Schristos # define MAXCLEVEL ZSTD_maxCLevel() 829*3117ece4Schristos #endif 830*3117ece4Schristos 831*3117ece4Schristos int main(int argCount, const char* argv[]) 832*3117ece4Schristos { 833*3117ece4Schristos int argNb, 834*3117ece4Schristos followLinks = 0, 835*3117ece4Schristos allowBlockDevices = 0, 836*3117ece4Schristos forceStdin = 0, 837*3117ece4Schristos forceStdout = 0, 838*3117ece4Schristos hasStdout = 0, 839*3117ece4Schristos ldmFlag = 0, 840*3117ece4Schristos main_pause = 0, 841*3117ece4Schristos adapt = 0, 842*3117ece4Schristos adaptMin = MINCLEVEL, 843*3117ece4Schristos adaptMax = MAXCLEVEL, 844*3117ece4Schristos rsyncable = 0, 845*3117ece4Schristos nextArgumentsAreFiles = 0, 846*3117ece4Schristos operationResult = 0, 847*3117ece4Schristos separateFiles = 0, 848*3117ece4Schristos setRealTimePrio = 0, 849*3117ece4Schristos singleThread = 0, 850*3117ece4Schristos defaultLogicalCores = 0, 851*3117ece4Schristos showDefaultCParams = 0, 852*3117ece4Schristos ultra=0, 853*3117ece4Schristos contentSize=1, 854*3117ece4Schristos removeSrcFile=0; 855*3117ece4Schristos ZSTD_paramSwitch_e mmapDict=ZSTD_ps_auto; 856*3117ece4Schristos ZSTD_paramSwitch_e useRowMatchFinder = ZSTD_ps_auto; 857*3117ece4Schristos FIO_compressionType_t cType = FIO_zstdCompression; 858*3117ece4Schristos unsigned nbWorkers = 0; 859*3117ece4Schristos double compressibility = -1.0; /* lorem ipsum generator */ 860*3117ece4Schristos unsigned bench_nbSeconds = 3; /* would be better if this value was synchronized from bench */ 861*3117ece4Schristos size_t blockSize = 0; 862*3117ece4Schristos 863*3117ece4Schristos FIO_prefs_t* const prefs = FIO_createPreferences(); 864*3117ece4Schristos FIO_ctx_t* const fCtx = FIO_createContext(); 865*3117ece4Schristos FIO_progressSetting_e progress = FIO_ps_auto; 866*3117ece4Schristos zstd_operation_mode operation = zom_compress; 867*3117ece4Schristos ZSTD_compressionParameters compressionParams; 868*3117ece4Schristos int cLevel = init_cLevel(); 869*3117ece4Schristos int cLevelLast = MINCLEVEL - 1; /* lower than minimum */ 870*3117ece4Schristos unsigned recursive = 0; 871*3117ece4Schristos unsigned memLimit = 0; 872*3117ece4Schristos FileNamesTable* filenames = UTIL_allocateFileNamesTable((size_t)argCount); /* argCount >= 1 */ 873*3117ece4Schristos FileNamesTable* file_of_names = UTIL_allocateFileNamesTable((size_t)argCount); /* argCount >= 1 */ 874*3117ece4Schristos const char* programName = argv[0]; 875*3117ece4Schristos const char* outFileName = NULL; 876*3117ece4Schristos const char* outDirName = NULL; 877*3117ece4Schristos const char* outMirroredDirName = NULL; 878*3117ece4Schristos const char* dictFileName = NULL; 879*3117ece4Schristos const char* patchFromDictFileName = NULL; 880*3117ece4Schristos const char* suffix = ZSTD_EXTENSION; 881*3117ece4Schristos unsigned maxDictSize = g_defaultMaxDictSize; 882*3117ece4Schristos unsigned dictID = 0; 883*3117ece4Schristos size_t streamSrcSize = 0; 884*3117ece4Schristos size_t targetCBlockSize = 0; 885*3117ece4Schristos size_t srcSizeHint = 0; 886*3117ece4Schristos size_t nbInputFileNames = 0; 887*3117ece4Schristos int dictCLevel = g_defaultDictCLevel; 888*3117ece4Schristos unsigned dictSelect = g_defaultSelectivityLevel; 889*3117ece4Schristos #ifndef ZSTD_NODICT 890*3117ece4Schristos ZDICT_cover_params_t coverParams = defaultCoverParams(); 891*3117ece4Schristos ZDICT_fastCover_params_t fastCoverParams = defaultFastCoverParams(); 892*3117ece4Schristos dictType dict = fastCover; 893*3117ece4Schristos #endif 894*3117ece4Schristos #ifndef ZSTD_NOBENCH 895*3117ece4Schristos BMK_advancedParams_t benchParams = BMK_initAdvancedParams(); 896*3117ece4Schristos #endif 897*3117ece4Schristos ZSTD_paramSwitch_e literalCompressionMode = ZSTD_ps_auto; 898*3117ece4Schristos 899*3117ece4Schristos 900*3117ece4Schristos /* init */ 901*3117ece4Schristos checkLibVersion(); 902*3117ece4Schristos (void)recursive; (void)cLevelLast; /* not used when ZSTD_NOBENCH set */ 903*3117ece4Schristos (void)memLimit; 904*3117ece4Schristos assert(argCount >= 1); 905*3117ece4Schristos if ((filenames==NULL) || (file_of_names==NULL)) { DISPLAYLEVEL(1, "zstd: allocation error \n"); exit(1); } 906*3117ece4Schristos programName = lastNameFromPath(programName); 907*3117ece4Schristos #ifdef ZSTD_MULTITHREAD 908*3117ece4Schristos nbWorkers = init_nbThreads(); 909*3117ece4Schristos #endif 910*3117ece4Schristos 911*3117ece4Schristos /* preset behaviors */ 912*3117ece4Schristos if (exeNameMatch(programName, ZSTD_ZSTDMT)) nbWorkers=0, singleThread=0; 913*3117ece4Schristos if (exeNameMatch(programName, ZSTD_UNZSTD)) operation=zom_decompress; 914*3117ece4Schristos if (exeNameMatch(programName, ZSTD_CAT)) { operation=zom_decompress; FIO_overwriteMode(prefs); forceStdout=1; followLinks=1; FIO_setPassThroughFlag(prefs, 1); outFileName=stdoutmark; g_displayLevel=1; } /* supports multiple formats */ 915*3117ece4Schristos if (exeNameMatch(programName, ZSTD_ZCAT)) { operation=zom_decompress; FIO_overwriteMode(prefs); forceStdout=1; followLinks=1; FIO_setPassThroughFlag(prefs, 1); outFileName=stdoutmark; g_displayLevel=1; } /* behave like zcat, also supports multiple formats */ 916*3117ece4Schristos if (exeNameMatch(programName, ZSTD_GZ)) { /* behave like gzip */ 917*3117ece4Schristos suffix = GZ_EXTENSION; cType = FIO_gzipCompression; removeSrcFile=1; 918*3117ece4Schristos dictCLevel = cLevel = 6; /* gzip default is -6 */ 919*3117ece4Schristos } 920*3117ece4Schristos if (exeNameMatch(programName, ZSTD_GUNZIP)) { operation=zom_decompress; removeSrcFile=1; } /* behave like gunzip, also supports multiple formats */ 921*3117ece4Schristos if (exeNameMatch(programName, ZSTD_GZCAT)) { operation=zom_decompress; FIO_overwriteMode(prefs); forceStdout=1; followLinks=1; FIO_setPassThroughFlag(prefs, 1); outFileName=stdoutmark; g_displayLevel=1; } /* behave like gzcat, also supports multiple formats */ 922*3117ece4Schristos if (exeNameMatch(programName, ZSTD_LZMA)) { suffix = LZMA_EXTENSION; cType = FIO_lzmaCompression; removeSrcFile=1; } /* behave like lzma */ 923*3117ece4Schristos if (exeNameMatch(programName, ZSTD_UNLZMA)) { operation=zom_decompress; cType = FIO_lzmaCompression; removeSrcFile=1; } /* behave like unlzma, also supports multiple formats */ 924*3117ece4Schristos if (exeNameMatch(programName, ZSTD_XZ)) { suffix = XZ_EXTENSION; cType = FIO_xzCompression; removeSrcFile=1; } /* behave like xz */ 925*3117ece4Schristos if (exeNameMatch(programName, ZSTD_UNXZ)) { operation=zom_decompress; cType = FIO_xzCompression; removeSrcFile=1; } /* behave like unxz, also supports multiple formats */ 926*3117ece4Schristos if (exeNameMatch(programName, ZSTD_LZ4)) { suffix = LZ4_EXTENSION; cType = FIO_lz4Compression; } /* behave like lz4 */ 927*3117ece4Schristos if (exeNameMatch(programName, ZSTD_UNLZ4)) { operation=zom_decompress; cType = FIO_lz4Compression; } /* behave like unlz4, also supports multiple formats */ 928*3117ece4Schristos memset(&compressionParams, 0, sizeof(compressionParams)); 929*3117ece4Schristos 930*3117ece4Schristos /* init crash handler */ 931*3117ece4Schristos FIO_addAbortHandler(); 932*3117ece4Schristos 933*3117ece4Schristos /* command switches */ 934*3117ece4Schristos for (argNb=1; argNb<argCount; argNb++) { 935*3117ece4Schristos const char* argument = argv[argNb]; 936*3117ece4Schristos const char* const originalArgument = argument; 937*3117ece4Schristos if (!argument) continue; /* Protection if argument empty */ 938*3117ece4Schristos 939*3117ece4Schristos if (nextArgumentsAreFiles) { 940*3117ece4Schristos UTIL_refFilename(filenames, argument); 941*3117ece4Schristos continue; 942*3117ece4Schristos } 943*3117ece4Schristos 944*3117ece4Schristos /* "-" means stdin/stdout */ 945*3117ece4Schristos if (!strcmp(argument, "-")){ 946*3117ece4Schristos UTIL_refFilename(filenames, stdinmark); 947*3117ece4Schristos continue; 948*3117ece4Schristos } 949*3117ece4Schristos 950*3117ece4Schristos /* Decode commands (note : aggregated commands are allowed) */ 951*3117ece4Schristos if (argument[0]=='-') { 952*3117ece4Schristos 953*3117ece4Schristos if (argument[1]=='-') { 954*3117ece4Schristos /* long commands (--long-word) */ 955*3117ece4Schristos if (!strcmp(argument, "--")) { nextArgumentsAreFiles=1; continue; } /* only file names allowed from now on */ 956*3117ece4Schristos if (!strcmp(argument, "--list")) { operation=zom_list; continue; } 957*3117ece4Schristos if (!strcmp(argument, "--compress")) { operation=zom_compress; continue; } 958*3117ece4Schristos if (!strcmp(argument, "--decompress")) { operation=zom_decompress; continue; } 959*3117ece4Schristos if (!strcmp(argument, "--uncompress")) { operation=zom_decompress; continue; } 960*3117ece4Schristos if (!strcmp(argument, "--force")) { FIO_overwriteMode(prefs); forceStdin=1; forceStdout=1; followLinks=1; allowBlockDevices=1; continue; } 961*3117ece4Schristos if (!strcmp(argument, "--version")) { printVersion(); CLEAN_RETURN(0); } 962*3117ece4Schristos if (!strcmp(argument, "--help")) { usageAdvanced(programName); CLEAN_RETURN(0); } 963*3117ece4Schristos if (!strcmp(argument, "--verbose")) { g_displayLevel++; continue; } 964*3117ece4Schristos if (!strcmp(argument, "--quiet")) { g_displayLevel--; continue; } 965*3117ece4Schristos if (!strcmp(argument, "--stdout")) { forceStdout=1; outFileName=stdoutmark; continue; } 966*3117ece4Schristos if (!strcmp(argument, "--ultra")) { ultra=1; continue; } 967*3117ece4Schristos if (!strcmp(argument, "--check")) { FIO_setChecksumFlag(prefs, 2); continue; } 968*3117ece4Schristos if (!strcmp(argument, "--no-check")) { FIO_setChecksumFlag(prefs, 0); continue; } 969*3117ece4Schristos if (!strcmp(argument, "--sparse")) { FIO_setSparseWrite(prefs, 2); continue; } 970*3117ece4Schristos if (!strcmp(argument, "--no-sparse")) { FIO_setSparseWrite(prefs, 0); continue; } 971*3117ece4Schristos if (!strcmp(argument, "--pass-through")) { FIO_setPassThroughFlag(prefs, 1); continue; } 972*3117ece4Schristos if (!strcmp(argument, "--no-pass-through")) { FIO_setPassThroughFlag(prefs, 0); continue; } 973*3117ece4Schristos if (!strcmp(argument, "--test")) { operation=zom_test; continue; } 974*3117ece4Schristos if (!strcmp(argument, "--asyncio")) { FIO_setAsyncIOFlag(prefs, 1); continue;} 975*3117ece4Schristos if (!strcmp(argument, "--no-asyncio")) { FIO_setAsyncIOFlag(prefs, 0); continue;} 976*3117ece4Schristos if (!strcmp(argument, "--train")) { operation=zom_train; if (outFileName==NULL) outFileName=g_defaultDictName; continue; } 977*3117ece4Schristos if (!strcmp(argument, "--no-dictID")) { FIO_setDictIDFlag(prefs, 0); continue; } 978*3117ece4Schristos if (!strcmp(argument, "--keep")) { removeSrcFile=0; continue; } 979*3117ece4Schristos if (!strcmp(argument, "--rm")) { removeSrcFile=1; continue; } 980*3117ece4Schristos if (!strcmp(argument, "--priority=rt")) { setRealTimePrio = 1; continue; } 981*3117ece4Schristos if (!strcmp(argument, "--show-default-cparams")) { showDefaultCParams = 1; continue; } 982*3117ece4Schristos if (!strcmp(argument, "--content-size")) { contentSize = 1; continue; } 983*3117ece4Schristos if (!strcmp(argument, "--no-content-size")) { contentSize = 0; continue; } 984*3117ece4Schristos if (!strcmp(argument, "--adapt")) { adapt = 1; continue; } 985*3117ece4Schristos if (!strcmp(argument, "--no-row-match-finder")) { useRowMatchFinder = ZSTD_ps_disable; continue; } 986*3117ece4Schristos if (!strcmp(argument, "--row-match-finder")) { useRowMatchFinder = ZSTD_ps_enable; continue; } 987*3117ece4Schristos if (longCommandWArg(&argument, "--adapt=")) { adapt = 1; if (!parseAdaptParameters(argument, &adaptMin, &adaptMax)) { badUsage(programName, originalArgument); CLEAN_RETURN(1); } continue; } 988*3117ece4Schristos if (!strcmp(argument, "--single-thread")) { nbWorkers = 0; singleThread = 1; continue; } 989*3117ece4Schristos if (!strcmp(argument, "--format=zstd")) { suffix = ZSTD_EXTENSION; cType = FIO_zstdCompression; continue; } 990*3117ece4Schristos if (!strcmp(argument, "--mmap-dict")) { mmapDict = ZSTD_ps_enable; continue; } 991*3117ece4Schristos if (!strcmp(argument, "--no-mmap-dict")) { mmapDict = ZSTD_ps_disable; continue; } 992*3117ece4Schristos #ifdef ZSTD_GZCOMPRESS 993*3117ece4Schristos if (!strcmp(argument, "--format=gzip")) { suffix = GZ_EXTENSION; cType = FIO_gzipCompression; continue; } 994*3117ece4Schristos if (exeNameMatch(programName, ZSTD_GZ)) { /* behave like gzip */ 995*3117ece4Schristos if (!strcmp(argument, "--best")) { dictCLevel = cLevel = 9; continue; } 996*3117ece4Schristos if (!strcmp(argument, "--no-name")) { /* ignore for now */; continue; } 997*3117ece4Schristos } 998*3117ece4Schristos #endif 999*3117ece4Schristos #ifdef ZSTD_LZMACOMPRESS 1000*3117ece4Schristos if (!strcmp(argument, "--format=lzma")) { suffix = LZMA_EXTENSION; cType = FIO_lzmaCompression; continue; } 1001*3117ece4Schristos if (!strcmp(argument, "--format=xz")) { suffix = XZ_EXTENSION; cType = FIO_xzCompression; continue; } 1002*3117ece4Schristos #endif 1003*3117ece4Schristos #ifdef ZSTD_LZ4COMPRESS 1004*3117ece4Schristos if (!strcmp(argument, "--format=lz4")) { suffix = LZ4_EXTENSION; cType = FIO_lz4Compression; continue; } 1005*3117ece4Schristos #endif 1006*3117ece4Schristos if (!strcmp(argument, "--rsyncable")) { rsyncable = 1; continue; } 1007*3117ece4Schristos if (!strcmp(argument, "--compress-literals")) { literalCompressionMode = ZSTD_ps_enable; continue; } 1008*3117ece4Schristos if (!strcmp(argument, "--no-compress-literals")) { literalCompressionMode = ZSTD_ps_disable; continue; } 1009*3117ece4Schristos if (!strcmp(argument, "--no-progress")) { progress = FIO_ps_never; continue; } 1010*3117ece4Schristos if (!strcmp(argument, "--progress")) { progress = FIO_ps_always; continue; } 1011*3117ece4Schristos if (!strcmp(argument, "--exclude-compressed")) { FIO_setExcludeCompressedFile(prefs, 1); continue; } 1012*3117ece4Schristos if (!strcmp(argument, "--fake-stdin-is-console")) { UTIL_fakeStdinIsConsole(); continue; } 1013*3117ece4Schristos if (!strcmp(argument, "--fake-stdout-is-console")) { UTIL_fakeStdoutIsConsole(); continue; } 1014*3117ece4Schristos if (!strcmp(argument, "--fake-stderr-is-console")) { UTIL_fakeStderrIsConsole(); continue; } 1015*3117ece4Schristos if (!strcmp(argument, "--trace-file-stat")) { UTIL_traceFileStat(); continue; } 1016*3117ece4Schristos 1017*3117ece4Schristos /* long commands with arguments */ 1018*3117ece4Schristos #ifndef ZSTD_NODICT 1019*3117ece4Schristos if (longCommandWArg(&argument, "--train-cover")) { 1020*3117ece4Schristos operation = zom_train; 1021*3117ece4Schristos if (outFileName == NULL) 1022*3117ece4Schristos outFileName = g_defaultDictName; 1023*3117ece4Schristos dict = cover; 1024*3117ece4Schristos /* Allow optional arguments following an = */ 1025*3117ece4Schristos if (*argument == 0) { memset(&coverParams, 0, sizeof(coverParams)); } 1026*3117ece4Schristos else if (*argument++ != '=') { badUsage(programName, originalArgument); CLEAN_RETURN(1); } 1027*3117ece4Schristos else if (!parseCoverParameters(argument, &coverParams)) { badUsage(programName, originalArgument); CLEAN_RETURN(1); } 1028*3117ece4Schristos continue; 1029*3117ece4Schristos } 1030*3117ece4Schristos if (longCommandWArg(&argument, "--train-fastcover")) { 1031*3117ece4Schristos operation = zom_train; 1032*3117ece4Schristos if (outFileName == NULL) 1033*3117ece4Schristos outFileName = g_defaultDictName; 1034*3117ece4Schristos dict = fastCover; 1035*3117ece4Schristos /* Allow optional arguments following an = */ 1036*3117ece4Schristos if (*argument == 0) { memset(&fastCoverParams, 0, sizeof(fastCoverParams)); } 1037*3117ece4Schristos else if (*argument++ != '=') { badUsage(programName, originalArgument); CLEAN_RETURN(1); } 1038*3117ece4Schristos else if (!parseFastCoverParameters(argument, &fastCoverParams)) { badUsage(programName, originalArgument); CLEAN_RETURN(1); } 1039*3117ece4Schristos continue; 1040*3117ece4Schristos } 1041*3117ece4Schristos if (longCommandWArg(&argument, "--train-legacy")) { 1042*3117ece4Schristos operation = zom_train; 1043*3117ece4Schristos if (outFileName == NULL) 1044*3117ece4Schristos outFileName = g_defaultDictName; 1045*3117ece4Schristos dict = legacy; 1046*3117ece4Schristos /* Allow optional arguments following an = */ 1047*3117ece4Schristos if (*argument == 0) { continue; } 1048*3117ece4Schristos else if (*argument++ != '=') { badUsage(programName, originalArgument); CLEAN_RETURN(1); } 1049*3117ece4Schristos else if (!parseLegacyParameters(argument, &dictSelect)) { badUsage(programName, originalArgument); CLEAN_RETURN(1); } 1050*3117ece4Schristos continue; 1051*3117ece4Schristos } 1052*3117ece4Schristos #endif 1053*3117ece4Schristos if (longCommandWArg(&argument, "--threads")) { NEXT_UINT32(nbWorkers); continue; } 1054*3117ece4Schristos if (longCommandWArg(&argument, "--memlimit")) { NEXT_UINT32(memLimit); continue; } 1055*3117ece4Schristos if (longCommandWArg(&argument, "--memory")) { NEXT_UINT32(memLimit); continue; } 1056*3117ece4Schristos if (longCommandWArg(&argument, "--memlimit-decompress")) { NEXT_UINT32(memLimit); continue; } 1057*3117ece4Schristos if (longCommandWArg(&argument, "--block-size")) { NEXT_TSIZE(blockSize); continue; } 1058*3117ece4Schristos if (longCommandWArg(&argument, "--maxdict")) { NEXT_UINT32(maxDictSize); continue; } 1059*3117ece4Schristos if (longCommandWArg(&argument, "--dictID")) { NEXT_UINT32(dictID); continue; } 1060*3117ece4Schristos if (longCommandWArg(&argument, "--zstd=")) { if (!parseCompressionParameters(argument, &compressionParams)) { badUsage(programName, originalArgument); CLEAN_RETURN(1); } ; cType = FIO_zstdCompression; continue; } 1061*3117ece4Schristos if (longCommandWArg(&argument, "--stream-size")) { NEXT_TSIZE(streamSrcSize); continue; } 1062*3117ece4Schristos if (longCommandWArg(&argument, "--target-compressed-block-size")) { NEXT_TSIZE(targetCBlockSize); continue; } 1063*3117ece4Schristos if (longCommandWArg(&argument, "--size-hint")) { NEXT_TSIZE(srcSizeHint); continue; } 1064*3117ece4Schristos if (longCommandWArg(&argument, "--output-dir-flat")) { 1065*3117ece4Schristos NEXT_FIELD(outDirName); 1066*3117ece4Schristos if (strlen(outDirName) == 0) { 1067*3117ece4Schristos DISPLAYLEVEL(1, "error: output dir cannot be empty string (did you mean to pass '.' instead?)\n"); 1068*3117ece4Schristos CLEAN_RETURN(1); 1069*3117ece4Schristos } 1070*3117ece4Schristos continue; 1071*3117ece4Schristos } 1072*3117ece4Schristos if (longCommandWArg(&argument, "--auto-threads")) { 1073*3117ece4Schristos const char* threadDefault = NULL; 1074*3117ece4Schristos NEXT_FIELD(threadDefault); 1075*3117ece4Schristos if (strcmp(threadDefault, "logical") == 0) 1076*3117ece4Schristos defaultLogicalCores = 1; 1077*3117ece4Schristos continue; 1078*3117ece4Schristos } 1079*3117ece4Schristos #ifdef UTIL_HAS_MIRRORFILELIST 1080*3117ece4Schristos if (longCommandWArg(&argument, "--output-dir-mirror")) { 1081*3117ece4Schristos NEXT_FIELD(outMirroredDirName); 1082*3117ece4Schristos if (strlen(outMirroredDirName) == 0) { 1083*3117ece4Schristos DISPLAYLEVEL(1, "error: output dir cannot be empty string (did you mean to pass '.' instead?)\n"); 1084*3117ece4Schristos CLEAN_RETURN(1); 1085*3117ece4Schristos } 1086*3117ece4Schristos continue; 1087*3117ece4Schristos } 1088*3117ece4Schristos #endif 1089*3117ece4Schristos #ifndef ZSTD_NOTRACE 1090*3117ece4Schristos if (longCommandWArg(&argument, "--trace")) { char const* traceFile; NEXT_FIELD(traceFile); TRACE_enable(traceFile); continue; } 1091*3117ece4Schristos #endif 1092*3117ece4Schristos if (longCommandWArg(&argument, "--patch-from")) { NEXT_FIELD(patchFromDictFileName); continue; } 1093*3117ece4Schristos if (longCommandWArg(&argument, "--long")) { 1094*3117ece4Schristos unsigned ldmWindowLog = 0; 1095*3117ece4Schristos ldmFlag = 1; 1096*3117ece4Schristos /* Parse optional window log */ 1097*3117ece4Schristos if (*argument == '=') { 1098*3117ece4Schristos ++argument; 1099*3117ece4Schristos ldmWindowLog = readU32FromChar(&argument); 1100*3117ece4Schristos } else if (*argument != 0) { 1101*3117ece4Schristos /* Invalid character following --long */ 1102*3117ece4Schristos badUsage(programName, originalArgument); 1103*3117ece4Schristos CLEAN_RETURN(1); 1104*3117ece4Schristos } else { 1105*3117ece4Schristos ldmWindowLog = g_defaultMaxWindowLog; 1106*3117ece4Schristos } 1107*3117ece4Schristos /* Only set windowLog if not already set by --zstd */ 1108*3117ece4Schristos if (compressionParams.windowLog == 0) 1109*3117ece4Schristos compressionParams.windowLog = ldmWindowLog; 1110*3117ece4Schristos continue; 1111*3117ece4Schristos } 1112*3117ece4Schristos #ifndef ZSTD_NOCOMPRESS /* linking ZSTD_minCLevel() requires compression support */ 1113*3117ece4Schristos if (longCommandWArg(&argument, "--fast")) { 1114*3117ece4Schristos /* Parse optional acceleration factor */ 1115*3117ece4Schristos if (*argument == '=') { 1116*3117ece4Schristos U32 const maxFast = (U32)-ZSTD_minCLevel(); 1117*3117ece4Schristos U32 fastLevel; 1118*3117ece4Schristos ++argument; 1119*3117ece4Schristos fastLevel = readU32FromChar(&argument); 1120*3117ece4Schristos if (fastLevel > maxFast) fastLevel = maxFast; 1121*3117ece4Schristos if (fastLevel) { 1122*3117ece4Schristos dictCLevel = cLevel = -(int)fastLevel; 1123*3117ece4Schristos } else { 1124*3117ece4Schristos badUsage(programName, originalArgument); 1125*3117ece4Schristos CLEAN_RETURN(1); 1126*3117ece4Schristos } 1127*3117ece4Schristos } else if (*argument != 0) { 1128*3117ece4Schristos /* Invalid character following --fast */ 1129*3117ece4Schristos badUsage(programName, originalArgument); 1130*3117ece4Schristos CLEAN_RETURN(1); 1131*3117ece4Schristos } else { 1132*3117ece4Schristos cLevel = -1; /* default for --fast */ 1133*3117ece4Schristos } 1134*3117ece4Schristos continue; 1135*3117ece4Schristos } 1136*3117ece4Schristos #endif 1137*3117ece4Schristos 1138*3117ece4Schristos if (longCommandWArg(&argument, "--filelist")) { 1139*3117ece4Schristos const char* listName; 1140*3117ece4Schristos NEXT_FIELD(listName); 1141*3117ece4Schristos UTIL_refFilename(file_of_names, listName); 1142*3117ece4Schristos continue; 1143*3117ece4Schristos } 1144*3117ece4Schristos 1145*3117ece4Schristos badUsage(programName, originalArgument); 1146*3117ece4Schristos CLEAN_RETURN(1); 1147*3117ece4Schristos } 1148*3117ece4Schristos 1149*3117ece4Schristos argument++; 1150*3117ece4Schristos while (argument[0]!=0) { 1151*3117ece4Schristos 1152*3117ece4Schristos #ifndef ZSTD_NOCOMPRESS 1153*3117ece4Schristos /* compression Level */ 1154*3117ece4Schristos if ((*argument>='0') && (*argument<='9')) { 1155*3117ece4Schristos dictCLevel = cLevel = (int)readU32FromChar(&argument); 1156*3117ece4Schristos continue; 1157*3117ece4Schristos } 1158*3117ece4Schristos #endif 1159*3117ece4Schristos 1160*3117ece4Schristos switch(argument[0]) 1161*3117ece4Schristos { 1162*3117ece4Schristos /* Display help */ 1163*3117ece4Schristos case 'V': printVersion(); CLEAN_RETURN(0); /* Version Only */ 1164*3117ece4Schristos case 'H': usageAdvanced(programName); CLEAN_RETURN(0); 1165*3117ece4Schristos case 'h': usage(stdout, programName); CLEAN_RETURN(0); 1166*3117ece4Schristos 1167*3117ece4Schristos /* Compress */ 1168*3117ece4Schristos case 'z': operation=zom_compress; argument++; break; 1169*3117ece4Schristos 1170*3117ece4Schristos /* Decoding */ 1171*3117ece4Schristos case 'd': 1172*3117ece4Schristos #ifndef ZSTD_NOBENCH 1173*3117ece4Schristos benchParams.mode = BMK_decodeOnly; 1174*3117ece4Schristos if (operation==zom_bench) { argument++; break; } /* benchmark decode (hidden option) */ 1175*3117ece4Schristos #endif 1176*3117ece4Schristos operation=zom_decompress; argument++; break; 1177*3117ece4Schristos 1178*3117ece4Schristos /* Force stdout, even if stdout==console */ 1179*3117ece4Schristos case 'c': forceStdout=1; outFileName=stdoutmark; argument++; break; 1180*3117ece4Schristos 1181*3117ece4Schristos /* destination file name */ 1182*3117ece4Schristos case 'o': argument++; NEXT_FIELD(outFileName); break; 1183*3117ece4Schristos 1184*3117ece4Schristos /* do not store filename - gzip compatibility - nothing to do */ 1185*3117ece4Schristos case 'n': argument++; break; 1186*3117ece4Schristos 1187*3117ece4Schristos /* Use file content as dictionary */ 1188*3117ece4Schristos case 'D': argument++; NEXT_FIELD(dictFileName); break; 1189*3117ece4Schristos 1190*3117ece4Schristos /* Overwrite */ 1191*3117ece4Schristos case 'f': FIO_overwriteMode(prefs); forceStdin=1; forceStdout=1; followLinks=1; allowBlockDevices=1; argument++; break; 1192*3117ece4Schristos 1193*3117ece4Schristos /* Verbose mode */ 1194*3117ece4Schristos case 'v': g_displayLevel++; argument++; break; 1195*3117ece4Schristos 1196*3117ece4Schristos /* Quiet mode */ 1197*3117ece4Schristos case 'q': g_displayLevel--; argument++; break; 1198*3117ece4Schristos 1199*3117ece4Schristos /* keep source file (default) */ 1200*3117ece4Schristos case 'k': removeSrcFile=0; argument++; break; 1201*3117ece4Schristos 1202*3117ece4Schristos /* Checksum */ 1203*3117ece4Schristos case 'C': FIO_setChecksumFlag(prefs, 2); argument++; break; 1204*3117ece4Schristos 1205*3117ece4Schristos /* test compressed file */ 1206*3117ece4Schristos case 't': operation=zom_test; argument++; break; 1207*3117ece4Schristos 1208*3117ece4Schristos /* limit memory */ 1209*3117ece4Schristos case 'M': 1210*3117ece4Schristos argument++; 1211*3117ece4Schristos memLimit = readU32FromChar(&argument); 1212*3117ece4Schristos break; 1213*3117ece4Schristos case 'l': operation=zom_list; argument++; break; 1214*3117ece4Schristos #ifdef UTIL_HAS_CREATEFILELIST 1215*3117ece4Schristos /* recursive */ 1216*3117ece4Schristos case 'r': recursive=1; argument++; break; 1217*3117ece4Schristos #endif 1218*3117ece4Schristos 1219*3117ece4Schristos #ifndef ZSTD_NOBENCH 1220*3117ece4Schristos /* Benchmark */ 1221*3117ece4Schristos case 'b': 1222*3117ece4Schristos operation=zom_bench; 1223*3117ece4Schristos argument++; 1224*3117ece4Schristos break; 1225*3117ece4Schristos 1226*3117ece4Schristos /* range bench (benchmark only) */ 1227*3117ece4Schristos case 'e': 1228*3117ece4Schristos /* compression Level */ 1229*3117ece4Schristos argument++; 1230*3117ece4Schristos cLevelLast = (int)readU32FromChar(&argument); 1231*3117ece4Schristos break; 1232*3117ece4Schristos 1233*3117ece4Schristos /* Modify Nb Iterations (benchmark only) */ 1234*3117ece4Schristos case 'i': 1235*3117ece4Schristos argument++; 1236*3117ece4Schristos bench_nbSeconds = readU32FromChar(&argument); 1237*3117ece4Schristos break; 1238*3117ece4Schristos 1239*3117ece4Schristos /* cut input into blocks (benchmark only) */ 1240*3117ece4Schristos case 'B': 1241*3117ece4Schristos argument++; 1242*3117ece4Schristos blockSize = readU32FromChar(&argument); 1243*3117ece4Schristos break; 1244*3117ece4Schristos 1245*3117ece4Schristos /* benchmark files separately (hidden option) */ 1246*3117ece4Schristos case 'S': 1247*3117ece4Schristos argument++; 1248*3117ece4Schristos separateFiles = 1; 1249*3117ece4Schristos break; 1250*3117ece4Schristos 1251*3117ece4Schristos #endif /* ZSTD_NOBENCH */ 1252*3117ece4Schristos 1253*3117ece4Schristos /* nb of threads (hidden option) */ 1254*3117ece4Schristos case 'T': 1255*3117ece4Schristos argument++; 1256*3117ece4Schristos nbWorkers = readU32FromChar(&argument); 1257*3117ece4Schristos break; 1258*3117ece4Schristos 1259*3117ece4Schristos /* Dictionary Selection level */ 1260*3117ece4Schristos case 's': 1261*3117ece4Schristos argument++; 1262*3117ece4Schristos dictSelect = readU32FromChar(&argument); 1263*3117ece4Schristos break; 1264*3117ece4Schristos 1265*3117ece4Schristos /* Pause at the end (-p) or set an additional param (-p#) (hidden option) */ 1266*3117ece4Schristos case 'p': argument++; 1267*3117ece4Schristos #ifndef ZSTD_NOBENCH 1268*3117ece4Schristos if ((*argument>='0') && (*argument<='9')) { 1269*3117ece4Schristos benchParams.additionalParam = (int)readU32FromChar(&argument); 1270*3117ece4Schristos } else 1271*3117ece4Schristos #endif 1272*3117ece4Schristos main_pause=1; 1273*3117ece4Schristos break; 1274*3117ece4Schristos 1275*3117ece4Schristos /* Select compressibility of synthetic sample */ 1276*3117ece4Schristos case 'P': 1277*3117ece4Schristos argument++; 1278*3117ece4Schristos compressibility = (double)readU32FromChar(&argument) / 100; 1279*3117ece4Schristos break; 1280*3117ece4Schristos 1281*3117ece4Schristos /* unknown command */ 1282*3117ece4Schristos default : 1283*3117ece4Schristos { char shortArgument[3] = {'-', 0, 0}; 1284*3117ece4Schristos shortArgument[1] = argument[0]; 1285*3117ece4Schristos badUsage(programName, shortArgument); 1286*3117ece4Schristos CLEAN_RETURN(1); 1287*3117ece4Schristos } 1288*3117ece4Schristos } 1289*3117ece4Schristos } 1290*3117ece4Schristos continue; 1291*3117ece4Schristos } /* if (argument[0]=='-') */ 1292*3117ece4Schristos 1293*3117ece4Schristos /* none of the above : add filename to list */ 1294*3117ece4Schristos UTIL_refFilename(filenames, argument); 1295*3117ece4Schristos } 1296*3117ece4Schristos 1297*3117ece4Schristos /* Welcome message (if verbose) */ 1298*3117ece4Schristos DISPLAYLEVEL(3, WELCOME_MESSAGE); 1299*3117ece4Schristos 1300*3117ece4Schristos #ifdef ZSTD_MULTITHREAD 1301*3117ece4Schristos if ((operation==zom_decompress) && (!singleThread) && (nbWorkers > 1)) { 1302*3117ece4Schristos DISPLAYLEVEL(2, "Warning : decompression does not support multi-threading\n"); 1303*3117ece4Schristos } 1304*3117ece4Schristos if ((nbWorkers==0) && (!singleThread)) { 1305*3117ece4Schristos /* automatically set # workers based on # of reported cpus */ 1306*3117ece4Schristos if (defaultLogicalCores) { 1307*3117ece4Schristos nbWorkers = (unsigned)UTIL_countLogicalCores(); 1308*3117ece4Schristos DISPLAYLEVEL(3, "Note: %d logical core(s) detected \n", nbWorkers); 1309*3117ece4Schristos } else { 1310*3117ece4Schristos nbWorkers = (unsigned)UTIL_countPhysicalCores(); 1311*3117ece4Schristos DISPLAYLEVEL(3, "Note: %d physical core(s) detected \n", nbWorkers); 1312*3117ece4Schristos } 1313*3117ece4Schristos } 1314*3117ece4Schristos #else 1315*3117ece4Schristos (void)singleThread; (void)nbWorkers; (void)defaultLogicalCores; 1316*3117ece4Schristos #endif 1317*3117ece4Schristos 1318*3117ece4Schristos g_utilDisplayLevel = g_displayLevel; 1319*3117ece4Schristos 1320*3117ece4Schristos #ifdef UTIL_HAS_CREATEFILELIST 1321*3117ece4Schristos if (!followLinks) { 1322*3117ece4Schristos unsigned u, fileNamesNb; 1323*3117ece4Schristos unsigned const nbFilenames = (unsigned)filenames->tableSize; 1324*3117ece4Schristos for (u=0, fileNamesNb=0; u<nbFilenames; u++) { 1325*3117ece4Schristos if ( UTIL_isLink(filenames->fileNames[u]) 1326*3117ece4Schristos && !UTIL_isFIFO(filenames->fileNames[u]) 1327*3117ece4Schristos ) { 1328*3117ece4Schristos DISPLAYLEVEL(2, "Warning : %s is a symbolic link, ignoring \n", filenames->fileNames[u]); 1329*3117ece4Schristos } else { 1330*3117ece4Schristos filenames->fileNames[fileNamesNb++] = filenames->fileNames[u]; 1331*3117ece4Schristos } } 1332*3117ece4Schristos if (fileNamesNb == 0 && nbFilenames > 0) /* all names are eliminated */ 1333*3117ece4Schristos CLEAN_RETURN(1); 1334*3117ece4Schristos filenames->tableSize = fileNamesNb; 1335*3117ece4Schristos } /* if (!followLinks) */ 1336*3117ece4Schristos 1337*3117ece4Schristos /* read names from a file */ 1338*3117ece4Schristos if (file_of_names->tableSize) { 1339*3117ece4Schristos size_t const nbFileLists = file_of_names->tableSize; 1340*3117ece4Schristos size_t flNb; 1341*3117ece4Schristos for (flNb=0; flNb < nbFileLists; flNb++) { 1342*3117ece4Schristos FileNamesTable* const fnt = UTIL_createFileNamesTable_fromFileName(file_of_names->fileNames[flNb]); 1343*3117ece4Schristos if (fnt==NULL) { 1344*3117ece4Schristos DISPLAYLEVEL(1, "zstd: error reading %s \n", file_of_names->fileNames[flNb]); 1345*3117ece4Schristos CLEAN_RETURN(1); 1346*3117ece4Schristos } 1347*3117ece4Schristos filenames = UTIL_mergeFileNamesTable(filenames, fnt); 1348*3117ece4Schristos } 1349*3117ece4Schristos } 1350*3117ece4Schristos 1351*3117ece4Schristos nbInputFileNames = filenames->tableSize; /* saving number of input files */ 1352*3117ece4Schristos 1353*3117ece4Schristos if (recursive) { /* at this stage, filenameTable is a list of paths, which can contain both files and directories */ 1354*3117ece4Schristos UTIL_expandFNT(&filenames, followLinks); 1355*3117ece4Schristos } 1356*3117ece4Schristos #else 1357*3117ece4Schristos (void)followLinks; 1358*3117ece4Schristos #endif 1359*3117ece4Schristos 1360*3117ece4Schristos if (operation == zom_list) { 1361*3117ece4Schristos #ifndef ZSTD_NODECOMPRESS 1362*3117ece4Schristos int const ret = FIO_listMultipleFiles((unsigned)filenames->tableSize, filenames->fileNames, g_displayLevel); 1363*3117ece4Schristos CLEAN_RETURN(ret); 1364*3117ece4Schristos #else 1365*3117ece4Schristos DISPLAYLEVEL(1, "file information is not supported \n"); 1366*3117ece4Schristos CLEAN_RETURN(1); 1367*3117ece4Schristos #endif 1368*3117ece4Schristos } 1369*3117ece4Schristos 1370*3117ece4Schristos /* Check if benchmark is selected */ 1371*3117ece4Schristos if (operation==zom_bench) { 1372*3117ece4Schristos #ifndef ZSTD_NOBENCH 1373*3117ece4Schristos if (cType != FIO_zstdCompression) { 1374*3117ece4Schristos DISPLAYLEVEL(1, "benchmark mode is only compatible with zstd format \n"); 1375*3117ece4Schristos CLEAN_RETURN(1); 1376*3117ece4Schristos } 1377*3117ece4Schristos benchParams.blockSize = blockSize; 1378*3117ece4Schristos benchParams.targetCBlockSize = targetCBlockSize; 1379*3117ece4Schristos benchParams.nbWorkers = (int)nbWorkers; 1380*3117ece4Schristos benchParams.realTime = (unsigned)setRealTimePrio; 1381*3117ece4Schristos benchParams.nbSeconds = bench_nbSeconds; 1382*3117ece4Schristos benchParams.ldmFlag = ldmFlag; 1383*3117ece4Schristos benchParams.ldmMinMatch = (int)g_ldmMinMatch; 1384*3117ece4Schristos benchParams.ldmHashLog = (int)g_ldmHashLog; 1385*3117ece4Schristos benchParams.useRowMatchFinder = (int)useRowMatchFinder; 1386*3117ece4Schristos if (g_ldmBucketSizeLog != LDM_PARAM_DEFAULT) { 1387*3117ece4Schristos benchParams.ldmBucketSizeLog = (int)g_ldmBucketSizeLog; 1388*3117ece4Schristos } 1389*3117ece4Schristos if (g_ldmHashRateLog != LDM_PARAM_DEFAULT) { 1390*3117ece4Schristos benchParams.ldmHashRateLog = (int)g_ldmHashRateLog; 1391*3117ece4Schristos } 1392*3117ece4Schristos benchParams.literalCompressionMode = literalCompressionMode; 1393*3117ece4Schristos 1394*3117ece4Schristos if (cLevel > ZSTD_maxCLevel()) cLevel = ZSTD_maxCLevel(); 1395*3117ece4Schristos if (cLevelLast > ZSTD_maxCLevel()) cLevelLast = ZSTD_maxCLevel(); 1396*3117ece4Schristos if (cLevelLast < cLevel) cLevelLast = cLevel; 1397*3117ece4Schristos if (cLevelLast > cLevel) 1398*3117ece4Schristos DISPLAYLEVEL(3, "Benchmarking levels from %d to %d\n", cLevel, cLevelLast); 1399*3117ece4Schristos if (filenames->tableSize > 0) { 1400*3117ece4Schristos if(separateFiles) { 1401*3117ece4Schristos unsigned i; 1402*3117ece4Schristos for(i = 0; i < filenames->tableSize; i++) { 1403*3117ece4Schristos int c; 1404*3117ece4Schristos DISPLAYLEVEL(3, "Benchmarking %s \n", filenames->fileNames[i]); 1405*3117ece4Schristos for(c = cLevel; c <= cLevelLast; c++) { 1406*3117ece4Schristos operationResult = BMK_benchFilesAdvanced(&filenames->fileNames[i], 1, dictFileName, c, &compressionParams, g_displayLevel, &benchParams); 1407*3117ece4Schristos } } 1408*3117ece4Schristos } else { 1409*3117ece4Schristos for(; cLevel <= cLevelLast; cLevel++) { 1410*3117ece4Schristos operationResult = BMK_benchFilesAdvanced(filenames->fileNames, (unsigned)filenames->tableSize, dictFileName, cLevel, &compressionParams, g_displayLevel, &benchParams); 1411*3117ece4Schristos } } 1412*3117ece4Schristos } else { 1413*3117ece4Schristos for(; cLevel <= cLevelLast; cLevel++) { 1414*3117ece4Schristos operationResult = BMK_syntheticTest(cLevel, compressibility, &compressionParams, g_displayLevel, &benchParams); 1415*3117ece4Schristos } } 1416*3117ece4Schristos 1417*3117ece4Schristos #else 1418*3117ece4Schristos (void)bench_nbSeconds; (void)blockSize; (void)setRealTimePrio; (void)separateFiles; (void)compressibility; 1419*3117ece4Schristos #endif 1420*3117ece4Schristos goto _end; 1421*3117ece4Schristos } 1422*3117ece4Schristos 1423*3117ece4Schristos /* Check if dictionary builder is selected */ 1424*3117ece4Schristos if (operation==zom_train) { 1425*3117ece4Schristos #ifndef ZSTD_NODICT 1426*3117ece4Schristos ZDICT_params_t zParams; 1427*3117ece4Schristos zParams.compressionLevel = dictCLevel; 1428*3117ece4Schristos zParams.notificationLevel = (unsigned)g_displayLevel; 1429*3117ece4Schristos zParams.dictID = dictID; 1430*3117ece4Schristos if (dict == cover) { 1431*3117ece4Schristos int const optimize = !coverParams.k || !coverParams.d; 1432*3117ece4Schristos coverParams.nbThreads = (unsigned)nbWorkers; 1433*3117ece4Schristos coverParams.zParams = zParams; 1434*3117ece4Schristos operationResult = DiB_trainFromFiles(outFileName, maxDictSize, filenames->fileNames, (int)filenames->tableSize, blockSize, NULL, &coverParams, NULL, optimize, memLimit); 1435*3117ece4Schristos } else if (dict == fastCover) { 1436*3117ece4Schristos int const optimize = !fastCoverParams.k || !fastCoverParams.d; 1437*3117ece4Schristos fastCoverParams.nbThreads = (unsigned)nbWorkers; 1438*3117ece4Schristos fastCoverParams.zParams = zParams; 1439*3117ece4Schristos operationResult = DiB_trainFromFiles(outFileName, maxDictSize, filenames->fileNames, (int)filenames->tableSize, blockSize, NULL, NULL, &fastCoverParams, optimize, memLimit); 1440*3117ece4Schristos } else { 1441*3117ece4Schristos ZDICT_legacy_params_t dictParams; 1442*3117ece4Schristos memset(&dictParams, 0, sizeof(dictParams)); 1443*3117ece4Schristos dictParams.selectivityLevel = dictSelect; 1444*3117ece4Schristos dictParams.zParams = zParams; 1445*3117ece4Schristos operationResult = DiB_trainFromFiles(outFileName, maxDictSize, filenames->fileNames, (int)filenames->tableSize, blockSize, &dictParams, NULL, NULL, 0, memLimit); 1446*3117ece4Schristos } 1447*3117ece4Schristos #else 1448*3117ece4Schristos (void)dictCLevel; (void)dictSelect; (void)dictID; (void)maxDictSize; /* not used when ZSTD_NODICT set */ 1449*3117ece4Schristos DISPLAYLEVEL(1, "training mode not available \n"); 1450*3117ece4Schristos operationResult = 1; 1451*3117ece4Schristos #endif 1452*3117ece4Schristos goto _end; 1453*3117ece4Schristos } 1454*3117ece4Schristos 1455*3117ece4Schristos #ifndef ZSTD_NODECOMPRESS 1456*3117ece4Schristos if (operation==zom_test) { FIO_setTestMode(prefs, 1); outFileName=nulmark; removeSrcFile=0; } /* test mode */ 1457*3117ece4Schristos #endif 1458*3117ece4Schristos 1459*3117ece4Schristos /* No input filename ==> use stdin and stdout */ 1460*3117ece4Schristos if (filenames->tableSize == 0) { 1461*3117ece4Schristos /* It is possible that the input 1462*3117ece4Schristos was a number of empty directories. In this case 1463*3117ece4Schristos stdin and stdout should not be used */ 1464*3117ece4Schristos if (nbInputFileNames > 0 ){ 1465*3117ece4Schristos DISPLAYLEVEL(1, "please provide correct input file(s) or non-empty directories -- ignored \n"); 1466*3117ece4Schristos CLEAN_RETURN(0); 1467*3117ece4Schristos } 1468*3117ece4Schristos UTIL_refFilename(filenames, stdinmark); 1469*3117ece4Schristos } 1470*3117ece4Schristos 1471*3117ece4Schristos if (filenames->tableSize == 1 && !strcmp(filenames->fileNames[0], stdinmark) && !outFileName) 1472*3117ece4Schristos outFileName = stdoutmark; /* when input is stdin, default output is stdout */ 1473*3117ece4Schristos 1474*3117ece4Schristos /* Check if input/output defined as console; trigger an error in this case */ 1475*3117ece4Schristos if (!forceStdin 1476*3117ece4Schristos && (UTIL_searchFileNamesTable(filenames, stdinmark) != -1) 1477*3117ece4Schristos && UTIL_isConsole(stdin) ) { 1478*3117ece4Schristos DISPLAYLEVEL(1, "stdin is a console, aborting\n"); 1479*3117ece4Schristos CLEAN_RETURN(1); 1480*3117ece4Schristos } 1481*3117ece4Schristos if ( (!outFileName || !strcmp(outFileName, stdoutmark)) 1482*3117ece4Schristos && UTIL_isConsole(stdout) 1483*3117ece4Schristos && (UTIL_searchFileNamesTable(filenames, stdinmark) != -1) 1484*3117ece4Schristos && !forceStdout 1485*3117ece4Schristos && operation!=zom_decompress ) { 1486*3117ece4Schristos DISPLAYLEVEL(1, "stdout is a console, aborting\n"); 1487*3117ece4Schristos CLEAN_RETURN(1); 1488*3117ece4Schristos } 1489*3117ece4Schristos 1490*3117ece4Schristos #ifndef ZSTD_NOCOMPRESS 1491*3117ece4Schristos /* check compression level limits */ 1492*3117ece4Schristos { int const maxCLevel = ultra ? ZSTD_maxCLevel() : ZSTDCLI_CLEVEL_MAX; 1493*3117ece4Schristos if (cLevel > maxCLevel) { 1494*3117ece4Schristos DISPLAYLEVEL(2, "Warning : compression level higher than max, reduced to %i \n", maxCLevel); 1495*3117ece4Schristos cLevel = maxCLevel; 1496*3117ece4Schristos } } 1497*3117ece4Schristos #endif 1498*3117ece4Schristos 1499*3117ece4Schristos if (showDefaultCParams) { 1500*3117ece4Schristos if (operation == zom_decompress) { 1501*3117ece4Schristos DISPLAYLEVEL(1, "error : can't use --show-default-cparams in decompression mode \n"); 1502*3117ece4Schristos CLEAN_RETURN(1); 1503*3117ece4Schristos } 1504*3117ece4Schristos } 1505*3117ece4Schristos 1506*3117ece4Schristos if (dictFileName != NULL && patchFromDictFileName != NULL) { 1507*3117ece4Schristos DISPLAYLEVEL(1, "error : can't use -D and --patch-from=# at the same time \n"); 1508*3117ece4Schristos CLEAN_RETURN(1); 1509*3117ece4Schristos } 1510*3117ece4Schristos 1511*3117ece4Schristos if (patchFromDictFileName != NULL && filenames->tableSize > 1) { 1512*3117ece4Schristos DISPLAYLEVEL(1, "error : can't use --patch-from=# on multiple files \n"); 1513*3117ece4Schristos CLEAN_RETURN(1); 1514*3117ece4Schristos } 1515*3117ece4Schristos 1516*3117ece4Schristos /* No status message by default when output is stdout */ 1517*3117ece4Schristos hasStdout = outFileName && !strcmp(outFileName,stdoutmark); 1518*3117ece4Schristos if (hasStdout && (g_displayLevel==2)) g_displayLevel=1; 1519*3117ece4Schristos 1520*3117ece4Schristos /* when stderr is not the console, do not pollute it with progress updates (unless requested) */ 1521*3117ece4Schristos if (!UTIL_isConsole(stderr) && (progress!=FIO_ps_always)) progress=FIO_ps_never; 1522*3117ece4Schristos FIO_setProgressSetting(progress); 1523*3117ece4Schristos 1524*3117ece4Schristos /* don't remove source files when output is stdout */; 1525*3117ece4Schristos if (hasStdout && removeSrcFile) { 1526*3117ece4Schristos DISPLAYLEVEL(3, "Note: src files are not removed when output is stdout \n"); 1527*3117ece4Schristos removeSrcFile = 0; 1528*3117ece4Schristos } 1529*3117ece4Schristos FIO_setRemoveSrcFile(prefs, removeSrcFile); 1530*3117ece4Schristos 1531*3117ece4Schristos /* IO Stream/File */ 1532*3117ece4Schristos FIO_setHasStdoutOutput(fCtx, hasStdout); 1533*3117ece4Schristos FIO_setNbFilesTotal(fCtx, (int)filenames->tableSize); 1534*3117ece4Schristos FIO_determineHasStdinInput(fCtx, filenames); 1535*3117ece4Schristos FIO_setNotificationLevel(g_displayLevel); 1536*3117ece4Schristos FIO_setAllowBlockDevices(prefs, allowBlockDevices); 1537*3117ece4Schristos FIO_setPatchFromMode(prefs, patchFromDictFileName != NULL); 1538*3117ece4Schristos FIO_setMMapDict(prefs, mmapDict); 1539*3117ece4Schristos if (memLimit == 0) { 1540*3117ece4Schristos if (compressionParams.windowLog == 0) { 1541*3117ece4Schristos memLimit = (U32)1 << g_defaultMaxWindowLog; 1542*3117ece4Schristos } else { 1543*3117ece4Schristos memLimit = (U32)1 << (compressionParams.windowLog & 31); 1544*3117ece4Schristos } } 1545*3117ece4Schristos if (patchFromDictFileName != NULL) 1546*3117ece4Schristos dictFileName = patchFromDictFileName; 1547*3117ece4Schristos FIO_setMemLimit(prefs, memLimit); 1548*3117ece4Schristos if (operation==zom_compress) { 1549*3117ece4Schristos #ifndef ZSTD_NOCOMPRESS 1550*3117ece4Schristos FIO_setCompressionType(prefs, cType); 1551*3117ece4Schristos FIO_setContentSize(prefs, contentSize); 1552*3117ece4Schristos FIO_setNbWorkers(prefs, (int)nbWorkers); 1553*3117ece4Schristos FIO_setBlockSize(prefs, (int)blockSize); 1554*3117ece4Schristos if (g_overlapLog!=OVERLAP_LOG_DEFAULT) FIO_setOverlapLog(prefs, (int)g_overlapLog); 1555*3117ece4Schristos FIO_setLdmFlag(prefs, (unsigned)ldmFlag); 1556*3117ece4Schristos FIO_setLdmHashLog(prefs, (int)g_ldmHashLog); 1557*3117ece4Schristos FIO_setLdmMinMatch(prefs, (int)g_ldmMinMatch); 1558*3117ece4Schristos if (g_ldmBucketSizeLog != LDM_PARAM_DEFAULT) FIO_setLdmBucketSizeLog(prefs, (int)g_ldmBucketSizeLog); 1559*3117ece4Schristos if (g_ldmHashRateLog != LDM_PARAM_DEFAULT) FIO_setLdmHashRateLog(prefs, (int)g_ldmHashRateLog); 1560*3117ece4Schristos FIO_setAdaptiveMode(prefs, adapt); 1561*3117ece4Schristos FIO_setUseRowMatchFinder(prefs, (int)useRowMatchFinder); 1562*3117ece4Schristos FIO_setAdaptMin(prefs, adaptMin); 1563*3117ece4Schristos FIO_setAdaptMax(prefs, adaptMax); 1564*3117ece4Schristos FIO_setRsyncable(prefs, rsyncable); 1565*3117ece4Schristos FIO_setStreamSrcSize(prefs, streamSrcSize); 1566*3117ece4Schristos FIO_setTargetCBlockSize(prefs, targetCBlockSize); 1567*3117ece4Schristos FIO_setSrcSizeHint(prefs, srcSizeHint); 1568*3117ece4Schristos FIO_setLiteralCompressionMode(prefs, literalCompressionMode); 1569*3117ece4Schristos FIO_setSparseWrite(prefs, 0); 1570*3117ece4Schristos if (adaptMin > cLevel) cLevel = adaptMin; 1571*3117ece4Schristos if (adaptMax < cLevel) cLevel = adaptMax; 1572*3117ece4Schristos 1573*3117ece4Schristos /* Compare strategies constant with the ground truth */ 1574*3117ece4Schristos { ZSTD_bounds strategyBounds = ZSTD_cParam_getBounds(ZSTD_c_strategy); 1575*3117ece4Schristos assert(ZSTD_NB_STRATEGIES == strategyBounds.upperBound); 1576*3117ece4Schristos (void)strategyBounds; } 1577*3117ece4Schristos 1578*3117ece4Schristos if (showDefaultCParams || g_displayLevel >= 4) { 1579*3117ece4Schristos size_t fileNb; 1580*3117ece4Schristos for (fileNb = 0; fileNb < (size_t)filenames->tableSize; fileNb++) { 1581*3117ece4Schristos if (showDefaultCParams) 1582*3117ece4Schristos printDefaultCParams(filenames->fileNames[fileNb], dictFileName, cLevel); 1583*3117ece4Schristos if (g_displayLevel >= 4) 1584*3117ece4Schristos printActualCParams(filenames->fileNames[fileNb], dictFileName, cLevel, &compressionParams); 1585*3117ece4Schristos } 1586*3117ece4Schristos } 1587*3117ece4Schristos 1588*3117ece4Schristos if (g_displayLevel >= 4) 1589*3117ece4Schristos FIO_displayCompressionParameters(prefs); 1590*3117ece4Schristos if ((filenames->tableSize==1) && outFileName) 1591*3117ece4Schristos operationResult = FIO_compressFilename(fCtx, prefs, outFileName, filenames->fileNames[0], dictFileName, cLevel, compressionParams); 1592*3117ece4Schristos else 1593*3117ece4Schristos operationResult = FIO_compressMultipleFilenames(fCtx, prefs, filenames->fileNames, outMirroredDirName, outDirName, outFileName, suffix, dictFileName, cLevel, compressionParams); 1594*3117ece4Schristos #else 1595*3117ece4Schristos /* these variables are only used when compression mode is enabled */ 1596*3117ece4Schristos (void)contentSize; (void)suffix; (void)adapt; (void)rsyncable; 1597*3117ece4Schristos (void)ultra; (void)cLevel; (void)ldmFlag; (void)literalCompressionMode; 1598*3117ece4Schristos (void)targetCBlockSize; (void)streamSrcSize; (void)srcSizeHint; 1599*3117ece4Schristos (void)ZSTD_strategyMap; (void)useRowMatchFinder; (void)cType; 1600*3117ece4Schristos DISPLAYLEVEL(1, "Compression not supported \n"); 1601*3117ece4Schristos #endif 1602*3117ece4Schristos } else { /* decompression or test */ 1603*3117ece4Schristos #ifndef ZSTD_NODECOMPRESS 1604*3117ece4Schristos if (filenames->tableSize == 1 && outFileName) { 1605*3117ece4Schristos operationResult = FIO_decompressFilename(fCtx, prefs, outFileName, filenames->fileNames[0], dictFileName); 1606*3117ece4Schristos } else { 1607*3117ece4Schristos operationResult = FIO_decompressMultipleFilenames(fCtx, prefs, filenames->fileNames, outMirroredDirName, outDirName, outFileName, dictFileName); 1608*3117ece4Schristos } 1609*3117ece4Schristos #else 1610*3117ece4Schristos DISPLAYLEVEL(1, "Decompression not supported \n"); 1611*3117ece4Schristos #endif 1612*3117ece4Schristos } 1613*3117ece4Schristos 1614*3117ece4Schristos _end: 1615*3117ece4Schristos FIO_freePreferences(prefs); 1616*3117ece4Schristos FIO_freeContext(fCtx); 1617*3117ece4Schristos if (main_pause) waitEnter(); 1618*3117ece4Schristos UTIL_freeFileNamesTable(filenames); 1619*3117ece4Schristos UTIL_freeFileNamesTable(file_of_names); 1620*3117ece4Schristos #ifndef ZSTD_NOTRACE 1621*3117ece4Schristos TRACE_finish(); 1622*3117ece4Schristos #endif 1623*3117ece4Schristos 1624*3117ece4Schristos return operationResult; 1625*3117ece4Schristos } 1626