164 |
|
|
165 |
const char *grubFindConfig(struct configFileInfo *cfi) { |
const char *grubFindConfig(struct configFileInfo *cfi) { |
166 |
static const char *configFiles[] = { |
static const char *configFiles[] = { |
|
"/etc/grub.conf", |
|
167 |
"/boot/grub/grub.conf", |
"/boot/grub/grub.conf", |
168 |
"/boot/grub/menu.lst", |
"/boot/grub/menu.lst", |
169 |
|
"/etc/grub.conf", |
170 |
NULL |
NULL |
171 |
}; |
}; |
172 |
static int i = -1; |
static int i = -1; |
243 |
} |
} |
244 |
|
|
245 |
int sizeOfSingleLine(struct singleLine * line) { |
int sizeOfSingleLine(struct singleLine * line) { |
|
int i; |
|
246 |
int count = 0; |
int count = 0; |
247 |
|
|
248 |
for (i = 0; i < line->numElements; i++) { |
for (int i = 0; i < line->numElements; i++) { |
249 |
int indentSize = 0; |
int indentSize = 0; |
250 |
|
|
251 |
count = count + strlen(line->elements[i].item); |
count = count + strlen(line->elements[i].item); |
572 |
|
|
573 |
static struct keywordTypes * getKeywordByType(enum lineType_e type, |
static struct keywordTypes * getKeywordByType(enum lineType_e type, |
574 |
struct configFileInfo * cfi) { |
struct configFileInfo * cfi) { |
575 |
struct keywordTypes * kw; |
for (struct keywordTypes *kw = cfi->keywords; kw->key; kw++) { |
|
for (kw = cfi->keywords; kw->key; kw++) { |
|
576 |
if (kw->type == type) |
if (kw->type == type) |
577 |
return kw; |
return kw; |
578 |
} |
} |
602 |
|
|
603 |
static enum lineType_e getTypeByKeyword(char * keyword, |
static enum lineType_e getTypeByKeyword(char * keyword, |
604 |
struct configFileInfo * cfi) { |
struct configFileInfo * cfi) { |
605 |
struct keywordTypes * kw; |
for (struct keywordTypes *kw = cfi->keywords; kw->key; kw++) { |
|
for (kw = cfi->keywords; kw->key; kw++) { |
|
606 |
if (!strcmp(keyword, kw->key)) |
if (!strcmp(keyword, kw->key)) |
607 |
return kw->type; |
return kw->type; |
608 |
} |
} |
689 |
} |
} |
690 |
|
|
691 |
struct singleLine * lineDup(struct singleLine * line) { |
struct singleLine * lineDup(struct singleLine * line) { |
|
int i; |
|
692 |
struct singleLine * newLine = malloc(sizeof(*newLine)); |
struct singleLine * newLine = malloc(sizeof(*newLine)); |
693 |
|
|
694 |
newLine->indent = strdup(line->indent); |
newLine->indent = strdup(line->indent); |
698 |
newLine->elements = malloc(sizeof(*newLine->elements) * |
newLine->elements = malloc(sizeof(*newLine->elements) * |
699 |
newLine->numElements); |
newLine->numElements); |
700 |
|
|
701 |
for (i = 0; i < newLine->numElements; i++) { |
for (int i = 0; i < newLine->numElements; i++) { |
702 |
newLine->elements[i].indent = strdup(line->elements[i].indent); |
newLine->elements[i].indent = strdup(line->elements[i].indent); |
703 |
newLine->elements[i].item = strdup(line->elements[i].item); |
newLine->elements[i].item = strdup(line->elements[i].item); |
704 |
} |
} |
707 |
} |
} |
708 |
|
|
709 |
static void lineFree(struct singleLine * line) { |
static void lineFree(struct singleLine * line) { |
|
int i; |
|
|
|
|
710 |
if (line->indent) free(line->indent); |
if (line->indent) free(line->indent); |
711 |
|
|
712 |
for (i = 0; i < line->numElements; i++) { |
for (int i = 0; i < line->numElements; i++) { |
713 |
free(line->elements[i].item); |
free(line->elements[i].item); |
714 |
free(line->elements[i].indent); |
free(line->elements[i].indent); |
715 |
} |
} |
720 |
|
|
721 |
static int lineWrite(FILE * out, struct singleLine * line, |
static int lineWrite(FILE * out, struct singleLine * line, |
722 |
struct configFileInfo * cfi) { |
struct configFileInfo * cfi) { |
|
int i; |
|
|
|
|
723 |
if (fprintf(out, "%s", line->indent) == -1) return -1; |
if (fprintf(out, "%s", line->indent) == -1) return -1; |
724 |
|
|
725 |
for (i = 0; i < line->numElements; i++) { |
for (int i = 0; i < line->numElements; i++) { |
726 |
/* Need to handle this, because we strip the quotes from |
/* Need to handle this, because we strip the quotes from |
727 |
* menuentry when read it. */ |
* menuentry when read it. */ |
728 |
if (line->type == LT_MENUENTRY && i == 1) { |
if (line->type == LT_MENUENTRY && i == 1) { |
828 |
if (*line->elements[0].item == '#') { |
if (*line->elements[0].item == '#') { |
829 |
char * fullLine; |
char * fullLine; |
830 |
int len; |
int len; |
|
int i; |
|
831 |
|
|
832 |
len = strlen(line->indent); |
len = strlen(line->indent); |
833 |
for (i = 0; i < line->numElements; i++) |
for (int i = 0; i < line->numElements; i++) |
834 |
len += strlen(line->elements[i].item) + |
len += strlen(line->elements[i].item) + |
835 |
strlen(line->elements[i].indent); |
strlen(line->elements[i].indent); |
836 |
|
|
839 |
free(line->indent); |
free(line->indent); |
840 |
line->indent = fullLine; |
line->indent = fullLine; |
841 |
|
|
842 |
for (i = 0; i < line->numElements; i++) { |
for (int i = 0; i < line->numElements; i++) { |
843 |
strcat(fullLine, line->elements[i].item); |
strcat(fullLine, line->elements[i].item); |
844 |
strcat(fullLine, line->elements[i].indent); |
strcat(fullLine, line->elements[i].indent); |
845 |
free(line->elements[i].item); |
free(line->elements[i].item); |
858 |
* elements up more |
* elements up more |
859 |
*/ |
*/ |
860 |
if (!isspace(kw->separatorChar)) { |
if (!isspace(kw->separatorChar)) { |
|
int i; |
|
861 |
char indent[2] = ""; |
char indent[2] = ""; |
862 |
indent[0] = kw->separatorChar; |
indent[0] = kw->separatorChar; |
863 |
for (i = 1; i < line->numElements; i++) { |
for (int i = 1; i < line->numElements; i++) { |
864 |
char *p; |
char *p; |
|
int j; |
|
865 |
int numNewElements; |
int numNewElements; |
866 |
|
|
867 |
numNewElements = 0; |
numNewElements = 0; |
877 |
sizeof(*line->elements) * elementsAlloced); |
sizeof(*line->elements) * elementsAlloced); |
878 |
} |
} |
879 |
|
|
880 |
for (j = line->numElements; j > i; j--) { |
for (int j = line->numElements; j > i; j--) { |
881 |
line->elements[j + numNewElements] = line->elements[j]; |
line->elements[j + numNewElements] = line->elements[j]; |
882 |
} |
} |
883 |
line->numElements += numNewElements; |
line->numElements += numNewElements; |
915 |
struct singleLine * last = NULL, * line, * defaultLine = NULL; |
struct singleLine * last = NULL, * line, * defaultLine = NULL; |
916 |
char * end; |
char * end; |
917 |
struct singleEntry * entry = NULL; |
struct singleEntry * entry = NULL; |
918 |
int i, len; |
int len; |
919 |
char * buf; |
char * buf; |
920 |
|
|
921 |
if (!strcmp(inName, "-")) { |
if (!strcmp(inName, "-")) { |
978 |
} |
} |
979 |
|
|
980 |
if (line->type == LT_SET_VARIABLE) { |
if (line->type == LT_SET_VARIABLE) { |
|
int i; |
|
981 |
dbgPrintf("found 'set' command (%d elements): ", line->numElements); |
dbgPrintf("found 'set' command (%d elements): ", line->numElements); |
982 |
dbgPrintf("%s", line->indent); |
dbgPrintf("%s", line->indent); |
983 |
for (i = 0; i < line->numElements; i++) |
for (int i = 0; i < line->numElements; i++) |
984 |
dbgPrintf("\"%s\"%s", line->elements[i].item, line->elements[i].indent); |
dbgPrintf("\"%s\"%s", line->elements[i].item, line->elements[i].indent); |
985 |
dbgPrintf("\n"); |
dbgPrintf("\n"); |
986 |
struct keywordTypes *kwType = getKeywordByType(LT_DEFAULT, cfi); |
struct keywordTypes *kwType = getKeywordByType(LT_DEFAULT, cfi); |
1008 |
* This only applies to grub, but that's the only place we |
* This only applies to grub, but that's the only place we |
1009 |
* should find LT_MBMODULE lines anyway. |
* should find LT_MBMODULE lines anyway. |
1010 |
*/ |
*/ |
1011 |
struct singleLine * l; |
for (struct singleLine *l = entry->lines; l; l = l->next) { |
|
for (l = entry->lines; l; l = l->next) { |
|
1012 |
if (l->type == LT_HYPER) |
if (l->type == LT_HYPER) |
1013 |
break; |
break; |
1014 |
else if (l->type == LT_KERNEL) { |
else if (l->type == LT_KERNEL) { |
1028 |
} else if (line->type == LT_TITLE && line->numElements > 1) { |
} else if (line->type == LT_TITLE && line->numElements > 1) { |
1029 |
/* make the title a single argument (undoing our parsing) */ |
/* make the title a single argument (undoing our parsing) */ |
1030 |
len = 0; |
len = 0; |
1031 |
for (i = 1; i < line->numElements; i++) { |
for (int i = 1; i < line->numElements; i++) { |
1032 |
len += strlen(line->elements[i].item); |
len += strlen(line->elements[i].item); |
1033 |
len += strlen(line->elements[i].indent); |
len += strlen(line->elements[i].indent); |
1034 |
} |
} |
1035 |
buf = malloc(len + 1); |
buf = malloc(len + 1); |
1036 |
*buf = '\0'; |
*buf = '\0'; |
1037 |
|
|
1038 |
for (i = 1; i < line->numElements; i++) { |
for (int i = 1; i < line->numElements; i++) { |
1039 |
strcat(buf, line->elements[i].item); |
strcat(buf, line->elements[i].item); |
1040 |
free(line->elements[i].item); |
free(line->elements[i].item); |
1041 |
|
|
1055 |
char *extras; |
char *extras; |
1056 |
char *title; |
char *title; |
1057 |
|
|
1058 |
for (i = 1; i < line->numElements; i++) { |
for (int i = 1; i < line->numElements; i++) { |
1059 |
len += strlen(line->elements[i].item); |
len += strlen(line->elements[i].item); |
1060 |
len += strlen(line->elements[i].indent); |
len += strlen(line->elements[i].indent); |
1061 |
} |
} |
1067 |
*extras = '\0'; |
*extras = '\0'; |
1068 |
|
|
1069 |
/* get title. */ |
/* get title. */ |
1070 |
for (i = 0; i < line->numElements; i++) { |
for (int i = 0; i < line->numElements; i++) { |
1071 |
if (!strcmp(line->elements[i].item, "menuentry")) |
if (!strcmp(line->elements[i].item, "menuentry")) |
1072 |
continue; |
continue; |
1073 |
if (isquote(*line->elements[i].item)) |
if (isquote(*line->elements[i].item)) |
1087 |
|
|
1088 |
/* get extras */ |
/* get extras */ |
1089 |
int count = 0; |
int count = 0; |
1090 |
for (i = 0; i < line->numElements; i++) { |
for (int i = 0; i < line->numElements; i++) { |
1091 |
if (count >= 2) { |
if (count >= 2) { |
1092 |
strcat(extras, line->elements[i].item); |
strcat(extras, line->elements[i].item); |
1093 |
strcat(extras, line->elements[i].indent); |
strcat(extras, line->elements[i].indent); |
1208 |
cfg->defaultImage = strtol(defaultLine->elements[1].item, &end, 10); |
cfg->defaultImage = strtol(defaultLine->elements[1].item, &end, 10); |
1209 |
if (*end) cfg->defaultImage = -1; |
if (*end) cfg->defaultImage = -1; |
1210 |
} else if (defaultLine->numElements >= 2) { |
} else if (defaultLine->numElements >= 2) { |
1211 |
i = 0; |
int i = 0; |
1212 |
while ((entry = findEntryByIndex(cfg, i))) { |
while ((entry = findEntryByIndex(cfg, i))) { |
1213 |
for (line = entry->lines; line; line = line->next) |
for (line = entry->lines; line; line = line->next) |
1214 |
if (line->type == LT_TITLE) break; |
if (line->type == LT_TITLE) break; |
1448 |
buf[rc] = '\0'; |
buf[rc] = '\0'; |
1449 |
chptr = buf; |
chptr = buf; |
1450 |
|
|
1451 |
|
char *foundanswer = NULL; |
1452 |
|
|
1453 |
while (chptr && chptr != buf+rc) { |
while (chptr && chptr != buf+rc) { |
1454 |
devname = chptr; |
devname = chptr; |
1455 |
|
|
1477 |
* for '/' obviously. |
* for '/' obviously. |
1478 |
*/ |
*/ |
1479 |
if (*(++chptr) == '/' && *(++chptr) == ' ') { |
if (*(++chptr) == '/' && *(++chptr) == ' ') { |
1480 |
/* |
/* remember the last / entry in mtab */ |
1481 |
* Move back 2, which is the first space after the device name, set |
foundanswer = devname; |
|
* it to \0 so strdup will just get the devicename. |
|
|
*/ |
|
|
chptr -= 2; |
|
|
*chptr = '\0'; |
|
|
return strdup(devname); |
|
1482 |
} |
} |
1483 |
|
|
1484 |
/* Next line */ |
/* Next line */ |
1487 |
chptr++; |
chptr++; |
1488 |
} |
} |
1489 |
|
|
1490 |
|
/* Return the last / entry found */ |
1491 |
|
if (foundanswer) { |
1492 |
|
chptr = strchr(foundanswer, ' '); |
1493 |
|
*chptr = '\0'; |
1494 |
|
return strdup(foundanswer); |
1495 |
|
} |
1496 |
|
|
1497 |
return NULL; |
return NULL; |
1498 |
} |
} |
1499 |
|
|
1867 |
|
|
1868 |
void setDefaultImage(struct grubConfig * config, int hasNew, |
void setDefaultImage(struct grubConfig * config, int hasNew, |
1869 |
const char * defaultKernelPath, int newIsDefault, |
const char * defaultKernelPath, int newIsDefault, |
1870 |
const char * prefix, int flags) { |
const char * prefix, int flags, int index) { |
1871 |
struct singleEntry * entry, * entry2, * newDefault; |
struct singleEntry * entry, * entry2, * newDefault; |
1872 |
int i, j; |
int i, j; |
1873 |
|
|
1874 |
if (newIsDefault) { |
if (newIsDefault) { |
1875 |
config->defaultImage = 0; |
config->defaultImage = 0; |
1876 |
return; |
return; |
1877 |
|
} else if ((index >= 0) && config->cfi->defaultIsIndex) { |
1878 |
|
if (findEntryByIndex(config, index)) |
1879 |
|
config->defaultImage = index; |
1880 |
|
else |
1881 |
|
config->defaultImage = -1; |
1882 |
|
return; |
1883 |
} else if (defaultKernelPath) { |
} else if (defaultKernelPath) { |
1884 |
i = 0; |
i = 0; |
1885 |
if (findEntryByPath(config, defaultKernelPath, prefix, &i)) { |
if (findEntryByPath(config, defaultKernelPath, prefix, &i)) { |
1960 |
return; |
return; |
1961 |
} |
} |
1962 |
|
|
1963 |
printf("kernel=%s%s\n", prefix, line->elements[1].item); |
if (!strncmp(prefix, line->elements[1].item, strlen(prefix))) |
1964 |
|
printf("kernel=%s\n", line->elements[1].item); |
1965 |
|
else |
1966 |
|
printf("kernel=%s%s\n", prefix, line->elements[1].item); |
1967 |
|
|
1968 |
if (line->numElements >= 3) { |
if (line->numElements >= 3) { |
1969 |
printf("args=\""); |
printf("args=\""); |
2022 |
line = getLineByType(LT_INITRD, entry->lines); |
line = getLineByType(LT_INITRD, entry->lines); |
2023 |
|
|
2024 |
if (line && line->numElements >= 2) { |
if (line && line->numElements >= 2) { |
2025 |
printf("initrd=%s", prefix); |
if (!strncmp(prefix, line->elements[1].item, strlen(prefix))) |
2026 |
|
printf("initrd="); |
2027 |
|
else |
2028 |
|
printf("initrd=%s", prefix); |
2029 |
|
|
2030 |
for (i = 1; i < line->numElements; i++) |
for (i = 1; i < line->numElements; i++) |
2031 |
printf("%s%s", line->elements[i].item, line->elements[i].indent); |
printf("%s%s", line->elements[i].item, line->elements[i].indent); |
2032 |
printf("\n"); |
printf("\n"); |
2044 |
} |
} |
2045 |
} |
} |
2046 |
|
|
2047 |
|
int isSuseSystem(void) { |
2048 |
|
const char * path; |
2049 |
|
const static char default_path[] = "/etc/SuSE-release"; |
2050 |
|
|
2051 |
|
if ((path = getenv("GRUBBY_SUSE_RELEASE")) == NULL) |
2052 |
|
path = default_path; |
2053 |
|
|
2054 |
|
if (!access(path, R_OK)) |
2055 |
|
return 1; |
2056 |
|
return 0; |
2057 |
|
} |
2058 |
|
|
2059 |
|
int isSuseGrubConf(const char * path) { |
2060 |
|
FILE * grubConf; |
2061 |
|
char * line = NULL; |
2062 |
|
size_t len = 0, res = 0; |
2063 |
|
|
2064 |
|
grubConf = fopen(path, "r"); |
2065 |
|
if (!grubConf) { |
2066 |
|
dbgPrintf("Could not open SuSE configuration file '%s'\n", path); |
2067 |
|
return 0; |
2068 |
|
} |
2069 |
|
|
2070 |
|
while ((res = getline(&line, &len, grubConf)) != -1) { |
2071 |
|
if (!strncmp(line, "setup", 5)) { |
2072 |
|
fclose(grubConf); |
2073 |
|
free(line); |
2074 |
|
return 1; |
2075 |
|
} |
2076 |
|
} |
2077 |
|
|
2078 |
|
dbgPrintf("SuSE configuration file '%s' does not appear to be valid\n", |
2079 |
|
path); |
2080 |
|
|
2081 |
|
fclose(grubConf); |
2082 |
|
free(line); |
2083 |
|
return 0; |
2084 |
|
} |
2085 |
|
|
2086 |
|
int suseGrubConfGetLba(const char * path, int * lbaPtr) { |
2087 |
|
FILE * grubConf; |
2088 |
|
char * line = NULL; |
2089 |
|
size_t res = 0, len = 0; |
2090 |
|
|
2091 |
|
if (!path) return 1; |
2092 |
|
if (!lbaPtr) return 1; |
2093 |
|
|
2094 |
|
grubConf = fopen(path, "r"); |
2095 |
|
if (!grubConf) return 1; |
2096 |
|
|
2097 |
|
while ((res = getline(&line, &len, grubConf)) != -1) { |
2098 |
|
if (line[res - 1] == '\n') |
2099 |
|
line[res - 1] = '\0'; |
2100 |
|
else if (len > res) |
2101 |
|
line[res] = '\0'; |
2102 |
|
else { |
2103 |
|
line = realloc(line, res + 1); |
2104 |
|
line[res] = '\0'; |
2105 |
|
} |
2106 |
|
|
2107 |
|
if (!strncmp(line, "setup", 5)) { |
2108 |
|
if (strstr(line, "--force-lba")) { |
2109 |
|
*lbaPtr = 1; |
2110 |
|
} else { |
2111 |
|
*lbaPtr = 0; |
2112 |
|
} |
2113 |
|
dbgPrintf("lba: %i\n", *lbaPtr); |
2114 |
|
break; |
2115 |
|
} |
2116 |
|
} |
2117 |
|
|
2118 |
|
free(line); |
2119 |
|
fclose(grubConf); |
2120 |
|
return 0; |
2121 |
|
} |
2122 |
|
|
2123 |
|
int suseGrubConfGetInstallDevice(const char * path, char ** devicePtr) { |
2124 |
|
FILE * grubConf; |
2125 |
|
char * line = NULL; |
2126 |
|
size_t res = 0, len = 0; |
2127 |
|
char * lastParamPtr = NULL; |
2128 |
|
char * secLastParamPtr = NULL; |
2129 |
|
char installDeviceNumber = '\0'; |
2130 |
|
char * bounds = NULL; |
2131 |
|
|
2132 |
|
if (!path) return 1; |
2133 |
|
if (!devicePtr) return 1; |
2134 |
|
|
2135 |
|
grubConf = fopen(path, "r"); |
2136 |
|
if (!grubConf) return 1; |
2137 |
|
|
2138 |
|
while ((res = getline(&line, &len, grubConf)) != -1) { |
2139 |
|
if (strncmp(line, "setup", 5)) |
2140 |
|
continue; |
2141 |
|
|
2142 |
|
if (line[res - 1] == '\n') |
2143 |
|
line[res - 1] = '\0'; |
2144 |
|
else if (len > res) |
2145 |
|
line[res] = '\0'; |
2146 |
|
else { |
2147 |
|
line = realloc(line, res + 1); |
2148 |
|
line[res] = '\0'; |
2149 |
|
} |
2150 |
|
|
2151 |
|
lastParamPtr = bounds = line + res; |
2152 |
|
|
2153 |
|
/* Last parameter in grub may be an optional IMAGE_DEVICE */ |
2154 |
|
while (!isspace(*lastParamPtr)) |
2155 |
|
lastParamPtr--; |
2156 |
|
lastParamPtr++; |
2157 |
|
|
2158 |
|
secLastParamPtr = lastParamPtr - 2; |
2159 |
|
dbgPrintf("lastParamPtr: %s\n", lastParamPtr); |
2160 |
|
|
2161 |
|
if (lastParamPtr + 3 > bounds) { |
2162 |
|
dbgPrintf("lastParamPtr going over boundary"); |
2163 |
|
fclose(grubConf); |
2164 |
|
free(line); |
2165 |
|
return 1; |
2166 |
|
} |
2167 |
|
if (!strncmp(lastParamPtr, "(hd", 3)) |
2168 |
|
lastParamPtr += 3; |
2169 |
|
dbgPrintf("lastParamPtr: %c\n", *lastParamPtr); |
2170 |
|
|
2171 |
|
/* |
2172 |
|
* Second last parameter will decide wether last parameter is |
2173 |
|
* an IMAGE_DEVICE or INSTALL_DEVICE |
2174 |
|
*/ |
2175 |
|
while (!isspace(*secLastParamPtr)) |
2176 |
|
secLastParamPtr--; |
2177 |
|
secLastParamPtr++; |
2178 |
|
|
2179 |
|
if (secLastParamPtr + 3 > bounds) { |
2180 |
|
dbgPrintf("secLastParamPtr going over boundary"); |
2181 |
|
fclose(grubConf); |
2182 |
|
free(line); |
2183 |
|
return 1; |
2184 |
|
} |
2185 |
|
dbgPrintf("secLastParamPtr: %s\n", secLastParamPtr); |
2186 |
|
if (!strncmp(secLastParamPtr, "(hd", 3)) { |
2187 |
|
secLastParamPtr += 3; |
2188 |
|
dbgPrintf("secLastParamPtr: %c\n", *secLastParamPtr); |
2189 |
|
installDeviceNumber = *secLastParamPtr; |
2190 |
|
} else { |
2191 |
|
installDeviceNumber = *lastParamPtr; |
2192 |
|
} |
2193 |
|
|
2194 |
|
*devicePtr = malloc(6); |
2195 |
|
snprintf(*devicePtr, 6, "(hd%c)", installDeviceNumber); |
2196 |
|
dbgPrintf("installDeviceNumber: %c\n", installDeviceNumber); |
2197 |
|
fclose(grubConf); |
2198 |
|
free(line); |
2199 |
|
return 0; |
2200 |
|
} |
2201 |
|
|
2202 |
|
free(line); |
2203 |
|
fclose(grubConf); |
2204 |
|
return 1; |
2205 |
|
} |
2206 |
|
|
2207 |
|
int grubGetBootFromDeviceMap(const char * device, |
2208 |
|
char ** bootPtr) { |
2209 |
|
FILE * deviceMap; |
2210 |
|
char * line = NULL; |
2211 |
|
size_t res = 0, len = 0; |
2212 |
|
char * devicePtr; |
2213 |
|
char * bounds = NULL; |
2214 |
|
const char * path; |
2215 |
|
const static char default_path[] = "/boot/grub/device.map"; |
2216 |
|
|
2217 |
|
if (!device) return 1; |
2218 |
|
if (!bootPtr) return 1; |
2219 |
|
|
2220 |
|
if ((path = getenv("GRUBBY_GRUB_DEVICE_MAP")) == NULL) |
2221 |
|
path = default_path; |
2222 |
|
|
2223 |
|
dbgPrintf("opening grub device.map file from: %s\n", path); |
2224 |
|
deviceMap = fopen(path, "r"); |
2225 |
|
if (!deviceMap) |
2226 |
|
return 1; |
2227 |
|
|
2228 |
|
while ((res = getline(&line, &len, deviceMap)) != -1) { |
2229 |
|
if (!strncmp(line, "#", 1)) |
2230 |
|
continue; |
2231 |
|
|
2232 |
|
if (line[res - 1] == '\n') |
2233 |
|
line[res - 1] = '\0'; |
2234 |
|
else if (len > res) |
2235 |
|
line[res] = '\0'; |
2236 |
|
else { |
2237 |
|
line = realloc(line, res + 1); |
2238 |
|
line[res] = '\0'; |
2239 |
|
} |
2240 |
|
|
2241 |
|
devicePtr = line; |
2242 |
|
bounds = line + res; |
2243 |
|
|
2244 |
|
while ((isspace(*line) && ((devicePtr + 1) <= bounds))) |
2245 |
|
devicePtr++; |
2246 |
|
dbgPrintf("device: %s\n", devicePtr); |
2247 |
|
|
2248 |
|
if (!strncmp(devicePtr, device, strlen(device))) { |
2249 |
|
devicePtr += strlen(device); |
2250 |
|
while (isspace(*devicePtr) && ((devicePtr + 1) <= bounds)) |
2251 |
|
devicePtr++; |
2252 |
|
|
2253 |
|
*bootPtr = strdup(devicePtr); |
2254 |
|
break; |
2255 |
|
} |
2256 |
|
} |
2257 |
|
|
2258 |
|
free(line); |
2259 |
|
fclose(deviceMap); |
2260 |
|
return 0; |
2261 |
|
} |
2262 |
|
|
2263 |
|
int suseGrubConfGetBoot(const char * path, char ** bootPtr) { |
2264 |
|
char * grubDevice; |
2265 |
|
|
2266 |
|
if (suseGrubConfGetInstallDevice(path, &grubDevice)) |
2267 |
|
dbgPrintf("error looking for grub installation device\n"); |
2268 |
|
else |
2269 |
|
dbgPrintf("grubby installation device: %s\n", grubDevice); |
2270 |
|
|
2271 |
|
if (grubGetBootFromDeviceMap(grubDevice, bootPtr)) |
2272 |
|
dbgPrintf("error looking for grub boot device\n"); |
2273 |
|
else |
2274 |
|
dbgPrintf("grubby boot device: %s\n", *bootPtr); |
2275 |
|
|
2276 |
|
free(grubDevice); |
2277 |
|
return 0; |
2278 |
|
} |
2279 |
|
|
2280 |
|
int parseSuseGrubConf(int * lbaPtr, char ** bootPtr) { |
2281 |
|
/* |
2282 |
|
* This SuSE grub configuration file at this location is not your average |
2283 |
|
* grub configuration file, but instead the grub commands used to setup |
2284 |
|
* grub on that system. |
2285 |
|
*/ |
2286 |
|
const char * path; |
2287 |
|
const static char default_path[] = "/etc/grub.conf"; |
2288 |
|
|
2289 |
|
if ((path = getenv("GRUBBY_SUSE_GRUB_CONF")) == NULL) |
2290 |
|
path = default_path; |
2291 |
|
|
2292 |
|
if (!isSuseGrubConf(path)) return 1; |
2293 |
|
|
2294 |
|
if (lbaPtr) { |
2295 |
|
*lbaPtr = 0; |
2296 |
|
if (suseGrubConfGetLba(path, lbaPtr)) |
2297 |
|
return 1; |
2298 |
|
} |
2299 |
|
|
2300 |
|
if (bootPtr) { |
2301 |
|
*bootPtr = NULL; |
2302 |
|
suseGrubConfGetBoot(path, bootPtr); |
2303 |
|
} |
2304 |
|
|
2305 |
|
return 0; |
2306 |
|
} |
2307 |
|
|
2308 |
int parseSysconfigGrub(int * lbaPtr, char ** bootPtr) { |
int parseSysconfigGrub(int * lbaPtr, char ** bootPtr) { |
2309 |
FILE * in; |
FILE * in; |
2310 |
char buf[1024]; |
char buf[1024]; |
2353 |
} |
} |
2354 |
|
|
2355 |
void dumpSysconfigGrub(void) { |
void dumpSysconfigGrub(void) { |
2356 |
char * boot; |
char * boot = NULL; |
2357 |
int lba; |
int lba; |
2358 |
|
|
2359 |
if (!parseSysconfigGrub(&lba, &boot)) { |
if (isSuseSystem()) { |
2360 |
if (lba) printf("lba\n"); |
if (parseSuseGrubConf(&lba, &boot)) { |
2361 |
if (boot) printf("boot=%s\n", boot); |
free(boot); |
2362 |
|
return; |
2363 |
|
} |
2364 |
|
} else { |
2365 |
|
if (parseSysconfigGrub(&lba, &boot)) { |
2366 |
|
free(boot); |
2367 |
|
return; |
2368 |
|
} |
2369 |
|
} |
2370 |
|
|
2371 |
|
if (lba) printf("lba\n"); |
2372 |
|
if (boot) { |
2373 |
|
printf("boot=%s\n", boot); |
2374 |
|
free(boot); |
2375 |
} |
} |
2376 |
} |
} |
2377 |
|
|
3185 |
int fd; |
int fd; |
3186 |
unsigned char bootSect[512]; |
unsigned char bootSect[512]; |
3187 |
char * boot; |
char * boot; |
3188 |
|
int onSuse = isSuseSystem(); |
3189 |
|
|
3190 |
if (parseSysconfigGrub(NULL, &boot)) |
|
3191 |
return 0; |
if (onSuse) { |
3192 |
|
if (parseSuseGrubConf(NULL, &boot)) |
3193 |
|
return 0; |
3194 |
|
} else { |
3195 |
|
if (parseSysconfigGrub(NULL, &boot)) |
3196 |
|
return 0; |
3197 |
|
} |
3198 |
|
|
3199 |
/* assume grub is not installed -- not an error condition */ |
/* assume grub is not installed -- not an error condition */ |
3200 |
if (!boot) |
if (!boot) |
3213 |
} |
} |
3214 |
close(fd); |
close(fd); |
3215 |
|
|
3216 |
|
/* The more elaborate checks do not work on SuSE. The checks done |
3217 |
|
* seem to be reasonble (at least for now), so just return success |
3218 |
|
*/ |
3219 |
|
if (onSuse) |
3220 |
|
return 2; |
3221 |
|
|
3222 |
return checkDeviceBootloader(boot, bootSect); |
return checkDeviceBootloader(boot, bootSect); |
3223 |
} |
} |
3224 |
|
|
3252 |
return checkDeviceBootloader(boot, bootSect); |
return checkDeviceBootloader(boot, bootSect); |
3253 |
} |
} |
3254 |
|
|
3255 |
|
int checkForYaboot(struct grubConfig * config) { |
3256 |
|
/* |
3257 |
|
* This is a simplistic check that we consider good enough for own puporses |
3258 |
|
* |
3259 |
|
* If we were to properly check if yaboot is *installed* we'd need to: |
3260 |
|
* 1) get the system boot device (LT_BOOT) |
3261 |
|
* 2) considering it's a raw filesystem, check if the yaboot binary matches |
3262 |
|
* the content on the boot device |
3263 |
|
* 3) if not, copy the binary to a temporary file and run "addnote" on it |
3264 |
|
* 4) check again if binary and boot device contents match |
3265 |
|
*/ |
3266 |
|
if (!access("/etc/yaboot.conf", R_OK)) |
3267 |
|
return 2; |
3268 |
|
|
3269 |
|
return 1; |
3270 |
|
} |
3271 |
|
|
3272 |
|
int checkForElilo(struct grubConfig * config) { |
3273 |
|
if (!access("/etc/elilo.conf", R_OK)) |
3274 |
|
return 2; |
3275 |
|
|
3276 |
|
return 1; |
3277 |
|
} |
3278 |
|
|
3279 |
static char * getRootSpecifier(char * str) { |
static char * getRootSpecifier(char * str) { |
3280 |
char * idx, * rootspec = NULL; |
char * idx, * rootspec = NULL; |
3281 |
|
|
3290 |
static char * getInitrdVal(struct grubConfig * config, |
static char * getInitrdVal(struct grubConfig * config, |
3291 |
const char * prefix, struct singleLine *tmplLine, |
const char * prefix, struct singleLine *tmplLine, |
3292 |
const char * newKernelInitrd, |
const char * newKernelInitrd, |
3293 |
char ** extraInitrds, int extraInitrdCount) |
const char ** extraInitrds, int extraInitrdCount) |
3294 |
{ |
{ |
3295 |
char *initrdVal, *end; |
char *initrdVal, *end; |
3296 |
int i; |
int i; |
3335 |
|
|
3336 |
int addNewKernel(struct grubConfig * config, struct singleEntry * template, |
int addNewKernel(struct grubConfig * config, struct singleEntry * template, |
3337 |
const char * prefix, |
const char * prefix, |
3338 |
char * newKernelPath, char * newKernelTitle, |
const char * newKernelPath, const char * newKernelTitle, |
3339 |
char * newKernelArgs, char * newKernelInitrd, |
const char * newKernelArgs, const char * newKernelInitrd, |
3340 |
char ** extraInitrds, int extraInitrdCount, |
const char ** extraInitrds, int extraInitrdCount, |
3341 |
char * newMBKernel, char * newMBKernelArgs) { |
const char * newMBKernel, const char * newMBKernelArgs) { |
3342 |
struct singleEntry * new; |
struct singleEntry * new; |
3343 |
struct singleLine * newLine = NULL, * tmplLine = NULL, * masterLine = NULL; |
struct singleLine * newLine = NULL, * tmplLine = NULL, * masterLine = NULL; |
3344 |
int needs; |
int needs; |
3746 |
int displayDefault = 0; |
int displayDefault = 0; |
3747 |
int displayDefaultIndex = 0; |
int displayDefaultIndex = 0; |
3748 |
int displayDefaultTitle = 0; |
int displayDefaultTitle = 0; |
3749 |
|
int defaultIndex = -1; |
3750 |
struct poptOption options[] = { |
struct poptOption options[] = { |
3751 |
{ "add-kernel", 0, POPT_ARG_STRING, &newKernelPath, 0, |
{ "add-kernel", 0, POPT_ARG_STRING, &newKernelPath, 0, |
3752 |
_("add an entry for the specified kernel"), _("kernel-path") }, |
_("add an entry for the specified kernel"), _("kernel-path") }, |
3764 |
{ "boot-filesystem", 0, POPT_ARG_STRING, &bootPrefix, 0, |
{ "boot-filesystem", 0, POPT_ARG_STRING, &bootPrefix, 0, |
3765 |
_("filestystem which contains /boot directory (for testing only)"), |
_("filestystem which contains /boot directory (for testing only)"), |
3766 |
_("bootfs") }, |
_("bootfs") }, |
3767 |
#if defined(__i386__) || defined(__x86_64__) |
#if defined(__i386__) || defined(__x86_64__) || defined (__powerpc64__) || defined (__ia64__) |
3768 |
{ "bootloader-probe", 0, POPT_ARG_NONE, &bootloaderProbe, 0, |
{ "bootloader-probe", 0, POPT_ARG_NONE, &bootloaderProbe, 0, |
3769 |
_("check if lilo is installed on lilo.conf boot sector") }, |
_("check which bootloader is installed on boot sector") }, |
3770 |
#endif |
#endif |
3771 |
{ "config-file", 'c', POPT_ARG_STRING, &grubConfig, 0, |
{ "config-file", 'c', POPT_ARG_STRING, &grubConfig, 0, |
3772 |
_("path to grub config file to update (\"-\" for stdin)"), |
_("path to grub config file to update (\"-\" for stdin)"), |
3819 |
{ "set-default", 0, POPT_ARG_STRING, &defaultKernel, 0, |
{ "set-default", 0, POPT_ARG_STRING, &defaultKernel, 0, |
3820 |
_("make the first entry referencing the specified kernel " |
_("make the first entry referencing the specified kernel " |
3821 |
"the default"), _("kernel-path") }, |
"the default"), _("kernel-path") }, |
3822 |
|
{ "set-default-index", 0, POPT_ARG_INT, &defaultIndex, 0, |
3823 |
|
_("make the given entry index the default entry"), |
3824 |
|
_("entry-index") }, |
3825 |
{ "silo", 0, POPT_ARG_NONE, &configureSilo, 0, |
{ "silo", 0, POPT_ARG_NONE, &configureSilo, 0, |
3826 |
_("configure silo bootloader") }, |
_("configure silo bootloader") }, |
3827 |
{ "title", 0, POPT_ARG_STRING, &newKernelTitle, 0, |
{ "title", 0, POPT_ARG_STRING, &newKernelTitle, 0, |
3930 |
} |
} |
3931 |
|
|
3932 |
if (bootloaderProbe && (displayDefault || kernelInfo || newKernelVersion || |
if (bootloaderProbe && (displayDefault || kernelInfo || newKernelVersion || |
3933 |
newKernelPath || removeKernelPath || makeDefault || |
newKernelPath || removeKernelPath || makeDefault || |
3934 |
defaultKernel || displayDefaultIndex || displayDefaultTitle)) { |
defaultKernel || displayDefaultIndex || displayDefaultTitle || |
3935 |
|
(defaultIndex >= 0))) { |
3936 |
fprintf(stderr, _("grubby: --bootloader-probe may not be used with " |
fprintf(stderr, _("grubby: --bootloader-probe may not be used with " |
3937 |
"specified option")); |
"specified option")); |
3938 |
return 1; |
return 1; |
3974 |
makeDefault = 1; |
makeDefault = 1; |
3975 |
defaultKernel = NULL; |
defaultKernel = NULL; |
3976 |
} |
} |
3977 |
|
else if (defaultKernel && (defaultIndex >= 0)) { |
3978 |
|
fprintf(stderr, _("grubby: --set-default and --set-default-index " |
3979 |
|
"may not be used together\n")); |
3980 |
|
return 1; |
3981 |
|
} |
3982 |
|
|
3983 |
if (grubConfig && !strcmp(grubConfig, "-") && !outputFile) { |
if (grubConfig && !strcmp(grubConfig, "-") && !outputFile) { |
3984 |
fprintf(stderr, _("grubby: output file must be specified if stdin " |
fprintf(stderr, _("grubby: output file must be specified if stdin " |
3987 |
} |
} |
3988 |
|
|
3989 |
if (!removeKernelPath && !newKernelPath && !displayDefault && !defaultKernel |
if (!removeKernelPath && !newKernelPath && !displayDefault && !defaultKernel |
3990 |
&& !kernelInfo && !bootloaderProbe && !updateKernelPath |
&& !kernelInfo && !bootloaderProbe && !updateKernelPath |
3991 |
&& !removeMBKernel && !displayDefaultIndex && !displayDefaultTitle) { |
&& !removeMBKernel && !displayDefaultIndex && !displayDefaultTitle |
3992 |
|
&& (defaultIndex == -1)) { |
3993 |
fprintf(stderr, _("grubby: no action specified\n")); |
fprintf(stderr, _("grubby: no action specified\n")); |
3994 |
return 1; |
return 1; |
3995 |
} |
} |
4016 |
} |
} |
4017 |
|
|
4018 |
if (bootloaderProbe) { |
if (bootloaderProbe) { |
4019 |
int lrc = 0, grc = 0, gr2c = 0, erc = 0; |
int lrc = 0, grc = 0, gr2c = 0, extrc = 0, yrc = 0, erc = 0; |
4020 |
struct grubConfig * lconfig, * gconfig; |
struct grubConfig * lconfig, * gconfig, * yconfig, * econfig; |
4021 |
|
|
4022 |
const char *grub2config = grub2FindConfig(&grub2ConfigType); |
const char *grub2config = grub2FindConfig(&grub2ConfigType); |
4023 |
if (grub2config) { |
if (grub2config) { |
4045 |
lrc = checkForLilo(lconfig); |
lrc = checkForLilo(lconfig); |
4046 |
} |
} |
4047 |
|
|
4048 |
|
if (!access(eliloConfigType.defaultConfig, F_OK)) { |
4049 |
|
econfig = readConfig(eliloConfigType.defaultConfig, |
4050 |
|
&eliloConfigType); |
4051 |
|
if (!econfig) |
4052 |
|
erc = 1; |
4053 |
|
else |
4054 |
|
erc = checkForElilo(econfig); |
4055 |
|
} |
4056 |
|
|
4057 |
if (!access(extlinuxConfigType.defaultConfig, F_OK)) { |
if (!access(extlinuxConfigType.defaultConfig, F_OK)) { |
4058 |
lconfig = readConfig(extlinuxConfigType.defaultConfig, &extlinuxConfigType); |
lconfig = readConfig(extlinuxConfigType.defaultConfig, &extlinuxConfigType); |
4059 |
if (!lconfig) |
if (!lconfig) |
4060 |
erc = 1; |
extrc = 1; |
4061 |
else |
else |
4062 |
erc = checkForExtLinux(lconfig); |
extrc = checkForExtLinux(lconfig); |
4063 |
} |
} |
4064 |
|
|
4065 |
if (lrc == 1 || grc == 1 || gr2c == 1) return 1; |
|
4066 |
|
if (!access(yabootConfigType.defaultConfig, F_OK)) { |
4067 |
|
yconfig = readConfig(yabootConfigType.defaultConfig, |
4068 |
|
&yabootConfigType); |
4069 |
|
if (!yconfig) |
4070 |
|
yrc = 1; |
4071 |
|
else |
4072 |
|
yrc = checkForYaboot(yconfig); |
4073 |
|
} |
4074 |
|
|
4075 |
|
if (lrc == 1 || grc == 1 || gr2c == 1 || extrc == 1 || yrc == 1 || |
4076 |
|
erc == 1) |
4077 |
|
return 1; |
4078 |
|
|
4079 |
if (lrc == 2) printf("lilo\n"); |
if (lrc == 2) printf("lilo\n"); |
4080 |
if (gr2c == 2) printf("grub2\n"); |
if (gr2c == 2) printf("grub2\n"); |
4081 |
if (grc == 2) printf("grub\n"); |
if (grc == 2) printf("grub\n"); |
4082 |
if (erc == 2) printf("extlinux\n"); |
if (extrc == 2) printf("extlinux\n"); |
4083 |
|
if (yrc == 2) printf("yaboot\n"); |
4084 |
|
if (erc == 2) printf("elilo\n"); |
4085 |
|
|
4086 |
return 0; |
return 0; |
4087 |
} |
} |
4148 |
markRemovedImage(config, removeKernelPath, bootPrefix); |
markRemovedImage(config, removeKernelPath, bootPrefix); |
4149 |
markRemovedImage(config, removeMBKernel, bootPrefix); |
markRemovedImage(config, removeMBKernel, bootPrefix); |
4150 |
setDefaultImage(config, newKernelPath != NULL, defaultKernel, makeDefault, |
setDefaultImage(config, newKernelPath != NULL, defaultKernel, makeDefault, |
4151 |
bootPrefix, flags); |
bootPrefix, flags, defaultIndex); |
4152 |
setFallbackImage(config, newKernelPath != NULL); |
setFallbackImage(config, newKernelPath != NULL); |
4153 |
if (updateImage(config, updateKernelPath, bootPrefix, newKernelArgs, |
if (updateImage(config, updateKernelPath, bootPrefix, newKernelArgs, |
4154 |
removeArgs, newMBKernelArgs, removeMBKernelArgs)) return 1; |
removeArgs, newMBKernelArgs, removeMBKernelArgs)) return 1; |
4158 |
} |
} |
4159 |
if (addNewKernel(config, template, bootPrefix, newKernelPath, |
if (addNewKernel(config, template, bootPrefix, newKernelPath, |
4160 |
newKernelTitle, newKernelArgs, newKernelInitrd, |
newKernelTitle, newKernelArgs, newKernelInitrd, |
4161 |
extraInitrds, extraInitrdCount, |
(const char **)extraInitrds, extraInitrdCount, |
4162 |
newMBKernel, newMBKernelArgs)) return 1; |
newMBKernel, newMBKernelArgs)) return 1; |
4163 |
|
|
4164 |
|
|