Magellan Linux

Diff of /trunk/grubby/grubby.c

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

revision 3018 by niro, Tue Jun 27 14:37:30 2017 UTC revision 3136 by niro, Tue Jul 7 11:09:37 2020 UTC
# Line 681  struct grubConfig { Line 681  struct grubConfig {
681   int fallbackImage; /* just like defaultImage */   int fallbackImage; /* just like defaultImage */
682   int flags;   int flags;
683   struct configFileInfo *cfi;   struct configFileInfo *cfi;
684     int isModified; /* assumes only one entry added
685       per invocation of grubby */
686  };  };
687    
688  blkid_cache blkid;  blkid_cache blkid;
# Line 1300  static struct grubConfig *readConfig(con Line 1302  static struct grubConfig *readConfig(con
1302   cfg->theLines = NULL;   cfg->theLines = NULL;
1303   cfg->entries = NULL;   cfg->entries = NULL;
1304   cfg->fallbackImage = 0;   cfg->fallbackImage = 0;
1305     cfg->isModified = 0;
1306    
1307   /* copy everything we have */   /* copy everything we have */
1308   while (*head) {   while (*head) {
# Line 1709  static void writeDefault(FILE * out, cha Line 1712  static void writeDefault(FILE * out, cha
1712   fprintf(out, "%sset default=\"${saved_entry}\"\n", indent);   fprintf(out, "%sset default=\"${saved_entry}\"\n", indent);
1713   if (cfg->defaultImage >= FIRST_ENTRY_INDEX && cfg->cfi->setEnv) {   if (cfg->defaultImage >= FIRST_ENTRY_INDEX && cfg->cfi->setEnv) {
1714   char *title;   char *title;
1715   entry = findEntryByIndex(cfg, cfg->defaultImage);   int trueIndex, currentIndex;
1716    
1717     trueIndex = 0;
1718     currentIndex = 0;
1719    
1720     while ((entry = findEntryByIndex(cfg, currentIndex))) {
1721     if (!entry->skip) {
1722     if (trueIndex == cfg->defaultImage) {
1723     break;
1724     }
1725     trueIndex++;
1726     }
1727     currentIndex++;
1728     }
1729   line = getLineByType(LT_MENUENTRY, entry->lines);   line = getLineByType(LT_MENUENTRY, entry->lines);
1730   if (!line)   if (!line)
1731   line = getLineByType(LT_TITLE, entry->lines);   line = getLineByType(LT_TITLE, entry->lines);
# Line 1776  static int writeConfig(struct grubConfig Line 1792  static int writeConfig(struct grubConfig
1792   int needs = MAIN_DEFAULT;   int needs = MAIN_DEFAULT;
1793   struct stat sb;   struct stat sb;
1794   int i;   int i;
1795     int rc = 0;
1796    
1797   if (!strcmp(outName, "-")) {   if (!strcmp(outName, "-")) {
1798   out = stdout;   out = stdout;
# Line 1890  static int writeConfig(struct grubConfig Line 1907  static int writeConfig(struct grubConfig
1907   }   }
1908    
1909   if (tmpOutName) {   if (tmpOutName) {
1910   if (rename(tmpOutName, outName)) {   /* write userspace buffers */
1911   fprintf(stderr,   if (fflush(out))
1912   _("grubby: error moving %s to %s: %s\n"),   rc = 1;
1913   tmpOutName, outName, strerror(errno));  
1914   unlink(outName);   /* purge the write-back cache with fsync() */
1915   return 1;   if (fsync(fileno(out)))
1916     rc = 1;
1917    
1918     if (fclose(out))
1919     rc = 1;
1920    
1921     if (rc == 0 && rename(tmpOutName, outName)) {
1922     unlink(tmpOutName);
1923     rc = 1;
1924   }   }
1925    
1926     /* fsync() the destination directory after rename */
1927     if (rc == 0) {
1928     int dirfd;
1929    
1930     dirfd = open(dirname(strdupa(outName)), O_RDONLY);
1931     if (dirfd < 0)
1932     rc = 1;
1933     else if (fsync(dirfd))
1934     rc = 1;
1935    
1936     if (dirfd >= 0)
1937     close(dirfd);
1938     }
1939    
1940     if (rc == 1)
1941     fprintf(stderr,
1942     _("grubby: error flushing data: %m\n"));
1943   }   }
1944    
1945   return 0;   return rc;
1946  }  }
1947    
1948  static int numEntries(struct grubConfig *cfg)  static int numEntries(struct grubConfig *cfg)
# Line 2436  struct singleEntry *findTemplate(struct Line 2479  struct singleEntry *findTemplate(struct
2479   index = 0;   index = 0;
2480   while ((entry = findEntryByIndex(cfg, index))) {   while ((entry = findEntryByIndex(cfg, index))) {
2481   if (suitableImage(entry, prefix, skipRemoved, flags)) {   if (suitableImage(entry, prefix, skipRemoved, flags)) {
2482   int j;   int j, unmodifiedIndex;
2483   for (j = 0; j < index; j++) {  
2484     unmodifiedIndex = index;
2485    
2486     for (j = 0; j < unmodifiedIndex; j++) {
2487   entry2 = findEntryByIndex(cfg, j);   entry2 = findEntryByIndex(cfg, j);
2488   if (entry2->skip)   if (entry2->skip)
2489   index--;   index--;
# Line 2498  void markRemovedImage(struct grubConfig Line 2544  void markRemovedImage(struct grubConfig
2544   entry->skip = 1;   entry->skip = 1;
2545  }  }
2546    
2547  void setDefaultImage(struct grubConfig *config, int isUserSpecifiedKernelPath,  void setDefaultImage(struct grubConfig *config, int isAddingBootEntry,
2548       const char *defaultKernelPath, int newBootEntryIsDefault,       const char *defaultKernelPath, int newBootEntryIsDefault,
2549       const char *prefix, int flags, int newDefaultBootEntryIndex)       const char *prefix, int flags,
2550         int newDefaultBootEntryIndex, int newBootEntryIndex)
2551  {  {
2552   struct singleEntry *entry, *entry2, *newDefault;   struct singleEntry *bootEntry, *newDefault;
2553   int i, j;   int indexToVerify, firstKernelEntryIndex, currentLookupIndex;
2554    
2555            /* initialize */
2556            currentLookupIndex = FIRST_ENTRY_INDEX;
2557    
2558     /* handle the two cases where the user explictly picks the default
2559     * boot entry index as it would exist post-modification */
2560    
2561     /* Case 1: user chose to make the latest boot entry the default */
2562   if (newBootEntryIsDefault) {   if (newBootEntryIsDefault) {
2563   config->defaultImage = FIRST_ENTRY_INDEX;   config->defaultImage = newBootEntryIndex;
2564   return;   return;
2565   } else if ((newDefaultBootEntryIndex >= 0) && config->cfi->defaultIsIndex) {   }
2566   if (findEntryByIndex(config, newDefaultBootEntryIndex))  
2567     /* Case 2: user picked an arbitrary index as the default boot entry */
2568     if (newDefaultBootEntryIndex >= FIRST_ENTRY_INDEX) {
2569     indexToVerify = newDefaultBootEntryIndex;
2570    
2571     /* user chose to make latest boot entry the default */
2572     if (newDefaultBootEntryIndex == newBootEntryIndex) {
2573     config->defaultImage = newBootEntryIndex;
2574     return;
2575     }
2576    
2577     /* the user picks the default index based on the
2578     * order of the bootloader configuration after
2579     * modification; ensure we are checking for the
2580     * existence of the correct entry */
2581     if (newBootEntryIndex < newDefaultBootEntryIndex) {
2582     if (!config->isModified)
2583     indexToVerify--;
2584     }
2585    
2586     /* verify the user selected index will exist */
2587     if (findEntryByIndex(config, indexToVerify)) {
2588   config->defaultImage = newDefaultBootEntryIndex;   config->defaultImage = newDefaultBootEntryIndex;
2589   else   } else {
2590   config->defaultImage = NO_DEFAULT_ENTRY;   config->defaultImage = NO_DEFAULT_ENTRY;
2591     }
2592    
2593   return;   return;
2594   } else if (defaultKernelPath) {   }
2595   i = 0;  
2596   if (findEntryByPath(config, defaultKernelPath, prefix, &i)) {   /* handle cases where the index value may shift */
2597   config->defaultImage = i;  
2598   } else {   /* check validity of existing default or first-entry-found
2599       selection */
2600     if (defaultKernelPath) {
2601                    /* we must initialize this */
2602                    firstKernelEntryIndex = 0;
2603     /* user requested first-entry-found */
2604     if (!findEntryByPath(config, defaultKernelPath,
2605         prefix, &firstKernelEntryIndex)) {
2606     /* don't change default if can't find match */
2607   config->defaultImage = NO_DEFAULT_ENTRY;   config->defaultImage = NO_DEFAULT_ENTRY;
2608   return;   return;
2609   }   }
  }  
2610    
2611   /* defaultImage now points to what we'd like to use, but before any   config->defaultImage = firstKernelEntryIndex;
  * order changes */  
  if ((config->defaultImage == DEFAULT_SAVED) ||  
     (config->defaultImage == DEFAULT_SAVED_GRUB2))  
  /* default is set to saved, we don't want to change it */  
  return;  
2612    
2613   if (config->defaultImage >= FIRST_ENTRY_INDEX)   /* this is where we start looking for decrement later */
2614   entry = findEntryByIndex(config, config->defaultImage);   currentLookupIndex = config->defaultImage;
  else  
  entry = NULL;  
2615    
2616   if (entry && !entry->skip) {   if (isAddingBootEntry && !config->isModified &&
2617   /* we can preserve the default */      (newBootEntryIndex < config->defaultImage)) {
2618   if (isUserSpecifiedKernelPath)   /* increment because new entry added before default */
2619   config->defaultImage++;   config->defaultImage++;
   
  /* count the number of entries erased before this one */  
  for (j = 0; j < config->defaultImage; j++) {  
  entry2 = findEntryByIndex(config, j);  
  if (entry2->skip)  
  config->defaultImage--;  
2620   }   }
  } else if (isUserSpecifiedKernelPath) {  
  config->defaultImage = FIRST_ENTRY_INDEX;  
2621   } else {   } else {
2622   /* Either we just erased the default (or the default line was                  /* check to see if the default is stored in the environment */
2623   * bad to begin with) and didn't put a new one in. We'll use                  if (config->defaultImage < FIRST_ENTRY_INDEX) {
2624   * the first valid image. */                      if (config->defaultImage == DEFAULT_SAVED || config->defaultImage == DEFAULT_SAVED_GRUB2)
2625                        {
2626                            if (config->cfi->defaultIsSaved) {
2627                                if (config->cfi->getEnv) {
2628                                    char *defaultTitle = config->cfi->getEnv(config->cfi, "saved_entry");
2629    
2630                                    if (defaultTitle) {
2631                                        if (isnumber(defaultTitle)) {
2632                                            currentLookupIndex = atoi(defaultTitle);
2633                                        } else {
2634                                            findEntryByTitle(config, defaultTitle, &currentLookupIndex);
2635                                        }
2636                                        /* set the default Image to an actual index */
2637                                        config->defaultImage = currentLookupIndex;
2638                                    }
2639                                }
2640                             }
2641                        }
2642                    } else {
2643                            /* use pre-existing default entry from the file*/
2644                            currentLookupIndex = config->defaultImage;
2645                    }
2646    
2647     if (isAddingBootEntry
2648        && (newBootEntryIndex <= config->defaultImage)) {
2649     config->defaultImage++;
2650    
2651     if (config->isModified) {
2652     currentLookupIndex++;
2653     }
2654     }
2655     }
2656    
2657     /* sanity check - is this entry index valid? */
2658     bootEntry = findEntryByIndex(config, currentLookupIndex);
2659    
2660     if ((bootEntry && bootEntry->skip) || !bootEntry) {
2661     /* entry is to be skipped or is invalid */
2662     if (isAddingBootEntry) {
2663     config->defaultImage = newBootEntryIndex;
2664     return;
2665     }
2666   newDefault =   newDefault =
2667      findTemplate(config, prefix, &config->defaultImage, 1,      findTemplate(config, prefix, &config->defaultImage, 1,
2668   flags);   flags);
2669   if (!newDefault)   if (!newDefault) {
2670   config->defaultImage = NO_DEFAULT_ENTRY;   config->defaultImage = NO_DEFAULT_ENTRY;
2671     }
2672    
2673     return;
2674     }
2675    
2676     currentLookupIndex--;
2677    
2678     /* decrement index by the total number of entries deleted */
2679    
2680     for (indexToVerify = currentLookupIndex;
2681         indexToVerify >= FIRST_ENTRY_INDEX; indexToVerify--) {
2682    
2683     bootEntry = findEntryByIndex(config, indexToVerify);
2684    
2685     if (bootEntry && bootEntry->skip) {
2686     config->defaultImage--;
2687     }
2688   }   }
2689  }  }
2690    
# Line 2586  void setFallbackImage(struct grubConfig Line 2713  void setFallbackImage(struct grubConfig
2713   }   }
2714  }  }
2715    
2716  void displayEntry(struct singleEntry *entry, const char *prefix, int index)  void displayEntry(struct grubConfig *config, struct singleEntry *entry, const char *prefix, int index)
2717  {  {
2718   struct singleLine *line;   struct singleLine *line;
2719   char *root = NULL;   char *root = NULL;
# Line 2682  void displayEntry(struct singleEntry *en Line 2809  void displayEntry(struct singleEntry *en
2809    
2810   line = getLineByType(LT_TITLE, entry->lines);   line = getLineByType(LT_TITLE, entry->lines);
2811   if (line) {   if (line) {
2812   printf("title=%s\n", line->elements[1].item);                  char *entryTitle;
2813                    /* if we can extractTitle, then it's a zipl config and
2814                     * if not then we go ahead with what's existed prior */
2815                    entryTitle = extractTitle(config, line);
2816                    if (!entryTitle) {
2817                        entryTitle=line->elements[1].item;
2818                    }
2819     printf("title=%s\n", entryTitle);
2820   } else {   } else {
2821   char *title;   char *title;
2822   line = getLineByType(LT_MENUENTRY, entry->lines);   line = getLineByType(LT_MENUENTRY, entry->lines);
# Line 3098  int displayInfo(struct grubConfig *confi Line 3232  int displayInfo(struct grubConfig *confi
3232   printf("lba\n");   printf("lba\n");
3233   }   }
3234    
3235   displayEntry(entry, prefix, i);   displayEntry(config, entry, prefix, i);
3236    
3237   i++;   i++;
3238   while ((entry = findEntryByPath(config, kernel, prefix, &i))) {   while ((entry = findEntryByPath(config, kernel, prefix, &i))) {
3239   displayEntry(entry, prefix, i);   displayEntry(config, entry, prefix, i);
3240   i++;   i++;
3241   }   }
3242    
# Line 3432  static void removeElement(struct singleL Line 3566  static void removeElement(struct singleL
3566   line->numElements--;   line->numElements--;
3567  }  }
3568    
3569  int argMatch(const char *one, const char *two)  static int argNameMatch(const char *one, const char *two)
3570  {  {
3571   char *first, *second;   char *first, *second;
3572   char *chptr;   char *chptra, *chptrb;
3573     int rc;
3574    
3575   first = strcpy(alloca(strlen(one) + 1), one);   first = strcpy(alloca(strlen(one) + 1), one);
3576   second = strcpy(alloca(strlen(two) + 1), two);   second = strcpy(alloca(strlen(two) + 1), two);
3577    
3578   chptr = strchr(first, '=');   chptra = strchr(first, '=');
3579   if (chptr)   if (chptra)
3580   *chptr = '\0';   *chptra = '\0';
3581    
3582     chptrb = strchr(second, '=');
3583     if (chptrb)
3584     *chptrb = '\0';
3585    
3586     rc = strcmp(first, second);
3587    
3588     if (chptra)
3589     *chptra = '=';
3590     if (chptrb)
3591     *chptrb = '=';
3592    
3593   chptr = strchr(second, '=');   return rc;
3594    }
3595    
3596    static int argHasValue(const char *arg)
3597    {
3598     char *chptr;
3599    
3600     chptr = strchr(arg, '=');
3601   if (chptr)   if (chptr)
3602   *chptr = '\0';   return 1;
3603     return 0;
3604    }
3605    
3606   return strcmp(first, second);  static int argValueMatch(const char *one, const char *two)
3607    {
3608     char *first, *second;
3609     char *chptra, *chptrb;
3610    
3611     first = strcpy(alloca(strlen(one) + 1), one);
3612     second = strcpy(alloca(strlen(two) + 1), two);
3613    
3614     chptra = strchr(first, '=');
3615     if (chptra)
3616     chptra += 1;
3617    
3618     chptrb = strchr(second, '=');
3619     if (chptrb)
3620     chptrb += 1;
3621    
3622     if (!chptra && !chptrb)
3623     return 0;
3624     else if (!chptra)
3625     return *chptrb - 0;
3626     else if (!chptrb)
3627     return 0 - *chptra;
3628     else
3629     return strcmp(chptra, chptrb);
3630  }  }
3631    
3632  int updateActualImage(struct grubConfig *cfg, const char *image,  int updateActualImage(struct grubConfig *cfg, const char *image,
# Line 3592  int updateActualImage(struct grubConfig Line 3770  int updateActualImage(struct grubConfig
3770   }   }
3771   if (usedElements[i])   if (usedElements[i])
3772   continue;   continue;
3773   if (!argMatch(line->elements[i].item, *arg)) {   if (!argNameMatch(line->elements[i].item, *arg)) {
3774   usedElements[i] = 1;   usedElements[i] = 1;
3775   break;   break;
3776   }   }
# Line 3651  int updateActualImage(struct grubConfig Line 3829  int updateActualImage(struct grubConfig
3829      !strcmp(line->elements[i].item, "--"))      !strcmp(line->elements[i].item, "--"))
3830   /* reached the end of hyper args, stop here */   /* reached the end of hyper args, stop here */
3831   break;   break;
3832   if (!argMatch(line->elements[i].item, *arg)) {   if (!argNameMatch(line->elements[i].item, *arg)) {
3833   removeElement(line, i);   if (!argHasValue(*arg) ||
3834   break;      !argValueMatch(line->elements[i].item, *arg)) {
3835     removeElement(line, i);
3836     break;
3837     }
3838   }   }
3839   }   }
3840   /* handle removing LT_ROOT line too */   /* handle removing LT_ROOT line too */
# Line 4729  int addNewKernel(struct grubConfig *conf Line 4910  int addNewKernel(struct grubConfig *conf
4910   }   }
4911    
4912   if (updateImage(config, indexs, prefix, newKernelArgs, NULL,   if (updateImage(config, indexs, prefix, newKernelArgs, NULL,
4913   newMBKernelArgs, NULL))   newMBKernelArgs, NULL)) {
4914     config->isModified = 1;
4915   return 1;   return 1;
4916     }
4917    
4918   return 0;   return 0;
4919  }  }
# Line 5263  int main(int argc, const char **argv) Line 5446  int main(int argc, const char **argv)
5446   markRemovedImage(config, removeKernelPath, bootPrefix);   markRemovedImage(config, removeKernelPath, bootPrefix);
5447   markRemovedImage(config, removeMBKernel, bootPrefix);   markRemovedImage(config, removeMBKernel, bootPrefix);
5448   setDefaultImage(config, newKernelPath != NULL, defaultKernel,   setDefaultImage(config, newKernelPath != NULL, defaultKernel,
5449   makeDefault, bootPrefix, flags, defaultIndex);   makeDefault, bootPrefix, flags, defaultIndex,
5450     newIndex);
5451   setFallbackImage(config, newKernelPath != NULL);   setFallbackImage(config, newKernelPath != NULL);
5452   if (updateImage(config, updateKernelPath, bootPrefix, newKernelArgs,   if (updateImage(config, updateKernelPath, bootPrefix, newKernelArgs,
5453   removeArgs, newMBKernelArgs, removeMBKernelArgs))   removeArgs, newMBKernelArgs, removeMBKernelArgs))

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