diff options
Diffstat (limited to 'programs')
-rw-r--r-- | programs/.gitignore | 4 | ||||
-rw-r--r-- | programs/Makefile | 39 | ||||
-rw-r--r-- | programs/README.md | 45 | ||||
-rw-r--r-- | programs/bench.c | 8 | ||||
-rw-r--r-- | programs/bench.h | 8 | ||||
-rw-r--r-- | programs/datagen.c | 8 | ||||
-rw-r--r-- | programs/datagen.h | 10 | ||||
-rw-r--r-- | programs/dibio.c | 8 | ||||
-rw-r--r-- | programs/dibio.h | 8 | ||||
-rw-r--r-- | programs/fileio.c | 467 | ||||
-rw-r--r-- | programs/fileio.h | 8 | ||||
-rw-r--r-- | programs/platform.h | 12 | ||||
-rw-r--r-- | programs/util.h | 12 | ||||
-rw-r--r-- | programs/zstd.1 | 6 | ||||
-rw-r--r-- | programs/zstd.1.md | 5 | ||||
-rw-r--r-- | programs/zstdcli.c | 106 |
16 files changed, 410 insertions, 344 deletions
diff --git a/programs/.gitignore b/programs/.gitignore index eeaf051d6edf..701830c777c2 100644 --- a/programs/.gitignore +++ b/programs/.gitignore @@ -1,8 +1,12 @@ # local binary (Makefile) zstd zstd32 +zstd4 zstd-compress zstd-decompress +zstd-frugal +zstd-small +zstd-nolegacy # Object files *.o diff --git a/programs/Makefile b/programs/Makefile index 8b080d446606..c5469cfc4def 100644 --- a/programs/Makefile +++ b/programs/Makefile @@ -39,9 +39,10 @@ endif CPPFLAGS+= -I$(ZSTDDIR) -I$(ZSTDDIR)/common -I$(ZSTDDIR)/compress \ -I$(ZSTDDIR)/dictBuilder \ + -DZSTD_NEWAPI \ -DXXH_NAMESPACE=ZSTD_ # because xxhash.o already compiled with this macro from library CFLAGS ?= -O3 -DEBUGFLAGS = -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \ +DEBUGFLAGS= -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \ -Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \ -Wstrict-prototypes -Wundef -Wpointer-arith -Wformat-security \ -Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \ @@ -131,12 +132,15 @@ else LZ4_MSG := $(NO_LZ4_MSG) endif -.PHONY: default all clean clean_decomp_o install uninstall generate_res - +.PHONY: default default: zstd-release +.PHONY: all all: zstd +.PHONY: allVariants +allVariants: zstd zstd-compress zstd-decompress zstd-small zstd-nolegacy + $(ZSTDDECOMP_O): CFLAGS += $(ALIGN_LOOP) zstd zstd4 : CPPFLAGS += $(THREAD_CPP) $(ZLIBCPP) $(LZMACPP) @@ -153,8 +157,9 @@ zstd zstd4 : $(ZSTDLIB_FILES) zstdcli.o fileio.o bench.o datagen.o dibio.o ifneq (,$(filter Windows%,$(OS))) windres/generate_res.bat endif - $(CC) $(FLAGS) $^ $(RES_FILE) -o zstd$(EXT) $(LDFLAGS) + $(CC) $(FLAGS) $^ $(RES_FILE) -o $@$(EXT) $(LDFLAGS) +.PHONY: zstd-release zstd-release: DEBUGFLAGS := zstd-release: zstd @@ -165,8 +170,8 @@ ifneq (,$(filter Windows%,$(OS))) endif $(CC) -m32 $(FLAGS) $^ $(RES32_FILE) -o $@$(EXT) -zstd-nolegacy : clean_decomp_o - $(MAKE) zstd ZSTD_LEGACY_SUPPORT=0 +zstd-nolegacy : $(ZSTD_FILES) $(ZDICT_FILES) zstdcli.o fileio.c bench.o datagen.o dibio.o + $(CC) $(FLAGS) $^ -o $@$(EXT) $(LDFLAGS) zstd-nomt : THREAD_CPP := zstd-nomt : THREAD_LD := @@ -197,9 +202,9 @@ zstd-pgo : clean zstd $(MAKE) zstd MOREFLAGS=-fprofile-use # minimal target, with only zstd compression and decompression. no bench. no legacy. -zstd-small: CFLAGS = "-Os -s" +zstd-small: CFLAGS = -Os -s zstd-frugal zstd-small: $(ZSTD_FILES) zstdcli.c fileio.c - $(CC) $(FLAGS) -DZSTD_NOBENCH -DZSTD_NODICT $^ -o zstd$(EXT) + $(CC) $(FLAGS) -DZSTD_NOBENCH -DZSTD_NODICT $^ -o $@$(EXT) zstd-decompress: $(ZSTDCOMMON_FILES) $(ZSTDDECOMP_FILES) zstdcli.c fileio.c $(CC) $(FLAGS) -DZSTD_NOBENCH -DZSTD_NODICT -DZSTD_NOCOMPRESS $^ -o $@$(EXT) @@ -207,34 +212,37 @@ zstd-decompress: $(ZSTDCOMMON_FILES) $(ZSTDDECOMP_FILES) zstdcli.c fileio.c zstd-compress: $(ZSTDCOMMON_FILES) $(ZSTDCOMP_FILES) zstdcli.c fileio.c $(CC) $(FLAGS) -DZSTD_NOBENCH -DZSTD_NODICT -DZSTD_NODECOMPRESS $^ -o $@$(EXT) -# zstd is now built with Multi-threading by default +# zstd is now built with multithreading enabled y default zstdmt: zstd +.PHONY: generate_res generate_res: windres/generate_res.bat +.PHONY: clean clean: $(MAKE) -C $(ZSTDDIR) clean @$(RM) $(ZSTDDIR)/decompress/*.o $(ZSTDDIR)/decompress/zstd_decompress.gcda @$(RM) core *.o tmp* result* *.gcda dictionary *.zst \ zstd$(EXT) zstd32$(EXT) zstd-compress$(EXT) zstd-decompress$(EXT) \ + zstd-small$(EXT) zstd-frugal$(EXT) zstd-nolegacy$(EXT) zstd4$(EXT) \ *.gcda default.profraw have_zlib$(EXT) @echo Cleaning completed -clean_decomp_o: - @$(RM) $(ZSTDDECOMP_O) - MD2ROFF = ronn MD2ROFF_FLAGS = --roff --warnings --manual="User Commands" --organization="zstd $(ZSTD_VERSION)" zstd.1: zstd.1.md cat $^ | $(MD2ROFF) $(MD2ROFF_FLAGS) | sed -n '/^\.\\\".*/!p' > $@ +.PHONY: man man: zstd.1 +.PHONY: clean-man clean-man: rm zstd.1 +.PHONY: preview-man preview-man: clean-man man man ./zstd.1 @@ -243,6 +251,10 @@ preview-man: clean-man man #----------------------------------------------------------------------------- ifneq (,$(filter $(shell uname),Linux Darwin GNU/kFreeBSD GNU OpenBSD FreeBSD NetBSD DragonFly SunOS)) +.PHONY: list +list: + @$(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | sort | egrep -v -e '^[^[:alnum:]]' -e '^$@$$' | xargs + ifneq (,$(filter $(shell uname),SunOS)) INSTALL ?= ginstall else @@ -263,6 +275,7 @@ INSTALL_PROGRAM ?= $(INSTALL) -m 755 INSTALL_SCRIPT ?= $(INSTALL) -m 755 INSTALL_MAN ?= $(INSTALL) -m 644 +.PHONY: install install: zstd @echo Installing binaries @$(INSTALL) -d -m 755 $(DESTDIR)$(BINDIR)/ $(DESTDIR)$(MANDIR)/ @@ -278,6 +291,7 @@ install: zstd @ln -sf zstd.1 $(DESTDIR)$(MANDIR)/unzstd.1 @echo zstd installation completed +.PHONY: uninstall uninstall: @$(RM) $(DESTDIR)$(BINDIR)/zstdgrep @$(RM) $(DESTDIR)$(BINDIR)/zstdless @@ -288,4 +302,5 @@ uninstall: @$(RM) $(DESTDIR)$(MANDIR)/unzstd.1 @$(RM) $(DESTDIR)$(MANDIR)/zstd.1 @echo zstd programs successfully uninstalled + endif diff --git a/programs/README.md b/programs/README.md index bd8fba069952..8b65dfdb3f24 100644 --- a/programs/README.md +++ b/programs/README.md @@ -3,44 +3,54 @@ Command Line Interface for Zstandard library Command Line Interface (CLI) can be created using the `make` command without any additional parameters. There are however other Makefile targets that create different variations of CLI: -- `zstd` : default CLI supporting gzip-like arguments; includes dictionary builder, benchmark, and support for decompression of legacy zstd versions -- `zstd32` : Same as `zstd`, but forced to compile in 32-bits mode -- `zstd_nolegacy` : Same as `zstd` except of support for decompression of legacy zstd versions -- `zstd-small` : CLI optimized for minimal size; without dictionary builder, benchmark, and support for decompression of legacy zstd versions -- `zstd-compress` : compressor-only version of CLI; without dictionary builder, benchmark, and support for decompression of legacy zstd versions -- `zstd-decompress` : decompressor-only version of CLI; without dictionary builder, benchmark, and support for decompression of legacy zstd versions +- `zstd` : default CLI supporting gzip-like arguments; includes dictionary builder, benchmark, and support for decompression of legacy zstd formats +- `zstd_nolegacy` : Same as `zstd` but without support for legacy zstd formats +- `zstd-small` : CLI optimized for minimal size; no dictionary builder, no benchmark, and no support for legacy zstd formats +- `zstd-compress` : version of CLI which can only compress into zstd format +- `zstd-decompress` : version of CLI which can only decompress zstd format #### Compilation variables -`zstd` tries to detect and use the following features automatically : +`zstd` scope can be altered by modifying the following compilation variables : - __HAVE_THREAD__ : multithreading is automatically enabled when `pthread` is detected. - It's possible to disable multithread support, by either compiling `zstd-nomt` target or using HAVE_THREAD=0 variable. + It's possible to disable multithread support, by setting HAVE_THREAD=0 . Example : make zstd HAVE_THREAD=0 It's also possible to force compilation with multithread support, using HAVE_THREAD=1. In which case, linking stage will fail if `pthread` library cannot be found. This might be useful to prevent silent feature disabling. - __HAVE_ZLIB__ : `zstd` can compress and decompress files in `.gz` format. - This is done through command `--format=gzip`. + This is ordered through command `--format=gzip`. Alternatively, symlinks named `gzip` or `gunzip` will mimic intended behavior. `.gz` support is automatically enabled when `zlib` library is detected at build time. - It's possible to disable `.gz` support, by either compiling `zstd-nogz` target or using HAVE_ZLIB=0 variable. + It's possible to disable `.gz` support, by setting HAVE_ZLIB=0. Example : make zstd HAVE_ZLIB=0 It's also possible to force compilation with zlib support, using HAVE_ZLIB=1. In which case, linking stage will fail if `zlib` library cannot be found. This might be useful to prevent silent feature disabling. - __HAVE_LZMA__ : `zstd` can compress and decompress files in `.xz` and `.lzma` formats. - This is done through commands `--format=xz` and `--format=lzma` respectively. + This is ordered through commands `--format=xz` and `--format=lzma` respectively. Alternatively, symlinks named `xz`, `unxz`, `lzma`, or `unlzma` will mimic intended behavior. `.xz` and `.lzma` support is automatically enabled when `lzma` library is detected at build time. - It's possible to disable `.xz` and `.lzma` support, by either compiling `zstd-noxz` target or using HAVE_LZMA=0 variable. + It's possible to disable `.xz` and `.lzma` support, by setting HAVE_LZMA=0 . Example : make zstd HAVE_LZMA=0 It's also possible to force compilation with lzma support, using HAVE_LZMA=1. In which case, linking stage will fail if `lzma` library cannot be found. This might be useful to prevent silent feature disabling. +- __ZSTD_LEGACY_SUPPORT__ : `zstd` can decompress files compressed by older versions of `zstd`. + Starting v0.8.0, all versions of `zstd` produce frames compliant with the [specification](../doc/zstd_compression_format.md), and are therefore compatible. + But older versions (< v0.8.0) produced different, incompatible, frames. + By default, `zstd` supports decoding legacy formats >= v0.4.0 (`ZSTD_LEGACY_SUPPORT=4`). + This can be altered by modifying this compilation variable. + `ZSTD_LEGACY_SUPPORT=1` means "support all formats >= v0.1.0". + `ZSTD_LEGACY_SUPPORT=2` means "support all formats >= v0.2.0", and so on. + `ZSTD_LEGACY_SUPPORT=0` means _DO NOT_ support any legacy format. + if `ZSTD_LEGACY_SUPPORT >= 8`, it's the same as `0`, since there is no legacy format after `7`. + Note : `zstd` only supports decoding older formats, and cannot generate any legacy format. + #### Aggregation of parameters CLI supports aggregation of parameters i.e. `-b1`, `-e18`, and `-i1` can be joined into `-b1e18i1`. @@ -61,7 +71,7 @@ will rely more and more on previously decoded content to compress the rest of th Usage of the dictionary builder and created dictionaries with CLI: -1. Create the dictionary : `zstd --train FullPathToTrainingSet/* -o dictionaryName` +1. Create the dictionary : `zstd --train PathToTrainingSet/* -o dictionaryName` 2. Compress with the dictionary: `zstd FILE -D dictionaryName` 3. Decompress with the dictionary: `zstd --decompress FILE.zst -D dictionaryName` @@ -70,8 +80,8 @@ Usage of the dictionary builder and created dictionaries with CLI: CLI includes in-memory compression benchmark module for zstd. The benchmark is conducted using given filenames. The files are read into memory and joined together. It makes benchmark more precise as it eliminates I/O overhead. -Many filenames can be supplied as multiple parameters, parameters with wildcards or -names of directories can be used as parameters with the `-r` option. +Multiple filenames can be supplied, as multiple parameters, with wildcards, +or names of directories can be used as parameters with `-r` option. The benchmark measures ratio, compressed size, compression and decompression speed. One can select compression levels starting from `-b` and ending with `-e`. @@ -101,13 +111,14 @@ Advanced arguments : -v : verbose mode; specify multiple times to increase verbosity -q : suppress warnings; specify twice to suppress errors too -c : force write to standard output, even if it is the console + -l : print information about zstd compressed files --ultra : enable levels beyond 19, up to 22 (requires more memory) - -T# : use # threads for compression (default:1) - -B# : select size of each job (default:0==automatic) --no-dictID : don't write dictID into header (dictionary compression) --[no-]check : integrity check (default:enabled) -r : operate recursively on directories --format=gzip : compress files to the .gz format +--format=xz : compress files to the .xz format +--format=lzma : compress files to the .lzma format --test : test compressed file integrity --[no-]sparse : sparse mode (default:disabled) -M# : Set a memory usage limit for decompression diff --git a/programs/bench.c b/programs/bench.c index f9493e3b0707..2b48a4663a86 100644 --- a/programs/bench.c +++ b/programs/bench.c @@ -1,10 +1,10 @@ -/** +/* * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). */ diff --git a/programs/bench.h b/programs/bench.h index 77a527f8ff82..5f8d61a25b30 100644 --- a/programs/bench.h +++ b/programs/bench.h @@ -1,10 +1,10 @@ -/** +/* * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). */ diff --git a/programs/datagen.c b/programs/datagen.c index d0116b97232f..b1da8e78b31e 100644 --- a/programs/datagen.c +++ b/programs/datagen.c @@ -1,10 +1,10 @@ -/** +/* * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). */ diff --git a/programs/datagen.h b/programs/datagen.h index 094056b696ca..5b1b7c47cc5d 100644 --- a/programs/datagen.h +++ b/programs/datagen.h @@ -1,11 +1,13 @@ -/** +/* * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). */ + + #ifndef DATAGEN_H #define DATAGEN_H diff --git a/programs/dibio.c b/programs/dibio.c index 31cde5c95db1..ab2dc285a273 100644 --- a/programs/dibio.c +++ b/programs/dibio.c @@ -1,10 +1,10 @@ -/** +/* * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). */ diff --git a/programs/dibio.h b/programs/dibio.h index 84f7d580283d..0227239b26db 100644 --- a/programs/dibio.h +++ b/programs/dibio.h @@ -1,10 +1,10 @@ -/** +/* * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). */ /* This library is designed for a single-threaded console application. diff --git a/programs/fileio.c b/programs/fileio.c index 1dd8008e8495..65b4c7579194 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -1,10 +1,10 @@ -/** +/* * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). */ @@ -925,230 +925,6 @@ int FIO_compressFilename(const char* dstFileName, const char* srcFileName, return result; } -typedef struct { - int numActualFrames; - int numSkippableFrames; - unsigned long long decompressedSize; - int decompUnavailable; - unsigned long long compressedSize; - int usesCheck; -} fileInfo_t; - -/* - * Reads information from file, stores in *info - * if successful, returns 0, returns 1 for frame analysis error, returns 2 for file not compressed with zstd - * returns 3 for cases in which file could not be opened. - */ -static int getFileInfo(fileInfo_t* info, const char* inFileName){ - int detectError = 0; - FILE* const srcFile = FIO_openSrcFile(inFileName); - if (srcFile == NULL) { - DISPLAY("Error: could not open source file %s\n", inFileName); - return 3; - } - info->compressedSize = (unsigned long long)UTIL_getFileSize(inFileName); - /* begin analyzing frame */ - for ( ; ; ) { - BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX]; - size_t const numBytesRead = fread(headerBuffer, 1, sizeof(headerBuffer), srcFile); - if (numBytesRead < ZSTD_frameHeaderSize_min) { - if (feof(srcFile) && numBytesRead == 0 && info->compressedSize > 0) { - break; - } - else if (feof(srcFile)) { - DISPLAY("Error: reached end of file with incomplete frame\n"); - detectError = 2; - break; - } - else { - DISPLAY("Error: did not reach end of file but ran out of frames\n"); - detectError = 1; - break; - } - } - { - U32 const magicNumber = MEM_readLE32(headerBuffer); - if (magicNumber == ZSTD_MAGICNUMBER) { - U64 const frameContentSize = ZSTD_getFrameContentSize(headerBuffer, numBytesRead); - if (frameContentSize == ZSTD_CONTENTSIZE_ERROR || frameContentSize == ZSTD_CONTENTSIZE_UNKNOWN) { - info->decompUnavailable = 1; - } - else { - info->decompressedSize += frameContentSize; - } - { - /* move to the end of the frame header */ - size_t const headerSize = ZSTD_frameHeaderSize(headerBuffer, numBytesRead); - if (ZSTD_isError(headerSize)) { - DISPLAY("Error: could not determine frame header size\n"); - detectError = 1; - break; - } - { - int const ret = fseek(srcFile, ((long)headerSize)-((long)numBytesRead), SEEK_CUR); - if (ret != 0) { - DISPLAY("Error: could not move to end of frame header\n"); - detectError = 1; - break; - } - } - } - - /* skip the rest of the blocks in the frame */ - { - int lastBlock = 0; - do { - BYTE blockHeaderBuffer[3]; - U32 blockHeader; - int blockSize; - size_t const readBytes = fread(blockHeaderBuffer, 1, 3, srcFile); - if (readBytes != 3) { - DISPLAY("There was a problem reading the block header\n"); - detectError = 1; - break; - } - blockHeader = MEM_readLE24(blockHeaderBuffer); - lastBlock = blockHeader & 1; - blockSize = blockHeader >> 3; - { - int const ret = fseek(srcFile, blockSize, SEEK_CUR); - if (ret != 0) { - DISPLAY("Error: could not skip to end of block\n"); - detectError = 1; - break; - } - } - } while (lastBlock != 1); - - if (detectError) { - break; - } - } - { - /* check if checksum is used */ - BYTE const frameHeaderDescriptor = headerBuffer[4]; - int const contentChecksumFlag = (frameHeaderDescriptor & (1 << 2)) >> 2; - if (contentChecksumFlag) { - int const ret = fseek(srcFile, 4, SEEK_CUR); - info->usesCheck = 1; - if (ret != 0) { - DISPLAY("Error: could not skip past checksum\n"); - detectError = 1; - break; - } - } - } - info->numActualFrames++; - } - else if (magicNumber == ZSTD_MAGIC_SKIPPABLE_START) { - BYTE frameSizeBuffer[4]; - size_t const readBytes = fread(frameSizeBuffer, 1, 4, srcFile); - if (readBytes != 4) { - DISPLAY("There was an error reading skippable frame size"); - detectError = 1; - break; - } - { - U32 const frameSize = MEM_readLE32(frameSizeBuffer); - int const ret = LONG_SEEK(srcFile, frameSize, SEEK_CUR); - if (ret != 0) { - DISPLAY("Error: could not find end of skippable frame\n"); - detectError = 1; - break; - } - } - info->numSkippableFrames++; - } - else { - detectError = 2; - break; - } - } - } - fclose(srcFile); - return detectError; -} - -static void displayInfo(const char* inFileName, fileInfo_t* info, int displayLevel){ - double const compressedSizeMB = (double)info->compressedSize/(1 MB); - double const decompressedSizeMB = (double)info->decompressedSize/(1 MB); - double const ratio = (info->compressedSize == 0) ? 0 : ((double)info->decompressedSize)/info->compressedSize; - const char* const checkString = (info->usesCheck ? "XXH64" : "None"); - if (displayLevel <= 2) { - if (!info->decompUnavailable) { - DISPLAYOUT("Skippable Non-Skippable Compressed Uncompressed Ratio Check Filename\n"); - DISPLAYOUT("%9d %13d %7.2f MB %9.2f MB %5.3f %5s %s\n", - info->numSkippableFrames, info->numActualFrames, compressedSizeMB, decompressedSizeMB, - ratio, checkString, inFileName); - } - else { - DISPLAYOUT("Skippable Non-Skippable Compressed Check Filename\n"); - DISPLAYOUT("%9d %13d %7.2f MB %5s %s\n", - info->numSkippableFrames, info->numActualFrames, compressedSizeMB, checkString, inFileName); - } - } - else{ - DISPLAYOUT("# Zstandard Frames: %d\n", info->numActualFrames); - DISPLAYOUT("# Skippable Frames: %d\n", info->numSkippableFrames); - DISPLAYOUT("Compressed Size: %.2f MB (%llu B)\n", compressedSizeMB, info->compressedSize); - if (!info->decompUnavailable) { - DISPLAYOUT("Decompressed Size: %.2f MB (%llu B)\n", decompressedSizeMB, info->decompressedSize); - DISPLAYOUT("Ratio: %.4f\n", ratio); - } - DISPLAYOUT("Check: %s\n", checkString); - DISPLAYOUT("\n"); - } -} - - -static int FIO_listFile(const char* inFileName, int displayLevel, unsigned fileNo, unsigned numFiles){ - /* initialize info to avoid warnings */ - fileInfo_t info; - memset(&info, 0, sizeof(info)); - DISPLAYOUT("%s (%u/%u):\n", inFileName, fileNo, numFiles); - { - int const error = getFileInfo(&info, inFileName); - if (error == 1) { - /* display error, but provide output */ - DISPLAY("An error occurred with getting file info\n"); - } - else if (error == 2) { - DISPLAYOUT("File %s not compressed with zstd\n", inFileName); - if (displayLevel > 2) { - DISPLAYOUT("\n"); - } - return 1; - } - else if (error == 3) { - /* error occurred with opening the file */ - if (displayLevel > 2) { - DISPLAYOUT("\n"); - } - return 1; - } - displayInfo(inFileName, &info, displayLevel); - return error; - } -} - -int FIO_listMultipleFiles(unsigned numFiles, const char** filenameTable, int displayLevel){ - if (numFiles == 0) { - DISPLAYOUT("No files given\n"); - return 0; - } - DISPLAYOUT("===========================================\n"); - DISPLAYOUT("Printing information about compressed files\n"); - DISPLAYOUT("===========================================\n"); - DISPLAYOUT("Number of files listed: %u\n", numFiles); - { - int error = 0; - unsigned u; - for (u=0; u<numFiles;u++) { - error |= FIO_listFile(filenameTable[u], displayLevel, u+1, numFiles); - } - return error; - } -} int FIO_compressMultipleFilenames(const char** inFileNamesTable, unsigned nbFiles, const char* suffix, @@ -1194,10 +970,8 @@ int FIO_compressMultipleFilenames(const char** inFileNamesTable, unsigned nbFile missed_files += FIO_compressFilename_dstFile(ress, dstFileName, inFileNamesTable[u], compressionLevel); } } - /* Close & Free */ FIO_freeCResources(ress); free(dstFileName); - return missed_files; } @@ -1208,8 +982,8 @@ int FIO_compressMultipleFilenames(const char** inFileNamesTable, unsigned nbFile #ifndef ZSTD_NODECOMPRESS /* ************************************************************************** -* Decompression -****************************************************************************/ + * Decompression + ***************************************************************************/ typedef struct { void* srcBuffer; size_t srcBufferLoaded; @@ -1616,7 +1390,7 @@ static unsigned long long FIO_decompressLz4Frame(dRess_t* ress, /* Write Block */ if (decodedBytes) { if (fwrite(ress->dstBuffer, 1, decodedBytes, ress->dstFile) != decodedBytes) { - DISPLAYLEVEL(1, "zstd: %s \n", strerr(errno)); + DISPLAYLEVEL(1, "zstd: %s \n", strerror(errno)); decodingError = 1; break; } filesize += decodedBytes; @@ -1878,4 +1652,231 @@ int FIO_decompressMultipleFilenames(const char** srcNamesTable, unsigned nbFiles return missingFiles + skippedFiles; } + + +/* ************************************************************************** + * .zst file info (--list command) + ***************************************************************************/ + +typedef struct { + int numActualFrames; + int numSkippableFrames; + unsigned long long decompressedSize; + int decompUnavailable; + unsigned long long compressedSize; + int usesCheck; +} fileInfo_t; + +/** getFileInfo() : + * Reads information from file, stores in *info + * @return : 0 if successful + * 1 for frame analysis error + * 2 for file not compressed with zstd + * 3 for cases in which file could not be opened. + */ +static int getFileInfo(fileInfo_t* info, const char* inFileName){ + int detectError = 0; + FILE* const srcFile = FIO_openSrcFile(inFileName); + if (srcFile == NULL) { + DISPLAY("Error: could not open source file %s\n", inFileName); + return 3; + } + info->compressedSize = (unsigned long long)UTIL_getFileSize(inFileName); + + /* begin analyzing frame */ + for ( ; ; ) { + BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX]; + size_t const numBytesRead = fread(headerBuffer, 1, sizeof(headerBuffer), srcFile); + if (numBytesRead < ZSTD_frameHeaderSize_min) { + if (feof(srcFile) && numBytesRead == 0 && info->compressedSize > 0) { + break; + } + else if (feof(srcFile)) { + DISPLAY("Error: reached end of file with incomplete frame\n"); + detectError = 2; + break; + } + else { + DISPLAY("Error: did not reach end of file but ran out of frames\n"); + detectError = 1; + break; + } + } + { U32 const magicNumber = MEM_readLE32(headerBuffer); + /* Zstandard frame */ + if (magicNumber == ZSTD_MAGICNUMBER) { + U64 const frameContentSize = ZSTD_getFrameContentSize(headerBuffer, numBytesRead); + if (frameContentSize == ZSTD_CONTENTSIZE_ERROR || frameContentSize == ZSTD_CONTENTSIZE_UNKNOWN) { + info->decompUnavailable = 1; + } else { + info->decompressedSize += frameContentSize; + } + /* move to the end of the frame header */ + { size_t const headerSize = ZSTD_frameHeaderSize(headerBuffer, numBytesRead); + if (ZSTD_isError(headerSize)) { + DISPLAY("Error: could not determine frame header size\n"); + detectError = 1; + break; + } + { int const ret = fseek(srcFile, ((long)headerSize)-((long)numBytesRead), SEEK_CUR); + if (ret != 0) { + DISPLAY("Error: could not move to end of frame header\n"); + detectError = 1; + break; + } } } + + /* skip the rest of the blocks in the frame */ + { int lastBlock = 0; + do { + BYTE blockHeaderBuffer[3]; + size_t const readBytes = fread(blockHeaderBuffer, 1, 3, srcFile); + if (readBytes != 3) { + DISPLAY("There was a problem reading the block header\n"); + detectError = 1; + break; + } + { U32 const blockHeader = MEM_readLE24(blockHeaderBuffer); + U32 const blockTypeID = (blockHeader >> 1) & 3; + U32 const isRLE = (blockTypeID == 1); + U32 const isWrongBlock = (blockTypeID == 3); + long const blockSize = isRLE ? 1 : (long)(blockHeader >> 3); + if (isWrongBlock) { + DISPLAY("Error: unsupported block type \n"); + detectError = 1; + break; + } + lastBlock = blockHeader & 1; + { int const ret = fseek(srcFile, blockSize, SEEK_CUR); + if (ret != 0) { + DISPLAY("Error: could not skip to end of block\n"); + detectError = 1; + break; + } } } + } while (lastBlock != 1); + + if (detectError) break; + } + + /* check if checksum is used */ + { BYTE const frameHeaderDescriptor = headerBuffer[4]; + int const contentChecksumFlag = (frameHeaderDescriptor & (1 << 2)) >> 2; + if (contentChecksumFlag) { + int const ret = fseek(srcFile, 4, SEEK_CUR); + info->usesCheck = 1; + if (ret != 0) { + DISPLAY("Error: could not skip past checksum\n"); + detectError = 1; + break; + } } } + info->numActualFrames++; + } + /* Skippable frame */ + else if ((magicNumber & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) { + U32 const frameSize = MEM_readLE32(headerBuffer + 4); + long const seek = (long)(8 + frameSize - numBytesRead); + int const ret = LONG_SEEK(srcFile, seek, SEEK_CUR); + if (ret != 0) { + DISPLAY("Error: could not find end of skippable frame\n"); + detectError = 1; + break; + } + info->numSkippableFrames++; + } + /* unknown content */ + else { + detectError = 2; + break; + } + } + } /* end analyzing frame */ + fclose(srcFile); + return detectError; +} + +static void displayInfo(const char* inFileName, fileInfo_t* info, int displayLevel){ + unsigned const unit = info->compressedSize < (1 MB) ? (1 KB) : (1 MB); + const char* const unitStr = info->compressedSize < (1 MB) ? "KB" : "MB"; + double const compressedSizeUnit = (double)info->compressedSize / unit; + double const decompressedSizeUnit = (double)info->decompressedSize / unit; + double const ratio = (info->compressedSize == 0) ? 0 : ((double)info->decompressedSize)/info->compressedSize; + const char* const checkString = (info->usesCheck ? "XXH64" : "None"); + if (displayLevel <= 2) { + if (!info->decompUnavailable) { + DISPLAYOUT("Skippable Non-Skippable Compressed Uncompressed Ratio Check Filename\n"); + DISPLAYOUT("%9d %13d %7.2f %2s %9.2f %2s %5.3f %5s %s\n", + info->numSkippableFrames, info->numActualFrames, + compressedSizeUnit, unitStr, decompressedSizeUnit, unitStr, + ratio, checkString, inFileName); + } else { + DISPLAYOUT("Skippable Non-Skippable Compressed Check Filename\n"); + DISPLAYOUT("%9d %13d %7.2f MB %5s %s\n", + info->numSkippableFrames, info->numActualFrames, + compressedSizeUnit, checkString, inFileName); + } + } else { + DISPLAYOUT("# Zstandard Frames: %d\n", info->numActualFrames); + DISPLAYOUT("# Skippable Frames: %d\n", info->numSkippableFrames); + DISPLAYOUT("Compressed Size: %.2f %2s (%llu B)\n", + compressedSizeUnit, unitStr, info->compressedSize); + if (!info->decompUnavailable) { + DISPLAYOUT("Decompressed Size: %.2f %2s (%llu B)\n", + decompressedSizeUnit, unitStr, info->decompressedSize); + DISPLAYOUT("Ratio: %.4f\n", ratio); + } + DISPLAYOUT("Check: %s\n", checkString); + DISPLAYOUT("\n"); + } +} + + +static int FIO_listFile(const char* inFileName, int displayLevel, unsigned fileNo, unsigned numFiles){ + /* initialize info to avoid warnings */ + fileInfo_t info; + memset(&info, 0, sizeof(info)); + DISPLAYOUT("%s (%u/%u):\n", inFileName, fileNo, numFiles); + { + int const error = getFileInfo(&info, inFileName); + if (error == 1) { + /* display error, but provide output */ + DISPLAY("An error occurred with getting file info\n"); + } + else if (error == 2) { + DISPLAYOUT("File %s not compressed with zstd\n", inFileName); + if (displayLevel > 2) { + DISPLAYOUT("\n"); + } + return 1; + } + else if (error == 3) { + /* error occurred with opening the file */ + if (displayLevel > 2) { + DISPLAYOUT("\n"); + } + return 1; + } + displayInfo(inFileName, &info, displayLevel); + return error; + } +} + +int FIO_listMultipleFiles(unsigned numFiles, const char** filenameTable, int displayLevel){ + if (numFiles == 0) { + DISPLAYOUT("No files given\n"); + return 0; + } + DISPLAYOUT("===========================================\n"); + DISPLAYOUT("Printing information about compressed files\n"); + DISPLAYOUT("===========================================\n"); + DISPLAYOUT("Number of files listed: %u\n", numFiles); + { + int error = 0; + unsigned u; + for (u=0; u<numFiles;u++) { + error |= FIO_listFile(filenameTable[u], displayLevel, u+1, numFiles); + } + return error; + } +} + + #endif /* #ifndef ZSTD_NODECOMPRESS */ diff --git a/programs/fileio.h b/programs/fileio.h index 9d9167df9ef5..8008e97dd5f3 100644 --- a/programs/fileio.h +++ b/programs/fileio.h @@ -1,10 +1,10 @@ -/** +/* * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). */ diff --git a/programs/platform.h b/programs/platform.h index 74412cde332e..fb2e9b173d2a 100644 --- a/programs/platform.h +++ b/programs/platform.h @@ -1,12 +1,10 @@ -/** - * platform.h - compiler and OS detection - * - * Copyright (c) 2016-present, Przemyslaw Skibinski, Yann Collet, Facebook, Inc. +/* + * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). */ #ifndef PLATFORM_H_MODULE diff --git a/programs/util.h b/programs/util.h index dd971e0f884b..7b553661cde3 100644 --- a/programs/util.h +++ b/programs/util.h @@ -1,12 +1,10 @@ -/** - * util.h - utility functions - * - * Copyright (c) 2016-present, Przemyslaw Skibinski, Yann Collet, Facebook, Inc. +/* + * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). */ #ifndef UTIL_H_MODULE diff --git a/programs/zstd.1 b/programs/zstd.1 index 5df45db2153e..5a91eea281f4 100644 --- a/programs/zstd.1 +++ b/programs/zstd.1 @@ -1,5 +1,5 @@ . -.TH "ZSTD" "1" "June 2017" "zstd 1.3.0" "User Commands" +.TH "ZSTD" "1" "August 2017" "zstd 1.3.1" "User Commands" . .SH "NAME" \fBzstd\fR \- zstd, zstdmt, unzstd, zstdcat \- Compress or decompress \.zst files @@ -105,7 +105,7 @@ unlocks high compression levels 20+ (maximum 22), using a lot more memory\. Note . .TP \fB\-T#\fR, \fB\-\-threads=#\fR -Compress using \fB#\fR threads (default: 1)\. If \fB#\fR is 0, attempt to detect and use the number of physical CPU cores\. This modifier does nothing if \fBzstd\fR is compiled without multithread support\. +Compress using \fB#\fR threads (default: 1)\. If \fB#\fR is 0, attempt to detect and use the number of physical CPU cores\. In all cases, the nb of threads is capped to ZSTDMT_NBTHREADS_MAX==256\. This modifier does nothing if \fBzstd\fR is compiled without multithread support\. . .TP \fB\-D file\fR @@ -149,7 +149,7 @@ display help/long help and exit . .TP \fB\-V\fR, \fB\-\-version\fR -display version number and exit +display version number and exit\. Advanced : \fB\-vV\fR also displays supported formats\. \fB\-vvV\fR also displays POSIX support\. . .TP \fB\-v\fR diff --git a/programs/zstd.1.md b/programs/zstd.1.md index 24e25a2f3af1..4310afa1aaf8 100644 --- a/programs/zstd.1.md +++ b/programs/zstd.1.md @@ -108,6 +108,7 @@ the last one takes effect. * `-T#`, `--threads=#`: Compress using `#` threads (default: 1). If `#` is 0, attempt to detect and use the number of physical CPU cores. + In all cases, the nb of threads is capped to ZSTDMT_NBTHREADS_MAX==256. This modifier does nothing if `zstd` is compiled without multithread support. * `-D file`: use `file` as Dictionary to compress or decompress FILE(s) @@ -139,7 +140,9 @@ the last one takes effect. * `-h`/`-H`, `--help`: display help/long help and exit * `-V`, `--version`: - display version number and exit + display version number and exit. + Advanced : `-vV` also displays supported formats. + `-vvV` also displays POSIX support. * `-v`: verbose mode * `-q`, `--quiet`: diff --git a/programs/zstdcli.c b/programs/zstdcli.c index 35772e0a7140..e7eb71db6e37 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -1,10 +1,10 @@ -/** +/* * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). */ @@ -16,7 +16,7 @@ #endif #ifndef ZSTDCLI_CLEVEL_MAX -# define ZSTDCLI_CLEVEL_MAX 19 /* when not using --ultra */ +# define ZSTDCLI_CLEVEL_MAX 19 /* without using --ultra */ #endif @@ -26,14 +26,15 @@ **************************************/ #include "platform.h" /* IS_CONSOLE, PLATFORM_POSIX_VERSION */ #include "util.h" /* UTIL_HAS_CREATEFILELIST, UTIL_createFileList */ +#include <stdio.h> /* fprintf(), stdin, stdout, stderr */ #include <string.h> /* strcmp, strlen */ #include <errno.h> /* errno */ -#include "fileio.h" +#include "fileio.h" /* stdinmark, stdoutmark, ZSTD_EXTENSION */ #ifndef ZSTD_NOBENCH # include "bench.h" /* BMK_benchFiles, BMK_SetNbSeconds */ #endif #ifndef ZSTD_NODICT -# include "dibio.h" +# include "dibio.h" /* ZDICT_cover_params_t, DiB_trainFromFiles() */ #endif #define ZSTD_STATIC_LINKING_ONLY /* ZSTD_maxCLevel */ #include "zstd.h" /* ZSTD_VERSION_STRING */ @@ -64,7 +65,7 @@ #define MB *(1 <<20) #define GB *(1U<<30) -#define DEFAULT_DISPLAY_LEVEL 2 +#define DISPLAY_LEVEL_DEFAULT 2 static const char* g_defaultDictName = "dictionary"; static const unsigned g_defaultMaxDictSize = 110 KB; @@ -79,7 +80,7 @@ static U32 g_overlapLog = OVERLAP_LOG_DEFAULT; **************************************/ #define DISPLAY(...) fprintf(g_displayOut, __VA_ARGS__) #define DISPLAYLEVEL(l, ...) { if (g_displayLevel>=l) { DISPLAY(__VA_ARGS__); } } -static int g_displayLevel = DEFAULT_DISPLAY_LEVEL; /* 0 : no display, 1: errors, 2 : + result + interaction + warnings, 3 : + progression, 4 : + information */ +static int g_displayLevel = DISPLAY_LEVEL_DEFAULT; /* 0 : no display, 1: errors, 2 : + result + interaction + warnings, 3 : + progression, 4 : + information */ static FILE* g_displayOut; @@ -88,12 +89,12 @@ static FILE* g_displayOut; **************************************/ static int usage(const char* programName) { - DISPLAY( "Usage :\n"); - DISPLAY( " %s [args] [FILE(s)] [-o file]\n", programName); + DISPLAY( "Usage : \n"); + DISPLAY( " %s [args] [FILE(s)] [-o file] \n", programName); DISPLAY( "\n"); - DISPLAY( "FILE : a filename\n"); + DISPLAY( "FILE : a filename \n"); DISPLAY( " with no FILE, or when FILE is - , read standard input\n"); - DISPLAY( "Arguments :\n"); + DISPLAY( "Arguments : \n"); #ifndef ZSTD_NOCOMPRESS DISPLAY( " -# : # compression level (1-%d, default:%d) \n", ZSTDCLI_CLEVEL_MAX, ZSTDCLI_CLEVEL_DEFAULT); #endif @@ -105,7 +106,7 @@ static int usage(const char* programName) DISPLAY( " -f : overwrite output without prompting and (de)compress links \n"); DISPLAY( "--rm : remove source file(s) after successful de/compression \n"); DISPLAY( " -k : preserve source file(s) (default) \n"); - DISPLAY( " -h/-H : display help/long help and exit\n"); + DISPLAY( " -h/-H : display help/long help and exit \n"); return 0; } @@ -114,12 +115,12 @@ static int usage_advanced(const char* programName) DISPLAY(WELCOME_MESSAGE); usage(programName); DISPLAY( "\n"); - DISPLAY( "Advanced arguments :\n"); - DISPLAY( " -V : display Version number and exit\n"); + DISPLAY( "Advanced arguments : \n"); + DISPLAY( " -V : display Version number and exit \n"); DISPLAY( " -v : verbose mode; specify multiple times to increase verbosity\n"); DISPLAY( " -q : suppress warnings; specify twice to suppress errors too\n"); DISPLAY( " -c : force write to standard output, even if it is the console\n"); - DISPLAY( " -l : print information about zstd compressed files.\n"); + DISPLAY( " -l : print information about zstd compressed files \n"); #ifndef ZSTD_NOCOMPRESS DISPLAY( "--ultra : enable levels beyond %i, up to %i (requires more memory)\n", ZSTDCLI_CLEVEL_MAX, ZSTD_maxCLevel()); #ifdef ZSTD_MULTITHREAD @@ -151,11 +152,10 @@ static int usage_advanced(const char* programName) #endif #endif DISPLAY( " -M# : Set a memory usage limit for decompression \n"); - DISPLAY( "--list : list information about a zstd compressed file \n"); DISPLAY( "-- : All arguments after \"--\" are treated as files \n"); #ifndef ZSTD_NODICT DISPLAY( "\n"); - DISPLAY( "Dictionary builder :\n"); + DISPLAY( "Dictionary builder : \n"); DISPLAY( "--train ## : create a dictionary from a training set of files \n"); DISPLAY( "--train-cover[=k=#,d=#,steps=#] : use the cover algorithm with optional args\n"); DISPLAY( "--train-legacy[=s=#] : use the legacy algorithm with selectivity (default: %u)\n", g_defaultSelectivityLevel); @@ -165,12 +165,12 @@ static int usage_advanced(const char* programName) #endif #ifndef ZSTD_NOBENCH DISPLAY( "\n"); - DISPLAY( "Benchmark arguments :\n"); + DISPLAY( "Benchmark arguments : \n"); DISPLAY( " -b# : benchmark file(s), using # compression level (default : 1) \n"); DISPLAY( " -e# : test all compression levels from -bX to # (default: 1)\n"); - DISPLAY( " -i# : minimum evaluation time in seconds (default : 3s)\n"); + DISPLAY( " -i# : minimum evaluation time in seconds (default : 3s) \n"); DISPLAY( " -B# : cut file into independent blocks of size # (default: no block)\n"); - DISPLAY( "--priority=rt : set process priority to real-time\n"); + DISPLAY( "--priority=rt : set process priority to real-time \n"); #endif return 0; } @@ -313,6 +313,35 @@ static unsigned parseCompressionParameters(const char* stringPtr, ZSTD_compressi return 1; } +static void printVersion(void) +{ + DISPLAY(WELCOME_MESSAGE); + /* format support */ + DISPLAYLEVEL(3, "*** supports: zstd"); +#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>0) && (ZSTD_LEGACY_SUPPORT<8) + DISPLAYLEVEL(3, ", zstd legacy v0.%d+", ZSTD_LEGACY_SUPPORT); +#endif +#ifdef ZSTD_GZCOMPRESS + DISPLAYLEVEL(3, ", gzip"); +#endif +#ifdef ZSTD_LZ4COMPRESS + DISPLAYLEVEL(3, ", lz4"); +#endif +#ifdef ZSTD_LZMACOMPRESS + DISPLAYLEVEL(3, ", lzma, xz "); +#endif + DISPLAYLEVEL(3, "\n"); + /* posix support */ +#ifdef _POSIX_C_SOURCE + DISPLAYLEVEL(4, "_POSIX_C_SOURCE defined: %ldL\n", (long) _POSIX_C_SOURCE); +#endif +#ifdef _POSIX_VERSION + DISPLAYLEVEL(4, "_POSIX_VERSION defined: %ldL \n", (long) _POSIX_VERSION); +#endif +#ifdef PLATFORM_POSIX_VERSION + DISPLAYLEVEL(4, "PLATFORM_POSIX_VERSION defined: %ldL\n", (long) PLATFORM_POSIX_VERSION); +#endif +} typedef enum { zom_compress, zom_decompress, zom_test, zom_bench, zom_train, zom_list } zstd_operation_mode; @@ -492,7 +521,7 @@ int main(int argCount, const char* argv[]) switch(argument[0]) { /* Display help */ - case 'V': g_displayOut=stdout; DISPLAY(WELCOME_MESSAGE); CLEAN_RETURN(0); /* Version Only */ + case 'V': g_displayOut=stdout; printVersion(); CLEAN_RETURN(0); /* Version Only */ case 'H': case 'h': g_displayOut=stdout; CLEAN_RETURN(usage_advanced(programName)); @@ -635,24 +664,18 @@ int main(int argCount, const char* argv[]) filenameTable[filenameIdx++] = argument; } - if (lastCommand) { DISPLAY("error : command must be followed by argument \n"); CLEAN_RETURN(1); } /* forgotten argument */ + if (lastCommand) { /* forgotten argument */ + DISPLAY("error : command must be followed by argument \n"); + CLEAN_RETURN(1); + } /* Welcome message (if verbose) */ DISPLAYLEVEL(3, WELCOME_MESSAGE); -#ifdef _POSIX_C_SOURCE - DISPLAYLEVEL(4, "_POSIX_C_SOURCE defined: %ldL\n", (long) _POSIX_C_SOURCE); -#endif -#ifdef _POSIX_VERSION - DISPLAYLEVEL(4, "_POSIX_VERSION defined: %ldL\n", (long) _POSIX_VERSION); -#endif -#ifdef PLATFORM_POSIX_VERSION - DISPLAYLEVEL(4, "PLATFORM_POSIX_VERSION defined: %ldL\n", (long) PLATFORM_POSIX_VERSION); -#endif if (nbThreads == 0) { /* try to guess */ nbThreads = UTIL_countPhysicalCores(); - DISPLAYLEVEL(3, "Note: %d physical core(s) detected\n", nbThreads); + DISPLAYLEVEL(3, "Note: %d physical core(s) detected \n", nbThreads); } g_utilDisplayLevel = g_displayLevel; @@ -679,10 +702,17 @@ int main(int argCount, const char* argv[]) } } #endif + if (operation == zom_list) { +#ifndef ZSTD_NODECOMPRESS int const ret = FIO_listMultipleFiles(filenameIdx, filenameTable, g_displayLevel); CLEAN_RETURN(ret); +#else + DISPLAY("file information is not supported \n"); + CLEAN_RETURN(1); +#endif } + /* Check if benchmark is selected */ if (operation==zom_bench) { #ifndef ZSTD_NOBENCH @@ -692,7 +722,7 @@ int main(int argCount, const char* argv[]) BMK_setNbSeconds(bench_nbSeconds); BMK_benchFiles(filenameTable, filenameIdx, dictFileName, cLevel, cLevelLast, &compressionParams, setRealTimePrio); #endif - (void)bench_nbSeconds; + (void)bench_nbSeconds; (void)blockSize; (void)setRealTimePrio; goto _end; } @@ -719,6 +749,10 @@ int main(int argCount, const char* argv[]) goto _end; } +#ifndef ZSTD_NODECOMPRESS + if (operation==zom_test) { outFileName=nulmark; FIO_setRemoveSrcFile(0); } /* test mode */ +#endif + /* No input filename ==> use stdin and stdout */ filenameIdx += !filenameIdx; /* filenameTable[0] is stdin by default */ if (!strcmp(filenameTable[0], stdinmark) && !outFileName) outFileName = stdoutmark; /* when input is stdin, default output is stdout */ @@ -759,11 +793,11 @@ int main(int argCount, const char* argv[]) else operationResult = FIO_compressMultipleFilenames(filenameTable, filenameIdx, outFileName ? outFileName : suffix, dictFileName, cLevel, &compressionParams); #else + (void)suffix; DISPLAY("Compression not supported\n"); #endif } else { /* decompression or test */ #ifndef ZSTD_NODECOMPRESS - if (operation==zom_test) { outFileName=nulmark; FIO_setRemoveSrcFile(0); } /* test mode */ FIO_setMemLimit(memLimit); if (filenameIdx==1 && outFileName) operationResult = FIO_decompressFilename(outFileName, filenameTable[0], dictFileName); |