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; |
701 |
struct configFileInfo *cfi); |
struct configFileInfo *cfi); |
702 |
static int getNextLine(char **bufPtr, struct singleLine *line, |
static int getNextLine(char **bufPtr, struct singleLine *line, |
703 |
struct configFileInfo *cfi); |
struct configFileInfo *cfi); |
704 |
static char *getRootSpecifier(char *str); |
static size_t getRootSpecifier(const char *str); |
705 |
static void requote(struct singleLine *line, struct configFileInfo *cfi); |
static void requote(struct singleLine *line, struct configFileInfo *cfi); |
706 |
static void insertElement(struct singleLine *line, |
static void insertElement(struct singleLine *line, |
707 |
const char *item, int insertHere, |
const char *item, int insertHere, |
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) { |
1622 |
*end == ' ' || *end == '\t')) |
*end == ' ' || *end == '\t')) |
1623 |
end++; |
end++; |
1624 |
if (*end) |
if (*end) |
1625 |
cfg->defaultImage = -1; |
cfg->defaultImage = NO_DEFAULT_ENTRY; |
1626 |
} else if (defaultLine->numElements == 3) { |
} else if (defaultLine->numElements == 3) { |
1627 |
char *value = defaultLine->elements[2].item; |
char *value = defaultLine->elements[2].item; |
1628 |
while (*value && (*value == '"' || |
while (*value && (*value == '"' || |
1635 |
*end == ' ' || *end == '\t')) |
*end == ' ' || *end == '\t')) |
1636 |
end++; |
end++; |
1637 |
if (*end) |
if (*end) |
1638 |
cfg->defaultImage = -1; |
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", |
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, |
1792 |
int needs = MAIN_DEFAULT; |
int needs = MAIN_DEFAULT; |
1793 |
struct stat sb; |
struct stat sb; |
1794 |
int i; |
int i; |
1795 |
|
int rc = 0; |
1796 |
|
|
1797 |
if (!strcmp(outName, "-")) { |
if (!strcmp(outName, "-")) { |
1798 |
out = stdout; |
out = stdout; |
1907 |
} |
} |
1908 |
|
|
1909 |
if (tmpOutName) { |
if (tmpOutName) { |
1910 |
if (rename(tmpOutName, outName)) { |
/* write userspace buffers */ |
1911 |
fprintf(stderr, |
if (fflush(out)) |
1912 |
_("grubby: error moving %s to %s: %s\n"), |
rc = 1; |
1913 |
tmpOutName, outName, strerror(errno)); |
|
1914 |
unlink(outName); |
/* purge the write-back cache with fsync() */ |
1915 |
return 1; |
if (fsync(fileno(out))) |
1916 |
|
rc = 1; |
1917 |
|
|
1918 |
|
if (fclose(out)) |
1919 |
|
rc = 1; |
1920 |
|
|
1921 |
|
if (rc == 0 && rename(tmpOutName, outName)) { |
1922 |
|
unlink(tmpOutName); |
1923 |
|
rc = 1; |
1924 |
|
} |
1925 |
|
|
1926 |
|
/* fsync() the destination directory after rename */ |
1927 |
|
if (rc == 0) { |
1928 |
|
int dirfd; |
1929 |
|
|
1930 |
|
dirfd = open(dirname(strdupa(outName)), O_RDONLY); |
1931 |
|
if (dirfd < 0) |
1932 |
|
rc = 1; |
1933 |
|
else if (fsync(dirfd)) |
1934 |
|
rc = 1; |
1935 |
|
|
1936 |
|
if (dirfd >= 0) |
1937 |
|
close(dirfd); |
1938 |
} |
} |
1939 |
|
|
1940 |
|
if (rc == 1) |
1941 |
|
fprintf(stderr, |
1942 |
|
_("grubby: error flushing data: %m\n")); |
1943 |
} |
} |
1944 |
|
|
1945 |
return 0; |
return rc; |
1946 |
} |
} |
1947 |
|
|
1948 |
static int numEntries(struct grubConfig *cfg) |
static int numEntries(struct grubConfig *cfg) |
2125 |
char *fullName; |
char *fullName; |
2126 |
int i; |
int i; |
2127 |
char *dev; |
char *dev; |
2128 |
char *rootspec; |
size_t rs; |
2129 |
char *rootdev; |
char *rootdev; |
2130 |
|
|
2131 |
if (skipRemoved && entry->skip) { |
if (skipRemoved && entry->skip) { |
2153 |
|
|
2154 |
fullName = alloca(strlen(bootPrefix) + |
fullName = alloca(strlen(bootPrefix) + |
2155 |
strlen(line->elements[1].item) + 1); |
strlen(line->elements[1].item) + 1); |
2156 |
rootspec = getRootSpecifier(line->elements[1].item); |
rs = getRootSpecifier(line->elements[1].item); |
|
int rootspec_offset = rootspec ? strlen(rootspec) : 0; |
|
2157 |
int hasslash = endswith(bootPrefix, '/') || |
int hasslash = endswith(bootPrefix, '/') || |
2158 |
beginswith(line->elements[1].item + rootspec_offset, '/'); |
beginswith(line->elements[1].item + rs, '/'); |
2159 |
sprintf(fullName, "%s%s%s", bootPrefix, hasslash ? "" : "/", |
sprintf(fullName, "%s%s%s", bootPrefix, hasslash ? "" : "/", |
2160 |
line->elements[1].item + rootspec_offset); |
line->elements[1].item + rs); |
2161 |
if (access(fullName, R_OK)) { |
if (access(fullName, R_OK)) { |
2162 |
notSuitablePrintf(entry, 0, "access to %s failed\n", fullName); |
notSuitablePrintf(entry, 0, "access to %s failed\n", fullName); |
2163 |
return 0; |
return 0; |
2249 |
struct singleLine *line; |
struct singleLine *line; |
2250 |
int i; |
int i; |
2251 |
char *chptr; |
char *chptr; |
|
char *rootspec = NULL; |
|
2252 |
enum lineType_e checkType = LT_KERNEL; |
enum lineType_e checkType = LT_KERNEL; |
2253 |
|
|
2254 |
if (isdigit(*kernel)) { |
if (isdigit(*kernel)) { |
2353 |
|
|
2354 |
if (line && line->type != LT_MENUENTRY && |
if (line && line->type != LT_MENUENTRY && |
2355 |
line->numElements >= 2) { |
line->numElements >= 2) { |
2356 |
rootspec = |
if (!strcmp(line->elements[1].item + |
2357 |
getRootSpecifier(line->elements[1]. |
getRootSpecifier( |
2358 |
item); |
line->elements[1].item), |
2359 |
if (!strcmp |
kernel + strlen(prefix))) |
|
(line->elements[1].item + |
|
|
((rootspec != |
|
|
NULL) ? strlen(rootspec) : 0), |
|
|
kernel + strlen(prefix))) |
|
2360 |
break; |
break; |
2361 |
} |
} |
2362 |
if (line->type == LT_MENUENTRY && |
if (line->type == LT_MENUENTRY && |
2461 |
} |
} |
2462 |
} |
} |
2463 |
} |
} |
2464 |
} else if (cfg->defaultImage > -1) { |
} else if (cfg->defaultImage >= FIRST_ENTRY_INDEX) { |
2465 |
entry = findEntryByIndex(cfg, cfg->defaultImage); |
entry = findEntryByIndex(cfg, cfg->defaultImage); |
2466 |
if (entry && suitableImage(entry, prefix, skipRemoved, flags)) { |
if (entry && suitableImage(entry, prefix, skipRemoved, flags)) { |
2467 |
if (indexPtr) |
if (indexPtr) |
2473 |
index = 0; |
index = 0; |
2474 |
while ((entry = findEntryByIndex(cfg, index))) { |
while ((entry = findEntryByIndex(cfg, index))) { |
2475 |
if (suitableImage(entry, prefix, skipRemoved, flags)) { |
if (suitableImage(entry, prefix, skipRemoved, flags)) { |
2476 |
int j; |
int j, unmodifiedIndex; |
2477 |
for (j = 0; j < index; j++) { |
|
2478 |
|
unmodifiedIndex = index; |
2479 |
|
|
2480 |
|
for (j = 0; j < unmodifiedIndex; j++) { |
2481 |
entry2 = findEntryByIndex(cfg, j); |
entry2 = findEntryByIndex(cfg, j); |
2482 |
if (entry2->skip) |
if (entry2->skip) |
2483 |
index--; |
index--; |
2538 |
entry->skip = 1; |
entry->skip = 1; |
2539 |
} |
} |
2540 |
|
|
2541 |
void setDefaultImage(struct grubConfig *config, int hasNew, |
void setDefaultImage(struct grubConfig *config, int isAddingBootEntry, |
2542 |
const char *defaultKernelPath, int newIsDefault, |
const char *defaultKernelPath, int newBootEntryIsDefault, |
2543 |
const char *prefix, int flags, int index) |
const char *prefix, int flags, |
2544 |
{ |
int newDefaultBootEntryIndex, int newBootEntryIndex) |
2545 |
struct singleEntry *entry, *entry2, *newDefault; |
{ |
2546 |
int i, j; |
struct singleEntry *bootEntry, *newDefault; |
2547 |
|
int indexToVerify, firstKernelEntryIndex, currentLookupIndex; |
2548 |
if (newIsDefault) { |
|
2549 |
config->defaultImage = 0; |
/* initialize */ |
2550 |
|
currentLookupIndex = FIRST_ENTRY_INDEX; |
2551 |
|
|
2552 |
|
/* handle the two cases where the user explictly picks the default |
2553 |
|
* boot entry index as it would exist post-modification */ |
2554 |
|
|
2555 |
|
/* Case 1: user chose to make the latest boot entry the default */ |
2556 |
|
if (newBootEntryIsDefault) { |
2557 |
|
config->defaultImage = newBootEntryIndex; |
2558 |
return; |
return; |
2559 |
} else if ((index >= 0) && config->cfi->defaultIsIndex) { |
} |
2560 |
if (findEntryByIndex(config, index)) |
|
2561 |
config->defaultImage = index; |
/* Case 2: user picked an arbitrary index as the default boot entry */ |
2562 |
else |
if (newDefaultBootEntryIndex >= FIRST_ENTRY_INDEX) { |
2563 |
config->defaultImage = -1; |
indexToVerify = newDefaultBootEntryIndex; |
2564 |
return; |
|
2565 |
} else if (defaultKernelPath) { |
/* user chose to make latest boot entry the default */ |
2566 |
i = 0; |
if (newDefaultBootEntryIndex == newBootEntryIndex) { |
2567 |
if (findEntryByPath(config, defaultKernelPath, prefix, &i)) { |
config->defaultImage = newBootEntryIndex; |
|
config->defaultImage = i; |
|
|
} else { |
|
|
config->defaultImage = -1; |
|
2568 |
return; |
return; |
2569 |
} |
} |
|
} |
|
2570 |
|
|
2571 |
/* defaultImage now points to what we'd like to use, but before any |
/* the user picks the default index based on the |
2572 |
* order changes */ |
* order of the bootloader configuration after |
2573 |
if ((config->defaultImage == DEFAULT_SAVED) || |
* modification; ensure we are checking for the |
2574 |
(config->defaultImage == DEFAULT_SAVED_GRUB2)) |
* existence of the correct entry */ |
2575 |
/* default is set to saved, we don't want to change it */ |
if (newBootEntryIndex < newDefaultBootEntryIndex) { |
2576 |
|
if (!config->isModified) |
2577 |
|
indexToVerify--; |
2578 |
|
} |
2579 |
|
|
2580 |
|
/* verify the user selected index will exist */ |
2581 |
|
if (findEntryByIndex(config, indexToVerify)) { |
2582 |
|
config->defaultImage = newDefaultBootEntryIndex; |
2583 |
|
} else { |
2584 |
|
config->defaultImage = NO_DEFAULT_ENTRY; |
2585 |
|
} |
2586 |
|
|
2587 |
return; |
return; |
2588 |
|
} |
2589 |
|
|
2590 |
if (config->defaultImage > -1) |
/* handle cases where the index value may shift */ |
|
entry = findEntryByIndex(config, config->defaultImage); |
|
|
else |
|
|
entry = NULL; |
|
2591 |
|
|
2592 |
if (entry && !entry->skip) { |
/* check validity of existing default or first-entry-found |
2593 |
/* we can preserve the default */ |
selection */ |
2594 |
if (hasNew) |
if (defaultKernelPath) { |
2595 |
config->defaultImage++; |
/* we must initialize this */ |
2596 |
|
firstKernelEntryIndex = 0; |
2597 |
|
/* user requested first-entry-found */ |
2598 |
|
if (!findEntryByPath(config, defaultKernelPath, |
2599 |
|
prefix, &firstKernelEntryIndex)) { |
2600 |
|
/* don't change default if can't find match */ |
2601 |
|
config->defaultImage = NO_DEFAULT_ENTRY; |
2602 |
|
return; |
2603 |
|
} |
2604 |
|
|
2605 |
|
config->defaultImage = firstKernelEntryIndex; |
2606 |
|
|
2607 |
|
/* this is where we start looking for decrement later */ |
2608 |
|
currentLookupIndex = config->defaultImage; |
2609 |
|
|
2610 |
/* count the number of entries erased before this one */ |
if (isAddingBootEntry && !config->isModified && |
2611 |
for (j = 0; j < config->defaultImage; j++) { |
(newBootEntryIndex < config->defaultImage)) { |
2612 |
entry2 = findEntryByIndex(config, j); |
/* increment because new entry added before default */ |
2613 |
if (entry2->skip) |
config->defaultImage++; |
|
config->defaultImage--; |
|
2614 |
} |
} |
|
} else if (hasNew) { |
|
|
config->defaultImage = 0; |
|
2615 |
} else { |
} else { |
2616 |
/* Either we just erased the default (or the default line was |
/* check to see if the default is stored in the environment */ |
2617 |
* bad to begin with) and didn't put a new one in. We'll use |
if (config->defaultImage < FIRST_ENTRY_INDEX) { |
2618 |
* the first valid image. */ |
if (config->defaultImage == DEFAULT_SAVED || config->defaultImage == DEFAULT_SAVED_GRUB2) |
2619 |
|
{ |
2620 |
|
if (config->cfi->defaultIsSaved) { |
2621 |
|
if (config->cfi->getEnv) { |
2622 |
|
char *defaultTitle = config->cfi->getEnv(config->cfi, "saved_entry"); |
2623 |
|
|
2624 |
|
if (defaultTitle) { |
2625 |
|
if (isnumber(defaultTitle)) { |
2626 |
|
currentLookupIndex = atoi(defaultTitle); |
2627 |
|
} else { |
2628 |
|
findEntryByTitle(config, defaultTitle, ¤tLookupIndex); |
2629 |
|
} |
2630 |
|
/* set the default Image to an actual index */ |
2631 |
|
config->defaultImage = currentLookupIndex; |
2632 |
|
} |
2633 |
|
} |
2634 |
|
} |
2635 |
|
} |
2636 |
|
} else { |
2637 |
|
/* use pre-existing default entry from the file*/ |
2638 |
|
currentLookupIndex = config->defaultImage; |
2639 |
|
} |
2640 |
|
|
2641 |
|
if (isAddingBootEntry |
2642 |
|
&& (newBootEntryIndex <= config->defaultImage)) { |
2643 |
|
config->defaultImage++; |
2644 |
|
|
2645 |
|
if (config->isModified) { |
2646 |
|
currentLookupIndex++; |
2647 |
|
} |
2648 |
|
} |
2649 |
|
} |
2650 |
|
|
2651 |
|
/* sanity check - is this entry index valid? */ |
2652 |
|
bootEntry = findEntryByIndex(config, currentLookupIndex); |
2653 |
|
|
2654 |
|
if ((bootEntry && bootEntry->skip) || !bootEntry) { |
2655 |
|
/* entry is to be skipped or is invalid */ |
2656 |
|
if (isAddingBootEntry) { |
2657 |
|
config->defaultImage = newBootEntryIndex; |
2658 |
|
return; |
2659 |
|
} |
2660 |
newDefault = |
newDefault = |
2661 |
findTemplate(config, prefix, &config->defaultImage, 1, |
findTemplate(config, prefix, &config->defaultImage, 1, |
2662 |
flags); |
flags); |
2663 |
if (!newDefault) |
if (!newDefault) { |
2664 |
config->defaultImage = -1; |
config->defaultImage = NO_DEFAULT_ENTRY; |
2665 |
|
} |
2666 |
|
|
2667 |
|
return; |
2668 |
|
} |
2669 |
|
|
2670 |
|
currentLookupIndex--; |
2671 |
|
|
2672 |
|
/* decrement index by the total number of entries deleted */ |
2673 |
|
|
2674 |
|
for (indexToVerify = currentLookupIndex; |
2675 |
|
indexToVerify >= FIRST_ENTRY_INDEX; indexToVerify--) { |
2676 |
|
|
2677 |
|
bootEntry = findEntryByIndex(config, indexToVerify); |
2678 |
|
|
2679 |
|
if (bootEntry && bootEntry->skip) { |
2680 |
|
config->defaultImage--; |
2681 |
|
} |
2682 |
} |
} |
2683 |
} |
} |
2684 |
|
|
2707 |
} |
} |
2708 |
} |
} |
2709 |
|
|
2710 |
void displayEntry(struct singleEntry *entry, const char *prefix, int index) |
void displayEntry(struct grubConfig *config, struct singleEntry *entry, const char *prefix, int index) |
2711 |
{ |
{ |
2712 |
struct singleLine *line; |
struct singleLine *line; |
2713 |
char *root = NULL; |
char *root = NULL; |
2803 |
|
|
2804 |
line = getLineByType(LT_TITLE, entry->lines); |
line = getLineByType(LT_TITLE, entry->lines); |
2805 |
if (line) { |
if (line) { |
2806 |
printf("title=%s\n", line->elements[1].item); |
char *entryTitle; |
2807 |
|
/* if we can extractTitle, then it's a zipl config and |
2808 |
|
* if not then we go ahead with what's existed prior */ |
2809 |
|
entryTitle = extractTitle(config, line); |
2810 |
|
if (!entryTitle) { |
2811 |
|
entryTitle=line->elements[1].item; |
2812 |
|
} |
2813 |
|
printf("title=%s\n", entryTitle); |
2814 |
} else { |
} else { |
2815 |
char *title; |
char *title; |
2816 |
line = getLineByType(LT_MENUENTRY, entry->lines); |
line = getLineByType(LT_MENUENTRY, entry->lines); |
3226 |
printf("lba\n"); |
printf("lba\n"); |
3227 |
} |
} |
3228 |
|
|
3229 |
displayEntry(entry, prefix, i); |
displayEntry(config, entry, prefix, i); |
3230 |
|
|
3231 |
i++; |
i++; |
3232 |
while ((entry = findEntryByPath(config, kernel, prefix, &i))) { |
while ((entry = findEntryByPath(config, kernel, prefix, &i))) { |
3233 |
displayEntry(entry, prefix, i); |
displayEntry(config, entry, prefix, i); |
3234 |
i++; |
i++; |
3235 |
} |
} |
3236 |
|
|
3265 |
type & (LT_HYPER | LT_KERNEL | LT_MBMODULE | LT_INITRD | |
type & (LT_HYPER | LT_KERNEL | LT_MBMODULE | LT_INITRD | |
3266 |
LT_KERNEL_EFI | LT_INITRD_EFI | LT_KERNEL_16 | |
LT_KERNEL_EFI | LT_INITRD_EFI | LT_KERNEL_16 | |
3267 |
LT_INITRD_16)) { |
LT_INITRD_16)) { |
3268 |
char *rootspec = |
size_t rs = getRootSpecifier(tmplLine->elements[1].item); |
3269 |
getRootSpecifier(tmplLine->elements[1].item); |
if (rs > 0) { |
|
if (rootspec != NULL) { |
|
3270 |
free(newLine->elements[1].item); |
free(newLine->elements[1].item); |
3271 |
newLine->elements[1].item = |
newLine->elements[1].item = sdupprintf( |
3272 |
sdupprintf("%s%s", rootspec, val); |
"%.*s%s", (int) rs, |
3273 |
|
tmplLine->elements[1].item, val); |
3274 |
} |
} |
3275 |
} |
} |
3276 |
} |
} |
3560 |
line->numElements--; |
line->numElements--; |
3561 |
} |
} |
3562 |
|
|
3563 |
int argMatch(const char *one, const char *two) |
static int argNameMatch(const char *one, const char *two) |
3564 |
{ |
{ |
3565 |
char *first, *second; |
char *first, *second; |
3566 |
char *chptr; |
char *chptra, *chptrb; |
3567 |
|
int rc; |
3568 |
|
|
3569 |
first = strcpy(alloca(strlen(one) + 1), one); |
first = strcpy(alloca(strlen(one) + 1), one); |
3570 |
second = strcpy(alloca(strlen(two) + 1), two); |
second = strcpy(alloca(strlen(two) + 1), two); |
3571 |
|
|
3572 |
chptr = strchr(first, '='); |
chptra = strchr(first, '='); |
3573 |
if (chptr) |
if (chptra) |
3574 |
*chptr = '\0'; |
*chptra = '\0'; |
3575 |
|
|
3576 |
|
chptrb = strchr(second, '='); |
3577 |
|
if (chptrb) |
3578 |
|
*chptrb = '\0'; |
3579 |
|
|
3580 |
|
rc = strcmp(first, second); |
3581 |
|
|
3582 |
|
if (chptra) |
3583 |
|
*chptra = '='; |
3584 |
|
if (chptrb) |
3585 |
|
*chptrb = '='; |
3586 |
|
|
3587 |
|
return rc; |
3588 |
|
} |
3589 |
|
|
3590 |
|
static int argHasValue(const char *arg) |
3591 |
|
{ |
3592 |
|
char *chptr; |
3593 |
|
|
3594 |
chptr = strchr(second, '='); |
chptr = strchr(arg, '='); |
3595 |
if (chptr) |
if (chptr) |
3596 |
*chptr = '\0'; |
return 1; |
3597 |
|
return 0; |
3598 |
|
} |
3599 |
|
|
3600 |
|
static int argValueMatch(const char *one, const char *two) |
3601 |
|
{ |
3602 |
|
char *first, *second; |
3603 |
|
char *chptra, *chptrb; |
3604 |
|
|
3605 |
return strcmp(first, second); |
first = strcpy(alloca(strlen(one) + 1), one); |
3606 |
|
second = strcpy(alloca(strlen(two) + 1), two); |
3607 |
|
|
3608 |
|
chptra = strchr(first, '='); |
3609 |
|
if (chptra) |
3610 |
|
chptra += 1; |
3611 |
|
|
3612 |
|
chptrb = strchr(second, '='); |
3613 |
|
if (chptrb) |
3614 |
|
chptrb += 1; |
3615 |
|
|
3616 |
|
if (!chptra && !chptrb) |
3617 |
|
return 0; |
3618 |
|
else if (!chptra) |
3619 |
|
return *chptrb - 0; |
3620 |
|
else if (!chptrb) |
3621 |
|
return 0 - *chptra; |
3622 |
|
else |
3623 |
|
return strcmp(chptra, chptrb); |
3624 |
} |
} |
3625 |
|
|
3626 |
int updateActualImage(struct grubConfig *cfg, const char *image, |
int updateActualImage(struct grubConfig *cfg, const char *image, |
3764 |
} |
} |
3765 |
if (usedElements[i]) |
if (usedElements[i]) |
3766 |
continue; |
continue; |
3767 |
if (!argMatch(line->elements[i].item, *arg)) { |
if (!argNameMatch(line->elements[i].item, *arg)) { |
3768 |
usedElements[i] = 1; |
usedElements[i] = 1; |
3769 |
break; |
break; |
3770 |
} |
} |
3823 |
!strcmp(line->elements[i].item, "--")) |
!strcmp(line->elements[i].item, "--")) |
3824 |
/* reached the end of hyper args, stop here */ |
/* reached the end of hyper args, stop here */ |
3825 |
break; |
break; |
3826 |
if (!argMatch(line->elements[i].item, *arg)) { |
if (!argNameMatch(line->elements[i].item, *arg)) { |
3827 |
removeElement(line, i); |
if (!argHasValue(*arg) || |
3828 |
break; |
!argValueMatch(line->elements[i].item, *arg)) { |
3829 |
|
removeElement(line, i); |
3830 |
|
break; |
3831 |
|
} |
3832 |
} |
} |
3833 |
} |
} |
3834 |
/* handle removing LT_ROOT line too */ |
/* handle removing LT_ROOT line too */ |
4322 |
return 1; |
return 1; |
4323 |
} |
} |
4324 |
|
|
4325 |
static char *getRootSpecifier(char *str) |
static size_t getRootSpecifier(const char *str) |
4326 |
{ |
{ |
4327 |
char *idx, *rootspec = NULL; |
size_t rs = 0; |
4328 |
|
|
4329 |
if (*str == '(') { |
if (*str == '(') { |
4330 |
idx = rootspec = strdup(str); |
for (; str[rs] != ')' && !isspace(str[rs]); rs++) { |
4331 |
while (*idx && (*idx != ')') && (!isspace(*idx))) |
if (!str[rs]) |
4332 |
idx++; |
return rs; |
4333 |
*(++idx) = '\0'; |
} |
4334 |
|
rs++; |
4335 |
} |
} |
4336 |
return rootspec; |
|
4337 |
|
return rs; |
4338 |
} |
} |
4339 |
|
|
4340 |
static char *getInitrdVal(struct grubConfig *config, |
static char *getInitrdVal(struct grubConfig *config, |
4396 |
struct singleEntry *new, *entry, *prev = NULL; |
struct singleEntry *new, *entry, *prev = NULL; |
4397 |
struct singleLine *newLine = NULL, *tmplLine = NULL, *masterLine = NULL; |
struct singleLine *newLine = NULL, *tmplLine = NULL, *masterLine = NULL; |
4398 |
int needs; |
int needs; |
4399 |
|
char *indexs; |
4400 |
char *chptr; |
char *chptr; |
4401 |
|
int rc; |
4402 |
|
|
4403 |
if (!newKernelPath) |
if (!newKernelPath) |
4404 |
return 0; |
return 0; |
4405 |
|
|
4406 |
|
rc = asprintf(&indexs, "%d", newIndex); |
4407 |
|
if (rc < 0) |
4408 |
|
return 1; |
4409 |
|
|
4410 |
/* if the newKernelTitle is too long silently munge it into something |
/* if the newKernelTitle is too long silently munge it into something |
4411 |
* 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 |
4412 |
* it until it looks better */ |
* it until it looks better */ |
4905 |
abort(); |
abort(); |
4906 |
} |
} |
4907 |
|
|
4908 |
if (updateImage(config, "0", prefix, newKernelArgs, NULL, |
if (updateImage(config, indexs, prefix, newKernelArgs, NULL, |
4909 |
newMBKernelArgs, NULL)) |
newMBKernelArgs, NULL)) { |
4910 |
|
config->isModified = 1; |
4911 |
return 1; |
return 1; |
4912 |
|
} |
4913 |
|
|
4914 |
return 0; |
return 0; |
4915 |
} |
} |
4972 |
NULL}, |
NULL}, |
4973 |
{"boot-filesystem", 0, POPT_ARG_STRING, &bootPrefix, 0, |
{"boot-filesystem", 0, POPT_ARG_STRING, &bootPrefix, 0, |
4974 |
_ |
_ |
4975 |
("filestystem which contains /boot directory (for testing only)"), |
("filesystem which contains /boot directory (for testing only)"), |
4976 |
_("bootfs")}, |
_("bootfs")}, |
4977 |
#if defined(__i386__) || defined(__x86_64__) || defined (__powerpc64__) || defined (__ia64__) |
#if defined(__i386__) || defined(__x86_64__) || defined (__powerpc64__) || defined (__ia64__) |
4978 |
{"bootloader-probe", 0, POPT_ARG_NONE, &bootloaderProbe, 0, |
{"bootloader-probe", 0, POPT_ARG_NONE, &bootloaderProbe, 0, |
5150 |
if (!cfi) { |
if (!cfi) { |
5151 |
if (grub2FindConfig(&grub2ConfigType)) { |
if (grub2FindConfig(&grub2ConfigType)) { |
5152 |
cfi = &grub2ConfigType; |
cfi = &grub2ConfigType; |
5153 |
|
configureGrub2 = 1; |
5154 |
if (envPath) |
if (envPath) |
5155 |
cfi->envFile = envPath; |
cfi->envFile = envPath; |
5156 |
} else |
} else { |
5157 |
#ifdef __ia64__ |
#ifdef __ia64__ |
5158 |
cfi = &eliloConfigType; |
cfi = &eliloConfigType; |
5159 |
#elif __powerpc__ |
configureLilo = 1; |
5160 |
|
#elif defined(__powerpc__) |
5161 |
cfi = &yabootConfigType; |
cfi = &yabootConfigType; |
5162 |
#elif __sparc__ |
configureYaboot = 1; |
5163 |
|
#elif defined(__sparc__) |
5164 |
cfi = &siloConfigType; |
cfi = &siloConfigType; |
5165 |
#elif __s390__ |
configureSilo = 1; |
5166 |
|
#elif defined(__s390__) || defined(__s390x__) |
5167 |
cfi = &ziplConfigType; |
cfi = &ziplConfigType; |
5168 |
#elif __s390x__ |
configureZipl = 1; |
|
cfi = &ziplConfigtype; |
|
5169 |
#else |
#else |
5170 |
cfi = &grubConfigType; |
cfi = &grubConfigType; |
5171 |
|
configureGrub = 1; |
5172 |
#endif |
#endif |
5173 |
|
} |
5174 |
} |
} |
5175 |
|
|
5176 |
if (!grubConfig) { |
if (!grubConfig) { |
5364 |
if (displayDefault) { |
if (displayDefault) { |
5365 |
struct singleLine *line; |
struct singleLine *line; |
5366 |
struct singleEntry *entry; |
struct singleEntry *entry; |
5367 |
char *rootspec; |
size_t rs; |
5368 |
|
|
5369 |
if (config->defaultImage == -1) |
if (config->defaultImage == NO_DEFAULT_ENTRY) |
5370 |
return 0; |
return 0; |
5371 |
if (config->defaultImage == DEFAULT_SAVED_GRUB2 && |
if (config->defaultImage == DEFAULT_SAVED_GRUB2 && |
5372 |
cfi->defaultIsSaved) |
cfi->defaultIsSaved) |
5373 |
config->defaultImage = 0; |
config->defaultImage = FIRST_ENTRY_INDEX; |
5374 |
entry = findEntryByIndex(config, config->defaultImage); |
entry = findEntryByIndex(config, config->defaultImage); |
5375 |
if (!entry) |
if (!entry) |
5376 |
return 0; |
return 0; |
5383 |
if (!line) |
if (!line) |
5384 |
return 0; |
return 0; |
5385 |
|
|
5386 |
rootspec = getRootSpecifier(line->elements[1].item); |
rs = getRootSpecifier(line->elements[1].item); |
5387 |
printf("%s%s\n", bootPrefix, line->elements[1].item + |
printf("%s%s\n", bootPrefix, line->elements[1].item + rs); |
|
((rootspec != NULL) ? strlen(rootspec) : 0)); |
|
5388 |
|
|
5389 |
return 0; |
return 0; |
5390 |
|
|
5392 |
struct singleLine *line; |
struct singleLine *line; |
5393 |
struct singleEntry *entry; |
struct singleEntry *entry; |
5394 |
|
|
5395 |
if (config->defaultImage == -1) |
if (config->defaultImage == NO_DEFAULT_ENTRY) |
5396 |
return 0; |
return 0; |
5397 |
if (config->defaultImage == DEFAULT_SAVED_GRUB2 && |
if (config->defaultImage == DEFAULT_SAVED_GRUB2 && |
5398 |
cfi->defaultIsSaved) |
cfi->defaultIsSaved) |
5399 |
config->defaultImage = 0; |
config->defaultImage = FIRST_ENTRY_INDEX; |
5400 |
entry = findEntryByIndex(config, config->defaultImage); |
entry = findEntryByIndex(config, config->defaultImage); |
5401 |
if (!entry) |
if (!entry) |
5402 |
return 0; |
return 0; |
5426 |
return 0; |
return 0; |
5427 |
|
|
5428 |
} else if (displayDefaultIndex) { |
} else if (displayDefaultIndex) { |
5429 |
if (config->defaultImage == -1) |
if (config->defaultImage == NO_DEFAULT_ENTRY) |
5430 |
return 0; |
return 0; |
5431 |
if (config->defaultImage == DEFAULT_SAVED_GRUB2 && |
if (config->defaultImage == DEFAULT_SAVED_GRUB2 && |
5432 |
cfi->defaultIsSaved) |
cfi->defaultIsSaved) |
5433 |
config->defaultImage = 0; |
config->defaultImage = FIRST_ENTRY_INDEX; |
5434 |
printf("%i\n", config->defaultImage); |
printf("%i\n", config->defaultImage); |
5435 |
return 0; |
return 0; |
5436 |
|
|
5446 |
markRemovedImage(config, removeKernelPath, bootPrefix); |
markRemovedImage(config, removeKernelPath, bootPrefix); |
5447 |
markRemovedImage(config, removeMBKernel, bootPrefix); |
markRemovedImage(config, removeMBKernel, bootPrefix); |
5448 |
setDefaultImage(config, newKernelPath != NULL, defaultKernel, |
setDefaultImage(config, newKernelPath != NULL, defaultKernel, |
5449 |
makeDefault, bootPrefix, flags, defaultIndex); |
makeDefault, bootPrefix, flags, defaultIndex, |
5450 |
|
newIndex); |
5451 |
setFallbackImage(config, newKernelPath != NULL); |
setFallbackImage(config, newKernelPath != NULL); |
5452 |
if (updateImage(config, updateKernelPath, bootPrefix, newKernelArgs, |
if (updateImage(config, updateKernelPath, bootPrefix, newKernelArgs, |
5453 |
removeArgs, newMBKernelArgs, removeMBKernelArgs)) |
removeArgs, newMBKernelArgs, removeMBKernelArgs)) |