Magellan Linux

Diff of /trunk/grubby/grubby.c

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

revision 3136 by niro, Tue Jul 7 11:09:37 2020 UTC revision 3150 by niro, Tue Jul 7 11:24:19 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 480  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 701  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 1438  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 1454  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 2118  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 2125  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 2153  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 2250  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 2355  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 3271  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 3621  static int argValueMatch(const char *one Line 3764  static int argValueMatch(const char *one
3764    
3765   if (!chptra && !chptrb)   if (!chptra && !chptrb)
3766   return 0;   return 0;
3767   else if (!chptra)   else if (!chptra && chptrb)
3768   return *chptrb - 0;   return *chptrb - 0;
3769   else if (!chptrb)   else if (!chptrb && chptra)
3770   return 0 - *chptra;   return 0 - *chptra;
3771   else   else
3772   return strcmp(chptra, chptrb);   return strcmp(chptra, chptrb);
# Line 4328  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 4970  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)"),
# Line 5078  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 5154  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 5363  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 == NO_DEFAULT_ENTRY)   if (config->defaultImage == NO_DEFAULT_ENTRY)
5530   return 0;   return 0;
# Line 5382  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    

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