pax_global_header00006660000000000000000000000064145632532470014525gustar00rootroot0000000000000052 comment=e8eb87d588072dc27c10bb548f794756aa762087 snappy-tools-1/000077500000000000000000000000001456325324700136775ustar00rootroot00000000000000snappy-tools-1/.builds/000077500000000000000000000000001456325324700152375ustar00rootroot00000000000000snappy-tools-1/.builds/freebsd-latest.yml000066400000000000000000000004621456325324700206700ustar00rootroot00000000000000# SPDX-License-Identifier: 0BSD image: freebsd/latest packages: - gmake - snappy - gettext-runtime - gettext-tools tasks: - build: | LDFLAGS=-L/usr/local/lib LDLIBS=-lintl CPPFLAGS=-I/usr/local/include gmake -C snappy-tools all check - install: | sudo gmake -C snappy-tools install snappy-tools-1/.builds/openbsd-latest.yml000066400000000000000000000004721456325324700207110ustar00rootroot00000000000000# SPDX-License-Identifier: 0BSD image: openbsd/latest packages: - gmake - snappy tasks: - nolibintl: | doas rm /usr/local/include/libintl.h - build: | CPPFLAGS=-I/usr/local/include LDFLAGS=-L/usr/local/lib gmake -C snappy-tools all check - install: | doas gmake -C snappy-tools install snappy-tools-1/.builds/sid+void.yml000066400000000000000000000041031456325324700174740ustar00rootroot00000000000000# SPDX-License-Identifier: 0BSD image: debian/sid secrets: - c58fa0df-47a6-4aa4-bc43-6c138525255d # snappy-tools SSH key packages: - clang - lld - libsnappy-dev - gettext - curl - groff - ghostscript tasks: - build-gcc: | make -C snappy-tools all check make -C snappy-tools clean - build-clang: | export CC=clang CXX=clang++ LDFLAGS=-fuse-ld=lld make -C snappy-tools all check - install: | sudo gmake -C snappy-tools install VERSION="$(git describe --abbrev=0)-git" - manual: | sudo sh -c 'curl https://git.sr.ht/~nabijaczleweli/groff-1.23-unfucking/blob/trunk/mdoc.local >> /etc/groff/mdoc.local' git -C snappy-tools worktree add ../snappy-tools-man man cd snappy-tools-man rm -r [a-z]* find /usr/local/share/man -type f -exec zcat {} + | groff -K utf8 -tpe -mdoc -Tps -dpaper=a4 -P-pa4 | ps2pdf - snappy-tools.pdf cp -pR /usr/local/share/man/* . find -type l -delete find -type f -exec gunzip {} + 2>/dev/null || : git diff --exit-code man* > /dev/null || { git add . git config user.email "nabijaczleweli/autouploader@nabijaczleweli.xyz" git config user.name "наб autouploader" git commit -m "Manual update by job $JOB_ID" || exit 0 git remote set-url origin 'git@git.sr.ht:~nabijaczleweli/snappy-tools' ssh-keyscan git.sr.ht > ~/.ssh/known_hosts git push } - void: | curl https://repo-default.voidlinux.org/live/current/sha256sum.txt | grep -w tar | grep -w x86_64 | grep -m1 musl > sha256sum.txt curl -SL https://repo-default.voidlinux.org/live/current/"$(awk -F'[( )]' '{print $3}' < sha256sum.txt)" | tar -xJ cp /etc/resolv.conf etc printf '%s\n' 'xbps-install -yS' \ 'xbps-install -yu xbps' \ 'xbps-install -y make gcc snappy snappy-devel' \ 'make -C snappy-tools clean' \ 'make -C snappy-tools all check ' \ 'make -C snappy-tools install VERSION=sid.yml SOURCE_DATE_EPOCH=0' | unshare -rR . sh -ex snappy-tools-1/.clang-format000066400000000000000000000020771456325324700162600ustar00rootroot00000000000000--- Language : Cpp BasedOnStyle : LLVM AlignAfterOpenBracket : true AlignEscapedNewlinesLeft : true AlignConsecutiveAssignments : true AllowShortFunctionsOnASingleLine : Inline AlwaysBreakTemplateDeclarations : true ColumnLimit : 160 ConstructorInitializerIndentWidth : 6 IndentCaseLabels : true MaxEmptyLinesToKeep : 2 KeepEmptyLinesAtTheStartOfBlocks : false NamespaceIndentation : All PointerAlignment : Middle SpacesBeforeTrailingComments : 2 IndentWidth : 2 TabWidth : 2 UseTab : ForIndentation SpaceBeforeParens : Never FixNamespaceComments : false ... snappy-tools-1/GNUmakefile000066400000000000000000000040041456325324700157470ustar00rootroot00000000000000# SPDX-License-Identifier: 0BSD CXX ?= c++ LOCALLOC ?= NOLOCREGEN ?= PKG_CONFIG ?= pkg-config VERSION ?= $(shell git describe) DATE_EPOCH = date $(shell date -d @0 > /dev/null 2>&1 && echo "-d @" || echo "-r ") SOURCE_DATE_EPOCH ?= $(shell git log -1 --no-show-signature --format=%at "snappy.1") MANUAL_DATE ?= $(shell $(DATE_EPOCH)$(SOURCE_DATE_EPOCH) +"%B %e, %Y") PREFIX ?= /usr/local CXXFLAGS += $(shell $(PKG_CONFIG) --cflags snappy 2>/dev/null) -pthread -O3 -g -Wall -Wextra -fno-exceptions -fno-rtti -std=c++20 LDLIBS += $(shell $(PKG_CONFIG) --libs snappy 2>/dev/null || echo -lsnappy) CPPFLAGS += -D_FILE_OFFSET_BITS=64 -DTEXTDOMAIN_DIRNAME='"$(if $(LOCALLOC),loc,$(PREFIX)/share/locale)"' ifneq (,$(shell command -v msgfmt)) LOCALES := $(wildcard *.po) endif .PHONY: all check clean install all: snappy $(patsubst %.po,loc/%/LC_MESSAGES/snappy-tools.mo,$(LOCALES)) check: snappy ifneq (,$(shell command -v groff)) ! sed 's/^\.Dd/& $(MANUAL_DATE)/' snappy.1 | groff -K utf8 -te -mdoc 2>&1 > /dev/null | grep . endif ./test clean: rm -rf snappy loc/ loc/snappy-tools.pot: snappy.cpp @mkdir -p $(@D) $(NOLOCREGEN)xgettext --from-code=UTF-8 -c -io- $^ | sed -n '/^#[:.]/,$$p' > $@ $(NOLOCREGEN)$(foreach l,$(LOCALES),msgmerge --backup=off --no-wrap -Uiq $(l) $@ &&) : @>> loc/snappy-tools.pot loc/%/LC_MESSAGES/snappy-tools.mo : %.po loc/snappy-tools.pot @mkdir -p $(@D) msgfmt --statistics --check-format --check-domain -o $@ $< install: all mkdir -p $(DESTDIR)$(PREFIX)/bin $(DESTDIR)$(PREFIX)/share/man/man1 $(DESTDIR)$(PREFIX)/share/locale cp -P snappy unsnappy $(DESTDIR)$(PREFIX)/bin awk '/^.Dd/ { $$2 = "$(MANUAL_DATE)" } /^.Dt/ { print ".ds doc-volume-operating-system" } /^.Os/ { $$2 = "snappy-tools $(VERSION)" } { gsub(/ \^/, " \\(ha"); gsub(/ ~/, " \\(ti"); print }' < snappy.1 | gzip -9 > $(DESTDIR)$(PREFIX)/share/man/man1/snappy.1.gz ln -sf snappy.1.gz $(DESTDIR)$(PREFIX)/share/man/man1/unsnappy.1.gz ifneq (,$(LOCALES)) cp -r $(patsubst %.po,loc/%,$(LOCALES)) $(DESTDIR)$(PREFIX)/share/locale endif snappy-tools-1/LICENSES/000077500000000000000000000000001456325324700151045ustar00rootroot00000000000000snappy-tools-1/LICENSES/0BSD.txt000066400000000000000000000011371456325324700163370ustar00rootroot00000000000000Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. snappy-tools-1/README000066400000000000000000000274531456325324700145720ustar00rootroot00000000000000snappy-tools https://builds.sr.ht/~nabijaczleweli/snappy-tools https://todo.sr.ht/~nabijaczleweli/snappy-tools (report at ) https://lists.sr.ht/~nabijaczleweli/snappy-tools https://man.sr.ht/~nabijaczleweli/snappy-tools I saw some "snappy framed data"-compressed files in my Firefox profile, and there didn't seem to be a decompressor for them in Debian. Upstream homepage at https://google.github.io/snappy/; you need libsnappy-dev to build. snappy(1): Snappy compression and decompression with and without framing usage: snappy [-f] data > snappy.sn|.sz snappy [-f] < data > snappy.sn|.sz snappy -d [-i] snappy.sn|.sz snappy -d [-i] < snappy.sn|.sz usage: unsnappy [-i] snappy.sn|.sz unsnappy [-i] < snappy.sn|.sz Manual available online at https://srhtcdn.githack.com/~nabijaczleweli/snappy-tools/blob/man/snappy-tools.pdf Naturally, the snappy framing format requires CRC32Cing the data. There is a hardware-accelerated implementation for arm64 SSE4.2-capable i386/x32/amd64, and CRCC-capable loong64 hosts: soft crc32q CRC32C E5645 357 MiB/s 6598 MiB/s 5800X3D 527 MiB/s 11085 MiB/s MT8173 246 MiB/s 5016 MiB/s (Cortex-A72) Note that upstream's spiel is 250M/s compression and 500M/s decompression (on "an i7"), and ~.55 of the ratio of gzip -1 for HTML: $ curl -SL https://github.com/google/snappy/ > data $ snappy data > /dev/null data: 286555 -> 81458 (28.43%) $ snappy -f data > /dev/null data: 286555 -> 81520 (28.45%) $ gzip -c1 data | wc -c 58254 (20%) $ lz4 -vc1 data > /dev/null *** LZ4 command line interface 64-bits v1.9.4, by Yann Collet *** Compressed 286555 bytes into 73853 bytes ==> 25.77% $ zstd -vc1 data > /dev/null *** Zstandard CLI (64-bit) v1.5.4, by Yann Collet *** data : 17.47% ( 280 KiB => 48.9 KiB, /*stdout*\) compare with the Silesia compression corpus' HTML-formatted "webster" file (https://sun.aei.polsl.pl//~sdeor/index.php?page=silesia): $ curl -SL https://sun.aei.polsl.pl//~sdeor/corpus/webster.bz2 | bzcat > webster $ snappy webster > /dev/null webster: 41458703 -> 20211213 (48.75%) $ snappy -f webster > /dev/null webster: 41458703 -> 20218182 (48.77%) $ gzip -c1 webster | wc -c 14977104 (36.13%) $ lz4 -vc1 data > /dev/null *** LZ4 command line interface 64-bits v1.9.4, by Yann Collet *** Compressed 41458703 bytes into 20149249 bytes ==> 48.60% $ zstd -vc1 data > /dev/null *** Zstandard CLI (64-bit) v1.5.4, by Yann Collet *** webster : 32.97% ( 39.5 MiB => 13.0 MiB, /*stdout*\) Speed testing on tmpfs on bookworm/E5645/DDR3-1600, which an i7 is very much not: $ while :; do cat data || break; done | head -c 100M > 100M $ hyperfine -N 'snappy 100M' 'snappy -f 100M' 'gzip -c1 100M' 'lz4 -c1 100M' 'zstd -c1 100M' snappy 100M (mean ± σ): 272.9 ms ± 2.5 ms [User: 248.2 ms, System: 24.4 ms] snappy -f 100M (mean ± σ): 298.8 ms ± 5.6 ms [User: 275.7 ms, System: 22.8 ms] gzip -c1 100M (mean ± σ): 1733 ms ± 10 ms [User: 1.709 s, System: 0.024 s] lz4 -c1 100M (mean ± σ): 329.9 ms ± 8.1 ms [User: 298.1 ms, System: 31.6 ms] zstd -c1 100M (mean ± σ): 128.1 ms ± 10.0 ms [User: 140.2 ms, System: 58.0 ms] Summary 'zstd -c1 100M' ran 780.640 MiB/s 2.13 ± 0.17 times faster than 'snappy 100M' 366.434 MiB/s 2.33 ± 0.19 times faster than 'snappy -f 100M' 334.672 MiB/s 2.58 ± 0.21 times faster than 'lz4 -c1 100M' 303.122 MiB/s 13.53 ± 1.06 times faster than 'gzip -c1 100M' 57.703 MiB/s snappy -d 100M.sn (mean ± σ): 206.8 ms ± 3.4 ms [User: 132.9 ms, System: 73.6 ms] snappy -d 100M.sz (mean ± σ): 153.5 ms ± 4.9 ms [User: 141.6 ms, System: 11.6 ms] gzip -dc 100M.gz (mean ± σ): 709.0 ms ± 5.6 ms [User: 698.3 ms, System: 10.4 ms] lz4 -dc 100M.lz4 (mean ± σ): 133.8 ms ± 6.1 ms [User: 118.5 ms, System: 15.1 ms] zstd -dc 100M.zst (mean ± σ): 61.3 ms ± 5.5 ms [User: 59.8 ms, System: 10.2 ms] Summary 'zstd -dc 100M.zst' ran 1631.321 MiB/s 2.18 ± 0.22 times faster than 'lz4 -dc 100M.lz4' 747.384 MiB/s 2.50 ± 0.24 times faster than 'snappy -d 100M.sz' 651.465 MiB/s 3.37 ± 0.31 times faster than 'snappy -d 100M.sn' 483.558 MiB/s 11.57 ± 1.05 times faster than 'gzip -dc 100M.gz' 141.043 MiB/s snappy webster (mean ± σ): 199.5 ms ± 5.3 ms [User: 189.7 ms, System: 9.6 ms] snappy -f webster (mean ± σ): 205.8 ms ± 4.7 ms [User: 191.6 ms, System: 13.9 ms] gzip -c1 webster (mean ± σ): 1032 ms ± 7 ms [User: 1.019 s, System: 0.012 s] lz4 -c1 webster (mean ± σ): 216.9 ms ± 5.7 ms [User: 202.0 ms, System: 14.6 ms] zstd -c1 webster (mean ± σ): 367.4 ms ± 5.2 ms [User: 368.9 ms, System: 35.3 ms] Summary 'snappy webster' ran 198.185 MiB/s 1.03 ± 0.04 times faster than 'snappy -f webster' 192.119 MiB/s 1.09 ± 0.04 times faster than 'lz4 -c1 webster' 182.287 MiB/s 1.84 ± 0.05 times faster than 'zstd -c1 webster' 107.615 MiB/s 5.17 ± 0.14 times faster than 'gzip -c1 webster' 38.312 MiB/s snappy -d webster.sn (mean ± σ): 134.0 ms ± 3.9 ms [User: 100.9 ms, System: 32.9 ms] snappy -d webster.sz (mean ± σ): 109.2 ms ± 2.3 ms [User: 100.1 ms, System: 8.9 ms] gzip -dc webster.gz (mean ± σ): 394.8 ms ± 5.0 ms [User: 389.3 ms, System: 5.2 ms] lz4 -dc webster.lz4 (mean ± σ): 67.8 ms ± 2.1 ms [User: 57.7 ms, System: 9.9 ms] zstd -dc webster.zst (mean ± σ): 110.1 ms ± 3.1 ms [User: 109.2 ms, System: 11.3 ms] Summary 'lz4 -dc webster.lz4' ran 583.157 MiB/s 1.61 ± 0.06 times faster than 'snappy -d webster.sz' 362.070 MiB/s 1.62 ± 0.07 times faster than 'zstd -dc webster.zst' 359.110 MiB/s 1.98 ± 0.08 times faster than 'snappy -d webster.sn' 295.060 MiB/s 5.82 ± 0.19 times faster than 'gzip -dc webster.gz' 100.147 MiB/s Speed testing on tmpfs on sid@2024-02-14/5800X3D/DDR4-3600, which is several i7s: snappy 100M (mean ± σ): 100.1 ms ± 1.6 ms [User: 88.7 ms, System: 11.3 ms] snappy -f 100M (mean ± σ): 108.8 ms ± 0.6 ms [User: 98.7 ms, System: 10.1 ms] gzip -c1 100M (mean ± σ): 710.5 ms ± 8.4 ms [User: 696.3 ms, System: 14.0 ms] lz4 -c1 100M (mean ± σ): 148.2 ms ± 1.8 ms [User: 111.8 ms, System: 36.3 ms] zstd -c1 100M (mean ± σ): 40.2 ms ± 1.2 ms [User: 32.8 ms, System: 40.6 ms] Summary zstd -c1 100M ran 2487.562 MiB/s 2.49 ± 0.08 times faster than snappy 100M 999.000 MiB/s 2.71 ± 0.08 times faster than snappy -f 100M 919.117 MiB/s 3.69 ± 0.12 times faster than lz4 -c1 100M 674.763 MiB/s 17.69 ± 0.57 times faster than gzip -c1 100M 140.745 MiB/s snappy -d 100M.sn (mean ± σ): 111.1 ms ± 1.2 ms [User: 67.3 ms, System: 43.6 ms] snappy -d 100M.sz (mean ± σ): 81.9 ms ± 1.3 ms [User: 76.1 ms, System: 5.7 ms] gzip -dc 100M.gz (mean ± σ): 351.8 ms ± 2.6 ms [User: 348.1 ms, System: 3.6 ms] lz4 -dc 100M.lz4 (mean ± σ): 45.7 ms ± 0.6 ms [User: 41.3 ms, System: 4.2 ms] zstd -dc 100M.zst (mean ± σ): 16.7 ms ± 0.2 ms [User: 16.2 ms, System: 3.5 ms] Summary zstd -dc 100M.zst ran 5988.023 MiB/s 2.73 ± 0.05 times faster than lz4 -dc 100M.lz4 2188.183 MiB/s 4.89 ± 0.10 times faster than snappy -d 100M.sz 1221.001 MiB/s 6.63 ± 0.11 times faster than snappy -d 100M.sn 900.090 MiB/s 21.00 ± 0.30 times faster than gzip -dc 100M.gz 284.252 MiB/s snappy webster (mean ± σ): 75.7 ms ± 1.1 ms [User: 72.2 ms, System: 3.4 ms] snappy -f webster (mean ± σ): 79.4 ms ± 1.1 ms [User: 74.2 ms, System: 5.1 ms] gzip -c1 webster (mean ± σ): 408.4 ms ± 4.7 ms [User: 405.9 ms, System: 2.4 ms] lz4 -c1 webster (mean ± σ): 93.8 ms ± 2.1 ms [User: 78.3 ms, System: 15.4 ms] zstd -c1 webster (mean ± σ): 118.7 ms ± 2.3 ms [User: 119.7 ms, System: 19.7 ms] Summary snappy webster ran 522.299 MiB/s 1.05 ± 0.02 times faster than snappy -f webster 497.960 MiB/s 1.24 ± 0.03 times faster than lz4 -c1 webster 421.514 MiB/s 1.57 ± 0.04 times faster than zstd -c1 webster 333.092 MiB/s 5.39 ± 0.10 times faster than gzip -c1 webster 96.812 MiB/s snappy -d webster.sn (mean ± σ): 67.8 ms ± 1.1 ms [User: 50.1 ms, System: 17.7 ms] snappy -d webster.sz (mean ± σ): 57.2 ms ± 1.0 ms [User: 54.1 ms, System: 3.0 ms] gzip -dc webster.gz (mean ± σ): 180.9 ms ± 1.7 ms [User: 178.1 ms, System: 2.7 ms] lz4 -dc webster.lz4 (mean ± σ): 25.3 ms ± 0.5 ms [User: 21.7 ms, System: 3.5 ms] zstd -dc webster.zst (mean ± σ): 34.2 ms ± 0.3 ms [User: 32.9 ms, System: 4.1 ms] Summary lz4 -dc webster.lz4 ran 1562.770 MiB/s 1.35 ± 0.03 times faster than zstd -dc webster.zst 1156.084 MiB/s 2.26 ± 0.06 times faster than snappy -d webster.sz 691.225 MiB/s 2.68 ± 0.07 times faster than snappy -d webster.sn 583.157 MiB/s 7.16 ± 0.16 times faster than gzip -dc webster.gz 218.563 MiB/s Speed testing on tmpfs on the Cortex-A72 half of sid@2024-01-07/MT8173/LPDDR3-1866: zstd -c1 100M ran 513.083 MiB/s 194.9 ms 1.92 ± 0.11 times faster than snappy 100M 267.809 MiB/s 373.4 ms 1.96 ± 0.14 times faster than snappy -f 100M 261.985 MiB/s 381.7 ms 2.50 ± 0.13 times faster than lz4 -c1 100M 205.212 MiB/s 487.3 ms 11.51 ± 0.25 times faster than gzip -c1 100M 44.563 MiB/s 2244 ms zstd -dc 100M.zst ran 938.967 MiB/s 106.5 ms 1.88 ± 0.25 times faster than lz4 -dc 100M.lz4 499.001 MiB/s 200.4 ms 2.92 ± 0.41 times faster than snappy -d 100M.sz 322.061 MiB/s 310.5 ms 3.08 ± 0.34 times faster than snappy -d 100M.sn 304.692 MiB/s 328.2 ms 8.84 ± 0.54 times faster than gzip -dc 100M.gz 106.157 MiB/s 942.0 ms snappy webster ran 146.545 MiB/s 269.8 ms 1.03 ± 0.13 times faster than snappy -f webster 142.891 MiB/s 276.7 ms 1.25 ± 0.14 times faster than lz4 -c1 webster 117.672 MiB/s 336.0 ms 1.77 ± 0.17 times faster than zstd -c1 webster 82.750 MiB/s 477.8 ms 5.06 ± 0.49 times faster than gzip -c1 webster 28.965 MiB/s 1365 ms lz4 -dc webster.lz4 ran 325.416 MiB/s 121.5 ms 1.44 ± 0.14 times faster than zstd -dc webster.zst 226.579 MiB/s 174.5 ms 1.90 ± 0.24 times faster than snappy -d webster.sz 171.383 MiB/s 230.7 ms 2.01 ± 0.26 times faster than snappy -d webster.sn 161.842 MiB/s 244.3 ms 4.59 ± 0.45 times faster than gzip -dc webster.gz 70.945 MiB/s 557.3 ms Unabridged measurements at https://man.sr.ht/~nabijaczleweli/snappy-tools/measurements/2024-02-13-1.md Release tarballs are signed with nabijaczleweli@nabijaczleweli.xyz (pull with WKD, but 7D69 474E 8402 8C5C C0C4 4163 BCFD 0B01 8D26 58F1). аnd stored in git notes, as-if via the example program provided at https://man.sr.ht/git.sr.ht/#signing-tagsx27-tarballs and are thus available on the refs listing/tag page as .tar.gz.asc. snappy-tools-1/fr.po000066400000000000000000000046111456325324700146500ustar00rootroot00000000000000# SPDX-License-Identifier: 0BSD msgid "" msgstr "Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: snappy.cpp:275 snappy.cpp:401 snappy.cpp:520 msgid "write error" msgstr "erreur d'écriture" #. not understood by the decompressor #: snappy.cpp:299 #, c-format msgid "%s: compressed block of length %zu: invalid data" msgstr "%s : bloc compressé de longueur %zu : données invalides" #: snappy.cpp:308 #, c-format msgid "%s: compressed block of length %zu: expecting %zu bytes, got %zu" msgstr "%s : bloc compressé de longueur %zu : attendu %zu bytes, lu %zu" #: snappy.cpp:339 #, c-format msgid "%s: stream identifier chunk: length %zu != %zu" msgstr "%s : tronçon d'identifiant de flux : %zu ≠ %zu" #: snappy.cpp:341 #, c-format msgid "%s: stream identifier chunk: content %.*s != %s" msgstr "%s : tronçon d'identifiant de flux : contenu %.*s ≠ %s" #. 4.5. Reserved unskippable chunks (chunk types 0x02-0x7f) #: snappy.cpp:355 #, c-format msgid "%s: chunk of length %zu: unknown type 0x%02X" msgstr "%s : tronçon de longueur %zu : type inconnu 0x%02X" #: snappy.cpp:365 #, c-format msgid "%s: chunk of length %zu: checksum 0x%08X != 0x%08X" msgstr "%s : tronçon de longueur %zu : somme de contrôle 0x%08X ≠ 0x%08X" #: snappy.cpp:436 #, c-format msgid "usage: %1$s [-i] snappy.sn|.sz\n" " %1$s [-i] < snappy.sn|.sz\n" msgstr "usage : %1$s [-i] snappy.sn|.sz\n" " %1$s [-i] < snappy.sn|.sz\n" #: snappy.cpp:438 #, c-format msgid "usage: %1$s [-f] data > snappy.sn|.sz\n" " %1$s [-f] < data > snappy.sn|.sz\n" " %1$s -d [-i] snappy.sn|.sz\n" " %1$s -d [-i] < snappy.sn|.sz\n" msgstr "usage : %1$s [-f] données > snappy.sn|.sz\n" " %1$s [-f] < données > snappy.sn|.sz\n" " %1$s -d [-i] snappy.sn|.sz\n" " %1$s -d [-i] < snappy.sn|.sz\n" #. filename, byte count read, byte count written, ratio #: snappy.cpp:586 #, c-format msgid "%s: %llu -> %llu (%.2f%%)\n" msgstr "%s : %llu → %llu (≈ %.2f%%)\n" #: snappy.cpp:589 #, c-format msgid "%s: %s: sized %lluB >= 4GiB w/o -f: output stream may be broken!\n" msgstr "%s : %s : taille de fichier %llu B ≥ 4 GiB sans -f : le flux de sortie peut être corrompu !\n" snappy-tools-1/pl.po000066400000000000000000000046221456325324700146560ustar00rootroot00000000000000# SPDX-License-Identifier: 0BSD msgid "" msgstr "Language: pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: snappy.cpp:275 snappy.cpp:401 snappy.cpp:520 msgid "write error" msgstr "błąd zapisu" #. not understood by the decompressor #: snappy.cpp:299 #, c-format msgid "%s: compressed block of length %zu: invalid data" msgstr "%s: skompresowany blok o długości %zu: niepoprawny format danych" #: snappy.cpp:308 #, c-format msgid "%s: compressed block of length %zu: expecting %zu bytes, got %zu" msgstr "%s: skompresowany blok o długości %zu: miało być %zu bajtów, wyszło %zu" #: snappy.cpp:339 #, c-format msgid "%s: stream identifier chunk: length %zu != %zu" msgstr "%s: kawałek \"identyfikator strumienia\": długość %zu ≠ %zu" #: snappy.cpp:341 #, c-format msgid "%s: stream identifier chunk: content %.*s != %s" msgstr "%s: kawałek \"identyfikator strumienia\": zawartość %.*s ≠ %s" #. 4.5. Reserved unskippable chunks (chunk types 0x02-0x7f) #: snappy.cpp:355 #, c-format msgid "%s: chunk of length %zu: unknown type 0x%02X" msgstr "%s: kawałek o długości %zu: nieznany typ 0x%02X" #: snappy.cpp:365 #, c-format msgid "%s: chunk of length %zu: checksum 0x%08X != 0x%08X" msgstr "%s: kawałek o długości %zu: suma kontrolna 0x%08X ≠ 0x%08X" #: snappy.cpp:436 #, c-format msgid "usage: %1$s [-i] snappy.sn|.sz\n" " %1$s [-i] < snappy.sn|.sz\n" msgstr "użycie: %1$s [-i] snappy.sn|.sz\n" " %1$s [-i] < snappy.sn|.sz\n" #: snappy.cpp:438 #, c-format msgid "usage: %1$s [-f] data > snappy.sn|.sz\n" " %1$s [-f] < data > snappy.sn|.sz\n" " %1$s -d [-i] snappy.sn|.sz\n" " %1$s -d [-i] < snappy.sn|.sz\n" msgstr "użycie: %1$s [-f] dane > snappy.sn|.sz\n" " %1$s [-f] < dane > snappy.sn|.sz\n" " %1$s -d [-i] snappy.sn|.sz\n" " %1$s -d [-i] < snappy.sn|.sz\n" #. filename, byte count read, byte count written, ratio #: snappy.cpp:586 #, c-format msgid "%s: %llu -> %llu (%.2f%%)\n" msgstr "%s: %llu → %llu (≈ %.2f%%)\n" #: snappy.cpp:589 #, c-format msgid "%s: %s: sized %lluB >= 4GiB w/o -f: output stream may be broken!\n" msgstr "%s: %s: ma rozmiar %lluB ≥ 4GiB i nie podano -f: wynik może być niepoprawny!\n" snappy-tools-1/snappy.1000066400000000000000000000061271456325324700153010ustar00rootroot00000000000000.\" SPDX-License-Identifier: 0BSD .\" .Dd .Dt SNAPPY 1 .Os . .Sh NAME .Nm snappy , unsnappy .Nd Snappy compression and decompression with and without framing .Sh SYNOPSIS .Nm .Op Fl f .Op Ar file .Li > .Pa snappy.sn Ns \&| Ns Pa .sz .Pp .Nm .Fl d .Op Fl i .Op Ar file .Nm unsnappy .Op Fl i .Op Ar file . .Sh DESCRIPTION Without .Fl d , compresses .Ar file .Pq standard input stream if Qo Sy - Qc , the default with Snappy to the standard output stream, then assesses the compression ratio achieved to the standard error stream. .br With .Fl f , the Snappy framing format is produced. .Pp When run as .Nm unsnappy , or with .Fl d , decompresses .Ar file .Pq likewise from Snappy, or the Snappy framing format (detected automatically), to the standard output stream. .br With .Fl i , decompression and framing errors are ignored and processing continues. .Pp As a format limitation, if .Ar file isn't seekable when producing or decompressing unframed Snappy streams, it will be read into memory in its entirety. . .Sh EXIT STATUS .Bl -tag -compact -width ".Sy 1" .It Sy 1 If a decompression error (invalid or truncated Snappy block) or a framing error (Stream identifier .Pq Sy 0xFF frame invalid, unknown reserved unskippable chunk .Pq Bq Sy 0x02 , 0x7F frame encountered, checksum mismatch). . .It Sy 2 On an I/O error. . .It Sy 3 When compressing without .Fl f and .Ar file is larger than 4GiB. (Output unaffected, but see .Sx BUGS . ) .El . .Sh DIAGNOSTICS After compressing, .Dl "data: 2048576 -> 1099105 (53.65%)" means that the .Ar file .Pa data was .Li 2048576 bytes, which were compressed down to .Li 1099105 bytes, and the output is thus .Li 53.65% the size. . .Sh SEE ALSO .Lk https://google.github.io/snappy/ "The Snappy homepage" . .Sh CONFORMING TO The framed format, with .Tn MIME type .Ql application/x-snappy-framed , version 2013-10-25: .Lk https://github.com/\:google/\:snappy/\:blob/\:main/\:framing_format.txt "Snappy framing format description" . .Pp The unframed format, as described in .Lk https://github.com/\:google/\:snappy/\:blob/\:main/\:format_description.txt "Snappy compressed format description" , as provided by the upstream .if !ddoc-str-Lb-libsnappy .ds doc-str-Lb-libsnappy Fast Compressor/Decompressor Library (libsnappy, -lsnappy) .Lb libsnappy . . .Sh BUGS The largest representable unframed stream is of size 4GiB\-1B (=\~4\(pc1024\(pc1024\(pc1024B\-1B =\~4294967295B). Above this size the length stored in the header becomes mangled, so the stream may be semantically correct but will produce an incorrect (short) output when decompressing. .Nm warns about this and exits .Sy 3 . .Pp On 32-bit systems it is impossible to produce unframed streams from files larger than 4GiB\-1B at all due to an API limitation .Pq Sx EXIT STATUS Sy 2 . On 32-bit systems the output size and compression ratio will be misrepresented if compression produces an unframed output larger than 4GiB\-1B. It is also impossible to decompress such files there. .Pp .\" https://docs.rs/snappy_framed/0.1.0/snappy_framed/index.html#a-note-about-checksums Supposedly, compressors which produce checksums with inverted byte order exist in the wild. snappy-tools-1/snappy.cpp000066400000000000000000000554231456325324700157260ustar00rootroot00000000000000// SPDX-License-Identifier: 0BSD #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if __has_include() #include #else #define gettext(s) (s) #define ngettext(s, p, n) (n == 1 ? s : p) #endif using namespace std::literals; #if __i386__ || __x86_64__ // using function multiversioning (or manual cpuid check) #include #if(__linux__ && !__GLIBC__) || __OpenBSD__ // cpuid #include #define CRC32C_GENERIC_ATTR #define CRC32C_GENERIC_NAME crc32c_generic #define PARALLEL_COMPRESSION_CRC32C parallel_compression_crc32c_generic #else // multiversioning #define MULTIVER 1 #define CRC32C_GENERIC_ATTR [[gnu::target("default")]] #define CRC32C_GENERIC_NAME crc32c #define PARALLEL_COMPRESSION_CRC32C parallel_compression_crc32c #endif #elif __aarch64__ // accelerated by default (CRC nominally optional on v8, required on v8.1) #include #define CRC32C_GENERIC_ATTR [[maybe_unused]] #define CRC32C_GENERIC_NAME crc32c_generic #define PARALLEL_COMPRESSION_CRC32C parallel_compression_crc32c_generic #elif __loongarch64 // manual cpucfg check in static init #include #define CRC32C_GENERIC_ATTR #define CRC32C_GENERIC_NAME crc32c_generic #define PARALLEL_COMPRESSION_CRC32C parallel_compression_crc32c // TODO: measure on hardware! defaults to true, which wins in QEMU #else #define CRC32C_GENERIC_ATTR #define CRC32C_GENERIC_NAME crc32c #define PARALLEL_COMPRESSION_CRC32C parallel_compression_crc32c #endif namespace { CRC32C_GENERIC_ATTR std::uint32_t CRC32C_GENERIC_NAME(std::uint32_t cur, const void * data, std::size_t data_len) { static const constexpr std::uint32_t crc_lut[] = { 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB, 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B, 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24, 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B, 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384, 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54, 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B, 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A, 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35, 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5, 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA, 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45, 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A, 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A, 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595, 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48, 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957, 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687, 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198, 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927, 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38, 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8, 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7, 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096, 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789, 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859, 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46, 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9, 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6, 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36, 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829, 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C, 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93, 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043, 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C, 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3, 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC, 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C, 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033, 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652, 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D, 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D, 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982, 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D, 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622, 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2, 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED, 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530, 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F, 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF, 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0, 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F, 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540, 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90, 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F, 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE, 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1, 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321, 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E, 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81, 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E, 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E, 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351}; auto bytes = reinterpret_cast(data), end = bytes + data_len; for(; bytes != end; ++bytes) cur = (cur >> 8) ^ crc_lut[(cur & 0xFF) ^ *bytes]; return cur; } CRC32C_GENERIC_ATTR bool PARALLEL_COMPRESSION_CRC32C() { return true; } #if __i386__ || __x86_64__ #if MULTIVER #define CRC32Q(sym) sym #else #define CRC32Q(sym) sym##_sse42 #endif [[gnu::target("sse4.2")]] std::uint32_t CRC32Q(crc32c)(std::uint32_t cur_r, const void * data, std::size_t data_len) { #if __x86_64__ // this isn't a simple std::size_t+#if _LP64 because x32 is amd64 ILP32 using sse42_t = std::uint64_t; #define _mm_crc32_big _mm_crc32_u64 #else using sse42_t = std::uint32_t; #define _mm_crc32_big _mm_crc32_u32 #endif sse42_t cur = cur_r; auto bulk_iter = reinterpret_cast(data); for(auto bulk = data_len / sizeof(sse42_t); bulk; --bulk, ++bulk_iter) cur = _mm_crc32_big(cur, *bulk_iter); auto single_iter = reinterpret_cast(bulk_iter); for(auto single = data_len % sizeof(sse42_t); single; --single, ++single_iter) cur = _mm_crc32_u8(cur, *single_iter); return cur; } [[gnu::target("sse4.2")]] bool CRC32Q(parallel_compression_crc32c)() { return false; } #if !MULTIVER const bool have_crc32q = ([] { std::uint32_t r[4]; return __get_cpuid_count(1, 0, &r[0], &r[1], &r[2], &r[3]) && ((r[2] & (1 << 20)) == (1 << 20)); }()); const auto crc32c = have_crc32q ? CRC32Q(crc32c) : CRC32C_GENERIC_NAME; const auto parallel_compression_crc32c = have_crc32q ? CRC32Q(parallel_compression_crc32c) : PARALLEL_COMPRESSION_CRC32C; #endif #elif __aarch64__ [[gnu::target("+crc")]] std::uint32_t crc32c(std::uint32_t cur, const void * data, std::size_t data_len) { auto bulk_iter = reinterpret_cast(data); for(auto bulk = data_len / sizeof(std::uint64_t); bulk; --bulk, ++bulk_iter) cur = __crc32cd(cur, *bulk_iter); auto single_iter = reinterpret_cast(bulk_iter); for(auto single = data_len % sizeof(std::uint64_t); single; --single, ++single_iter) cur = __crc32cb(cur, *single_iter); return cur; } bool parallel_compression_crc32c() { return false; } #elif __loongarch64 std::uint32_t crc32c_crcc(std::uint32_t cur_r, const void * data, std::size_t data_len) { int cur; std::memcpy(&cur, &cur_r, sizeof(std::uint32_t)); auto bulk_iter = reinterpret_cast(data); for(auto bulk = data_len / sizeof(long int); bulk; --bulk, ++bulk_iter) cur = __crcc_w_d_w(*bulk_iter, cur); auto single_iter = reinterpret_cast(bulk_iter); for(auto single = data_len % sizeof(long int); single; --single, ++single_iter) cur = __crcc_w_b_w(*single_iter, cur); std::memcpy(&cur_r, &cur, sizeof(std::uint32_t)); return cur_r; } // bool parallel_compression_crc32c() { // // TODO: measure on hardware! defaults to true, which wins in QEMU // } // As of 2024-01-14, the official upstream ISA manual (https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html#_cpucfg) says: // Table 3. The configuration information accessible by the CPUCFG instruction // Word number Bit number Annotation Implication // 0x1 25 IOCSR_BRD 1 indicates that the string of processor product information is recorded at address 0 of the IOCSR access space // // That is, information such as “Loongson3A5000 @2.5GHz” // // This is corroborated by the manuals for the 3A5000/3B5000, 3C5000, and 3D5000 // https://github.com/loongson-community/docs/blob/master/3A5000/Loongson3A5000_3B5000%20user%20book_V1.3.pdf // https://github.com/loongson-community/docs/blob/master/3C5000/龙芯3C5000寄存器及使用手册V1.0.pdf // https://github.com/loongson-community/docs/blob/master/3D5000/2023061508513851030.龙芯3D5000处理器寄存器使用手册_V1.0.pdf // whereas the 3A4000 manual allocates cpucfg completely differently // https://github.com/loongson-community/docs/blob/master/3A4000/3A4000_user_v1.5_20191220.pdf // // The 3A6000's allocation scheme agrees with the live doc and the 5000s except bit 25 is // CRC32 为 1 表示支持 CRC32 加速指令。 1’b1 // https://github.com/loongson-community/docs/blob/master/3A6000/Loongson3A6000%20user%20book_V1.1.pdf // // Linux checks bit 25 for CRC/CRCC presence since // https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=df830336045db1246d3245d3737fee9939c5f731 // saying // LoongArch: Fix probing of the CRC32 feature // // Not all LoongArch processors support CRC32 instructions. This feature // is indicated by CPUCFG1.CRC32 (Bit25) but it is wrongly defined in the // previous versions of the ISA manual (and so does in loongarch.h). The // CRC32 feature is set unconditionally now, so fix it. #define LOONG64_CPUCFG1_CRC32 (1 << 25) static const auto crc32c = __cpucfg(1) & LOONG64_CPUCFG1_CRC32 ? crc32c_crcc : crc32c_generic; #endif std::uint32_t crc32c_finish(std::uint32_t cur) { cur = ~cur; // https://github.com/google/snappy/blob/f82bff66afe0de4c9ae22f8c4ef84e3c2233e799/framing_format.txt#L53-L55 cur = ((cur >> 15) | (cur << 17)) + 0xA282EAD8; return cur; } static union { char buf[0xFFFFFF]; std::uint32_t bufsum; }; // A Source is an interface that yields a sequence of bytes struct fd_source : snappy::Source { int fd; const char * filename; off_t size, off; fd_source(int fd, const char * filename) : fd(fd), filename(filename) { if((this->off = (filename == "-"sv ? lseek(this->fd, 0, SEEK_CUR) : 0)) == -1) return; if((this->size = lseek(this->fd, 0, SEEK_END)) == -1) this->off = -1; } // Return the number of bytes left to read from the source virtual size_t Available() const { return this->size - this->off; } // Peek at the next flat region of the source. Does not reposition // the source. The returned region is empty iff Available()==0. // // Returns a pointer to the beginning of the region and store its // length in *len. // // The returned region is valid until the next call to Skip() or // until this object is destroyed, whichever occurs first. // // The returned region may be larger than Available() (for example // if this ByteSource is a view on a substring of a larger source). // The caller is responsible for ensuring that it only reads the // Available() bytes. virtual const char * Peek(size_t * len) { static_assert(snappy::kBlockSize <= sizeof(buf)); ssize_t rd; while((rd = pread(this->fd, buf, std::min(static_cast(snappy::kBlockSize), this->size), this->off)) == -1 && errno == EINTR) ; if(rd == -1) err(2, "%s", this->filename); if(rd == 0) this->off = this->size; *len = rd; return buf; } // Skip the next n bytes. Invalidates any buffer returned by // a previous call to Peek(). // REQUIRES: Available() >= n virtual void Skip(size_t n) { this->off += n; } }; struct FILE_sink : snappy::Sink { FILE * f; FILE_sink(FILE * f) : f(f) {} // Append "bytes[0,n-1]" to this. virtual void Append(const char * bytes, size_t n) { if(std::fwrite(bytes, 1, n, this->f) != n) err(2, gettext("write error")); } }; struct FILE_crc32_sink : FILE_sink { std::uint32_t sum = ~0; using FILE_sink::FILE_sink; // Append "bytes[0,n-1]" to this. virtual void Append(const char * bytes, size_t n) { FILE_sink::Append(bytes, n); this->sum = crc32c(this->sum, bytes, n); } }; bool uncompress_unframed(const void * data, std::size_t data_len, snappy::Sink * sink, auto filename, bool ignore_errors) { std::uint32_t len = -1; bool err{}; { snappy::ByteArraySource src{reinterpret_cast(data), data_len}; if(!snappy::GetUncompressedLength(&src, &len)) { // not understood by the decompressor warnx(gettext("%s: compressed block of length %zu: invalid data"), filename, data_len), err = true; if(!ignore_errors) return err; } } { snappy::ByteArraySource src{reinterpret_cast(data), data_len}; auto un = snappy::UncompressAsMuchAsPossible(&src, sink); if(un != len) warnx(gettext("%s: compressed block of length %zu: expecting %zu bytes, got %zu"), filename, data_len, static_cast(len), un), err = true; } return err; } // The stream ends when the file ends -- there is no explicit end-of-file marker. int uncompress_framed(FILE * f, const char * filename, bool ignore_errors) { bool err{}; for(;;) { auto tp = getc(f); if(tp == EOF) { checkerr: if(std::ferror(f)) ::err(2, "%s", filename); else return err; } std::uint32_t chunk_len{}; for(int i = 0; i < 3; ++i) { auto l = getc(f); if(l == EOF) goto checkerr; chunk_len |= l << (i * 8); } if(std::fread(buf, 1, chunk_len, f) != chunk_len) goto checkerr; FILE_crc32_sink sink{stdout}; switch(tp) { case 0xFF: // 4.1. Stream identifier (chunk type 0xff) if(chunk_len != std::strlen("sNaPpY")) warnx(gettext("%s: stream identifier chunk: length %zu != %zu"), filename, static_cast(chunk_len), std::strlen("sNaPpY")), err = true; if(std::memcmp(buf, "sNaPpY", std::strlen("sNaPpY"))) warnx(gettext("%s: stream identifier chunk: content %.*s != %s"), filename, (int)chunk_len, buf, "sNaPpY"), err = true; break; case 0x00: // 4.2. Compressed data (chunk type 0x00) err |= uncompress_unframed(buf + 4, chunk_len - 4, &sink, filename, ignore_errors); sink.f = nullptr; break; case 0x01: // 4.3. Uncompressed data (chunk type 0x01) sink.Append(buf + 4, chunk_len - 4); sink.f = nullptr; break; case 0xFE: // 4.4. Padding (chunk type 0xfe) break; default: if(tp >= 0x02 && tp <= 0x7F) // 4.5. Reserved unskippable chunks (chunk types 0x02-0x7f) warnx(gettext("%s: chunk of length %zu: unknown type 0x%02X"), filename, static_cast(chunk_len), tp), err = true; else // 4.6. Reserved skippable chunks (chunk types 0x80-0xfd) ; } if(err && !ignore_errors) return err; if(!sink.f) { sink.sum = crc32c_finish(sink.sum); if(le32toh(bufsum) != sink.sum) { warnx(gettext("%s: chunk of length %zu: checksum 0x%08X != 0x%08X"), filename, static_cast(chunk_len), sink.sum, le32toh(bufsum)), err = true; if(!ignore_errors) return err; } } } return err; } std::pair ingest(FILE * f, const char * filename, const void * prefix = nullptr, std::size_t prefix_len = 0) { char * data; std::size_t data_size; auto mf = open_memstream(&data, &data_size); if(!mf) mferr: err(2, nullptr); std::fwrite(prefix, 1, prefix_len, mf); for(auto rd = sizeof(buf); rd == sizeof(buf);) { if((rd = std::fread(buf, 1, sizeof(buf), f)) != sizeof(buf) && std::ferror(f)) err(2, "%s", filename); if(std::fwrite(buf, 1, rd, mf) != rd) goto mferr; } if(std::fclose(mf)) goto mferr; return {data, data_size}; } struct stdout_flush { ~stdout_flush() { if(std::fflush(stdout)) err(2, gettext("write error")); } }; } int main(int argc, char * const * argv) { setlocale(LC_ALL, ""); #if __has_include() bindtextdomain("snappy-tools", TEXTDOMAIN_DIRNAME); textdomain("snappy-tools"); #endif auto bn = std::strrchr(argv[0] ?: "", '/') ?: (argv[0] ?: ""); auto uncompress_argv0 = *bn == 'u' || (*bn == '/' && *(bn + 1) == 'u'); bool uncompress = uncompress_argv0; bool uncompress_ignore_errors{}; bool compress_frame{}; for(int arg; (arg = getopt(argc, argv, uncompress_argv0 ? "i" : "dif")) != -1;) switch(arg) { case 'd': uncompress = true; break; case 'i': uncompress_ignore_errors = true; break; case 'f': compress_frame = true; break; default: usage: // Also in README! return std::fprintf(stderr, uncompress_argv0 ? gettext("usage: %1$s [-i] snappy.sn|.sz\n" " %1$s [-i] < snappy.sn|.sz\n") : gettext("usage: %1$s [-f] data > snappy.sn|.sz\n" " %1$s [-f] < data > snappy.sn|.sz\n" " %1$s -d [-i] snappy.sn|.sz\n" " %1$s -d [-i] < snappy.sn|.sz\n"), argv[0]), 1; } if(*(argv + optind) && *(argv + optind + 1)) goto usage; auto filename = *(argv + optind) ?: "-"; if(filename != "-"sv) if(!std::freopen(filename, "r", stdin)) err(2, "%s", filename); const int fd = 0; FILE * const f = stdin; stdout_flush _flusher{}; if(uncompress) { auto hdrlen = std::fread(buf, 1, sizeof("\xFF\x06\x00\x00sNaPpY") - 1, f); if(hdrlen != sizeof("\xFF\x06\x00\x00sNaPpY") - 1) { if(std::ferror(f)) err(2, "%s", filename); FILE_sink sink{stdout}; return uncompress_unframed(buf, hdrlen, &sink, filename, uncompress_ignore_errors); } else if(!std::memcmp(buf, "\xFF\x06\x00\x00sNaPpY", sizeof("\xFF\x06\x00\x00sNaPpY") - 1)) return uncompress_framed(f, filename, uncompress_ignore_errors); // Ideally we'd just ungetc but realistically glibc/musl give us 8 bytes and we want 9 :/ // while(hdrlen--) // assert(std::ungetc(buf[hdrlen], stdin) != EOF); off_t orig_pos, len; const void * mapping; if((orig_pos = ftello(f)) == -1 || fseeko(f, 0, SEEK_END) == -1 || (len = ftello(f)) == -1 || ((mapping = mmap(nullptr, len, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED && (fseeko(f, orig_pos, SEEK_SET), true))) { auto dt = ingest(f, filename, buf, hdrlen); FILE_sink sink{stdout}; return uncompress_unframed(dt.first, dt.second, &sink, filename, uncompress_ignore_errors); } FILE_sink sink{stdout}; return uncompress_unframed(reinterpret_cast(mapping) + (orig_pos - hdrlen), len - (orig_pos - hdrlen), &sink, filename, uncompress_ignore_errors); } else { unsigned long long read{}, written{}; // No thread: {read → compress → cksum → write}... // // Yes thread: {read 🚧→ compress 🚧→ write}... // ↓ len ↑ sum // thread: {🚧→ cksum 🚧→}... const auto crc_in_thread = parallel_compression_crc32c(); struct ipc { pthread_barrier_t barrier; std::atomic len_sum; } ipc; pthread_t cksum_thread; if(crc_in_thread) { while(pthread_barrier_init(&ipc.barrier, nullptr, 2)) ; while(pthread_create( &cksum_thread, nullptr, [](void * ipcp) -> void * { auto & ipc = *reinterpret_cast(ipcp); for(;;) { pthread_barrier_wait(&ipc.barrier); ipc.len_sum.store(htole32(crc32c_finish(crc32c(~0, buf, ipc.len_sum.load(std::memory_order::relaxed)))), std::memory_order::relaxed); pthread_barrier_wait(&ipc.barrier); } __builtin_unreachable(); }, &ipc)) ; } if(compress_frame) { if(std::fwrite("\xFF\x06\x00\x00sNaPpY", 1, sizeof("\xFF\x06\x00\x00sNaPpY") - 1, stdout) != sizeof("\xFF\x06\x00\x00sNaPpY") - 1) we: err(2, gettext("write error")); written = sizeof("\xFF\x06\x00\x00sNaPpY") - 1; // However, we place an additional restriction that the uncompressed data in a chunk must be no longer than 65536 bytes. for(std::size_t rd = 65536; rd == 65536;) { if((rd = std::fread(buf, 1, 65536, f)) != 65536 && std::ferror(f)) err(2, "%s", filename); read += rd; if(!rd) break; if(crc_in_thread) { ipc.len_sum.store(rd, std::memory_order::relaxed); pthread_barrier_wait(&ipc.barrier); } auto compbuf = buf + 65536; std::size_t compbuf_len = -1; snappy::RawCompress(buf, rd, compbuf, &compbuf_len); // Both the uncompressed and the compressed chunks have the same final size: [1 + 3 ] + 4 + data // [type + len] + cksum + data // [header ] + body // 4.2. Compressed data (chunk type 0x00) // 4.3. Uncompressed data (chunk type 0x01) std::uint8_t tp = (compbuf_len < rd) ? 0x00 : 0x01; if(putc(tp, stdout) == EOF) goto we; auto outsize = 4 + (tp ? rd : compbuf_len); if(putc((outsize & 0x0000FF) >> 0, stdout) == EOF || // putc((outsize & 0x00FF00) >> 8, stdout) == EOF || // putc((outsize & 0xFF0000) >> 16, stdout) == EOF) goto we; std::uint32_t crc; if(crc_in_thread) { pthread_barrier_wait(&ipc.barrier); crc = ipc.len_sum.load(std::memory_order::relaxed); } else crc = htole32(crc32c_finish(crc32c(~0, buf, rd))); if(std::fwrite(&crc, 1, 4, stdout) != 4) goto we; if(std::fwrite(tp ? buf : compbuf, 1, tp ? rd : compbuf_len, stdout) != (tp ? rd : compbuf_len)) goto we; written += 1 + 3 + 4 + (tp ? rd : compbuf_len); } } else { FILE_sink sink{stdout}; if(fd_source source{fd, filename}; source.size && source.off != -1) { read = source.size - source.off; if(read != source.Available()) errno = EOVERFLOW, err(2, "%s", filename); written = Compress(&source, &sink); } else { auto dt = ingest(f, filename); read = dt.second; snappy::ByteArraySource src{reinterpret_cast(dt.first), dt.second}; written = Compress(&src, &sink); } } // filename, byte count read, byte count written, ratio std::fprintf(stderr, gettext("%s: %llu -> %llu (%.2f%%)\n"), filename, read, written, 100. * ((double)written / read)); if(!compress_frame && read >= 4ull * 1024 * 1024 * 1024) return std::fprintf(stderr, gettext("%s: %s: sized %lluB >= 4GiB w/o -f: output stream may be broken!\n"), argv[0], filename, read), 3; } } snappy-tools-1/test000077500000000000000000000322741456325324700146140ustar00rootroot00000000000000#!/bin/sh # SPDX-License-Identifier: 0BSD LC_ALL=C export LC_ALL # head -c is Issue 8 and OpenBSD does not have it head -c 0 < /dev/null 2>/dev/null || head() { dd bs=1 count="$2" 2>/dev/null; } command -v truncate > /dev/null || truncate() { tr=$2; printf '\0' | dd bs=1 count=1 seek=$(( tr - 1 )) > "$3" 2>/dev/null; } command -v base64 > /dev/null || base64() { b64decode -r; } EMPTYSUM='4294967295 0' # cksum /dev/null reqsum() { # file cksum [label] sum="$(cksum < "$1")" || exit [ "$sum" = "$2" ] || { echo "$0: ${3-"$1"}: cksum $sum != $2" >&2 exit 1 } } expexit() { # expecting comment ret=$? [ "$ret" -eq "${1-0}" ] || { echo "$0: $2: $ret != ${1-0}!" >&2 ret=${ret#0} exit ${ret:-100} } } reqcompuncomp() { for src in file ${pipe-pipe}; do case $src in file) "$snappy" $tpfl $1 "$2" > "${tmpd}out$suff" 2>"${tmpd}err$suff" ;; pipe) cat "$2" | "$snappy" $tpfl $1 > "${tmpd}out$suff" 2>"${tmpd}err$suff" ;; esac expexit "${exit-0}" "${4-"$2"}" grep -v ' -> ' "${tmpd}err$suff" > "${tmpd}errG$suff" [ -n "$error" ] && { mv "${tmpd}errG$suff" "${tmpd}err$suff" grep -v -e "$error" "${tmpd}err$suff" > "${tmpd}errG$suff" } [ -s "${tmpd}errG$suff" ] && { echo "$0: ${4-"$2"} $tpfl ${1:- }: error output!" >&2 cat "${tmpd}errG$suff" >&2 exit 101 } reqsum "${tmpd}out$suff" "$3" "${4-"$2"} ${1:- } ${tp}compressed ($src)" done rm "${tmpd}out$suff" } reqcomp() { # -f|'' file cksum [label] tp= tpfl= reqcompuncomp "$@" } requncomp() { # -i|'' file cksum [label] tp=un tpfl=-d reqcompuncomp "$@" } trap 'rm -rf "$tmpd"' EXIT INT tmpd="$(mktemp -d)/" || exit snappy="${snappy-./snappy}" LP64="$(od -tc -N5 -An "$snappy" | { read -r x7f e l f wide [ "$x7f$e$l$f" = '177ELF' ] || { echo "$0: $snappy not an ELF" >&2 exit 102 } case "$wide" in (001) ;; (002) echo 1 ;; (* ) echo "$0: $snappy ELF EI_CLASS=$wide != 00[12]" >&2; exit 102 ;; esac })" || exit truncate -s $(( 4 * 1024 * 1024 * 1024 - 1 )) "${tmpd}4G-1" truncate -s $(( 4 * 1024 * 1024 * 1024 )) "${tmpd}4G" truncate -s $(( 4 * 1024 * 1024 * 1024 + 1 )) "${tmpd}4G+1" pipe= suff=0 reqcomp '' "${tmpd}4G-1" '1595709065 201457669' & slowpids="$slowpids $!" if [ -n "$LP64" ]; then pipe= exit=3 error=': sized 4294967296B >= 4GiB w/o -f: output stream may be broken!' suff=1 reqcomp '' "${tmpd}4G" '3359713396 201457665' & slowpids="$slowpids $!" pipe= exit=3 error=': sized 4294967297B >= 4GiB w/o -f: output stream may be broken!' suff=2 reqcomp '' "${tmpd}4G+1" '2636691535 201457667' & slowpids="$slowpids $!" else pipe= exit=2 error='Value too large for defined data type' reqcomp '' "${tmpd}4G" "$EMPTYSUM" # EOVERFLOW pipe= exit=2 error='Value too large for defined data type' reqcomp '' "${tmpd}4G+1" "$EMPTYSUM" # EOVERFLOW unset pipe exit error # OpenBSD echo "$0: ILP32" >&2 fi pipe= suff=3 reqcomp -f "${tmpd}4G-1" '3376615409 202178570' & slowpids="$slowpids $!" pipe= suff=4 reqcomp -f "${tmpd}4G" '1723315092 202178570' & slowpids="$slowpids $!" pipe= suff=5 reqcomp -f "${tmpd}4G+1" '1639829730 202178579' & slowpids="$slowpids $!" # A constant megabyte of uncompressible data but without shipping a constant megabyte of uncompressible data # This is the minstd generator (m = 2^31−1, a = 48271, c = 0), seed chosen from date +%s at time of writing # This could be a shell function but converting a number to bytes is too slow to be useful { printf '%s\n' '#include ' \ '#include ' \ '#include ' \ 'int main() {' \ ' uint32_t seed = 1703786413, le;' \ ' for(;;) {' \ ' seed = (48271 * seed) % 0x7FFFFFFF;' \ ' le = htole32(seed);' \ ' fwrite(&le, 1, sizeof(le), stdout);' \ ' }' \ '}' | ${CC-cc} ${CPPFLAGS} ${CFLAGS} -O0 -xc - -o "${tmpd}genrand" "${tmpd}genrand" | head -c $(( 1024 * 1024 )) > "${tmpd}rand" } & randpid=$! # A constant megabyte of easily-compressible data but without shipping a constant megabyte of easily-compressible data i=0; while [ $i -lt 1024 ]; do printf '%1023d\n' $i i=$(( i + 1 )) done > "${tmpd}notrand" reqsum "${tmpd}notrand" '1532305231 1048576' [ -w /dev/full ] && { "$snappy" "${tmpd}notrand" > /dev/full 2>/dev/null expexit 2 '/dev/full' "$snappy" -f "${tmpd}notrand" > /dev/full 2>/dev/null expexit 2 '/dev/full' "$snappy" /ENOENT > /dev/full 2>/dev/null expexit 2 '/ENOENT' "$snappy" -d /ENOENT > /dev/full 2>/dev/null expexit 2 '-d /ENOENT' } || echo "$0: no /dev/full" >&2 # $ echo data | ./snappy -f | hd # 000000 ff 06 00 00 73 4e 61 50 70 59 01 09 00 00 eb 1b >....sNaPpY......< # 000010 fb 25 64 61 74 61 0a >.%data.< # 000017 stream_identifier() { # data data="${1-sNaPpY}" printf '\377' printf "\\$(printf %03o ${#data})"'\0\0' printf '%s' "$data" } uncompressed() { printf '\1' printf '\11\0\0' # 9 printf '\353\33\373\45' printf 'data\n' } # $ echo data data data data data | ./snappy -f | hd # 000000 ff 06 00 00 73 4e 61 50 70 59 00 10 00 00 c4 61 >....sNaPpY.....a< # 000010 e6 61 19 10 64 61 74 61 20 4a 05 00 00 0a >.a..data J....< # 00001e compressed() { printf '\0' printf '\20\0\0' printf '\304\141\346\141' compressed_data } compressed_data() { printf '\31\20data\40\112\5\0\0\n' } mangle_cksum() { head -c $(( 1 + 3 )) head -c 4 > /dev/null printf '\377\377\377\377' cat } stream_identifier > "${tmpd}tmp" requncomp '' "${tmpd}tmp" "$EMPTYSUM" { stream_identifier; uncompressed; } > "${tmpd}tmp" requncomp '' "${tmpd}tmp" "$(echo data | cksum)" # 4.1. Stream identifier (chunk type 0xff) { stream_identifier; stream_identifier snoopy; uncompressed; } > "${tmpd}tmp" exit=1 error=': stream identifier chunk: content snoopy != sNaPpY' requncomp '' "${tmpd}tmp" "$EMPTYSUM" exit=1 error=': stream identifier chunk: content snoopy != sNaPpY' requncomp -i "${tmpd}tmp" "$(echo data | cksum)" { stream_identifier; stream_identifier short; uncompressed; } > "${tmpd}tmp" exit=1 error='stream identifier chunk: length 5 != 6 : stream identifier chunk: content short != sNaPpY' requncomp '' "${tmpd}tmp" "$EMPTYSUM" exit=1 error='stream identifier chunk: length 5 != 6 : stream identifier chunk: content short != sNaPpY' requncomp -i "${tmpd}tmp" "$(echo data | cksum)" unset pipe exit error # OpenBSD # 4.2. Compressed data (chunk type 0x00) { stream_identifier; compressed; } > "${tmpd}tmp" requncomp '' "${tmpd}tmp" "$(echo data data data data data | cksum)" requncomp -i "${tmpd}tmp" "$(echo data data data data data | cksum)" compressed_data > "${tmpd}tmp" requncomp '' "${tmpd}tmp" "$(echo data data data data data | cksum)" requncomp -i "${tmpd}tmp" "$(echo data data data data data | cksum)" { stream_identifier; { printf '\0'; printf '\5\0\0'; printf '\330\352\202\242'; printf '\377'; } } > "${tmpd}tmp" exit=1 error=': compressed block of length 1: invalid data' requncomp '' "${tmpd}tmp" "$EMPTYSUM" exit=1 error=': compressed block of length 1: invalid data : compressed block of length 1: expecting 127 bytes, got 0' requncomp -i "${tmpd}tmp" "$EMPTYSUM" printf '\377' > "${tmpd}tmp" exit=1 error=': compressed block of length 1: invalid data' requncomp '' "${tmpd}tmp" "$EMPTYSUM" exit=1 error=': compressed block of length 1: invalid data : compressed block of length 1: expecting 127 bytes, got 0' requncomp -i "${tmpd}tmp" "$EMPTYSUM" unset pipe exit error # OpenBSD # 4.3. Uncompressed data (chunk type 0x01) : nothing # 4.4. Padding (chunk type 0xfe) { stream_identifier; { printf '\376'; printf '\5\0\0'; echo skip; } } > "${tmpd}tmp" requncomp '' "${tmpd}tmp" "$EMPTYSUM" requncomp -i "${tmpd}tmp" "$EMPTYSUM" # 4.6. Reserved skippable chunks (chunk types 0x80-0xfd) { stream_identifier; { printf '\375'; printf '\5\0\0'; echo skip; }; { printf '\200'; printf '\5\0\0'; echo skip; } } > "${tmpd}tmp" requncomp '' "${tmpd}tmp" "$EMPTYSUM" requncomp -i "${tmpd}tmp" "$EMPTYSUM" # 4.5. Reserved unskippable chunks (chunk types 0x02-0x7f) { stream_identifier; { printf '\2'; printf '\5\0\0'; echo need; }; { printf '\177'; printf '\5\0\0'; echo need; }; uncompressed; } > "${tmpd}tmp" exit=1 error=': chunk of length 5: unknown type 0x02' requncomp '' "${tmpd}tmp" "$EMPTYSUM" exit=1 error=': chunk of length 5: unknown type 0x02 : chunk of length 5: unknown type 0x7F' requncomp -i "${tmpd}tmp" "$(echo data | cksum)" # Broken checksum { stream_identifier; uncompressed | mangle_cksum; uncompressed; } > "${tmpd}tmp" exit=1 error=': chunk of length 9: checksum 0x25FB1BEB != 0xFFFFFFFF' requncomp '' "${tmpd}tmp" "$(echo data | cksum)" exit=1 error=': chunk of length 9: checksum 0x25FB1BEB != 0xFFFFFFFF' requncomp -i "${tmpd}tmp" "$({ echo data; echo data; } | cksum)" { stream_identifier; compressed | mangle_cksum; uncompressed; } > "${tmpd}tmp" exit=1 error=': chunk of length 16: checksum 0x61E661C4 != 0xFFFFFFFF' requncomp '' "${tmpd}tmp" "$(echo data data data data data | cksum)" exit=1 error=': chunk of length 16: checksum 0x61E661C4 != 0xFFFFFFFF' requncomp -i "${tmpd}tmp" "$({ echo data data data data data; echo data; } | cksum)" { stream_identifier; uncompressed | mangle_cksum; compressed | mangle_cksum; uncompressed; } > "${tmpd}tmp" exit=1 error=': chunk of length 9: checksum 0x25FB1BEB != 0xFFFFFFFF' requncomp '' "${tmpd}tmp" "$(echo data | cksum)" exit=1 error=': chunk of length 9: checksum 0x25FB1BEB != 0xFFFFFFFF : chunk of length 16: checksum 0x61E661C4 != 0xFFFFFFFF' requncomp -i "${tmpd}tmp" "$({ echo data; echo data data data data data; echo data; } | cksum)" unset pipe exit error # OpenBSD wait $randpid reqsum "${tmpd}rand" '3325647168 1048576' cat "${tmpd}notrand" "${tmpd}rand" > "${tmpd}both" reqsum "${tmpd}both" '2787934995 2097152' reqcomp '' "${tmpd}rand" '3602555776 1048627' reqcomp '' "${tmpd}notrand" '1720161590 51441' reqcomp '' "${tmpd}both" '2176093359 1100066' reqcomp -f "${tmpd}rand" '1464354933 1048714' reqcomp -f "${tmpd}notrand" '4240805396 51624' reqcomp -f "${tmpd}both" '2083221021 1100328' # Sought input { echo pref; stream_identifier; compressed; } > "${tmpd}tmp" { head -c 5; "$snappy" -d 2>/dev/null || exit; } < "${tmpd}tmp" > "${tmpd}head-d" { head -c 5; "$snappy" -di 2>/dev/null || exit; } < "${tmpd}tmp" > "${tmpd}head-di" reqsum "${tmpd}head-d" "$(printf '%s\n' pref 'data data data data data' | cksum)" reqsum "${tmpd}head-di" "$(printf '%s\n' pref 'data data data data data' | cksum)" { head -c $(( 1024 * 1024 )) > /dev/null; "$snappy" 2>/dev/null || exit; } < "${tmpd}both" > "${tmpd}rand.comp" { head -c $(( 1024 * 1024 )) > /dev/null; "$snappy" -f 2>/dev/null || exit; } < "${tmpd}both" > "${tmpd}rand.comp-f" reqsum "${tmpd}rand.comp" '3602555776 1048627' # same as rand reqsum "${tmpd}rand.comp-f" '1464354933 1048714' # same as rand # Wikipedia (old) # 0000000: ca02 f042 5769 6b69 7065 6469 6120 6973 ...BWikipedia is # 0000010: 2061 2066 7265 652c 2077 6562 2d62 6173 a free, web-bas # 0000020: 6564 2c20 636f 6c6c 6162 6f72 6174 6976 ed, collaborativ # 0000030: 652c 206d 756c 7469 6c69 6e67 7561 6c20 e, multilingual # 0000040: 656e 6379 636c 6f09 3ff0 1470 726f 6a65 encyclo.?..proje # 0000050: 6374 2e00 0000 0000 0000 0000 0000 0000 ct. WIKIRAW='Wikipedia is a free, web-based, collaborative, multilingual encyclopedia project.' echo ygLwQldpa2lwZWRpYSBpcyBhIGZyZWUsIHdlYi1iYXNlZCwgY29sbGFib3JhdGl2ZSwgbXVsdGlsaW5ndWFsIGVuY3ljbG8JP/AUcHJvamVjdC4AAAAAAAAAAAAAAAAA | base64 -d > "${tmpd}wiki.old.sn" reqsum "${tmpd}wiki.old.sn" '1128299641 96' exit=1 error='compressed block of length 96: expecting 330 bytes, got 94' requncomp '' "${tmpd}wiki.old.sn" "$(printf '%s\0\0\0\0\0\0\0\0\0\0\0\0\0' "$WIKIRAW" | cksum)" exit=1 error='compressed block of length 96: expecting 330 bytes, got 94' requncomp -i "${tmpd}wiki.old.sn" "$(printf '%s\0\0\0\0\0\0\0\0\0\0\0\0\0' "$WIKIRAW" | cksum)" unset pipe exit error # OpenBSD # Wikipedia (new) # https://en.wikipedia.org/w/index.php?title=Snappy_(compression)&oldid=1192681788 # 000000 51 f0 42 57 69 6b 69 70 65 64 69 61 20 69 73 20 >Q.BWikipedia is < # 000010 61 20 66 72 65 65 2c 20 77 65 62 2d 62 61 73 65 >a free, web-base< # 000020 64 2c 20 63 6f 6c 6c 61 62 6f 72 61 74 69 76 65 >d, collaborative< # 000030 2c 20 6d 75 6c 74 69 6c 69 6e 67 75 61 6c 20 65 >, multilingual e< # 000040 6e 63 79 63 6c 6f 09 3f 1c 70 72 6f 6a 65 63 74 >ncyclo.?.project< # 000050 2e >.< echo UfBCV2lraXBlZGlhIGlzIGEgZnJlZSwgd2ViLWJhc2VkLCBjb2xsYWJvcmF0aXZlLCBtdWx0aWxpbmd1YWwgZW5jeWNsbwk/HHByb2plY3Qu | base64 -d > "${tmpd}wiki.new.sn" reqsum "${tmpd}wiki.new.sn" '2867047585 81' requncomp '' "${tmpd}wiki.new.sn" "$(printf '%s' "$WIKIRAW" | cksum)" requncomp -i "${tmpd}wiki.new.sn" "$(printf '%s' "$WIKIRAW" | cksum)" for i in $slowpids; do wait $i || exit done snappy-tools-1/unsnappy000077700000000000000000000000001456325324700167272snappyustar00rootroot00000000000000