#!/bin/sh . common.sh DEVNAME=$1 case "$DEVNAME" in /dev/loop*|/dev/ram*|/dev/dm-*|/dev/md*|/dev/fd*) exit ;; esac [ -b "$DEVNAME" ] || exit debug_log "grok-block.${DEVNAME##*/}" addmenu_repairhfs() { local device="$1" addmenu "$device//reboot" \ "[ Reboot into Mac OS X in order to repair disk $device ]" \ "eject /cdrom; sleep 2; reboot -f" addmenu "$device//fsck" \ "[ (DANGEROUS) Try to repair errors on $device with fsck.hfsplus ]" \ "/bin/openvt -sw -- sh -c 'fsck.hfsplus $device && remenu'" } addmenu_chooseroot() { local device="$1" loopfile="$2" addmenu "$device//$loopfile" \ "[ Boot the system on $device${loopfile:+ in file $(basename $loopfile)} ]" \ "menu-select --fs=$ID_FS_TYPE boot-luks $device ${loopfile:-$device}" } addmenu_choose_native_root() { local device="$1" loopfile="$2" addmenu "$device//$device" \ "[ Boot the system on $device ]" \ "menu-select --fs=$ID_FS_TYPE boot-native $device" } addmenu_makeroot() { local device="$1" loopfile="$2" megs="$3" copy_cdrom="$4" ( addmenu "$device//$loopfile" \ "[ Install Samizdat to $device (in file $(basename $loopfile)) ]" \ "menu-select --fs=$ID_FS_TYPE boot-new $device $loopfile $megs $copy_cdrom" ) & } addmenu_destroy_hard_drive() { local device="$1" ( addmenu "$device//$device" \ "[ Install Samizdat to $device -- THIS DESTROYS ALL DATA ]" \ "menu-select boot-destroy-disk $device" ) & } retry_mount() { tries=20 until mntout="$(mount "$@" 2>&1)" do tries=$(( tries - 1 )) case "$mntout" in *"Device or resource busy"*) if [ $tries -le 0 ]; then warn "mount $@ failed: $mntout" return 1 else sleep 1 continue fi ;; *) warn "mount $@ failed: $mntout" break ;; esac done } is_lvm() { for n in 0 1 2 3; do [ "LVM2 001" = "$(dd if="$1" bs=1 skip=$((512*n+24)) count=8 2>/dev/null)" ] && return 0 done return 1 } is_device_without_partitions() { case "$1" in /dev/nbd*|/dev/sr*|*[0-9]) return 1 ;; esac [ "$(parted -sm "$1" print | grep -c :)" = 1 ] } is_incomplete_samizdat_install() { # TODO: Possibly only some of the partitions are incomplete local partition_names="$(parted -sm "$1" print | sed 1,2d | awk -F: -e '{printf "%s:", $6}')" [ "$partition_names" = 'samizdat-grub-incomplete:samizdat-plaintext-incomplete:samizdat-luks-encrypted-incomplete:' ] } parent_device() { local d="$1" while [ "$d" != "${d%[0-9]}" ]; do d=${d%[0-9]}; done printf '%s' "$d" } wait_for_files_() { : wait_for_files: Polling... ( set +x local f for f in "$@"; do while ! [ -e "$f" ]; do sleep 0.1; done done ) : wait_for_files: ...finished. } grok_block() { local mountpoint="/mnt/${DEVNAME##*/}" mkdir -p "$mountpoint" case "$ID_FS_TYPE" in ntfs) mount_type='-t ntfs-3g' ;; "") mount_type= ;; *) mount_type="-t $ID_FS_TYPE" ;; esac # Skip partitions that we created. # The name 'samizdat-plaintext' is recognized and used to add the menu entry, below. case "$DEVNAME" in # Avoid mouting this multiple times in case this script gets called multiple times, # because while it's mounted, the dmsetup stuff will fail with device busy. /dev/nbd0) bootdone nbd0-dev return ;; /dev/nbd1) bootwait nbd-script nbd0-dev wait_for_files_ /sys/block/nbd0/pid /sys/block/nbd1/pid ;; esac case "$ID_PART_ENTRY_NAME" in samizdat-*-incomplete|samizdat-plaintext|samizdat-keys|samizdat-grub) return ;; samizdat-rootfs) ;; samizdat-luks-encrypted) if ! [ -f /autobooted ] then touch /autobooted menu-select boot-native "$(parent_device "$DEVNAME")" return fi ;; esac if [ "$ID_FS_TYPE" = btrfs ]; then btrfs device ready "$DEVNAME" fi if [ "$ID_FS_TYPE" = hfsplus ] && ! fsck.hfsplus -q "$DEVNAME"; then (if fsck.hfsplus "$DEVNAME"; then grok-block "$DEVNAME" else addmenu_repairhfs "$DEVNAME" fi) & return fi if ! mountpoint -q "$mountpoint"; then if [ "$DEVNAME" = /dev/nbd1 ] then OPTIONS='-o device=/dev/nbd0' else OPTIONS= fi retry_mount $mount_type -r $OPTIONS "$DEVNAME" "$mountpoint" fi if ! mountpoint -q "$mountpoint"; then rmdir "$mountpoint" is_device_without_partitions "$DEVNAME" || is_incomplete_samizdat_install "$DEVNAME" && addmenu_destroy_hard_drive "$DEVNAME" elif [ "$ID_PART_ENTRY_NAME" = samizdat-rootfs ]; then bootdone samizdat-rootfs elif [ "$DEVNAME" = /dev/nbd1 ]; then # This is our rootfs, over the network umount "$mountpoint" rmdir "$mountpoint" bootdone samizdat-nbd-dev else umount "$mountpoint" rmdir "$mountpoint" fi } # Get me all them nice udev variables eval "$(PATH=$PATH:/lib/udev vol_id "$DEVNAME" | sed "s/'/'\\\\''/; s/=\(.*\)/='\1'/" )" grok_block & # vim:set et sw=2: