# libarchive -- ONE reader/writer across tar, cpio, zip, iso9660 and mtree, where # every other archiver on this image speaks exactly one format. bsdtar and # bsdcpio are the two CLIs the ticket names; this file covers bsdtar's core # (which formats and which compressors were actually linked in, and a plain # round-trip), its siblings cover the four compressors (-compress) and the # multi-format surface (-formats). # # THE BACKEND CASES ARE THE POINT, NOT DECORATION. libarchive's PACKAGECONFIG is # a menu of eight optional codecs and this image asks for exactly four -- # `zlib bz2 xz zstd`, the DISTRO_FEATURES filter contributing nothing because # brintos.conf sets DISTRO_FEATURES = "". A configure that silently failed to # find one of the four would still build, still link, and still pass every # uncompressed case below; it would only fail later, on a caller who handed it a # .tar.zst. bsdtar --version names every codec it linked, so the four positive # cases and the lz4 negative assert the recipe's menu selection end to end. The # negative is not symmetry for its own sake: lz4 IS on this image (BRINTOS-165) # and IS a libarchive PACKAGECONFIG option, so it is the one codec that could # plausibly have been picked up by accident. # # Process count, not work, is what costs a suite its 60 s budget here (the lesson # 56-lz4.test learned the hard way and 97-parted.test paid for again), so the # payload is built by a shell loop of printf BUILTINS rather than forked tools, # every output match is a `case` against a string captured once, and the # compressor round-trips live in their own file rather than extending this one. . "$BST_LIB" require bsdtar libarchive/bsdtar-present T=${TMPDIR:-/tmp}/bst-libarchive.$$ rm -rf "$T"; mkdir -p "$T/src/sub" "$T/out" has() { case "$3" in *"$2"*) bst_ok "$1" ;; *) bst_notok "$1" "want '$2' in: $(_bst_1line "$3")" ;; esac; } hasnt(){ case "$3" in *"$2"*) bst_notok "$1" "'$2' is linked in, but this image's PACKAGECONFIG does not ask for it" ;; *) bst_ok "$1" ;; esac; } # ~37 KiB of compressible text, a nested file and a symlink. printf is a busybox # ash builtin, so this whole loop forks nothing. i=0 while [ $i -lt 512 ]; do printf 'the quick brown fox jumps over the lazy dog 0123456789 ABCDEFGHIJKLMNOP\n' i=$((i + 1)) done > "$T/src/compressible.txt" printf 'libarchive fixture\n' > "$T/src/top.txt" printf 'nested payload\n' > "$T/src/sub/nested.txt" ln -s top.txt "$T/src/link" # ------------------------------------------------- the binary loads and reports V=$(bsdtar --version 2>&1) has libarchive/bsdtar-version "bsdtar 3.7.9" "$V" has libarchive/lib-version "libarchive 3.7.9" "$V" # ------------------------------------- the four codecs the PACKAGECONFIG asks for has libarchive/backend-zlib "zlib/" "$V" has libarchive/backend-bz2 "bz2lib/" "$V" has libarchive/backend-xz "liblzma/" "$V" has libarchive/backend-zstd "libzstd/" "$V" hasnt libarchive/backend-no-lz4 "liblz4/" "$V" # ------------------------------------------------------- plain tar round-trip # -C is used everywhere below so each archive costs ONE process rather than a # subshell plus a cd. check libarchive/tar-create bsdtar -C "$T/src" -cf "$T/plain.tar" . LIST=$(bsdtar -tf "$T/plain.tar" 2>&1) has libarchive/tar-list-file "top.txt" "$LIST" has libarchive/tar-list-nested "sub/nested.txt" "$LIST" has libarchive/tar-list-link "link" "$LIST" check libarchive/tar-extract bsdtar -C "$T/out" -xf "$T/plain.tar" check libarchive/tar-roundtrip cmp -s "$T/src/compressible.txt" "$T/out/compressible.txt" check_eq libarchive/tar-nested "nested payload" "$(cat "$T/out/sub/nested.txt" 2>/dev/null)" # A symlink stored as a symlink rather than dereferenced into a second copy is # the cheapest evidence that entry metadata, not just file bytes, survives. check_eq libarchive/tar-symlink "top.txt" "$(readlink "$T/out/link" 2>/dev/null)" # ------------------------------------ reading an archive THIS TOOL DID NOT WRITE # GNU tar holds /bin/tar here -- it declares ALTERNATIVE_PRIORITY 100 against # bsdtar's 80, so this port does NOT displace it and 58-tar.test still describes # the same binary it always did. That leaves two independent implementations on # one image, which is what makes a genuine interop assertion possible: neither # archive below is read by the implementation that produced it. if command -v tar > /dev/null 2>&1; then mkdir -p "$T/gnu-in" "$T/ours-in" check libarchive/interop-gnu-reads-ours tar -C "$T/gnu-in" -xf "$T/plain.tar" check libarchive/interop-gnu-content cmp -s "$T/src/compressible.txt" "$T/gnu-in/compressible.txt" tar -C "$T/src" -cf "$T/gnu.tar" . 2> /dev/null check libarchive/interop-ours-reads-gnu bsdtar -C "$T/ours-in" -xf "$T/gnu.tar" check libarchive/interop-ours-content cmp -s "$T/src/compressible.txt" "$T/ours-in/compressible.txt" else bst_skip libarchive/interop-gnu "GNU tar is not on this image" fi # ------------------------------------------------------------------- controls # Without these a bsdtar that answered plausibly for any input -- or one that # reported success while writing nothing -- would sweep every case above. # # THE JUNK IS NOT /dev/zero, and that distinction is the case's whole content. # A run of zero bytes is a VALID, EMPTY tar: the all-zero 512-byte block IS # tar's end-of-archive marker, so `bsdtar -tf` over zeroes correctly exits 0 and # lists nothing. A control built on zeroes therefore goes red against a working # bsdtar -- which is exactly how the first draft of this case failed, and it # reads as a tar bug rather than as a test bug. The two properties are separated # instead: zeroes must list NOTHING (not "must fail"), and non-archive bytes # must be REJECTED. i=0 while [ $i -lt 256 ]; do printf 'NOT-AN-ARCHIVE-%d-qwertyuiopasdfghjklzxcvbnm\n' "$i" i=$((i + 1)) done > "$T/junk" dd if=/dev/zero of="$T/zeroes" bs=1024 count=64 2> /dev/null Z=$(bsdtar -tf "$T/zeroes" 2>/dev/null) if [ -z "$Z" ]; then bst_ok libarchive/empty-tar-lists-nothing else bst_notok libarchive/empty-tar-lists-nothing "zero bytes listed entries: $(_bst_1line "$Z")" fi if bsdtar -tf "$T/junk" > /dev/null 2>&1; then bst_notok libarchive/reject-junk "bsdtar listed 11 KiB of non-archive text as a valid archive" else bst_ok libarchive/reject-junk fi if bsdtar -tf "$T/absent.tar" > /dev/null 2>&1; then bst_notok libarchive/reject-missing "bsdtar returned 0 on a file that does not exist" else bst_ok libarchive/reject-missing fi rm -rf "$T"