File os-prober-1.49-fix-grub2.cfg-parsing.patch of Package os-prober

From: Andrey Borzenkov <arvidjaar@gmail.com>
Subject: fix parsing GRUB2 grub.cfg
References: bnc#796919

Fix several problems in parsing of grub.cfg by
linux-boot-probes/mounted/40grub2

1. It looked for /boot/grub/grub.cfg only. Make it check for
/boot/grub2-efi/grub.cfg, /boot/grub2/grub.cfg, /boot/grub/grub.cfg in
that order

2. Parsing of menuentry was completely broken. It is (near to) impossible
to parse full fledged shell quoted strings with a couple of sed expressions.
Replace it with ``eval "set -- $line"'', which should handle quoting
automatically. It still may fail for manually created grub.cfg though.

3. It checked for literal "(on /dev/.*)" to filter out menu entries
added by another os-prober on target system. But grub.cfg now includes
TRANSLATED strings, so this check will fail if grub.cfg was created in
non-English locale. Relax check and make it '(.* /dev/.*)'. It should
work as long as grub.cfg was created by grub-mkconfig.
Index: os-prober/linux-boot-probes/mounted/common/40grub2
===================================================================
--- os-prober.orig/linux-boot-probes/mounted/common/40grub2
+++ os-prober/linux-boot-probes/mounted/common/40grub2
@@ -34,33 +34,43 @@ parse_grub_menu () {
 	title=""
 	ignore_item=0
 
-	while read line; do
+	# grub.cfg is written in shell like language that can contain
+	# arbitrary quoting. We need to extract second word according to
+	# normal quoting rules. Unfortunately, sticking ``eval $line'' for
+	# every line will try to interpret it according to shell
+	# grammar and error out for something as simple as "xxx; then".
+	# So the following is using it only on known cases.
+	# FIXME: it will fail if ``menuentry'' is not the first word on line.
+	# case patterns below include SPACE and TAB.
+	while read -r line; do
 		debug "parsing: $line"
-		set -f
-		set -- $line
-		set +f
-		case "$1" in
-			menuentry)
+		line="$(printf "%s" "$line" | sed -e 's/^[[:space:]]*//')"
+		case "$line" in
+			menuentry[" 	"]*)
 				entry_result
-				shift 1
-				# The double-quoted string is the title.
-				title="$(echo "$@" | sed -n 's/[^"]*"\(.*\)".*/\1/p' | sed 's/://g')"
-				if [ -z "$title" ]; then
-					# ... or single-quoted?  The
-					# unescaping here is odd because the
-					# 'set' above has already eaten
-					# backslash-escapes.
-					title="$(echo "$@" | sed -n "s/[^']*'\(.*\)'.*/\1/p" | sed "s/'''/'/; s/://g")"
-				fi
+				set -f
+				eval "set -- $line"
+				set +f
+				title="$2"
 				if [ -z "$title" ]; then
 					ignore_item=1
-				elif echo "$title" | grep -q '(on /dev/[^)]*)$'; then
+				# Currently GRUB2 puts translated strings
+				# in grub.cfg, so checking for verbatim
+				# (on /dev/.*) will fail if target grub.cfg
+				# was created in non-English locale
+				elif echo "$title" | grep -q '(.* /dev/[^)]*)$'; then
 					log "Skipping entry '$title':"
 					log "appears to be an automatic reference taken from another menu.lst"
 					ignore_item=1
 				fi
 			;;
-			linux)
+			linux[" 	"]*)
+				# And here we do NOT want to strip off
+				# existing quting, which will be transferred
+				# verbatim in new grub.cfg
+				set -f
+				set -- $line
+				set +f
 				# Hack alert: sed off any (hdn,n) but
 				# assume the kernel is on the same
 				# partition.
@@ -73,7 +83,13 @@ parse_grub_menu () {
 					kernel="/boot$kernel"
 				fi
 			;;
-			initrd)
+			initrd[" 	"]*)
+				# And here we do NOT want to strip off
+				# existing quting, which will be transferred
+				# verbatim in new grub.cfg
+				set -f
+				set -- $line
+				set +f
 				initrd="$(echo "$2" | sed 's/(.*)//')"
 				# Initrd same.
 				if [ "$partition" != "$bootpart" ]; then
@@ -89,11 +105,20 @@ parse_grub_menu () {
 	entry_result
 }
 
-if [ -e "$mpoint/boot/grub/grub.cfg" ] && \
+grubcfg=
+if [ -e "$mpoint/boot/grub2-efi/grub.cfg" ]; then
+	grubcfg="$mpoint/boot/grub2-efi/grub.cfg"
+elif [ -e "$mpoint/boot/grub2/grub.cfg" ]; then
+	grubcfg="$mpoint/boot/grub2/grub.cfg"
+elif [ -e "$mpoint/boot/grub/grub.cfg" ]; then
+	grubcfg="$mpoint/boot/grub/grub.cfg"
+fi
+
+if [ -n "$grubcfg" ] && \
    ([ ! -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"
+    [ "$grubcfg" -nt "$mpoint/boot/grub/menu.lst" ]); then
+	debug "parsing $grubcfg"
+	parse_grub_menu "$mpoint" "$partition" "$bootpart" < "$grubcfg"
 fi
 
 if [ "$found_item" = 0 ]; then
openSUSE Build Service is sponsored by