Magellan Linux

Diff of /trunk/grubby/grubby.c

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

revision 3002 by niro, Tue Jun 27 14:11:58 2017 UTC revision 3136 by niro, Tue Jul 7 11:09:37 2020 UTC
# Line 75  struct lineElement { Line 75  struct lineElement {
75  };  };
76    
77  enum lineType_e {  enum lineType_e {
78     LT_UNIDENTIFIED = 0,
79   LT_WHITESPACE = 1 << 0,   LT_WHITESPACE = 1 << 0,
80   LT_TITLE = 1 << 1,   LT_TITLE = 1 << 1,
81   LT_KERNEL = 1 << 2,   LT_KERNEL = 1 << 2,
# Line 131  struct singleEntry { Line 132  struct singleEntry {
132  #define NEED_DEVTREE (1 << 6)  #define NEED_DEVTREE (1 << 6)
133    
134  #define MAIN_DEFAULT    (1 << 0)  #define MAIN_DEFAULT    (1 << 0)
135    #define FIRST_ENTRY_INDEX    0 /* boot entry index value begin and increment
136       from this initial value */
137    #define NO_DEFAULT_ENTRY    -1 /* indicates that no specific default boot
138       entry was set or currently exists */
139  #define DEFAULT_SAVED       -2  #define DEFAULT_SAVED       -2
140  #define DEFAULT_SAVED_GRUB2 -3  #define DEFAULT_SAVED_GRUB2 -3
141    
# Line 676  struct grubConfig { Line 681  struct grubConfig {
681   int fallbackImage; /* just like defaultImage */   int fallbackImage; /* just like defaultImage */
682   int flags;   int flags;
683   struct configFileInfo *cfi;   struct configFileInfo *cfi;
684     int isModified; /* assumes only one entry added
685       per invocation of grubby */
686  };  };
687    
688  blkid_cache blkid;  blkid_cache blkid;
# Line 750  static char *sdupprintf(const char *form Line 757  static char *sdupprintf(const char *form
757   return buf;   return buf;
758  }  }
759    
760    static inline int
761    kwcmp(struct keywordTypes *kw, const char * label, int case_insensitive)
762    {
763        int kwl = strlen(kw->key);
764        int ll = strlen(label);
765        int rc;
766        int (*snc)(const char *s1, const char *s2, size_t n) =
767               case_insensitive ? strncasecmp : strncmp;
768        int (*sc)(const char *s1, const char *s2) =
769               case_insensitive ? strcasecmp : strcmp;
770    
771        rc = snc(kw->key, label, kwl);
772        if (rc)
773           return rc;
774    
775        for (int i = kwl; i < ll; i++) {
776           if (isspace(label[i]))
777               return 0;
778           if (kw->separatorChar && label[i] == kw->separatorChar)
779               return 0;
780           else if (kw->nextChar && label[i] == kw->nextChar)
781               return 0;
782           return sc(kw->key+kwl, label+kwl);
783        }
784        return 0;
785    }
786    
787  static enum lineType_e preferredLineType(enum lineType_e type,  static enum lineType_e preferredLineType(enum lineType_e type,
788   struct configFileInfo *cfi)   struct configFileInfo *cfi)
789  {  {
# Line 815  static enum lineType_e getTypeByKeyword( Line 849  static enum lineType_e getTypeByKeyword(
849   struct configFileInfo *cfi)   struct configFileInfo *cfi)
850  {  {
851   for (struct keywordTypes * kw = cfi->keywords; kw->key; kw++) {   for (struct keywordTypes * kw = cfi->keywords; kw->key; kw++) {
852   if (cfi->caseInsensitive) {   if (!kwcmp(kw, keyword, cfi->caseInsensitive))
853   if (!strcasecmp(keyword, kw->key))   return kw->type;
  return kw->type;  
  } else {  
  if (!strcmp(keyword, kw->key))  
  return kw->type;  
  }  
854   }   }
855   return LT_UNKNOWN;   return LT_UNKNOWN;
856  }  }
# Line 916  static int readFile(int fd, char **bufPt Line 945  static int readFile(int fd, char **bufPt
945    
946  static void lineInit(struct singleLine *line)  static void lineInit(struct singleLine *line)
947  {  {
948     line->type = LT_UNIDENTIFIED;
949   line->indent = NULL;   line->indent = NULL;
950   line->elements = NULL;   line->elements = NULL;
951   line->numElements = 0;   line->numElements = 0;
# Line 998  static int lineWrite(FILE * out, struct Line 1028  static int lineWrite(FILE * out, struct
1028    
1029   if (fprintf(out, "%s", line->elements[i].item) == -1)   if (fprintf(out, "%s", line->elements[i].item) == -1)
1030   return -1;   return -1;
1031   if (i < line->numElements - 1)   if (i < line->numElements - 1 || line->type == LT_SET_VARIABLE)
1032   if (fprintf(out, "%s", line->elements[i].indent) == -1)   if (fprintf(out, "%s", line->elements[i].indent) == -1)
1033   return -1;   return -1;
1034   }   }
# Line 1053  static int getNextLine(char **bufPtr, st Line 1083  static int getNextLine(char **bufPtr, st
1083   break;   break;
1084   chptr++;   chptr++;
1085   }   }
1086     if (line->type == LT_UNIDENTIFIED)
1087     line->type = getTypeByKeyword(start, cfi);
1088   element->item = strndup(start, chptr - start);   element->item = strndup(start, chptr - start);
1089   start = chptr;   start = chptr;
1090    
# Line 1118  static int getNextLine(char **bufPtr, st Line 1150  static int getNextLine(char **bufPtr, st
1150   line->type = LT_WHITESPACE;   line->type = LT_WHITESPACE;
1151   line->numElements = 0;   line->numElements = 0;
1152   }   }
1153   } else {   } else if (line->type == LT_INITRD) {
1154   struct keywordTypes *kw;   struct keywordTypes *kw;
1155    
1156   kw = getKeywordByType(line->type, cfi);   kw = getKeywordByType(line->type, cfi);
# Line 1180  static int getNextLine(char **bufPtr, st Line 1212  static int getNextLine(char **bufPtr, st
1212   }   }
1213   }   }
1214   }   }
1215     } else if (line->type == LT_SET_VARIABLE) {
1216     /* and if it's a "set blah=" we need to split it
1217     * yet a third way to avoid rhbz# XXX FIXME :/
1218     */
1219     char *eq;
1220     int l;
1221     int numElements = line->numElements;
1222     struct lineElement *newElements;
1223     eq = strchr(line->elements[1].item, '=');
1224     if (!eq)
1225     return 0;
1226     l = eq - line->elements[1].item;
1227     if (eq[1] != 0)
1228     numElements++;
1229     newElements = calloc(numElements,sizeof (*newElements));
1230     memcpy(&newElements[0], &line->elements[0],
1231           sizeof (newElements[0]));
1232     newElements[1].item =
1233     strndup(line->elements[1].item, l);
1234     newElements[1].indent = "=";
1235     *(eq++) = '\0';
1236     newElements[2].item = strdup(eq);
1237     free(line->elements[1].item);
1238     if (line->elements[1].indent)
1239     newElements[2].indent = line->elements[1].indent;
1240     for (int i = 2; i < line->numElements; i++) {
1241     newElements[i+1].item = line->elements[i].item;
1242     newElements[i+1].indent =
1243     line->elements[i].indent;
1244     }
1245     free(line->elements);
1246     line->elements = newElements;
1247     line->numElements = numElements;
1248   }   }
1249   }   }
1250    
# Line 1237  static struct grubConfig *readConfig(con Line 1302  static struct grubConfig *readConfig(con
1302   cfg->theLines = NULL;   cfg->theLines = NULL;
1303   cfg->entries = NULL;   cfg->entries = NULL;
1304   cfg->fallbackImage = 0;   cfg->fallbackImage = 0;
1305     cfg->isModified = 0;
1306    
1307   /* copy everything we have */   /* copy everything we have */
1308   while (*head) {   while (*head) {
# Line 1285  static struct grubConfig *readConfig(con Line 1351  static struct grubConfig *readConfig(con
1351      getKeywordByType(LT_DEFAULT, cfi);      getKeywordByType(LT_DEFAULT, cfi);
1352   if (kwType && line->numElements == 3   if (kwType && line->numElements == 3
1353      && !strcmp(line->elements[1].item, kwType->key)      && !strcmp(line->elements[1].item, kwType->key)
1354      && !is_special_grub2_variable(line->elements[2].      && !is_special_grub2_variable(
1355    item)) {   line->elements[2].item)) {
1356   dbgPrintf("Line sets default config\n");   dbgPrintf("Line sets default config\n");
1357   cfg->flags &= ~GRUB_CONFIG_NO_DEFAULT;   cfg->flags &= ~GRUB_CONFIG_NO_DEFAULT;
1358   defaultLine = line;   defaultLine = line;
1359   }   }
   
1360   } else if (iskernel(line->type)) {   } else if (iskernel(line->type)) {
1361   /* if by some freak chance this is multiboot and the   /* if by some freak chance this is multiboot and the
1362   * "module" lines came earlier in the template, make   * "module" lines came earlier in the template, make
# Line 1545  static struct grubConfig *readConfig(con Line 1610  static struct grubConfig *readConfig(con
1610   }   }
1611   }   }
1612   } else if (cfi->defaultIsVariable) {   } else if (cfi->defaultIsVariable) {
1613   char *value = defaultLine->elements[2].item;   if (defaultLine->numElements == 2) {
1614   while (*value && (*value == '"' || *value == '\'' ||   char *value = defaultLine->elements[1].item + 8;
1615    *value == ' ' || *value == '\t'))   while (*value && (*value == '"' ||
1616   value++;    *value == '\'' ||
1617   cfg->defaultImage = strtol(value, &end, 10);    *value == ' ' ||
1618   while (*end && (*end == '"' || *end == '\'' ||    *value == '\t'))
1619   *end == ' ' || *end == '\t'))   value++;
1620   end++;   cfg->defaultImage = strtol(value, &end, 10);
1621   if (*end)   while (*end && (*end == '"' || *end == '\'' ||
1622   cfg->defaultImage = -1;   *end == ' ' || *end == '\t'))
1623     end++;
1624     if (*end)
1625     cfg->defaultImage = NO_DEFAULT_ENTRY;
1626     } else if (defaultLine->numElements == 3) {
1627     char *value = defaultLine->elements[2].item;
1628     while (*value && (*value == '"' ||
1629      *value == '\'' ||
1630      *value == ' ' ||
1631      *value == '\t'))
1632     value++;
1633     cfg->defaultImage = strtol(value, &end, 10);
1634     while (*end && (*end == '"' || *end == '\'' ||
1635     *end == ' ' || *end == '\t'))
1636     end++;
1637     if (*end)
1638     cfg->defaultImage = NO_DEFAULT_ENTRY;
1639     }
1640   } else if (cfi->defaultSupportSaved &&   } else if (cfi->defaultSupportSaved &&
1641     !strncmp(defaultLine->elements[1].item, "saved",     !strncmp(defaultLine->elements[1].item, "saved",
1642      5)) {      5)) {
# Line 1563  static struct grubConfig *readConfig(con Line 1645  static struct grubConfig *readConfig(con
1645   cfg->defaultImage =   cfg->defaultImage =
1646      strtol(defaultLine->elements[1].item, &end, 10);      strtol(defaultLine->elements[1].item, &end, 10);
1647   if (*end)   if (*end)
1648   cfg->defaultImage = -1;   cfg->defaultImage = NO_DEFAULT_ENTRY;
1649   } else if (defaultLine->numElements >= 2) {   } else if (defaultLine->numElements >= 2) {
1650   int i = 0;   int i = 0;
1651   while ((entry = findEntryByIndex(cfg, i))) {   while ((entry = findEntryByIndex(cfg, i))) {
# Line 1591  static struct grubConfig *readConfig(con Line 1673  static struct grubConfig *readConfig(con
1673   if (entry) {   if (entry) {
1674   cfg->defaultImage = i;   cfg->defaultImage = i;
1675   } else {   } else {
1676   cfg->defaultImage = -1;   cfg->defaultImage = NO_DEFAULT_ENTRY;
1677   }   }
1678   }   }
1679   } else if (cfg->cfi->defaultIsSaved && cfg->cfi->getEnv) {   } else if (cfg->cfi->defaultIsSaved && cfg->cfi->getEnv) {
# Line 1608  static struct grubConfig *readConfig(con Line 1690  static struct grubConfig *readConfig(con
1690   cfg->defaultImage = index;   cfg->defaultImage = index;
1691   }   }
1692   } else {   } else {
1693   cfg->defaultImage = 0;   cfg->defaultImage = FIRST_ENTRY_INDEX;
1694   }   }
1695    
1696   return cfg;   return cfg;
# Line 1628  static void writeDefault(FILE * out, cha Line 1710  static void writeDefault(FILE * out, cha
1710   fprintf(out, "%sdefault%ssaved\n", indent, separator);   fprintf(out, "%sdefault%ssaved\n", indent, separator);
1711   else if (cfg->cfi->defaultIsSaved) {   else if (cfg->cfi->defaultIsSaved) {
1712   fprintf(out, "%sset default=\"${saved_entry}\"\n", indent);   fprintf(out, "%sset default=\"${saved_entry}\"\n", indent);
1713   if (cfg->defaultImage >= 0 && cfg->cfi->setEnv) {   if (cfg->defaultImage >= FIRST_ENTRY_INDEX && cfg->cfi->setEnv) {
1714   char *title;   char *title;
1715   entry = findEntryByIndex(cfg, cfg->defaultImage);   int trueIndex, currentIndex;
1716    
1717     trueIndex = 0;
1718     currentIndex = 0;
1719    
1720     while ((entry = findEntryByIndex(cfg, currentIndex))) {
1721     if (!entry->skip) {
1722     if (trueIndex == cfg->defaultImage) {
1723     break;
1724     }
1725     trueIndex++;
1726     }
1727     currentIndex++;
1728     }
1729   line = getLineByType(LT_MENUENTRY, entry->lines);   line = getLineByType(LT_MENUENTRY, entry->lines);
1730   if (!line)   if (!line)
1731   line = getLineByType(LT_TITLE, entry->lines);   line = getLineByType(LT_TITLE, entry->lines);
# Line 1641  static void writeDefault(FILE * out, cha Line 1736  static void writeDefault(FILE * out, cha
1736   "saved_entry", title);   "saved_entry", title);
1737   }   }
1738   }   }
1739   } else if (cfg->defaultImage > -1) {   } else if (cfg->defaultImage >= FIRST_ENTRY_INDEX) {
1740   if (cfg->cfi->defaultIsIndex) {   if (cfg->cfi->defaultIsIndex) {
1741   if (cfg->cfi->defaultIsVariable) {   if (cfg->cfi->defaultIsVariable) {
1742   fprintf(out, "%sset default=\"%d\"\n", indent,   fprintf(out, "%sset default=\"%d\"\n", indent,
# Line 1697  static int writeConfig(struct grubConfig Line 1792  static int writeConfig(struct grubConfig
1792   int needs = MAIN_DEFAULT;   int needs = MAIN_DEFAULT;
1793   struct stat sb;   struct stat sb;
1794   int i;   int i;
1795     int rc = 0;
1796    
1797   if (!strcmp(outName, "-")) {   if (!strcmp(outName, "-")) {
1798   out = stdout;   out = stdout;
# Line 1811  static int writeConfig(struct grubConfig Line 1907  static int writeConfig(struct grubConfig
1907   }   }
1908    
1909   if (tmpOutName) {   if (tmpOutName) {
1910   if (rename(tmpOutName, outName)) {   /* write userspace buffers */
1911   fprintf(stderr,   if (fflush(out))
1912   _("grubby: error moving %s to %s: %s\n"),   rc = 1;
1913   tmpOutName, outName, strerror(errno));  
1914   unlink(outName);   /* purge the write-back cache with fsync() */
1915   return 1;   if (fsync(fileno(out)))
1916     rc = 1;
1917    
1918     if (fclose(out))
1919     rc = 1;
1920    
1921     if (rc == 0 && rename(tmpOutName, outName)) {
1922     unlink(tmpOutName);
1923     rc = 1;
1924   }   }
1925    
1926     /* fsync() the destination directory after rename */
1927     if (rc == 0) {
1928     int dirfd;
1929    
1930     dirfd = open(dirname(strdupa(outName)), O_RDONLY);
1931     if (dirfd < 0)
1932     rc = 1;
1933     else if (fsync(dirfd))
1934     rc = 1;
1935    
1936     if (dirfd >= 0)
1937     close(dirfd);
1938     }
1939    
1940     if (rc == 1)
1941     fprintf(stderr,
1942     _("grubby: error flushing data: %m\n"));
1943   }   }
1944    
1945   return 0;   return rc;
1946  }  }
1947    
1948  static int numEntries(struct grubConfig *cfg)  static int numEntries(struct grubConfig *cfg)
# Line 2345  struct singleEntry *findTemplate(struct Line 2467  struct singleEntry *findTemplate(struct
2467   }   }
2468   }   }
2469   }   }
2470   } else if (cfg->defaultImage > -1) {   } else if (cfg->defaultImage >= FIRST_ENTRY_INDEX) {
2471   entry = findEntryByIndex(cfg, cfg->defaultImage);   entry = findEntryByIndex(cfg, cfg->defaultImage);
2472   if (entry && suitableImage(entry, prefix, skipRemoved, flags)) {   if (entry && suitableImage(entry, prefix, skipRemoved, flags)) {
2473   if (indexPtr)   if (indexPtr)
# Line 2357  struct singleEntry *findTemplate(struct Line 2479  struct singleEntry *findTemplate(struct
2479   index = 0;   index = 0;
2480   while ((entry = findEntryByIndex(cfg, index))) {   while ((entry = findEntryByIndex(cfg, index))) {
2481   if (suitableImage(entry, prefix, skipRemoved, flags)) {   if (suitableImage(entry, prefix, skipRemoved, flags)) {
2482   int j;   int j, unmodifiedIndex;
2483   for (j = 0; j < index; j++) {  
2484     unmodifiedIndex = index;
2485    
2486     for (j = 0; j < unmodifiedIndex; j++) {
2487   entry2 = findEntryByIndex(cfg, j);   entry2 = findEntryByIndex(cfg, j);
2488   if (entry2->skip)   if (entry2->skip)
2489   index--;   index--;
# Line 2419  void markRemovedImage(struct grubConfig Line 2544  void markRemovedImage(struct grubConfig
2544   entry->skip = 1;   entry->skip = 1;
2545  }  }
2546    
2547  void setDefaultImage(struct grubConfig *config, int hasNew,  void setDefaultImage(struct grubConfig *config, int isAddingBootEntry,
2548       const char *defaultKernelPath, int newIsDefault,       const char *defaultKernelPath, int newBootEntryIsDefault,
2549       const char *prefix, int flags, int index)       const char *prefix, int flags,
2550  {       int newDefaultBootEntryIndex, int newBootEntryIndex)
2551   struct singleEntry *entry, *entry2, *newDefault;  {
2552   int i, j;   struct singleEntry *bootEntry, *newDefault;
2553     int indexToVerify, firstKernelEntryIndex, currentLookupIndex;
2554   if (newIsDefault) {  
2555   config->defaultImage = 0;          /* initialize */
2556   return;          currentLookupIndex = FIRST_ENTRY_INDEX;
2557   } else if ((index >= 0) && config->cfi->defaultIsIndex) {  
2558   if (findEntryByIndex(config, index))   /* handle the two cases where the user explictly picks the default
2559   config->defaultImage = index;   * boot entry index as it would exist post-modification */
2560   else  
2561   config->defaultImage = -1;   /* Case 1: user chose to make the latest boot entry the default */
2562     if (newBootEntryIsDefault) {
2563     config->defaultImage = newBootEntryIndex;
2564   return;   return;
2565   } else if (defaultKernelPath) {   }
2566   i = 0;  
2567   if (findEntryByPath(config, defaultKernelPath, prefix, &i)) {   /* Case 2: user picked an arbitrary index as the default boot entry */
2568   config->defaultImage = i;   if (newDefaultBootEntryIndex >= FIRST_ENTRY_INDEX) {
2569   } else {   indexToVerify = newDefaultBootEntryIndex;
2570   config->defaultImage = -1;  
2571     /* user chose to make latest boot entry the default */
2572     if (newDefaultBootEntryIndex == newBootEntryIndex) {
2573     config->defaultImage = newBootEntryIndex;
2574   return;   return;
2575   }   }
  }  
2576    
2577   /* defaultImage now points to what we'd like to use, but before any   /* the user picks the default index based on the
2578   * order changes */   * order of the bootloader configuration after
2579   if ((config->defaultImage == DEFAULT_SAVED) ||   * modification; ensure we are checking for the
2580      (config->defaultImage == DEFAULT_SAVED_GRUB2))   * existence of the correct entry */
2581   /* default is set to saved, we don't want to change it */   if (newBootEntryIndex < newDefaultBootEntryIndex) {
2582     if (!config->isModified)
2583     indexToVerify--;
2584     }
2585    
2586     /* verify the user selected index will exist */
2587     if (findEntryByIndex(config, indexToVerify)) {
2588     config->defaultImage = newDefaultBootEntryIndex;
2589     } else {
2590     config->defaultImage = NO_DEFAULT_ENTRY;
2591     }
2592    
2593   return;   return;
2594     }
2595    
2596   if (config->defaultImage > -1)   /* handle cases where the index value may shift */
  entry = findEntryByIndex(config, config->defaultImage);  
  else  
  entry = NULL;  
2597    
2598   if (entry && !entry->skip) {   /* check validity of existing default or first-entry-found
2599   /* we can preserve the default */     selection */
2600   if (hasNew)   if (defaultKernelPath) {
2601   config->defaultImage++;                  /* we must initialize this */
2602                    firstKernelEntryIndex = 0;
2603     /* user requested first-entry-found */
2604     if (!findEntryByPath(config, defaultKernelPath,
2605         prefix, &firstKernelEntryIndex)) {
2606     /* don't change default if can't find match */
2607     config->defaultImage = NO_DEFAULT_ENTRY;
2608     return;
2609     }
2610    
2611     config->defaultImage = firstKernelEntryIndex;
2612    
2613   /* count the number of entries erased before this one */   /* this is where we start looking for decrement later */
2614   for (j = 0; j < config->defaultImage; j++) {   currentLookupIndex = config->defaultImage;
2615   entry2 = findEntryByIndex(config, j);  
2616   if (entry2->skip)   if (isAddingBootEntry && !config->isModified &&
2617   config->defaultImage--;      (newBootEntryIndex < config->defaultImage)) {
2618     /* increment because new entry added before default */
2619     config->defaultImage++;
2620   }   }
  } else if (hasNew) {  
  config->defaultImage = 0;  
2621   } else {   } else {
2622   /* Either we just erased the default (or the default line was                  /* check to see if the default is stored in the environment */
2623   * bad to begin with) and didn't put a new one in. We'll use                  if (config->defaultImage < FIRST_ENTRY_INDEX) {
2624   * the first valid image. */                      if (config->defaultImage == DEFAULT_SAVED || config->defaultImage == DEFAULT_SAVED_GRUB2)
2625                        {
2626                            if (config->cfi->defaultIsSaved) {
2627                                if (config->cfi->getEnv) {
2628                                    char *defaultTitle = config->cfi->getEnv(config->cfi, "saved_entry");
2629    
2630                                    if (defaultTitle) {
2631                                        if (isnumber(defaultTitle)) {
2632                                            currentLookupIndex = atoi(defaultTitle);
2633                                        } else {
2634                                            findEntryByTitle(config, defaultTitle, &currentLookupIndex);
2635                                        }
2636                                        /* set the default Image to an actual index */
2637                                        config->defaultImage = currentLookupIndex;
2638                                    }
2639                                }
2640                             }
2641                        }
2642                    } else {
2643                            /* use pre-existing default entry from the file*/
2644                            currentLookupIndex = config->defaultImage;
2645                    }
2646    
2647     if (isAddingBootEntry
2648        && (newBootEntryIndex <= config->defaultImage)) {
2649     config->defaultImage++;
2650    
2651     if (config->isModified) {
2652     currentLookupIndex++;
2653     }
2654     }
2655     }
2656    
2657     /* sanity check - is this entry index valid? */
2658     bootEntry = findEntryByIndex(config, currentLookupIndex);
2659    
2660     if ((bootEntry && bootEntry->skip) || !bootEntry) {
2661     /* entry is to be skipped or is invalid */
2662     if (isAddingBootEntry) {
2663     config->defaultImage = newBootEntryIndex;
2664     return;
2665     }
2666   newDefault =   newDefault =
2667      findTemplate(config, prefix, &config->defaultImage, 1,      findTemplate(config, prefix, &config->defaultImage, 1,
2668   flags);   flags);
2669   if (!newDefault)   if (!newDefault) {
2670   config->defaultImage = -1;   config->defaultImage = NO_DEFAULT_ENTRY;
2671     }
2672    
2673     return;
2674     }
2675    
2676     currentLookupIndex--;
2677    
2678     /* decrement index by the total number of entries deleted */
2679    
2680     for (indexToVerify = currentLookupIndex;
2681         indexToVerify >= FIRST_ENTRY_INDEX; indexToVerify--) {
2682    
2683     bootEntry = findEntryByIndex(config, indexToVerify);
2684    
2685     if (bootEntry && bootEntry->skip) {
2686     config->defaultImage--;
2687     }
2688   }   }
2689  }  }
2690    
# Line 2507  void setFallbackImage(struct grubConfig Line 2713  void setFallbackImage(struct grubConfig
2713   }   }
2714  }  }
2715    
2716  void displayEntry(struct singleEntry *entry, const char *prefix, int index)  void displayEntry(struct grubConfig *config, struct singleEntry *entry, const char *prefix, int index)
2717  {  {
2718   struct singleLine *line;   struct singleLine *line;
2719   char *root = NULL;   char *root = NULL;
# Line 2603  void displayEntry(struct singleEntry *en Line 2809  void displayEntry(struct singleEntry *en
2809    
2810   line = getLineByType(LT_TITLE, entry->lines);   line = getLineByType(LT_TITLE, entry->lines);
2811   if (line) {   if (line) {
2812   printf("title=%s\n", line->elements[1].item);                  char *entryTitle;
2813                    /* if we can extractTitle, then it's a zipl config and
2814                     * if not then we go ahead with what's existed prior */
2815                    entryTitle = extractTitle(config, line);
2816                    if (!entryTitle) {
2817                        entryTitle=line->elements[1].item;
2818                    }
2819     printf("title=%s\n", entryTitle);
2820   } else {   } else {
2821   char *title;   char *title;
2822   line = getLineByType(LT_MENUENTRY, entry->lines);   line = getLineByType(LT_MENUENTRY, entry->lines);
# Line 3019  int displayInfo(struct grubConfig *confi Line 3232  int displayInfo(struct grubConfig *confi
3232   printf("lba\n");   printf("lba\n");
3233   }   }
3234    
3235   displayEntry(entry, prefix, i);   displayEntry(config, entry, prefix, i);
3236    
3237   i++;   i++;
3238   while ((entry = findEntryByPath(config, kernel, prefix, &i))) {   while ((entry = findEntryByPath(config, kernel, prefix, &i))) {
3239   displayEntry(entry, prefix, i);   displayEntry(config, entry, prefix, i);
3240   i++;   i++;
3241   }   }
3242    
# Line 3353  static void removeElement(struct singleL Line 3566  static void removeElement(struct singleL
3566   line->numElements--;   line->numElements--;
3567  }  }
3568    
3569  int argMatch(const char *one, const char *two)  static int argNameMatch(const char *one, const char *two)
3570  {  {
3571   char *first, *second;   char *first, *second;
3572   char *chptr;   char *chptra, *chptrb;
3573     int rc;
3574    
3575   first = strcpy(alloca(strlen(one) + 1), one);   first = strcpy(alloca(strlen(one) + 1), one);
3576   second = strcpy(alloca(strlen(two) + 1), two);   second = strcpy(alloca(strlen(two) + 1), two);
3577    
3578   chptr = strchr(first, '=');   chptra = strchr(first, '=');
3579   if (chptr)   if (chptra)
3580   *chptr = '\0';   *chptra = '\0';
3581    
3582     chptrb = strchr(second, '=');
3583     if (chptrb)
3584     *chptrb = '\0';
3585    
3586     rc = strcmp(first, second);
3587    
3588     if (chptra)
3589     *chptra = '=';
3590     if (chptrb)
3591     *chptrb = '=';
3592    
3593     return rc;
3594    }
3595    
3596    static int argHasValue(const char *arg)
3597    {
3598     char *chptr;
3599    
3600   chptr = strchr(second, '=');   chptr = strchr(arg, '=');
3601   if (chptr)   if (chptr)
3602   *chptr = '\0';   return 1;
3603     return 0;
3604    }
3605    
3606    static int argValueMatch(const char *one, const char *two)
3607    {
3608     char *first, *second;
3609     char *chptra, *chptrb;
3610    
3611   return strcmp(first, second);   first = strcpy(alloca(strlen(one) + 1), one);
3612     second = strcpy(alloca(strlen(two) + 1), two);
3613    
3614     chptra = strchr(first, '=');
3615     if (chptra)
3616     chptra += 1;
3617    
3618     chptrb = strchr(second, '=');
3619     if (chptrb)
3620     chptrb += 1;
3621    
3622     if (!chptra && !chptrb)
3623     return 0;
3624     else if (!chptra)
3625     return *chptrb - 0;
3626     else if (!chptrb)
3627     return 0 - *chptra;
3628     else
3629     return strcmp(chptra, chptrb);
3630  }  }
3631    
3632  int updateActualImage(struct grubConfig *cfg, const char *image,  int updateActualImage(struct grubConfig *cfg, const char *image,
# Line 3513  int updateActualImage(struct grubConfig Line 3770  int updateActualImage(struct grubConfig
3770   }   }
3771   if (usedElements[i])   if (usedElements[i])
3772   continue;   continue;
3773   if (!argMatch(line->elements[i].item, *arg)) {   if (!argNameMatch(line->elements[i].item, *arg)) {
3774   usedElements[i] = 1;   usedElements[i] = 1;
3775   break;   break;
3776   }   }
# Line 3572  int updateActualImage(struct grubConfig Line 3829  int updateActualImage(struct grubConfig
3829      !strcmp(line->elements[i].item, "--"))      !strcmp(line->elements[i].item, "--"))
3830   /* reached the end of hyper args, stop here */   /* reached the end of hyper args, stop here */
3831   break;   break;
3832   if (!argMatch(line->elements[i].item, *arg)) {   if (!argNameMatch(line->elements[i].item, *arg)) {
3833   removeElement(line, i);   if (!argHasValue(*arg) ||
3834   break;      !argValueMatch(line->elements[i].item, *arg)) {
3835     removeElement(line, i);
3836     break;
3837     }
3838   }   }
3839   }   }
3840   /* handle removing LT_ROOT line too */   /* handle removing LT_ROOT line too */
# Line 4135  int addNewKernel(struct grubConfig *conf Line 4395  int addNewKernel(struct grubConfig *conf
4395   const char *newKernelArgs, const char *newKernelInitrd,   const char *newKernelArgs, const char *newKernelInitrd,
4396   const char **extraInitrds, int extraInitrdCount,   const char **extraInitrds, int extraInitrdCount,
4397   const char *newMBKernel, const char *newMBKernelArgs,   const char *newMBKernel, const char *newMBKernelArgs,
4398   const char *newDevTreePath)   const char *newDevTreePath, int newIndex)
4399  {  {
4400   struct singleEntry *new;   struct singleEntry *new, *entry, *prev = NULL;
4401   struct singleLine *newLine = NULL, *tmplLine = NULL, *masterLine = NULL;   struct singleLine *newLine = NULL, *tmplLine = NULL, *masterLine = NULL;
4402   int needs;   int needs;
4403     char *indexs;
4404   char *chptr;   char *chptr;
4405     int rc;
4406    
4407   if (!newKernelPath)   if (!newKernelPath)
4408   return 0;   return 0;
4409    
4410     rc = asprintf(&indexs, "%d", newIndex);
4411     if (rc < 0)
4412     return 1;
4413    
4414   /* if the newKernelTitle is too long silently munge it into something   /* if the newKernelTitle is too long silently munge it into something
4415   * we can live with. truncating is first check, then we'll just mess with   * we can live with. truncating is first check, then we'll just mess with
4416   * it until it looks better */   * it until it looks better */
# Line 4167  int addNewKernel(struct grubConfig *conf Line 4433  int addNewKernel(struct grubConfig *conf
4433   new = malloc(sizeof(*new));   new = malloc(sizeof(*new));
4434   new->skip = 0;   new->skip = 0;
4435   new->multiboot = 0;   new->multiboot = 0;
  new->next = config->entries;  
4436   new->lines = NULL;   new->lines = NULL;
4437   config->entries = new;   entry = config->entries;
4438     for (unsigned int i = 0; i < newIndex; i++) {
4439     if (!entry)
4440     break;
4441     prev = entry;
4442     entry = entry->next;
4443     }
4444     new->next = entry;
4445    
4446     if (prev)
4447     prev->next = new;
4448     else
4449     config->entries = new;
4450    
4451   /* copy/update from the template */   /* copy/update from the template */
4452   needs = NEED_KERNEL | NEED_TITLE;   needs = NEED_KERNEL | NEED_TITLE;
# Line 4632  int addNewKernel(struct grubConfig *conf Line 4909  int addNewKernel(struct grubConfig *conf
4909   abort();   abort();
4910   }   }
4911    
4912   if (updateImage(config, "0", prefix, newKernelArgs, NULL,   if (updateImage(config, indexs, prefix, newKernelArgs, NULL,
4913   newMBKernelArgs, NULL))   newMBKernelArgs, NULL)) {
4914     config->isModified = 1;
4915   return 1;   return 1;
4916     }
4917    
4918   return 0;   return 0;
4919  }  }
# Line 4662  int main(int argc, const char **argv) Line 4941  int main(int argc, const char **argv)
4941   char *newDevTreePath = NULL;   char *newDevTreePath = NULL;
4942   char *newMBKernel = NULL;   char *newMBKernel = NULL;
4943   char *newMBKernelArgs = NULL;   char *newMBKernelArgs = NULL;
4944     int newIndex = 0;
4945   char *removeMBKernelArgs = NULL;   char *removeMBKernelArgs = NULL;
4946   char *removeMBKernel = NULL;   char *removeMBKernel = NULL;
4947   char *bootPrefix = NULL;   char *bootPrefix = NULL;
# Line 4696  int main(int argc, const char **argv) Line 4976  int main(int argc, const char **argv)
4976   NULL},   NULL},
4977   {"boot-filesystem", 0, POPT_ARG_STRING, &bootPrefix, 0,   {"boot-filesystem", 0, POPT_ARG_STRING, &bootPrefix, 0,
4978   _   _
4979   ("filestystem which contains /boot directory (for testing only)"),   ("filesystem which contains /boot directory (for testing only)"),
4980   _("bootfs")},   _("bootfs")},
4981  #if defined(__i386__) || defined(__x86_64__) || defined (__powerpc64__) || defined (__ia64__)  #if defined(__i386__) || defined(__x86_64__) || defined (__powerpc64__) || defined (__ia64__)
4982   {"bootloader-probe", 0, POPT_ARG_NONE, &bootloaderProbe, 0,   {"bootloader-probe", 0, POPT_ARG_NONE, &bootloaderProbe, 0,
# Line 4768  int main(int argc, const char **argv) Line 5048  int main(int argc, const char **argv)
5048   {"set-default-index", 0, POPT_ARG_INT, &defaultIndex, 0,   {"set-default-index", 0, POPT_ARG_INT, &defaultIndex, 0,
5049   _("make the given entry index the default entry"),   _("make the given entry index the default entry"),
5050   _("entry-index")},   _("entry-index")},
5051     {"set-index", 0, POPT_ARG_INT, &newIndex, 0,
5052     _("use the given index when creating a new entry"),
5053     _("entry-index")},
5054   {"silo", 0, POPT_ARG_NONE, &configureSilo, 0,   {"silo", 0, POPT_ARG_NONE, &configureSilo, 0,
5055   _("configure silo bootloader")},   _("configure silo bootloader")},
5056   {"title", 0, POPT_ARG_STRING, &newKernelTitle, 0,   {"title", 0, POPT_ARG_STRING, &newKernelTitle, 0,
# Line 5082  int main(int argc, const char **argv) Line 5365  int main(int argc, const char **argv)
5365   struct singleEntry *entry;   struct singleEntry *entry;
5366   char *rootspec;   char *rootspec;
5367    
5368   if (config->defaultImage == -1)   if (config->defaultImage == NO_DEFAULT_ENTRY)
5369   return 0;   return 0;
5370   if (config->defaultImage == DEFAULT_SAVED_GRUB2 &&   if (config->defaultImage == DEFAULT_SAVED_GRUB2 &&
5371      cfi->defaultIsSaved)      cfi->defaultIsSaved)
5372   config->defaultImage = 0;   config->defaultImage = FIRST_ENTRY_INDEX;
5373   entry = findEntryByIndex(config, config->defaultImage);   entry = findEntryByIndex(config, config->defaultImage);
5374   if (!entry)   if (!entry)
5375   return 0;   return 0;
# Line 5109  int main(int argc, const char **argv) Line 5392  int main(int argc, const char **argv)
5392   struct singleLine *line;   struct singleLine *line;
5393   struct singleEntry *entry;   struct singleEntry *entry;
5394    
5395   if (config->defaultImage == -1)   if (config->defaultImage == NO_DEFAULT_ENTRY)
5396   return 0;   return 0;
5397   if (config->defaultImage == DEFAULT_SAVED_GRUB2 &&   if (config->defaultImage == DEFAULT_SAVED_GRUB2 &&
5398      cfi->defaultIsSaved)      cfi->defaultIsSaved)
5399   config->defaultImage = 0;   config->defaultImage = FIRST_ENTRY_INDEX;
5400   entry = findEntryByIndex(config, config->defaultImage);   entry = findEntryByIndex(config, config->defaultImage);
5401   if (!entry)   if (!entry)
5402   return 0;   return 0;
# Line 5143  int main(int argc, const char **argv) Line 5426  int main(int argc, const char **argv)
5426   return 0;   return 0;
5427    
5428   } else if (displayDefaultIndex) {   } else if (displayDefaultIndex) {
5429   if (config->defaultImage == -1)   if (config->defaultImage == NO_DEFAULT_ENTRY)
5430   return 0;   return 0;
5431   if (config->defaultImage == DEFAULT_SAVED_GRUB2 &&   if (config->defaultImage == DEFAULT_SAVED_GRUB2 &&
5432      cfi->defaultIsSaved)      cfi->defaultIsSaved)
5433   config->defaultImage = 0;   config->defaultImage = FIRST_ENTRY_INDEX;
5434   printf("%i\n", config->defaultImage);   printf("%i\n", config->defaultImage);
5435   return 0;   return 0;
5436    
# Line 5163  int main(int argc, const char **argv) Line 5446  int main(int argc, const char **argv)
5446   markRemovedImage(config, removeKernelPath, bootPrefix);   markRemovedImage(config, removeKernelPath, bootPrefix);
5447   markRemovedImage(config, removeMBKernel, bootPrefix);   markRemovedImage(config, removeMBKernel, bootPrefix);
5448   setDefaultImage(config, newKernelPath != NULL, defaultKernel,   setDefaultImage(config, newKernelPath != NULL, defaultKernel,
5449   makeDefault, bootPrefix, flags, defaultIndex);   makeDefault, bootPrefix, flags, defaultIndex,
5450     newIndex);
5451   setFallbackImage(config, newKernelPath != NULL);   setFallbackImage(config, newKernelPath != NULL);
5452   if (updateImage(config, updateKernelPath, bootPrefix, newKernelArgs,   if (updateImage(config, updateKernelPath, bootPrefix, newKernelArgs,
5453   removeArgs, newMBKernelArgs, removeMBKernelArgs))   removeArgs, newMBKernelArgs, removeMBKernelArgs))
# Line 5183  int main(int argc, const char **argv) Line 5467  int main(int argc, const char **argv)
5467   if (addNewKernel(config, template, bootPrefix, newKernelPath,   if (addNewKernel(config, template, bootPrefix, newKernelPath,
5468   newKernelTitle, newKernelArgs, newKernelInitrd,   newKernelTitle, newKernelArgs, newKernelInitrd,
5469   (const char **)extraInitrds, extraInitrdCount,   (const char **)extraInitrds, extraInitrdCount,
5470   newMBKernel, newMBKernelArgs, newDevTreePath))   newMBKernel, newMBKernelArgs, newDevTreePath,
5471     newIndex))
5472   return 1;   return 1;
5473    
5474   if (numEntries(config) == 0) {   if (numEntries(config) == 0) {

Legend:
Removed from v.3002  
changed lines
  Added in v.3136