Magellan Linux

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

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

trunk/mkinitrd-magellan/grubby/grubby.c revision 926 by niro, Wed Oct 28 13:29:38 2009 UTC trunk/grubby/grubby.c revision 1694 by niro, Fri Feb 17 23:23:07 2012 UTC
# Line 36  Line 36 
36  #include <signal.h>  #include <signal.h>
37  #include <blkid/blkid.h>  #include <blkid/blkid.h>
38    
39    #ifndef DEBUG
40  #define DEBUG 0  #define DEBUG 0
41    #endif
42    
43  #if DEBUG  #if DEBUG
44  #define dbgPrintf(format, args...) fprintf(stderr, format , ## args)  #define dbgPrintf(format, args...) fprintf(stderr, format , ## args)
# Line 115  struct configFileInfo { Line 117  struct configFileInfo {
117      struct keywordTypes * keywords;      struct keywordTypes * keywords;
118      int defaultIsIndex;      int defaultIsIndex;
119      int defaultSupportSaved;      int defaultSupportSaved;
120      enum lineType_e entrySeparator;      enum lineType_e entryStart;
121      int needsBootPrefix;      int needsBootPrefix;
122      int argsInQuotes;      int argsInQuotes;
123      int maxTitleLength;      int maxTitleLength;
# Line 139  struct keywordTypes grubKeywords[] = { Line 141  struct keywordTypes grubKeywords[] = {
141  };  };
142    
143  struct configFileInfo grubConfigType = {  struct configFileInfo grubConfigType = {
144      "/boot/grub/grub.conf",    /* defaultConfig */      .defaultConfig = "/boot/grub/grub.conf",
145      grubKeywords,    /* keywords */      .keywords = grubKeywords,
146      1,    /* defaultIsIndex */      .defaultIsIndex = 1,
147      1,    /* defaultSupportSaved */      .defaultSupportSaved = 1,
148      LT_TITLE,    /* entrySeparator */      .entryStart = LT_TITLE,
149      1,    /* needsBootPrefix */      .needsBootPrefix = 1,
150      0,    /* argsInQuotes */      .mbHyperFirst = 1,
151      0,    /* maxTitleLength */      .mbInitRdIsModule = 1,
152      0,                                      /* titleBracketed */      .mbAllowExtraInitRds = 1,
     1,                                      /* mbHyperFirst */  
     1,                                      /* mbInitRdIsModule */  
     0,                                      /* mbConcatArgs */  
     1,                                      /* mbAllowExtraInitRds */  
153  };  };
154    
155  struct keywordTypes yabootKeywords[] = {  struct keywordTypes yabootKeywords[] = {
# Line 249  struct keywordTypes extlinuxKeywords[] = Line 247  struct keywordTypes extlinuxKeywords[] =
247  };  };
248  int useextlinuxmenu;  int useextlinuxmenu;
249  struct configFileInfo eliloConfigType = {  struct configFileInfo eliloConfigType = {
250      "/boot/efi/EFI/redhat/elilo.conf",    /* defaultConfig */      .defaultConfig = "/boot/efi/EFI/redhat/elilo.conf",
251      eliloKeywords,    /* keywords */      .keywords = eliloKeywords,
252      0,    /* defaultIsIndex */      .entryStart = LT_KERNEL,
253      0,    /* defaultSupportSaved */      .needsBootPrefix = 1,
254      LT_KERNEL,    /* entrySeparator */      .argsInQuotes = 1,
255      1,                    /* needsBootPrefix */      .mbConcatArgs = 1,
     1,    /* argsInQuotes */  
     0,    /* maxTitleLength */  
     0,                                      /* titleBracketed */  
     0,                                      /* mbHyperFirst */  
     0,                                      /* mbInitRdIsModule */  
     1,                                      /* mbConcatArgs */  
     0,                                      /* mbAllowExtraInitRds */  
256  };  };
257    
258  struct configFileInfo liloConfigType = {  struct configFileInfo liloConfigType = {
259      "/etc/lilo.conf",    /* defaultConfig */      .defaultConfig = "/etc/lilo.conf",
260      liloKeywords,    /* keywords */      .keywords = liloKeywords,
261      0,    /* defaultIsIndex */      .entryStart = LT_KERNEL,
262      0,    /* defaultSupportSaved */      .argsInQuotes = 1,
263      LT_KERNEL,    /* entrySeparator */      .maxTitleLength = 15,
     0,    /* needsBootPrefix */  
     1,    /* argsInQuotes */  
     15,    /* maxTitleLength */  
     0,                                      /* titleBracketed */  
     0,                                      /* mbHyperFirst */  
     0,                                      /* mbInitRdIsModule */  
     0,                                      /* mbConcatArgs */  
     0,                                      /* mbAllowExtraInitRds */  
264  };  };
265    
266  struct configFileInfo yabootConfigType = {  struct configFileInfo yabootConfigType = {
267      "/etc/yaboot.conf",    /* defaultConfig */      .defaultConfig = "/etc/yaboot.conf",
268      yabootKeywords,    /* keywords */      .keywords = yabootKeywords,
269      0,    /* defaultIsIndex */      .entryStart = LT_KERNEL,
270      0,    /* defaultSupportSaved */      .needsBootPrefix = 1,
271      LT_KERNEL,    /* entrySeparator */      .argsInQuotes = 1,
272      1,    /* needsBootPrefix */      .maxTitleLength = 15,
273      1,    /* argsInQuotes */      .mbAllowExtraInitRds = 1,
     15,    /* maxTitleLength */  
     0,                                      /* titleBracketed */  
     0,                                      /* mbHyperFirst */  
     0,                                      /* mbInitRdIsModule */  
     0,                                      /* mbConcatArgs */  
     1,                                      /* mbAllowExtraInitRds */  
274  };  };
275    
276  struct configFileInfo siloConfigType = {  struct configFileInfo siloConfigType = {
277      "/etc/silo.conf",    /* defaultConfig */      .defaultConfig = "/etc/silo.conf",
278      siloKeywords,    /* keywords */      .keywords = siloKeywords,
279      0,    /* defaultIsIndex */      .entryStart = LT_KERNEL,
280      0,    /* defaultSupportSaved */      .needsBootPrefix = 1,
281      LT_KERNEL,    /* entrySeparator */      .argsInQuotes = 1,
282      1,    /* needsBootPrefix */      .maxTitleLength = 15,
     1,    /* argsInQuotes */  
     15,    /* maxTitleLength */  
     0,                                      /* titleBracketed */  
     0,                                      /* mbHyperFirst */  
     0,                                      /* mbInitRdIsModule */  
     0,                                      /* mbConcatArgs */  
     0,                                      /* mbAllowExtraInitRds */  
283  };  };
284    
285  struct configFileInfo ziplConfigType = {  struct configFileInfo ziplConfigType = {
286      "/etc/zipl.conf",    /* defaultConfig */      .defaultConfig = "/etc/zipl.conf",
287      ziplKeywords,    /* keywords */      .keywords = ziplKeywords,
288      0,    /* defaultIsIndex */      .entryStart = LT_TITLE,
289      0,    /* defaultSupportSaved */      .argsInQuotes = 1,
290      LT_TITLE,    /* entrySeparator */      .titleBracketed = 1,
     0,    /* needsBootPrefix */  
     1,    /* argsInQuotes */  
     0,    /* maxTitleLength */  
     1,                                      /* titleBracketed */  
     0,                                      /* mbHyperFirst */  
     0,                                      /* mbInitRdIsModule */  
     0,                                      /* mbConcatArgs */  
     0,                                      /* mbAllowExtraInitRds */  
291  };  };
292    
293  struct configFileInfo extlinuxConfigType = {  struct configFileInfo extlinuxConfigType = {
294      "/boot/extlinux/extlinux.conf",         /* defaultConfig */      .defaultConfig = "/boot/extlinux/extlinux.conf",
295      extlinuxKeywords,                       /* keywords */      .keywords = extlinuxKeywords,
296      0,                                      /* defaultIsIndex */      .entryStart = LT_TITLE,
297      0,                                      /* defaultSupportSaved */      .needsBootPrefix = 1,
298      LT_TITLE,                               /* entrySeparator */      .maxTitleLength = 255,
299      1,                                      /* needsBootPrefix */      .mbAllowExtraInitRds = 1,
     0,                                      /* argsInQuotes */  
     255,                                    /* maxTitleLength */  
     0,                                      /* titleBracketed */  
     0,                                      /* mbHyperFirst */  
     0,                                      /* mbInitRdIsModule */  
     0,                                      /* mbConcatArgs */  
     1,                                      /* mbAllowExtraInitRds */  
300  };  };
301    
302  struct grubConfig {  struct grubConfig {
# Line 356  struct grubConfig { Line 311  struct grubConfig {
311      struct configFileInfo * cfi;      struct configFileInfo * cfi;
312  };  };
313    
314    blkid_cache blkid;
315    
316  struct singleEntry * findEntryByIndex(struct grubConfig * cfg, int index);  struct singleEntry * findEntryByIndex(struct grubConfig * cfg, int index);
317  struct singleEntry * findEntryByPath(struct grubConfig * cfg,  struct singleEntry * findEntryByPath(struct grubConfig * cfg,
318       const char * path, const char * prefix,       const char * path, const char * prefix,
# Line 434  static struct keywordTypes * getKeywordB Line 391  static struct keywordTypes * getKeywordB
391  }  }
392    
393  static char * getpathbyspec(char *device) {  static char * getpathbyspec(char *device) {
     static blkid_cache blkid;  
   
394      if (!blkid)      if (!blkid)
395          blkid_get_cache(&blkid, NULL);          blkid_get_cache(&blkid, NULL);
396    
397      return blkid_get_devname(blkid, device, NULL);      return blkid_get_devname(blkid, device, NULL);
398  }  }
399    
400    static char * getuuidbydev(char *device) {
401        if (!blkid)
402     blkid_get_cache(&blkid, NULL);
403    
404        return blkid_get_tag_value(blkid, "UUID", device);
405    }
406    
407  static enum lineType_e getTypeByKeyword(char * keyword,  static enum lineType_e getTypeByKeyword(char * keyword,
408   struct configFileInfo * cfi) {   struct configFileInfo * cfi) {
409      struct keywordTypes * kw;      struct keywordTypes * kw;
# Line 477  static int isBracketedTitle(struct singl Line 439  static int isBracketedTitle(struct singl
439      return 0;      return 0;
440  }  }
441    
442  static int isEntrySeparator(struct singleLine * line,  static int isEntryStart(struct singleLine * line,
443                              struct configFileInfo * cfi) {                              struct configFileInfo * cfi) {
444      return line->type == cfi->entrySeparator || line->type == LT_OTHER ||      return line->type == cfi->entryStart || line->type == LT_OTHER ||
445   (cfi->titleBracketed && isBracketedTitle(line));   (cfi->titleBracketed && isBracketedTitle(line));
446  }  }
447    
# Line 802  static struct grubConfig * readConfig(co Line 764  static struct grubConfig * readConfig(co
764      cfg->secondaryIndent = strdup(line->indent);      cfg->secondaryIndent = strdup(line->indent);
765   }   }
766    
767   if (isEntrySeparator(line, cfi)) {   if (isEntryStart(line, cfi)) {
768      sawEntry = 1;      sawEntry = 1;
769      if (!entry) {      if (!entry) {
770   cfg->entries = malloc(sizeof(*entry));   cfg->entries = malloc(sizeof(*entry));
# Line 1155  static int numEntries(struct grubConfig Line 1117  static int numEntries(struct grubConfig
1117      return i;      return i;
1118  }  }
1119    
1120    static char *findDiskForRoot()
1121    {
1122        int fd;
1123        char buf[65536];
1124        char *devname;
1125        char *chptr;
1126        int rc;
1127    
1128        if ((fd = open(_PATH_MOUNTED, O_RDONLY)) < 0) {
1129            fprintf(stderr, "grubby: failed to open %s: %s\n",
1130                    _PATH_MOUNTED, strerror(errno));
1131            return NULL;
1132        }
1133    
1134        rc = read(fd, buf, sizeof(buf) - 1);
1135        if (rc <= 0) {
1136            fprintf(stderr, "grubby: failed to read %s: %s\n",
1137                    _PATH_MOUNTED, strerror(errno));
1138            close(fd);
1139            return NULL;
1140        }
1141        close(fd);
1142        buf[rc] = '\0';
1143        chptr = buf;
1144    
1145        while (chptr && chptr != buf+rc) {
1146            devname = chptr;
1147    
1148            /*
1149             * The first column of a mtab entry is the device, but if the entry is a
1150             * special device it won't start with /, so move on to the next line.
1151             */
1152            if (*devname != '/') {
1153                chptr = strchr(chptr, '\n');
1154                if (chptr)
1155                    chptr++;
1156                continue;
1157            }
1158    
1159            /* Seek to the next space */
1160            chptr = strchr(chptr, ' ');
1161            if (!chptr) {
1162                fprintf(stderr, "grubby: error parsing %s: %s\n",
1163                        _PATH_MOUNTED, strerror(errno));
1164                return NULL;
1165            }
1166    
1167            /*
1168             * The second column of a mtab entry is the mount point, we are looking
1169             * for '/' obviously.
1170             */
1171            if (*(++chptr) == '/' && *(++chptr) == ' ') {
1172                /*
1173                 * Move back 2, which is the first space after the device name, set
1174                 * it to \0 so strdup will just get the devicename.
1175                 */
1176                chptr -= 2;
1177                *chptr = '\0';
1178                return strdup(devname);
1179            }
1180    
1181            /* Next line */
1182            chptr = strchr(chptr, '\n');
1183            if (chptr)
1184                chptr++;
1185        }
1186    
1187        return NULL;
1188    }
1189    
1190  int suitableImage(struct singleEntry * entry, const char * bootPrefix,  int suitableImage(struct singleEntry * entry, const char * bootPrefix,
1191    int skipRemoved, int flags) {    int skipRemoved, int flags) {
1192      struct singleLine * line;      struct singleLine * line;
1193      char * fullName;      char * fullName;
1194      int i;      int i;
     struct stat sb, sb2;  
1195      char * dev;      char * dev;
1196      char * rootspec;      char * rootspec;
1197        char * rootdev;
1198    
1199      if (skipRemoved && entry->skip) return 0;      if (skipRemoved && entry->skip) return 0;
1200    
# Line 1212  int suitableImage(struct singleEntry * e Line 1244  int suitableImage(struct singleEntry * e
1244      if (!dev)      if (!dev)
1245          return 0;          return 0;
1246    
1247      i = stat(dev, &sb);      rootdev = findDiskForRoot();
1248      if (i)      if (!rootdev)
1249   return 0;   return 0;
1250    
1251      stat("/", &sb2);      if (!getuuidbydev(rootdev) || !getuuidbydev(dev)) {
1252            free(rootdev);
1253            return 0;
1254        }
1255    
1256      if (sb.st_rdev != sb2.st_dev)      if (strcmp(getuuidbydev(rootdev), getuuidbydev(dev))) {
1257     free(rootdev);
1258          return 0;          return 0;
1259        }
1260    
1261        free(rootdev);
1262    
1263      return 1;      return 1;
1264  }  }
# Line 1895  int updateActualImage(struct grubConfig Line 1934  int updateActualImage(struct grubConfig
1934      const char ** arg;      const char ** arg;
1935      int useKernelArgs, useRoot;      int useKernelArgs, useRoot;
1936      int firstElement;      int firstElement;
1937      int *usedElements, *usedArgs;      int *usedElements;
1938      int doreplace;      int doreplace;
1939    
1940      if (!image) return 0;      if (!image) return 0;
# Line 1930  int updateActualImage(struct grubConfig Line 1969  int updateActualImage(struct grubConfig
1969      useRoot = (getKeywordByType(LT_ROOT, cfg->cfi)      useRoot = (getKeywordByType(LT_ROOT, cfg->cfi)
1970         && !multibootArgs);         && !multibootArgs);
1971    
     for (k = 0, arg = newArgs; *arg; arg++, k++) ;  
     usedArgs = calloc(k, sizeof(*usedArgs));  
   
1972      for (; (entry = findEntryByPath(cfg, image, prefix, &index)); index++) {      for (; (entry = findEntryByPath(cfg, image, prefix, &index)); index++) {
1973    
1974   if (multibootArgs && !entry->multiboot)   if (multibootArgs && !entry->multiboot)
# Line 2008  int updateActualImage(struct grubConfig Line 2044  int updateActualImage(struct grubConfig
2044          usedElements = calloc(line->numElements, sizeof(*usedElements));          usedElements = calloc(line->numElements, sizeof(*usedElements));
2045    
2046   for (k = 0, arg = newArgs; *arg; arg++, k++) {   for (k = 0, arg = newArgs; *arg; arg++, k++) {
             if (usedArgs[k]) continue;  
2047    
2048      doreplace = 1;      doreplace = 1;
2049      for (i = firstElement; i < line->numElements; i++) {      for (i = firstElement; i < line->numElements; i++) {
# Line 2023  int updateActualImage(struct grubConfig Line 2058  int updateActualImage(struct grubConfig
2058                      continue;                      continue;
2059   if (!argMatch(line->elements[i].item, *arg)) {   if (!argMatch(line->elements[i].item, *arg)) {
2060                      usedElements[i]=1;                      usedElements[i]=1;
                     usedArgs[k]=1;  
2061      break;      break;
2062                  }                  }
2063              }              }
# Line 2093  int updateActualImage(struct grubConfig Line 2127  int updateActualImage(struct grubConfig
2127   }   }
2128      }      }
2129    
     free(usedArgs);  
2130      free(newArgs);      free(newArgs);
2131      free(oldArgs);      free(oldArgs);
2132    
# Line 2119  int updateImage(struct grubConfig * cfg, Line 2152  int updateImage(struct grubConfig * cfg,
2152      return rc;      return rc;
2153  }  }
2154    
2155    int updateInitrd(struct grubConfig * cfg, const char * image,
2156                     const char * prefix, const char * initrd) {
2157        struct singleEntry * entry;
2158        struct singleLine * line, * kernelLine;
2159        int index = 0;
2160    
2161        if (!image) return 0;
2162    
2163        for (; (entry = findEntryByPath(cfg, image, prefix, &index)); index++) {
2164            kernelLine = getLineByType(LT_KERNEL, entry->lines);
2165            if (!kernelLine) continue;
2166    
2167            line = getLineByType(LT_INITRD, entry->lines);
2168            if (line)
2169                removeLine(entry, line);
2170            if (prefix) {
2171                int prefixLen = strlen(prefix);
2172                if (!strncmp(initrd, prefix, prefixLen))
2173                    initrd += prefixLen;
2174            }
2175            line = addLine(entry, cfg->cfi, LT_INITRD, kernelLine->indent, initrd);
2176            if (!line) return 1;
2177            break;
2178        }
2179    
2180        return 0;
2181    }
2182    
2183  int checkDeviceBootloader(const char * device, const unsigned char * boot) {  int checkDeviceBootloader(const char * device, const unsigned char * boot) {
2184      int fd;      int fd;
2185      unsigned char bootSect[512];      unsigned char bootSect[512];
# Line 2614  int addNewKernel(struct grubConfig * con Line 2675  int addNewKernel(struct grubConfig * con
2675   /* don't have a template, so start the entry with the   /* don't have a template, so start the entry with the
2676   * appropriate starting line   * appropriate starting line
2677   */   */
2678   switch (config->cfi->entrySeparator) {   switch (config->cfi->entryStart) {
2679      case LT_KERNEL:      case LT_KERNEL:
2680   if (new->multiboot && config->cfi->mbHyperFirst) {   if (new->multiboot && config->cfi->mbHyperFirst) {
2681      /* fall through to LT_HYPER */      /* fall through to LT_HYPER */
# Line 2666  int addNewKernel(struct grubConfig * con Line 2727  int addNewKernel(struct grubConfig * con
2727    
2728      /* add the remainder of the lines, i.e. those that either      /* add the remainder of the lines, i.e. those that either
2729       * weren't present in the template, or in the case of no template,       * weren't present in the template, or in the case of no template,
2730       * all the lines following the entrySeparator.       * all the lines following the entryStart.
2731       */       */
2732      if (needs & NEED_TITLE) {      if (needs & NEED_TITLE) {
2733   newLine = addLine(new, config->cfi, LT_TITLE,   newLine = addLine(new, config->cfi, LT_TITLE,
# Line 2948  int main(int argc, const char ** argv) { Line 3009  int main(int argc, const char ** argv) {
3009      if (newKernelPath && !newKernelTitle) {      if (newKernelPath && !newKernelTitle) {
3010   fprintf(stderr, _("grubby: kernel title must be specified\n"));   fprintf(stderr, _("grubby: kernel title must be specified\n"));
3011   return 1;   return 1;
3012      } else if (!newKernelPath && (newKernelTitle  || newKernelInitrd ||      } else if (!newKernelPath && (newKernelTitle  || copyDefault ||
3013    newKernelInitrd || copyDefault     ||    (newKernelInitrd && !updateKernelPath)||
3014    makeDefault || extraInitrdCount > 0)) {    makeDefault || extraInitrdCount > 0)) {
3015   fprintf(stderr, _("grubby: kernel path expected\n"));   fprintf(stderr, _("grubby: kernel path expected\n"));
3016   return 1;   return 1;
# Line 3082  int main(int argc, const char ** argv) { Line 3143  int main(int argc, const char ** argv) {
3143      setFallbackImage(config, newKernelPath != NULL);      setFallbackImage(config, newKernelPath != NULL);
3144      if (updateImage(config, updateKernelPath, bootPrefix, newKernelArgs,      if (updateImage(config, updateKernelPath, bootPrefix, newKernelArgs,
3145                      removeArgs, newMBKernelArgs, removeMBKernelArgs)) return 1;                      removeArgs, newMBKernelArgs, removeMBKernelArgs)) return 1;
3146        if (updateKernelPath && newKernelInitrd) {
3147                if (updateInitrd(config, updateKernelPath, bootPrefix,
3148                                 newKernelInitrd)) return 1;
3149        }
3150      if (addNewKernel(config, template, bootPrefix, newKernelPath,      if (addNewKernel(config, template, bootPrefix, newKernelPath,
3151                       newKernelTitle, newKernelArgs, newKernelInitrd,                       newKernelTitle, newKernelArgs, newKernelInitrd,
3152                       extraInitrds, extraInitrdCount,                       extraInitrds, extraInitrdCount,

Legend:
Removed from v.926  
changed lines
  Added in v.1694