Magellan Linux

Diff of /tags/grubby-8_32/grubby.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1720 by niro, Sat Feb 18 00:51:28 2012 UTC revision 1746 by niro, Sat Feb 18 01:06:20 2012 UTC
# Line 46  Line 46 
46  #define dbgPrintf(format, args...)  #define dbgPrintf(format, args...)
47  #endif  #endif
48    
49    int debug = 0; /* Currently just for template debugging */
50    
51  #define _(A) (A)  #define _(A) (A)
52    
53  #define MAX_EXTRA_INITRDS  16 /* code segment checked by --bootloader-probe */  #define MAX_EXTRA_INITRDS  16 /* code segment checked by --bootloader-probe */
# Line 239  const char *grub2FindConfig(struct confi Line 241  const char *grub2FindConfig(struct confi
241      return configFiles[i];      return configFiles[i];
242  }  }
243    
244    int sizeOfSingleLine(struct singleLine * line) {
245      int i;
246      int count = 0;
247    
248      for (i = 0; i < line->numElements; i++) {
249        int indentSize = 0;
250    
251        count = count + strlen(line->elements[i].item);
252    
253        indentSize = strlen(line->elements[i].indent);
254        if (indentSize > 0)
255          count = count + indentSize;
256        else
257          /* be extra safe and add room for whitespaces */
258          count = count + 1;
259      }
260    
261      /* room for trailing terminator */
262      count = count + 1;
263    
264      return count;
265    }
266    
267    char *grub2ExtractTitle(struct singleLine * line) {
268        char * current;
269        char * current_indent;
270        int current_len;
271        int current_indent_len;
272        int i;
273    
274        /* bail out if line does not start with menuentry */
275        if (strcmp(line->elements[0].item, "menuentry"))
276          return NULL;
277    
278        i = 1;
279        current = line->elements[i].item;
280        current_len = strlen(current);
281    
282        /* if second word is quoted, strip the quotes and return single word */
283        if ((*current == '\'') && (*(current + current_len - 1) == '\'')) {
284          char *tmp;
285    
286          tmp = strdup(current);
287          *(tmp + current_len - 1) = '\0';
288          return ++tmp;
289        }
290    
291        /* if no quotes, return second word verbatim */
292        if (*current != '\'') {
293          return current;
294        }
295    
296        /* second element start with a quote, so we have to find the element
297         * whose last character is also quote (assuming it's the closing one) */
298        if (*current == '\'') {
299          int resultMaxSize;
300          char * result;
301    
302          resultMaxSize = sizeOfSingleLine(line);
303          result = malloc(resultMaxSize);
304          snprintf(result, resultMaxSize, "%s", ++current);
305    
306          i++;
307          for (; i < line->numElements; ++i) {
308     current = line->elements[i].item;
309     current_len = strlen(current);
310     current_indent = line->elements[i].indent;
311     current_indent_len = strlen(current_indent);
312    
313     strncat(result, current_indent, current_indent_len);
314     if (*(current + current_len - 1) != '\'') {
315      strncat(result, current, current_len);
316     } else {
317      strncat(result, current, current_len - 1);
318      break;
319     }
320          }
321          return result;
322        }
323    
324        return NULL;
325    }
326    
327  struct configFileInfo grub2ConfigType = {  struct configFileInfo grub2ConfigType = {
328      .findConfig = grub2FindConfig,      .findConfig = grub2FindConfig,
329      .keywords = grub2Keywords,      .keywords = grub2Keywords,
# Line 874  static struct grubConfig * readConfig(co Line 959  static struct grubConfig * readConfig(co
959      cfg->secondaryIndent = strdup(line->indent);      cfg->secondaryIndent = strdup(line->indent);
960   }   }
961    
962   if (isEntryStart(line, cfi)) {   if (isEntryStart(line, cfi) || (cfg->entries && !sawEntry)) {
963      sawEntry = 1;      sawEntry = 1;
964      if (!entry) {      if (!entry) {
965   cfg->entries = malloc(sizeof(*entry));   cfg->entries = malloc(sizeof(*entry));
# Line 1338  static char *findDiskForRoot() Line 1423  static char *findDiskForRoot()
1423      return NULL;      return NULL;
1424  }  }
1425    
1426    void printEntry(struct singleEntry * entry) {
1427        int i;
1428        struct singleLine * line;
1429    
1430        for (line = entry->lines; line; line = line->next) {
1431     fprintf(stderr, "DBG: %s", line->indent);
1432     for (i = 0; i < line->numElements; i++) {
1433     fprintf(stderr, "%s%s",
1434        line->elements[i].item, line->elements[i].indent);
1435     }
1436     fprintf(stderr, "\n");
1437        }
1438    }
1439    
1440    void notSuitablePrintf(struct singleEntry * entry, const char *fmt, ...)
1441    {
1442        va_list argp;
1443    
1444        if (!debug)
1445     return;
1446    
1447        va_start(argp, fmt);
1448        fprintf(stderr, "DBG: Image entry failed: ");
1449        vfprintf(stderr, fmt, argp);
1450        printEntry(entry);
1451        va_end(argp);
1452    }
1453    
1454    #define beginswith(s, c) ((s) && (s)[0] == (c))
1455    
1456    static int endswith(const char *s, char c)
1457    {
1458     int slen;
1459    
1460     if (!s && !s[0])
1461     return 0;
1462     slen = strlen(s) - 1;
1463    
1464     return s[slen] == c;
1465    }
1466    
1467  int suitableImage(struct singleEntry * entry, const char * bootPrefix,  int suitableImage(struct singleEntry * entry, const char * bootPrefix,
1468    int skipRemoved, int flags) {    int skipRemoved, int flags) {
1469      struct singleLine * line;      struct singleLine * line;
# Line 1347  int suitableImage(struct singleEntry * e Line 1473  int suitableImage(struct singleEntry * e
1473      char * rootspec;      char * rootspec;
1474      char * rootdev;      char * rootdev;
1475    
1476      if (skipRemoved && entry->skip) return 0;      if (skipRemoved && entry->skip) {
1477     notSuitablePrintf(entry, "marked to skip\n");
1478     return 0;
1479        }
1480    
1481      line = getLineByType(LT_KERNEL|LT_HYPER, entry->lines);      line = getLineByType(LT_KERNEL|LT_HYPER, entry->lines);
1482      if (!line || line->numElements < 2) return 0;      if (!line) {
1483     notSuitablePrintf(entry, "no line found\n");
1484     return 0;
1485        }
1486        if (line->numElements < 2) {
1487     notSuitablePrintf(entry, "line has only %d elements\n",
1488        line->numElements);
1489     return 0;
1490        }
1491    
1492      if (flags & GRUBBY_BADIMAGE_OKAY) return 1;      if (flags & GRUBBY_BADIMAGE_OKAY) return 1;
1493    
1494      fullName = alloca(strlen(bootPrefix) +      fullName = alloca(strlen(bootPrefix) +
1495        strlen(line->elements[1].item) + 1);        strlen(line->elements[1].item) + 1);
1496      rootspec = getRootSpecifier(line->elements[1].item);      rootspec = getRootSpecifier(line->elements[1].item);
1497      sprintf(fullName, "%s%s", bootPrefix,      int rootspec_offset = rootspec ? strlen(rootspec) : 0;
1498              line->elements[1].item + (rootspec ? strlen(rootspec) : 0));      int hasslash = endswith(bootPrefix, '/') ||
1499      if (access(fullName, R_OK)) return 0;       beginswith(line->elements[1].item + rootspec_offset, '/');
1500        sprintf(fullName, "%s%s%s", bootPrefix, hasslash ? "" : "/",
1501                line->elements[1].item + rootspec_offset);
1502        if (access(fullName, R_OK)) {
1503     notSuitablePrintf(entry, "access to %s failed\n", fullName);
1504     return 0;
1505        }
1506      for (i = 2; i < line->numElements; i++)      for (i = 2; i < line->numElements; i++)
1507   if (!strncasecmp(line->elements[i].item, "root=", 5)) break;   if (!strncasecmp(line->elements[i].item, "root=", 5)) break;
1508      if (i < line->numElements) {      if (i < line->numElements) {
# Line 1378  int suitableImage(struct singleEntry * e Line 1520  int suitableImage(struct singleEntry * e
1520      line = getLineByType(LT_KERNELARGS|LT_MBMODULE, entry->lines);      line = getLineByType(LT_KERNELARGS|LT_MBMODULE, entry->lines);
1521    
1522              /* failed to find one */              /* failed to find one */
1523              if (!line) return 0;              if (!line) {
1524     notSuitablePrintf(entry, "no line found\n");
1525     return 0;
1526                }
1527    
1528      for (i = 1; i < line->numElements; i++)      for (i = 1; i < line->numElements; i++)
1529          if (!strncasecmp(line->elements[i].item, "root=", 5)) break;          if (!strncasecmp(line->elements[i].item, "root=", 5)) break;
1530      if (i < line->numElements)      if (i < line->numElements)
1531          dev = line->elements[i].item + 5;          dev = line->elements[i].item + 5;
1532      else {      else {
1533     notSuitablePrintf(entry, "no root= entry found\n");
1534   /* it failed too...  can't find root= */   /* it failed too...  can't find root= */
1535          return 0;          return 0;
1536              }              }
# Line 1392  int suitableImage(struct singleEntry * e Line 1538  int suitableImage(struct singleEntry * e
1538      }      }
1539    
1540      dev = getpathbyspec(dev);      dev = getpathbyspec(dev);
1541      if (!dev)      if (!getpathbyspec(dev)) {
1542            notSuitablePrintf(entry, "can't find blkid entry for %s\n", dev);
1543          return 0;          return 0;
1544        } else
1545     dev = getpathbyspec(dev);
1546    
1547      rootdev = findDiskForRoot();      rootdev = findDiskForRoot();
1548      if (!rootdev)      if (!rootdev) {
1549            notSuitablePrintf(entry, "can't find root device\n");
1550   return 0;   return 0;
1551        }
1552    
1553      if (!getuuidbydev(rootdev) || !getuuidbydev(dev)) {      if (!getuuidbydev(rootdev) || !getuuidbydev(dev)) {
1554            notSuitablePrintf(entry, "uuid missing: rootdev %s, dev %s\n",
1555     getuuidbydev(rootdev), getuuidbydev(dev));
1556          free(rootdev);          free(rootdev);
1557          return 0;          return 0;
1558      }      }
1559    
1560      if (strcmp(getuuidbydev(rootdev), getuuidbydev(dev))) {      if (strcmp(getuuidbydev(rootdev), getuuidbydev(dev))) {
1561            notSuitablePrintf(entry, "uuid mismatch: rootdev %s, dev %s\n",
1562     getuuidbydev(rootdev), getuuidbydev(dev));
1563   free(rootdev);   free(rootdev);
1564          return 0;          return 0;
1565      }      }
# Line 2961  int addNewKernel(struct grubConfig * con Line 3116  int addNewKernel(struct grubConfig * con
3116   }   }
3117      } else if (tmplLine->type == LT_ECHO) {      } else if (tmplLine->type == LT_ECHO) {
3118      requote(tmplLine, config->cfi);      requote(tmplLine, config->cfi);
3119        static const char *prefix = "'Loading ";
3120      if (tmplLine->numElements > 1 &&      if (tmplLine->numElements > 1 &&
3121      strstr(tmplLine->elements[1].item, "'Loading Linux ")) {      strstr(tmplLine->elements[1].item, prefix) &&
3122   char *prefix = "'Loading ";      masterLine->next && masterLine->next->type == LT_KERNEL) {
3123   char *newTitle = malloc(strlen(prefix) +   char *newTitle = malloc(strlen(prefix) +
3124   strlen(newKernelTitle) + 2);   strlen(newKernelTitle) + 2);
3125    
# Line 3161  int main(int argc, const char ** argv) { Line 3317  int main(int argc, const char ** argv) {
3317      int copyDefault = 0, makeDefault = 0;      int copyDefault = 0, makeDefault = 0;
3318      int displayDefault = 0;      int displayDefault = 0;
3319      int displayDefaultIndex = 0;      int displayDefaultIndex = 0;
3320        int displayDefaultTitle = 0;
3321      struct poptOption options[] = {      struct poptOption options[] = {
3322   { "add-kernel", 0, POPT_ARG_STRING, &newKernelPath, 0,   { "add-kernel", 0, POPT_ARG_STRING, &newKernelPath, 0,
3323      _("add an entry for the specified kernel"), _("kernel-path") },      _("add an entry for the specified kernel"), _("kernel-path") },
# Line 3191  int main(int argc, const char ** argv) { Line 3348  int main(int argc, const char ** argv) {
3348        "the kernel referenced by the default image does not exist, "        "the kernel referenced by the default image does not exist, "
3349        "the first linux entry whose kernel does exist is used as the "        "the first linux entry whose kernel does exist is used as the "
3350        "template"), NULL },        "template"), NULL },
3351     { "debug", 0, 0, &debug, 0,
3352        _("print debugging information for failures") },
3353   { "default-kernel", 0, 0, &displayDefault, 0,   { "default-kernel", 0, 0, &displayDefault, 0,
3354      _("display the path of the default kernel") },      _("display the path of the default kernel") },
3355   { "default-index", 0, 0, &displayDefaultIndex, 0,   { "default-index", 0, 0, &displayDefaultIndex, 0,
3356      _("display the index of the default kernel") },      _("display the index of the default kernel") },
3357     { "default-title", 0, 0, &displayDefaultTitle, 0,
3358        _("display the title of the default kernel") },
3359   { "elilo", 0, POPT_ARG_NONE, &configureELilo, 0,   { "elilo", 0, POPT_ARG_NONE, &configureELilo, 0,
3360      _("configure elilo bootloader") },      _("configure elilo bootloader") },
3361   { "extlinux", 0, POPT_ARG_NONE, &configureExtLinux, 0,   { "extlinux", 0, POPT_ARG_NONE, &configureExtLinux, 0,
# Line 3338  int main(int argc, const char ** argv) { Line 3499  int main(int argc, const char ** argv) {
3499    
3500      if (bootloaderProbe && (displayDefault || kernelInfo || newKernelVersion ||      if (bootloaderProbe && (displayDefault || kernelInfo || newKernelVersion ||
3501    newKernelPath || removeKernelPath || makeDefault ||    newKernelPath || removeKernelPath || makeDefault ||
3502    defaultKernel || displayDefaultIndex)) {    defaultKernel || displayDefaultIndex || displayDefaultTitle)) {
3503   fprintf(stderr, _("grubby: --bootloader-probe may not be used with "   fprintf(stderr, _("grubby: --bootloader-probe may not be used with "
3504    "specified option"));    "specified option"));
3505   return 1;   return 1;
# Line 3389  int main(int argc, const char ** argv) { Line 3550  int main(int argc, const char ** argv) {
3550    
3551      if (!removeKernelPath && !newKernelPath && !displayDefault && !defaultKernel      if (!removeKernelPath && !newKernelPath && !displayDefault && !defaultKernel
3552   && !kernelInfo && !bootloaderProbe && !updateKernelPath   && !kernelInfo && !bootloaderProbe && !updateKernelPath
3553          && !removeMBKernel && !displayDefaultIndex) {          && !removeMBKernel && !displayDefaultIndex && !displayDefaultTitle) {
3554   fprintf(stderr, _("grubby: no action specified\n"));   fprintf(stderr, _("grubby: no action specified\n"));
3555   return 1;   return 1;
3556      }      }
# Line 3485  int main(int argc, const char ** argv) { Line 3646  int main(int argc, const char ** argv) {
3646    
3647   return 0;   return 0;
3648    
3649        } else if (displayDefaultTitle) {
3650     struct singleLine * line;
3651     struct singleEntry * entry;
3652    
3653     if (config->defaultImage == -1) return 0;
3654     entry = findEntryByIndex(config, config->defaultImage);
3655     if (!entry) return 0;
3656    
3657     if (!configureGrub2) {
3658      line = getLineByType(LT_TITLE, entry->lines);
3659      if (!line) return 0;
3660      printf("%s\n", line->elements[1].item);
3661    
3662     } else {
3663      char * title;
3664    
3665      dbgPrintf("This is GRUB2, default title is embeded in menuentry\n");
3666      line = getLineByType(LT_MENUENTRY, entry->lines);
3667      if (!line) return 0;
3668      title = grub2ExtractTitle(line);
3669      if (title)
3670        printf("%s\n", title);
3671     }
3672     return 0;
3673    
3674      } else if (displayDefaultIndex) {      } else if (displayDefaultIndex) {
3675          if (config->defaultImage == -1) return 0;          if (config->defaultImage == -1) return 0;
3676          printf("%i\n", config->defaultImage);          printf("%i\n", config->defaultImage);

Legend:
Removed from v.1720  
changed lines
  Added in v.1746