1#!/bin/bash 2 3[ -f testing.sh ] && . testing.sh 4 5#testing "name" "command" "result" "infile" "stdin" 6 7# For reproducibility: UTC and umask 0002 8 9OLDTZ="$TZ" 10export TZ=utc 11OLDUMASK=$(umask) 12umask 0002 13 14# 255 bytes, longest VFS name 15LONG=0123456789abcdef0123456789abcdef 16LONG=$LONG$LONG$LONG$LONG$LONG$LONG$LONG$LONG 17LONG=${LONG:1:255} 18 19# Reproducible tarballs: override ownership and timestamp. 20TAR='tar c --owner root --group root --mtime @1234567890' 21 22# Different tars add variable trailing NUL padding (1024 bytes is just minimum) 23# so look at first N 512-byte frames when analyzing header content. 24function SUM() 25{ 26 tee save.dat | head -c $(($1*512)) | sha1sum | sed "s/ .*//" 27} 28 29function LST() 30{ 31 tar tv "$@" | sed 's/[ \t][ \t]*/ /g' 32} 33 34touch file 35testing "create file" "$TAR file | SUM 3" \ 36 "fecaecba936e604bb115627a6ef4db7c7a3a8f81\n" "" "" 37 38testing "pass file" "$TAR file | LST" \ 39 "-rw-rw-r-- root/root 0 2009-02-13 23:31 file\n" "" "" 40 41touch file1 file2 42echo -e "file1\nfile2" > files-newline 43testing "-T newline" "$TAR -T files-newline | LST" \ 44 "-rw-rw-r-- root/root 0 2009-02-13 23:31 file1\n-rw-rw-r-- root/root 0 2009-02-13 23:31 file2\n" "" "" 45tr '\n' '\0' < files-newline > files-null 46testing "-T null" "$TAR --null -T files-null | LST" \ 47 "-rw-rw-r-- root/root 0 2009-02-13 23:31 file1\n-rw-rw-r-- root/root 0 2009-02-13 23:31 file2\n" "" "" 48 49# The kernel has two hardwired meaningful UIDs: 0 (root) and 65534 (nobody). 50# (Technically changeable via /proc/sys/*/overflowuid but nobody ever does) 51skipnot id nobody >/dev/null 52testing "pass user" "tar -c --owner nobody:65534 --group root --mtime @0 file | LST" \ 53 "-rw-rw-r-- nobody/root 0 1970-01-01 00:00 file\n" "" "" 54# (We assume that if we have the nobody user, we also have the group, in the 55# absence of a good portable way to test for the existence of a named group.) 56skipnot id nobody >/dev/null 57testing "pass group" "tar c --owner root --group nobody:65534 --mtime @0 file | LST" \ 58 "-rw-rw-r-- root/nobody 0 1970-01-01 00:00 file\n" "" "" 59 60# Historically we output a "base 256" format that _we_ could decode but that 61# GNU tar choked on, so check the exact bytes with SUM, not a LST round trip. 62testing "huge values" "tar c --owner 9999999 --group 8888888 --mtime @0 file | SUM 3" \ 63 "396b07fd2f80eeb312462e3bfb7dc1325dc6bcfb\n" "" "" 64 65touch -t 198701231234.56 file 66testing "pass mtime" \ 67 "tar c --owner root --group root file | LST --full-time" \ 68 "-rw-rw-r-- root/root 0 1987-01-23 12:34:56 file\n" "" "" 69 70testing "adjust mode" \ 71 "tar c --owner root --group root --mode a+x file | LST --full-time" \ 72 "-rwxrwxr-x root/root 0 1987-01-23 12:34:56 file\n" "" "" 73 74mkdir dir 75testing "create dir" "$TAR dir | SUM 3" \ 76 "05739c423d7d4a7f12b3dbb7c94149acb2bb4f8d\n" "" "" 77 78testing "pass dir" "$TAR dir | LST" \ 79 "drwxrwxr-x root/root 0 2009-02-13 23:31 dir/\n" "" "" 80 81# note: does _not_ include dir entry in archive, just file 82touch dir/file 83testing "create file in dir" "$TAR dir/file | SUM 3" \ 84 "2d7b96c7025987215f5a41f10eaa84311160afdb\n" "" "" 85 86# Tests recursion without worrying about content order 87testing "create dir and dir/file" "$TAR dir | SUM 3" \ 88 "0bcc8005a3e07eb63c9b735267aecc5b774795d7\n" "" "" 89 90testing "pass dir/file" "$TAR dir | LST" \ 91 "drwxrwxr-x root/root 0 2009-02-13 23:31 dir/\n-rw-rw-r-- root/root 0 2009-02-13 23:31 dir/file\n" "" "" 92 93echo boing > dir/that 94testing "tar C" "$TAR -C dir that | SUM 3" \ 95 "f0deff71bf4858eb0c5f49d99d052f12f1831feb\n" "" "" 96 97# / and .. only stripped from name, not symlink target. 98ln -s ../name.././.. dir/link 99testing "create symlink" "$TAR dir/link | SUM 3" \ 100 "7324cafbd9aeec5036b6efc54d741f11528aeb10\n" "" "" 101 102# Also two explicit targets 103ln dir/file dir/hardlink 104testing "create hardlink" "$TAR dir/file dir/hardlink | SUM 3" \ 105 "c5383651f8c03ec0fe15e8a9e28a4e8e5273990d\n" "" "" 106 107ln dir/link dir/hlink 108testing "create hardlink to symlink" "$TAR dir/link dir/hlink | SUM 3" \ 109 "3bc16f8fb6fc8b05f691da8caf989a70ee99284a\n" "" "" 110 111skipnot mkfifo dir/fifo 2>/dev/null 112testing "create dir/fifo" "$TAR dir/fifo | SUM 3" \ 113 "bd1365db6e8ead4c813333f9666994c1899924d9\n" "" "" 114 115# test L and K records 116 117# 4+96=100 (biggest short name), 4+97=101 (shortest long name) 118touch dir/${LONG:1:96} dir/${LONG:1:97} 119testing "create long fname" "$TAR dir/${LONG:1:97} dir/${LONG:1:96} | SUM 3" \ 120 "99348686fe9c9bf80f5740f1fc0c6f32f2021e3d\n" "" "" 121 122ln -s dir/${LONG:1:96} dir/lshort 123ln -s dir/${LONG:1:97} dir/llong 124testing "create long symlnk" "$TAR dir/lshort dir/llong | SUM 3" \ 125 "8a5d652dc85f252a2e3b3f47d1ecd699e98a5f4b\n" "" "" 126 127ln -s $LONG dir/${LONG:5} 128testing "create long->long" "$TAR dir/${LONG:5} | SUM 7" \ 129 "543116b8e690a116a559ab5b673f9b6d6601c925\n" "" "" 130# absolute and relative link names, broken and not 131 132ln -s file dir/linkok 133testing "create symlink" "$TAR dir/linkok | SUM 3" \ 134 "55652846506cf0a9d43b3ef03ccf9e98123befaf\n" "" "" 135 136ln -s /dev/null dir/linknull 137testing "pass absolute symlink" "$TAR dir/linknull | LST" \ 138 "lrwxrwxrwx root/root 0 2009-02-13 23:31 dir/linknull -> /dev/null\n" "" "" 139 140ln -s rel/broken dir/relbrok 141testing "pass broken symlink" "$TAR dir/relbrok | LST" \ 142 "lrwxrwxrwx root/root 0 2009-02-13 23:31 dir/relbrok -> rel/broken\n" "" "" 143 144ln -s /does/not/exist dir/linkabsbrok 145testing "pass broken absolute symlink" "$TAR dir/linkabsbrok | LST" \ 146 "lrwxrwxrwx root/root 0 2009-02-13 23:31 dir/linkabsbrok -> /does/not/exist\n" \ 147 "" "" 148 149# this expects devtmpfs values 150 151testing "pass /dev/null" \ 152 "tar c --mtime @0 /dev/null 2>/dev/null | LST" \ 153 "crw-rw-rw- root/root 1,3 1970-01-01 00:00 dev/null\n" "" "" 154testing "--absolute-names" \ 155 "tar c --mtime @0 --absolute-names /dev/null 2>/dev/null | LST" \ 156 "crw-rw-rw- root/root 1,3 1970-01-01 00:00 /dev/null\n" "" "" 157 158# compression types 159testing "autodetect gzip" 'LST -f "$FILES"/tar/tar.tgz' \ 160 "drwxr-x--- enh/eng 0 2017-05-13 01:05 dir/\n-rw-r----- enh/eng 12 2017-05-13 01:05 dir/file\n" \ 161 "" "" 162 163testing "manually specify bz2" 'LST -jf "$FILES"/tar/tar.tbz2' \ 164 "drwxr-x--- enh/eng 0 2017-05-13 01:05 dir/\n-rw-r----- enh/eng 12 2017-05-13 01:05 dir/file\n" \ 165 "" "" 166 167# -I 168testing "-I gzip c" "$TAR -Igzip file | file - | grep -o 'gzip compressed'" \ 169 "gzip compressed\n" "" "" 170testing "-I gzip t" 'LST -Igzip -f "$FILES"/tar/tar.tgz' \ 171 "drwxr-x--- enh/eng 0 2017-05-13 01:05 dir/\n-rw-r----- enh/eng 12 2017-05-13 01:05 dir/file\n" \ 172 "" "" 173 174skipnot mknod dir/char c 12 34 2>/dev/null 175testing "character special" "tar --mtime @0 -cf test.tar dir/char && rm -f dir/char && tar xf test.tar && ls -l dir/char" \ 176 "crw-rw---- 1 root root 12, 34 1970-01-01 00:00 dir/char\n" "" "" 177 178skipnot mknod dir/block b 23 45 2>/dev/null 179testing "block special" "tar --mtime @0 -cf test.tar dir/block && rm -f dir/block && tar xf test.tar && ls -l dir/block" \ 180 "brw-rw---- 1 root root 23, 45 1970-01-01 00:00 dir/block\n" "" "" 181 182skipnot chown nobody dir/file 2>/dev/null 183testing "ownership" "$TAR dir/file | SUM 3" \ 184 "2d7b96c7025987215f5a41f10eaa84311160afdb\n" "" "" 185 186mkdir -p dd/sub/blah && 187tar cf test.tar dd/sub/blah && 188rm -rf dd/sub && 189ln -s ../.. dd/sub || SKIPNEXT=1 190toyonly testing "symlink out of cwd" \ 191 "tar xf test.tar 2> /dev/null || echo yes ; [ ! -e dd/sub/blah ] && echo yes" \ 192 "yes\nyes\n" "" "" 193 194# If not root can't preserve ownership, so don't try yet. 195 196testing "extract dir/file from tar" \ 197 "tar xvCf dd $FILES/tar/tar.tar && stat -c '%A %Y %n' dd/dir dd/dir/file" \ 198 "dir/\ndir/file\ndrwxr-x--- 1494637555 dd/dir\n-rw-r----- 1494637555 dd/dir/file\n" \ 199 "" "" 200 201testing "extract dir/file from tgz (autodetect)" \ 202 "tar xvCf dd $FILES/tar/tar.tgz && stat -c '%A %Y %n' dd/dir dd/dir/file" \ 203 "dir/\ndir/file\ndrwxr-x--- 1494637555 dd/dir\n-rw-r----- 1494637555 dd/dir/file\n" \ 204 "" "" 205 206toyonly testing "cat tgz | extract dir/file (autodetect)" \ 207 "cat $FILES/tar/tar.tgz | tar xvC dd && stat -c '%A %Y %n' dd/dir dd/dir/file" \ 208 "dir/\ndir/file\ndrwxr-x--- 1494637555 dd/dir\n-rw-r----- 1494637555 dd/dir/file\n" \ 209 "" "" 210 211testing "extract dir/file from tbz2 (autodetect)" \ 212 "tar xvCf dd $FILES/tar/tar.tbz2 && stat -c '%A %Y %n' dd/dir dd/dir/file" \ 213 "dir/\ndir/file\ndrwxr-x--- 1494637555 dd/dir\n-rw-r----- 1494637555 dd/dir/file\n" \ 214 "" "" 215 216toyonly testing "cat tbz | extract dir/file (autodetect)" \ 217 "cat $FILES/tar/tar.tbz2 | tar xvC dd && stat -c '%A %Y %n' dd/dir dd/dir/file" \ 218 "dir/\ndir/file\ndrwxr-x--- 1494637555 dd/dir\n-rw-r----- 1494637555 dd/dir/file\n" \ 219 "" "" 220 221yes | head -n $((1<<18)) > bang 222{ dd bs=$((1<<16)) count=1 status=none; dd bs=8192 seek=14 count=1 status=none; dd bs=4096 seek=64 count=5 status=none; } < bang > fweep 223testing "sparse without overflow" "$TAR --sparse fweep | SUM 3" \ 224 "e1560110293247934493626d564c8f03c357cec5\n" "" "" 225rm bang fweep 226 227for i in 1 3 5 7 9 14 27 36 128 256 300 304 228do 229 dd if=/dev/zero of=fweep bs=65536 seek=$i count=1 2>/dev/null 230done 231 232testing "sparse single overflow" "$TAR --sparse fweep | SUM 6" \ 233 "063fc6519ea2607763bc591cc90dd15ac2b43eb8\n" "" "" 234 235rm fweep 236for i in $(seq 8 3 200) 237do 238 dd if=/dev/zero of=fweep bs=65536 seek=$i count=1 2>/dev/null 239 dd if=/dev/zero of=fweep2 bs=65536 seek=$i count=1 2>/dev/null 240done 241truncate -s 20m fweep2 242 243testing "sparse double overflow" "$TAR --sparse fweep | SUM 7" \ 244 "f1fe57f8313a9d682ec9013a80f3798910b6ff51\n" "" "" 245 246tar c --sparse fweep > fweep.tar 247rm fweep 248testing "sparse extract" "tar xf fweep.tar && $TAR --sparse fweep | SUM 4" \ 249 "38dc57b8b95632a287db843c214b5c96d1cfe415\n" "" "" 250testing "sparse tvf" "tar tvf fweep.tar | grep -wq 13172736 && echo right size"\ 251 "right size\n" "" "" 252rm fweep fweep.tar 253 254tar c --sparse fweep2 > fweep2.tar 255rm fweep2 256testing "sparse extract hole at end" \ 257 "tar xf fweep2.tar && $TAR --sparse fweep2 | SUM 4" \ 258 "791060574c569e5c059e2b90c1961a3575898f97\n" "" "" 259rm fweep2 fweep2.tar 260 261testcmd "longname" "tf $FILES/tar/long_path.tar" \ 262 "$(printf 'long file name%86cTRAILING' ' ' | tr ' ' _)\n" "" "" 263 264mkdir -p links 265touch links/orig 266ln links/{orig,link1} 267ln links/{orig,link2} 268testcmd 'links' '-cf test.tar links' '' '' '' 269rm -rf links 270 271mkdir links 272for i in {0..12}; do touch links/orig$i; ln links/{orig,link}$i; done 273testcmd 'links2' '-cf test.tar links' '' '' '' 274rm -rf links 275 276install -m 000 -d folder/skip/oof && 277testcmd 'exclude' '--exclude skip -cvf tar.tar folder && echo yes' \ 278 'folder/\nyes\n' '' '' 279rm -rf folder tar.tar 280 281mkdir -p one/two; echo hello > one/two/three; tar czf test.tar one/two/three 282rm one/two/three; mkdir one/two/three 283testcmd 'replace dir with file' '-xf test.tar && cat one/two/three' \ 284 'hello\n' '' '' 285rm -rf one test.tar 286 287mkdir ..dotsdir 288testing "create ..dotsdir" "$TAR ..dotsdir | SUM 3" \ 289 "de99091a91c74ef6b90093e9165b413670730572\n" "" "" 290 291testing "pass ..dotsdir" "$TAR ..dotsdir | LST" \ 292 "drwxrwxr-x root/root 0 2009-02-13 23:31 ..dotsdir/\n" "" "" 293rmdir ..dotsdir 294 295mkdir -p one/two/three/four/five 296touch one/two/three/four/five/six 297testing "--strip" "$TAR one | tar t --strip=2 --show-transformed | grep six" \ 298 "three/four/five/six\n" "" "" 299testing "--xform" "$TAR one --xform=s@three/four/@zero@ | tar t | grep six" \ 300 "one/two/zerofive/six\n" "" "" 301rm -rf one 302 303if false 304then 305# Sequencing issues that leak implementation details out the interface 306testing "what order are --xform, --strip, and --exclude processed in?" 307testing "--xform vs ../ removal and adding / to dirs" 308 309chmod 700 dir 310tar cpf tar.tgz dir/file 311#chmod 700 dir 312#tar xpf file 313#ls -ld dir/file 314 315# restore ownership of file, dir, and symlink 316 317# merge add_to_tar and write_longname, 318# filter, incl or excl and anchored/wildcards 319 320# extract file not under cwd 321# exclusion defaults to --no-anchored and --wildcards-match-slash 322# both incl and excl 323 324# catch symlink overwrite 325# add dir with no trailing slash 326# don't allow hardlink target outside cwd 327# extract dir/file without dir in tarball 328# create with and without each flag 329# --owner --group --numeric-owner 330# extract with and without each flag 331# --owner 0 --group 0 332# set symlink owner 333# >256 hardlink inodes 334# // remove leading / and any .. entries from saved name 335# // exclusion defaults to --no-anchored and --wildcards-match-slash 336# //bork blah../thing blah/../thing blah/../and/../that blah/.. ../blah 337# tar tv --owner --group --mtime 338# extract file within dir date correct 339# name ending in /.. or just ".." as a name 340 341 342fi 343 344TZ="$OLDTZ" 345umask $OLDUMASK 346unset LONG TAR SUM OLDUMASK OLDTZ 347unset -f LST 348rm save.dat 349