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 3149 by niro, Tue Jul 7 11:23:41 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 75  struct lineElement { Line 77  struct lineElement {
77  };  };
78    
79  enum lineType_e {  enum lineType_e {
80     LT_UNIDENTIFIED = 0,
81   LT_WHITESPACE = 1 << 0,   LT_WHITESPACE = 1 << 0,
82   LT_TITLE = 1 << 1,   LT_TITLE = 1 << 1,
83   LT_KERNEL = 1 << 2,   LT_KERNEL = 1 << 2,
# Line 131  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 475  char *grub2ExtractTitle(struct singleLin Line 482  char *grub2ExtractTitle(struct singleLin
482   snprintf(result, resultMaxSize, "%s", ++current);   snprintf(result, resultMaxSize, "%s", ++current);
483    
484   i++;   i++;
485     int result_len = 0;
486   for (; i < line->numElements; ++i) {   for (; i < line->numElements; ++i) {
487   current = line->elements[i].item;   current = line->elements[i].item;
488   current_len = strlen(current);   current_len = strlen(current);
489   current_indent = line->elements[i].indent;   current_indent = line->elements[i].indent;
490   current_indent_len = strlen(current_indent);   current_indent_len = strlen(current_indent);
491    
492   strncat(result, current_indent, current_indent_len);   memcpy(result + result_len, current_indent, current_indent_len);
493     result_len += current_indent_len;
494    
495   if (current[current_len - 1] != quote_char) {   if (current[current_len - 1] != quote_char) {
496   strncat(result, current, current_len);   memcpy(result + result_len, current_indent,
497           current_indent_len);
498     result_len += current_len;
499   } else {   } else {
500   strncat(result, current, current_len - 1);   memcpy(result + result_len, current_indent,
501           current_indent_len);
502     result_len += (current_len - 1);
503   break;   break;
504   }   }
505   }   }
506     result[result_len] = '\0';
507   return result;   return result;
508  }  }
509    
# Line 676  struct grubConfig { Line 691  struct grubConfig {
691   int fallbackImage; /* just like defaultImage */   int fallbackImage; /* just like defaultImage */
692   int flags;   int flags;
693   struct configFileInfo *cfi;   struct configFileInfo *cfi;
694     int isModified; /* assumes only one entry added
695       per invocation of grubby */
696  };  };
697    
698  blkid_cache blkid;  blkid_cache blkid;
# Line 694  static int lineWrite(FILE * out, struct Line 711  static int lineWrite(FILE * out, struct
711       struct configFileInfo *cfi);       struct configFileInfo *cfi);
712  static int getNextLine(char **bufPtr, struct singleLine *line,  static int getNextLine(char **bufPtr, struct singleLine *line,
713         struct configFileInfo *cfi);         struct configFileInfo *cfi);
714  static char *getRootSpecifier(char *str);  static size_t getRootSpecifier(const char *str);
715  static void requote(struct singleLine *line, struct configFileInfo *cfi);  static void requote(struct singleLine *line, struct configFileInfo *cfi);
716  static void insertElement(struct singleLine *line,  static void insertElement(struct singleLine *line,
717    const char *item, int insertHere,    const char *item, int insertHere,
# Line 750  static char *sdupprintf(const char *form Line 767  static char *sdupprintf(const char *form
767   return buf;   return buf;
768  }  }
769    
770    static inline int
771    kwcmp(struct keywordTypes *kw, const char * label, int case_insensitive)
772    {
773        int kwl = strlen(kw->key);
774        int ll = strlen(label);
775        int rc;
776        int (*snc)(const char *s1, const char *s2, size_t n) =
777               case_insensitive ? strncasecmp : strncmp;
778        int (*sc)(const char *s1, const char *s2) =
779               case_insensitive ? strcasecmp : strcmp;
780    
781        rc = snc(kw->key, label, kwl);
782        if (rc)
783           return rc;
784    
785        for (int i = kwl; i < ll; i++) {
786           if (isspace(label[i]))
787               return 0;
788           if (kw->separatorChar && label[i] == kw->separatorChar)
789               return 0;
790           else if (kw->nextChar && label[i] == kw->nextChar)
791               return 0;
792           return sc(kw->key+kwl, label+kwl);
793        }
794        return 0;
795    }
796    
797  static enum lineType_e preferredLineType(enum lineType_e type,  static enum lineType_e preferredLineType(enum lineType_e type,
798   struct configFileInfo *cfi)   struct configFileInfo *cfi)
799  {  {
# Line 815  static enum lineType_e getTypeByKeyword( Line 859  static enum lineType_e getTypeByKeyword(
859   struct configFileInfo *cfi)   struct configFileInfo *cfi)
860  {  {
861   for (struct keywordTypes * kw = cfi->keywords; kw->key; kw++) {   for (struct keywordTypes * kw = cfi->keywords; kw->key; kw++) {
862   if (cfi->caseInsensitive) {   if (!kwcmp(kw, keyword, cfi->caseInsensitive))
863   if (!strcasecmp(keyword, kw->key))   return kw->type;
  return kw->type;  
  } else {  
  if (!strcmp(keyword, kw->key))  
  return kw->type;  
  }  
864   }   }
865   return LT_UNKNOWN;   return LT_UNKNOWN;
866  }  }
# Line 916  static int readFile(int fd, char **bufPt Line 955  static int readFile(int fd, char **bufPt
955    
956  static void lineInit(struct singleLine *line)  static void lineInit(struct singleLine *line)
957  {  {
958     line->type = LT_UNIDENTIFIED;
959   line->indent = NULL;   line->indent = NULL;
960   line->elements = NULL;   line->elements = NULL;
961   line->numElements = 0;   line->numElements = 0;
# Line 998  static int lineWrite(FILE * out, struct Line 1038  static int lineWrite(FILE * out, struct
1038    
1039   if (fprintf(out, "%s", line->elements[i].item) == -1)   if (fprintf(out, "%s", line->elements[i].item) == -1)
1040   return -1;   return -1;
1041   if (i < line->numElements - 1)   if (i < line->numElements - 1 || line->type == LT_SET_VARIABLE)
1042   if (fprintf(out, "%s", line->elements[i].indent) == -1)   if (fprintf(out, "%s", line->elements[i].indent) == -1)
1043   return -1;   return -1;
1044   }   }
# Line 1053  static int getNextLine(char **bufPtr, st Line 1093  static int getNextLine(char **bufPtr, st
1093   break;   break;
1094   chptr++;   chptr++;
1095   }   }
1096     if (line->type == LT_UNIDENTIFIED)
1097     line->type = getTypeByKeyword(start, cfi);
1098   element->item = strndup(start, chptr - start);   element->item = strndup(start, chptr - start);
1099   start = chptr;   start = chptr;
1100    
# Line 1118  static int getNextLine(char **bufPtr, st Line 1160  static int getNextLine(char **bufPtr, st
1160   line->type = LT_WHITESPACE;   line->type = LT_WHITESPACE;
1161   line->numElements = 0;   line->numElements = 0;
1162   }   }
1163   } else {   } else if (line->type == LT_INITRD) {
1164   struct keywordTypes *kw;   struct keywordTypes *kw;
1165    
1166   kw = getKeywordByType(line->type, cfi);   kw = getKeywordByType(line->type, cfi);
# Line 1180  static int getNextLine(char **bufPtr, st Line 1222  static int getNextLine(char **bufPtr, st
1222   }   }
1223   }   }
1224   }   }
1225     } else if (line->type == LT_SET_VARIABLE) {
1226     /* and if it's a "set blah=" we need to split it
1227     * yet a third way to avoid rhbz# XXX FIXME :/
1228     */
1229     char *eq;
1230     int l;
1231     int numElements = line->numElements;
1232     struct lineElement *newElements;
1233     eq = strchr(line->elements[1].item, '=');
1234     if (!eq)
1235     return 0;
1236     l = eq - line->elements[1].item;
1237     if (eq[1] != 0)
1238     numElements++;
1239     newElements = calloc(numElements,sizeof (*newElements));
1240     memcpy(&newElements[0], &line->elements[0],
1241           sizeof (newElements[0]));
1242     newElements[1].item =
1243     strndup(line->elements[1].item, l);
1244     newElements[1].indent = "=";
1245     *(eq++) = '\0';
1246     newElements[2].item = strdup(eq);
1247     free(line->elements[1].item);
1248     if (line->elements[1].indent)
1249     newElements[2].indent = line->elements[1].indent;
1250     for (int i = 2; i < line->numElements; i++) {
1251     newElements[i+1].item = line->elements[i].item;
1252     newElements[i+1].indent =
1253     line->elements[i].indent;
1254     }
1255     free(line->elements);
1256     line->elements = newElements;
1257     line->numElements = numElements;
1258   }   }
1259   }   }
1260    
# Line 1237  static struct grubConfig *readConfig(con Line 1312  static struct grubConfig *readConfig(con
1312   cfg->theLines = NULL;   cfg->theLines = NULL;
1313   cfg->entries = NULL;   cfg->entries = NULL;
1314   cfg->fallbackImage = 0;   cfg->fallbackImage = 0;
1315     cfg->isModified = 0;
1316    
1317   /* copy everything we have */   /* copy everything we have */
1318   while (*head) {   while (*head) {
# Line 1285  static struct grubConfig *readConfig(con Line 1361  static struct grubConfig *readConfig(con
1361      getKeywordByType(LT_DEFAULT, cfi);      getKeywordByType(LT_DEFAULT, cfi);
1362   if (kwType && line->numElements == 3   if (kwType && line->numElements == 3
1363      && !strcmp(line->elements[1].item, kwType->key)      && !strcmp(line->elements[1].item, kwType->key)
1364      && !is_special_grub2_variable(line->elements[2].      && !is_special_grub2_variable(
1365    item)) {   line->elements[2].item)) {
1366   dbgPrintf("Line sets default config\n");   dbgPrintf("Line sets default config\n");
1367   cfg->flags &= ~GRUB_CONFIG_NO_DEFAULT;   cfg->flags &= ~GRUB_CONFIG_NO_DEFAULT;
1368   defaultLine = line;   defaultLine = line;
1369   }   }
   
1370   } else if (iskernel(line->type)) {   } else if (iskernel(line->type)) {
1371   /* if by some freak chance this is multiboot and the   /* if by some freak chance this is multiboot and the
1372   * "module" lines came earlier in the template, make   * "module" lines came earlier in the template, make
# Line 1373  static struct grubConfig *readConfig(con Line 1448  static struct grubConfig *readConfig(con
1448   extras = malloc(len + 1);   extras = malloc(len + 1);
1449   *extras = '\0';   *extras = '\0';
1450    
1451     int buf_len = 0;
1452   /* get title. */   /* get title. */
1453   for (int i = 0; i < line->numElements; i++) {   for (int i = 0; i < line->numElements; i++) {
1454   if (!strcmp   if (!strcmp
# Line 1389  static struct grubConfig *readConfig(con Line 1465  static struct grubConfig *readConfig(con
1465    
1466   len = strlen(title);   len = strlen(title);
1467   if (title[len - 1] == quote_char) {   if (title[len - 1] == quote_char) {
1468   strncat(buf, title, len - 1);   memcpy(buf + buf_len, title, len - 1);
1469     buf_len += (len - 1);
1470   break;   break;
1471   } else {   } else {
1472   strcat(buf, title);   memcpy(buf + buf_len, title, len);
1473   strcat(buf, line->elements[i].indent);   buf_len += len;
1474     len = strlen(line->elements[i].indent);
1475     memcpy(buf + buf_len, line->elements[i].indent, len);
1476     buf_len += len;
1477   }   }
1478   }   }
1479     buf[buf_len] = '\0';
1480    
1481   /* get extras */   /* get extras */
1482   int count = 0;   int count = 0;
# Line 1545  static struct grubConfig *readConfig(con Line 1626  static struct grubConfig *readConfig(con
1626   }   }
1627   }   }
1628   } else if (cfi->defaultIsVariable) {   } else if (cfi->defaultIsVariable) {
1629   char *value = defaultLine->elements[2].item;   if (defaultLine->numElements == 2) {
1630   while (*value && (*value == '"' || *value == '\'' ||   char *value = defaultLine->elements[1].item + 8;
1631    *value == ' ' || *value == '\t'))   while (*value && (*value == '"' ||
1632   value++;    *value == '\'' ||
1633   cfg->defaultImage = strtol(value, &end, 10);    *value == ' ' ||
1634   while (*end && (*end == '"' || *end == '\'' ||    *value == '\t'))
1635   *end == ' ' || *end == '\t'))   value++;
1636   end++;   cfg->defaultImage = strtol(value, &end, 10);
1637   if (*end)   while (*end && (*end == '"' || *end == '\'' ||
1638   cfg->defaultImage = -1;   *end == ' ' || *end == '\t'))
1639     end++;
1640     if (*end)
1641     cfg->defaultImage = NO_DEFAULT_ENTRY;
1642     } else if (defaultLine->numElements == 3) {
1643     char *value = defaultLine->elements[2].item;
1644     while (*value && (*value == '"' ||
1645      *value == '\'' ||
1646      *value == ' ' ||
1647      *value == '\t'))
1648     value++;
1649     cfg->defaultImage = strtol(value, &end, 10);
1650     while (*end && (*end == '"' || *end == '\'' ||
1651     *end == ' ' || *end == '\t'))
1652     end++;
1653     if (*end)
1654     cfg->defaultImage = NO_DEFAULT_ENTRY;
1655     }
1656   } else if (cfi->defaultSupportSaved &&   } else if (cfi->defaultSupportSaved &&
1657     !strncmp(defaultLine->elements[1].item, "saved",     !strncmp(defaultLine->elements[1].item, "saved",
1658      5)) {      5)) {
# Line 1563  static struct grubConfig *readConfig(con Line 1661  static struct grubConfig *readConfig(con
1661   cfg->defaultImage =   cfg->defaultImage =
1662      strtol(defaultLine->elements[1].item, &end, 10);      strtol(defaultLine->elements[1].item, &end, 10);
1663   if (*end)   if (*end)
1664   cfg->defaultImage = -1;   cfg->defaultImage = NO_DEFAULT_ENTRY;
1665   } else if (defaultLine->numElements >= 2) {   } else if (defaultLine->numElements >= 2) {
1666   int i = 0;   int i = 0;
1667   while ((entry = findEntryByIndex(cfg, i))) {   while ((entry = findEntryByIndex(cfg, i))) {
# Line 1591  static struct grubConfig *readConfig(con Line 1689  static struct grubConfig *readConfig(con
1689   if (entry) {   if (entry) {
1690   cfg->defaultImage = i;   cfg->defaultImage = i;
1691   } else {   } else {
1692   cfg->defaultImage = -1;   cfg->defaultImage = NO_DEFAULT_ENTRY;
1693   }   }
1694   }   }
1695   } else if (cfg->cfi->defaultIsSaved && cfg->cfi->getEnv) {   } else if (cfg->cfi->defaultIsSaved && cfg->cfi->getEnv) {
# Line 1608  static struct grubConfig *readConfig(con Line 1706  static struct grubConfig *readConfig(con
1706   cfg->defaultImage = index;   cfg->defaultImage = index;
1707   }   }
1708   } else {   } else {
1709   cfg->defaultImage = 0;   cfg->defaultImage = FIRST_ENTRY_INDEX;
1710   }   }
1711    
1712   return cfg;   return cfg;
# Line 1628  static void writeDefault(FILE * out, cha Line 1726  static void writeDefault(FILE * out, cha
1726   fprintf(out, "%sdefault%ssaved\n", indent, separator);   fprintf(out, "%sdefault%ssaved\n", indent, separator);
1727   else if (cfg->cfi->defaultIsSaved) {   else if (cfg->cfi->defaultIsSaved) {
1728   fprintf(out, "%sset default=\"${saved_entry}\"\n", indent);   fprintf(out, "%sset default=\"${saved_entry}\"\n", indent);
1729   if (cfg->defaultImage >= 0 && cfg->cfi->setEnv) {   if (cfg->defaultImage >= FIRST_ENTRY_INDEX && cfg->cfi->setEnv) {
1730   char *title;   char *title;
1731   entry = findEntryByIndex(cfg, cfg->defaultImage);   int trueIndex, currentIndex;
1732    
1733     trueIndex = 0;
1734     currentIndex = 0;
1735    
1736     while ((entry = findEntryByIndex(cfg, currentIndex))) {
1737     if (!entry->skip) {
1738     if (trueIndex == cfg->defaultImage) {
1739     break;
1740     }
1741     trueIndex++;
1742     }
1743     currentIndex++;
1744     }
1745   line = getLineByType(LT_MENUENTRY, entry->lines);   line = getLineByType(LT_MENUENTRY, entry->lines);
1746   if (!line)   if (!line)
1747   line = getLineByType(LT_TITLE, entry->lines);   line = getLineByType(LT_TITLE, entry->lines);
# Line 1641  static void writeDefault(FILE * out, cha Line 1752  static void writeDefault(FILE * out, cha
1752   "saved_entry", title);   "saved_entry", title);
1753   }   }
1754   }   }
1755   } else if (cfg->defaultImage > -1) {   } else if (cfg->defaultImage >= FIRST_ENTRY_INDEX) {
1756   if (cfg->cfi->defaultIsIndex) {   if (cfg->cfi->defaultIsIndex) {
1757   if (cfg->cfi->defaultIsVariable) {   if (cfg->cfi->defaultIsVariable) {
1758   fprintf(out, "%sset default=\"%d\"\n", indent,   fprintf(out, "%sset default=\"%d\"\n", indent,
# Line 1697  static int writeConfig(struct grubConfig Line 1808  static int writeConfig(struct grubConfig
1808   int needs = MAIN_DEFAULT;   int needs = MAIN_DEFAULT;
1809   struct stat sb;   struct stat sb;
1810   int i;   int i;
1811     int rc = 0;
1812    
1813   if (!strcmp(outName, "-")) {   if (!strcmp(outName, "-")) {
1814   out = stdout;   out = stdout;
# Line 1811  static int writeConfig(struct grubConfig Line 1923  static int writeConfig(struct grubConfig
1923   }   }
1924    
1925   if (tmpOutName) {   if (tmpOutName) {
1926   if (rename(tmpOutName, outName)) {   /* write userspace buffers */
1927   fprintf(stderr,   if (fflush(out))
1928   _("grubby: error moving %s to %s: %s\n"),   rc = 1;
1929   tmpOutName, outName, strerror(errno));  
1930   unlink(outName);   /* purge the write-back cache with fsync() */
1931   return 1;   if (fsync(fileno(out)))
1932     rc = 1;
1933    
1934     if (fclose(out))
1935     rc = 1;
1936    
1937     if (rc == 0 && rename(tmpOutName, outName)) {
1938     unlink(tmpOutName);
1939     rc = 1;
1940     }
1941    
1942     /* fsync() the destination directory after rename */
1943     if (rc == 0) {
1944     int dirfd;
1945    
1946     dirfd = open(dirname(strdupa(outName)), O_RDONLY);
1947     if (dirfd < 0)
1948     rc = 1;
1949     else if (fsync(dirfd))
1950     rc = 1;
1951    
1952     if (dirfd >= 0)
1953     close(dirfd);
1954   }   }
1955    
1956     if (rc == 1)
1957     fprintf(stderr,
1958     _("grubby: error flushing data: %m\n"));
1959   }   }
1960    
1961   return 0;   return rc;
1962  }  }
1963    
1964  static int numEntries(struct grubConfig *cfg)  static int numEntries(struct grubConfig *cfg)
# Line 1996  static int endswith(const char *s, char Line 2134  static int endswith(const char *s, char
2134   return s[slen] == c;   return s[slen] == c;
2135  }  }
2136    
2137    typedef struct {
2138     const char *start;
2139     size_t      chars;
2140    } field;
2141    
2142    static int iscomma(int c)
2143    {
2144     return c == ',';
2145    }
2146    
2147    static int isequal(int c)
2148    {
2149     return c == '=';
2150    }
2151    
2152    static field findField(const field *in, typeof(isspace) *isdelim, field *out)
2153    {
2154     field nxt = {};
2155     size_t off = 0;
2156    
2157     while (off < in->chars && isdelim(in->start[off]))
2158     off++;
2159    
2160     if (off == in->chars)
2161     return nxt;
2162    
2163     out->start = &in->start[off];
2164     out->chars = 0;
2165    
2166     while (off + out->chars < in->chars && !isdelim(out->start[out->chars]))
2167     out->chars++;
2168    
2169     nxt.start = out->start + out->chars;
2170     nxt.chars = in->chars - off - out->chars;
2171     return nxt;
2172    }
2173    
2174    static int fieldEquals(const field *in, const char *str)
2175    {
2176     return in->chars == strlen(str) &&
2177     strncmp(in->start, str, in->chars) == 0;
2178    }
2179    
2180    /* Parse /proc/mounts to determine the subvolume prefix. */
2181    static size_t subvolPrefix(const char *str)
2182    {
2183     FILE *file = NULL;
2184     char *line = NULL;
2185     size_t prfx = 0;
2186     size_t size = 0;
2187    
2188     file = fopen(mounts, "r");
2189     if (!file)
2190     return 0;
2191    
2192     for (ssize_t s; (s = getline(&line, &size, file)) >= 0; ) {
2193     field nxt = { line, s };
2194     field dev = {};
2195     field path = {};
2196     field type = {};
2197     field opts = {};
2198     field opt = {};
2199    
2200     nxt = findField(&nxt, isspace, &dev);
2201     if (!nxt.start)
2202     continue;
2203    
2204     nxt = findField(&nxt, isspace, &path);
2205     if (!nxt.start)
2206     continue;
2207    
2208     nxt = findField(&nxt, isspace, &type);
2209     if (!nxt.start)
2210     continue;
2211    
2212     nxt = findField(&nxt, isspace, &opts);
2213     if (!nxt.start)
2214     continue;
2215    
2216     if (!fieldEquals(&type, "btrfs"))
2217     continue;
2218    
2219     /* We have found a btrfs mount point. */
2220    
2221     nxt = opts;
2222     while ((nxt = findField(&nxt, iscomma, &opt)).start) {
2223     field key = {};
2224     field val = {};
2225    
2226     opt = findField(&opt, isequal, &key);
2227     if (!opt.start)
2228     continue;
2229    
2230     opt = findField(&opt, isequal, &val);
2231     if (!opt.start)
2232     continue;
2233    
2234     if (!fieldEquals(&key, "subvol"))
2235     continue;
2236    
2237     /* We have found a btrfs subvolume mount point. */
2238    
2239     if (strncmp(val.start, str, val.chars))
2240     continue;
2241    
2242     if (val.start[val.chars - 1] != '/' &&
2243     str[val.chars] != '/')
2244     continue;
2245    
2246     /* The subvolume mount point matches our input. */
2247    
2248     if (prfx < val.chars)
2249     prfx = val.chars;
2250     }
2251     }
2252    
2253     dbgPrintf("%s(): str: '%s', prfx: '%s'\n", __FUNCTION__, str, prfx);
2254    
2255     fclose(file);
2256     free(line);
2257     return prfx;
2258    }
2259    
2260  int suitableImage(struct singleEntry *entry, const char *bootPrefix,  int suitableImage(struct singleEntry *entry, const char *bootPrefix,
2261    int skipRemoved, int flags)    int skipRemoved, int flags)
2262  {  {
# Line 2003  int suitableImage(struct singleEntry *en Line 2264  int suitableImage(struct singleEntry *en
2264   char *fullName;   char *fullName;
2265   int i;   int i;
2266   char *dev;   char *dev;
2267   char *rootspec;   size_t rs;
2268   char *rootdev;   char *rootdev;
2269    
2270   if (skipRemoved && entry->skip) {   if (skipRemoved && entry->skip) {
# Line 2031  int suitableImage(struct singleEntry *en Line 2292  int suitableImage(struct singleEntry *en
2292    
2293   fullName = alloca(strlen(bootPrefix) +   fullName = alloca(strlen(bootPrefix) +
2294    strlen(line->elements[1].item) + 1);    strlen(line->elements[1].item) + 1);
2295   rootspec = getRootSpecifier(line->elements[1].item);   rs = getRootSpecifier(line->elements[1].item);
  int rootspec_offset = rootspec ? strlen(rootspec) : 0;  
2296   int hasslash = endswith(bootPrefix, '/') ||   int hasslash = endswith(bootPrefix, '/') ||
2297      beginswith(line->elements[1].item + rootspec_offset, '/');      beginswith(line->elements[1].item + rs, '/');
2298   sprintf(fullName, "%s%s%s", bootPrefix, hasslash ? "" : "/",   sprintf(fullName, "%s%s%s", bootPrefix, hasslash ? "" : "/",
2299   line->elements[1].item + rootspec_offset);   line->elements[1].item + rs);
2300   if (access(fullName, R_OK)) {   if (access(fullName, R_OK)) {
2301   notSuitablePrintf(entry, 0, "access to %s failed\n", fullName);   notSuitablePrintf(entry, 0, "access to %s failed\n", fullName);
2302   return 0;   return 0;
# Line 2128  struct singleEntry *findEntryByPath(stru Line 2388  struct singleEntry *findEntryByPath(stru
2388   struct singleLine *line;   struct singleLine *line;
2389   int i;   int i;
2390   char *chptr;   char *chptr;
  char *rootspec = NULL;  
2391   enum lineType_e checkType = LT_KERNEL;   enum lineType_e checkType = LT_KERNEL;
2392    
2393   if (isdigit(*kernel)) {   if (isdigit(*kernel)) {
# Line 2233  struct singleEntry *findEntryByPath(stru Line 2492  struct singleEntry *findEntryByPath(stru
2492    
2493   if (line && line->type != LT_MENUENTRY &&   if (line && line->type != LT_MENUENTRY &&
2494      line->numElements >= 2) {      line->numElements >= 2) {
2495   rootspec =   if (!strcmp(line->elements[1].item +
2496      getRootSpecifier(line->elements[1].   getRootSpecifier(
2497       item);   line->elements[1].item),
2498   if (!strcmp   kernel + strlen(prefix)))
     (line->elements[1].item +  
      ((rootspec !=  
        NULL) ? strlen(rootspec) : 0),  
      kernel + strlen(prefix)))  
2499   break;   break;
2500   }   }
2501   if (line->type == LT_MENUENTRY &&   if (line->type == LT_MENUENTRY &&
# Line 2345  struct singleEntry *findTemplate(struct Line 2600  struct singleEntry *findTemplate(struct
2600   }   }
2601   }   }
2602   }   }
2603   } else if (cfg->defaultImage > -1) {   } else if (cfg->defaultImage >= FIRST_ENTRY_INDEX) {
2604   entry = findEntryByIndex(cfg, cfg->defaultImage);   entry = findEntryByIndex(cfg, cfg->defaultImage);
2605   if (entry && suitableImage(entry, prefix, skipRemoved, flags)) {   if (entry && suitableImage(entry, prefix, skipRemoved, flags)) {
2606   if (indexPtr)   if (indexPtr)
# Line 2357  struct singleEntry *findTemplate(struct Line 2612  struct singleEntry *findTemplate(struct
2612   index = 0;   index = 0;
2613   while ((entry = findEntryByIndex(cfg, index))) {   while ((entry = findEntryByIndex(cfg, index))) {
2614   if (suitableImage(entry, prefix, skipRemoved, flags)) {   if (suitableImage(entry, prefix, skipRemoved, flags)) {
2615   int j;   int j, unmodifiedIndex;
2616   for (j = 0; j < index; j++) {  
2617     unmodifiedIndex = index;
2618    
2619     for (j = 0; j < unmodifiedIndex; j++) {
2620   entry2 = findEntryByIndex(cfg, j);   entry2 = findEntryByIndex(cfg, j);
2621   if (entry2->skip)   if (entry2->skip)
2622   index--;   index--;
# Line 2419  void markRemovedImage(struct grubConfig Line 2677  void markRemovedImage(struct grubConfig
2677   entry->skip = 1;   entry->skip = 1;
2678  }  }
2679    
2680  void setDefaultImage(struct grubConfig *config, int hasNew,  void setDefaultImage(struct grubConfig *config, int isAddingBootEntry,
2681       const char *defaultKernelPath, int newIsDefault,       const char *defaultKernelPath, int newBootEntryIsDefault,
2682       const char *prefix, int flags, int index)       const char *prefix, int flags,
2683  {       int newDefaultBootEntryIndex, int newBootEntryIndex)
2684   struct singleEntry *entry, *entry2, *newDefault;  {
2685   int i, j;   struct singleEntry *bootEntry, *newDefault;
2686     int indexToVerify, firstKernelEntryIndex, currentLookupIndex;
2687   if (newIsDefault) {  
2688   config->defaultImage = 0;          /* initialize */
2689            currentLookupIndex = FIRST_ENTRY_INDEX;
2690    
2691     /* handle the two cases where the user explictly picks the default
2692     * boot entry index as it would exist post-modification */
2693    
2694     /* Case 1: user chose to make the latest boot entry the default */
2695     if (newBootEntryIsDefault) {
2696     config->defaultImage = newBootEntryIndex;
2697   return;   return;
2698   } else if ((index >= 0) && config->cfi->defaultIsIndex) {   }
2699   if (findEntryByIndex(config, index))  
2700   config->defaultImage = index;   /* Case 2: user picked an arbitrary index as the default boot entry */
2701   else   if (newDefaultBootEntryIndex >= FIRST_ENTRY_INDEX) {
2702   config->defaultImage = -1;   indexToVerify = newDefaultBootEntryIndex;
2703   return;  
2704   } else if (defaultKernelPath) {   /* user chose to make latest boot entry the default */
2705   i = 0;   if (newDefaultBootEntryIndex == newBootEntryIndex) {
2706   if (findEntryByPath(config, defaultKernelPath, prefix, &i)) {   config->defaultImage = newBootEntryIndex;
  config->defaultImage = i;  
  } else {  
  config->defaultImage = -1;  
2707   return;   return;
2708   }   }
  }  
2709    
2710   /* defaultImage now points to what we'd like to use, but before any   /* the user picks the default index based on the
2711   * order changes */   * order of the bootloader configuration after
2712   if ((config->defaultImage == DEFAULT_SAVED) ||   * modification; ensure we are checking for the
2713      (config->defaultImage == DEFAULT_SAVED_GRUB2))   * existence of the correct entry */
2714   /* default is set to saved, we don't want to change it */   if (newBootEntryIndex < newDefaultBootEntryIndex) {
2715     if (!config->isModified)
2716     indexToVerify--;
2717     }
2718    
2719     /* verify the user selected index will exist */
2720     if (findEntryByIndex(config, indexToVerify)) {
2721     config->defaultImage = newDefaultBootEntryIndex;
2722     } else {
2723     config->defaultImage = NO_DEFAULT_ENTRY;
2724     }
2725    
2726   return;   return;
2727     }
2728    
2729   if (config->defaultImage > -1)   /* handle cases where the index value may shift */
  entry = findEntryByIndex(config, config->defaultImage);  
  else  
  entry = NULL;  
2730    
2731   if (entry && !entry->skip) {   /* check validity of existing default or first-entry-found
2732   /* we can preserve the default */     selection */
2733   if (hasNew)   if (defaultKernelPath) {
2734   config->defaultImage++;                  /* we must initialize this */
2735                    firstKernelEntryIndex = 0;
2736     /* user requested first-entry-found */
2737     if (!findEntryByPath(config, defaultKernelPath,
2738         prefix, &firstKernelEntryIndex)) {
2739     /* don't change default if can't find match */
2740     config->defaultImage = NO_DEFAULT_ENTRY;
2741     return;
2742     }
2743    
2744     config->defaultImage = firstKernelEntryIndex;
2745    
2746     /* this is where we start looking for decrement later */
2747     currentLookupIndex = config->defaultImage;
2748    
2749   /* count the number of entries erased before this one */   if (isAddingBootEntry && !config->isModified &&
2750   for (j = 0; j < config->defaultImage; j++) {      (newBootEntryIndex < config->defaultImage)) {
2751   entry2 = findEntryByIndex(config, j);   /* increment because new entry added before default */
2752   if (entry2->skip)   config->defaultImage++;
  config->defaultImage--;  
2753   }   }
  } else if (hasNew) {  
  config->defaultImage = 0;  
2754   } else {   } else {
2755   /* Either we just erased the default (or the default line was                  /* check to see if the default is stored in the environment */
2756   * bad to begin with) and didn't put a new one in. We'll use                  if (config->defaultImage < FIRST_ENTRY_INDEX) {
2757   * the first valid image. */                      if (config->defaultImage == DEFAULT_SAVED || config->defaultImage == DEFAULT_SAVED_GRUB2)
2758                        {
2759                            if (config->cfi->defaultIsSaved) {
2760                                if (config->cfi->getEnv) {
2761                                    char *defaultTitle = config->cfi->getEnv(config->cfi, "saved_entry");
2762    
2763                                    if (defaultTitle) {
2764                                        if (isnumber(defaultTitle)) {
2765                                            currentLookupIndex = atoi(defaultTitle);
2766                                        } else {
2767                                            findEntryByTitle(config, defaultTitle, &currentLookupIndex);
2768                                        }
2769                                        /* set the default Image to an actual index */
2770                                        config->defaultImage = currentLookupIndex;
2771                                    }
2772                                }
2773                             }
2774                        }
2775                    } else {
2776                            /* use pre-existing default entry from the file*/
2777                            currentLookupIndex = config->defaultImage;
2778                    }
2779    
2780     if (isAddingBootEntry
2781        && (newBootEntryIndex <= config->defaultImage)) {
2782     config->defaultImage++;
2783    
2784     if (config->isModified) {
2785     currentLookupIndex++;
2786     }
2787     }
2788     }
2789    
2790     /* sanity check - is this entry index valid? */
2791     bootEntry = findEntryByIndex(config, currentLookupIndex);
2792    
2793     if ((bootEntry && bootEntry->skip) || !bootEntry) {
2794     /* entry is to be skipped or is invalid */
2795     if (isAddingBootEntry) {
2796     config->defaultImage = newBootEntryIndex;
2797     return;
2798     }
2799   newDefault =   newDefault =
2800      findTemplate(config, prefix, &config->defaultImage, 1,      findTemplate(config, prefix, &config->defaultImage, 1,
2801   flags);   flags);
2802   if (!newDefault)   if (!newDefault) {
2803   config->defaultImage = -1;   config->defaultImage = NO_DEFAULT_ENTRY;
2804     }
2805    
2806     return;
2807     }
2808    
2809     currentLookupIndex--;
2810    
2811     /* decrement index by the total number of entries deleted */
2812    
2813     for (indexToVerify = currentLookupIndex;
2814         indexToVerify >= FIRST_ENTRY_INDEX; indexToVerify--) {
2815    
2816     bootEntry = findEntryByIndex(config, indexToVerify);
2817    
2818     if (bootEntry && bootEntry->skip) {
2819     config->defaultImage--;
2820     }
2821   }   }
2822  }  }
2823    
# Line 2507  void setFallbackImage(struct grubConfig Line 2846  void setFallbackImage(struct grubConfig
2846   }   }
2847  }  }
2848    
2849  void displayEntry(struct singleEntry *entry, const char *prefix, int index)  void displayEntry(struct grubConfig *config, struct singleEntry *entry, const char *prefix, int index)
2850  {  {
2851   struct singleLine *line;   struct singleLine *line;
2852   char *root = NULL;   char *root = NULL;
# Line 2603  void displayEntry(struct singleEntry *en Line 2942  void displayEntry(struct singleEntry *en
2942    
2943   line = getLineByType(LT_TITLE, entry->lines);   line = getLineByType(LT_TITLE, entry->lines);
2944   if (line) {   if (line) {
2945   printf("title=%s\n", line->elements[1].item);                  char *entryTitle;
2946                    /* if we can extractTitle, then it's a zipl config and
2947                     * if not then we go ahead with what's existed prior */
2948                    entryTitle = extractTitle(config, line);
2949                    if (!entryTitle) {
2950                        entryTitle=line->elements[1].item;
2951                    }
2952     printf("title=%s\n", entryTitle);
2953   } else {   } else {
2954   char *title;   char *title;
2955   line = getLineByType(LT_MENUENTRY, entry->lines);   line = getLineByType(LT_MENUENTRY, entry->lines);
# Line 3019  int displayInfo(struct grubConfig *confi Line 3365  int displayInfo(struct grubConfig *confi
3365   printf("lba\n");   printf("lba\n");
3366   }   }
3367    
3368   displayEntry(entry, prefix, i);   displayEntry(config, entry, prefix, i);
3369    
3370   i++;   i++;
3371   while ((entry = findEntryByPath(config, kernel, prefix, &i))) {   while ((entry = findEntryByPath(config, kernel, prefix, &i))) {
3372   displayEntry(entry, prefix, i);   displayEntry(config, entry, prefix, i);
3373   i++;   i++;
3374   }   }
3375    
# Line 3058  struct singleLine *addLineTmpl(struct si Line 3404  struct singleLine *addLineTmpl(struct si
3404      type & (LT_HYPER | LT_KERNEL | LT_MBMODULE | LT_INITRD |      type & (LT_HYPER | LT_KERNEL | LT_MBMODULE | LT_INITRD |
3405      LT_KERNEL_EFI | LT_INITRD_EFI | LT_KERNEL_16 |      LT_KERNEL_EFI | LT_INITRD_EFI | LT_KERNEL_16 |
3406      LT_INITRD_16)) {      LT_INITRD_16)) {
3407   char *rootspec =   const char *prfx = tmplLine->elements[1].item;
3408      getRootSpecifier(tmplLine->elements[1].item);   size_t rs = getRootSpecifier(prfx);
3409   if (rootspec != NULL) {   if (isinitrd(tmplLine->type)) {
3410     for (struct singleLine *l = entry->lines;
3411         rs == 0 && l; l = l->next) {
3412     if (iskernel(l->type)) {
3413     prfx = l->elements[1].item;
3414     rs = getRootSpecifier(prfx);
3415     break;
3416     }
3417     }
3418     }
3419     if (rs > 0) {
3420   free(newLine->elements[1].item);   free(newLine->elements[1].item);
3421   newLine->elements[1].item =   newLine->elements[1].item = sdupprintf(
3422      sdupprintf("%s%s", rootspec, val);   "%.*s%s", (int) rs, prfx, val);
3423   }   }
3424   }   }
3425   }   }
# Line 3353  static void removeElement(struct singleL Line 3709  static void removeElement(struct singleL
3709   line->numElements--;   line->numElements--;
3710  }  }
3711    
3712  int argMatch(const char *one, const char *two)  static int argNameMatch(const char *one, const char *two)
3713  {  {
3714   char *first, *second;   char *first, *second;
3715   char *chptr;   char *chptra, *chptrb;
3716     int rc;
3717    
3718   first = strcpy(alloca(strlen(one) + 1), one);   first = strcpy(alloca(strlen(one) + 1), one);
3719   second = strcpy(alloca(strlen(two) + 1), two);   second = strcpy(alloca(strlen(two) + 1), two);
3720    
3721   chptr = strchr(first, '=');   chptra = strchr(first, '=');
3722   if (chptr)   if (chptra)
3723   *chptr = '\0';   *chptra = '\0';
3724    
3725     chptrb = strchr(second, '=');
3726     if (chptrb)
3727     *chptrb = '\0';
3728    
3729     rc = strcmp(first, second);
3730    
3731     if (chptra)
3732     *chptra = '=';
3733     if (chptrb)
3734     *chptrb = '=';
3735    
3736     return rc;
3737    }
3738    
3739    static int argHasValue(const char *arg)
3740    {
3741     char *chptr;
3742    
3743   chptr = strchr(second, '=');   chptr = strchr(arg, '=');
3744   if (chptr)   if (chptr)
3745   *chptr = '\0';   return 1;
3746     return 0;
3747    }
3748    
3749    static int argValueMatch(const char *one, const char *two)
3750    {
3751     char *first, *second;
3752     char *chptra, *chptrb;
3753    
3754     first = strcpy(alloca(strlen(one) + 1), one);
3755     second = strcpy(alloca(strlen(two) + 1), two);
3756    
3757     chptra = strchr(first, '=');
3758     if (chptra)
3759     chptra += 1;
3760    
3761     chptrb = strchr(second, '=');
3762     if (chptrb)
3763     chptrb += 1;
3764    
3765   return strcmp(first, second);   if (!chptra && !chptrb)
3766     return 0;
3767     else if (!chptra)
3768     return *chptrb - 0;
3769     else if (!chptrb)
3770     return 0 - *chptra;
3771     else
3772     return strcmp(chptra, chptrb);
3773  }  }
3774    
3775  int updateActualImage(struct grubConfig *cfg, const char *image,  int updateActualImage(struct grubConfig *cfg, const char *image,
# Line 3513  int updateActualImage(struct grubConfig Line 3913  int updateActualImage(struct grubConfig
3913   }   }
3914   if (usedElements[i])   if (usedElements[i])
3915   continue;   continue;
3916   if (!argMatch(line->elements[i].item, *arg)) {   if (!argNameMatch(line->elements[i].item, *arg)) {
3917   usedElements[i] = 1;   usedElements[i] = 1;
3918   break;   break;
3919   }   }
# Line 3572  int updateActualImage(struct grubConfig Line 3972  int updateActualImage(struct grubConfig
3972      !strcmp(line->elements[i].item, "--"))      !strcmp(line->elements[i].item, "--"))
3973   /* reached the end of hyper args, stop here */   /* reached the end of hyper args, stop here */
3974   break;   break;
3975   if (!argMatch(line->elements[i].item, *arg)) {   if (!argNameMatch(line->elements[i].item, *arg)) {
3976   removeElement(line, i);   if (!argHasValue(*arg) ||
3977   break;      !argValueMatch(line->elements[i].item, *arg)) {
3978     removeElement(line, i);
3979     break;
3980     }
3981   }   }
3982   }   }
3983   /* handle removing LT_ROOT line too */   /* handle removing LT_ROOT line too */
# Line 4068  int checkForElilo(struct grubConfig *con Line 4471  int checkForElilo(struct grubConfig *con
4471   return 1;   return 1;
4472  }  }
4473    
4474  static char *getRootSpecifier(char *str)  static size_t getRootSpecifier(const char *str)
4475  {  {
4476   char *idx, *rootspec = NULL;   size_t rs = 0;
4477    
4478   if (*str == '(') {   if (*str == '(') {
4479   idx = rootspec = strdup(str);   for (; str[rs] != ')' && !isspace(str[rs]); rs++) {
4480   while (*idx && (*idx != ')') && (!isspace(*idx)))   if (!str[rs])
4481   idx++;   return rs;
4482   *(++idx) = '\0';   }
4483     rs++;
4484   }   }
4485   return rootspec;  
4486     return rs + subvolPrefix(str + rs);
4487  }  }
4488    
4489  static char *getInitrdVal(struct grubConfig *config,  static char *getInitrdVal(struct grubConfig *config,
# Line 4135  int addNewKernel(struct grubConfig *conf Line 4540  int addNewKernel(struct grubConfig *conf
4540   const char *newKernelArgs, const char *newKernelInitrd,   const char *newKernelArgs, const char *newKernelInitrd,
4541   const char **extraInitrds, int extraInitrdCount,   const char **extraInitrds, int extraInitrdCount,
4542   const char *newMBKernel, const char *newMBKernelArgs,   const char *newMBKernel, const char *newMBKernelArgs,
4543   const char *newDevTreePath)   const char *newDevTreePath, int newIndex)
4544  {  {
4545   struct singleEntry *new;   struct singleEntry *new, *entry, *prev = NULL;
4546   struct singleLine *newLine = NULL, *tmplLine = NULL, *masterLine = NULL;   struct singleLine *newLine = NULL, *tmplLine = NULL, *masterLine = NULL;
4547   int needs;   int needs;
4548     char *indexs;
4549   char *chptr;   char *chptr;
4550     int rc;
4551    
4552   if (!newKernelPath)   if (!newKernelPath)
4553   return 0;   return 0;
4554    
4555     rc = asprintf(&indexs, "%d", newIndex);
4556     if (rc < 0)
4557     return 1;
4558    
4559   /* if the newKernelTitle is too long silently munge it into something   /* if the newKernelTitle is too long silently munge it into something
4560   * 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
4561   * it until it looks better */   * it until it looks better */
# Line 4167  int addNewKernel(struct grubConfig *conf Line 4578  int addNewKernel(struct grubConfig *conf
4578   new = malloc(sizeof(*new));   new = malloc(sizeof(*new));
4579   new->skip = 0;   new->skip = 0;
4580   new->multiboot = 0;   new->multiboot = 0;
  new->next = config->entries;  
4581   new->lines = NULL;   new->lines = NULL;
4582   config->entries = new;   entry = config->entries;
4583     for (unsigned int i = 0; i < newIndex; i++) {
4584     if (!entry)
4585     break;
4586     prev = entry;
4587     entry = entry->next;
4588     }
4589     new->next = entry;
4590    
4591     if (prev)
4592     prev->next = new;
4593     else
4594     config->entries = new;
4595    
4596   /* copy/update from the template */   /* copy/update from the template */
4597   needs = NEED_KERNEL | NEED_TITLE;   needs = NEED_KERNEL | NEED_TITLE;
# Line 4632  int addNewKernel(struct grubConfig *conf Line 5054  int addNewKernel(struct grubConfig *conf
5054   abort();   abort();
5055   }   }
5056    
5057   if (updateImage(config, "0", prefix, newKernelArgs, NULL,   if (updateImage(config, indexs, prefix, newKernelArgs, NULL,
5058   newMBKernelArgs, NULL))   newMBKernelArgs, NULL)) {
5059     config->isModified = 1;
5060   return 1;   return 1;
5061     }
5062    
5063   return 0;   return 0;
5064  }  }
# Line 4662  int main(int argc, const char **argv) Line 5086  int main(int argc, const char **argv)
5086   char *newDevTreePath = NULL;   char *newDevTreePath = NULL;
5087   char *newMBKernel = NULL;   char *newMBKernel = NULL;
5088   char *newMBKernelArgs = NULL;   char *newMBKernelArgs = NULL;
5089     int newIndex = 0;
5090   char *removeMBKernelArgs = NULL;   char *removeMBKernelArgs = NULL;
5091   char *removeMBKernel = NULL;   char *removeMBKernel = NULL;
5092   char *bootPrefix = NULL;   char *bootPrefix = NULL;
# Line 4690  int main(int argc, const char **argv) Line 5115  int main(int argc, const char **argv)
5115   {"mbargs", 0, POPT_ARG_STRING, &newMBKernelArgs, 0,   {"mbargs", 0, POPT_ARG_STRING, &newMBKernelArgs, 0,
5116   _("default arguments for the new multiboot kernel or "   _("default arguments for the new multiboot kernel or "
5117     "new arguments for multiboot kernel being updated"), NULL},     "new arguments for multiboot kernel being updated"), NULL},
5118     {"mounts", 0, POPT_ARG_STRING, &mounts, 0,
5119     _("path to fake /proc/mounts file (for testing only)"),
5120     _("mounts")},
5121   {"bad-image-okay", 0, 0, &badImageOkay, 0,   {"bad-image-okay", 0, 0, &badImageOkay, 0,
5122   _   _
5123   ("don't sanity check images in boot entries (for testing only)"),   ("don't sanity check images in boot entries (for testing only)"),
5124   NULL},   NULL},
5125   {"boot-filesystem", 0, POPT_ARG_STRING, &bootPrefix, 0,   {"boot-filesystem", 0, POPT_ARG_STRING, &bootPrefix, 0,
5126   _   _
5127   ("filestystem which contains /boot directory (for testing only)"),   ("filesystem which contains /boot directory (for testing only)"),
5128   _("bootfs")},   _("bootfs")},
5129  #if defined(__i386__) || defined(__x86_64__) || defined (__powerpc64__) || defined (__ia64__)  #if defined(__i386__) || defined(__x86_64__) || defined (__powerpc64__) || defined (__ia64__)
5130   {"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 5196  int main(int argc, const char **argv)
5196   {"set-default-index", 0, POPT_ARG_INT, &defaultIndex, 0,   {"set-default-index", 0, POPT_ARG_INT, &defaultIndex, 0,
5197   _("make the given entry index the default entry"),   _("make the given entry index the default entry"),
5198   _("entry-index")},   _("entry-index")},
5199     {"set-index", 0, POPT_ARG_INT, &newIndex, 0,
5200     _("use the given index when creating a new entry"),
5201     _("entry-index")},
5202   {"silo", 0, POPT_ARG_NONE, &configureSilo, 0,   {"silo", 0, POPT_ARG_NONE, &configureSilo, 0,
5203   _("configure silo bootloader")},   _("configure silo bootloader")},
5204   {"title", 0, POPT_ARG_STRING, &newKernelTitle, 0,   {"title", 0, POPT_ARG_STRING, &newKernelTitle, 0,
# Line 4795  int main(int argc, const char **argv) Line 5226  int main(int argc, const char **argv)
5226   exit(1);   exit(1);
5227   }   }
5228   saved_command_line[0] = '\0';   saved_command_line[0] = '\0';
5229     int cmdline_len = 0, arg_len;
5230   for (int j = 1; j < argc; j++) {   for (int j = 1; j < argc; j++) {
5231   strcat(saved_command_line, argv[j]);   arg_len = strlen(argv[j]);
5232   strncat(saved_command_line, j == argc - 1 ? "" : " ", 1);   memcpy(saved_command_line + cmdline_len, argv[j], arg_len);
5233     cmdline_len += arg_len;
5234     if (j != argc - 1) {
5235     memcpy(saved_command_line + cmdline_len, " ", 1);
5236     cmdline_len++;
5237     }
5238    
5239   }   }
5240     saved_command_line[cmdline_len] = '\0';
5241    
5242   optCon = poptGetContext("grubby", argc, argv, options, 0);   optCon = poptGetContext("grubby", argc, argv, options, 0);
5243   poptReadDefaultConfig(optCon, 1);   poptReadDefaultConfig(optCon, 1);
# Line 4871  int main(int argc, const char **argv) Line 5310  int main(int argc, const char **argv)
5310   if (!cfi) {   if (!cfi) {
5311   if (grub2FindConfig(&grub2ConfigType)) {   if (grub2FindConfig(&grub2ConfigType)) {
5312   cfi = &grub2ConfigType;   cfi = &grub2ConfigType;
5313     configureGrub2 = 1;
5314   if (envPath)   if (envPath)
5315   cfi->envFile = envPath;   cfi->envFile = envPath;
5316   } else   } else {
5317  #ifdef __ia64__  #ifdef __ia64__
5318   cfi = &eliloConfigType;   cfi = &eliloConfigType;
5319  #elif __powerpc__   configureLilo = 1;
5320    #elif defined(__powerpc__)
5321   cfi = &yabootConfigType;   cfi = &yabootConfigType;
5322  #elif __sparc__   configureYaboot = 1;
5323    #elif defined(__sparc__)
5324   cfi = &siloConfigType;   cfi = &siloConfigType;
5325  #elif __s390__   configureSilo = 1;
5326    #elif defined(__s390__) || defined(__s390x__)
5327   cfi = &ziplConfigType;   cfi = &ziplConfigType;
5328  #elif __s390x__   configureZipl = 1;
  cfi = &ziplConfigtype;  
5329  #else  #else
5330   cfi = &grubConfigType;   cfi = &grubConfigType;
5331     configureGrub = 1;
5332  #endif  #endif
5333     }
5334   }   }
5335    
5336   if (!grubConfig) {   if (!grubConfig) {
# Line 5080  int main(int argc, const char **argv) Line 5524  int main(int argc, const char **argv)
5524   if (displayDefault) {   if (displayDefault) {
5525   struct singleLine *line;   struct singleLine *line;
5526   struct singleEntry *entry;   struct singleEntry *entry;
5527   char *rootspec;   size_t rs;
5528    
5529   if (config->defaultImage == -1)   if (config->defaultImage == NO_DEFAULT_ENTRY)
5530   return 0;   return 0;
5531   if (config->defaultImage == DEFAULT_SAVED_GRUB2 &&   if (config->defaultImage == DEFAULT_SAVED_GRUB2 &&
5532      cfi->defaultIsSaved)      cfi->defaultIsSaved)
5533   config->defaultImage = 0;   config->defaultImage = FIRST_ENTRY_INDEX;
5534   entry = findEntryByIndex(config, config->defaultImage);   entry = findEntryByIndex(config, config->defaultImage);
5535   if (!entry)   if (!entry)
5536   return 0;   return 0;
# Line 5099  int main(int argc, const char **argv) Line 5543  int main(int argc, const char **argv)
5543   if (!line)   if (!line)
5544   return 0;   return 0;
5545    
5546   rootspec = getRootSpecifier(line->elements[1].item);   rs = getRootSpecifier(line->elements[1].item);
5547   printf("%s%s\n", bootPrefix, line->elements[1].item +   printf("%s%s\n", bootPrefix, line->elements[1].item + rs);
        ((rootspec != NULL) ? strlen(rootspec) : 0));  
5548    
5549   return 0;   return 0;
5550    
# Line 5109  int main(int argc, const char **argv) Line 5552  int main(int argc, const char **argv)
5552   struct singleLine *line;   struct singleLine *line;
5553   struct singleEntry *entry;   struct singleEntry *entry;
5554    
5555   if (config->defaultImage == -1)   if (config->defaultImage == NO_DEFAULT_ENTRY)
5556   return 0;   return 0;
5557   if (config->defaultImage == DEFAULT_SAVED_GRUB2 &&   if (config->defaultImage == DEFAULT_SAVED_GRUB2 &&
5558      cfi->defaultIsSaved)      cfi->defaultIsSaved)
5559   config->defaultImage = 0;   config->defaultImage = FIRST_ENTRY_INDEX;
5560   entry = findEntryByIndex(config, config->defaultImage);   entry = findEntryByIndex(config, config->defaultImage);
5561   if (!entry)   if (!entry)
5562   return 0;   return 0;
# Line 5143  int main(int argc, const char **argv) Line 5586  int main(int argc, const char **argv)
5586   return 0;   return 0;
5587    
5588   } else if (displayDefaultIndex) {   } else if (displayDefaultIndex) {
5589   if (config->defaultImage == -1)   if (config->defaultImage == NO_DEFAULT_ENTRY)
5590   return 0;   return 0;
5591   if (config->defaultImage == DEFAULT_SAVED_GRUB2 &&   if (config->defaultImage == DEFAULT_SAVED_GRUB2 &&
5592      cfi->defaultIsSaved)      cfi->defaultIsSaved)
5593   config->defaultImage = 0;   config->defaultImage = FIRST_ENTRY_INDEX;
5594   printf("%i\n", config->defaultImage);   printf("%i\n", config->defaultImage);
5595   return 0;   return 0;
5596    
# Line 5163  int main(int argc, const char **argv) Line 5606  int main(int argc, const char **argv)
5606   markRemovedImage(config, removeKernelPath, bootPrefix);   markRemovedImage(config, removeKernelPath, bootPrefix);
5607   markRemovedImage(config, removeMBKernel, bootPrefix);   markRemovedImage(config, removeMBKernel, bootPrefix);
5608   setDefaultImage(config, newKernelPath != NULL, defaultKernel,   setDefaultImage(config, newKernelPath != NULL, defaultKernel,
5609   makeDefault, bootPrefix, flags, defaultIndex);   makeDefault, bootPrefix, flags, defaultIndex,
5610     newIndex);
5611   setFallbackImage(config, newKernelPath != NULL);   setFallbackImage(config, newKernelPath != NULL);
5612   if (updateImage(config, updateKernelPath, bootPrefix, newKernelArgs,   if (updateImage(config, updateKernelPath, bootPrefix, newKernelArgs,
5613   removeArgs, newMBKernelArgs, removeMBKernelArgs))   removeArgs, newMBKernelArgs, removeMBKernelArgs))
# Line 5183  int main(int argc, const char **argv) Line 5627  int main(int argc, const char **argv)
5627   if (addNewKernel(config, template, bootPrefix, newKernelPath,   if (addNewKernel(config, template, bootPrefix, newKernelPath,
5628   newKernelTitle, newKernelArgs, newKernelInitrd,   newKernelTitle, newKernelArgs, newKernelInitrd,
5629   (const char **)extraInitrds, extraInitrdCount,   (const char **)extraInitrds, extraInitrdCount,
5630   newMBKernel, newMBKernelArgs, newDevTreePath))   newMBKernel, newMBKernelArgs, newDevTreePath,
5631     newIndex))
5632   return 1;   return 1;
5633    
5634   if (numEntries(config) == 0) {   if (numEntries(config) == 0) {

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