Magellan Linux

Diff of /trunk/grubby/grubby.c

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

revision 3014 by niro, Tue Jun 27 14:34:11 2017 UTC revision 3139 by niro, Tue Jul 7 11:12:00 2020 UTC
# Line 68  int isEfi = 0; Line 68  int isEfi = 0;
68    
69  char *saved_command_line = NULL;  char *saved_command_line = NULL;
70    
71    const char *mounts = "/proc/mounts";
72    
73  /* comments get lumped in with indention */  /* comments get lumped in with indention */
74  struct lineElement {  struct lineElement {
75   char *item;   char *item;
# Line 132  struct singleEntry { Line 134  struct singleEntry {
134  #define NEED_DEVTREE (1 << 6)  #define NEED_DEVTREE (1 << 6)
135    
136  #define MAIN_DEFAULT    (1 << 0)  #define MAIN_DEFAULT    (1 << 0)
137    #define FIRST_ENTRY_INDEX    0 /* boot entry index value begin and increment
138       from this initial value */
139    #define NO_DEFAULT_ENTRY    -1 /* indicates that no specific default boot
140       entry was set or currently exists */
141  #define DEFAULT_SAVED       -2  #define DEFAULT_SAVED       -2
142  #define DEFAULT_SAVED_GRUB2 -3  #define DEFAULT_SAVED_GRUB2 -3
143    
# Line 677  struct grubConfig { Line 683  struct grubConfig {
683   int fallbackImage; /* just like defaultImage */   int fallbackImage; /* just like defaultImage */
684   int flags;   int flags;
685   struct configFileInfo *cfi;   struct configFileInfo *cfi;
686     int isModified; /* assumes only one entry added
687       per invocation of grubby */
688  };  };
689    
690  blkid_cache blkid;  blkid_cache blkid;
# Line 695  static int lineWrite(FILE * out, struct Line 703  static int lineWrite(FILE * out, struct
703       struct configFileInfo *cfi);       struct configFileInfo *cfi);
704  static int getNextLine(char **bufPtr, struct singleLine *line,  static int getNextLine(char **bufPtr, struct singleLine *line,
705         struct configFileInfo *cfi);         struct configFileInfo *cfi);
706  static char *getRootSpecifier(char *str);  static size_t getRootSpecifier(const char *str);
707  static void requote(struct singleLine *line, struct configFileInfo *cfi);  static void requote(struct singleLine *line, struct configFileInfo *cfi);
708  static void insertElement(struct singleLine *line,  static void insertElement(struct singleLine *line,
709    const char *item, int insertHere,    const char *item, int insertHere,
# Line 1296  static struct grubConfig *readConfig(con Line 1304  static struct grubConfig *readConfig(con
1304   cfg->theLines = NULL;   cfg->theLines = NULL;
1305   cfg->entries = NULL;   cfg->entries = NULL;
1306   cfg->fallbackImage = 0;   cfg->fallbackImage = 0;
1307     cfg->isModified = 0;
1308    
1309   /* copy everything we have */   /* copy everything we have */
1310   while (*head) {   while (*head) {
# Line 1615  static struct grubConfig *readConfig(con Line 1624  static struct grubConfig *readConfig(con
1624   *end == ' ' || *end == '\t'))   *end == ' ' || *end == '\t'))
1625   end++;   end++;
1626   if (*end)   if (*end)
1627   cfg->defaultImage = -1;   cfg->defaultImage = NO_DEFAULT_ENTRY;
1628   } else if (defaultLine->numElements == 3) {   } else if (defaultLine->numElements == 3) {
1629   char *value = defaultLine->elements[2].item;   char *value = defaultLine->elements[2].item;
1630   while (*value && (*value == '"' ||   while (*value && (*value == '"' ||
# Line 1628  static struct grubConfig *readConfig(con Line 1637  static struct grubConfig *readConfig(con
1637   *end == ' ' || *end == '\t'))   *end == ' ' || *end == '\t'))
1638   end++;   end++;
1639   if (*end)   if (*end)
1640   cfg->defaultImage = -1;   cfg->defaultImage = NO_DEFAULT_ENTRY;
1641   }   }
1642   } else if (cfi->defaultSupportSaved &&   } else if (cfi->defaultSupportSaved &&
1643     !strncmp(defaultLine->elements[1].item, "saved",     !strncmp(defaultLine->elements[1].item, "saved",
# Line 1638  static struct grubConfig *readConfig(con Line 1647  static struct grubConfig *readConfig(con
1647   cfg->defaultImage =   cfg->defaultImage =
1648      strtol(defaultLine->elements[1].item, &end, 10);      strtol(defaultLine->elements[1].item, &end, 10);
1649   if (*end)   if (*end)
1650   cfg->defaultImage = -1;   cfg->defaultImage = NO_DEFAULT_ENTRY;
1651   } else if (defaultLine->numElements >= 2) {   } else if (defaultLine->numElements >= 2) {
1652   int i = 0;   int i = 0;
1653   while ((entry = findEntryByIndex(cfg, i))) {   while ((entry = findEntryByIndex(cfg, i))) {
# Line 1666  static struct grubConfig *readConfig(con Line 1675  static struct grubConfig *readConfig(con
1675   if (entry) {   if (entry) {
1676   cfg->defaultImage = i;   cfg->defaultImage = i;
1677   } else {   } else {
1678   cfg->defaultImage = -1;   cfg->defaultImage = NO_DEFAULT_ENTRY;
1679   }   }
1680   }   }
1681   } else if (cfg->cfi->defaultIsSaved && cfg->cfi->getEnv) {   } else if (cfg->cfi->defaultIsSaved && cfg->cfi->getEnv) {
# Line 1683  static struct grubConfig *readConfig(con Line 1692  static struct grubConfig *readConfig(con
1692   cfg->defaultImage = index;   cfg->defaultImage = index;
1693   }   }
1694   } else {   } else {
1695   cfg->defaultImage = 0;   cfg->defaultImage = FIRST_ENTRY_INDEX;
1696   }   }
1697    
1698   return cfg;   return cfg;
# Line 1703  static void writeDefault(FILE * out, cha Line 1712  static void writeDefault(FILE * out, cha
1712   fprintf(out, "%sdefault%ssaved\n", indent, separator);   fprintf(out, "%sdefault%ssaved\n", indent, separator);
1713   else if (cfg->cfi->defaultIsSaved) {   else if (cfg->cfi->defaultIsSaved) {
1714   fprintf(out, "%sset default=\"${saved_entry}\"\n", indent);   fprintf(out, "%sset default=\"${saved_entry}\"\n", indent);
1715   if (cfg->defaultImage >= 0 && cfg->cfi->setEnv) {   if (cfg->defaultImage >= FIRST_ENTRY_INDEX && cfg->cfi->setEnv) {
1716   char *title;   char *title;
1717   entry = findEntryByIndex(cfg, cfg->defaultImage);   int trueIndex, currentIndex;
1718    
1719     trueIndex = 0;
1720     currentIndex = 0;
1721    
1722     while ((entry = findEntryByIndex(cfg, currentIndex))) {
1723     if (!entry->skip) {
1724     if (trueIndex == cfg->defaultImage) {
1725     break;
1726     }
1727     trueIndex++;
1728     }
1729     currentIndex++;
1730     }
1731   line = getLineByType(LT_MENUENTRY, entry->lines);   line = getLineByType(LT_MENUENTRY, entry->lines);
1732   if (!line)   if (!line)
1733   line = getLineByType(LT_TITLE, entry->lines);   line = getLineByType(LT_TITLE, entry->lines);
# Line 1716  static void writeDefault(FILE * out, cha Line 1738  static void writeDefault(FILE * out, cha
1738   "saved_entry", title);   "saved_entry", title);
1739   }   }
1740   }   }
1741   } else if (cfg->defaultImage > -1) {   } else if (cfg->defaultImage >= FIRST_ENTRY_INDEX) {
1742   if (cfg->cfi->defaultIsIndex) {   if (cfg->cfi->defaultIsIndex) {
1743   if (cfg->cfi->defaultIsVariable) {   if (cfg->cfi->defaultIsVariable) {
1744   fprintf(out, "%sset default=\"%d\"\n", indent,   fprintf(out, "%sset default=\"%d\"\n", indent,
# Line 1772  static int writeConfig(struct grubConfig Line 1794  static int writeConfig(struct grubConfig
1794   int needs = MAIN_DEFAULT;   int needs = MAIN_DEFAULT;
1795   struct stat sb;   struct stat sb;
1796   int i;   int i;
1797     int rc = 0;
1798    
1799   if (!strcmp(outName, "-")) {   if (!strcmp(outName, "-")) {
1800   out = stdout;   out = stdout;
# Line 1886  static int writeConfig(struct grubConfig Line 1909  static int writeConfig(struct grubConfig
1909   }   }
1910    
1911   if (tmpOutName) {   if (tmpOutName) {
1912   if (rename(tmpOutName, outName)) {   /* write userspace buffers */
1913   fprintf(stderr,   if (fflush(out))
1914   _("grubby: error moving %s to %s: %s\n"),   rc = 1;
1915   tmpOutName, outName, strerror(errno));  
1916   unlink(outName);   /* purge the write-back cache with fsync() */
1917   return 1;   if (fsync(fileno(out)))
1918     rc = 1;
1919    
1920     if (fclose(out))
1921     rc = 1;
1922    
1923     if (rc == 0 && rename(tmpOutName, outName)) {
1924     unlink(tmpOutName);
1925     rc = 1;
1926     }
1927    
1928     /* fsync() the destination directory after rename */
1929     if (rc == 0) {
1930     int dirfd;
1931    
1932     dirfd = open(dirname(strdupa(outName)), O_RDONLY);
1933     if (dirfd < 0)
1934     rc = 1;
1935     else if (fsync(dirfd))
1936     rc = 1;
1937    
1938     if (dirfd >= 0)
1939     close(dirfd);
1940   }   }
1941    
1942     if (rc == 1)
1943     fprintf(stderr,
1944     _("grubby: error flushing data: %m\n"));
1945   }   }
1946    
1947   return 0;   return rc;
1948  }  }
1949    
1950  static int numEntries(struct grubConfig *cfg)  static int numEntries(struct grubConfig *cfg)
# Line 2071  static int endswith(const char *s, char Line 2120  static int endswith(const char *s, char
2120   return s[slen] == c;   return s[slen] == c;
2121  }  }
2122    
2123    typedef struct {
2124     const char *start;
2125     size_t      chars;
2126    } field;
2127    
2128    static int iscomma(int c)
2129    {
2130     return c == ',';
2131    }
2132    
2133    static int isequal(int c)
2134    {
2135     return c == '=';
2136    }
2137    
2138    static field findField(const field *in, typeof(isspace) *isdelim, field *out)
2139    {
2140     field nxt = {};
2141     size_t off = 0;
2142    
2143     while (off < in->chars && isdelim(in->start[off]))
2144     off++;
2145    
2146     if (off == in->chars)
2147     return nxt;
2148    
2149     out->start = &in->start[off];
2150     out->chars = 0;
2151    
2152     while (off + out->chars < in->chars && !isdelim(out->start[out->chars]))
2153     out->chars++;
2154    
2155     nxt.start = out->start + out->chars;
2156     nxt.chars = in->chars - off - out->chars;
2157     return nxt;
2158    }
2159    
2160    static int fieldEquals(const field *in, const char *str)
2161    {
2162     return in->chars == strlen(str) &&
2163     strncmp(in->start, str, in->chars) == 0;
2164    }
2165    
2166    /* Parse /proc/mounts to determine the subvolume prefix. */
2167    static size_t subvolPrefix(const char *str)
2168    {
2169     FILE *file = NULL;
2170     char *line = NULL;
2171     size_t prfx = 0;
2172     size_t size = 0;
2173    
2174     file = fopen(mounts, "r");
2175     if (!file)
2176     return 0;
2177    
2178     for (ssize_t s; (s = getline(&line, &size, file)) >= 0; ) {
2179     field nxt = { line, s };
2180     field dev = {};
2181     field path = {};
2182     field type = {};
2183     field opts = {};
2184     field opt = {};
2185    
2186     nxt = findField(&nxt, isspace, &dev);
2187     if (!nxt.start)
2188     continue;
2189    
2190     nxt = findField(&nxt, isspace, &path);
2191     if (!nxt.start)
2192     continue;
2193    
2194     nxt = findField(&nxt, isspace, &type);
2195     if (!nxt.start)
2196     continue;
2197    
2198     nxt = findField(&nxt, isspace, &opts);
2199     if (!nxt.start)
2200     continue;
2201    
2202     if (!fieldEquals(&type, "btrfs"))
2203     continue;
2204    
2205     /* We have found a btrfs mount point. */
2206    
2207     nxt = opts;
2208     while ((nxt = findField(&nxt, iscomma, &opt)).start) {
2209     field key = {};
2210     field val = {};
2211    
2212     opt = findField(&opt, isequal, &key);
2213     if (!opt.start)
2214     continue;
2215    
2216     opt = findField(&opt, isequal, &val);
2217     if (!opt.start)
2218     continue;
2219    
2220     if (!fieldEquals(&key, "subvol"))
2221     continue;
2222    
2223     /* We have found a btrfs subvolume mount point. */
2224    
2225     if (strncmp(val.start, str, val.chars))
2226     continue;
2227    
2228     if (val.start[val.chars - 1] != '/' &&
2229     str[val.chars] != '/')
2230     continue;
2231    
2232     /* The subvolume mount point matches our input. */
2233    
2234     if (prfx < val.chars)
2235     prfx = val.chars;
2236     }
2237     }
2238    
2239     dbgPrintf("%s(): str: '%s', prfx: '%s'\n", __FUNCTION__, str, prfx);
2240    
2241     fclose(file);
2242     free(line);
2243     return prfx;
2244    }
2245    
2246  int suitableImage(struct singleEntry *entry, const char *bootPrefix,  int suitableImage(struct singleEntry *entry, const char *bootPrefix,
2247    int skipRemoved, int flags)    int skipRemoved, int flags)
2248  {  {
# Line 2078  int suitableImage(struct singleEntry *en Line 2250  int suitableImage(struct singleEntry *en
2250   char *fullName;   char *fullName;
2251   int i;   int i;
2252   char *dev;   char *dev;
2253   char *rootspec;   size_t rs;
2254   char *rootdev;   char *rootdev;
2255    
2256   if (skipRemoved && entry->skip) {   if (skipRemoved && entry->skip) {
# Line 2106  int suitableImage(struct singleEntry *en Line 2278  int suitableImage(struct singleEntry *en
2278    
2279   fullName = alloca(strlen(bootPrefix) +   fullName = alloca(strlen(bootPrefix) +
2280    strlen(line->elements[1].item) + 1);    strlen(line->elements[1].item) + 1);
2281   rootspec = getRootSpecifier(line->elements[1].item);   rs = getRootSpecifier(line->elements[1].item);
  int rootspec_offset = rootspec ? strlen(rootspec) : 0;  
2282   int hasslash = endswith(bootPrefix, '/') ||   int hasslash = endswith(bootPrefix, '/') ||
2283      beginswith(line->elements[1].item + rootspec_offset, '/');      beginswith(line->elements[1].item + rs, '/');
2284   sprintf(fullName, "%s%s%s", bootPrefix, hasslash ? "" : "/",   sprintf(fullName, "%s%s%s", bootPrefix, hasslash ? "" : "/",
2285   line->elements[1].item + rootspec_offset);   line->elements[1].item + rs);
2286   if (access(fullName, R_OK)) {   if (access(fullName, R_OK)) {
2287   notSuitablePrintf(entry, 0, "access to %s failed\n", fullName);   notSuitablePrintf(entry, 0, "access to %s failed\n", fullName);
2288   return 0;   return 0;
# Line 2203  struct singleEntry *findEntryByPath(stru Line 2374  struct singleEntry *findEntryByPath(stru
2374   struct singleLine *line;   struct singleLine *line;
2375   int i;   int i;
2376   char *chptr;   char *chptr;
  char *rootspec = NULL;  
2377   enum lineType_e checkType = LT_KERNEL;   enum lineType_e checkType = LT_KERNEL;
2378    
2379   if (isdigit(*kernel)) {   if (isdigit(*kernel)) {
# Line 2308  struct singleEntry *findEntryByPath(stru Line 2478  struct singleEntry *findEntryByPath(stru
2478    
2479   if (line && line->type != LT_MENUENTRY &&   if (line && line->type != LT_MENUENTRY &&
2480      line->numElements >= 2) {      line->numElements >= 2) {
2481   rootspec =   if (!strcmp(line->elements[1].item +
2482      getRootSpecifier(line->elements[1].   getRootSpecifier(
2483       item);   line->elements[1].item),
2484   if (!strcmp   kernel + strlen(prefix)))
     (line->elements[1].item +  
      ((rootspec !=  
        NULL) ? strlen(rootspec) : 0),  
      kernel + strlen(prefix)))  
2485   break;   break;
2486   }   }
2487   if (line->type == LT_MENUENTRY &&   if (line->type == LT_MENUENTRY &&
# Line 2420  struct singleEntry *findTemplate(struct Line 2586  struct singleEntry *findTemplate(struct
2586   }   }
2587   }   }
2588   }   }
2589   } else if (cfg->defaultImage > -1) {   } else if (cfg->defaultImage >= FIRST_ENTRY_INDEX) {
2590   entry = findEntryByIndex(cfg, cfg->defaultImage);   entry = findEntryByIndex(cfg, cfg->defaultImage);
2591   if (entry && suitableImage(entry, prefix, skipRemoved, flags)) {   if (entry && suitableImage(entry, prefix, skipRemoved, flags)) {
2592   if (indexPtr)   if (indexPtr)
# Line 2432  struct singleEntry *findTemplate(struct Line 2598  struct singleEntry *findTemplate(struct
2598   index = 0;   index = 0;
2599   while ((entry = findEntryByIndex(cfg, index))) {   while ((entry = findEntryByIndex(cfg, index))) {
2600   if (suitableImage(entry, prefix, skipRemoved, flags)) {   if (suitableImage(entry, prefix, skipRemoved, flags)) {
2601   int j;   int j, unmodifiedIndex;
2602   for (j = 0; j < index; j++) {  
2603     unmodifiedIndex = index;
2604    
2605     for (j = 0; j < unmodifiedIndex; j++) {
2606   entry2 = findEntryByIndex(cfg, j);   entry2 = findEntryByIndex(cfg, j);
2607   if (entry2->skip)   if (entry2->skip)
2608   index--;   index--;
# Line 2494  void markRemovedImage(struct grubConfig Line 2663  void markRemovedImage(struct grubConfig
2663   entry->skip = 1;   entry->skip = 1;
2664  }  }
2665    
2666  void setDefaultImage(struct grubConfig *config, int hasNew,  void setDefaultImage(struct grubConfig *config, int isAddingBootEntry,
2667       const char *defaultKernelPath, int newIsDefault,       const char *defaultKernelPath, int newBootEntryIsDefault,
2668       const char *prefix, int flags, int index)       const char *prefix, int flags,
2669  {       int newDefaultBootEntryIndex, int newBootEntryIndex)
2670   struct singleEntry *entry, *entry2, *newDefault;  {
2671   int i, j;   struct singleEntry *bootEntry, *newDefault;
2672     int indexToVerify, firstKernelEntryIndex, currentLookupIndex;
2673   if (newIsDefault) {  
2674   config->defaultImage = 0;          /* initialize */
2675   return;          currentLookupIndex = FIRST_ENTRY_INDEX;
2676   } else if ((index >= 0) && config->cfi->defaultIsIndex) {  
2677   if (findEntryByIndex(config, index))   /* handle the two cases where the user explictly picks the default
2678   config->defaultImage = index;   * boot entry index as it would exist post-modification */
2679   else  
2680   config->defaultImage = -1;   /* Case 1: user chose to make the latest boot entry the default */
2681     if (newBootEntryIsDefault) {
2682     config->defaultImage = newBootEntryIndex;
2683   return;   return;
2684   } else if (defaultKernelPath) {   }
2685   i = 0;  
2686   if (findEntryByPath(config, defaultKernelPath, prefix, &i)) {   /* Case 2: user picked an arbitrary index as the default boot entry */
2687   config->defaultImage = i;   if (newDefaultBootEntryIndex >= FIRST_ENTRY_INDEX) {
2688   } else {   indexToVerify = newDefaultBootEntryIndex;
2689   config->defaultImage = -1;  
2690     /* user chose to make latest boot entry the default */
2691     if (newDefaultBootEntryIndex == newBootEntryIndex) {
2692     config->defaultImage = newBootEntryIndex;
2693   return;   return;
2694   }   }
  }  
2695    
2696   /* defaultImage now points to what we'd like to use, but before any   /* the user picks the default index based on the
2697   * order changes */   * order of the bootloader configuration after
2698   if ((config->defaultImage == DEFAULT_SAVED) ||   * modification; ensure we are checking for the
2699      (config->defaultImage == DEFAULT_SAVED_GRUB2))   * existence of the correct entry */
2700   /* default is set to saved, we don't want to change it */   if (newBootEntryIndex < newDefaultBootEntryIndex) {
2701     if (!config->isModified)
2702     indexToVerify--;
2703     }
2704    
2705     /* verify the user selected index will exist */
2706     if (findEntryByIndex(config, indexToVerify)) {
2707     config->defaultImage = newDefaultBootEntryIndex;
2708     } else {
2709     config->defaultImage = NO_DEFAULT_ENTRY;
2710     }
2711    
2712   return;   return;
2713     }
2714    
2715   if (config->defaultImage > -1)   /* handle cases where the index value may shift */
  entry = findEntryByIndex(config, config->defaultImage);  
  else  
  entry = NULL;  
2716    
2717   if (entry && !entry->skip) {   /* check validity of existing default or first-entry-found
2718   /* we can preserve the default */     selection */
2719   if (hasNew)   if (defaultKernelPath) {
2720   config->defaultImage++;                  /* we must initialize this */
2721                    firstKernelEntryIndex = 0;
2722     /* user requested first-entry-found */
2723     if (!findEntryByPath(config, defaultKernelPath,
2724         prefix, &firstKernelEntryIndex)) {
2725     /* don't change default if can't find match */
2726     config->defaultImage = NO_DEFAULT_ENTRY;
2727     return;
2728     }
2729    
2730     config->defaultImage = firstKernelEntryIndex;
2731    
2732     /* this is where we start looking for decrement later */
2733     currentLookupIndex = config->defaultImage;
2734    
2735   /* count the number of entries erased before this one */   if (isAddingBootEntry && !config->isModified &&
2736   for (j = 0; j < config->defaultImage; j++) {      (newBootEntryIndex < config->defaultImage)) {
2737   entry2 = findEntryByIndex(config, j);   /* increment because new entry added before default */
2738   if (entry2->skip)   config->defaultImage++;
  config->defaultImage--;  
2739   }   }
  } else if (hasNew) {  
  config->defaultImage = 0;  
2740   } else {   } else {
2741   /* Either we just erased the default (or the default line was                  /* check to see if the default is stored in the environment */
2742   * bad to begin with) and didn't put a new one in. We'll use                  if (config->defaultImage < FIRST_ENTRY_INDEX) {
2743   * the first valid image. */                      if (config->defaultImage == DEFAULT_SAVED || config->defaultImage == DEFAULT_SAVED_GRUB2)
2744                        {
2745                            if (config->cfi->defaultIsSaved) {
2746                                if (config->cfi->getEnv) {
2747                                    char *defaultTitle = config->cfi->getEnv(config->cfi, "saved_entry");
2748    
2749                                    if (defaultTitle) {
2750                                        if (isnumber(defaultTitle)) {
2751                                            currentLookupIndex = atoi(defaultTitle);
2752                                        } else {
2753                                            findEntryByTitle(config, defaultTitle, &currentLookupIndex);
2754                                        }
2755                                        /* set the default Image to an actual index */
2756                                        config->defaultImage = currentLookupIndex;
2757                                    }
2758                                }
2759                             }
2760                        }
2761                    } else {
2762                            /* use pre-existing default entry from the file*/
2763                            currentLookupIndex = config->defaultImage;
2764                    }
2765    
2766     if (isAddingBootEntry
2767        && (newBootEntryIndex <= config->defaultImage)) {
2768     config->defaultImage++;
2769    
2770     if (config->isModified) {
2771     currentLookupIndex++;
2772     }
2773     }
2774     }
2775    
2776     /* sanity check - is this entry index valid? */
2777     bootEntry = findEntryByIndex(config, currentLookupIndex);
2778    
2779     if ((bootEntry && bootEntry->skip) || !bootEntry) {
2780     /* entry is to be skipped or is invalid */
2781     if (isAddingBootEntry) {
2782     config->defaultImage = newBootEntryIndex;
2783     return;
2784     }
2785   newDefault =   newDefault =
2786      findTemplate(config, prefix, &config->defaultImage, 1,      findTemplate(config, prefix, &config->defaultImage, 1,
2787   flags);   flags);
2788   if (!newDefault)   if (!newDefault) {
2789   config->defaultImage = -1;   config->defaultImage = NO_DEFAULT_ENTRY;
2790     }
2791    
2792     return;
2793     }
2794    
2795     currentLookupIndex--;
2796    
2797     /* decrement index by the total number of entries deleted */
2798    
2799     for (indexToVerify = currentLookupIndex;
2800         indexToVerify >= FIRST_ENTRY_INDEX; indexToVerify--) {
2801    
2802     bootEntry = findEntryByIndex(config, indexToVerify);
2803    
2804     if (bootEntry && bootEntry->skip) {
2805     config->defaultImage--;
2806     }
2807   }   }
2808  }  }
2809    
# Line 2582  void setFallbackImage(struct grubConfig Line 2832  void setFallbackImage(struct grubConfig
2832   }   }
2833  }  }
2834    
2835  void displayEntry(struct singleEntry *entry, const char *prefix, int index)  void displayEntry(struct grubConfig *config, struct singleEntry *entry, const char *prefix, int index)
2836  {  {
2837   struct singleLine *line;   struct singleLine *line;
2838   char *root = NULL;   char *root = NULL;
# Line 2678  void displayEntry(struct singleEntry *en Line 2928  void displayEntry(struct singleEntry *en
2928    
2929   line = getLineByType(LT_TITLE, entry->lines);   line = getLineByType(LT_TITLE, entry->lines);
2930   if (line) {   if (line) {
2931   printf("title=%s\n", line->elements[1].item);                  char *entryTitle;
2932                    /* if we can extractTitle, then it's a zipl config and
2933                     * if not then we go ahead with what's existed prior */
2934                    entryTitle = extractTitle(config, line);
2935                    if (!entryTitle) {
2936                        entryTitle=line->elements[1].item;
2937                    }
2938     printf("title=%s\n", entryTitle);
2939   } else {   } else {
2940   char *title;   char *title;
2941   line = getLineByType(LT_MENUENTRY, entry->lines);   line = getLineByType(LT_MENUENTRY, entry->lines);
# Line 3094  int displayInfo(struct grubConfig *confi Line 3351  int displayInfo(struct grubConfig *confi
3351   printf("lba\n");   printf("lba\n");
3352   }   }
3353    
3354   displayEntry(entry, prefix, i);   displayEntry(config, entry, prefix, i);
3355    
3356   i++;   i++;
3357   while ((entry = findEntryByPath(config, kernel, prefix, &i))) {   while ((entry = findEntryByPath(config, kernel, prefix, &i))) {
3358   displayEntry(entry, prefix, i);   displayEntry(config, entry, prefix, i);
3359   i++;   i++;
3360   }   }
3361    
# Line 3133  struct singleLine *addLineTmpl(struct si Line 3390  struct singleLine *addLineTmpl(struct si
3390      type & (LT_HYPER | LT_KERNEL | LT_MBMODULE | LT_INITRD |      type & (LT_HYPER | LT_KERNEL | LT_MBMODULE | LT_INITRD |
3391      LT_KERNEL_EFI | LT_INITRD_EFI | LT_KERNEL_16 |      LT_KERNEL_EFI | LT_INITRD_EFI | LT_KERNEL_16 |
3392      LT_INITRD_16)) {      LT_INITRD_16)) {
3393   char *rootspec =   const char *prfx = tmplLine->elements[1].item;
3394      getRootSpecifier(tmplLine->elements[1].item);   size_t rs = getRootSpecifier(prfx);
3395   if (rootspec != NULL) {   if (isinitrd(tmplLine->type)) {
3396     for (struct singleLine *l = entry->lines;
3397         rs == 0 && l; l = l->next) {
3398     if (iskernel(l->type)) {
3399     prfx = l->elements[1].item;
3400     rs = getRootSpecifier(prfx);
3401     break;
3402     }
3403     }
3404     }
3405     if (rs > 0) {
3406   free(newLine->elements[1].item);   free(newLine->elements[1].item);
3407   newLine->elements[1].item =   newLine->elements[1].item = sdupprintf(
3408      sdupprintf("%s%s", rootspec, val);   "%.*s%s", (int) rs, prfx, val);
3409   }   }
3410   }   }
3411   }   }
# Line 3428  static void removeElement(struct singleL Line 3695  static void removeElement(struct singleL
3695   line->numElements--;   line->numElements--;
3696  }  }
3697    
3698  int argMatch(const char *one, const char *two)  static int argNameMatch(const char *one, const char *two)
3699  {  {
3700   char *first, *second;   char *first, *second;
3701   char *chptr;   char *chptra, *chptrb;
3702     int rc;
3703    
3704   first = strcpy(alloca(strlen(one) + 1), one);   first = strcpy(alloca(strlen(one) + 1), one);
3705   second = strcpy(alloca(strlen(two) + 1), two);   second = strcpy(alloca(strlen(two) + 1), two);
3706    
3707   chptr = strchr(first, '=');   chptra = strchr(first, '=');
3708   if (chptr)   if (chptra)
3709   *chptr = '\0';   *chptra = '\0';
3710    
3711     chptrb = strchr(second, '=');
3712     if (chptrb)
3713     *chptrb = '\0';
3714    
3715     rc = strcmp(first, second);
3716    
3717     if (chptra)
3718     *chptra = '=';
3719     if (chptrb)
3720     *chptrb = '=';
3721    
3722     return rc;
3723    }
3724    
3725   chptr = strchr(second, '=');  static int argHasValue(const char *arg)
3726    {
3727     char *chptr;
3728    
3729     chptr = strchr(arg, '=');
3730   if (chptr)   if (chptr)
3731   *chptr = '\0';   return 1;
3732     return 0;
3733    }
3734    
3735    static int argValueMatch(const char *one, const char *two)
3736    {
3737     char *first, *second;
3738     char *chptra, *chptrb;
3739    
3740   return strcmp(first, second);   first = strcpy(alloca(strlen(one) + 1), one);
3741     second = strcpy(alloca(strlen(two) + 1), two);
3742    
3743     chptra = strchr(first, '=');
3744     if (chptra)
3745     chptra += 1;
3746    
3747     chptrb = strchr(second, '=');
3748     if (chptrb)
3749     chptrb += 1;
3750    
3751     if (!chptra && !chptrb)
3752     return 0;
3753     else if (!chptra)
3754     return *chptrb - 0;
3755     else if (!chptrb)
3756     return 0 - *chptra;
3757     else
3758     return strcmp(chptra, chptrb);
3759  }  }
3760    
3761  int updateActualImage(struct grubConfig *cfg, const char *image,  int updateActualImage(struct grubConfig *cfg, const char *image,
# Line 3588  int updateActualImage(struct grubConfig Line 3899  int updateActualImage(struct grubConfig
3899   }   }
3900   if (usedElements[i])   if (usedElements[i])
3901   continue;   continue;
3902   if (!argMatch(line->elements[i].item, *arg)) {   if (!argNameMatch(line->elements[i].item, *arg)) {
3903   usedElements[i] = 1;   usedElements[i] = 1;
3904   break;   break;
3905   }   }
# Line 3647  int updateActualImage(struct grubConfig Line 3958  int updateActualImage(struct grubConfig
3958      !strcmp(line->elements[i].item, "--"))      !strcmp(line->elements[i].item, "--"))
3959   /* reached the end of hyper args, stop here */   /* reached the end of hyper args, stop here */
3960   break;   break;
3961   if (!argMatch(line->elements[i].item, *arg)) {   if (!argNameMatch(line->elements[i].item, *arg)) {
3962   removeElement(line, i);   if (!argHasValue(*arg) ||
3963   break;      !argValueMatch(line->elements[i].item, *arg)) {
3964     removeElement(line, i);
3965     break;
3966     }
3967   }   }
3968   }   }
3969   /* handle removing LT_ROOT line too */   /* handle removing LT_ROOT line too */
# Line 4143  int checkForElilo(struct grubConfig *con Line 4457  int checkForElilo(struct grubConfig *con
4457   return 1;   return 1;
4458  }  }
4459    
4460  static char *getRootSpecifier(char *str)  static size_t getRootSpecifier(const char *str)
4461  {  {
4462   char *idx, *rootspec = NULL;   size_t rs = 0;
4463    
4464   if (*str == '(') {   if (*str == '(') {
4465   idx = rootspec = strdup(str);   for (; str[rs] != ')' && !isspace(str[rs]); rs++) {
4466   while (*idx && (*idx != ')') && (!isspace(*idx)))   if (!str[rs])
4467   idx++;   return rs;
4468   *(++idx) = '\0';   }
4469     rs++;
4470   }   }
4471   return rootspec;  
4472     return rs + subvolPrefix(str + rs);
4473  }  }
4474    
4475  static char *getInitrdVal(struct grubConfig *config,  static char *getInitrdVal(struct grubConfig *config,
# Line 4725  int addNewKernel(struct grubConfig *conf Line 5041  int addNewKernel(struct grubConfig *conf
5041   }   }
5042    
5043   if (updateImage(config, indexs, prefix, newKernelArgs, NULL,   if (updateImage(config, indexs, prefix, newKernelArgs, NULL,
5044   newMBKernelArgs, NULL))   newMBKernelArgs, NULL)) {
5045     config->isModified = 1;
5046   return 1;   return 1;
5047     }
5048    
5049   return 0;   return 0;
5050  }  }
# Line 4783  int main(int argc, const char **argv) Line 5101  int main(int argc, const char **argv)
5101   {"mbargs", 0, POPT_ARG_STRING, &newMBKernelArgs, 0,   {"mbargs", 0, POPT_ARG_STRING, &newMBKernelArgs, 0,
5102   _("default arguments for the new multiboot kernel or "   _("default arguments for the new multiboot kernel or "
5103     "new arguments for multiboot kernel being updated"), NULL},     "new arguments for multiboot kernel being updated"), NULL},
5104     {"mounts", 0, POPT_ARG_STRING, &mounts, 0,
5105     _("path to fake /proc/mounts file (for testing only)"),
5106     _("mounts")},
5107   {"bad-image-okay", 0, 0, &badImageOkay, 0,   {"bad-image-okay", 0, 0, &badImageOkay, 0,
5108   _   _
5109   ("don't sanity check images in boot entries (for testing only)"),   ("don't sanity check images in boot entries (for testing only)"),
# Line 4967  int main(int argc, const char **argv) Line 5288  int main(int argc, const char **argv)
5288   if (!cfi) {   if (!cfi) {
5289   if (grub2FindConfig(&grub2ConfigType)) {   if (grub2FindConfig(&grub2ConfigType)) {
5290   cfi = &grub2ConfigType;   cfi = &grub2ConfigType;
5291     configureGrub2 = 1;
5292   if (envPath)   if (envPath)
5293   cfi->envFile = envPath;   cfi->envFile = envPath;
5294   } else   } else {
5295  #ifdef __ia64__  #ifdef __ia64__
5296   cfi = &eliloConfigType;   cfi = &eliloConfigType;
5297  #elif __powerpc__   configureLilo = 1;
5298    #elif defined(__powerpc__)
5299   cfi = &yabootConfigType;   cfi = &yabootConfigType;
5300  #elif __sparc__   configureYaboot = 1;
5301    #elif defined(__sparc__)
5302   cfi = &siloConfigType;   cfi = &siloConfigType;
5303  #elif __s390__   configureSilo = 1;
5304    #elif defined(__s390__) || defined(__s390x__)
5305   cfi = &ziplConfigType;   cfi = &ziplConfigType;
5306  #elif __s390x__   configureZipl = 1;
  cfi = &ziplConfigtype;  
5307  #else  #else
5308   cfi = &grubConfigType;   cfi = &grubConfigType;
5309     configureGrub = 1;
5310  #endif  #endif
5311     }
5312   }   }
5313    
5314   if (!grubConfig) {   if (!grubConfig) {
# Line 5176  int main(int argc, const char **argv) Line 5502  int main(int argc, const char **argv)
5502   if (displayDefault) {   if (displayDefault) {
5503   struct singleLine *line;   struct singleLine *line;
5504   struct singleEntry *entry;   struct singleEntry *entry;
5505   char *rootspec;   size_t rs;
5506    
5507   if (config->defaultImage == -1)   if (config->defaultImage == NO_DEFAULT_ENTRY)
5508   return 0;   return 0;
5509   if (config->defaultImage == DEFAULT_SAVED_GRUB2 &&   if (config->defaultImage == DEFAULT_SAVED_GRUB2 &&
5510      cfi->defaultIsSaved)      cfi->defaultIsSaved)
5511   config->defaultImage = 0;   config->defaultImage = FIRST_ENTRY_INDEX;
5512   entry = findEntryByIndex(config, config->defaultImage);   entry = findEntryByIndex(config, config->defaultImage);
5513   if (!entry)   if (!entry)
5514   return 0;   return 0;
# Line 5195  int main(int argc, const char **argv) Line 5521  int main(int argc, const char **argv)
5521   if (!line)   if (!line)
5522   return 0;   return 0;
5523    
5524   rootspec = getRootSpecifier(line->elements[1].item);   rs = getRootSpecifier(line->elements[1].item);
5525   printf("%s%s\n", bootPrefix, line->elements[1].item +   printf("%s%s\n", bootPrefix, line->elements[1].item + rs);
        ((rootspec != NULL) ? strlen(rootspec) : 0));  
5526    
5527   return 0;   return 0;
5528    
# Line 5205  int main(int argc, const char **argv) Line 5530  int main(int argc, const char **argv)
5530   struct singleLine *line;   struct singleLine *line;
5531   struct singleEntry *entry;   struct singleEntry *entry;
5532    
5533   if (config->defaultImage == -1)   if (config->defaultImage == NO_DEFAULT_ENTRY)
5534   return 0;   return 0;
5535   if (config->defaultImage == DEFAULT_SAVED_GRUB2 &&   if (config->defaultImage == DEFAULT_SAVED_GRUB2 &&
5536      cfi->defaultIsSaved)      cfi->defaultIsSaved)
5537   config->defaultImage = 0;   config->defaultImage = FIRST_ENTRY_INDEX;
5538   entry = findEntryByIndex(config, config->defaultImage);   entry = findEntryByIndex(config, config->defaultImage);
5539   if (!entry)   if (!entry)
5540   return 0;   return 0;
# Line 5239  int main(int argc, const char **argv) Line 5564  int main(int argc, const char **argv)
5564   return 0;   return 0;
5565    
5566   } else if (displayDefaultIndex) {   } else if (displayDefaultIndex) {
5567   if (config->defaultImage == -1)   if (config->defaultImage == NO_DEFAULT_ENTRY)
5568   return 0;   return 0;
5569   if (config->defaultImage == DEFAULT_SAVED_GRUB2 &&   if (config->defaultImage == DEFAULT_SAVED_GRUB2 &&
5570      cfi->defaultIsSaved)      cfi->defaultIsSaved)
5571   config->defaultImage = 0;   config->defaultImage = FIRST_ENTRY_INDEX;
5572   printf("%i\n", config->defaultImage);   printf("%i\n", config->defaultImage);
5573   return 0;   return 0;
5574    
# Line 5259  int main(int argc, const char **argv) Line 5584  int main(int argc, const char **argv)
5584   markRemovedImage(config, removeKernelPath, bootPrefix);   markRemovedImage(config, removeKernelPath, bootPrefix);
5585   markRemovedImage(config, removeMBKernel, bootPrefix);   markRemovedImage(config, removeMBKernel, bootPrefix);
5586   setDefaultImage(config, newKernelPath != NULL, defaultKernel,   setDefaultImage(config, newKernelPath != NULL, defaultKernel,
5587   makeDefault, bootPrefix, flags, defaultIndex);   makeDefault, bootPrefix, flags, defaultIndex,
5588     newIndex);
5589   setFallbackImage(config, newKernelPath != NULL);   setFallbackImage(config, newKernelPath != NULL);
5590   if (updateImage(config, updateKernelPath, bootPrefix, newKernelArgs,   if (updateImage(config, updateKernelPath, bootPrefix, newKernelArgs,
5591   removeArgs, newMBKernelArgs, removeMBKernelArgs))   removeArgs, newMBKernelArgs, removeMBKernelArgs))

Legend:
Removed from v.3014  
changed lines
  Added in v.3139