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