--- trunk/grubby/grubby.c 2017/06/27 14:11:58 3002 +++ trunk/grubby/grubby.c 2017/06/27 14:34:11 3014 @@ -75,6 +75,7 @@ }; enum lineType_e { + LT_UNIDENTIFIED = 0, LT_WHITESPACE = 1 << 0, LT_TITLE = 1 << 1, LT_KERNEL = 1 << 2, @@ -750,6 +751,33 @@ return buf; } +static inline int +kwcmp(struct keywordTypes *kw, const char * label, int case_insensitive) +{ + int kwl = strlen(kw->key); + int ll = strlen(label); + int rc; + int (*snc)(const char *s1, const char *s2, size_t n) = + case_insensitive ? strncasecmp : strncmp; + int (*sc)(const char *s1, const char *s2) = + case_insensitive ? strcasecmp : strcmp; + + rc = snc(kw->key, label, kwl); + if (rc) + return rc; + + for (int i = kwl; i < ll; i++) { + if (isspace(label[i])) + return 0; + if (kw->separatorChar && label[i] == kw->separatorChar) + return 0; + else if (kw->nextChar && label[i] == kw->nextChar) + return 0; + return sc(kw->key+kwl, label+kwl); + } + return 0; +} + static enum lineType_e preferredLineType(enum lineType_e type, struct configFileInfo *cfi) { @@ -815,13 +843,8 @@ struct configFileInfo *cfi) { for (struct keywordTypes * kw = cfi->keywords; kw->key; kw++) { - if (cfi->caseInsensitive) { - if (!strcasecmp(keyword, kw->key)) - return kw->type; - } else { - if (!strcmp(keyword, kw->key)) - return kw->type; - } + if (!kwcmp(kw, keyword, cfi->caseInsensitive)) + return kw->type; } return LT_UNKNOWN; } @@ -916,6 +939,7 @@ static void lineInit(struct singleLine *line) { + line->type = LT_UNIDENTIFIED; line->indent = NULL; line->elements = NULL; line->numElements = 0; @@ -998,7 +1022,7 @@ if (fprintf(out, "%s", line->elements[i].item) == -1) return -1; - if (i < line->numElements - 1) + if (i < line->numElements - 1 || line->type == LT_SET_VARIABLE) if (fprintf(out, "%s", line->elements[i].indent) == -1) return -1; } @@ -1053,6 +1077,8 @@ break; chptr++; } + if (line->type == LT_UNIDENTIFIED) + line->type = getTypeByKeyword(start, cfi); element->item = strndup(start, chptr - start); start = chptr; @@ -1118,7 +1144,7 @@ line->type = LT_WHITESPACE; line->numElements = 0; } - } else { + } else if (line->type == LT_INITRD) { struct keywordTypes *kw; kw = getKeywordByType(line->type, cfi); @@ -1180,6 +1206,39 @@ } } } + } else if (line->type == LT_SET_VARIABLE) { + /* and if it's a "set blah=" we need to split it + * yet a third way to avoid rhbz# XXX FIXME :/ + */ + char *eq; + int l; + int numElements = line->numElements; + struct lineElement *newElements; + eq = strchr(line->elements[1].item, '='); + if (!eq) + return 0; + l = eq - line->elements[1].item; + if (eq[1] != 0) + numElements++; + newElements = calloc(numElements,sizeof (*newElements)); + memcpy(&newElements[0], &line->elements[0], + sizeof (newElements[0])); + newElements[1].item = + strndup(line->elements[1].item, l); + newElements[1].indent = "="; + *(eq++) = '\0'; + newElements[2].item = strdup(eq); + free(line->elements[1].item); + if (line->elements[1].indent) + newElements[2].indent = line->elements[1].indent; + for (int i = 2; i < line->numElements; i++) { + newElements[i+1].item = line->elements[i].item; + newElements[i+1].indent = + line->elements[i].indent; + } + free(line->elements); + line->elements = newElements; + line->numElements = numElements; } } @@ -1285,13 +1344,12 @@ getKeywordByType(LT_DEFAULT, cfi); if (kwType && line->numElements == 3 && !strcmp(line->elements[1].item, kwType->key) - && !is_special_grub2_variable(line->elements[2]. - item)) { + && !is_special_grub2_variable( + line->elements[2].item)) { dbgPrintf("Line sets default config\n"); cfg->flags &= ~GRUB_CONFIG_NO_DEFAULT; defaultLine = line; } - } else if (iskernel(line->type)) { /* if by some freak chance this is multiboot and the * "module" lines came earlier in the template, make @@ -1545,16 +1603,33 @@ } } } else if (cfi->defaultIsVariable) { - char *value = defaultLine->elements[2].item; - while (*value && (*value == '"' || *value == '\'' || - *value == ' ' || *value == '\t')) - value++; - cfg->defaultImage = strtol(value, &end, 10); - while (*end && (*end == '"' || *end == '\'' || - *end == ' ' || *end == '\t')) - end++; - if (*end) - cfg->defaultImage = -1; + if (defaultLine->numElements == 2) { + char *value = defaultLine->elements[1].item + 8; + while (*value && (*value == '"' || + *value == '\'' || + *value == ' ' || + *value == '\t')) + value++; + cfg->defaultImage = strtol(value, &end, 10); + while (*end && (*end == '"' || *end == '\'' || + *end == ' ' || *end == '\t')) + end++; + if (*end) + cfg->defaultImage = -1; + } else if (defaultLine->numElements == 3) { + char *value = defaultLine->elements[2].item; + while (*value && (*value == '"' || + *value == '\'' || + *value == ' ' || + *value == '\t')) + value++; + cfg->defaultImage = strtol(value, &end, 10); + while (*end && (*end == '"' || *end == '\'' || + *end == ' ' || *end == '\t')) + end++; + if (*end) + cfg->defaultImage = -1; + } } else if (cfi->defaultSupportSaved && !strncmp(defaultLine->elements[1].item, "saved", 5)) { @@ -4135,16 +4210,22 @@ const char *newKernelArgs, const char *newKernelInitrd, const char **extraInitrds, int extraInitrdCount, const char *newMBKernel, const char *newMBKernelArgs, - const char *newDevTreePath) + const char *newDevTreePath, int newIndex) { - struct singleEntry *new; + struct singleEntry *new, *entry, *prev = NULL; struct singleLine *newLine = NULL, *tmplLine = NULL, *masterLine = NULL; int needs; + char *indexs; char *chptr; + int rc; if (!newKernelPath) return 0; + rc = asprintf(&indexs, "%d", newIndex); + if (rc < 0) + return 1; + /* if the newKernelTitle is too long silently munge it into something * we can live with. truncating is first check, then we'll just mess with * it until it looks better */ @@ -4167,9 +4248,20 @@ new = malloc(sizeof(*new)); new->skip = 0; new->multiboot = 0; - new->next = config->entries; new->lines = NULL; - config->entries = new; + entry = config->entries; + for (unsigned int i = 0; i < newIndex; i++) { + if (!entry) + break; + prev = entry; + entry = entry->next; + } + new->next = entry; + + if (prev) + prev->next = new; + else + config->entries = new; /* copy/update from the template */ needs = NEED_KERNEL | NEED_TITLE; @@ -4632,7 +4724,7 @@ abort(); } - if (updateImage(config, "0", prefix, newKernelArgs, NULL, + if (updateImage(config, indexs, prefix, newKernelArgs, NULL, newMBKernelArgs, NULL)) return 1; @@ -4662,6 +4754,7 @@ char *newDevTreePath = NULL; char *newMBKernel = NULL; char *newMBKernelArgs = NULL; + int newIndex = 0; char *removeMBKernelArgs = NULL; char *removeMBKernel = NULL; char *bootPrefix = NULL; @@ -4696,7 +4789,7 @@ NULL}, {"boot-filesystem", 0, POPT_ARG_STRING, &bootPrefix, 0, _ - ("filestystem which contains /boot directory (for testing only)"), + ("filesystem which contains /boot directory (for testing only)"), _("bootfs")}, #if defined(__i386__) || defined(__x86_64__) || defined (__powerpc64__) || defined (__ia64__) {"bootloader-probe", 0, POPT_ARG_NONE, &bootloaderProbe, 0, @@ -4768,6 +4861,9 @@ {"set-default-index", 0, POPT_ARG_INT, &defaultIndex, 0, _("make the given entry index the default entry"), _("entry-index")}, + {"set-index", 0, POPT_ARG_INT, &newIndex, 0, + _("use the given index when creating a new entry"), + _("entry-index")}, {"silo", 0, POPT_ARG_NONE, &configureSilo, 0, _("configure silo bootloader")}, {"title", 0, POPT_ARG_STRING, &newKernelTitle, 0, @@ -5183,7 +5279,8 @@ if (addNewKernel(config, template, bootPrefix, newKernelPath, newKernelTitle, newKernelArgs, newKernelInitrd, (const char **)extraInitrds, extraInitrdCount, - newMBKernel, newMBKernelArgs, newDevTreePath)) + newMBKernel, newMBKernelArgs, newDevTreePath, + newIndex)) return 1; if (numEntries(config) == 0) {