--- trunk/grubby/grubby.c 2012/02/18 00:49:41 1718 +++ trunk/grubby/grubby.c 2012/02/18 01:05:52 1745 @@ -46,6 +46,8 @@ #define dbgPrintf(format, args...) #endif +int debug = 0; /* Currently just for template debugging */ + #define _(A) (A) #define MAX_EXTRA_INITRDS 16 /* code segment checked by --bootloader-probe */ @@ -874,7 +876,7 @@ cfg->secondaryIndent = strdup(line->indent); } - if (isEntryStart(line, cfi)) { + if (isEntryStart(line, cfi) || (cfg->entries && !sawEntry)) { sawEntry = 1; if (!entry) { cfg->entries = malloc(sizeof(*entry)); @@ -1338,6 +1340,47 @@ return NULL; } +void printEntry(struct singleEntry * entry) { + int i; + struct singleLine * line; + + for (line = entry->lines; line; line = line->next) { + fprintf(stderr, "DBG: %s", line->indent); + for (i = 0; i < line->numElements; i++) { + fprintf(stderr, "%s%s", + line->elements[i].item, line->elements[i].indent); + } + fprintf(stderr, "\n"); + } +} + +void notSuitablePrintf(struct singleEntry * entry, const char *fmt, ...) +{ + va_list argp; + + if (!debug) + return; + + va_start(argp, fmt); + fprintf(stderr, "DBG: Image entry failed: "); + vfprintf(stderr, fmt, argp); + printEntry(entry); + va_end(argp); +} + +#define beginswith(s, c) ((s) && (s)[0] == (c)) + +static int endswith(const char *s, char c) +{ + int slen; + + if (!s && !s[0]) + return 0; + slen = strlen(s) - 1; + + return s[slen] == c; +} + int suitableImage(struct singleEntry * entry, const char * bootPrefix, int skipRemoved, int flags) { struct singleLine * line; @@ -1347,20 +1390,36 @@ char * rootspec; char * rootdev; - if (skipRemoved && entry->skip) return 0; + if (skipRemoved && entry->skip) { + notSuitablePrintf(entry, "marked to skip\n"); + return 0; + } line = getLineByType(LT_KERNEL|LT_HYPER, entry->lines); - if (!line || line->numElements < 2) return 0; + if (!line) { + notSuitablePrintf(entry, "no line found\n"); + return 0; + } + if (line->numElements < 2) { + notSuitablePrintf(entry, "line has only %d elements\n", + line->numElements); + return 0; + } if (flags & GRUBBY_BADIMAGE_OKAY) return 1; fullName = alloca(strlen(bootPrefix) + strlen(line->elements[1].item) + 1); rootspec = getRootSpecifier(line->elements[1].item); - sprintf(fullName, "%s%s", bootPrefix, - line->elements[1].item + (rootspec ? strlen(rootspec) : 0)); - if (access(fullName, R_OK)) return 0; - + int rootspec_offset = rootspec ? strlen(rootspec) : 0; + int hasslash = endswith(bootPrefix, '/') || + beginswith(line->elements[1].item + rootspec_offset, '/'); + sprintf(fullName, "%s%s%s", bootPrefix, hasslash ? "" : "/", + line->elements[1].item + rootspec_offset); + if (access(fullName, R_OK)) { + notSuitablePrintf(entry, "access to %s failed\n", fullName); + return 0; + } for (i = 2; i < line->numElements; i++) if (!strncasecmp(line->elements[i].item, "root=", 5)) break; if (i < line->numElements) { @@ -1378,13 +1437,17 @@ line = getLineByType(LT_KERNELARGS|LT_MBMODULE, entry->lines); /* failed to find one */ - if (!line) return 0; + if (!line) { + notSuitablePrintf(entry, "no line found\n"); + return 0; + } for (i = 1; i < line->numElements; i++) if (!strncasecmp(line->elements[i].item, "root=", 5)) break; if (i < line->numElements) dev = line->elements[i].item + 5; else { + notSuitablePrintf(entry, "no root= entry found\n"); /* it failed too... can't find root= */ return 0; } @@ -1392,19 +1455,28 @@ } dev = getpathbyspec(dev); - if (!dev) + if (!getpathbyspec(dev)) { + notSuitablePrintf(entry, "can't find blkid entry for %s\n", dev); return 0; + } else + dev = getpathbyspec(dev); rootdev = findDiskForRoot(); - if (!rootdev) + if (!rootdev) { + notSuitablePrintf(entry, "can't find root device\n"); return 0; + } if (!getuuidbydev(rootdev) || !getuuidbydev(dev)) { + notSuitablePrintf(entry, "uuid missing: rootdev %s, dev %s\n", + getuuidbydev(rootdev), getuuidbydev(dev)); free(rootdev); return 0; } if (strcmp(getuuidbydev(rootdev), getuuidbydev(dev))) { + notSuitablePrintf(entry, "uuid mismatch: rootdev %s, dev %s\n", + getuuidbydev(rootdev), getuuidbydev(dev)); free(rootdev); return 0; } @@ -2961,9 +3033,10 @@ } } else if (tmplLine->type == LT_ECHO) { requote(tmplLine, config->cfi); + static const char *prefix = "'Loading "; if (tmplLine->numElements > 1 && - strstr(tmplLine->elements[1].item, "'Loading Linux ")) { - char *prefix = "'Loading "; + strstr(tmplLine->elements[1].item, prefix) && + masterLine->next && masterLine->next->type == LT_KERNEL) { char *newTitle = malloc(strlen(prefix) + strlen(newKernelTitle) + 2); @@ -3160,6 +3233,8 @@ struct singleEntry * template = NULL; int copyDefault = 0, makeDefault = 0; int displayDefault = 0; + int displayDefaultIndex = 0; + int displayDefaultTitle = 0; struct poptOption options[] = { { "add-kernel", 0, POPT_ARG_STRING, &newKernelPath, 0, _("add an entry for the specified kernel"), _("kernel-path") }, @@ -3190,8 +3265,14 @@ "the kernel referenced by the default image does not exist, " "the first linux entry whose kernel does exist is used as the " "template"), NULL }, + { "debug", 0, 0, &debug, 0, + _("print debugging information for failures") }, { "default-kernel", 0, 0, &displayDefault, 0, _("display the path of the default kernel") }, + { "default-index", 0, 0, &displayDefaultIndex, 0, + _("display the index of the default kernel") }, + { "default-title", 0, 0, &displayDefaultTitle, 0, + _("display the title of the default kernel") }, { "elilo", 0, POPT_ARG_NONE, &configureELilo, 0, _("configure elilo bootloader") }, { "extlinux", 0, POPT_ARG_NONE, &configureExtLinux, 0, @@ -3335,7 +3416,7 @@ if (bootloaderProbe && (displayDefault || kernelInfo || newKernelVersion || newKernelPath || removeKernelPath || makeDefault || - defaultKernel)) { + defaultKernel || displayDefaultIndex || displayDefaultTitle)) { fprintf(stderr, _("grubby: --bootloader-probe may not be used with " "specified option")); return 1; @@ -3386,7 +3467,7 @@ if (!removeKernelPath && !newKernelPath && !displayDefault && !defaultKernel && !kernelInfo && !bootloaderProbe && !updateKernelPath - && !removeMBKernel) { + && !removeMBKernel && !displayDefaultIndex && !displayDefaultTitle) { fprintf(stderr, _("grubby: no action specified\n")); return 1; } @@ -3481,6 +3562,59 @@ ((rootspec != NULL) ? strlen(rootspec) : 0)); return 0; + + } else if (displayDefaultTitle) { + struct singleLine * line; + struct singleEntry * entry; + + if (config->defaultImage == -1) return 0; + entry = findEntryByIndex(config, config->defaultImage); + if (!entry) return 0; + + if (!configureGrub2) { + line = getLineByType(LT_TITLE, entry->lines); + if (!line) return 0; + printf("%s\n", line->elements[1].item); + + } else { + int i; + size_t len; + char * start; + char * tmp; + + dbgPrintf("This is GRUB2, default title is embeded in menuentry\n"); + line = getLineByType(LT_MENUENTRY, entry->lines); + if (!line) return 0; + + for (i = 0; i < line->numElements; i++) { + + if (!strcmp(line->elements[i].item, "menuentry")) + continue; + + if (*line->elements[i].item == '\'') + start = line->elements[i].item + 1; + else + start = line->elements[i].item; + + len = strlen(start); + if (*(start + len - 1) == '\'') { + tmp = strdup(start); + *(tmp + len - 1) = '\0'; + printf("%s", tmp); + free(tmp); + break; + } else { + printf("%s ", start); + } + } + printf("\n"); + } + return 0; + + } else if (displayDefaultIndex) { + if (config->defaultImage == -1) return 0; + printf("%i\n", config->defaultImage); + } else if (kernelInfo) return displayInfo(config, kernelInfo, bootPrefix);