--- /dev/null
+# menuentry title [--class=class ...] [--users=users] [--unrestricted] [--hotkey=key] [--id=id] [arg ...] { command; ...}
+menuentry test1 arg1_1 arg1_2 {
+ linux /test1.linux ROOT=vmtest1 "test1=test 1"
+ initrd /test1.initrd
+}
+menuentry 'test 2' {
+ linux /test2.linux ROOT=vmtest2 "test2=test 2"
+ initrd /test2.initrd
+}
+}
+menuentry "test 3" {
+ linux /test3.linux ROOT=vmtest3 "test3=test 3"
+ initrd /test3.initrd
+}
+}
+menuentry 'test 4' arg4_1 arg4_2 {
+ linux /test4.linux ROOT=vmtest4 "test4=test 4"
+ initrd /test4.initrd
+}
+}
+menuentry "test 5" arg5_1 arg5_2 {
+ linux /test5.linux ROOT=vmtest5 "test5=test 5"
+ initrd /test5.initrd
+}
+}
+menuentry 'test 6' --class=class6 {
+ linux /test6.linux ROOT=vmtest6 "test6=test 6"
+ initrd /test6.initrd
+}
+}
+menuentry "test 7" --class=class7 {
+ linux /test7.linux ROOT=vmtest7 "test7=test 7"
+ initrd /test7.initrd
+}
+}
+menuentry --class=class8 'test 8' {
+ linux /test8.linux ROOT=vmtest8 "test8=test 8"
+ initrd /test8.initrd
+}
+}
+menuentry --class=class9 "test 9" {
+ linux /test9.linux ROOT=vmtest9 "test9=test 9"
+ initrd /test9.initrd
+}
+}
+menuentry --class=class10 --id=id10 'test 10' {
+ linux /test10.linux ROOT=vmtest10 "test10=test 10"
+ initrd /test10.initrd
+}
+}
+menuentry --class=class11 --id=id11 "test 11" {
+ linux /test11.linux ROOT=vmtest11 "test11=test 11"
+ initrd /test11.initrd
+}
+}
+menuentry --class=class12 --id=id12 'test 12' arg10_1 arg10_2 {
+ linux /test12.linux ROOT=vmtest12 "test12=test 12"
+ initrd /test12.initrd
+}
+}
+menuentry --class=class13 --id=id13 "test 13" arg11_1 arg11_2 {
+ linux /test13.linux ROOT=vmtest13 "test13=test 13"
+ initrd /test13.initrd
+}
+menuentry --class=class14 --id='id 14' "test 14" arg14_1 arg14_2 {
+ linux /test14.linux ROOT=vmtest14 "test14=test 14"
+ initrd /test14.initrd
+}
+menuentry --class=class15 --id='id 15' 'test'' 15' arg15_1 arg15_2 {
+ linux /test15.linux ROOT=vmtest15 "test15=test 15"
+ initrd /test15.initrd
+}
+menuentry --class=class16 --id='id 16' 'test'\'' 16' arg16_1 arg16_2 {
+ linux /test16.linux ROOT=vmtest16 "test16=test 16"
+ initrd /test16.initrd
+}
+menuentry --class=class17 --id='id 17' 'test'\''17' arg17_1 arg17_2 {
+ linux /test17.linux ROOT=vmtest17 "test17=test 17"
+ initrd /test17.initrd
+}
--- /dev/null
+#!/bin/sh
+. usr/share/os-prober/common.sh
+set -e
+
+partition="$1"
+bootpart="$2"
+mpoint="$3"
+type="$4"
+
+found_item=0
+
+entry_result () {
+ if [ "$ignore_item" = 0 ] && \
+ [ -n "$kernel" ] && \
+ [ -e "$mpoint/$kernel" ]; then
+ result "$rootpart:$bootpart:$title:$kernel:$initrd:$parameters"
+ found_item=1
+ fi
+ kernel=""
+ parameters=""
+ initrd=""
+ title=""
+ ignore_item=0
+}
+
+parse_grub_menu () {
+ mpoint="$1"
+ rootpart="$2"
+ bootpart="$3"
+
+ kernel=""
+ parameters=""
+ initrd=""
+ title=""
+ ignore_item=0
+
+ while read line; do
+ debug "parsing: $line"
+ set -f
+ set -- $line
+ set +f
+ case "$1" in
+ menuentry)
+ entry_result
+ shift 1
+ # strip all of: --option=abcd --option='ab cd' --option="ab cd" menuentry { command block
+ # and everything else except the first quoted string or non-space word
+ # and remove any : from the remaining title
+ title=$( printf "%s" "$line" | sed -n "s/^[[:blank:]]*//; p" )
+ title=$( printf "%s" "$title" | sed -n "s/--[^ ]*=\(\([\"']\)[^\"']*\2 \|[^ ]* \)//g; p" )
+ title=$( printf "%s" "$title" | sed -n "s/{//; p" )
+ title=$( printf "%s" "$title" | sed -n "s/menuentry//; p" )
+ title=$( printf "%s" "$title" | sed -n "s/^[ ]*\(\([\"']\{1\}\)\(.*\)\2\|\([^\"' ][^ ]*\)\).*/\3\4/; p" )
+ title=$( printf "%s" "$title" | sed -n "s/\\\\'//; p" )
+ title=$( printf "%s" "$title" | sed -n "s/''//; p" )
+ title=$( printf "%s" "$title" | sed -n "s/://g; p" )
+ if [ -z "$title" ]; then
+ echo "No title: $line"
+ ignore_item=1
+ elif echo "$title" | grep -q '(on /dev/[^)]*)$'; then
+ log "Skipping entry '$title':"
+ log "appears to be an automatic reference taken from another menu.lst"
+ ignore_item=1
+ fi
+ ;;
+ linux)
+ # Hack alert: sed off any (hdn,n) but
+ # assume the kernel is on the same
+ # partition.
+ kernel="$(echo "$2" | sed 's/(.*)//')"
+ shift 2
+ parameters="$@"
+ # Systems with a separate /boot will not have
+ # the path to the kernel in grub.cfg.
+ if [ "$partition" != "$bootpart" ]; then
+ kernel="/boot$kernel"
+ fi
+ ;;
+ initrd)
+ initrd="$(echo "$2" | sed 's/(.*)//')"
+ # Initrd same.
+ if [ "$partition" != "$bootpart" ]; then
+ initrd="/boot$initrd"
+ fi
+ ;;
+ "}")
+ entry_result
+ ;;
+ esac
+ done
+
+ entry_result
+}
+
+if [ -e "$mpoint/boot/grub/grub.cfg" ] && \
+ ([ ! -e "$mpoint/boot/grub/menu.lst" ] || \
+ [ "$mpoint/boot/grub/grub.cfg" -nt "$mpoint/boot/grub/menu.lst" ]); then
+ debug "parsing grub.cfg"
+ parse_grub_menu "$mpoint" "$partition" "$bootpart" < "$mpoint/boot/grub/grub.cfg"
+elif [ -e "$mpoint/boot/grub2/grub.cfg" ]; then
+ debug "parsing grub.cfg"
+ parse_grub_menu "$mpoint" "$partition" "$bootpart" < "$mpoint/boot/grub2/grub.cfg"
+fi
+
+if [ "$found_item" = 0 ]; then
+ exit 1
+else
+ exit 0
+fi
--- /dev/null
+newns () {
+ [ "$OS_PROBER_NEWNS" ] || exec /usr/lib/os-prober/newns "$0" "$@"
+}
+
+cleanup_tmpdir=false
+cleanup () {
+ if $cleanup_tmpdir; then
+ rm -rf "$OS_PROBER_TMP"
+ fi
+}
+
+require_tmpdir() {
+ if [ -z "$OS_PROBER_TMP" ]; then
+ if type mktemp >/dev/null 2>&1; then
+ export OS_PROBER_TMP="$(mktemp -d /tmp/os-prober.XXXXXX)"
+ cleanup_tmpdir=:
+ trap cleanup EXIT HUP INT QUIT TERM
+ else
+ export OS_PROBER_TMP=/tmp
+ fi
+ fi
+}
+
+count_for() {
+ _labelprefix="$1"
+ _result=$(grep "^${_labelprefix} " /var/lib/os-prober/labels 2>/dev/null || true)
+
+ if [ -z "$_result" ]; then
+ return
+ else
+ echo "$_result" | cut -d' ' -f2
+ fi
+}
+
+count_next_label() {
+ require_tmpdir
+
+ _labelprefix="$1"
+ _cfor="$(count_for "${_labelprefix}")"
+
+ if [ -z "$_cfor" ]; then
+ echo "${_labelprefix} 1" >> /var/lib/os-prober/labels
+ else
+ sed "s/^${_labelprefix} ${_cfor}/${_labelprefix} $(($_cfor + 1))/" /var/lib/os-prober/labels > "$OS_PROBER_TMP/os-prober.tmp"
+ mv "$OS_PROBER_TMP/os-prober.tmp" /var/lib/os-prober/labels
+ fi
+
+ echo "${_labelprefix}${_cfor}"
+}
+
+progname=
+cache_progname() {
+ case $progname in
+ '')
+ progname="${0##*/}"
+ ;;
+ esac
+}
+
+log() {
+ cache_progname
+ logger -t "$progname" "$@"
+}
+
+error() {
+ log "error: $@"
+}
+
+warn() {
+ log "warning: $@"
+}
+
+debug() {
+ if [ -z "$OS_PROBER_DISABLE_DEBUG" ]; then
+ log "debug: $@"
+ fi
+}
+
+result () {
+ log "result:" "$@"
+ echo "$@"
+}
+
+# shim to make it easier to use os-prober outside d-i
+if ! type mapdevfs >/dev/null 2>&1; then
+ mapdevfs () {
+ readlink -f "$1"
+ }
+fi
+
+item_in_dir () {
+ if [ "$1" = "-q" ]; then
+ q="-q"
+ shift 1
+ else
+ q=""
+ fi
+ [ -d "$2" ] || return 1
+ # find files with any case
+ ls -1 "$2" | grep $q -i "^$1$"
+}
+
+# We can't always tell the filesystem type up front, but if we have the
+# information then we should use it. Note that we can't use block-attr here
+# as it's only available in udebs.
+# If not detected after different attempts then "NOT-DETECTED" will be printed
+# because function is not supposed to exit error codes.
+fs_type () {
+ local fstype=""
+ if (export PATH="/lib/udev:$PATH"; type vol_id) >/dev/null 2>&1; then
+ PATH="/lib/udev:$PATH" \
+ fstype=$(vol_id --type "$1" 2>/dev/null || true)
+ [ -z "$fstype" ] || { echo "$fstype"; return; }
+ fi
+ if type lsblk >/dev/null 2>&1 ; then
+ fstype=$(lsblk --nodeps --noheading --output FSTYPE -- "$1" || true)
+ [ -z "$fstype" ] || { echo "$fstype"; return; }
+ fi
+ if type blkid >/dev/null 2>&1; then
+ fstype=$(blkid -o value -s TYPE "$1" 2>/dev/null || true)
+ [ -z "$fstype" ] || { echo "$fstype"; return; }
+ fi
+ echo "NOT-DETECTED"
+}
+
+is_dos_extended_partition() {
+ if type blkid >/dev/null 2>&1; then
+ local output
+
+ output="$(blkid -o export $1)"
+
+ # old blkid (util-linux << 2.24) errors out on extended p.
+ if [ "$?" = "2" ]; then
+ return 0
+ fi
+
+ # dos partition type and no filesystem type?...
+ if echo $output | grep -q ' PTTYPE=dos ' &&
+ ! echo $output | grep -q ' TYPE='; then
+ return 0
+ else
+ return 1
+ fi
+ fi
+
+ return 1
+}
+
+parse_proc_mounts () {
+ while read -r line; do
+ set -f
+ set -- $line
+ set +f
+ printf '%s %s %s\n' "$(mapdevfs "$1")" "$2" "$3"
+ done
+}
+
+parsefstab () {
+ while read -r line; do
+ case "$line" in
+ "#"*)
+ :
+ ;;
+ *)
+ set -f
+ set -- $line
+ set +f
+ printf '%s %s %s\n' "$1" "$2" "$3"
+ ;;
+ esac
+ done
+}
+
+unescape_mount () {
+ printf %s "$1" | \
+ sed 's/\\011/ /g; s/\\012/\n/g; s/\\040/ /g; s/\\134/\\/g'
+}
+
+find_label () {
+ local output
+ if type blkid >/dev/null 2>&1; then
+ # Hopefully everyone has blkid by now
+ output="$(blkid -o device -t LABEL="$1")" || return 1
+ echo "$output" | head -n1
+ elif [ -h "/dev/disk/by-label/$1" ]; then
+ # Last-ditch fallback
+ readlink -f "/dev/disk/by-label/$1"
+ else
+ return 1
+ fi
+}
+
+find_uuid () {
+ local output
+ if type blkid >/dev/null 2>&1; then
+ # Hopefully everyone has blkid by now
+ output="$(blkid -o device -t UUID="$1")" || return 1
+ echo "$output" | head -n1
+ elif [ -h "/dev/disk/by-uuid/$1" ]; then
+ # Last-ditch fallback
+ readlink -f "/dev/disk/by-uuid/$1"
+ else
+ return 1
+ fi
+}
+
+# Sets $mountboot as output variables. This is very messy, but POSIX shell
+# isn't really up to the task of doing it more cleanly.
+linux_mount_boot () {
+ partition="$1"
+ tmpmnt="$2"
+
+ bootpart=""
+ mounted=""
+ if [ -e "$tmpmnt/etc/fstab" ]; then
+ # Try to mount any /boot partition.
+ bootmnt=$(parsefstab < "$tmpmnt/etc/fstab" | grep " /boot ") || true
+ if [ -n "$bootmnt" ]; then
+ set -f
+ set -- $bootmnt
+ set +f
+ boottomnt=""
+
+ # Try to map labels and UUIDs ourselves if possible,
+ # so that we can check whether they're already
+ # mounted somewhere else.
+ tmppart="$1"
+ if echo "$1" | grep -q "LABEL="; then
+ label="$(echo "$1" | cut -d = -f 2)"
+ if tmppart="$(find_label "$label")"; then
+ debug "mapped LABEL=$label to $tmppart"
+ else
+ debug "found boot partition LABEL=$label for Linux system on $partition, but cannot map to existing device"
+ mountboot="$partition 0"
+ return
+ fi
+ elif echo "$1" | grep -q "UUID="; then
+ uuid="$(echo "$1" | cut -d = -f 2)"
+ if tmppart="$(find_uuid "$uuid")"; then
+ debug "mapped UUID=$uuid to $tmppart"
+ else
+ debug "found boot partition UUID=$uuid for Linux system on $partition, but cannot map to existing device"
+ mountboot="$partition 0"
+ return
+ fi
+ fi
+ shift
+ set -- "$(mapdevfs "$tmppart")" "$@"
+
+ if grep -q "^$1 " "$OS_PROBER_TMP/mounted-map"; then
+ bindfrom="$(grep "^$1 " "$OS_PROBER_TMP/mounted-map" | head -n1 | cut -d " " -f 2)"
+ bindfrom="$(unescape_mount "$bindfrom")"
+ if [ "$bindfrom" != "$tmpmnt/boot" ]; then
+ if mount --bind "$bindfrom" "$tmpmnt/boot"; then
+ mounted=1
+ bootpart="$1"
+ else
+ debug "failed to bind-mount $bindfrom onto $tmpmnt/boot"
+ fi
+ fi
+ fi
+ if [ "$mounted" ]; then
+ :
+ elif [ -e "$1" ]; then
+ bootpart="$1"
+ boottomnt="$1"
+ elif [ -e "$tmpmnt/$1" ]; then
+ bootpart="$1"
+ boottomnt="$tmpmnt/$1"
+ elif [ -e "/target/$1" ]; then
+ bootpart="$1"
+ boottomnt="/target/$1"
+ else
+ bootpart=""
+ fi
+
+ if [ ! "$mounted" ]; then
+ if [ -z "$bootpart" ]; then
+ debug "found boot partition $1 for linux system on $partition, but cannot map to existing device"
+ else
+ debug "found boot partition $bootpart for linux system on $partition"
+ if type grub-mount >/dev/null 2>&1 && \
+ grub-mount "$boottomnt" "$tmpmnt/boot" 2>/dev/null; then
+ mounted=1
+ fi
+ fi
+ fi
+ fi
+ fi
+ if [ -z "$bootpart" ]; then
+ bootpart="$partition"
+ fi
+ if [ -z "$mounted" ]; then
+ mounted=0
+ fi
+
+ mountboot="$bootpart $mounted"
+}