75 |
}; |
}; |
76 |
|
|
77 |
enum lineType_e { |
enum lineType_e { |
78 |
|
LT_UNIDENTIFIED = 0, |
79 |
LT_WHITESPACE = 1 << 0, |
LT_WHITESPACE = 1 << 0, |
80 |
LT_TITLE = 1 << 1, |
LT_TITLE = 1 << 1, |
81 |
LT_KERNEL = 1 << 2, |
LT_KERNEL = 1 << 2, |
132 |
#define NEED_DEVTREE (1 << 6) |
#define NEED_DEVTREE (1 << 6) |
133 |
|
|
134 |
#define MAIN_DEFAULT (1 << 0) |
#define MAIN_DEFAULT (1 << 0) |
135 |
|
#define FIRST_ENTRY_INDEX 0 /* boot entry index value begin and increment |
136 |
|
from this initial value */ |
137 |
|
#define NO_DEFAULT_ENTRY -1 /* indicates that no specific default boot |
138 |
|
entry was set or currently exists */ |
139 |
#define DEFAULT_SAVED -2 |
#define DEFAULT_SAVED -2 |
140 |
#define DEFAULT_SAVED_GRUB2 -3 |
#define DEFAULT_SAVED_GRUB2 -3 |
141 |
|
|
681 |
int fallbackImage; /* just like defaultImage */ |
int fallbackImage; /* just like defaultImage */ |
682 |
int flags; |
int flags; |
683 |
struct configFileInfo *cfi; |
struct configFileInfo *cfi; |
684 |
|
int isModified; /* assumes only one entry added |
685 |
|
per invocation of grubby */ |
686 |
}; |
}; |
687 |
|
|
688 |
blkid_cache blkid; |
blkid_cache blkid; |
757 |
return buf; |
return buf; |
758 |
} |
} |
759 |
|
|
760 |
|
static inline int |
761 |
|
kwcmp(struct keywordTypes *kw, const char * label, int case_insensitive) |
762 |
|
{ |
763 |
|
int kwl = strlen(kw->key); |
764 |
|
int ll = strlen(label); |
765 |
|
int rc; |
766 |
|
int (*snc)(const char *s1, const char *s2, size_t n) = |
767 |
|
case_insensitive ? strncasecmp : strncmp; |
768 |
|
int (*sc)(const char *s1, const char *s2) = |
769 |
|
case_insensitive ? strcasecmp : strcmp; |
770 |
|
|
771 |
|
rc = snc(kw->key, label, kwl); |
772 |
|
if (rc) |
773 |
|
return rc; |
774 |
|
|
775 |
|
for (int i = kwl; i < ll; i++) { |
776 |
|
if (isspace(label[i])) |
777 |
|
return 0; |
778 |
|
if (kw->separatorChar && label[i] == kw->separatorChar) |
779 |
|
return 0; |
780 |
|
else if (kw->nextChar && label[i] == kw->nextChar) |
781 |
|
return 0; |
782 |
|
return sc(kw->key+kwl, label+kwl); |
783 |
|
} |
784 |
|
return 0; |
785 |
|
} |
786 |
|
|
787 |
static enum lineType_e preferredLineType(enum lineType_e type, |
static enum lineType_e preferredLineType(enum lineType_e type, |
788 |
struct configFileInfo *cfi) |
struct configFileInfo *cfi) |
789 |
{ |
{ |
849 |
struct configFileInfo *cfi) |
struct configFileInfo *cfi) |
850 |
{ |
{ |
851 |
for (struct keywordTypes * kw = cfi->keywords; kw->key; kw++) { |
for (struct keywordTypes * kw = cfi->keywords; kw->key; kw++) { |
852 |
if (cfi->caseInsensitive) { |
if (!kwcmp(kw, keyword, cfi->caseInsensitive)) |
853 |
if (!strcasecmp(keyword, kw->key)) |
return kw->type; |
|
return kw->type; |
|
|
} else { |
|
|
if (!strcmp(keyword, kw->key)) |
|
|
return kw->type; |
|
|
} |
|
854 |
} |
} |
855 |
return LT_UNKNOWN; |
return LT_UNKNOWN; |
856 |
} |
} |
945 |
|
|
946 |
static void lineInit(struct singleLine *line) |
static void lineInit(struct singleLine *line) |
947 |
{ |
{ |
948 |
|
line->type = LT_UNIDENTIFIED; |
949 |
line->indent = NULL; |
line->indent = NULL; |
950 |
line->elements = NULL; |
line->elements = NULL; |
951 |
line->numElements = 0; |
line->numElements = 0; |
1028 |
|
|
1029 |
if (fprintf(out, "%s", line->elements[i].item) == -1) |
if (fprintf(out, "%s", line->elements[i].item) == -1) |
1030 |
return -1; |
return -1; |
1031 |
if (i < line->numElements - 1) |
if (i < line->numElements - 1 || line->type == LT_SET_VARIABLE) |
1032 |
if (fprintf(out, "%s", line->elements[i].indent) == -1) |
if (fprintf(out, "%s", line->elements[i].indent) == -1) |
1033 |
return -1; |
return -1; |
1034 |
} |
} |
1083 |
break; |
break; |
1084 |
chptr++; |
chptr++; |
1085 |
} |
} |
1086 |
|
if (line->type == LT_UNIDENTIFIED) |
1087 |
|
line->type = getTypeByKeyword(start, cfi); |
1088 |
element->item = strndup(start, chptr - start); |
element->item = strndup(start, chptr - start); |
1089 |
start = chptr; |
start = chptr; |
1090 |
|
|
1150 |
line->type = LT_WHITESPACE; |
line->type = LT_WHITESPACE; |
1151 |
line->numElements = 0; |
line->numElements = 0; |
1152 |
} |
} |
1153 |
} else { |
} else if (line->type == LT_INITRD) { |
1154 |
struct keywordTypes *kw; |
struct keywordTypes *kw; |
1155 |
|
|
1156 |
kw = getKeywordByType(line->type, cfi); |
kw = getKeywordByType(line->type, cfi); |
1212 |
} |
} |
1213 |
} |
} |
1214 |
} |
} |
1215 |
|
} else if (line->type == LT_SET_VARIABLE) { |
1216 |
|
/* and if it's a "set blah=" we need to split it |
1217 |
|
* yet a third way to avoid rhbz# XXX FIXME :/ |
1218 |
|
*/ |
1219 |
|
char *eq; |
1220 |
|
int l; |
1221 |
|
int numElements = line->numElements; |
1222 |
|
struct lineElement *newElements; |
1223 |
|
eq = strchr(line->elements[1].item, '='); |
1224 |
|
if (!eq) |
1225 |
|
return 0; |
1226 |
|
l = eq - line->elements[1].item; |
1227 |
|
if (eq[1] != 0) |
1228 |
|
numElements++; |
1229 |
|
newElements = calloc(numElements,sizeof (*newElements)); |
1230 |
|
memcpy(&newElements[0], &line->elements[0], |
1231 |
|
sizeof (newElements[0])); |
1232 |
|
newElements[1].item = |
1233 |
|
strndup(line->elements[1].item, l); |
1234 |
|
newElements[1].indent = "="; |
1235 |
|
*(eq++) = '\0'; |
1236 |
|
newElements[2].item = strdup(eq); |
1237 |
|
free(line->elements[1].item); |
1238 |
|
if (line->elements[1].indent) |
1239 |
|
newElements[2].indent = line->elements[1].indent; |
1240 |
|
for (int i = 2; i < line->numElements; i++) { |
1241 |
|
newElements[i+1].item = line->elements[i].item; |
1242 |
|
newElements[i+1].indent = |
1243 |
|
line->elements[i].indent; |
1244 |
|
} |
1245 |
|
free(line->elements); |
1246 |
|
line->elements = newElements; |
1247 |
|
line->numElements = numElements; |
1248 |
} |
} |
1249 |
} |
} |
1250 |
|
|
1302 |
cfg->theLines = NULL; |
cfg->theLines = NULL; |
1303 |
cfg->entries = NULL; |
cfg->entries = NULL; |
1304 |
cfg->fallbackImage = 0; |
cfg->fallbackImage = 0; |
1305 |
|
cfg->isModified = 0; |
1306 |
|
|
1307 |
/* copy everything we have */ |
/* copy everything we have */ |
1308 |
while (*head) { |
while (*head) { |
1351 |
getKeywordByType(LT_DEFAULT, cfi); |
getKeywordByType(LT_DEFAULT, cfi); |
1352 |
if (kwType && line->numElements == 3 |
if (kwType && line->numElements == 3 |
1353 |
&& !strcmp(line->elements[1].item, kwType->key) |
&& !strcmp(line->elements[1].item, kwType->key) |
1354 |
&& !is_special_grub2_variable(line->elements[2]. |
&& !is_special_grub2_variable( |
1355 |
item)) { |
line->elements[2].item)) { |
1356 |
dbgPrintf("Line sets default config\n"); |
dbgPrintf("Line sets default config\n"); |
1357 |
cfg->flags &= ~GRUB_CONFIG_NO_DEFAULT; |
cfg->flags &= ~GRUB_CONFIG_NO_DEFAULT; |
1358 |
defaultLine = line; |
defaultLine = line; |
1359 |
} |
} |
|
|
|
1360 |
} else if (iskernel(line->type)) { |
} else if (iskernel(line->type)) { |
1361 |
/* if by some freak chance this is multiboot and the |
/* if by some freak chance this is multiboot and the |
1362 |
* "module" lines came earlier in the template, make |
* "module" lines came earlier in the template, make |
1610 |
} |
} |
1611 |
} |
} |
1612 |
} else if (cfi->defaultIsVariable) { |
} else if (cfi->defaultIsVariable) { |
1613 |
char *value = defaultLine->elements[2].item; |
if (defaultLine->numElements == 2) { |
1614 |
while (*value && (*value == '"' || *value == '\'' || |
char *value = defaultLine->elements[1].item + 8; |
1615 |
*value == ' ' || *value == '\t')) |
while (*value && (*value == '"' || |
1616 |
value++; |
*value == '\'' || |
1617 |
cfg->defaultImage = strtol(value, &end, 10); |
*value == ' ' || |
1618 |
while (*end && (*end == '"' || *end == '\'' || |
*value == '\t')) |
1619 |
*end == ' ' || *end == '\t')) |
value++; |
1620 |
end++; |
cfg->defaultImage = strtol(value, &end, 10); |
1621 |
if (*end) |
while (*end && (*end == '"' || *end == '\'' || |
1622 |
cfg->defaultImage = -1; |
*end == ' ' || *end == '\t')) |
1623 |
|
end++; |
1624 |
|
if (*end) |
1625 |
|
cfg->defaultImage = NO_DEFAULT_ENTRY; |
1626 |
|
} else if (defaultLine->numElements == 3) { |
1627 |
|
char *value = defaultLine->elements[2].item; |
1628 |
|
while (*value && (*value == '"' || |
1629 |
|
*value == '\'' || |
1630 |
|
*value == ' ' || |
1631 |
|
*value == '\t')) |
1632 |
|
value++; |
1633 |
|
cfg->defaultImage = strtol(value, &end, 10); |
1634 |
|
while (*end && (*end == '"' || *end == '\'' || |
1635 |
|
*end == ' ' || *end == '\t')) |
1636 |
|
end++; |
1637 |
|
if (*end) |
1638 |
|
cfg->defaultImage = NO_DEFAULT_ENTRY; |
1639 |
|
} |
1640 |
} else if (cfi->defaultSupportSaved && |
} else if (cfi->defaultSupportSaved && |
1641 |
!strncmp(defaultLine->elements[1].item, "saved", |
!strncmp(defaultLine->elements[1].item, "saved", |
1642 |
5)) { |
5)) { |
1645 |
cfg->defaultImage = |
cfg->defaultImage = |
1646 |
strtol(defaultLine->elements[1].item, &end, 10); |
strtol(defaultLine->elements[1].item, &end, 10); |
1647 |
if (*end) |
if (*end) |
1648 |
cfg->defaultImage = -1; |
cfg->defaultImage = NO_DEFAULT_ENTRY; |
1649 |
} else if (defaultLine->numElements >= 2) { |
} else if (defaultLine->numElements >= 2) { |
1650 |
int i = 0; |
int i = 0; |
1651 |
while ((entry = findEntryByIndex(cfg, i))) { |
while ((entry = findEntryByIndex(cfg, i))) { |
1673 |
if (entry) { |
if (entry) { |
1674 |
cfg->defaultImage = i; |
cfg->defaultImage = i; |
1675 |
} else { |
} else { |
1676 |
cfg->defaultImage = -1; |
cfg->defaultImage = NO_DEFAULT_ENTRY; |
1677 |
} |
} |
1678 |
} |
} |
1679 |
} else if (cfg->cfi->defaultIsSaved && cfg->cfi->getEnv) { |
} else if (cfg->cfi->defaultIsSaved && cfg->cfi->getEnv) { |
1690 |
cfg->defaultImage = index; |
cfg->defaultImage = index; |
1691 |
} |
} |
1692 |
} else { |
} else { |
1693 |
cfg->defaultImage = 0; |
cfg->defaultImage = FIRST_ENTRY_INDEX; |
1694 |
} |
} |
1695 |
|
|
1696 |
return cfg; |
return cfg; |
1710 |
fprintf(out, "%sdefault%ssaved\n", indent, separator); |
fprintf(out, "%sdefault%ssaved\n", indent, separator); |
1711 |
else if (cfg->cfi->defaultIsSaved) { |
else if (cfg->cfi->defaultIsSaved) { |
1712 |
fprintf(out, "%sset default=\"${saved_entry}\"\n", indent); |
fprintf(out, "%sset default=\"${saved_entry}\"\n", indent); |
1713 |
if (cfg->defaultImage >= 0 && cfg->cfi->setEnv) { |
if (cfg->defaultImage >= FIRST_ENTRY_INDEX && cfg->cfi->setEnv) { |
1714 |
char *title; |
char *title; |
1715 |
entry = findEntryByIndex(cfg, cfg->defaultImage); |
int trueIndex, currentIndex; |
1716 |
|
|
1717 |
|
trueIndex = 0; |
1718 |
|
currentIndex = 0; |
1719 |
|
|
1720 |
|
while ((entry = findEntryByIndex(cfg, currentIndex))) { |
1721 |
|
if (!entry->skip) { |
1722 |
|
if (trueIndex == cfg->defaultImage) { |
1723 |
|
break; |
1724 |
|
} |
1725 |
|
trueIndex++; |
1726 |
|
} |
1727 |
|
currentIndex++; |
1728 |
|
} |
1729 |
line = getLineByType(LT_MENUENTRY, entry->lines); |
line = getLineByType(LT_MENUENTRY, entry->lines); |
1730 |
if (!line) |
if (!line) |
1731 |
line = getLineByType(LT_TITLE, entry->lines); |
line = getLineByType(LT_TITLE, entry->lines); |
1736 |
"saved_entry", title); |
"saved_entry", title); |
1737 |
} |
} |
1738 |
} |
} |
1739 |
} else if (cfg->defaultImage > -1) { |
} else if (cfg->defaultImage >= FIRST_ENTRY_INDEX) { |
1740 |
if (cfg->cfi->defaultIsIndex) { |
if (cfg->cfi->defaultIsIndex) { |
1741 |
if (cfg->cfi->defaultIsVariable) { |
if (cfg->cfi->defaultIsVariable) { |
1742 |
fprintf(out, "%sset default=\"%d\"\n", indent, |
fprintf(out, "%sset default=\"%d\"\n", indent, |
2440 |
} |
} |
2441 |
} |
} |
2442 |
} |
} |
2443 |
} else if (cfg->defaultImage > -1) { |
} else if (cfg->defaultImage >= FIRST_ENTRY_INDEX) { |
2444 |
entry = findEntryByIndex(cfg, cfg->defaultImage); |
entry = findEntryByIndex(cfg, cfg->defaultImage); |
2445 |
if (entry && suitableImage(entry, prefix, skipRemoved, flags)) { |
if (entry && suitableImage(entry, prefix, skipRemoved, flags)) { |
2446 |
if (indexPtr) |
if (indexPtr) |
2452 |
index = 0; |
index = 0; |
2453 |
while ((entry = findEntryByIndex(cfg, index))) { |
while ((entry = findEntryByIndex(cfg, index))) { |
2454 |
if (suitableImage(entry, prefix, skipRemoved, flags)) { |
if (suitableImage(entry, prefix, skipRemoved, flags)) { |
2455 |
int j; |
int j, unmodifiedIndex; |
2456 |
for (j = 0; j < index; j++) { |
|
2457 |
|
unmodifiedIndex = index; |
2458 |
|
|
2459 |
|
for (j = 0; j < unmodifiedIndex; j++) { |
2460 |
entry2 = findEntryByIndex(cfg, j); |
entry2 = findEntryByIndex(cfg, j); |
2461 |
if (entry2->skip) |
if (entry2->skip) |
2462 |
index--; |
index--; |
2517 |
entry->skip = 1; |
entry->skip = 1; |
2518 |
} |
} |
2519 |
|
|
2520 |
void setDefaultImage(struct grubConfig *config, int hasNew, |
void setDefaultImage(struct grubConfig *config, int isAddingBootEntry, |
2521 |
const char *defaultKernelPath, int newIsDefault, |
const char *defaultKernelPath, int newBootEntryIsDefault, |
2522 |
const char *prefix, int flags, int index) |
const char *prefix, int flags, |
2523 |
{ |
int newDefaultBootEntryIndex, int newBootEntryIndex) |
2524 |
struct singleEntry *entry, *entry2, *newDefault; |
{ |
2525 |
int i, j; |
struct singleEntry *bootEntry, *newDefault; |
2526 |
|
int indexToVerify, firstKernelEntryIndex, currentLookupIndex; |
2527 |
if (newIsDefault) { |
|
2528 |
config->defaultImage = 0; |
/* initialize */ |
2529 |
|
currentLookupIndex = FIRST_ENTRY_INDEX; |
2530 |
|
|
2531 |
|
/* handle the two cases where the user explictly picks the default |
2532 |
|
* boot entry index as it would exist post-modification */ |
2533 |
|
|
2534 |
|
/* Case 1: user chose to make the latest boot entry the default */ |
2535 |
|
if (newBootEntryIsDefault) { |
2536 |
|
config->defaultImage = newBootEntryIndex; |
2537 |
return; |
return; |
2538 |
} else if ((index >= 0) && config->cfi->defaultIsIndex) { |
} |
2539 |
if (findEntryByIndex(config, index)) |
|
2540 |
config->defaultImage = index; |
/* Case 2: user picked an arbitrary index as the default boot entry */ |
2541 |
else |
if (newDefaultBootEntryIndex >= FIRST_ENTRY_INDEX |
2542 |
config->defaultImage = -1; |
&& config->cfi->defaultIsIndex) { |
2543 |
return; |
indexToVerify = newDefaultBootEntryIndex; |
2544 |
} else if (defaultKernelPath) { |
|
2545 |
i = 0; |
/* user chose to make latest boot entry the default */ |
2546 |
if (findEntryByPath(config, defaultKernelPath, prefix, &i)) { |
if (newDefaultBootEntryIndex == newBootEntryIndex) { |
2547 |
config->defaultImage = i; |
config->defaultImage = newBootEntryIndex; |
|
} else { |
|
|
config->defaultImage = -1; |
|
2548 |
return; |
return; |
2549 |
} |
} |
|
} |
|
2550 |
|
|
2551 |
/* defaultImage now points to what we'd like to use, but before any |
/* the user picks the default index based on the |
2552 |
* order changes */ |
* order of the bootloader configuration after |
2553 |
if ((config->defaultImage == DEFAULT_SAVED) || |
* modification; ensure we are checking for the |
2554 |
(config->defaultImage == DEFAULT_SAVED_GRUB2)) |
* existence of the correct entry */ |
2555 |
/* default is set to saved, we don't want to change it */ |
if (newBootEntryIndex < newDefaultBootEntryIndex) { |
2556 |
|
if (!config->isModified) |
2557 |
|
indexToVerify--; |
2558 |
|
} |
2559 |
|
|
2560 |
|
/* verify the user selected index will exist */ |
2561 |
|
if (findEntryByIndex(config, indexToVerify)) { |
2562 |
|
config->defaultImage = newDefaultBootEntryIndex; |
2563 |
|
} else { |
2564 |
|
config->defaultImage = NO_DEFAULT_ENTRY; |
2565 |
|
} |
2566 |
|
|
2567 |
return; |
return; |
2568 |
|
} |
2569 |
|
|
2570 |
if (config->defaultImage > -1) |
/* handle cases where the index value may shift */ |
|
entry = findEntryByIndex(config, config->defaultImage); |
|
|
else |
|
|
entry = NULL; |
|
2571 |
|
|
2572 |
if (entry && !entry->skip) { |
/* check validity of existing default or first-entry-found |
2573 |
/* we can preserve the default */ |
selection */ |
2574 |
if (hasNew) |
if (defaultKernelPath) { |
2575 |
config->defaultImage++; |
/* we must initialize this */ |
2576 |
|
firstKernelEntryIndex = 0; |
2577 |
|
/* user requested first-entry-found */ |
2578 |
|
if (!findEntryByPath(config, defaultKernelPath, |
2579 |
|
prefix, &firstKernelEntryIndex)) { |
2580 |
|
/* don't change default if can't find match */ |
2581 |
|
config->defaultImage = NO_DEFAULT_ENTRY; |
2582 |
|
return; |
2583 |
|
} |
2584 |
|
|
2585 |
|
config->defaultImage = firstKernelEntryIndex; |
2586 |
|
|
2587 |
/* count the number of entries erased before this one */ |
/* this is where we start looking for decrement later */ |
2588 |
for (j = 0; j < config->defaultImage; j++) { |
currentLookupIndex = config->defaultImage; |
2589 |
entry2 = findEntryByIndex(config, j); |
|
2590 |
if (entry2->skip) |
if (isAddingBootEntry && !config->isModified && |
2591 |
config->defaultImage--; |
(newBootEntryIndex < config->defaultImage)) { |
2592 |
|
/* increment because new entry added before default */ |
2593 |
|
config->defaultImage++; |
2594 |
} |
} |
|
} else if (hasNew) { |
|
|
config->defaultImage = 0; |
|
2595 |
} else { |
} else { |
2596 |
/* Either we just erased the default (or the default line was |
/* check to see if the default is stored in the environment */ |
2597 |
* bad to begin with) and didn't put a new one in. We'll use |
if (config->defaultImage < FIRST_ENTRY_INDEX) { |
2598 |
* the first valid image. */ |
if (config->defaultImage == DEFAULT_SAVED || config->defaultImage == DEFAULT_SAVED_GRUB2) |
2599 |
|
{ |
2600 |
|
if (config->cfi->defaultIsSaved) { |
2601 |
|
if (config->cfi->getEnv) { |
2602 |
|
char *defaultTitle = config->cfi->getEnv(config->cfi, "saved_entry"); |
2603 |
|
|
2604 |
|
if (defaultTitle) { |
2605 |
|
if (isnumber(defaultTitle)) { |
2606 |
|
currentLookupIndex = atoi(defaultTitle); |
2607 |
|
} else { |
2608 |
|
findEntryByTitle(config, defaultTitle, ¤tLookupIndex); |
2609 |
|
} |
2610 |
|
/* set the default Image to an actual index */ |
2611 |
|
config->defaultImage = currentLookupIndex; |
2612 |
|
} |
2613 |
|
} |
2614 |
|
} |
2615 |
|
} |
2616 |
|
} else { |
2617 |
|
/* use pre-existing default entry from the file*/ |
2618 |
|
currentLookupIndex = config->defaultImage; |
2619 |
|
} |
2620 |
|
|
2621 |
|
if (isAddingBootEntry |
2622 |
|
&& (newBootEntryIndex <= config->defaultImage)) { |
2623 |
|
config->defaultImage++; |
2624 |
|
|
2625 |
|
if (config->isModified) { |
2626 |
|
currentLookupIndex++; |
2627 |
|
} |
2628 |
|
} |
2629 |
|
} |
2630 |
|
|
2631 |
|
/* sanity check - is this entry index valid? */ |
2632 |
|
bootEntry = findEntryByIndex(config, currentLookupIndex); |
2633 |
|
|
2634 |
|
if ((bootEntry && bootEntry->skip) || !bootEntry) { |
2635 |
|
/* entry is to be skipped or is invalid */ |
2636 |
|
if (isAddingBootEntry) { |
2637 |
|
config->defaultImage = newBootEntryIndex; |
2638 |
|
return; |
2639 |
|
} |
2640 |
newDefault = |
newDefault = |
2641 |
findTemplate(config, prefix, &config->defaultImage, 1, |
findTemplate(config, prefix, &config->defaultImage, 1, |
2642 |
flags); |
flags); |
2643 |
if (!newDefault) |
if (!newDefault) { |
2644 |
config->defaultImage = -1; |
config->defaultImage = NO_DEFAULT_ENTRY; |
2645 |
|
} |
2646 |
|
|
2647 |
|
return; |
2648 |
|
} |
2649 |
|
|
2650 |
|
currentLookupIndex--; |
2651 |
|
|
2652 |
|
/* decrement index by the total number of entries deleted */ |
2653 |
|
|
2654 |
|
for (indexToVerify = currentLookupIndex; |
2655 |
|
indexToVerify >= FIRST_ENTRY_INDEX; indexToVerify--) { |
2656 |
|
|
2657 |
|
bootEntry = findEntryByIndex(config, indexToVerify); |
2658 |
|
|
2659 |
|
if (bootEntry && bootEntry->skip) { |
2660 |
|
config->defaultImage--; |
2661 |
|
} |
2662 |
} |
} |
2663 |
} |
} |
2664 |
|
|
4315 |
const char *newKernelArgs, const char *newKernelInitrd, |
const char *newKernelArgs, const char *newKernelInitrd, |
4316 |
const char **extraInitrds, int extraInitrdCount, |
const char **extraInitrds, int extraInitrdCount, |
4317 |
const char *newMBKernel, const char *newMBKernelArgs, |
const char *newMBKernel, const char *newMBKernelArgs, |
4318 |
const char *newDevTreePath) |
const char *newDevTreePath, int newIndex) |
4319 |
{ |
{ |
4320 |
struct singleEntry *new; |
struct singleEntry *new, *entry, *prev = NULL; |
4321 |
struct singleLine *newLine = NULL, *tmplLine = NULL, *masterLine = NULL; |
struct singleLine *newLine = NULL, *tmplLine = NULL, *masterLine = NULL; |
4322 |
int needs; |
int needs; |
4323 |
|
char *indexs; |
4324 |
char *chptr; |
char *chptr; |
4325 |
|
int rc; |
4326 |
|
|
4327 |
if (!newKernelPath) |
if (!newKernelPath) |
4328 |
return 0; |
return 0; |
4329 |
|
|
4330 |
|
rc = asprintf(&indexs, "%d", newIndex); |
4331 |
|
if (rc < 0) |
4332 |
|
return 1; |
4333 |
|
|
4334 |
/* if the newKernelTitle is too long silently munge it into something |
/* if the newKernelTitle is too long silently munge it into something |
4335 |
* we can live with. truncating is first check, then we'll just mess with |
* we can live with. truncating is first check, then we'll just mess with |
4336 |
* it until it looks better */ |
* it until it looks better */ |
4353 |
new = malloc(sizeof(*new)); |
new = malloc(sizeof(*new)); |
4354 |
new->skip = 0; |
new->skip = 0; |
4355 |
new->multiboot = 0; |
new->multiboot = 0; |
|
new->next = config->entries; |
|
4356 |
new->lines = NULL; |
new->lines = NULL; |
4357 |
config->entries = new; |
entry = config->entries; |
4358 |
|
for (unsigned int i = 0; i < newIndex; i++) { |
4359 |
|
if (!entry) |
4360 |
|
break; |
4361 |
|
prev = entry; |
4362 |
|
entry = entry->next; |
4363 |
|
} |
4364 |
|
new->next = entry; |
4365 |
|
|
4366 |
|
if (prev) |
4367 |
|
prev->next = new; |
4368 |
|
else |
4369 |
|
config->entries = new; |
4370 |
|
|
4371 |
/* copy/update from the template */ |
/* copy/update from the template */ |
4372 |
needs = NEED_KERNEL | NEED_TITLE; |
needs = NEED_KERNEL | NEED_TITLE; |
4829 |
abort(); |
abort(); |
4830 |
} |
} |
4831 |
|
|
4832 |
if (updateImage(config, "0", prefix, newKernelArgs, NULL, |
if (updateImage(config, indexs, prefix, newKernelArgs, NULL, |
4833 |
newMBKernelArgs, NULL)) |
newMBKernelArgs, NULL)) { |
4834 |
|
config->isModified = 1; |
4835 |
return 1; |
return 1; |
4836 |
|
} |
4837 |
|
|
4838 |
return 0; |
return 0; |
4839 |
} |
} |
4861 |
char *newDevTreePath = NULL; |
char *newDevTreePath = NULL; |
4862 |
char *newMBKernel = NULL; |
char *newMBKernel = NULL; |
4863 |
char *newMBKernelArgs = NULL; |
char *newMBKernelArgs = NULL; |
4864 |
|
int newIndex = 0; |
4865 |
char *removeMBKernelArgs = NULL; |
char *removeMBKernelArgs = NULL; |
4866 |
char *removeMBKernel = NULL; |
char *removeMBKernel = NULL; |
4867 |
char *bootPrefix = NULL; |
char *bootPrefix = NULL; |
4896 |
NULL}, |
NULL}, |
4897 |
{"boot-filesystem", 0, POPT_ARG_STRING, &bootPrefix, 0, |
{"boot-filesystem", 0, POPT_ARG_STRING, &bootPrefix, 0, |
4898 |
_ |
_ |
4899 |
("filestystem which contains /boot directory (for testing only)"), |
("filesystem which contains /boot directory (for testing only)"), |
4900 |
_("bootfs")}, |
_("bootfs")}, |
4901 |
#if defined(__i386__) || defined(__x86_64__) || defined (__powerpc64__) || defined (__ia64__) |
#if defined(__i386__) || defined(__x86_64__) || defined (__powerpc64__) || defined (__ia64__) |
4902 |
{"bootloader-probe", 0, POPT_ARG_NONE, &bootloaderProbe, 0, |
{"bootloader-probe", 0, POPT_ARG_NONE, &bootloaderProbe, 0, |
4968 |
{"set-default-index", 0, POPT_ARG_INT, &defaultIndex, 0, |
{"set-default-index", 0, POPT_ARG_INT, &defaultIndex, 0, |
4969 |
_("make the given entry index the default entry"), |
_("make the given entry index the default entry"), |
4970 |
_("entry-index")}, |
_("entry-index")}, |
4971 |
|
{"set-index", 0, POPT_ARG_INT, &newIndex, 0, |
4972 |
|
_("use the given index when creating a new entry"), |
4973 |
|
_("entry-index")}, |
4974 |
{"silo", 0, POPT_ARG_NONE, &configureSilo, 0, |
{"silo", 0, POPT_ARG_NONE, &configureSilo, 0, |
4975 |
_("configure silo bootloader")}, |
_("configure silo bootloader")}, |
4976 |
{"title", 0, POPT_ARG_STRING, &newKernelTitle, 0, |
{"title", 0, POPT_ARG_STRING, &newKernelTitle, 0, |
5285 |
struct singleEntry *entry; |
struct singleEntry *entry; |
5286 |
char *rootspec; |
char *rootspec; |
5287 |
|
|
5288 |
if (config->defaultImage == -1) |
if (config->defaultImage == NO_DEFAULT_ENTRY) |
5289 |
return 0; |
return 0; |
5290 |
if (config->defaultImage == DEFAULT_SAVED_GRUB2 && |
if (config->defaultImage == DEFAULT_SAVED_GRUB2 && |
5291 |
cfi->defaultIsSaved) |
cfi->defaultIsSaved) |
5292 |
config->defaultImage = 0; |
config->defaultImage = FIRST_ENTRY_INDEX; |
5293 |
entry = findEntryByIndex(config, config->defaultImage); |
entry = findEntryByIndex(config, config->defaultImage); |
5294 |
if (!entry) |
if (!entry) |
5295 |
return 0; |
return 0; |
5312 |
struct singleLine *line; |
struct singleLine *line; |
5313 |
struct singleEntry *entry; |
struct singleEntry *entry; |
5314 |
|
|
5315 |
if (config->defaultImage == -1) |
if (config->defaultImage == NO_DEFAULT_ENTRY) |
5316 |
return 0; |
return 0; |
5317 |
if (config->defaultImage == DEFAULT_SAVED_GRUB2 && |
if (config->defaultImage == DEFAULT_SAVED_GRUB2 && |
5318 |
cfi->defaultIsSaved) |
cfi->defaultIsSaved) |
5319 |
config->defaultImage = 0; |
config->defaultImage = FIRST_ENTRY_INDEX; |
5320 |
entry = findEntryByIndex(config, config->defaultImage); |
entry = findEntryByIndex(config, config->defaultImage); |
5321 |
if (!entry) |
if (!entry) |
5322 |
return 0; |
return 0; |
5346 |
return 0; |
return 0; |
5347 |
|
|
5348 |
} else if (displayDefaultIndex) { |
} else if (displayDefaultIndex) { |
5349 |
if (config->defaultImage == -1) |
if (config->defaultImage == NO_DEFAULT_ENTRY) |
5350 |
return 0; |
return 0; |
5351 |
if (config->defaultImage == DEFAULT_SAVED_GRUB2 && |
if (config->defaultImage == DEFAULT_SAVED_GRUB2 && |
5352 |
cfi->defaultIsSaved) |
cfi->defaultIsSaved) |
5353 |
config->defaultImage = 0; |
config->defaultImage = FIRST_ENTRY_INDEX; |
5354 |
printf("%i\n", config->defaultImage); |
printf("%i\n", config->defaultImage); |
5355 |
return 0; |
return 0; |
5356 |
|
|
5366 |
markRemovedImage(config, removeKernelPath, bootPrefix); |
markRemovedImage(config, removeKernelPath, bootPrefix); |
5367 |
markRemovedImage(config, removeMBKernel, bootPrefix); |
markRemovedImage(config, removeMBKernel, bootPrefix); |
5368 |
setDefaultImage(config, newKernelPath != NULL, defaultKernel, |
setDefaultImage(config, newKernelPath != NULL, defaultKernel, |
5369 |
makeDefault, bootPrefix, flags, defaultIndex); |
makeDefault, bootPrefix, flags, defaultIndex, |
5370 |
|
newIndex); |
5371 |
setFallbackImage(config, newKernelPath != NULL); |
setFallbackImage(config, newKernelPath != NULL); |
5372 |
if (updateImage(config, updateKernelPath, bootPrefix, newKernelArgs, |
if (updateImage(config, updateKernelPath, bootPrefix, newKernelArgs, |
5373 |
removeArgs, newMBKernelArgs, removeMBKernelArgs)) |
removeArgs, newMBKernelArgs, removeMBKernelArgs)) |
5387 |
if (addNewKernel(config, template, bootPrefix, newKernelPath, |
if (addNewKernel(config, template, bootPrefix, newKernelPath, |
5388 |
newKernelTitle, newKernelArgs, newKernelInitrd, |
newKernelTitle, newKernelArgs, newKernelInitrd, |
5389 |
(const char **)extraInitrds, extraInitrdCount, |
(const char **)extraInitrds, extraInitrdCount, |
5390 |
newMBKernel, newMBKernelArgs, newDevTreePath)) |
newMBKernel, newMBKernelArgs, newDevTreePath, |
5391 |
|
newIndex)) |
5392 |
return 1; |
return 1; |
5393 |
|
|
5394 |
if (numEntries(config) == 0) { |
if (numEntries(config) == 0) { |