#!/usr/bin/env bash # Validate the exported tar, then corrupt disposable copies to test rejection. source "$(dirname -- "${BASH_SOURCE[0]}")/../../tools/lib.sh" cd "$FDS_ROOT" [[ -f out/rootfs-aarch64.tar ]] || die 'Run make rootfs PROFILE=cli first' scratch=$(mktemp -d "$FDS_ROOT/out/m1-checks.XXXXXX") trap 'rm -rf -- "$scratch"' EXIT build=$(dirname -- "$(realpath out/rootfs-aarch64.tar)") ( cd "$build" sha256sum -c rootfs.sha256 packages.sha256 ) python3 - "$build" <<'PY' import json import pathlib import struct import sys import tarfile build = pathlib.Path(sys.argv[1]) metadata = json.loads((build / 'archive-metadata.json').read_text()) with tarfile.open(build / 'rootfs-aarch64.tar') as archive: members = {member.name: member for member in archive} assert members['.'].isdir() and (members['.'].uid, members['.'].gid, members['.'].mode) == (0, 0, 0o755), 'Incorrect root directory metadata' assert members.keys() == metadata.keys(), 'Archive member mismatch' for name, member in members.items(): assert not name.startswith('/') and '..' not in pathlib.PurePosixPath(name).parts assert not (member.ischr() or member.isblk()), name if member.isfifo(): assert name.startswith('etc/s6-linux-init/current/run-image/'), name expected = metadata[name] assert (member.uid, member.gid, member.mode) == (expected['uid'], expected['gid'], int(expected['mode'], 8)), name for name in ('usr/bin/wall', 'usr/bin/write'): if name in members: assert (members[name].uid, members[name].gid, members[name].mode) == (0, 5, 0o2755), name assert (members['usr/lib/utempter/utempter'].uid, members['usr/lib/utempter/utempter'].gid, members['usr/lib/utempter/utempter'].mode) == (0, 14, 0o2711), 'Incorrect utempter group restoration' assert members['etc/shadow'].mode == 0o600 assert members['tmp'].mode == 0o1777 assert members['root'].mode == 0o700 assert (members['usr/bin/xbps-uchroot'].uid, members['usr/bin/xbps-uchroot'].gid, members['usr/bin/xbps-uchroot'].mode) == (0, 101, 0o4750) assert members['bin'].linkname == 'usr/bin' capability = members['usr/bin/iputils-ping'].pax_headers['SCHILY.xattr.security.capability'].encode('utf-8', 'surrogateescape') assert len(capability) == 20 and struct.unpack_from('> 24 == 2 assert struct.unpack_from('> 24 == 3 assert struct.unpack_from('"$scratch/rejection.log" 2>&1; then die 'Unimplemented profile was accepted' fi grep -q 'Supported profiles: cli, development' "$scratch/rejection.log" printf 'PASS: rejects unimplemented image profile\n' printf 'NOTE: run make init-test separately for native PID 1 and full ARM boot checks\n' printf 'SKIP: physical Pi/monitor tests and boot timings require hardware\n' printf 'PASS: exported-rootfs acceptance and failure-path checks\n'