. "$BST_LIB" # eject 2.1.5 (meta-oe recipes-support) — the removable-media ejector and its # companion volname. Neither busybox nor toybox ships an eject applet on this # image (CONFIG_EJECT is not set in poky's busybox defconfig), so a bare `eject` # already is this port and the update-alternatives registration at priority 100 # is uncontested. # # THE SHAPE OF THIS SUITE IS DECIDED BY ONE FACT: this kernel has NO BLOCK LAYER # (CONFIG_BLOCK is not set) — no /proc/partitions, no /sys/block, no # block-special node anywhere in /dev. eject accepts a device only if stat(2) # says S_ISBLK, so on this machine NO argument can ever reach the ioctls. That # is a property of a browser machine whose only storage is the virtiofs cloud # rootfs, not a defect. So the suite covers, for real, everything upstream of # the ioctl — the option parser, the compiled-in default device, the /etc/mtab # and /etc/fstab readers, the block-device gate — and gates the device cases on # a RUNTIME probe, so they run the real assertion the day a block device exists # instead of reporting a stale skip. # # volname is the half that DOES run end to end here: it never checks S_ISBLK, it # just opens its argument, seeks to 32808 and reads 32 bytes — the ISO9660 # primary-volume-descriptor volume-identifier field — so a synthetic file # exercises the whole program on this target. # An installed eject.eject with no /usr/bin/eject means update-alternatives did # not run. That is a failure, not an absence, so say so rather than let # `require` turn it into a quiet skip. if ! command -v eject >/dev/null 2>&1 && [ -x /usr/bin/eject.eject ]; then bst_notok eject/alternative "eject.eject is installed but /usr/bin/eject does not resolve" exit 0 fi require eject eject/present tmp=${TMPDIR:-/tmp}/bst-eject.$$ out=$tmp.out; reg=$tmp.reg; iso=$tmp.iso # Runtime probe for the block layer — the gate for the device cases below. blkdev="" for d in /dev/*; do if [ -b "$d" ]; then blkdev="$d"; break; fi done # ---------------------------------------------------------------- identity --- check_out eject/version "eject version 2.1.5 by Jeff Tranter" eject -V check_out eject/version-long "eject version 2.1.5" eject --version # -h exits 0 here: meta-oe's eject-2.1.5-error-return.patch drops upstream's # exit(1) from usage(), so --help is a success path and not an error one. check_rc eject/help-rc 0 sh -c "eject -h > '$out' 2>&1" check_out eject/help-banner "Eject version 2.1.5 by Jeff Tranter" cat "$out" check_out eject/help-usage "eject [-vnrsfqpm] []" cat "$out" check_out eject/help-default "If omitted, name defaults to \`cdrom'." cat "$out" check_out eject/help-longopt "-T --traytoggle" cat "$out" # update-alternatives owns both names; the real binaries carry the .eject suffix. check_out eject/alternative "eject.eject" readlink /usr/bin/eject check_out eject/volname-alternative "volname.eject" readlink /usr/bin/volname # -d reports the device compiled into the binary without opening anything, so it # is the one device-related case that succeeds on a machine with no devices. check_rc eject/default-rc 0 sh -c "eject -d > '$out' 2>&1" check_out eject/default-name "default device: \`cdrom'" cat "$out" # ---------------------------------------------------------- option parsing --- check_rc eject/badopt-rc 1 sh -c "eject -Z > '$out' 2>&1" check_out eject/badopt-msg "invalid option" cat "$out" check_rc eject/missing-arg-rc 1 sh -c "eject -a > '$out' 2>&1" check_out eject/missing-arg-msg "option requires an argument" cat "$out" # -a takes on|off|1|0 and validates the word itself, which is eject's own check # rather than getopt's — a different code path from the two above. check_rc eject/auto-badarg-rc 1 sh -c "eject -a bogus /dev/nosuchdev0 > '$out' 2>&1" check_out eject/auto-badarg-msg "invalid argument to --auto/-a option" cat "$out" # ------------------------------------------------------- device resolution --- # A name that resolves to nothing at all: FindDevice tries the name, /dev/, # /media/ and /mnt/, exhausts them, and reports the original name. check_rc eject/enoent-rc 1 sh -c "eject -n /dev/nosuchdev0 > '$out' 2>&1" check_out eject/enoent-msg "unable to find or open device for: \`/dev/nosuchdev0'" cat "$out" # With no name at all it falls back to the compiled-in default, which proves the # default is actually USED and not merely printed by -d. check_rc eject/nodefaultdev-rc 1 sh -c "eject > '$out' 2>&1" check_out eject/nodefaultdev-msg "unable to find or open device for: \`cdrom'" cat "$out" # An existing path that is not block-special is rejected by the S_ISBLK gate, # with a different diagnostic from the not-found one above. This is the case # that will change the day this kernel grows a block layer. : > "$reg" check_rc eject/notblock-rc 1 sh -c "eject -n '$reg' > '$out' 2>&1" check_out eject/notblock-msg "as device name but it is no block device" cat "$out" # Every action option funnels through the same resolution, so one of them stands # for the rest: none can reach an ioctl on this machine. check_rc eject/listspeed-rc 1 sh -c "eject -X /dev/nosuchdev0 > '$out' 2>&1" check_out eject/listspeed-msg "unable to find or open device for" cat "$out" # ------------------------------------------- the mount-table readers DO run --- # Given a MOUNT POINT, eject looks it up in the mount table and reports the # device mounted there. Deriving the expected device name from /proc/mounts at # runtime makes this a comparison against the file eject read, not a constant. procdev=$(awk '$2 == "/proc" { print $1; exit }' /proc/mounts 2>/dev/null) if [ -n "$procdev" ]; then # -p reads /proc/mounts directly. sh -c "eject -n -p /proc > '$out' 2>&1" check_out eject/procmounts-dev "tried to use \`$procdev' as device name" cat "$out" # -v states the resolution it made — the direct evidence that the parse ran # and matched, rather than that the name happened to fail somewhere. sh -c "eject -n -p -v /proc > '$out' 2>&1" check_out eject/procmounts-verbose "\`$procdev' is mounted at \`/proc'" cat "$out" # ...and WITHOUT -p it reads /etc/mtab, which on this image is a symlink to # ../proc/mounts. Same answer through a different path, so this case is what # would catch that symlink going missing. sh -c "eject -n -v /proc > '$out' 2>&1" check_out eject/mtab-verbose "\`$procdev' is mounted at \`/proc'" cat "$out" else bst_notok eject/procmounts-dev "no /proc entry in /proc/mounts — cannot exercise the mount-table reader" fi # /etc/mtab must be the kernel's mount table for the default (no -p) path above # to work at all. Both spellings a distro uses are accepted; what is asserted is # that it is a link INTO /proc and not a stale regular file. mtablink=$(readlink /etc/mtab 2>/dev/null) case "$mtablink" in *proc/mounts|*proc/self/mounts) bst_ok eject/mtab-symlink ;; *) bst_notok eject/mtab-symlink "/etc/mtab is not a link to the kernel mount table: '$mtablink'" ;; esac # For a path that is neither mounted nor in /etc/fstab, -v reports both negative # answers — which is how the fstab reader (MountableDevice) is covered at all, # since nothing here is mountable. sh -c "eject -n -v '$reg' > '$out' 2>&1" check_out eject/not-mounted "is not mounted" cat "$out" check_out eject/not-mountpoint "is not a mount point" cat "$out" # ------------------------------------------------------------------ volname --- # volname does no S_ISBLK check: it opens the path, seeks to 32808 and reads 32 # bytes. 32808 is sector 16 (the ISO9660 primary volume descriptor) + 40, the # volume-identifier field — so this file is a real PVD volume-id placement even # though it is not a whole filesystem. The decoy at offset 0 is what makes this # an assertion about the OFFSET and not merely about reading the file. label='BRINTOS-WASM32-SELFTEST-VOLUME ' decoy='DECOY-AT-OFFSET-ZERO-NOT-THE-VOLID' { printf '%s' "$decoy"; dd if=/dev/zero bs=32774 count=1 2>/dev/null; printf '%s' "$label"; } > "$iso" isosize=$(wc -c < "$iso" 2>/dev/null | tr -d ' ') if [ "$isosize" != "32840" ]; then bst_notok volname/fixture "synthetic ISO fixture is $isosize bytes, want 32840" else bst_ok volname/fixture vout=$(volname "$iso" 2>&1); vrc=$? check_eq volname/iso-rc 0 "$vrc" check_out volname/iso-label "BRINTOS-WASM32-SELFTEST-VOLUME" printf '%s\n' "$vout" case "$vout" in *DECOY*) bst_notok volname/iso-offset "read offset 0, not 32808: $(_bst_1line "$vout")" ;; *) bst_ok volname/iso-offset ;; esac fi check_rc volname/enoent-rc 1 sh -c "volname /dev/nosuchdev0 > '$out' 2>&1" check_out volname/enoent-msg "No such file or directory" cat "$out" check_rc volname/usage-rc 1 sh -c "volname a b c > '$out' 2>&1" check_out volname/usage-msg "usage: volname []" cat "$out" # ------------------------------------------------- block-layer-gated cases --- # These run the real assertion the moment a block device exists. if [ -n "$blkdev" ]; then # Do NOT pin the reported name to the argument: eject walks the symlink # chain (SymLink(), up to ld hops) and reports the name it resolved to, so # /dev/dm-0 comes back as /dev/mapper/-. What is asserted is that a # block-special argument reaches the -n report at all and exits 0. bout=$(eject -n "$blkdev" 2>&1); brc=$? check_eq eject/blockdev-rc 0 "$brc" check_out eject/blockdev-noop "device is \`" printf '%s\n' "$bout" else bst_skip eject/blockdev-noop "no block layer on this kernel (CONFIG_BLOCK not set): no /proc/partitions, no /sys/block, no block-special node in /dev — eject's S_ISBLK gate can never be satisfied here" bst_skip eject/blockdev-rc "same: eject cannot reach an ioctl without a block-special device" fi # eject unmounts a mounted device by forking /bin/umount before ejecting it. # That path needs a device that is BOTH block-special and mounted, so it is # unreachable here for the same reason, and is reported rather than omitted. bst_skip eject/unmount-fork "eject's fork(2)+exec umount path needs a mounted BLOCK device; this kernel has no block layer, so it cannot be reached from this image" rm -f "$out" "$reg" "$iso" 2>/dev/null