--- trunk/grubby/grubby.c 2017/06/27 14:39:37 3021 +++ trunk/grubby/grubby.c 2020/07/07 11:11:04 3138 @@ -701,7 +701,7 @@ struct configFileInfo *cfi); static int getNextLine(char **bufPtr, struct singleLine *line, struct configFileInfo *cfi); -static char *getRootSpecifier(char *str); +static size_t getRootSpecifier(const char *str); static void requote(struct singleLine *line, struct configFileInfo *cfi); static void insertElement(struct singleLine *line, const char *item, int insertHere, @@ -1712,7 +1712,20 @@ fprintf(out, "%sset default=\"${saved_entry}\"\n", indent); if (cfg->defaultImage >= FIRST_ENTRY_INDEX && cfg->cfi->setEnv) { char *title; - entry = findEntryByIndex(cfg, cfg->defaultImage); + int trueIndex, currentIndex; + + trueIndex = 0; + currentIndex = 0; + + while ((entry = findEntryByIndex(cfg, currentIndex))) { + if (!entry->skip) { + if (trueIndex == cfg->defaultImage) { + break; + } + trueIndex++; + } + currentIndex++; + } line = getLineByType(LT_MENUENTRY, entry->lines); if (!line) line = getLineByType(LT_TITLE, entry->lines); @@ -1779,6 +1792,7 @@ int needs = MAIN_DEFAULT; struct stat sb; int i; + int rc = 0; if (!strcmp(outName, "-")) { out = stdout; @@ -1893,16 +1907,42 @@ } if (tmpOutName) { - if (rename(tmpOutName, outName)) { - fprintf(stderr, - _("grubby: error moving %s to %s: %s\n"), - tmpOutName, outName, strerror(errno)); - unlink(outName); - return 1; + /* write userspace buffers */ + if (fflush(out)) + rc = 1; + + /* purge the write-back cache with fsync() */ + if (fsync(fileno(out))) + rc = 1; + + if (fclose(out)) + rc = 1; + + if (rc == 0 && rename(tmpOutName, outName)) { + unlink(tmpOutName); + rc = 1; + } + + /* fsync() the destination directory after rename */ + if (rc == 0) { + int dirfd; + + dirfd = open(dirname(strdupa(outName)), O_RDONLY); + if (dirfd < 0) + rc = 1; + else if (fsync(dirfd)) + rc = 1; + + if (dirfd >= 0) + close(dirfd); } + + if (rc == 1) + fprintf(stderr, + _("grubby: error flushing data: %m\n")); } - return 0; + return rc; } static int numEntries(struct grubConfig *cfg) @@ -2085,7 +2125,7 @@ char *fullName; int i; char *dev; - char *rootspec; + size_t rs; char *rootdev; if (skipRemoved && entry->skip) { @@ -2113,12 +2153,11 @@ fullName = alloca(strlen(bootPrefix) + strlen(line->elements[1].item) + 1); - rootspec = getRootSpecifier(line->elements[1].item); - int rootspec_offset = rootspec ? strlen(rootspec) : 0; + rs = getRootSpecifier(line->elements[1].item); int hasslash = endswith(bootPrefix, '/') || - beginswith(line->elements[1].item + rootspec_offset, '/'); + beginswith(line->elements[1].item + rs, '/'); sprintf(fullName, "%s%s%s", bootPrefix, hasslash ? "" : "/", - line->elements[1].item + rootspec_offset); + line->elements[1].item + rs); if (access(fullName, R_OK)) { notSuitablePrintf(entry, 0, "access to %s failed\n", fullName); return 0; @@ -2210,7 +2249,6 @@ struct singleLine *line; int i; char *chptr; - char *rootspec = NULL; enum lineType_e checkType = LT_KERNEL; if (isdigit(*kernel)) { @@ -2315,14 +2353,10 @@ if (line && line->type != LT_MENUENTRY && line->numElements >= 2) { - rootspec = - getRootSpecifier(line->elements[1]. - item); - if (!strcmp - (line->elements[1].item + - ((rootspec != - NULL) ? strlen(rootspec) : 0), - kernel + strlen(prefix))) + if (!strcmp(line->elements[1].item + + getRootSpecifier( + line->elements[1].item), + kernel + strlen(prefix))) break; } if (line->type == LT_MENUENTRY && @@ -2439,8 +2473,11 @@ index = 0; while ((entry = findEntryByIndex(cfg, index))) { if (suitableImage(entry, prefix, skipRemoved, flags)) { - int j; - for (j = 0; j < index; j++) { + int j, unmodifiedIndex; + + unmodifiedIndex = index; + + for (j = 0; j < unmodifiedIndex; j++) { entry2 = findEntryByIndex(cfg, j); if (entry2->skip) index--; @@ -2509,6 +2546,9 @@ struct singleEntry *bootEntry, *newDefault; int indexToVerify, firstKernelEntryIndex, currentLookupIndex; + /* initialize */ + currentLookupIndex = FIRST_ENTRY_INDEX; + /* handle the two cases where the user explictly picks the default * boot entry index as it would exist post-modification */ @@ -2519,8 +2559,7 @@ } /* Case 2: user picked an arbitrary index as the default boot entry */ - if (newDefaultBootEntryIndex >= FIRST_ENTRY_INDEX - && config->cfi->defaultIsIndex) { + if (newDefaultBootEntryIndex >= FIRST_ENTRY_INDEX) { indexToVerify = newDefaultBootEntryIndex; /* user chose to make latest boot entry the default */ @@ -2553,6 +2592,8 @@ /* check validity of existing default or first-entry-found selection */ if (defaultKernelPath) { + /* we must initialize this */ + firstKernelEntryIndex = 0; /* user requested first-entry-found */ if (!findEntryByPath(config, defaultKernelPath, prefix, &firstKernelEntryIndex)) { @@ -2572,8 +2613,30 @@ config->defaultImage++; } } else { - /* use pre-existing default entry */ - currentLookupIndex = config->defaultImage; + /* check to see if the default is stored in the environment */ + if (config->defaultImage < FIRST_ENTRY_INDEX) { + if (config->defaultImage == DEFAULT_SAVED || config->defaultImage == DEFAULT_SAVED_GRUB2) + { + if (config->cfi->defaultIsSaved) { + if (config->cfi->getEnv) { + char *defaultTitle = config->cfi->getEnv(config->cfi, "saved_entry"); + + if (defaultTitle) { + if (isnumber(defaultTitle)) { + currentLookupIndex = atoi(defaultTitle); + } else { + findEntryByTitle(config, defaultTitle, ¤tLookupIndex); + } + /* set the default Image to an actual index */ + config->defaultImage = currentLookupIndex; + } + } + } + } + } else { + /* use pre-existing default entry from the file*/ + currentLookupIndex = config->defaultImage; + } if (isAddingBootEntry && (newBootEntryIndex <= config->defaultImage)) { @@ -2644,7 +2707,7 @@ } } -void displayEntry(struct singleEntry *entry, const char *prefix, int index) +void displayEntry(struct grubConfig *config, struct singleEntry *entry, const char *prefix, int index) { struct singleLine *line; char *root = NULL; @@ -2740,7 +2803,14 @@ line = getLineByType(LT_TITLE, entry->lines); if (line) { - printf("title=%s\n", line->elements[1].item); + char *entryTitle; + /* if we can extractTitle, then it's a zipl config and + * if not then we go ahead with what's existed prior */ + entryTitle = extractTitle(config, line); + if (!entryTitle) { + entryTitle=line->elements[1].item; + } + printf("title=%s\n", entryTitle); } else { char *title; line = getLineByType(LT_MENUENTRY, entry->lines); @@ -3156,11 +3226,11 @@ printf("lba\n"); } - displayEntry(entry, prefix, i); + displayEntry(config, entry, prefix, i); i++; while ((entry = findEntryByPath(config, kernel, prefix, &i))) { - displayEntry(entry, prefix, i); + displayEntry(config, entry, prefix, i); i++; } @@ -3195,12 +3265,12 @@ type & (LT_HYPER | LT_KERNEL | LT_MBMODULE | LT_INITRD | LT_KERNEL_EFI | LT_INITRD_EFI | LT_KERNEL_16 | LT_INITRD_16)) { - char *rootspec = - getRootSpecifier(tmplLine->elements[1].item); - if (rootspec != NULL) { + size_t rs = getRootSpecifier(tmplLine->elements[1].item); + if (rs > 0) { free(newLine->elements[1].item); - newLine->elements[1].item = - sdupprintf("%s%s", rootspec, val); + newLine->elements[1].item = sdupprintf( + "%.*s%s", (int) rs, + tmplLine->elements[1].item, val); } } } @@ -3490,23 +3560,67 @@ line->numElements--; } -int argMatch(const char *one, const char *two) +static int argNameMatch(const char *one, const char *two) { char *first, *second; - char *chptr; + char *chptra, *chptrb; + int rc; first = strcpy(alloca(strlen(one) + 1), one); second = strcpy(alloca(strlen(two) + 1), two); - chptr = strchr(first, '='); - if (chptr) - *chptr = '\0'; + chptra = strchr(first, '='); + if (chptra) + *chptra = '\0'; + + chptrb = strchr(second, '='); + if (chptrb) + *chptrb = '\0'; + + rc = strcmp(first, second); + + if (chptra) + *chptra = '='; + if (chptrb) + *chptrb = '='; + + return rc; +} + +static int argHasValue(const char *arg) +{ + char *chptr; - chptr = strchr(second, '='); + chptr = strchr(arg, '='); if (chptr) - *chptr = '\0'; + return 1; + return 0; +} + +static int argValueMatch(const char *one, const char *two) +{ + char *first, *second; + char *chptra, *chptrb; - return strcmp(first, second); + first = strcpy(alloca(strlen(one) + 1), one); + second = strcpy(alloca(strlen(two) + 1), two); + + chptra = strchr(first, '='); + if (chptra) + chptra += 1; + + chptrb = strchr(second, '='); + if (chptrb) + chptrb += 1; + + if (!chptra && !chptrb) + return 0; + else if (!chptra) + return *chptrb - 0; + else if (!chptrb) + return 0 - *chptra; + else + return strcmp(chptra, chptrb); } int updateActualImage(struct grubConfig *cfg, const char *image, @@ -3650,7 +3764,7 @@ } if (usedElements[i]) continue; - if (!argMatch(line->elements[i].item, *arg)) { + if (!argNameMatch(line->elements[i].item, *arg)) { usedElements[i] = 1; break; } @@ -3709,9 +3823,12 @@ !strcmp(line->elements[i].item, "--")) /* reached the end of hyper args, stop here */ break; - if (!argMatch(line->elements[i].item, *arg)) { - removeElement(line, i); - break; + if (!argNameMatch(line->elements[i].item, *arg)) { + if (!argHasValue(*arg) || + !argValueMatch(line->elements[i].item, *arg)) { + removeElement(line, i); + break; + } } } /* handle removing LT_ROOT line too */ @@ -4205,17 +4322,19 @@ return 1; } -static char *getRootSpecifier(char *str) +static size_t getRootSpecifier(const char *str) { - char *idx, *rootspec = NULL; + size_t rs = 0; if (*str == '(') { - idx = rootspec = strdup(str); - while (*idx && (*idx != ')') && (!isspace(*idx))) - idx++; - *(++idx) = '\0'; + for (; str[rs] != ')' && !isspace(str[rs]); rs++) { + if (!str[rs]) + return rs; + } + rs++; } - return rootspec; + + return rs; } static char *getInitrdVal(struct grubConfig *config, @@ -5031,22 +5150,27 @@ if (!cfi) { if (grub2FindConfig(&grub2ConfigType)) { cfi = &grub2ConfigType; + configureGrub2 = 1; if (envPath) cfi->envFile = envPath; - } else + } else { #ifdef __ia64__ cfi = &eliloConfigType; -#elif __powerpc__ + configureLilo = 1; +#elif defined(__powerpc__) cfi = &yabootConfigType; -#elif __sparc__ + configureYaboot = 1; +#elif defined(__sparc__) cfi = &siloConfigType; -#elif __s390__ + configureSilo = 1; +#elif defined(__s390__) || defined(__s390x__) cfi = &ziplConfigType; -#elif __s390x__ - cfi = &ziplConfigtype; + configureZipl = 1; #else cfi = &grubConfigType; + configureGrub = 1; #endif + } } if (!grubConfig) { @@ -5240,7 +5364,7 @@ if (displayDefault) { struct singleLine *line; struct singleEntry *entry; - char *rootspec; + size_t rs; if (config->defaultImage == NO_DEFAULT_ENTRY) return 0; @@ -5259,9 +5383,8 @@ if (!line) return 0; - rootspec = getRootSpecifier(line->elements[1].item); - printf("%s%s\n", bootPrefix, line->elements[1].item + - ((rootspec != NULL) ? strlen(rootspec) : 0)); + rs = getRootSpecifier(line->elements[1].item); + printf("%s%s\n", bootPrefix, line->elements[1].item + rs); return 0;