1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324
|
#!/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 <endian.h>' \
'#include <stdint.h>' \
'#include <stdio.h>' \
'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
|