[Merge] ~ubuntu-core-dev/grub/+git/ubuntu:wip/preinst-check into ~ubuntu-core-dev/grub/+git/ubuntu:focal
Dimitri John Ledkov
launchpad at surgut.co.uk
Thu Jul 30 22:26:15 UTC 2020
Fixes.
Diff comments:
> diff --git a/debian/preinst.in b/debian/preinst.in
> index 9d67cec..419360e 100644
> --- a/debian/preinst.in
> +++ b/debian/preinst.in
> @@ -10,6 +10,321 @@ case "$1" in
> ;;
> esac
>
> +# This only works on a Linux system with udev running. This is probably the
> +# vast majority of systems where we need any of this, though, and we fall
> +# back reasonably gracefully if we don't have it.
> +cached_available_ids=
> +available_ids()
> +{
> + local id path
> +
> + if [ "$cached_available_ids" ]; then
> + echo "$cached_available_ids"
> + return
> + fi
> +
> + [ -d /dev/disk/by-id ] || return
> + cached_available_ids="$(
> + for path in /dev/disk/by-id/*; do
> + [ -e "$path" ] || continue
> + printf '%s %s\n' "$path" "$(readlink -f "$path")"
> + done | sort -k2 -s -u | cut -d' ' -f1
> + )"
> + echo "$cached_available_ids"
> +}
> +
> +# Returns non-zero and no output if no mapping can be found.
> +device_to_id()
> +{
> + local id
> + for id in $(available_ids); do
> + if [ "$(readlink -f "$id")" = "$(readlink -f "$1")" ]; then
> + echo "$id"
> + return 0
> + fi
> + done
> + # Fall back to the plain device name if there's no by-id link for it.
> + if [ -e "$1" ]; then
> + echo "$1"
> + return 0
> + fi
> + return 1
> +}
> +
> +all_disks()
> +{
> + local id
> + for id in $(available_ids); do
> + case $id in
> + *-part*) ;;
> + *) echo "$id" ;;
> + esac
> + done
> +}
> +
> +all_partitions()
> +{
> + local id ids
> + ids=
> + for id in $(available_ids); do
> + if [ "$id" != "$1" ] && [ "${id%-part*}" = "$1" ]; then
> + ids="${ids:+$ids }$id"
> + fi
> + done
> + echo "$ids"
> +}
> +
> +# for Linux
> +sysfs_size()
> +{
> + local num_sectors sector_size size
> + # Try to find out the size without relying on a partitioning tool being
> + # installed. This isn't too hard on Linux 2.6 with sysfs, but we have to
> + # try a couple of variants on detection of the sector size.
> + if [ -e "$1/size" ]; then
> + num_sectors="$(cat "$1/size")"
> + sector_size=512
> + if [ -e "$1/queue/logical_block_size" ]; then
> + sector_size="$(cat "$1/queue/logical_block_size")"
> + elif [ -e "$1/queue/hw_sector_size" ]; then
> + sector_size="$(cat "$1/queue/hw_sector_size")"
> + fi
> + size="$(expr "$num_sectors" \* "$sector_size" / 1000 / 1000)"
> + fi
> + [ "$size" ] || size='???'
> + echo "$size"
> +}
> +
> +# for kFreeBSD
> +camcontrol_size()
> +{
> + local num_sectors sector_size size=
> +
> + if num_sectors="$(camcontrol readcap "$1" -q -s -N)"; then
> + sector_size="$(camcontrol readcap "$1" -q -b)"
> + size="$(expr "$num_sectors" \* "$sector_size" / 1000 / 1000)"
> + fi
> +
> + [ "$size" ] || size='???'
> + echo "$size"
> +}
> +
> +maybe_udevadm()
> +{
> + if which udevadm >/dev/null 2>&1; then
> + udevadm "$@" || true
> + fi
> +}
> +
> +# Returns value in $RET, like a debconf command.
> +describe_disk()
> +{
> + local disk id sysfs_path disk_basename size model
> + disk="$1"
> + id="$2"
> +
> + model=
> + case $(uname -s) in
> + Linux)
> + sysfs_path="$(maybe_udevadm info -n "$disk" -q path)"
> + if [ -z "$sysfs_path" ]; then
> + sysfs_path="/block/$(printf %s "${disk#/dev/}" | sed 's,/,!,g')"
> + fi
> + size="$(sysfs_size "/sys$sysfs_path")"
> +
> + model="$(maybe_udevadm info -n "$disk" -q property | sed -n 's/^ID_MODEL=//p')"
> + if [ -z "$model" ]; then
> + model="$(maybe_udevadm info -n "$disk" -q property | sed -n 's/^DM_NAME=//p')"
> + if [ -z "$model" ]; then
> + model="$(maybe_udevadm info -n "$disk" -q property | sed -n 's/^MD_NAME=//p')"
> + if [ -z "$model" ] && which dmsetup >/dev/null 2>&1; then
> + model="$(dmsetup info -c --noheadings -o name "$disk" 2>/dev/null || true)"
> + fi
> + fi
> + fi
> + ;;
> + GNU/kFreeBSD)
> + disk_basename=$(basename "$disk")
> + size="$(camcontrol_size "$disk_basename")"
> + model="$(camcontrol inquiry "$disk_basename" | sed -ne "s/^pass0: <\([^>]*\)>.*/\1/p")"
> + ;;
> + esac
> +
> + [ "$model" ] || model='???'
> +
> + db_subst grub-pc/disk_description DEVICE "$disk"
> + db_subst grub-pc/disk_description SIZE "$size"
> + db_subst grub-pc/disk_description MODEL "$model"
> + db_metaget grub-pc/disk_description description
> +}
> +
> +# Returns value in $RET, like a debconf command.
> +describe_partition()
> +{
> + local disk part id path sysfs_path diskbase partbase size
> + disk="$1"
> + part="$2"
> + id="$3"
> + path="$4"
> +
> + sysfs_path="$(maybe_udevadm info -n "$part" -q path)"
> + if [ -z "$sysfs_path" ]; then
> + diskbase="${disk#/dev/}"
> + diskbase="$(printf %s "$diskbase" | sed 's,/,!,g')"
> + partbase="${part#/dev/}"
> + partbase="$(printf %s "$partbase" | sed 's,/,!,g')"
> + sysfs_path="/block/$diskbase/$partbase"
> + fi
> + size="$(sysfs_size "/sys$sysfs_path")"
> +
> + db_subst grub-pc/partition_description DEVICE "$part"
> + db_subst grub-pc/partition_description SIZE "$size"
> + db_subst grub-pc/partition_description PATH "$path"
> + db_metaget grub-pc/partition_description description
> +}
> +
> +usable_partitions()
> +{
> + local last_partition path partition partition_id
> +
> + last_partition=
> + for path in / /boot /boot/grub; do
> + partition="$(grub-probe -t device "$path" || true)"
> + if [ -z "$partition" ] || [ "$partition" = "$last_partition" ]; then
> + continue
> + fi
> + partition_id="$(device_to_id "$partition" || true)"
> + echo "$path:$partition_id"
> + last_partition="$partition"
> + done | sort -t: -k2
> +}
> +
> +get_mountpoint()
> +{
> + local relpath boot_mountpoint
> +
> + relpath="$(grub-mkrelpath "$1")"
> + boot_mountpoint="${1#$relpath}"
> + echo "${boot_mountpoint:-/}"
> +}
> +
> +check_install_devices()
> +{
> + . /usr/share/debconf/confmodule
> +
> + # get devices
> + question=grub-pc/install_devices
> + priority=high
fixing.
> + device_map="$(grub-mkdevicemap -m - | grep -v '^(fd[0-9]\+)' || true)"
> + devices="$(echo "$device_map" | cut -f2)"
> + db_get grub-pc/install_devices
> +
> + # it's ok to not want grub
> + if [ -z "$RET" ]; then
> + return 0
> + fi
> +
> + # check if valid
> + valid=1
> + for device in $RET; do
> + if [ ! -e "${device%,}" ]; then
> + valid=0
> + break
> + fi
> + done
> +
> + # they are valid, great
> + if [ "$valid" = 1 ]; then
> + return 0
> + fi
> +
> + # if not valid, switch to disks_changed question
> + if [ "$valid" = 0 ]; then
fixing.
> + question=grub-pc/install_devices_disks_changed
> + priority=critical
> + db_set "$question" "$RET"
> + db_fset "$question" seen false
> + db_fset grub-pc/install_devices_empty seen false
fixing.
> + fi
> +
> + # populate possible devices
> + ids=
> + descriptions=
> + partitions="$(usable_partitions)"
> + for device in $devices; do
> + disk_id="$(device_to_id "$device" || true)"
> + if [ "$disk_id" ]; then
> + ids="${ids:+$ids, }$disk_id"
> + describe_disk "$(readlink -f "$device")" "$disk_id"
> + RET="$(printf %s "$RET" | sed 's/,/\\,/g')"
> + descriptions="${descriptions:+$descriptions, }$RET"
> + for partition_pair in $partitions; do
> + partition_id="${partition_pair#*:}"
> + if [ "${partition_id#$disk_id-part}" != "$partition_id" ]; then
> + ids="${ids:+$ids, }$partition_id"
> + describe_partition "$(readlink -f "$device")" "$(readlink -f "$partition_id")" "$partition_id" "$(get_mountpoint "${partition_pair%%:*}")"
> + RET="$(printf %s "$RET" | sed 's/,/\\,/g')"
> + descriptions="${descriptions:+$descriptions, }$RET"
> + fi
> + done
> + fi
> + done
> + # Some "partitions" may in fact be at the disk level, e.g. RAID.
> + # List these as well if they haven't already been listed.
> + for partition_pair in $partitions; do
> + partition_id="${partition_pair#*:}"
> + if [ "${partition_id#*-part}" = "$partition_id" ]; then
> + case ", $ids, " in
> + ", $partition_id, ") ;;
> + *)
> + ids="${ids:+$ids, }$partition_id"
> + describe_disk "$(readlink -f "$partition_id")" "$partition_id"
> + RET="$(printf %s "$RET" | sed 's/,/\\,/g')"
> + descriptions="${descriptions:+$descriptions, }$RET"
> + ;;
> + esac
> + fi
> + done
> + db_subst "$question" RAW_CHOICES "$ids"
> + db_subst "$question" CHOICES "$descriptions"
> + db_input "$priority" "$question"
fixing.
> + db_go
> + db_get "$question"
> +
> + # one no longer wants grub installed, but did before
> + # this is confusing, abort
> + if [ -z "$RET" ]; then
> + return 1
> + fi
fixing.
> +
> + # update devices list
> + if [ "$question" != grub-pc/install_devices ] && [ "$RET" ]; then
fixing.
> + # XXX cjwatson 2019-02-26: The description of
> + # grub-pc/install_devices_disks_changed ought to explain that
> + # selecting no devices will leave the configuration unchanged
> + # so that you'll be prompted again next time, but it's a bit
> + # close to the Debian 10 release to be introducing new
> + # translatable text. For now, it should be sufficient to
> + # avoid losing configuration data.
> + db_set grub-pc/install_devices "$RET"
> + db_fset grub-pc/install_devices seen true
> + fi
> + return 0
> +}
> +
> +case "$1" in
> + upgrade)
> + # XXX what if we booted in EFI mode?
> + # XXX what if we are in a chroot?
> + if [ "$DPKG_MAINTSCRIPT_PACKAGE" = "grub-pc" ]; then
fixing.
> + if ! check_install_devices; then
> + echo Invalid grub-pc configuration, please run $ sudo dpkg-reconfigure grub-pc
> + exit 1
> + fi
> + fi
> + ;;
> +esac
> +
> #DEBHELPER#
>
> exit 0
--
https://code.launchpad.net/~ubuntu-core-dev/grub/+git/ubuntu/+merge/388423
Your team Ubuntu Core Development Team is subscribed to branch ~ubuntu-core-dev/grub/+git/ubuntu:focal.
More information about the Ubuntu-reviews
mailing list