#!/usr/bin/sh set -e # dash shell does not have "{varname}>&1" feature that bash shell has # for auto-assignment of new filedescriptors. # It is cumbersome to write the 'eval' to use our own variables in redirections. # Therefore use fixed numbers. export fd_result=3 # file descriptor for external results export fd_logger=9 # file descriptor for input to logger . /usr/share/os-prober/common.sh newns "$@" require_tmpdir log_output () { if type log-output >/dev/null 2>&1; then log-output -t os-prober --pass-stdout $@ else $@ fi } : >"$OS_PROBER_TMP/dmraid-map" DMRAID=$(type dmraid >/dev/null 2>&1 || true) if [ "$DMRAID" ]; then dmraid -r -c >"$OS_PROBER_TMP/dmraid-map" fi on_sataraid () { local parent="${1%/*}" local device="/dev/${parent##*/}" if grep -q "$device" "$OS_PROBER_TMP/dmraid-map"; then return 0 fi return 1 } partitions () { os_name="$(uname -s)" # Exclude partitions that have whole_disk sysfs attribute set. if [ -d /sys/block ]; then # Exclude partitions on physical disks that are part of a # Serial ATA RAID disk. for part in /sys/block/*/*[0-9]; do if [ -f "$part/start" ] && \ [ ! -f "$part/whole_disk" ] && ! on_sataraid $part; then name="$(echo "${part##*/}" | sed 's,[!.],/,g')" if [ -e "/dev/$name" ]; then echo "/dev/$name" fi fi done # Add Serial ATA RAID devices if type dmraid >/dev/null 2>&1 && \ dmraid -s -c >/dev/null 2>&1; then for raidset in $(dmraid -sa -c); do for part in /dev/mapper/"$raidset"*[0-9]; do echo "$part" done done fi elif [ "$os_name" = Linux ]; then echo "Cannot find list of partitions! (Try mounting /sys.)" >&2 exit 1 elif [ "$os_name" = GNU ]; then for part in /dev/hd*s*[0-9] /dev/sd*s*[0-9]; do if [ -s "$part" ]; then echo "$part" fi done else # We don't know how to probe OSes on non-Linux and non-GNU kernels. # For now, just don't get in the way. exit 0 fi # Add MD RAID devices if [ -f /proc/mdstat ] ; then awk '/^md/ {printf "/dev/"$1"\n"}' /proc/mdstat fi # Also detect OSes on LVM volumes (assumes LVM is active) if type lvs >/dev/null 2>&1; then echo "$(LVM_SUPPRESS_FD_WARNINGS=1 log_output lvs --noheadings --separator : -o vg_name,lv_name 2>/dev/null | sed "s|-|--|g;s|^[[:space:]]*\(.*\):\(.*\)$|/dev/mapper/\1-\2|")" fi # now lets make sure we got all of the btrfs partitions and disks blkid | grep 'TYPE="btrfs"' | cut -d ':' -f 1 } parse_proc_swaps () { while read line; do set -f set -- $line set +f echo "$(mapdevfs $1) swap" done } parse_proc_mdstat () { if type udevadm >/dev/null 2>&1; then udevinfo () { udevadm info "$@" } fi while read line; do for word in $line; do dev="${word%%\[*}" # TODO: factor this out to something in di-utils if # it's needed elsewhere if [ -d /sys/block ] && type udevinfo >/dev/null 2>&1; then if ! udevinfo -q path -n "/dev/$dev" 2>/dev/null | \ grep -q '/.*/.*/'; then continue fi elif ! echo "$dev" | grep -q "/part"; then continue fi raidpart="/dev/$dev" echo "$(mapdevfs "$raidpart")" done done } # Needed for idempotency rm -f /var/lib/os-prober/labels for prog in /usr/libexec/os-probes/init/*; do if [ -x "$prog" ] && [ -f "$prog" ]; then "$prog" || true fi done # We need to properly canonicalize partitions with mount points and partitions # used in RAID grep "^/dev/" /proc/mounts | parse_proc_mounts >"$OS_PROBER_TMP/mounted-map" || true : >"$OS_PROBER_TMP/swaps-map" if [ -f /proc/swaps ]; then grep "^/dev/" /proc/swaps | parse_proc_swaps >"$OS_PROBER_TMP/swaps-map" || true fi : >"$OS_PROBER_TMP/raided-map" if [ -f /proc/mdstat ] ; then grep "^md" /proc/mdstat | cut -d: -f2- | parse_proc_mdstat >"$OS_PROBER_TMP/raided-map" || true fi : >"$OS_PROBER_TMP/btrfs-vols" ( ( for partition in $(partitions); do if ! mapped="$(mapdevfs "$partition")"; then log "Device '$partition' does not exist; skipping" continue fi # Skip partitions used in software RAID arrays if grep -q "^$mapped" "$OS_PROBER_TMP/raided-map" ; then debug "$partition: part of software raid array" continue fi # Skip partitions used as active swap if grep -q "^$mapped " "$OS_PROBER_TMP/swaps-map" ; then debug "$partition: is active swap" continue fi # do btrfs processing here; both mounted and unmounted will # be handled by 50mounted-tests so we can do a subvol only once. type=$(blkid -o value -s TYPE $mapped || true) if [ "$type" = btrfs ]; then uuid=$(blkid -o value -s UUID $mapped) if grep -q "^$uuid" "$OS_PROBER_TMP/btrfs-vols" ; then continue fi debug "btrfs volume uuid=$uuid partition=$partition" echo "$uuid" >>"$OS_PROBER_TMP/btrfs-vols" test="/usr/libexec/os-probes/50mounted-tests" if [ -f "$test" ] && [ -x "$test" ]; then debug "running $test on btrfs $partition" if "$test" btrfs "$uuid" "$partition"; then debug "os detected by $test" continue fi fi elif ! grep -q "^$mapped " "$OS_PROBER_TMP/mounted-map" ; then for test in /usr/libexec/os-probes/*; do if [ -f "$test" ] && [ -x "$test" ]; then debug "running $test on $partition" if "$test" "$partition"; then debug "os detected by $test" break fi fi done else mpoint=$(grep "^$mapped " "$OS_PROBER_TMP/mounted-map" | head -n1 | cut -d " " -f 2) mpoint="$(unescape_mount "$mpoint")" if [ "$mpoint" != "/target/boot" ] && [ "$mpoint" != "/target" ] && [ "$mpoint" != "/" ]; then type=$(grep "^$mapped " "$OS_PROBER_TMP/mounted-map" | head -n1 | cut -d " " -f 3) for test in /usr/libexec/os-probes/mounted/*; do if [ -f "$test" ] && [ -x "$test" ]; then debug "running $test on mounted $partition" if "$test" "$partition" "$mpoint" "$type"; then debug "os detected by $test" break fi fi done fi fi done ) 9>&1 | logger 1>&- # fd_logger ) 3>&1 # fd_result