--- trunk/grubby/grubby.c 2013/10/21 13:59:08 2252 +++ trunk/grubby/grubby.c 2014/07/16 09:49:24 2682 @@ -182,6 +182,8 @@ "/boot/grub/grub.conf", "/boot/grub/menu.lst", "/etc/grub.conf", + "/boot/grub2/grub.cfg", + "/boot/grub2-efi/grub.cfg", NULL }; static int i = -1; @@ -273,8 +275,8 @@ static char buf[1025]; char *s = NULL; char *ret = NULL; - char *envFile = info->envFile ? info->envFile : "/boot/grub2/grubenv"; - int rc = asprintf(&s, "grub2-editenv %s list | grep '^%s='", envFile, name); + char *envFile = info->envFile ? info->envFile : "/boot/grub/grubenv"; + int rc = asprintf(&s, "grub-editenv %s list | grep '^%s='", envFile, name); if (rc < 0) return NULL; @@ -297,13 +299,56 @@ return ret; } +static int sPopCount(const char *s, const char *c) +{ + int ret = 0; + if (!s) + return -1; + for (int i = 0; s[i] != '\0'; i++) + for (int j = 0; c[j] != '\0'; j++) + if (s[i] == c[j]) + ret++; + return ret; +} + +static char *shellEscape(const char *s) +{ + int l = strlen(s) + sPopCount(s, "'") * 2; + + char *ret = calloc(l+1, sizeof (*ret)); + if (!ret) + return NULL; + for (int i = 0, j = 0; s[i] != '\0'; i++, j++) { + if (s[i] == '\'') + ret[j++] = '\\'; + ret[j] = s[i]; + } + return ret; +} + +static void unquote(char *s) +{ + int l = strlen(s); + + if ((s[l-1] == '\'' && s[0] == '\'') || (s[l-1] == '"' && s[0] == '"')) { + memmove(s, s+1, l-2); + s[l-2] = '\0'; + } +} + static int grub2SetEnv(struct configFileInfo *info, char *name, char *value) { char *s = NULL; int rc = 0; - char *envFile = info->envFile ? info->envFile : "/boot/grub2/grubenv"; + char *envFile = info->envFile ? info->envFile : "/boot/grub/grubenv"; + + unquote(value); + value = shellEscape(value); + if (!value) + return -1; - rc = asprintf(&s, "grub2-editenv %s set '%s=%s'", envFile, name, value); + rc = asprintf(&s, "grub-editenv %s set '%s=%s'", envFile, name, value); + free(value); if (rc <0) return -1; @@ -1023,6 +1068,15 @@ return 0; } +static int isnumber(const char *s) +{ + int i; + for (i = 0; s[i] != '\0'; i++) + if (s[i] < '0' || s[i] > '9') + return 0; + return i; +} + static struct grubConfig * readConfig(const char * inName, struct configFileInfo * cfi) { int in; @@ -1319,7 +1373,12 @@ char *defTitle = cfi->getEnv(cfg->cfi, "saved_entry"); if (defTitle) { int index = 0; - entry = findEntryByTitle(cfg, defTitle, &index); + if (isnumber(defTitle)) { + index = atoi(defTitle); + entry = findEntryByIndex(cfg, index); + } else { + entry = findEntryByTitle(cfg, defTitle, &index); + } if (entry) cfg->defaultImage = index; } @@ -1368,7 +1427,12 @@ char *defTitle = cfi->getEnv(cfg->cfi, "saved_entry"); if (defTitle) { int index = 0; - entry = findEntryByTitle(cfg, defTitle, &index); + if (isnumber(defTitle)) { + index = atoi(defTitle); + entry = findEntryByIndex(cfg, index); + } else { + entry = findEntryByTitle(cfg, defTitle, &index); + } if (entry) cfg->defaultImage = index; } @@ -2019,7 +2083,14 @@ char *defTitle = cfg->cfi->getEnv(cfg->cfi, "saved_entry"); if (defTitle) { int index = 0; - entry = findEntryByTitle(cfg, defTitle, &index); + if (isnumber(defTitle)) { + index = atoi(defTitle); + entry = findEntryByIndex(cfg, index); + } else { + entry = findEntryByTitle(cfg, defTitle, &index); + } + if (entry) + cfg->defaultImage = index; } } } else if (cfg->defaultImage > -1) { @@ -3187,6 +3258,42 @@ return rc; } +int addMBInitrd(struct grubConfig * cfg, const char *newMBKernel, + const char * image, const char * prefix, const char * initrd) { + struct singleEntry * entry; + struct singleLine * line, * kernelLine, *endLine = NULL; + int index = 0; + + if (!image) return 0; + + for (; (entry = findEntryByPath(cfg, newMBKernel, prefix, &index)); index++) { + kernelLine = getLineByType(LT_MBMODULE, entry->lines); + if (!kernelLine) continue; + + if (prefix) { + int prefixLen = strlen(prefix); + if (!strncmp(initrd, prefix, prefixLen)) + initrd += prefixLen; + } + endLine = getLineByType(LT_ENTRY_END, entry->lines); + if (endLine) + removeLine(entry, endLine); + line = addLine(entry, cfg->cfi, preferredLineType(LT_MBMODULE,cfg->cfi), + kernelLine->indent, initrd); + if (!line) + return 1; + if (endLine) { + line = addLine(entry, cfg->cfi, LT_ENTRY_END, "", NULL); + if (!line) + return 1; + } + + break; + } + + return 0; +} + int updateInitrd(struct grubConfig * cfg, const char * image, const char * prefix, const char * initrd) { struct singleEntry * entry; @@ -4360,6 +4467,9 @@ char * rootspec; if (config->defaultImage == -1) return 0; + if (config->defaultImage == DEFAULT_SAVED_GRUB2 && + cfi->defaultIsSaved) + config->defaultImage = 0; entry = findEntryByIndex(config, config->defaultImage); if (!entry) return 0; if (!suitableImage(entry, bootPrefix, 0, flags)) return 0; @@ -4378,6 +4488,9 @@ struct singleEntry * entry; if (config->defaultImage == -1) return 0; + if (config->defaultImage == DEFAULT_SAVED_GRUB2 && + cfi->defaultIsSaved) + config->defaultImage = 0; entry = findEntryByIndex(config, config->defaultImage); if (!entry) return 0; @@ -4400,6 +4513,9 @@ } else if (displayDefaultIndex) { if (config->defaultImage == -1) return 0; + if (config->defaultImage == DEFAULT_SAVED_GRUB2 && + cfi->defaultIsSaved) + config->defaultImage = 0; printf("%i\n", config->defaultImage); return 0; @@ -4419,8 +4535,15 @@ if (updateImage(config, updateKernelPath, bootPrefix, newKernelArgs, removeArgs, newMBKernelArgs, removeMBKernelArgs)) return 1; if (updateKernelPath && newKernelInitrd) { - if (updateInitrd(config, updateKernelPath, bootPrefix, - newKernelInitrd)) return 1; + if (newMBKernel) { + if (addMBInitrd(config, newMBKernel, updateKernelPath, + bootPrefix, newKernelInitrd)) + return 1; + } else { + if (updateInitrd(config, updateKernelPath, bootPrefix, + newKernelInitrd)) + return 1; + } } if (addNewKernel(config, template, bootPrefix, newKernelPath, newKernelTitle, newKernelArgs, newKernelInitrd,