tar.test 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. #!/bin/bash
  2. [ -f testing.sh ] && . testing.sh
  3. #testing "name" "command" "result" "infile" "stdin"
  4. # For reproducibility: TZ=UTC, umask 0002, override ownership and timestamp
  5. export TZ=utc
  6. umask 0002
  7. TAR='tar c --owner root --group sys --mtime @1234567890'
  8. # 255 bytes, longest VFS name
  9. LONG=0123456789abcdef0123456789abcdef
  10. LONG=$LONG$LONG$LONG$LONG$LONG$LONG$LONG$LONG
  11. LONG=${LONG:1:255}
  12. # We check both sha1sum (to ensure binary identical output) and list contents.
  13. # Check hash of first N 512 byte frames to ensure result is binary identical.
  14. function SUM()
  15. {
  16. # Different tars add variable trailing NUL padding (1024 bytes is just
  17. # minimum) so look at first N 512-byte frames when analyzing header content.
  18. tee save.dat | head -c $(($1*512)) | sha1sum | sed "s/ .*//"
  19. }
  20. # List tarball contents, converting variable tabs into one space
  21. function LST()
  22. {
  23. tar tv "$@" | sed 's/[ \t][ \t]*/ /g'
  24. }
  25. # Check that stored empty file is binary identical and decodes as expected.
  26. touch file
  27. testing "store file" "$TAR file | SUM 3" \
  28. "2735f3a18d770dd0d7145d76108532f72bef9927\n" "" ""
  29. testing "pass file" "$TAR file | LST" \
  30. "-rw-rw-r-- root/sys 0 2009-02-13 23:31 file\n" "" ""
  31. # Two files from -T list
  32. touch file1 file2
  33. testing "-T newline" "$TAR -T input | LST" \
  34. "-rw-rw-r-- root/sys 0 2009-02-13 23:31 file1\n-rw-rw-r-- root/sys 0 2009-02-13 23:31 file2\n" "file1\nfile2\n" ""
  35. testing "-T null" "$TAR --null -T input | LST" \
  36. "-rw-rw-r-- root/sys 0 2009-02-13 23:31 file1\n-rw-rw-r-- root/sys 0 2009-02-13 23:31 file2\n" "file1\0file2\0" ""
  37. # User "root" is UID 0 and group "sys" is GID 3 (on Linux, BSD, and Mac),
  38. # inherited from Bell Labs Unix v7
  39. # Note: testing both "tar c" and "tar -c" here.
  40. testing "specify UID, fetch GID" "tar -c --owner nobody:65534 --group sys --mtime @0 file | LST" \
  41. "-rw-rw-r-- nobody/sys 0 1970-01-01 00:00 file\n" "" ""
  42. testing "fetch UID, specify GID" "tar c --owner root --group nobody:65534 --mtime @0 file | LST" \
  43. "-rw-rw-r-- root/nobody 0 1970-01-01 00:00 file\n" "" ""
  44. # Large values switch from ascii numbers to a binary format.
  45. testing "huge values" "tar c --owner 9999999 --group 8888888 --mtime @0 file | SUM 3" \
  46. "396b07fd2f80eeb312462e3bfb7dc1325dc6bcfb\n" "" ""
  47. testcmd "longname" "tf $FILES/tar/long_path.tar" \
  48. "$(printf 'long file name%86cTRAILING' ' ' | tr ' ' _)\n" "" ""
  49. touch -t 198701231234.56 file
  50. testing "pass mtime" \
  51. "tar c --owner root --group sys file | LST --full-time" \
  52. "-rw-rw-r-- root/sys 0 1987-01-23 12:34:56 file\n" "" ""
  53. testing "adjust mode" \
  54. "tar c --owner root --group sys --mode a+x file | LST --full-time" \
  55. "-rwxrwxr-x root/sys 0 1987-01-23 12:34:56 file\n" "" ""
  56. mkdir dir
  57. testing "store dir" "$TAR dir | SUM 3" \
  58. "85add1060cfe831ca0cdc945158efe6db485b81e\n" "" ""
  59. testing "pass dir" "$TAR dir | LST" \
  60. "drwxrwxr-x root/sys 0 2009-02-13 23:31 dir/\n" "" ""
  61. # note: does _not_ include dir entry in archive, just file
  62. touch dir/file
  63. testing "store file in dir" "$TAR dir/file | SUM 3" \
  64. "d9e7fb3884430d29e7eed0dc04a2593dd260df14\n" "" ""
  65. # Test recursion with one file so filesystem sort order can't change result
  66. testing "store dir and dir/file" "$TAR dir | SUM 3" \
  67. "a4e35f87e28c4565b60ba01dbe79e431914f8788\n" "" ""
  68. testing "pass dir/file" "$TAR dir | LST" \
  69. "drwxrwxr-x root/sys 0 2009-02-13 23:31 dir/\n-rw-rw-r-- root/sys 0 2009-02-13 23:31 dir/file\n" "" ""
  70. echo boing > dir/that
  71. testing "tar C" "$TAR -C dir that | SUM 3" \
  72. "d469d4bc06def2d8808400ba30025ca295d05e4f\n" "" ""
  73. ln dir/file dir/hardlink
  74. testing "store hardlink" "$TAR dir/file dir/hardlink | SUM 3" \
  75. "519de8abd1b32debd495a0fc1d96082184abbdcc\n" "" ""
  76. skipnot mkfifo dir/fifo 2>/dev/null
  77. testing "create dir/fifo" "$TAR dir/fifo | SUM 3" \
  78. "cad477bd0fc5173d0a43f4774f514035456960e6\n" "" ""
  79. # test L and K records
  80. # 4+96=100 (biggest short name), 4+97=101 (shortest long name)
  81. touch dir/${LONG:1:96} dir/${LONG:1:97}
  82. testing "create long fname" "$TAR dir/${LONG:1:97} dir/${LONG:1:96} | SUM 3" \
  83. "d70018505fa5df19ae73498cfc74d0281601e42e\n" "" ""
  84. # MacOS X has different symlink permissions, skip these tests there
  85. [ "$(uname)" == Darwin ] && SKIP=999
  86. # / and .. only stripped from name, not symlink target.
  87. ln -s ../name.././.. dir/link
  88. testing "create symlink" "$TAR dir/link | SUM 3" \
  89. "f841bf9d757c655c5d37f30be62acb7ae24f433c\n" "" ""
  90. ln dir/link dir/hlink
  91. testing "create hardlink to symlink" "$TAR dir/link dir/hlink | SUM 3" \
  92. "de571a6dbf09e1485e513ad13a178b1729267452\n" "" ""
  93. ln -s dir/${LONG:1:96} dir/lshort
  94. ln -s dir/${LONG:1:97} dir/llong
  95. testing "create long symlink" "$TAR dir/lshort dir/llong | SUM 3" \
  96. "07eaf397634b5443dbf2d3ec38a4302150fcfe82\n" "" ""
  97. ln -s $LONG dir/${LONG:5}
  98. testing "create long->long" "$TAR dir/${LONG:5} | SUM 7" \
  99. "b9e24f53e27496c5125445230d201b4a36ff7398\n" "" ""
  100. # absolute and relative link names, broken and not
  101. ln -s file dir/linkok
  102. testing "create symlink" "$TAR dir/linkok | SUM 3" \
  103. "f5669cfd179ddcdd5ca9f8a1561a99e11e0a08b1\n" "" ""
  104. SKIP=0 # End of tests that don't match MacOS symlink permissions
  105. symlink_perms=lrwxrwxrwx
  106. [ "$(uname)" == "Darwin" ] && symlink_perms=lrwxrwxr-x
  107. ln -s /dev/null dir/linknull
  108. testing "pass absolute symlink" "$TAR dir/linknull | LST" \
  109. "$symlink_perms root/sys 0 2009-02-13 23:31 dir/linknull -> /dev/null\n" "" ""
  110. ln -s rel/broken dir/relbrok
  111. testing "pass broken symlink" "$TAR dir/relbrok | LST" \
  112. "$symlink_perms root/sys 0 2009-02-13 23:31 dir/relbrok -> rel/broken\n" "" ""
  113. ln -s /does/not/exist dir/linkabsbrok
  114. testing "pass broken absolute symlink" "$TAR dir/linkabsbrok | LST" \
  115. "$symlink_perms root/sys 0 2009-02-13 23:31 dir/linkabsbrok -> /does/not/exist\n" \
  116. "" ""
  117. nulldev=1,3 # devtmpfs values
  118. [ "$(uname)" == "Darwin" ] && nulldev=3,2
  119. testing "pass /dev/null" \
  120. "tar c --mtime @0 --group sys /dev/null 2>/dev/null | LST" \
  121. "crw-rw-rw- root/sys $nulldev 1970-01-01 00:00 dev/null\n" "" ""
  122. testing "--absolute-names" \
  123. "tar c --mtime @0 --group sys --absolute-names /dev/null 2>/dev/null | LST" \
  124. "crw-rw-rw- root/sys $nulldev 1970-01-01 00:00 /dev/null\n" "" ""
  125. # compression types
  126. testing "autodetect gzip" 'LST -f "$FILES"/tar/tar.tgz' \
  127. "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" \
  128. "" ""
  129. testing "manually specify bz2" 'LST -jf "$FILES"/tar/tar.tbz2' \
  130. "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" \
  131. "" ""
  132. # -I
  133. testing "-I gzip c" "$TAR -Igzip file | file - | grep -o 'gzip compressed'" \
  134. "gzip compressed\n" "" ""
  135. testing "-I gzip t" 'LST -Igzip -f "$FILES"/tar/tar.tgz' \
  136. "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" \
  137. "" ""
  138. skipnot mknod -m 660 dir/char c 12 34 2>/dev/null && chgrp sys dir/char
  139. NOSPACE=1 testing "character special" "tar --mtime @0 -cf test.tar dir/char && rm -f dir/char && tar xf test.tar && ls -l --full-time dir/char" \
  140. "crw-rw---- 1 root sys 12, 34 1970-01-01 00:00:00.000000000 +0000 dir/char\n"\
  141. "" ""
  142. skipnot mknod -m 660 dir/block b 23 45 2>/dev/null && chgrp sys dir/block
  143. NOSPACE=1 testing "block special" "tar --mtime @0 -cf test.tar dir/block && rm -f dir/block && tar xf test.tar && ls -l --full-time dir/block" \
  144. "brw-rw---- 1 root sys 23, 45 1970-01-01 00:00:00.000000000 +0000 dir/block\n"\
  145. "" ""
  146. skipnot chown nobody:nogroup dir/file 2>/dev/null
  147. testing "ownership" "$TAR dir/file | SUM 3" \
  148. "2d7b96c7025987215f5a41f10eaa84311160afdb\n" "" ""
  149. mkdir -p dd/sub/blah &&
  150. tar cf test.tar dd/sub/blah &&
  151. rm -rf dd/sub &&
  152. skipnot ln -s ../.. dd/sub
  153. toyonly testing "symlink out of cwd" \
  154. "tar xf test.tar 2> /dev/null || echo yes ; [ ! -e dd/sub/blah ] && echo yes" \
  155. "yes\nyes\n" "" ""
  156. # If not root can't preserve ownership, so don't try yet.
  157. testing "extract dir/file from tar" \
  158. "tar xvCf dd $FILES/tar/tar.tar && stat -c '%A %Y %n' dd/dir dd/dir/file" \
  159. "dir/\ndir/file\ndrwxr-x--- 1494637555 dd/dir\n-rw-r----- 1494637555 dd/dir/file\n" \
  160. "" ""
  161. testing "extract dir/file from tgz (autodetect)" \
  162. "tar xvCf dd $FILES/tar/tar.tgz && stat -c '%A %Y %n' dd/dir dd/dir/file" \
  163. "dir/\ndir/file\ndrwxr-x--- 1494637555 dd/dir\n-rw-r----- 1494637555 dd/dir/file\n" \
  164. "" ""
  165. toyonly testing "cat tgz | extract dir/file (autodetect)" \
  166. "cat $FILES/tar/tar.tgz | tar xvC dd && stat -c '%A %Y %n' dd/dir dd/dir/file" \
  167. "dir/\ndir/file\ndrwxr-x--- 1494637555 dd/dir\n-rw-r----- 1494637555 dd/dir/file\n" \
  168. "" ""
  169. testing "extract dir/file from tbz2 (autodetect)" \
  170. "tar xvCf dd $FILES/tar/tar.tbz2 && stat -c '%A %Y %n' dd/dir dd/dir/file" \
  171. "dir/\ndir/file\ndrwxr-x--- 1494637555 dd/dir\n-rw-r----- 1494637555 dd/dir/file\n" \
  172. "" ""
  173. toyonly testing "cat tbz | extract dir/file (autodetect)" \
  174. "cat $FILES/tar/tar.tbz2 | tar xvC dd && stat -c '%A %Y %n' dd/dir dd/dir/file" \
  175. "dir/\ndir/file\ndrwxr-x--- 1494637555 dd/dir\n-rw-r----- 1494637555 dd/dir/file\n" \
  176. "" ""
  177. mkdir path && ln -s "$(which gzip)" "$(which tar)" path/ && [ -x path/gzip ] ||
  178. ((++SKIP))
  179. toyonly testing "autodetect falls back to gzip -d when no zcat" \
  180. "PATH=path; tar tf $FILES/tar/tar.tgz" "dir/\ndir/file\n" "" ""
  181. rm -rf path
  182. # Tests that don't produce the same results on MacOS X as Linux
  183. [ "$(uname)" == Darwin ] && SKIP=999
  184. yes | head -n $((1<<18)) > bang
  185. {
  186. dd bs=$((1<<16)) count=1 status=none
  187. dd bs=8192 seek=14 count=1 status=none
  188. dd bs=4096 seek=64 count=5 status=none
  189. } < bang > fweep
  190. testing "sparse without overflow" "$TAR --sparse fweep | SUM 3" \
  191. "50dc56c3c7eed163f0f37c0cfc2562852a612ad0\n" "" ""
  192. rm bang fweep
  193. for i in 1 3 5 7 9 14 27 36 128 256 300 304
  194. do
  195. dd if=/dev/zero of=fweep bs=65536 seek=$i count=1 2>/dev/null
  196. done
  197. testing "sparse single overflow" "$TAR --sparse fweep | SUM 6" \
  198. "81d59c3a7470201f92d60e63a43318ddde893f6d\n" "" ""
  199. rm fweep
  200. for i in $(seq 8 3 200)
  201. do
  202. dd if=/dev/zero of=fweep bs=65536 seek=$i count=1 2>/dev/null
  203. dd if=/dev/zero of=fweep2 bs=65536 seek=$i count=1 2>/dev/null
  204. done
  205. truncate -s 20m fweep2
  206. testing "sparse double overflow" "$TAR --sparse fweep | SUM 7" \
  207. "024aacd955e45f89bafedb3f37c8d39b4d556471\n" "" ""
  208. tar c --sparse fweep > fweep.tar
  209. rm fweep
  210. testing "sparse extract" "tar xf fweep.tar && $TAR --sparse fweep | SUM 4" \
  211. "b949d3a3b4c6457c873f1ea9918fd9029c5ed4b3\n" "" ""
  212. testing "sparse tvf" \
  213. "tar tvf fweep.tar | grep -wq 13172736 && echo right size" "right size\n" \
  214. "" ""
  215. rm fweep fweep.tar
  216. tar c --sparse fweep2 > fweep2.tar
  217. rm fweep2
  218. testing "sparse extract hole at end" \
  219. "tar xf fweep2.tar && $TAR --sparse fweep2 | SUM 4" \
  220. "807664bcad0e827793318ff742991d6f006b2127\n" "" ""
  221. rm fweep2 fweep2.tar
  222. SKIP=0 # End of tests that don't work on MacOS X
  223. mkdir -p links
  224. touch links/orig
  225. ln links/{orig,link1}
  226. ln links/{orig,link2}
  227. testcmd 'links' '-cf test.tar links' '' '' ''
  228. rm -rf links
  229. mkdir links
  230. for i in {0..12}; do touch links/orig$i; ln links/{orig,link}$i; done
  231. testcmd 'links2' '-cf test.tar links' '' '' ''
  232. rm -rf links
  233. install -m 000 -d folder/skip/oof &&
  234. testcmd 'exclude' '--exclude skip -cvf tar.tar folder && echo yes' \
  235. 'folder/\nyes\n' '' ''
  236. rm -rf folder tar.tar
  237. mkdir -p one/two; echo hello > one/two/three; tar czf test.tar one/two/three
  238. rm one/two/three; mkdir one/two/three
  239. testcmd 'replace dir with file' '-xf test.tar && cat one/two/three' \
  240. 'hello\n' '' ''
  241. rm -rf one test.tar
  242. mkdir ..dotsdir
  243. testing "create ..dotsdir" "$TAR ..dotsdir | SUM 3" \
  244. "62ff23c9b427020331992b9bc71f082099c1411f\n" "" ""
  245. testing "pass ..dotsdir" "$TAR ..dotsdir | LST" \
  246. "drwxrwxr-x root/sys 0 2009-02-13 23:31 ..dotsdir/\n" "" ""
  247. rmdir ..dotsdir
  248. mkdir -p one/two/three/four/five
  249. touch one/two/three/four/five/six
  250. testing "--strip" "$TAR one | tar t --strip=2 --show-transformed | grep six" \
  251. "three/four/five/six\n" "" ""
  252. # toybox tar --xform depends on toybox sed
  253. [ -z "$TEST_HOST" ] && ! sed --tarxform '' </dev/null 2>/dev/null && SKIP=99
  254. mkdir uno
  255. ln -s tres uno/dos
  256. touch uno/tres
  257. ln uno/tres uno/quatro
  258. tt() { $TAR --no-recursion uno uno/{dos,tres,quatro} "$@" | \
  259. LST --show-transformed-names $XX | sed 's/^.* 23:31 //'; }
  260. testing 'xform S' \
  261. "tt --xform 's/uno/one/S;s/dos/two/S;s/tres/three/S;s/quatro/four/S'" \
  262. "one/\none/two -> tres\none/three\none/four link to one/three\n" "" ""
  263. testing 'xform flags=rh starts with all disabled' \
  264. "tt --xform 's/uno/one/;flags=rh;s/dos/two/;s/tres/three/;s/quatro/four/'" \
  265. "one/\none/two -> tres\none/three\none/four link to one/three\n" "" ""
  266. testing 'xform flags=rHhsS toggles' \
  267. "tt --xform 's/uno/one/;flags=rHhsS;s/dos/two/;s/tres/three/;s/quatro/four/'"\
  268. "one/\none/two -> tres\none/three\none/four link to one/three\n" "" ""
  269. testing 'xform flags= is not a delta from previous' \
  270. "tt --xform 'flags=s;flags=rh;s/uno/one/;s/dos/two/;s/tres/three/;s/quatro/four/'" \
  271. "one/\none/two -> tres\none/three\none/four link to one/three\n" "" ""
  272. testing 'xform H' \
  273. "tt --xform 'flags=rsH;s/uno/one/;s/dos/two/;s/tres/three/;s/quatro/four/'" \
  274. "one/\none/two -> three\none/three\none/four link to uno/tres\n" "" ""
  275. testing 'xform R' \
  276. "tt --xform 'flags=rshR;s/uno/one/;s/dos/two/;s/tres/three/;s/quatro/four/'" \
  277. "uno/\nuno/dos -> three\nuno/tres\nuno/quatro link to one/three\n" "" ""
  278. testing "xform path" "$TAR one --xform=s@three/four/@zero@ | tar t | grep six" \
  279. "one/two/zerofive/six\n" "" ""
  280. testing "xform trailing slash special case" \
  281. "$TAR --xform 's#^.+/##x' one/two/three/four/five | tar t" 'five/\nsix\n' '' ''
  282. # The quoting works because default IFS splits on whitepace not ;
  283. testing "xform extract all" \
  284. "XX='--xform s/uno/one/;s/dos/two/;s/tres/three/;s/quatro/four/' tt" \
  285. 'one/\none/two -> three\none/three\none/four link to one/three\n' '' ''
  286. testing 'xform extract S' \
  287. "XX='--xform s/uno/one/S;s/dos/two/S;s/tres/three/S;s/quatro/four/S' tt" \
  288. "one/\none/two -> tres\none/three\none/four link to one/three\n" "" ""
  289. testing 'xform extract H' \
  290. "XX='--xform flags=rs;s/uno/one/;s/dos/two/;s/tres/three/;s/quatro/four/' tt"\
  291. "one/\none/two -> three\none/three\none/four link to uno/tres\n" "" ""
  292. testing 'xform extract R' \
  293. "XX='--xform flags=sh;s/uno/one/;s/dos/two/;s/tres/three/;s/quatro/four/' tt"\
  294. "uno/\nuno/dos -> three\nuno/tres\nuno/quatro link to one/three\n" "" ""
  295. rm -rf uno
  296. SKIP=0
  297. rm -rf one
  298. testing '-P' "$TAR -P --no-recursion -C / /// .. | SUM 3" \
  299. "a3e94211582da121845d823374d8f41ead62d7bd\n" "" ""
  300. testing 'without -P' "$TAR --no-recursion -C / /// .. 2>/dev/null | SUM 3" \
  301. "077d03243e247b074806904885e6da272fd5857a\n" "" ""
  302. if false
  303. then
  304. # Sequencing issues that leak implementation details out the interface
  305. testing "what order are --xform, --strip, and --exclude processed in?"
  306. testing "--xform vs ../ removal and adding / to dirs"
  307. chmod 700 dir
  308. tar cpf tar.tgz dir/file
  309. #chmod 700 dir
  310. #tar xpf file
  311. #ls -ld dir/file
  312. # restore ownership of file, dir, and symlink
  313. # merge add_to_tar and write_longname,
  314. # filter, incl or excl and anchored/wildcards
  315. # extract file not under cwd
  316. # exclusion defaults to --no-anchored and --wildcards-match-slash
  317. # both incl and excl
  318. # catch symlink overwrite
  319. # add dir with no trailing slash
  320. # don't allow hardlink target outside cwd
  321. # extract dir/file without dir in tarball
  322. # create with and without each flag
  323. # --owner --group --numeric-owner
  324. # extract with and without each flag
  325. # --owner 0 --group 0
  326. # set symlink owner
  327. # >256 hardlink inodes
  328. # // remove leading / and any .. entries from saved name
  329. # // exclusion defaults to --no-anchored and --wildcards-match-slash
  330. # //bork blah../thing blah/../thing blah/../and/../that blah/.. ../blah
  331. # tar tv --owner --group --mtime
  332. # extract file within dir date correct
  333. # name ending in /.. or just ".." as a name
  334. fi
  335. rm -f save.dat