Blame SOURCES/0034-Don-t-assume-make-default-just-because-set-index-was.patch

cca0c4
From ff38bf8209faf54c25e15b1fcec4184fee1f39e9 Mon Sep 17 00:00:00 2001
cca0c4
From: Robert Marshall <rmarshall@redhat.com>
cca0c4
Date: Tue, 13 Dec 2016 18:20:15 -0500
cca0c4
Subject: [PATCH 34/55] Don't assume --make-default just because --set-index
cca0c4
 was passed.
cca0c4
cca0c4
grubby previously made the assumption that every time a new
cca0c4
boot entry gets added using --set-index, it should be the default. Due
cca0c4
to this behavior, it also masked an logic error that prevented the
cca0c4
selection of the proper index in cases where it was necessary to
cca0c4
dynamically pick a new default boot entry, or to keep the existing
cca0c4
default boot entry when its position in the config file moved.
cca0c4
cca0c4
Resolves: rhbz#1285601
cca0c4
---
cca0c4
 grubby.c | 138 ++++++++++++++++++++++++++++++++++++++-----------------
cca0c4
 1 file changed, 97 insertions(+), 41 deletions(-)
cca0c4
cca0c4
diff --git a/grubby.c b/grubby.c
cca0c4
index 1f712ec1391..fcca6364887 100644
cca0c4
--- a/grubby.c
cca0c4
+++ b/grubby.c
cca0c4
@@ -2498,66 +2498,121 @@ void markRemovedImage(struct grubConfig *cfg, const char *image,
cca0c4
 		entry->skip = 1;
cca0c4
 }
cca0c4
 
cca0c4
-void setDefaultImage(struct grubConfig *config, int isUserSpecifiedKernelPath,
cca0c4
+void setDefaultImage(struct grubConfig *config, int isAddingBootEntry,
cca0c4
 		     const char *defaultKernelPath, int newBootEntryIsDefault,
cca0c4
-		     const char *prefix, int flags, int newDefaultBootEntryIndex)
cca0c4
+		     const char *prefix, int flags,
cca0c4
+		     int newDefaultBootEntryIndex, int newBootEntryIndex)
cca0c4
 {
cca0c4
-	struct singleEntry *entry, *entry2, *newDefault;
cca0c4
-	int i, j;
cca0c4
+	struct singleEntry *bootEntry, *newDefault;
cca0c4
+	int indexToVerify, firstKernelEntryIndex, currentLookupIndex;
cca0c4
 
cca0c4
+	/* handle the two cases where the user explictly picks the default
cca0c4
+	 * boot entry index as it would exist post-modification */
cca0c4
+
cca0c4
+	/* Case 1: user chose to make the latest boot entry the default */
cca0c4
 	if (newBootEntryIsDefault) {
cca0c4
-		config->defaultImage = FIRST_ENTRY_INDEX;
cca0c4
+		config->defaultImage = newBootEntryIndex;
cca0c4
 		return;
cca0c4
-	} else if ((newDefaultBootEntryIndex >= 0) && config->cfi->defaultIsIndex) {
cca0c4
-		if (findEntryByIndex(config, newDefaultBootEntryIndex))
cca0c4
+	}
cca0c4
+
cca0c4
+	/* Case 2: user picked an arbitrary index as the default boot entry */
cca0c4
+	if (newDefaultBootEntryIndex >= FIRST_ENTRY_INDEX
cca0c4
+	    && config->cfi->defaultIsIndex) {
cca0c4
+		indexToVerify = newDefaultBootEntryIndex;
cca0c4
+
cca0c4
+		/* user chose to make latest boot entry the default */
cca0c4
+		if (newDefaultBootEntryIndex == newBootEntryIndex) {
cca0c4
+			config->defaultImage = newBootEntryIndex;
cca0c4
+			return;
cca0c4
+		}
cca0c4
+
cca0c4
+		/* the user picks the default index based on the
cca0c4
+		 * order of the bootloader configuration after
cca0c4
+		 * modification; ensure we are checking for the
cca0c4
+		 * existence of the correct entry */
cca0c4
+		if (newBootEntryIndex < newDefaultBootEntryIndex) {
cca0c4
+			if (!config->isModified)
cca0c4
+				indexToVerify--;
cca0c4
+		}
cca0c4
+
cca0c4
+		/* verify the user selected index will exist */
cca0c4
+		if (findEntryByIndex(config, indexToVerify)) {
cca0c4
 			config->defaultImage = newDefaultBootEntryIndex;
cca0c4
-		else
cca0c4
-			config->defaultImage = NO_DEFAULT_ENTRY;
cca0c4
-		return;
cca0c4
-	} else if (defaultKernelPath) {
cca0c4
-		i = 0;
cca0c4
-		if (findEntryByPath(config, defaultKernelPath, prefix, &i)) {
cca0c4
-			config->defaultImage = i;
cca0c4
 		} else {
cca0c4
 			config->defaultImage = NO_DEFAULT_ENTRY;
cca0c4
-			return;
cca0c4
 		}
cca0c4
-	}
cca0c4
 
cca0c4
-	/* defaultImage now points to what we'd like to use, but before any
cca0c4
-	 * order changes */
cca0c4
-	if ((config->defaultImage == DEFAULT_SAVED) ||
cca0c4
-	    (config->defaultImage == DEFAULT_SAVED_GRUB2))
cca0c4
-		/* default is set to saved, we don't want to change it */
cca0c4
 		return;
cca0c4
+	}
cca0c4
 
cca0c4
-	if (config->defaultImage >= FIRST_ENTRY_INDEX)
cca0c4
-		entry = findEntryByIndex(config, config->defaultImage);
cca0c4
-	else
cca0c4
-		entry = NULL;
cca0c4
+	/* handle cases where the index value may shift */
cca0c4
 
cca0c4
-	if (entry && !entry->skip) {
cca0c4
-		/* we can preserve the default */
cca0c4
-		if (isUserSpecifiedKernelPath)
cca0c4
+	/* check validity of existing default or first-entry-found
cca0c4
+	   selection */
cca0c4
+	if (defaultKernelPath) {
cca0c4
+		/* user requested first-entry-found */
cca0c4
+		if (!findEntryByPath(config, defaultKernelPath,
cca0c4
+				     prefix, &firstKernelEntryIndex)) {
cca0c4
+			/* don't change default if can't find match */
cca0c4
+			config->defaultImage = NO_DEFAULT_ENTRY;
cca0c4
+			return;
cca0c4
+		}
cca0c4
+
cca0c4
+		config->defaultImage = firstKernelEntryIndex;
cca0c4
+
cca0c4
+		/* this is where we start looking for decrement later */
cca0c4
+		currentLookupIndex = config->defaultImage;
cca0c4
+
cca0c4
+		if (isAddingBootEntry && !config->isModified &&
cca0c4
+		    (newBootEntryIndex < config->defaultImage)) {
cca0c4
+			/* increment because new entry added before default */
cca0c4
 			config->defaultImage++;
cca0c4
-
cca0c4
-		/* count the number of entries erased before this one */
cca0c4
-		for (j = 0; j < config->defaultImage; j++) {
cca0c4
-			entry2 = findEntryByIndex(config, j);
cca0c4
-			if (entry2->skip)
cca0c4
-				config->defaultImage--;
cca0c4
 		}
cca0c4
-	} else if (isUserSpecifiedKernelPath) {
cca0c4
-		config->defaultImage = FIRST_ENTRY_INDEX;
cca0c4
 	} else {
cca0c4
-		/* Either we just erased the default (or the default line was
cca0c4
-		 * bad to begin with) and didn't put a new one in. We'll use
cca0c4
-		 * the first valid image. */
cca0c4
+		/* use pre-existing default entry */
cca0c4
+		currentLookupIndex = config->defaultImage;
cca0c4
+
cca0c4
+		if (isAddingBootEntry
cca0c4
+		    && (newBootEntryIndex <= config->defaultImage)) {
cca0c4
+			config->defaultImage++;
cca0c4
+
cca0c4
+			if (config->isModified) {
cca0c4
+				currentLookupIndex++;
cca0c4
+			}
cca0c4
+		}
cca0c4
+	}
cca0c4
+
cca0c4
+	/* sanity check - is this entry index valid? */
cca0c4
+	bootEntry = findEntryByIndex(config, currentLookupIndex);
cca0c4
+
cca0c4
+	if ((bootEntry && bootEntry->skip) || !bootEntry) {
cca0c4
+		/* entry is to be skipped or is invalid */
cca0c4
+		if (isAddingBootEntry) {
cca0c4
+			config->defaultImage = newBootEntryIndex;
cca0c4
+			return;
cca0c4
+		}
cca0c4
 		newDefault =
cca0c4
 		    findTemplate(config, prefix, &config->defaultImage, 1,
cca0c4
 				 flags);
cca0c4
-		if (!newDefault)
cca0c4
+		if (!newDefault) {
cca0c4
 			config->defaultImage = NO_DEFAULT_ENTRY;
cca0c4
+		}
cca0c4
+
cca0c4
+		return;
cca0c4
+	}
cca0c4
+
cca0c4
+	currentLookupIndex--;
cca0c4
+
cca0c4
+	/* decrement index by the total number of entries deleted */
cca0c4
+
cca0c4
+	for (indexToVerify = currentLookupIndex;
cca0c4
+	     indexToVerify >= FIRST_ENTRY_INDEX; indexToVerify--) {
cca0c4
+
cca0c4
+		bootEntry = findEntryByIndex(config, indexToVerify);
cca0c4
+
cca0c4
+		if (bootEntry && bootEntry->skip) {
cca0c4
+			config->defaultImage--;
cca0c4
+		}
cca0c4
 	}
cca0c4
 }
cca0c4
 
cca0c4
@@ -5265,7 +5320,8 @@ int main(int argc, const char **argv)
cca0c4
 	markRemovedImage(config, removeKernelPath, bootPrefix);
cca0c4
 	markRemovedImage(config, removeMBKernel, bootPrefix);
cca0c4
 	setDefaultImage(config, newKernelPath != NULL, defaultKernel,
cca0c4
-			makeDefault, bootPrefix, flags, defaultIndex);
cca0c4
+			makeDefault, bootPrefix, flags, defaultIndex,
cca0c4
+			newIndex);
cca0c4
 	setFallbackImage(config, newKernelPath != NULL);
cca0c4
 	if (updateImage(config, updateKernelPath, bootPrefix, newKernelArgs,
cca0c4
 			removeArgs, newMBKernelArgs, removeMBKernelArgs))
cca0c4
-- 
cca0c4
2.17.1
cca0c4