--- trunk/grubby/grubby.c 2017/06/27 14:38:16 3019 +++ trunk/grubby/grubby.c 2017/06/27 14:39:37 3021 @@ -2501,66 +2501,121 @@ 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 + } else { config->defaultImage = NO_DEFAULT_ENTRY; + } + return; - } else if (defaultKernelPath) { - i = 0; - if (findEntryByPath(config, defaultKernelPath, prefix, &i)) { - config->defaultImage = i; - } else { + } + + /* handle cases where the index value may shift */ + + /* 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; } - } - /* 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; + config->defaultImage = firstKernelEntryIndex; - if (config->defaultImage >= FIRST_ENTRY_INDEX) - entry = findEntryByIndex(config, config->defaultImage); - else - entry = NULL; + /* this is where we start looking for decrement later */ + currentLookupIndex = config->defaultImage; - if (entry && !entry->skip) { - /* we can preserve the default */ - if (isUserSpecifiedKernelPath) + 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--; + } } } @@ -5268,7 +5323,8 @@ 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))