grubby/SOURCES/0014-Lindent-dammit.patch
2021-09-09 18:05:54 +00:00

9240 lines
254 KiB
Diff

From 446e0e6f0179373ccb2073df62d5552c44a0f36a Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Tue, 18 Aug 2015 10:43:39 -0400
Subject: [PATCH 14/55] Lindent, dammit.
Signed-off-by: Peter Jones <pjones@redhat.com>
---
grubby.c | 8666 ++++++++++++++++++++++++++++--------------------------
1 file changed, 4560 insertions(+), 4106 deletions(-)
diff --git a/grubby.c b/grubby.c
index 70477ba14ee..fe6595b8386 100644
--- a/grubby.c
+++ b/grubby.c
@@ -48,7 +48,7 @@
#define dbgPrintf(format, args...)
#endif
-int debug = 0; /* Currently just for template debugging */
+int debug = 0; /* Currently just for template debugging */
#define _(A) (A)
@@ -70,51 +70,51 @@ char *saved_command_line = NULL;
/* comments get lumped in with indention */
struct lineElement {
- char * item;
- char * indent;
+ char *item;
+ char *indent;
};
-enum lineType_e {
- LT_WHITESPACE = 1 << 0,
- LT_TITLE = 1 << 1,
- LT_KERNEL = 1 << 2,
- LT_INITRD = 1 << 3,
- LT_HYPER = 1 << 4,
- LT_DEFAULT = 1 << 5,
- LT_MBMODULE = 1 << 6,
- LT_ROOT = 1 << 7,
- LT_FALLBACK = 1 << 8,
- LT_KERNELARGS = 1 << 9,
- LT_BOOT = 1 << 10,
- LT_BOOTROOT = 1 << 11,
- LT_LBA = 1 << 12,
- LT_OTHER = 1 << 13,
- LT_GENERIC = 1 << 14,
- LT_ECHO = 1 << 16,
- LT_MENUENTRY = 1 << 17,
- LT_ENTRY_END = 1 << 18,
- LT_SET_VARIABLE = 1 << 19,
- LT_KERNEL_EFI = 1 << 20,
- LT_INITRD_EFI = 1 << 21,
- LT_KERNEL_16 = 1 << 22,
- LT_INITRD_16 = 1 << 23,
- LT_DEVTREE = 1 << 24,
- LT_UNKNOWN = 1 << 25,
+enum lineType_e {
+ LT_WHITESPACE = 1 << 0,
+ LT_TITLE = 1 << 1,
+ LT_KERNEL = 1 << 2,
+ LT_INITRD = 1 << 3,
+ LT_HYPER = 1 << 4,
+ LT_DEFAULT = 1 << 5,
+ LT_MBMODULE = 1 << 6,
+ LT_ROOT = 1 << 7,
+ LT_FALLBACK = 1 << 8,
+ LT_KERNELARGS = 1 << 9,
+ LT_BOOT = 1 << 10,
+ LT_BOOTROOT = 1 << 11,
+ LT_LBA = 1 << 12,
+ LT_OTHER = 1 << 13,
+ LT_GENERIC = 1 << 14,
+ LT_ECHO = 1 << 16,
+ LT_MENUENTRY = 1 << 17,
+ LT_ENTRY_END = 1 << 18,
+ LT_SET_VARIABLE = 1 << 19,
+ LT_KERNEL_EFI = 1 << 20,
+ LT_INITRD_EFI = 1 << 21,
+ LT_KERNEL_16 = 1 << 22,
+ LT_INITRD_16 = 1 << 23,
+ LT_DEVTREE = 1 << 24,
+ LT_UNKNOWN = 1 << 25,
};
struct singleLine {
- char * indent;
- int numElements;
- struct lineElement * elements;
- struct singleLine * next;
- enum lineType_e type;
+ char *indent;
+ int numElements;
+ struct lineElement *elements;
+ struct singleLine *next;
+ enum lineType_e type;
};
struct singleEntry {
- struct singleLine * lines;
- int skip;
- int multiboot;
- struct singleEntry * next;
+ struct singleLine *lines;
+ int skip;
+ int multiboot;
+ struct singleEntry *next;
};
#define GRUBBY_BADIMAGE_OKAY (1 << 0)
@@ -135,1723 +135,1849 @@ struct singleEntry {
#define DEFAULT_SAVED_GRUB2 -3
struct keywordTypes {
- char * key;
- enum lineType_e type;
- char nextChar;
- char separatorChar;
+ char *key;
+ enum lineType_e type;
+ char nextChar;
+ char separatorChar;
};
struct configFileInfo;
-typedef const char *(*findConfigFunc)(struct configFileInfo *);
-typedef const int (*writeLineFunc)(struct configFileInfo *,
- struct singleLine *line);
-typedef char *(*getEnvFunc)(struct configFileInfo *, char *name);
-typedef int (*setEnvFunc)(struct configFileInfo *, char *name, char *value);
+typedef const char *(*findConfigFunc) (struct configFileInfo *);
+typedef const int (*writeLineFunc) (struct configFileInfo *,
+ struct singleLine * line);
+typedef char *(*getEnvFunc) (struct configFileInfo *, char *name);
+typedef int (*setEnvFunc) (struct configFileInfo *, char *name, char *value);
struct configFileInfo {
- char * defaultConfig;
- findConfigFunc findConfig;
- writeLineFunc writeLine;
- getEnvFunc getEnv;
- setEnvFunc setEnv;
- struct keywordTypes * keywords;
- int caseInsensitive;
- int defaultIsIndex;
- int defaultIsVariable;
- int defaultSupportSaved;
- int defaultIsSaved;
- int defaultIsUnquoted;
- enum lineType_e entryStart;
- enum lineType_e entryEnd;
- int needsBootPrefix;
- int argsInQuotes;
- int maxTitleLength;
- int titleBracketed;
- int titlePosition;
- int mbHyperFirst;
- int mbInitRdIsModule;
- int mbConcatArgs;
- int mbAllowExtraInitRds;
- char *envFile;
+ char *defaultConfig;
+ findConfigFunc findConfig;
+ writeLineFunc writeLine;
+ getEnvFunc getEnv;
+ setEnvFunc setEnv;
+ struct keywordTypes *keywords;
+ int caseInsensitive;
+ int defaultIsIndex;
+ int defaultIsVariable;
+ int defaultSupportSaved;
+ int defaultIsSaved;
+ int defaultIsUnquoted;
+ enum lineType_e entryStart;
+ enum lineType_e entryEnd;
+ int needsBootPrefix;
+ int argsInQuotes;
+ int maxTitleLength;
+ int titleBracketed;
+ int titlePosition;
+ int mbHyperFirst;
+ int mbInitRdIsModule;
+ int mbConcatArgs;
+ int mbAllowExtraInitRds;
+ char *envFile;
};
struct keywordTypes grubKeywords[] = {
- { "title", LT_TITLE, ' ' },
- { "root", LT_BOOTROOT, ' ' },
- { "default", LT_DEFAULT, ' ' },
- { "fallback", LT_FALLBACK, ' ' },
- { "kernel", LT_KERNEL, ' ' },
- { "initrd", LT_INITRD, ' ', ' ' },
- { "module", LT_MBMODULE, ' ' },
- { "kernel", LT_HYPER, ' ' },
- { NULL, 0, 0 },
+ {"title", LT_TITLE, ' '},
+ {"root", LT_BOOTROOT, ' '},
+ {"default", LT_DEFAULT, ' '},
+ {"fallback", LT_FALLBACK, ' '},
+ {"kernel", LT_KERNEL, ' '},
+ {"initrd", LT_INITRD, ' ', ' '},
+ {"module", LT_MBMODULE, ' '},
+ {"kernel", LT_HYPER, ' '},
+ {NULL, 0, 0},
};
-const char *grubFindConfig(struct configFileInfo *cfi) {
- static const char *configFiles[] = {
- "/boot/grub/menu.lst",
- "/etc/grub.conf",
- NULL
- };
- static int i = -1;
+const char *grubFindConfig(struct configFileInfo *cfi)
+{
+ static const char *configFiles[] = {
+ "/boot/grub/menu.lst",
+ "/etc/grub.conf",
+ NULL
+ };
+ static int i = -1;
- if (i == -1) {
- for (i = 0; configFiles[i] != NULL; i++) {
- dbgPrintf("Checking \"%s\": ", configFiles[i]);
- if (!access(configFiles[i], R_OK)) {
- dbgPrintf("found\n");
- return configFiles[i];
- }
- dbgPrintf("not found\n");
+ if (i == -1) {
+ for (i = 0; configFiles[i] != NULL; i++) {
+ dbgPrintf("Checking \"%s\": ", configFiles[i]);
+ if (!access(configFiles[i], R_OK)) {
+ dbgPrintf("found\n");
+ return configFiles[i];
+ }
+ dbgPrintf("not found\n");
+ }
}
- }
- return configFiles[i];
+ return configFiles[i];
}
struct configFileInfo grubConfigType = {
- .findConfig = grubFindConfig,
- .keywords = grubKeywords,
- .defaultIsIndex = 1,
- .defaultSupportSaved = 1,
- .entryStart = LT_TITLE,
- .needsBootPrefix = 1,
- .mbHyperFirst = 1,
- .mbInitRdIsModule = 1,
- .mbAllowExtraInitRds = 1,
- .titlePosition = 1,
+ .findConfig = grubFindConfig,
+ .keywords = grubKeywords,
+ .defaultIsIndex = 1,
+ .defaultSupportSaved = 1,
+ .entryStart = LT_TITLE,
+ .needsBootPrefix = 1,
+ .mbHyperFirst = 1,
+ .mbInitRdIsModule = 1,
+ .mbAllowExtraInitRds = 1,
+ .titlePosition = 1,
};
struct keywordTypes grub2Keywords[] = {
- { "menuentry", LT_MENUENTRY, ' ' },
- { "}", LT_ENTRY_END, ' ' },
- { "echo", LT_ECHO, ' ' },
- { "set", LT_SET_VARIABLE,' ', '=' },
- { "root", LT_BOOTROOT, ' ' },
- { "default", LT_DEFAULT, ' ' },
- { "fallback", LT_FALLBACK, ' ' },
- { "linux", LT_KERNEL, ' ' },
- { "linuxefi", LT_KERNEL_EFI, ' ' },
- { "linux16", LT_KERNEL_16, ' ' },
- { "initrd", LT_INITRD, ' ', ' ' },
- { "initrdefi", LT_INITRD_EFI, ' ', ' ' },
- { "initrd16", LT_INITRD_16, ' ', ' ' },
- { "module", LT_MBMODULE, ' ' },
- { "kernel", LT_HYPER, ' ' },
- { "devicetree", LT_DEVTREE, ' ' },
- { NULL, 0, 0 },
+ {"menuentry", LT_MENUENTRY, ' '},
+ {"}", LT_ENTRY_END, ' '},
+ {"echo", LT_ECHO, ' '},
+ {"set", LT_SET_VARIABLE, ' ', '='},
+ {"root", LT_BOOTROOT, ' '},
+ {"default", LT_DEFAULT, ' '},
+ {"fallback", LT_FALLBACK, ' '},
+ {"linux", LT_KERNEL, ' '},
+ {"linuxefi", LT_KERNEL_EFI, ' '},
+ {"linux16", LT_KERNEL_16, ' '},
+ {"initrd", LT_INITRD, ' ', ' '},
+ {"initrdefi", LT_INITRD_EFI, ' ', ' '},
+ {"initrd16", LT_INITRD_16, ' ', ' '},
+ {"module", LT_MBMODULE, ' '},
+ {"kernel", LT_HYPER, ' '},
+ {"devicetree", LT_DEVTREE, ' '},
+ {NULL, 0, 0},
};
-const char *grub2FindConfig(struct configFileInfo *cfi) {
- static const char *configFiles[] = {
- "/etc/grub2-efi.cfg",
- "/etc/grub2.cfg",
- "/boot/grub2/grub.cfg",
- "/boot/grub2-efi/grub.cfg",
- NULL
- };
- static int i = -1;
- static const char *grub_cfg = "/boot/grub/grub.cfg";
- int rc = -1;
+const char *grub2FindConfig(struct configFileInfo *cfi)
+{
+ static const char *configFiles[] = {
+ "/etc/grub2-efi.cfg",
+ "/etc/grub2.cfg",
+ "/boot/grub2/grub.cfg",
+ "/boot/grub2-efi/grub.cfg",
+ NULL
+ };
+ static int i = -1;
+ static const char *grub_cfg = "/boot/grub/grub.cfg";
+ int rc = -1;
- if (i == -1) {
- for (i = 0; configFiles[i] != NULL; i++) {
- dbgPrintf("Checking \"%s\": ", configFiles[i]);
- if ((rc = access(configFiles[i], R_OK))) {
- if (errno == EACCES) {
- printf("Unable to access bootloader configuration file "
- "\"%s\": %m\n", configFiles[i]);
- exit(1);
+ if (i == -1) {
+ for (i = 0; configFiles[i] != NULL; i++) {
+ dbgPrintf("Checking \"%s\": ", configFiles[i]);
+ if ((rc = access(configFiles[i], R_OK))) {
+ if (errno == EACCES) {
+ printf
+ ("Unable to access bootloader configuration file "
+ "\"%s\": %m\n", configFiles[i]);
+ exit(1);
+ }
+ continue;
+ } else {
+ dbgPrintf("found\n");
+ return configFiles[i];
+ }
}
- continue;
- } else {
+ }
+
+ /* Ubuntu renames grub2 to grub, so check for the grub.d directory
+ * that isn't in grub1, and if it exists, return the config file path
+ * that they use. */
+ if (configFiles[i] == NULL && !access("/etc/grub.d/", R_OK)) {
dbgPrintf("found\n");
- return configFiles[i];
- }
+ return grub_cfg;
}
- }
- /* Ubuntu renames grub2 to grub, so check for the grub.d directory
- * that isn't in grub1, and if it exists, return the config file path
- * that they use. */
- if (configFiles[i] == NULL && !access("/etc/grub.d/", R_OK)) {
- dbgPrintf("found\n");
- return grub_cfg;
- }
-
- dbgPrintf("not found\n");
- return configFiles[i];
+ dbgPrintf("not found\n");
+ return configFiles[i];
}
/* kind of hacky. It'll give the first 1024 bytes, ish. */
static char *grub2GetEnv(struct configFileInfo *info, char *name)
{
- static char buf[1025];
- char *s = NULL;
- char *ret = NULL;
- char *envFile = info->envFile ? info->envFile : "/boot/grub2/grubenv";
- int rc = asprintf(&s, "grub2-editenv %s list | grep '^%s='", envFile, name);
+ static char buf[1025];
+ char *s = NULL;
+ char *ret = NULL;
+ char *envFile = info->envFile ? info->envFile : "/boot/grub2/grubenv";
+ int rc =
+ asprintf(&s, "grub2-editenv %s list | grep '^%s='", envFile, name);
- if (rc < 0)
- return NULL;
+ if (rc < 0)
+ return NULL;
- FILE *f = popen(s, "r");
- if (!f)
- goto out;
+ FILE *f = popen(s, "r");
+ if (!f)
+ goto out;
- memset(buf, '\0', sizeof (buf));
- ret = fgets(buf, 1024, f);
- pclose(f);
+ memset(buf, '\0', sizeof(buf));
+ ret = fgets(buf, 1024, f);
+ pclose(f);
- if (ret) {
- ret += strlen(name) + 1;
- ret[strlen(ret) - 1] = '\0';
- }
- dbgPrintf("grub2GetEnv(%s): %s\n", name, ret);
+ if (ret) {
+ ret += strlen(name) + 1;
+ ret[strlen(ret) - 1] = '\0';
+ }
+ dbgPrintf("grub2GetEnv(%s): %s\n", name, ret);
out:
- free(s);
- return ret;
+ free(s);
+ return ret;
}
static int sPopCount(const char *s, const char *c)
{
- int ret = 0;
- if (!s)
- return -1;
- for (int i = 0; s[i] != '\0'; i++)
- for (int j = 0; c[j] != '\0'; j++)
- if (s[i] == c[j])
- ret++;
- return ret;
+ int ret = 0;
+ if (!s)
+ return -1;
+ for (int i = 0; s[i] != '\0'; i++)
+ for (int j = 0; c[j] != '\0'; j++)
+ if (s[i] == c[j])
+ ret++;
+ return ret;
}
static char *shellEscape(const char *s)
{
- int l = strlen(s) + sPopCount(s, "'") * 2;
+ int l = strlen(s) + sPopCount(s, "'") * 2;
- char *ret = calloc(l+1, sizeof (*ret));
- if (!ret)
- return NULL;
- for (int i = 0, j = 0; s[i] != '\0'; i++, j++) {
- if (s[i] == '\'')
- ret[j++] = '\\';
- ret[j] = s[i];
- }
- return ret;
+ char *ret = calloc(l + 1, sizeof(*ret));
+ if (!ret)
+ return NULL;
+ for (int i = 0, j = 0; s[i] != '\0'; i++, j++) {
+ if (s[i] == '\'')
+ ret[j++] = '\\';
+ ret[j] = s[i];
+ }
+ return ret;
}
static void unquote(char *s)
{
- int l = strlen(s);
+ int l = strlen(s);
- if ((s[l-1] == '\'' && s[0] == '\'') || (s[l-1] == '"' && s[0] == '"')) {
- memmove(s, s+1, l-2);
- s[l-2] = '\0';
- }
+ if ((s[l - 1] == '\'' && s[0] == '\'')
+ || (s[l - 1] == '"' && s[0] == '"')) {
+ memmove(s, s + 1, l - 2);
+ s[l - 2] = '\0';
+ }
}
static int grub2SetEnv(struct configFileInfo *info, char *name, char *value)
{
- char *s = NULL;
- int rc = 0;
- char *envFile = info->envFile ? info->envFile : "/boot/grub2/grubenv";
+ char *s = NULL;
+ int rc = 0;
+ char *envFile = info->envFile ? info->envFile : "/boot/grub2/grubenv";
- unquote(value);
- value = shellEscape(value);
- if (!value)
- return -1;
+ unquote(value);
+ value = shellEscape(value);
+ if (!value)
+ return -1;
- rc = asprintf(&s, "grub2-editenv %s set '%s=%s'", envFile, name, value);
- free(value);
- if (rc <0)
- return -1;
+ rc = asprintf(&s, "grub2-editenv %s set '%s=%s'", envFile, name, value);
+ free(value);
+ if (rc < 0)
+ return -1;
- dbgPrintf("grub2SetEnv(%s): %s\n", name, s);
- rc = system(s);
- free(s);
- return rc;
+ dbgPrintf("grub2SetEnv(%s): %s\n", name, s);
+ rc = system(s);
+ free(s);
+ return rc;
}
/* this is a gigantic hack to avoid clobbering grub2 variables... */
static int is_special_grub2_variable(const char *name)
{
- if (!strcmp(name,"\"${next_entry}\""))
- return 1;
- if (!strcmp(name,"\"${prev_saved_entry}\""))
- return 1;
- return 0;
+ if (!strcmp(name, "\"${next_entry}\""))
+ return 1;
+ if (!strcmp(name, "\"${prev_saved_entry}\""))
+ return 1;
+ return 0;
}
-int sizeOfSingleLine(struct singleLine * line) {
- int count = 0;
+int sizeOfSingleLine(struct singleLine *line)
+{
+ int count = 0;
- for (int i = 0; i < line->numElements; i++) {
- int indentSize = 0;
+ for (int i = 0; i < line->numElements; i++) {
+ int indentSize = 0;
- count = count + strlen(line->elements[i].item);
+ count = count + strlen(line->elements[i].item);
- indentSize = strlen(line->elements[i].indent);
- if (indentSize > 0)
- count = count + indentSize;
- else
- /* be extra safe and add room for whitespaces */
- count = count + 1;
- }
+ indentSize = strlen(line->elements[i].indent);
+ if (indentSize > 0)
+ count = count + indentSize;
+ else
+ /* be extra safe and add room for whitespaces */
+ count = count + 1;
+ }
- /* room for trailing terminator */
- count = count + 1;
+ /* room for trailing terminator */
+ count = count + 1;
- return count;
+ return count;
}
static int isquote(char q)
{
- if (q == '\'' || q == '\"')
- return 1;
- return 0;
+ if (q == '\'' || q == '\"')
+ return 1;
+ return 0;
}
-static int iskernel(enum lineType_e type) {
- return (type == LT_KERNEL || type == LT_KERNEL_EFI || type == LT_KERNEL_16);
+static int iskernel(enum lineType_e type)
+{
+ return (type == LT_KERNEL || type == LT_KERNEL_EFI
+ || type == LT_KERNEL_16);
}
-static int isinitrd(enum lineType_e type) {
- return (type == LT_INITRD || type == LT_INITRD_EFI || type == LT_INITRD_16);
+static int isinitrd(enum lineType_e type)
+{
+ return (type == LT_INITRD || type == LT_INITRD_EFI
+ || type == LT_INITRD_16);
}
-char *grub2ExtractTitle(struct singleLine * line) {
- char * current;
- char * current_indent;
- int current_len;
- int current_indent_len;
- int i;
+char *grub2ExtractTitle(struct singleLine *line)
+{
+ char *current;
+ char *current_indent;
+ int current_len;
+ int current_indent_len;
+ int i;
- /* bail out if line does not start with menuentry */
- if (strcmp(line->elements[0].item, "menuentry"))
- return NULL;
+ /* bail out if line does not start with menuentry */
+ if (strcmp(line->elements[0].item, "menuentry"))
+ return NULL;
- i = 1;
- current = line->elements[i].item;
- current_len = strlen(current);
-
- /* if second word is quoted, strip the quotes and return single word */
- if (isquote(*current) && isquote(current[current_len - 1])) {
- char *tmp;
-
- tmp = strdup(current+1);
- if (!tmp)
- return NULL;
- tmp[strlen(tmp)-1] = '\0';
- return tmp;
- }
-
- /* if no quotes, return second word verbatim */
- if (!isquote(*current))
- return current;
-
- /* second element start with a quote, so we have to find the element
- * whose last character is also quote (assuming it's the closing one) */
- int resultMaxSize;
- char * result;
- /* need to ensure that ' does not match " as we search */
- char quote_char = *current;
-
- resultMaxSize = sizeOfSingleLine(line);
- result = malloc(resultMaxSize);
- snprintf(result, resultMaxSize, "%s", ++current);
-
- i++;
- for (; i < line->numElements; ++i) {
+ i = 1;
current = line->elements[i].item;
current_len = strlen(current);
- current_indent = line->elements[i].indent;
- current_indent_len = strlen(current_indent);
-
- strncat(result, current_indent, current_indent_len);
- if (current[current_len-1] != quote_char) {
- strncat(result, current, current_len);
- } else {
- strncat(result, current, current_len - 1);
- break;
+
+ /* if second word is quoted, strip the quotes and return single word */
+ if (isquote(*current) && isquote(current[current_len - 1])) {
+ char *tmp;
+
+ tmp = strdup(current + 1);
+ if (!tmp)
+ return NULL;
+ tmp[strlen(tmp) - 1] = '\0';
+ return tmp;
+ }
+
+ /* if no quotes, return second word verbatim */
+ if (!isquote(*current))
+ return current;
+
+ /* second element start with a quote, so we have to find the element
+ * whose last character is also quote (assuming it's the closing one) */
+ int resultMaxSize;
+ char *result;
+ /* need to ensure that ' does not match " as we search */
+ char quote_char = *current;
+
+ resultMaxSize = sizeOfSingleLine(line);
+ result = malloc(resultMaxSize);
+ snprintf(result, resultMaxSize, "%s", ++current);
+
+ i++;
+ for (; i < line->numElements; ++i) {
+ current = line->elements[i].item;
+ current_len = strlen(current);
+ current_indent = line->elements[i].indent;
+ current_indent_len = strlen(current_indent);
+
+ strncat(result, current_indent, current_indent_len);
+ if (current[current_len - 1] != quote_char) {
+ strncat(result, current, current_len);
+ } else {
+ strncat(result, current, current_len - 1);
+ break;
+ }
}
- }
- return result;
+ return result;
}
struct configFileInfo grub2ConfigType = {
- .findConfig = grub2FindConfig,
- .getEnv = grub2GetEnv,
- .setEnv = grub2SetEnv,
- .keywords = grub2Keywords,
- .defaultIsIndex = 1,
- .defaultSupportSaved = 1,
- .defaultIsVariable = 1,
- .entryStart = LT_MENUENTRY,
- .entryEnd = LT_ENTRY_END,
- .titlePosition = 1,
- .needsBootPrefix = 1,
- .mbHyperFirst = 1,
- .mbInitRdIsModule = 1,
- .mbAllowExtraInitRds = 1,
+ .findConfig = grub2FindConfig,
+ .getEnv = grub2GetEnv,
+ .setEnv = grub2SetEnv,
+ .keywords = grub2Keywords,
+ .defaultIsIndex = 1,
+ .defaultSupportSaved = 1,
+ .defaultIsVariable = 1,
+ .entryStart = LT_MENUENTRY,
+ .entryEnd = LT_ENTRY_END,
+ .titlePosition = 1,
+ .needsBootPrefix = 1,
+ .mbHyperFirst = 1,
+ .mbInitRdIsModule = 1,
+ .mbAllowExtraInitRds = 1,
};
struct keywordTypes yabootKeywords[] = {
- { "label", LT_TITLE, '=' },
- { "root", LT_ROOT, '=' },
- { "default", LT_DEFAULT, '=' },
- { "image", LT_KERNEL, '=' },
- { "bsd", LT_GENERIC, '=' },
- { "macos", LT_GENERIC, '=' },
- { "macosx", LT_GENERIC, '=' },
- { "magicboot", LT_GENERIC, '=' },
- { "darwin", LT_GENERIC, '=' },
- { "timeout", LT_GENERIC, '=' },
- { "install", LT_GENERIC, '=' },
- { "fstype", LT_GENERIC, '=' },
- { "hfstype", LT_GENERIC, '=' },
- { "delay", LT_GENERIC, '=' },
- { "defaultos", LT_GENERIC, '=' },
- { "init-message", LT_GENERIC, '=' },
- { "enablecdboot", LT_GENERIC, ' ' },
- { "enableofboot", LT_GENERIC, ' ' },
- { "enablenetboot", LT_GENERIC, ' ' },
- { "nonvram", LT_GENERIC, ' ' },
- { "hide", LT_GENERIC, ' ' },
- { "protect", LT_GENERIC, ' ' },
- { "nobless", LT_GENERIC, ' ' },
- { "nonvram", LT_GENERIC, ' ' },
- { "brokenosx", LT_GENERIC, ' ' },
- { "usemount", LT_GENERIC, ' ' },
- { "mntpoint", LT_GENERIC, '=' },
- { "partition", LT_GENERIC, '=' },
- { "device", LT_GENERIC, '=' },
- { "fstype", LT_GENERIC, '=' },
- { "initrd", LT_INITRD, '=', ';' },
- { "append", LT_KERNELARGS, '=' },
- { "boot", LT_BOOT, '=' },
- { "lba", LT_LBA, ' ' },
- { NULL, 0, 0 },
+ {"label", LT_TITLE, '='},
+ {"root", LT_ROOT, '='},
+ {"default", LT_DEFAULT, '='},
+ {"image", LT_KERNEL, '='},
+ {"bsd", LT_GENERIC, '='},
+ {"macos", LT_GENERIC, '='},
+ {"macosx", LT_GENERIC, '='},
+ {"magicboot", LT_GENERIC, '='},
+ {"darwin", LT_GENERIC, '='},
+ {"timeout", LT_GENERIC, '='},
+ {"install", LT_GENERIC, '='},
+ {"fstype", LT_GENERIC, '='},
+ {"hfstype", LT_GENERIC, '='},
+ {"delay", LT_GENERIC, '='},
+ {"defaultos", LT_GENERIC, '='},
+ {"init-message", LT_GENERIC, '='},
+ {"enablecdboot", LT_GENERIC, ' '},
+ {"enableofboot", LT_GENERIC, ' '},
+ {"enablenetboot", LT_GENERIC, ' '},
+ {"nonvram", LT_GENERIC, ' '},
+ {"hide", LT_GENERIC, ' '},
+ {"protect", LT_GENERIC, ' '},
+ {"nobless", LT_GENERIC, ' '},
+ {"nonvram", LT_GENERIC, ' '},
+ {"brokenosx", LT_GENERIC, ' '},
+ {"usemount", LT_GENERIC, ' '},
+ {"mntpoint", LT_GENERIC, '='},
+ {"partition", LT_GENERIC, '='},
+ {"device", LT_GENERIC, '='},
+ {"fstype", LT_GENERIC, '='},
+ {"initrd", LT_INITRD, '=', ';'},
+ {"append", LT_KERNELARGS, '='},
+ {"boot", LT_BOOT, '='},
+ {"lba", LT_LBA, ' '},
+ {NULL, 0, 0},
};
struct keywordTypes liloKeywords[] = {
- { "label", LT_TITLE, '=' },
- { "root", LT_ROOT, '=' },
- { "default", LT_DEFAULT, '=' },
- { "image", LT_KERNEL, '=' },
- { "other", LT_OTHER, '=' },
- { "initrd", LT_INITRD, '=' },
- { "append", LT_KERNELARGS, '=' },
- { "boot", LT_BOOT, '=' },
- { "lba", LT_LBA, ' ' },
- { NULL, 0, 0 },
+ {"label", LT_TITLE, '='},
+ {"root", LT_ROOT, '='},
+ {"default", LT_DEFAULT, '='},
+ {"image", LT_KERNEL, '='},
+ {"other", LT_OTHER, '='},
+ {"initrd", LT_INITRD, '='},
+ {"append", LT_KERNELARGS, '='},
+ {"boot", LT_BOOT, '='},
+ {"lba", LT_LBA, ' '},
+ {NULL, 0, 0},
};
struct keywordTypes eliloKeywords[] = {
- { "label", LT_TITLE, '=' },
- { "root", LT_ROOT, '=' },
- { "default", LT_DEFAULT, '=' },
- { "image", LT_KERNEL, '=' },
- { "initrd", LT_INITRD, '=' },
- { "append", LT_KERNELARGS, '=' },
- { "vmm", LT_HYPER, '=' },
- { NULL, 0, 0 },
+ {"label", LT_TITLE, '='},
+ {"root", LT_ROOT, '='},
+ {"default", LT_DEFAULT, '='},
+ {"image", LT_KERNEL, '='},
+ {"initrd", LT_INITRD, '='},
+ {"append", LT_KERNELARGS, '='},
+ {"vmm", LT_HYPER, '='},
+ {NULL, 0, 0},
};
struct keywordTypes siloKeywords[] = {
- { "label", LT_TITLE, '=' },
- { "root", LT_ROOT, '=' },
- { "default", LT_DEFAULT, '=' },
- { "image", LT_KERNEL, '=' },
- { "other", LT_OTHER, '=' },
- { "initrd", LT_INITRD, '=' },
- { "append", LT_KERNELARGS, '=' },
- { "boot", LT_BOOT, '=' },
- { NULL, 0, 0 },
+ {"label", LT_TITLE, '='},
+ {"root", LT_ROOT, '='},
+ {"default", LT_DEFAULT, '='},
+ {"image", LT_KERNEL, '='},
+ {"other", LT_OTHER, '='},
+ {"initrd", LT_INITRD, '='},
+ {"append", LT_KERNELARGS, '='},
+ {"boot", LT_BOOT, '='},
+ {NULL, 0, 0},
};
struct keywordTypes ziplKeywords[] = {
- { "target", LT_BOOTROOT, '=' },
- { "image", LT_KERNEL, '=' },
- { "ramdisk", LT_INITRD, '=' },
- { "parameters", LT_KERNELARGS, '=' },
- { "default", LT_DEFAULT, '=' },
- { NULL, 0, 0 },
+ {"target", LT_BOOTROOT, '='},
+ {"image", LT_KERNEL, '='},
+ {"ramdisk", LT_INITRD, '='},
+ {"parameters", LT_KERNELARGS, '='},
+ {"default", LT_DEFAULT, '='},
+ {NULL, 0, 0},
};
struct keywordTypes extlinuxKeywords[] = {
- { "label", LT_TITLE, ' ' },
- { "root", LT_ROOT, ' ' },
- { "default", LT_DEFAULT, ' ' },
- { "kernel", LT_KERNEL, ' ' },
- { "initrd", LT_INITRD, ' ', ',' },
- { "append", LT_KERNELARGS, ' ' },
- { "prompt", LT_UNKNOWN, ' ' },
- { "fdt", LT_DEVTREE, ' ' },
- { "fdtdir", LT_DEVTREE, ' ' },
- { NULL, 0, 0 },
+ {"label", LT_TITLE, ' '},
+ {"root", LT_ROOT, ' '},
+ {"default", LT_DEFAULT, ' '},
+ {"kernel", LT_KERNEL, ' '},
+ {"initrd", LT_INITRD, ' ', ','},
+ {"append", LT_KERNELARGS, ' '},
+ {"prompt", LT_UNKNOWN, ' '},
+ {"fdt", LT_DEVTREE, ' '},
+ {"fdtdir", LT_DEVTREE, ' '},
+ {NULL, 0, 0},
};
+
int useextlinuxmenu;
struct configFileInfo eliloConfigType = {
- .defaultConfig = "/boot/efi/EFI/redhat/elilo.conf",
- .keywords = eliloKeywords,
- .entryStart = LT_KERNEL,
- .needsBootPrefix = 1,
- .argsInQuotes = 1,
- .mbConcatArgs = 1,
- .titlePosition = 1,
+ .defaultConfig = "/boot/efi/EFI/redhat/elilo.conf",
+ .keywords = eliloKeywords,
+ .entryStart = LT_KERNEL,
+ .needsBootPrefix = 1,
+ .argsInQuotes = 1,
+ .mbConcatArgs = 1,
+ .titlePosition = 1,
};
struct configFileInfo liloConfigType = {
- .defaultConfig = "/etc/lilo.conf",
- .keywords = liloKeywords,
- .entryStart = LT_KERNEL,
- .argsInQuotes = 1,
- .maxTitleLength = 15,
- .titlePosition = 1,
+ .defaultConfig = "/etc/lilo.conf",
+ .keywords = liloKeywords,
+ .entryStart = LT_KERNEL,
+ .argsInQuotes = 1,
+ .maxTitleLength = 15,
+ .titlePosition = 1,
};
struct configFileInfo yabootConfigType = {
- .defaultConfig = "/etc/yaboot.conf",
- .keywords = yabootKeywords,
- .entryStart = LT_KERNEL,
- .needsBootPrefix = 1,
- .argsInQuotes = 1,
- .maxTitleLength = 15,
- .mbAllowExtraInitRds = 1,
- .titlePosition = 1,
+ .defaultConfig = "/etc/yaboot.conf",
+ .keywords = yabootKeywords,
+ .entryStart = LT_KERNEL,
+ .needsBootPrefix = 1,
+ .argsInQuotes = 1,
+ .maxTitleLength = 15,
+ .mbAllowExtraInitRds = 1,
+ .titlePosition = 1,
};
struct configFileInfo siloConfigType = {
- .defaultConfig = "/etc/silo.conf",
- .keywords = siloKeywords,
- .entryStart = LT_KERNEL,
- .needsBootPrefix = 1,
- .argsInQuotes = 1,
- .maxTitleLength = 15,
- .titlePosition = 1,
+ .defaultConfig = "/etc/silo.conf",
+ .keywords = siloKeywords,
+ .entryStart = LT_KERNEL,
+ .needsBootPrefix = 1,
+ .argsInQuotes = 1,
+ .maxTitleLength = 15,
+ .titlePosition = 1,
};
struct configFileInfo ziplConfigType = {
- .defaultConfig = "/etc/zipl.conf",
- .keywords = ziplKeywords,
- .entryStart = LT_TITLE,
- .argsInQuotes = 1,
- .titleBracketed = 1,
+ .defaultConfig = "/etc/zipl.conf",
+ .keywords = ziplKeywords,
+ .entryStart = LT_TITLE,
+ .argsInQuotes = 1,
+ .titleBracketed = 1,
};
struct configFileInfo extlinuxConfigType = {
- .defaultConfig = "/boot/extlinux/extlinux.conf",
- .keywords = extlinuxKeywords,
- .caseInsensitive = 1,
- .entryStart = LT_TITLE,
- .needsBootPrefix = 1,
- .maxTitleLength = 255,
- .mbAllowExtraInitRds = 1,
- .defaultIsUnquoted = 1,
- .titlePosition = 1,
+ .defaultConfig = "/boot/extlinux/extlinux.conf",
+ .keywords = extlinuxKeywords,
+ .caseInsensitive = 1,
+ .entryStart = LT_TITLE,
+ .needsBootPrefix = 1,
+ .maxTitleLength = 255,
+ .mbAllowExtraInitRds = 1,
+ .defaultIsUnquoted = 1,
+ .titlePosition = 1,
};
struct grubConfig {
- struct singleLine * theLines;
- struct singleEntry * entries;
- char * primaryIndent;
- char * secondaryIndent;
- int defaultImage; /* -1 if none specified -- this value is
- * written out, overriding original */
- int fallbackImage; /* just like defaultImage */
- int flags;
- struct configFileInfo * cfi;
+ struct singleLine *theLines;
+ struct singleEntry *entries;
+ char *primaryIndent;
+ char *secondaryIndent;
+ int defaultImage; /* -1 if none specified -- this value is
+ * written out, overriding original */
+ int fallbackImage; /* just like defaultImage */
+ int flags;
+ struct configFileInfo *cfi;
};
blkid_cache blkid;
-struct singleEntry * findEntryByIndex(struct grubConfig * cfg, int index);
-struct singleEntry * findEntryByPath(struct grubConfig * cfg,
- const char * path, const char * prefix,
- int * index);
-struct singleEntry * findEntryByTitle(struct grubConfig * cfg, char *title,
- int * index);
-static int readFile(int fd, char ** bufPtr);
-static void lineInit(struct singleLine * line);
-struct singleLine * lineDup(struct singleLine * line);
-static void lineFree(struct singleLine * line);
-static int lineWrite(FILE * out, struct singleLine * line,
- struct configFileInfo * cfi);
-static int getNextLine(char ** bufPtr, struct singleLine * line,
- struct configFileInfo * cfi);
-static char * getRootSpecifier(char * str);
-static void requote(struct singleLine *line, struct configFileInfo * cfi);
-static void insertElement(struct singleLine * line,
- const char * item, int insertHere,
- struct configFileInfo * cfi);
-static void removeElement(struct singleLine * line, int removeHere);
-static struct keywordTypes * getKeywordByType(enum lineType_e type,
- struct configFileInfo * cfi);
-static enum lineType_e getTypeByKeyword(char * keyword,
- struct configFileInfo * cfi);
-static struct singleLine * getLineByType(enum lineType_e type,
- struct singleLine * line);
-static int checkForExtLinux(struct grubConfig * config);
-struct singleLine * addLineTmpl(struct singleEntry * entry,
- struct singleLine * tmplLine,
- struct singleLine * prevLine,
- const char * val,
- struct configFileInfo * cfi);
-struct singleLine * addLine(struct singleEntry * entry,
- struct configFileInfo * cfi,
- enum lineType_e type, char * defaultIndent,
- const char * val);
+struct singleEntry *findEntryByIndex(struct grubConfig *cfg, int index);
+struct singleEntry *findEntryByPath(struct grubConfig *cfg,
+ const char *path, const char *prefix,
+ int *index);
+struct singleEntry *findEntryByTitle(struct grubConfig *cfg, char *title,
+ int *index);
+static int readFile(int fd, char **bufPtr);
+static void lineInit(struct singleLine *line);
+struct singleLine *lineDup(struct singleLine *line);
+static void lineFree(struct singleLine *line);
+static int lineWrite(FILE * out, struct singleLine *line,
+ struct configFileInfo *cfi);
+static int getNextLine(char **bufPtr, struct singleLine *line,
+ struct configFileInfo *cfi);
+static char *getRootSpecifier(char *str);
+static void requote(struct singleLine *line, struct configFileInfo *cfi);
+static void insertElement(struct singleLine *line,
+ const char *item, int insertHere,
+ struct configFileInfo *cfi);
+static void removeElement(struct singleLine *line, int removeHere);
+static struct keywordTypes *getKeywordByType(enum lineType_e type,
+ struct configFileInfo *cfi);
+static enum lineType_e getTypeByKeyword(char *keyword,
+ struct configFileInfo *cfi);
+static struct singleLine *getLineByType(enum lineType_e type,
+ struct singleLine *line);
+static int checkForExtLinux(struct grubConfig *config);
+struct singleLine *addLineTmpl(struct singleEntry *entry,
+ struct singleLine *tmplLine,
+ struct singleLine *prevLine,
+ const char *val, struct configFileInfo *cfi);
+struct singleLine *addLine(struct singleEntry *entry,
+ struct configFileInfo *cfi,
+ enum lineType_e type, char *defaultIndent,
+ const char *val);
-static char * sdupprintf(const char *format, ...)
+static char *sdupprintf(const char *format, ...)
#ifdef __GNUC__
- __attribute__ ((format (printf, 1, 2)));
+ __attribute__ ((format(printf, 1, 2)));
#else
- ;
+;
#endif
-static char * sdupprintf(const char *format, ...) {
- char *buf = NULL;
- char c;
- va_list args;
- size_t size = 0;
- va_start(args, format);
-
- /* XXX requires C99 vsnprintf behavior */
- size = vsnprintf(&c, 1, format, args) + 1;
- if (size == -1) {
- printf("ERROR: vsnprintf behavior is not C99\n");
- abort();
- }
+static char *sdupprintf(const char *format, ...)
+{
+ char *buf = NULL;
+ char c;
+ va_list args;
+ size_t size = 0;
+ va_start(args, format);
- va_end(args);
- va_start(args, format);
+ /* XXX requires C99 vsnprintf behavior */
+ size = vsnprintf(&c, 1, format, args) + 1;
+ if (size == -1) {
+ printf("ERROR: vsnprintf behavior is not C99\n");
+ abort();
+ }
- buf = malloc(size);
- if (buf == NULL)
- return NULL;
- vsnprintf(buf, size, format, args);
- va_end (args);
+ va_end(args);
+ va_start(args, format);
- return buf;
+ buf = malloc(size);
+ if (buf == NULL)
+ return NULL;
+ vsnprintf(buf, size, format, args);
+ va_end(args);
+
+ return buf;
}
static enum lineType_e preferredLineType(enum lineType_e type,
- struct configFileInfo *cfi) {
- if (isEfi && cfi == &grub2ConfigType) {
- switch (type) {
- case LT_KERNEL:
- return isEfiOnly ? LT_KERNEL : LT_KERNEL_EFI;
- case LT_INITRD:
- return isEfiOnly ? LT_INITRD : LT_INITRD_EFI;
- default:
- return type;
- }
+ struct configFileInfo *cfi)
+{
+ if (isEfi && cfi == &grub2ConfigType) {
+ switch (type) {
+ case LT_KERNEL:
+ return isEfiOnly ? LT_KERNEL : LT_KERNEL_EFI;
+ case LT_INITRD:
+ return isEfiOnly ? LT_INITRD : LT_INITRD_EFI;
+ default:
+ return type;
+ }
#if defined(__i386__) || defined(__x86_64__)
- } else if (cfi == &grub2ConfigType) {
- switch (type) {
- case LT_KERNEL:
- return LT_KERNEL_16;
- case LT_INITRD:
- return LT_INITRD_16;
- default:
- return type;
- }
+ } else if (cfi == &grub2ConfigType) {
+ switch (type) {
+ case LT_KERNEL:
+ return LT_KERNEL_16;
+ case LT_INITRD:
+ return LT_INITRD_16;
+ default:
+ return type;
+ }
#endif
- }
- return type;
+ }
+ return type;
}
-static struct keywordTypes * getKeywordByType(enum lineType_e type,
- struct configFileInfo * cfi) {
- for (struct keywordTypes *kw = cfi->keywords; kw->key; kw++) {
- if (kw->type == type)
- return kw;
- }
- return NULL;
+static struct keywordTypes *getKeywordByType(enum lineType_e type,
+ struct configFileInfo *cfi)
+{
+ for (struct keywordTypes * kw = cfi->keywords; kw->key; kw++) {
+ if (kw->type == type)
+ return kw;
+ }
+ return NULL;
}
-static char *getKeyByType(enum lineType_e type, struct configFileInfo * cfi) {
- struct keywordTypes *kt = getKeywordByType(type, cfi);
- if (kt)
- return kt->key;
- return "unknown";
+static char *getKeyByType(enum lineType_e type, struct configFileInfo *cfi)
+{
+ struct keywordTypes *kt = getKeywordByType(type, cfi);
+ if (kt)
+ return kt->key;
+ return "unknown";
}
-static char * getpathbyspec(char *device) {
- if (!blkid)
- blkid_get_cache(&blkid, NULL);
+static char *getpathbyspec(char *device)
+{
+ if (!blkid)
+ blkid_get_cache(&blkid, NULL);
- return blkid_get_devname(blkid, device, NULL);
+ return blkid_get_devname(blkid, device, NULL);
}
-static char * getuuidbydev(char *device) {
- if (!blkid)
- blkid_get_cache(&blkid, NULL);
+static char *getuuidbydev(char *device)
+{
+ if (!blkid)
+ blkid_get_cache(&blkid, NULL);
- return blkid_get_tag_value(blkid, "UUID", device);
+ return blkid_get_tag_value(blkid, "UUID", device);
}
-static enum lineType_e getTypeByKeyword(char * keyword,
- struct configFileInfo * cfi) {
- for (struct keywordTypes *kw = cfi->keywords; kw->key; kw++) {
- if (cfi->caseInsensitive) {
- if (!strcasecmp(keyword, kw->key))
- return kw->type;
- } else {
- if (!strcmp(keyword, kw->key))
- return kw->type;
+static enum lineType_e getTypeByKeyword(char *keyword,
+ struct configFileInfo *cfi)
+{
+ for (struct keywordTypes * kw = cfi->keywords; kw->key; kw++) {
+ if (cfi->caseInsensitive) {
+ if (!strcasecmp(keyword, kw->key))
+ return kw->type;
+ } else {
+ if (!strcmp(keyword, kw->key))
+ return kw->type;
+ }
}
- }
- return LT_UNKNOWN;
+ return LT_UNKNOWN;
}
-static struct singleLine * getLineByType(enum lineType_e type,
- struct singleLine * line) {
- dbgPrintf("getLineByType(%d): ", type);
- for (; line; line = line->next) {
- dbgPrintf("%d:%s ", line->type,
- line->numElements ? line->elements[0].item : "(empty)");
- if (line->type & type) break;
- }
- dbgPrintf(line ? "\n" : " (failed)\n");
- return line;
+static struct singleLine *getLineByType(enum lineType_e type,
+ struct singleLine *line)
+{
+ dbgPrintf("getLineByType(%d): ", type);
+ for (; line; line = line->next) {
+ dbgPrintf("%d:%s ", line->type,
+ line->numElements ? line->elements[0].
+ item : "(empty)");
+ if (line->type & type)
+ break;
+ }
+ dbgPrintf(line ? "\n" : " (failed)\n");
+ return line;
}
-static int isBracketedTitle(struct singleLine * line) {
- if (line->numElements == 1 && *line->elements[0].item == '[') {
- int len = strlen(line->elements[0].item);
- if (*(line->elements[0].item + len - 1) == ']') {
- /* FIXME: this is a hack... */
- if (strcmp(line->elements[0].item, "[defaultboot]")) {
- return 1;
- }
- }
- }
- return 0;
+static int isBracketedTitle(struct singleLine *line)
+{
+ if (line->numElements == 1 && *line->elements[0].item == '[') {
+ int len = strlen(line->elements[0].item);
+ if (*(line->elements[0].item + len - 1) == ']') {
+ /* FIXME: this is a hack... */
+ if (strcmp(line->elements[0].item, "[defaultboot]")) {
+ return 1;
+ }
+ }
+ }
+ return 0;
}
-static int isEntryStart(struct singleLine * line,
- struct configFileInfo * cfi) {
- return line->type == cfi->entryStart || line->type == LT_OTHER ||
- (cfi->titleBracketed && isBracketedTitle(line));
+static int isEntryStart(struct singleLine *line, struct configFileInfo *cfi)
+{
+ return line->type == cfi->entryStart || line->type == LT_OTHER ||
+ (cfi->titleBracketed && isBracketedTitle(line));
}
/* extract the title from within brackets (for zipl) */
-static char * extractTitle(struct grubConfig *cfg, struct singleLine * line) {
- /* bracketed title... let's extract it */
- char * title = NULL;
- if (line->type == LT_TITLE) {
- char *tmp = line->elements[cfg->cfi->titlePosition].item;
- if (cfg->cfi->titleBracketed) {
- tmp++;
- title = strdup(tmp);
- *(title + strlen(title) - 1) = '\0';
- } else {
- title = strdup(tmp);
- }
- } else if (line->type == LT_MENUENTRY)
- title = strdup(line->elements[1].item);
- else
- return NULL;
- return title;
-}
-
-static int readFile(int fd, char ** bufPtr) {
- int alloced = 0, size = 0, i = 0;
- char * buf = NULL;
-
- do {
- size += i;
- if ((size + 1024) > alloced) {
- alloced += 4096;
- buf = realloc(buf, alloced + 1);
- }
- } while ((i = read(fd, buf + size, 1024)) > 0);
-
- if (i < 0) {
- fprintf(stderr, _("error reading input: %s\n"), strerror(errno));
- free(buf);
- return 1;
- }
-
- buf = realloc(buf, size + 2);
- if (size == 0)
- buf[size++] = '\n';
- else
- if (buf[size - 1] != '\n')
- buf[size++] = '\n';
- buf[size] = '\0';
-
- *bufPtr = buf;
-
- return 0;
-}
-
-static void lineInit(struct singleLine * line) {
- line->indent = NULL;
- line->elements = NULL;
- line->numElements = 0;
- line->next = NULL;
-}
-
-struct singleLine * lineDup(struct singleLine * line) {
- struct singleLine * newLine = malloc(sizeof(*newLine));
-
- newLine->indent = strdup(line->indent);
- newLine->next = NULL;
- newLine->type = line->type;
- newLine->numElements = line->numElements;
- newLine->elements = malloc(sizeof(*newLine->elements) *
- newLine->numElements);
-
- for (int i = 0; i < newLine->numElements; i++) {
- newLine->elements[i].indent = strdup(line->elements[i].indent);
- newLine->elements[i].item = strdup(line->elements[i].item);
- }
-
- return newLine;
-}
-
-static void lineFree(struct singleLine * line) {
- if (line->indent) free(line->indent);
-
- for (int i = 0; i < line->numElements; i++) {
- free(line->elements[i].item);
- free(line->elements[i].indent);
- }
-
- if (line->elements) free(line->elements);
- lineInit(line);
+static char *extractTitle(struct grubConfig *cfg, struct singleLine *line)
+{
+ /* bracketed title... let's extract it */
+ char *title = NULL;
+ if (line->type == LT_TITLE) {
+ char *tmp = line->elements[cfg->cfi->titlePosition].item;
+ if (cfg->cfi->titleBracketed) {
+ tmp++;
+ title = strdup(tmp);
+ *(title + strlen(title) - 1) = '\0';
+ } else {
+ title = strdup(tmp);
+ }
+ } else if (line->type == LT_MENUENTRY)
+ title = strdup(line->elements[1].item);
+ else
+ return NULL;
+ return title;
}
-static int lineWrite(FILE * out, struct singleLine * line,
- struct configFileInfo * cfi) {
- if (fprintf(out, "%s", line->indent) == -1) return -1;
+static int readFile(int fd, char **bufPtr)
+{
+ int alloced = 0, size = 0, i = 0;
+ char *buf = NULL;
- for (int i = 0; i < line->numElements; i++) {
- /* Need to handle this, because we strip the quotes from
- * menuentry when read it. */
- if (line->type == LT_MENUENTRY && i == 1) {
- if(!isquote(*line->elements[i].item)) {
- int substring = 0;
- /* If the line contains nested quotes, we did not strip
- * the "interna" quotes and we must use the right quotes
- * again when writing the updated file. */
- for (int j = i; j < line->numElements; j++) {
- if (strchr(line->elements[i].item, '\'') != NULL) {
- substring = 1;
- fprintf(out, "\"%s\"", line->elements[i].item);
- break;
- }
+ do {
+ size += i;
+ if ((size + 1024) > alloced) {
+ alloced += 4096;
+ buf = realloc(buf, alloced + 1);
}
- if (!substring)
- fprintf(out, "\'%s\'", line->elements[i].item);
- } else {
- fprintf(out, "%s", line->elements[i].item);
- }
- fprintf(out, "%s", line->elements[i].indent);
+ } while ((i = read(fd, buf + size, 1024)) > 0);
- continue;
+ if (i < 0) {
+ fprintf(stderr, _("error reading input: %s\n"),
+ strerror(errno));
+ free(buf);
+ return 1;
}
- if (i == 1 && line->type == LT_KERNELARGS && cfi->argsInQuotes)
- if (fputc('"', out) == EOF) return -1;
-
- if (fprintf(out, "%s", line->elements[i].item) == -1) return -1;
- if (i < line->numElements - 1)
- if (fprintf(out, "%s", line->elements[i].indent) == -1) return -1;
- }
+ buf = realloc(buf, size + 2);
+ if (size == 0)
+ buf[size++] = '\n';
+ else if (buf[size - 1] != '\n')
+ buf[size++] = '\n';
+ buf[size] = '\0';
- if (line->type == LT_KERNELARGS && cfi->argsInQuotes)
- if (fputc('"', out) == EOF) return -1;
+ *bufPtr = buf;
- if (fprintf(out, "\n") == -1) return -1;
-
- return 0;
+ return 0;
}
-/* we've guaranteed that the buffer ends w/ \n\0 */
-static int getNextLine(char ** bufPtr, struct singleLine * line,
- struct configFileInfo * cfi) {
- char * end;
- char * start = *bufPtr;
- char * chptr;
- int elementsAlloced = 0;
- struct lineElement * element;
- int first = 1;
-
- lineFree(line);
-
- end = strchr(start, '\n');
- *end = '\0';
- *bufPtr = end + 1;
-
- for (chptr = start; *chptr && isspace(*chptr); chptr++) ;
-
- line->indent = strndup(start, chptr - start);
- start = chptr;
-
- while (start < end) {
- /* we know !isspace(*start) */
+static void lineInit(struct singleLine *line)
+{
+ line->indent = NULL;
+ line->elements = NULL;
+ line->numElements = 0;
+ line->next = NULL;
+}
- if (elementsAlloced == line->numElements) {
- elementsAlloced += 5;
- line->elements = realloc(line->elements,
- sizeof(*line->elements) * elementsAlloced);
- }
+struct singleLine *lineDup(struct singleLine *line)
+{
+ struct singleLine *newLine = malloc(sizeof(*newLine));
- element = line->elements + line->numElements;
+ newLine->indent = strdup(line->indent);
+ newLine->next = NULL;
+ newLine->type = line->type;
+ newLine->numElements = line->numElements;
+ newLine->elements = malloc(sizeof(*newLine->elements) *
+ newLine->numElements);
- chptr = start;
- while (*chptr && !isspace(*chptr)) {
- if (first && *chptr == '=') break;
- chptr++;
+ for (int i = 0; i < newLine->numElements; i++) {
+ newLine->elements[i].indent = strdup(line->elements[i].indent);
+ newLine->elements[i].item = strdup(line->elements[i].item);
}
- element->item = strndup(start, chptr - start);
- start = chptr;
-
- /* lilo actually accepts the pathological case of append = " foo " */
- if (*start == '=')
- chptr = start + 1;
- else
- chptr = start;
-
- do {
- for (; *chptr && isspace(*chptr); chptr++);
- if (*chptr == '=')
- chptr = chptr + 1;
- } while (isspace(*chptr));
-
- element->indent = strndup(start, chptr - start);
- start = chptr;
- line->numElements++;
- first = 0;
- }
-
- if (!line->numElements)
- line->type = LT_WHITESPACE;
- else {
- line->type = getTypeByKeyword(line->elements[0].item, cfi);
- if (line->type == LT_UNKNOWN) {
- /* zipl does [title] instead of something reasonable like all
- * the other boot loaders. kind of ugly */
- if (cfi->titleBracketed && isBracketedTitle(line)) {
- line->type = LT_TITLE;
- }
-
- /* this is awkward, but we need to be able to handle keywords
- that begin with a # (specifically for #boot in grub.conf),
- but still make comments lines with no elements (everything
- stored in the indent */
- if (*line->elements[0].item == '#') {
- char * fullLine;
- int len;
-
- len = strlen(line->indent);
- for (int i = 0; i < line->numElements; i++)
- len += strlen(line->elements[i].item) +
- strlen(line->elements[i].indent);
+ return newLine;
+}
- fullLine = malloc(len + 1);
- strcpy(fullLine, line->indent);
+static void lineFree(struct singleLine *line)
+{
+ if (line->indent)
free(line->indent);
- line->indent = fullLine;
- for (int i = 0; i < line->numElements; i++) {
- strcat(fullLine, line->elements[i].item);
- strcat(fullLine, line->elements[i].indent);
- free(line->elements[i].item);
- free(line->elements[i].indent);
+ for (int i = 0; i < line->numElements; i++) {
+ free(line->elements[i].item);
+ free(line->elements[i].indent);
+ }
+
+ if (line->elements)
+ free(line->elements);
+ lineInit(line);
+}
+
+static int lineWrite(FILE * out, struct singleLine *line,
+ struct configFileInfo *cfi)
+{
+ if (fprintf(out, "%s", line->indent) == -1)
+ return -1;
+
+ for (int i = 0; i < line->numElements; i++) {
+ /* Need to handle this, because we strip the quotes from
+ * menuentry when read it. */
+ if (line->type == LT_MENUENTRY && i == 1) {
+ if (!isquote(*line->elements[i].item)) {
+ int substring = 0;
+ /* If the line contains nested quotes, we did
+ * not strip the "interna" quotes and we must
+ * use the right quotes again when writing
+ * the updated file. */
+ for (int j = i; j < line->numElements; j++) {
+ if (strchr(line->elements[i].item, '\'')
+ != NULL) {
+ substring = 1;
+ fprintf(out, "\"%s\"",
+ line->elements[i].item);
+ break;
+ }
+ }
+ if (!substring)
+ fprintf(out, "\'%s\'",
+ line->elements[i].item);
+ } else {
+ fprintf(out, "%s", line->elements[i].item);
+ }
+ fprintf(out, "%s", line->elements[i].indent);
+
+ continue;
+ }
+
+ if (i == 1 && line->type == LT_KERNELARGS && cfi->argsInQuotes)
+ if (fputc('"', out) == EOF)
+ return -1;
+
+ if (fprintf(out, "%s", line->elements[i].item) == -1)
+ return -1;
+ if (i < line->numElements - 1)
+ if (fprintf(out, "%s", line->elements[i].indent) == -1)
+ return -1;
+ }
+
+ if (line->type == LT_KERNELARGS && cfi->argsInQuotes)
+ if (fputc('"', out) == EOF)
+ return -1;
+
+ if (fprintf(out, "\n") == -1)
+ return -1;
+
+ return 0;
+}
+
+/* we've guaranteed that the buffer ends w/ \n\0 */
+static int getNextLine(char **bufPtr, struct singleLine *line,
+ struct configFileInfo *cfi)
+{
+ char *end;
+ char *start = *bufPtr;
+ char *chptr;
+ int elementsAlloced = 0;
+ struct lineElement *element;
+ int first = 1;
+
+ lineFree(line);
+
+ end = strchr(start, '\n');
+ *end = '\0';
+ *bufPtr = end + 1;
+
+ for (chptr = start; *chptr && isspace(*chptr); chptr++) ;
+
+ line->indent = strndup(start, chptr - start);
+ start = chptr;
+
+ while (start < end) {
+ /* we know !isspace(*start) */
+
+ if (elementsAlloced == line->numElements) {
+ elementsAlloced += 5;
+ line->elements = realloc(line->elements,
+ sizeof(*line->elements) *
+ elementsAlloced);
+ }
+
+ element = line->elements + line->numElements;
+
+ chptr = start;
+ while (*chptr && !isspace(*chptr)) {
+ if (first && *chptr == '=')
+ break;
+ chptr++;
}
+ element->item = strndup(start, chptr - start);
+ start = chptr;
+
+ /* lilo actually accepts the pathological case of
+ * append = " foo " */
+ if (*start == '=')
+ chptr = start + 1;
+ else
+ chptr = start;
+
+ do {
+ for (; *chptr && isspace(*chptr); chptr++) ;
+ if (*chptr == '=')
+ chptr = chptr + 1;
+ } while (isspace(*chptr));
+
+ element->indent = strndup(start, chptr - start);
+ start = chptr;
+
+ line->numElements++;
+ first = 0;
+ }
+ if (!line->numElements)
line->type = LT_WHITESPACE;
- line->numElements = 0;
- }
- } else {
- struct keywordTypes *kw;
-
- kw = getKeywordByType(line->type, cfi);
-
- /* space isn't the only separator, we need to split
- * elements up more
- */
- if (!isspace(kw->separatorChar)) {
- char indent[2] = "";
- indent[0] = kw->separatorChar;
- for (int i = 1; i < line->numElements; i++) {
- char *p;
- int numNewElements;
-
- numNewElements = 0;
- p = line->elements[i].item;
- while (*p != '\0') {
- if (*p == kw->separatorChar)
- numNewElements++;
- p++;
- }
- if (line->numElements + numNewElements >= elementsAlloced) {
- elementsAlloced += numNewElements + 5;
- line->elements = realloc(line->elements,
- sizeof(*line->elements) * elementsAlloced);
+ else {
+ line->type = getTypeByKeyword(line->elements[0].item, cfi);
+ if (line->type == LT_UNKNOWN) {
+ /* zipl does [title] instead of something reasonable
+ * like all the other boot loaders. kind of ugly */
+ if (cfi->titleBracketed && isBracketedTitle(line)) {
+ line->type = LT_TITLE;
}
- for (int j = line->numElements; j > i; j--) {
- line->elements[j + numNewElements] = line->elements[j];
- }
- line->numElements += numNewElements;
+ /* this is awkward, but we need to be able to handle
+ * keywords that begin with a # (specifically for
+ * #boot in grub.conf), but still make comments lines
+ * with no elements (everything stored in the indent
+ */
+ if (*line->elements[0].item == '#') {
+ char *fullLine;
+ int len;
+
+ len = strlen(line->indent);
+ for (int i = 0; i < line->numElements; i++)
+ len += strlen(line->elements[i].item) +
+ strlen(line->elements[i].indent);
- p = line->elements[i].item;
- while (*p != '\0') {
+ fullLine = malloc(len + 1);
+ strcpy(fullLine, line->indent);
+ free(line->indent);
+ line->indent = fullLine;
- while (*p != kw->separatorChar && *p != '\0') p++;
- if (*p == '\0') {
- break;
+ for (int i = 0; i < line->numElements; i++) {
+ strcat(fullLine,
+ line->elements[i].item);
+ strcat(fullLine,
+ line->elements[i].indent);
+ free(line->elements[i].item);
+ free(line->elements[i].indent);
}
- line->elements[i + 1].indent = line->elements[i].indent;
- line->elements[i].indent = strdup(indent);
- *p++ = '\0';
- i++;
- line->elements[i].item = strdup(p);
+ line->type = LT_WHITESPACE;
+ line->numElements = 0;
+ }
+ } else {
+ struct keywordTypes *kw;
+
+ kw = getKeywordByType(line->type, cfi);
+
+ /* space isn't the only separator, we need to split
+ * elements up more
+ */
+ if (!isspace(kw->separatorChar)) {
+ char indent[2] = "";
+ indent[0] = kw->separatorChar;
+ for (int i = 1; i < line->numElements; i++) {
+ char *p;
+ int numNewElements;
+
+ numNewElements = 0;
+ p = line->elements[i].item;
+ while (*p != '\0') {
+ if (*p == kw->separatorChar)
+ numNewElements++;
+ p++;
+ }
+ if (line->numElements +
+ numNewElements >= elementsAlloced) {
+ elementsAlloced +=
+ numNewElements + 5;
+ line->elements =
+ realloc(line->elements,
+ sizeof(*line->
+ elements) *
+ elementsAlloced);
+ }
+
+ for (int j = line->numElements; j > i;
+ j--) {
+ line->elements[j +
+ numNewElements] =
+ line->elements[j];
+ }
+ line->numElements += numNewElements;
+
+ p = line->elements[i].item;
+ while (*p != '\0') {
+
+ while (*p != kw->separatorChar
+ && *p != '\0')
+ p++;
+ if (*p == '\0') {
+ break;
+ }
+
+ line->elements[i + 1].indent =
+ line->elements[i].indent;
+ line->elements[i].indent =
+ strdup(indent);
+ *p++ = '\0';
+ i++;
+ line->elements[i].item =
+ strdup(p);
+ }
+ }
}
- }
}
}
- }
- return 0;
+ return 0;
}
static int isnumber(const char *s)
{
- int i;
- for (i = 0; s[i] != '\0'; i++)
- if (s[i] < '0' || s[i] > '9')
- return 0;
- return i;
+ int i;
+ for (i = 0; s[i] != '\0'; i++)
+ if (s[i] < '0' || s[i] > '9')
+ return 0;
+ return i;
}
-static struct grubConfig * readConfig(const char * inName,
- struct configFileInfo * cfi) {
- int in;
- char * incoming = NULL, * head;
- int rc;
- int sawEntry = 0;
- int movedLine = 0;
- struct grubConfig * cfg;
- struct singleLine * last = NULL, * line, * defaultLine = NULL;
- char * end;
- struct singleEntry * entry = NULL;
- int len;
- char * buf;
-
- if (inName == NULL) {
- printf("Could not find bootloader configuration\n");
- exit(1);
- } else if (!strcmp(inName, "-")) {
- in = 0;
- } else {
- if ((in = open(inName, O_RDONLY)) < 0) {
- fprintf(stderr, _("error opening %s for read: %s\n"),
- inName, strerror(errno));
- return NULL;
- }
- }
-
- rc = readFile(in, &incoming);
- close(in);
- if (rc) return NULL;
-
- head = incoming;
- cfg = malloc(sizeof(*cfg));
- cfg->primaryIndent = strdup("");
- cfg->secondaryIndent = strdup("\t");
- cfg->flags = GRUB_CONFIG_NO_DEFAULT;
- cfg->cfi = cfi;
- cfg->theLines = NULL;
- cfg->entries = NULL;
- cfg->fallbackImage = 0;
-
- /* copy everything we have */
- while (*head) {
- line = malloc(sizeof(*line));
- lineInit(line);
-
- if (getNextLine(&head, line, cfi)) {
- free(line);
- /* XXX memory leak of everything in cfg */
- return NULL;
- }
-
- if (!sawEntry && line->numElements) {
- free(cfg->primaryIndent);
- cfg->primaryIndent = strdup(line->indent);
- } else if (line->numElements) {
- free(cfg->secondaryIndent);
- cfg->secondaryIndent = strdup(line->indent);
- }
-
- if (isEntryStart(line, cfi) || (cfg->entries && !sawEntry)) {
- sawEntry = 1;
- if (!entry) {
- cfg->entries = malloc(sizeof(*entry));
- entry = cfg->entries;
- } else {
- entry->next = malloc(sizeof(*entry));
- entry = entry->next;
- }
-
- entry->skip = 0;
- entry->multiboot = 0;
- entry->lines = NULL;
- entry->next = NULL;
+static struct grubConfig *readConfig(const char *inName,
+ struct configFileInfo *cfi)
+{
+ int in;
+ char *incoming = NULL, *head;
+ int rc;
+ int sawEntry = 0;
+ int movedLine = 0;
+ struct grubConfig *cfg;
+ struct singleLine *last = NULL, *line, *defaultLine = NULL;
+ char *end;
+ struct singleEntry *entry = NULL;
+ int len;
+ char *buf;
+
+ if (inName == NULL) {
+ printf("Could not find bootloader configuration\n");
+ exit(1);
+ } else if (!strcmp(inName, "-")) {
+ in = 0;
+ } else {
+ if ((in = open(inName, O_RDONLY)) < 0) {
+ fprintf(stderr, _("error opening %s for read: %s\n"),
+ inName, strerror(errno));
+ return NULL;
+ }
}
- if (line->type == LT_SET_VARIABLE) {
- dbgPrintf("found 'set' command (%d elements): ", line->numElements);
- dbgPrintf("%s", line->indent);
- for (int i = 0; i < line->numElements; i++)
- dbgPrintf("\"%s\"%s", line->elements[i].item, line->elements[i].indent);
- dbgPrintf("\n");
- struct keywordTypes *kwType = getKeywordByType(LT_DEFAULT, cfi);
- if (kwType && line->numElements == 3 &&
- !strcmp(line->elements[1].item, kwType->key) &&
- !is_special_grub2_variable(line->elements[2].item)) {
- dbgPrintf("Line sets default config\n");
- cfg->flags &= ~GRUB_CONFIG_NO_DEFAULT;
- defaultLine = line;
- }
-
- } else if (iskernel(line->type)) {
- /* if by some freak chance this is multiboot and the "module"
- * lines came earlier in the template, make sure to use LT_HYPER
- * instead of LT_KERNEL now
- */
- if (entry && entry->multiboot)
- line->type = LT_HYPER;
-
- } else if (line->type == LT_MBMODULE) {
- /* go back and fix the LT_KERNEL line to indicate LT_HYPER
- * instead, now that we know this is a multiboot entry.
- * This only applies to grub, but that's the only place we
- * should find LT_MBMODULE lines anyway.
- */
- for (struct singleLine *l = entry->lines; l; l = l->next) {
- if (l->type == LT_HYPER)
- break;
- else if (iskernel(l->type)) {
- l->type = LT_HYPER;
- break;
- }
- }
- entry->multiboot = 1;
-
- } else if (line->type == LT_HYPER) {
- entry->multiboot = 1;
-
- } else if (line->type == LT_FALLBACK && line->numElements == 2) {
- cfg->fallbackImage = strtol(line->elements[1].item, &end, 10);
- if (*end) cfg->fallbackImage = -1;
-
- } else if ((line->type == LT_DEFAULT && cfi->defaultIsUnquoted) ||
- (line->type == LT_TITLE && line->numElements > 1)) {
- /* make the title/default a single argument (undoing our parsing) */
- len = 0;
- for (int i = 1; i < line->numElements; i++) {
- len += strlen(line->elements[i].item);
- len += strlen(line->elements[i].indent);
- }
- buf = malloc(len + 1);
- *buf = '\0';
-
- for (int i = 1; i < line->numElements; i++) {
- strcat(buf, line->elements[i].item);
- free(line->elements[i].item);
-
- if ((i + 1) != line->numElements) {
- strcat(buf, line->elements[i].indent);
- free(line->elements[i].indent);
- }
- }
-
- line->elements[1].indent =
- line->elements[line->numElements - 1].indent;
- line->elements[1].item = buf;
- line->numElements = 2;
- } else if (line->type == LT_MENUENTRY && line->numElements > 3) {
- /* let --remove-kernel="TITLE=what" work */
- len = 0;
- char *extras;
- char *title;
- /* initially unseen value */
- char quote_char = '\0';
-
- for (int i = 1; i < line->numElements; i++) {
- len += strlen(line->elements[i].item);
- len += strlen(line->elements[i].indent);
- }
- buf = malloc(len + 1);
- *buf = '\0';
-
- /* allocate mem for extra flags. */
- extras = malloc(len + 1);
- *extras = '\0';
-
- /* get title. */
- for (int i = 0; i < line->numElements; i++) {
- if (!strcmp(line->elements[i].item, "menuentry"))
- continue;
- if (isquote(*line->elements[i].item) && quote_char == '\0') {
- /* ensure we properly pair off quotes */
- quote_char = *line->elements[i].item;
- title = line->elements[i].item + 1;
- } else {
- title = line->elements[i].item;
+ rc = readFile(in, &incoming);
+ close(in);
+ if (rc)
+ return NULL;
+
+ head = incoming;
+ cfg = malloc(sizeof(*cfg));
+ cfg->primaryIndent = strdup("");
+ cfg->secondaryIndent = strdup("\t");
+ cfg->flags = GRUB_CONFIG_NO_DEFAULT;
+ cfg->cfi = cfi;
+ cfg->theLines = NULL;
+ cfg->entries = NULL;
+ cfg->fallbackImage = 0;
+
+ /* copy everything we have */
+ while (*head) {
+ line = malloc(sizeof(*line));
+ lineInit(line);
+
+ if (getNextLine(&head, line, cfi)) {
+ free(line);
+ /* XXX memory leak of everything in cfg */
+ return NULL;
}
- len = strlen(title);
- if (title[len-1] == quote_char) {
- strncat(buf, title,len-1);
- break;
- } else {
- strcat(buf, title);
- strcat(buf, line->elements[i].indent);
+ if (!sawEntry && line->numElements) {
+ free(cfg->primaryIndent);
+ cfg->primaryIndent = strdup(line->indent);
+ } else if (line->numElements) {
+ free(cfg->secondaryIndent);
+ cfg->secondaryIndent = strdup(line->indent);
}
- }
-
- /* get extras */
- int count = 0;
- quote_char = '\0';
- for (int i = 0; i < line->numElements; i++) {
- if (count >= 2) {
- strcat(extras, line->elements[i].item);
- strcat(extras, line->elements[i].indent);
- }
-
- if (!strcmp(line->elements[i].item, "menuentry"))
- continue;
- /* count ' or ", there should be two in menuentry line. */
- if (isquote(*line->elements[i].item) && quote_char == '\0') {
- /* ensure we properly pair off quotes */
- quote_char = *line->elements[i].item;
- count++;
+ if (isEntryStart(line, cfi) || (cfg->entries && !sawEntry)) {
+ sawEntry = 1;
+ if (!entry) {
+ cfg->entries = malloc(sizeof(*entry));
+ entry = cfg->entries;
+ } else {
+ entry->next = malloc(sizeof(*entry));
+ entry = entry->next;
+ }
+
+ entry->skip = 0;
+ entry->multiboot = 0;
+ entry->lines = NULL;
+ entry->next = NULL;
}
- len = strlen(line->elements[i].item);
-
- if (line->elements[i].item[len -1] == quote_char)
- count++;
-
- /* ok, we get the final ' or ", others are extras. */
- }
- line->elements[1].indent =
- line->elements[line->numElements - 2].indent;
- line->elements[1].item = buf;
- line->elements[2].indent =
- line->elements[line->numElements - 2].indent;
- line->elements[2].item = extras;
- line->numElements = 3;
- } else if (line->type == LT_KERNELARGS && cfi->argsInQuotes) {
- /* Strip off any " which may be present; they'll be put back
- on write. This is one of the few (the only?) places that grubby
- canonicalizes the output */
-
- if (line->numElements >= 2) {
- int last, len;
-
- if (isquote(*line->elements[1].item))
- memmove(line->elements[1].item, line->elements[1].item + 1,
- strlen(line->elements[1].item + 1) + 1);
-
- last = line->numElements - 1;
- len = strlen(line->elements[last].item) - 1;
- if (isquote(line->elements[last].item[len]))
- line->elements[last].item[len] = '\0';
- }
- }
+ if (line->type == LT_SET_VARIABLE) {
+ dbgPrintf("found 'set' command (%d elements): ",
+ line->numElements);
+ dbgPrintf("%s", line->indent);
+ for (int i = 0; i < line->numElements; i++)
+ dbgPrintf("\"%s\"%s", line->elements[i].item,
+ line->elements[i].indent);
+ dbgPrintf("\n");
+ struct keywordTypes *kwType =
+ getKeywordByType(LT_DEFAULT, cfi);
+ if (kwType && line->numElements == 3
+ && !strcmp(line->elements[1].item, kwType->key)
+ && !is_special_grub2_variable(line->elements[2].
+ item)) {
+ dbgPrintf("Line sets default config\n");
+ cfg->flags &= ~GRUB_CONFIG_NO_DEFAULT;
+ defaultLine = line;
+ }
+
+ } else if (iskernel(line->type)) {
+ /* if by some freak chance this is multiboot and the
+ * "module" lines came earlier in the template, make
+ * sure to use LT_HYPER instead of LT_KERNEL now
+ */
+ if (entry && entry->multiboot)
+ line->type = LT_HYPER;
+
+ } else if (line->type == LT_MBMODULE) {
+ /* go back and fix the LT_KERNEL line to indicate
+ * LT_HYPER instead, now that we know this is a
+ * multiboot entry. This only applies to grub, but
+ * that's the only place we should find LT_MBMODULE
+ * lines anyway.
+ */
+ for (struct singleLine * l = entry->lines; l;
+ l = l->next) {
+ if (l->type == LT_HYPER)
+ break;
+ else if (iskernel(l->type)) {
+ l->type = LT_HYPER;
+ break;
+ }
+ }
+ entry->multiboot = 1;
+
+ } else if (line->type == LT_HYPER) {
+ entry->multiboot = 1;
+
+ } else if (line->type == LT_FALLBACK && line->numElements == 2) {
+ cfg->fallbackImage =
+ strtol(line->elements[1].item, &end, 10);
+ if (*end)
+ cfg->fallbackImage = -1;
+
+ } else if ((line->type == LT_DEFAULT && cfi->defaultIsUnquoted)
+ || (line->type == LT_TITLE
+ && line->numElements > 1)) {
+ /* make the title/default a single argument (undoing
+ * our parsing) */
+ len = 0;
+ for (int i = 1; i < line->numElements; i++) {
+ len += strlen(line->elements[i].item);
+ len += strlen(line->elements[i].indent);
+ }
+ buf = malloc(len + 1);
+ *buf = '\0';
+
+ for (int i = 1; i < line->numElements; i++) {
+ strcat(buf, line->elements[i].item);
+ free(line->elements[i].item);
+
+ if ((i + 1) != line->numElements) {
+ strcat(buf, line->elements[i].indent);
+ free(line->elements[i].indent);
+ }
+ }
+
+ line->elements[1].indent =
+ line->elements[line->numElements - 1].indent;
+ line->elements[1].item = buf;
+ line->numElements = 2;
+ } else if (line->type == LT_MENUENTRY && line->numElements > 3) {
+ /* let --remove-kernel="TITLE=what" work */
+ len = 0;
+ char *extras;
+ char *title;
+ /* initially unseen value */
+ char quote_char = '\0';
+
+ for (int i = 1; i < line->numElements; i++) {
+ len += strlen(line->elements[i].item);
+ len += strlen(line->elements[i].indent);
+ }
+ buf = malloc(len + 1);
+ *buf = '\0';
+
+ /* allocate mem for extra flags. */
+ extras = malloc(len + 1);
+ *extras = '\0';
+
+ /* get title. */
+ for (int i = 0; i < line->numElements; i++) {
+ if (!strcmp
+ (line->elements[i].item, "menuentry"))
+ continue;
+ if (isquote(*line->elements[i].item)
+ && quote_char == '\0') {
+ /* ensure we properly pair off quotes */
+ quote_char = *line->elements[i].item;
+ title = line->elements[i].item + 1;
+ } else {
+ title = line->elements[i].item;
+ }
+
+ len = strlen(title);
+ if (title[len - 1] == quote_char) {
+ strncat(buf, title, len - 1);
+ break;
+ } else {
+ strcat(buf, title);
+ strcat(buf, line->elements[i].indent);
+ }
+ }
+
+ /* get extras */
+ int count = 0;
+ quote_char = '\0';
+ for (int i = 0; i < line->numElements; i++) {
+ if (count >= 2) {
+ strcat(extras, line->elements[i].item);
+ strcat(extras,
+ line->elements[i].indent);
+ }
+
+ if (!strcmp
+ (line->elements[i].item, "menuentry"))
+ continue;
+
+ /* count ' or ", there should be two in menuentry line. */
+ if (isquote(*line->elements[i].item)
+ && quote_char == '\0') {
+ /* ensure we properly pair off quotes */
+ quote_char = *line->elements[i].item;
+ count++;
+ }
+
+ len = strlen(line->elements[i].item);
+
+ if (line->elements[i].item[len - 1] ==
+ quote_char)
+ count++;
+
+ /* ok, we get the final ' or ", others are extras. */
+ }
+ line->elements[1].indent =
+ line->elements[line->numElements - 2].indent;
+ line->elements[1].item = buf;
+ line->elements[2].indent =
+ line->elements[line->numElements - 2].indent;
+ line->elements[2].item = extras;
+ line->numElements = 3;
+ } else if (line->type == LT_KERNELARGS && cfi->argsInQuotes) {
+ /* Strip off any " which may be present; they'll be
+ * put back on write. This is one of the few (the
+ * only?) places that grubby canonicalizes the output
+ */
+ if (line->numElements >= 2) {
+ int last, len;
+
+ if (isquote(*line->elements[1].item))
+ memmove(line->elements[1].item,
+ line->elements[1].item + 1,
+ strlen(line->elements[1].item +
+ 1) + 1);
+
+ last = line->numElements - 1;
+ len = strlen(line->elements[last].item) - 1;
+ if (isquote(line->elements[last].item[len]))
+ line->elements[last].item[len] = '\0';
+ }
+ }
- if (line->type == LT_DEFAULT && line->numElements == 2) {
- cfg->flags &= ~GRUB_CONFIG_NO_DEFAULT;
- defaultLine = line;
- }
+ if (line->type == LT_DEFAULT && line->numElements == 2) {
+ cfg->flags &= ~GRUB_CONFIG_NO_DEFAULT;
+ defaultLine = line;
+ }
- /* If we find a generic config option which should live at the
- top of the file, move it there. Old versions of grubby were
- probably responsible for putting new images in the wrong
- place in front of it anyway. */
- if (sawEntry && line->type == LT_GENERIC) {
- struct singleLine **l = &cfg->theLines;
- struct singleLine **last_nonws = &cfg->theLines;
- while (*l) {
- if ((*l)->type != LT_WHITESPACE)
- last_nonws = &((*l)->next);
- l = &((*l)->next);
+ /* If we find a generic config option which should live at the
+ top of the file, move it there. Old versions of grubby were
+ probably responsible for putting new images in the wrong
+ place in front of it anyway. */
+ if (sawEntry && line->type == LT_GENERIC) {
+ struct singleLine **l = &cfg->theLines;
+ struct singleLine **last_nonws = &cfg->theLines;
+ while (*l) {
+ if ((*l)->type != LT_WHITESPACE)
+ last_nonws = &((*l)->next);
+ l = &((*l)->next);
+ }
+ line->next = *last_nonws;
+ *last_nonws = line;
+ movedLine = 1;
+ continue; /* without setting 'last' */
}
- line->next = *last_nonws;
- *last_nonws = line;
- movedLine = 1;
- continue; /* without setting 'last' */
- }
- /* If a second line of whitespace happens after a generic option
- which was moved, drop it. */
- if (movedLine && line->type == LT_WHITESPACE && last->type == LT_WHITESPACE) {
- lineFree(line);
- free(line);
+ /* If a second line of whitespace happens after a generic
+ * option which was moved, drop it. */
+ if (movedLine && line->type == LT_WHITESPACE
+ && last->type == LT_WHITESPACE) {
+ lineFree(line);
+ free(line);
+ movedLine = 0;
+ continue;
+ }
movedLine = 0;
- continue;
- }
- movedLine = 0;
- if (sawEntry) {
- if (!entry->lines)
- entry->lines = line;
- else
- last->next = line;
- dbgPrintf("readConfig added %s to %p\n", getKeyByType(line->type, cfi), entry);
+ if (sawEntry) {
+ if (!entry->lines)
+ entry->lines = line;
+ else
+ last->next = line;
+ dbgPrintf("readConfig added %s to %p\n",
+ getKeyByType(line->type, cfi), entry);
+
+ /* we could have seen this outside of an entry... if
+ * so, we ignore it like any other line we don't grok
+ */
+ if (line->type == LT_ENTRY_END && sawEntry)
+ sawEntry = 0;
+ } else {
+ if (!cfg->theLines)
+ cfg->theLines = line;
+ else
+ last->next = line;
+ dbgPrintf("readConfig added %s to cfg\n",
+ getKeyByType(line->type, cfi));
+ }
- /* we could have seen this outside of an entry... if so, we
- * ignore it like any other line we don't grok */
- if (line->type == LT_ENTRY_END && sawEntry)
- sawEntry = 0;
- } else {
- if (!cfg->theLines)
- cfg->theLines = line;
- else
- last->next = line;
- dbgPrintf("readConfig added %s to cfg\n", getKeyByType(line->type, cfi));
+ last = line;
}
- last = line;
- }
+ free(incoming);
+
+ dbgPrintf("defaultLine is %s\n", defaultLine ? "set" : "unset");
+ if (defaultLine) {
+ if (defaultLine->numElements > 2 &&
+ cfi->defaultSupportSaved &&
+ !strncmp(defaultLine->elements[2].item,
+ "\"${saved_entry}\"", 16)) {
+ cfg->cfi->defaultIsSaved = 1;
+ cfg->defaultImage = DEFAULT_SAVED_GRUB2;
+ if (cfg->cfi->getEnv) {
+ char *defTitle =
+ cfi->getEnv(cfg->cfi, "saved_entry");
+ if (defTitle) {
+ int index = 0;
+ if (isnumber(defTitle)) {
+ index = atoi(defTitle);
+ entry =
+ findEntryByIndex(cfg,
+ index);
+ } else {
+ entry =
+ findEntryByTitle(cfg,
+ defTitle,
+ &index);
+ }
+ if (entry)
+ cfg->defaultImage = index;
+ }
+ }
+ } else if (cfi->defaultIsVariable) {
+ char *value = defaultLine->elements[2].item;
+ while (*value && (*value == '"' || *value == '\'' ||
+ *value == ' ' || *value == '\t'))
+ value++;
+ cfg->defaultImage = strtol(value, &end, 10);
+ while (*end && (*end == '"' || *end == '\'' ||
+ *end == ' ' || *end == '\t'))
+ end++;
+ if (*end)
+ cfg->defaultImage = -1;
+ } else if (cfi->defaultSupportSaved &&
+ !strncmp(defaultLine->elements[1].item, "saved",
+ 5)) {
+ cfg->defaultImage = DEFAULT_SAVED;
+ } else if (cfi->defaultIsIndex) {
+ cfg->defaultImage =
+ strtol(defaultLine->elements[1].item, &end, 10);
+ if (*end)
+ cfg->defaultImage = -1;
+ } else if (defaultLine->numElements >= 2) {
+ int i = 0;
+ while ((entry = findEntryByIndex(cfg, i))) {
+ for (line = entry->lines; line;
+ line = line->next)
+ if (line->type == LT_TITLE)
+ break;
- free(incoming);
+ if (!cfi->titleBracketed) {
+ if (line && (line->numElements >= 2) &&
+ !strcmp(defaultLine->elements[1].
+ item,
+ line->elements[1].item))
+ break;
+ } else if (line) {
+ if (!strcmp
+ (defaultLine->elements[1].item,
+ extractTitle(cfg, line)))
+ break;
+ }
+ i++;
+ entry = NULL;
+ }
- dbgPrintf("defaultLine is %s\n", defaultLine ? "set" : "unset");
- if (defaultLine) {
- if (defaultLine->numElements > 2 &&
- cfi->defaultSupportSaved &&
- !strncmp(defaultLine->elements[2].item,"\"${saved_entry}\"", 16)) {
- cfg->cfi->defaultIsSaved = 1;
- cfg->defaultImage = DEFAULT_SAVED_GRUB2;
- if (cfg->cfi->getEnv) {
- char *defTitle = cfi->getEnv(cfg->cfi, "saved_entry");
- if (defTitle) {
+ if (entry) {
+ cfg->defaultImage = i;
+ } else {
+ cfg->defaultImage = -1;
+ }
+ }
+ } else if (cfg->cfi->defaultIsSaved && cfg->cfi->getEnv) {
+ char *defTitle = cfi->getEnv(cfg->cfi, "saved_entry");
+ if (defTitle) {
int index = 0;
if (isnumber(defTitle)) {
- index = atoi(defTitle);
- entry = findEntryByIndex(cfg, index);
+ index = atoi(defTitle);
+ entry = findEntryByIndex(cfg, index);
} else {
- entry = findEntryByTitle(cfg, defTitle, &index);
+ entry = findEntryByTitle(cfg, defTitle, &index);
}
if (entry)
- cfg->defaultImage = index;
- }
+ cfg->defaultImage = index;
}
- } else if (cfi->defaultIsVariable) {
- char *value = defaultLine->elements[2].item;
- while (*value && (*value == '"' || *value == '\'' ||
- *value == ' ' || *value == '\t'))
- value++;
- cfg->defaultImage = strtol(value, &end, 10);
- while (*end && (*end == '"' || *end == '\'' ||
- *end == ' ' || *end == '\t'))
- end++;
- if (*end) cfg->defaultImage = -1;
- } else if (cfi->defaultSupportSaved &&
- !strncmp(defaultLine->elements[1].item, "saved", 5)) {
- cfg->defaultImage = DEFAULT_SAVED;
- } else if (cfi->defaultIsIndex) {
- cfg->defaultImage = strtol(defaultLine->elements[1].item, &end, 10);
- if (*end) cfg->defaultImage = -1;
- } else if (defaultLine->numElements >= 2) {
- int i = 0;
- while ((entry = findEntryByIndex(cfg, i))) {
- for (line = entry->lines; line; line = line->next)
- if (line->type == LT_TITLE) break;
-
- if (!cfi->titleBracketed) {
- if (line && (line->numElements >= 2) &&
- !strcmp(defaultLine->elements[1].item,
- line->elements[1].item)) break;
- } else if (line) {
- if (!strcmp(defaultLine->elements[1].item,
- extractTitle(cfg, line))) break;
- }
- i++;
- entry = NULL;
- }
-
- if (entry){
- cfg->defaultImage = i;
- }else{
- cfg->defaultImage = -1;
- }
- }
- } else if (cfg->cfi->defaultIsSaved && cfg->cfi->getEnv) {
- char *defTitle = cfi->getEnv(cfg->cfi, "saved_entry");
- if (defTitle) {
- int index = 0;
- if (isnumber(defTitle)) {
- index = atoi(defTitle);
- entry = findEntryByIndex(cfg, index);
- } else {
- entry = findEntryByTitle(cfg, defTitle, &index);
- }
- if (entry)
- cfg->defaultImage = index;
- }
- } else {
- cfg->defaultImage = 0;
- }
-
- return cfg;
-}
-
-static void writeDefault(FILE * out, char * indent,
- char * separator, struct grubConfig * cfg) {
- struct singleEntry * entry;
- struct singleLine * line;
- int i;
-
- if (!cfg->defaultImage && cfg->flags == GRUB_CONFIG_NO_DEFAULT)
- return;
-
- if (cfg->defaultImage == DEFAULT_SAVED)
- fprintf(out, "%sdefault%ssaved\n", indent, separator);
- else if (cfg->cfi->defaultIsSaved) {
- fprintf(out, "%sset default=\"${saved_entry}\"\n", indent);
- if (cfg->defaultImage >= 0 && cfg->cfi->setEnv) {
- char *title;
- entry = findEntryByIndex(cfg, cfg->defaultImage);
- line = getLineByType(LT_MENUENTRY, entry->lines);
- if (!line)
- line = getLineByType(LT_TITLE, entry->lines);
- if (line) {
- title = extractTitle(cfg, line);
- if (title)
- cfg->cfi->setEnv(cfg->cfi, "saved_entry", title);
- }
- }
- } else if (cfg->defaultImage > -1) {
- if (cfg->cfi->defaultIsIndex) {
- if (cfg->cfi->defaultIsVariable) {
- fprintf(out, "%sset default=\"%d\"\n", indent,
- cfg->defaultImage);
- } else {
- fprintf(out, "%sdefault%s%d\n", indent, separator,
- cfg->defaultImage);
- }
} else {
- int image = cfg->defaultImage;
+ cfg->defaultImage = 0;
+ }
- entry = cfg->entries;
- while (entry && entry->skip)
- entry = entry->next;
+ return cfg;
+}
- i = 0;
- while (entry && i < image) {
- entry = entry->next;
+static void writeDefault(FILE * out, char *indent,
+ char *separator, struct grubConfig *cfg)
+{
+ struct singleEntry *entry;
+ struct singleLine *line;
+ int i;
- while (entry && entry->skip)
- entry = entry->next;
- i++;
- }
-
- if (!entry)
+ if (!cfg->defaultImage && cfg->flags == GRUB_CONFIG_NO_DEFAULT)
return;
- line = getLineByType(LT_TITLE, entry->lines);
-
- if (line && line->numElements >= 2)
- fprintf(out, "%sdefault%s%s\n", indent, separator,
- line->elements[1].item);
- else if (line && (line->numElements == 1) &&
- cfg->cfi->titleBracketed) {
- char *title = extractTitle(cfg, line);
- if (title) {
- fprintf(out, "%sdefault%s%s\n", indent, separator, title);
- free(title);
+ if (cfg->defaultImage == DEFAULT_SAVED)
+ fprintf(out, "%sdefault%ssaved\n", indent, separator);
+ else if (cfg->cfi->defaultIsSaved) {
+ fprintf(out, "%sset default=\"${saved_entry}\"\n", indent);
+ if (cfg->defaultImage >= 0 && cfg->cfi->setEnv) {
+ char *title;
+ entry = findEntryByIndex(cfg, cfg->defaultImage);
+ line = getLineByType(LT_MENUENTRY, entry->lines);
+ if (!line)
+ line = getLineByType(LT_TITLE, entry->lines);
+ if (line) {
+ title = extractTitle(cfg, line);
+ if (title)
+ cfg->cfi->setEnv(cfg->cfi,
+ "saved_entry", title);
+ }
+ }
+ } else if (cfg->defaultImage > -1) {
+ if (cfg->cfi->defaultIsIndex) {
+ if (cfg->cfi->defaultIsVariable) {
+ fprintf(out, "%sset default=\"%d\"\n", indent,
+ cfg->defaultImage);
+ } else {
+ fprintf(out, "%sdefault%s%d\n", indent,
+ separator, cfg->defaultImage);
+ }
+ } else {
+ int image = cfg->defaultImage;
+
+ entry = cfg->entries;
+ while (entry && entry->skip)
+ entry = entry->next;
+
+ i = 0;
+ while (entry && i < image) {
+ entry = entry->next;
+
+ while (entry && entry->skip)
+ entry = entry->next;
+ i++;
+ }
+
+ if (!entry)
+ return;
+
+ line = getLineByType(LT_TITLE, entry->lines);
+
+ if (line && line->numElements >= 2)
+ fprintf(out, "%sdefault%s%s\n", indent,
+ separator, line->elements[1].item);
+ else if (line && (line->numElements == 1)
+ && cfg->cfi->titleBracketed) {
+ char *title = extractTitle(cfg, line);
+ if (title) {
+ fprintf(out, "%sdefault%s%s\n", indent,
+ separator, title);
+ free(title);
+ }
+ }
}
- }
}
- }
}
-static int writeConfig(struct grubConfig * cfg, char * outName,
- const char * prefix) {
- FILE * out;
- struct singleLine * line;
- struct singleEntry * entry;
- char * tmpOutName;
- int needs = MAIN_DEFAULT;
- struct stat sb;
- int i;
-
- if (!strcmp(outName, "-")) {
- out = stdout;
- tmpOutName = NULL;
- } else {
- if (!lstat(outName, &sb) && S_ISLNK(sb.st_mode)) {
- char * buf;
- int len = 256;
- int rc;
-
- /* most likely the symlink is relative, so change our
- directory to the dir of the symlink */
- char *dir = strdupa(outName);
- rc = chdir(dirname(dir));
- do {
- buf = alloca(len + 1);
- rc = readlink(basename(outName), buf, len);
- if (rc == len) len += 256;
- } while (rc == len);
-
- if (rc < 0) {
- fprintf(stderr, _("grubby: error readlink link %s: %s\n"),
- outName, strerror(errno));
- return 1;
- }
-
- outName = buf;
- outName[rc] = '\0';
- }
-
- tmpOutName = alloca(strlen(outName) + 2);
- sprintf(tmpOutName, "%s-", outName);
- out = fopen(tmpOutName, "w");
- if (!out) {
- fprintf(stderr, _("grubby: error creating %s: %s\n"), tmpOutName,
- strerror(errno));
- return 1;
- }
-
- if (!stat(outName, &sb)) {
- if (chmod(tmpOutName, sb.st_mode & ~(S_IFMT))) {
- fprintf(stderr, _("grubby: error setting perms on %s: %s\n"),
- tmpOutName, strerror(errno));
- fclose(out);
- unlink(tmpOutName);
- return 1;
- }
- }
- }
-
- line = cfg->theLines;
- struct keywordTypes *defaultKw = getKeywordByType(LT_DEFAULT, cfg->cfi);
- while (line) {
- if (line->type == LT_SET_VARIABLE && defaultKw &&
- line->numElements == 3 &&
- !strcmp(line->elements[1].item, defaultKw->key) &&
- !is_special_grub2_variable(line->elements[2].item)) {
- writeDefault(out, line->indent, line->elements[0].indent, cfg);
- needs &= ~MAIN_DEFAULT;
- } else if (line->type == LT_DEFAULT) {
- writeDefault(out, line->indent, line->elements[0].indent, cfg);
- needs &= ~MAIN_DEFAULT;
- } else if (line->type == LT_FALLBACK) {
- if (cfg->fallbackImage > -1)
- fprintf(out, "%s%s%s%d\n", line->indent,
- line->elements[0].item, line->elements[0].indent,
- cfg->fallbackImage);
+static int writeConfig(struct grubConfig *cfg, char *outName,
+ const char *prefix)
+{
+ FILE *out;
+ struct singleLine *line;
+ struct singleEntry *entry;
+ char *tmpOutName;
+ int needs = MAIN_DEFAULT;
+ struct stat sb;
+ int i;
+
+ if (!strcmp(outName, "-")) {
+ out = stdout;
+ tmpOutName = NULL;
} else {
- if (lineWrite(out, line, cfg->cfi) == -1) {
- fprintf(stderr, _("grubby: error writing %s: %s\n"),
- tmpOutName, strerror(errno));
- fclose(out);
- unlink(tmpOutName);
- return 1;
- }
+ if (!lstat(outName, &sb) && S_ISLNK(sb.st_mode)) {
+ char *buf;
+ int len = 256;
+ int rc;
+
+ /* most likely the symlink is relative, so change our
+ directory to the dir of the symlink */
+ char *dir = strdupa(outName);
+ rc = chdir(dirname(dir));
+ do {
+ buf = alloca(len + 1);
+ rc = readlink(basename(outName), buf, len);
+ if (rc == len)
+ len += 256;
+ } while (rc == len);
+
+ if (rc < 0) {
+ fprintf(stderr,
+ _
+ ("grubby: error readlink link %s: %s\n"),
+ outName, strerror(errno));
+ return 1;
+ }
+
+ outName = buf;
+ outName[rc] = '\0';
+ }
+
+ tmpOutName = alloca(strlen(outName) + 2);
+ sprintf(tmpOutName, "%s-", outName);
+ out = fopen(tmpOutName, "w");
+ if (!out) {
+ fprintf(stderr, _("grubby: error creating %s: %s\n"),
+ tmpOutName, strerror(errno));
+ return 1;
+ }
+
+ if (!stat(outName, &sb)) {
+ if (chmod(tmpOutName, sb.st_mode & ~(S_IFMT))) {
+ fprintf(stderr,
+ _
+ ("grubby: error setting perms on %s: %s\n"),
+ tmpOutName, strerror(errno));
+ fclose(out);
+ unlink(tmpOutName);
+ return 1;
+ }
+ }
}
- line = line->next;
- }
-
- if (needs & MAIN_DEFAULT) {
- writeDefault(out, cfg->primaryIndent, "=", cfg);
- needs &= ~MAIN_DEFAULT;
- }
-
- i = 0;
- while ((entry = findEntryByIndex(cfg, i++))) {
- if (entry->skip) continue;
-
- line = entry->lines;
+ line = cfg->theLines;
+ struct keywordTypes *defaultKw = getKeywordByType(LT_DEFAULT, cfg->cfi);
while (line) {
- if (lineWrite(out, line, cfg->cfi) == -1) {
- fprintf(stderr, _("grubby: error writing %s: %s\n"),
- tmpOutName, strerror(errno));
- fclose(out);
- unlink(tmpOutName);
- return 1;
- }
- line = line->next;
+ if (line->type == LT_SET_VARIABLE && defaultKw &&
+ line->numElements == 3 &&
+ !strcmp(line->elements[1].item, defaultKw->key) &&
+ !is_special_grub2_variable(line->elements[2].item)) {
+ writeDefault(out, line->indent,
+ line->elements[0].indent, cfg);
+ needs &= ~MAIN_DEFAULT;
+ } else if (line->type == LT_DEFAULT) {
+ writeDefault(out, line->indent,
+ line->elements[0].indent, cfg);
+ needs &= ~MAIN_DEFAULT;
+ } else if (line->type == LT_FALLBACK) {
+ if (cfg->fallbackImage > -1)
+ fprintf(out, "%s%s%s%d\n", line->indent,
+ line->elements[0].item,
+ line->elements[0].indent,
+ cfg->fallbackImage);
+ } else {
+ if (lineWrite(out, line, cfg->cfi) == -1) {
+ fprintf(stderr,
+ _("grubby: error writing %s: %s\n"),
+ tmpOutName, strerror(errno));
+ fclose(out);
+ unlink(tmpOutName);
+ return 1;
+ }
+ }
+
+ line = line->next;
+ }
+
+ if (needs & MAIN_DEFAULT) {
+ writeDefault(out, cfg->primaryIndent, "=", cfg);
+ needs &= ~MAIN_DEFAULT;
+ }
+
+ i = 0;
+ while ((entry = findEntryByIndex(cfg, i++))) {
+ if (entry->skip)
+ continue;
+
+ line = entry->lines;
+ while (line) {
+ if (lineWrite(out, line, cfg->cfi) == -1) {
+ fprintf(stderr,
+ _("grubby: error writing %s: %s\n"),
+ tmpOutName, strerror(errno));
+ fclose(out);
+ unlink(tmpOutName);
+ return 1;
+ }
+ line = line->next;
+ }
}
- }
- if (tmpOutName) {
- if (rename(tmpOutName, outName)) {
- fprintf(stderr, _("grubby: error moving %s to %s: %s\n"),
- tmpOutName, outName, strerror(errno));
- unlink(outName);
- return 1;
+ if (tmpOutName) {
+ if (rename(tmpOutName, outName)) {
+ fprintf(stderr,
+ _("grubby: error moving %s to %s: %s\n"),
+ tmpOutName, outName, strerror(errno));
+ unlink(outName);
+ return 1;
+ }
}
- }
- return 0;
+ return 0;
}
-static int numEntries(struct grubConfig *cfg) {
- int i = 0;
- struct singleEntry * entry;
+static int numEntries(struct grubConfig *cfg)
+{
+ int i = 0;
+ struct singleEntry *entry;
- entry = cfg->entries;
- while (entry) {
- if (!entry->skip)
- i++;
- entry = entry->next;
- }
- return i;
+ entry = cfg->entries;
+ while (entry) {
+ if (!entry->skip)
+ i++;
+ entry = entry->next;
+ }
+ return i;
}
static char *findDiskForRoot()
{
- int fd;
- char buf[65536];
- char *devname;
- char *chptr;
- int rc;
-
- if ((fd = open(_PATH_MOUNTED, O_RDONLY)) < 0) {
- fprintf(stderr, "grubby: failed to open %s: %s\n",
- _PATH_MOUNTED, strerror(errno));
- return NULL;
- }
-
- rc = read(fd, buf, sizeof(buf) - 1);
- if (rc <= 0) {
- fprintf(stderr, "grubby: failed to read %s: %s\n",
- _PATH_MOUNTED, strerror(errno));
- close(fd);
- return NULL;
- }
- close(fd);
- buf[rc] = '\0';
- chptr = buf;
-
- char *foundanswer = NULL;
-
- while (chptr && chptr != buf+rc) {
- devname = chptr;
-
- /*
- * The first column of a mtab entry is the device, but if the entry is a
- * special device it won't start with /, so move on to the next line.
- */
- if (*devname != '/') {
- chptr = strchr(chptr, '\n');
- if (chptr)
- chptr++;
- continue;
- }
-
- /* Seek to the next space */
- chptr = strchr(chptr, ' ');
- if (!chptr) {
- fprintf(stderr, "grubby: error parsing %s: %s\n",
- _PATH_MOUNTED, strerror(errno));
- return NULL;
- }
-
- /*
- * The second column of a mtab entry is the mount point, we are looking
- * for '/' obviously.
- */
- if (*(++chptr) == '/' && *(++chptr) == ' ') {
- /* remember the last / entry in mtab */
- foundanswer = devname;
- }
-
- /* Next line */
- chptr = strchr(chptr, '\n');
- if (chptr)
- chptr++;
- }
-
- /* Return the last / entry found */
- if (foundanswer) {
- chptr = strchr(foundanswer, ' ');
- *chptr = '\0';
- return strdup(foundanswer);
- }
-
- return NULL;
+ int fd;
+ char buf[65536];
+ char *devname;
+ char *chptr;
+ int rc;
+
+ if ((fd = open(_PATH_MOUNTED, O_RDONLY)) < 0) {
+ fprintf(stderr, "grubby: failed to open %s: %s\n",
+ _PATH_MOUNTED, strerror(errno));
+ return NULL;
+ }
+
+ rc = read(fd, buf, sizeof(buf) - 1);
+ if (rc <= 0) {
+ fprintf(stderr, "grubby: failed to read %s: %s\n",
+ _PATH_MOUNTED, strerror(errno));
+ close(fd);
+ return NULL;
+ }
+ close(fd);
+ buf[rc] = '\0';
+ chptr = buf;
+
+ char *foundanswer = NULL;
+
+ while (chptr && chptr != buf + rc) {
+ devname = chptr;
+
+ /*
+ * The first column of a mtab entry is the device, but if the
+ * entry is a special device it won't start with /, so move
+ * on to the next line.
+ */
+ if (*devname != '/') {
+ chptr = strchr(chptr, '\n');
+ if (chptr)
+ chptr++;
+ continue;
+ }
+
+ /* Seek to the next space */
+ chptr = strchr(chptr, ' ');
+ if (!chptr) {
+ fprintf(stderr, "grubby: error parsing %s: %s\n",
+ _PATH_MOUNTED, strerror(errno));
+ return NULL;
+ }
+
+ /*
+ * The second column of a mtab entry is the mount point, we
+ * are looking for '/' obviously.
+ */
+ if (*(++chptr) == '/' && *(++chptr) == ' ') {
+ /* remember the last / entry in mtab */
+ foundanswer = devname;
+ }
+
+ /* Next line */
+ chptr = strchr(chptr, '\n');
+ if (chptr)
+ chptr++;
+ }
+
+ /* Return the last / entry found */
+ if (foundanswer) {
+ chptr = strchr(foundanswer, ' ');
+ *chptr = '\0';
+ return strdup(foundanswer);
+ }
+
+ return NULL;
}
-void printEntry(struct singleEntry * entry, FILE *f) {
- int i;
- struct singleLine * line;
-
- for (line = entry->lines; line; line = line->next) {
- log_message(f, "DBG: %s", line->indent);
- for (i = 0; i < line->numElements; i++) {
- /* Need to handle this, because we strip the quotes from
- * menuentry when read it. */
- if (line->type == LT_MENUENTRY && i == 1) {
- if(!isquote(*line->elements[i].item))
- log_message(f, "\'%s\'", line->elements[i].item);
- else
- log_message(f, "%s", line->elements[i].item);
- log_message(f, "%s", line->elements[i].indent);
-
- continue;
- }
-
- log_message(f, "%s%s",
- line->elements[i].item, line->elements[i].indent);
+void printEntry(struct singleEntry *entry, FILE * f)
+{
+ int i;
+ struct singleLine *line;
+
+ for (line = entry->lines; line; line = line->next) {
+ log_message(f, "DBG: %s", line->indent);
+ for (i = 0; i < line->numElements; i++) {
+ /* Need to handle this, because we strip the quotes from
+ * menuentry when read it. */
+ if (line->type == LT_MENUENTRY && i == 1) {
+ if (!isquote(*line->elements[i].item))
+ log_message(f, "\'%s\'",
+ line->elements[i].item);
+ else
+ log_message(f, "%s",
+ line->elements[i].item);
+ log_message(f, "%s", line->elements[i].indent);
+
+ continue;
+ }
+
+ log_message(f, "%s%s",
+ line->elements[i].item,
+ line->elements[i].indent);
+ }
+ log_message(f, "\n");
}
- log_message(f, "\n");
- }
}
-void notSuitablePrintf(struct singleEntry * entry, int okay, const char *fmt, ...)
+void notSuitablePrintf(struct singleEntry *entry, int okay, const char *fmt,
+ ...)
{
- static int once;
- va_list argp, argq;
-
- va_start(argp, fmt);
-
- va_copy(argq, argp);
- if (!once) {
- log_time(NULL);
- log_message(NULL, "command line: %s\n", saved_command_line);
- }
- log_message(NULL, "DBG: Image entry %s: ", okay ? "succeeded" : "failed");
- log_vmessage(NULL, fmt, argq);
-
- printEntry(entry, NULL);
- va_end(argq);
-
- if (!debug) {
+ static int once;
+ va_list argp, argq;
+
+ va_start(argp, fmt);
+
+ va_copy(argq, argp);
+ if (!once) {
+ log_time(NULL);
+ log_message(NULL, "command line: %s\n", saved_command_line);
+ }
+ log_message(NULL, "DBG: Image entry %s: ",
+ okay ? "succeeded" : "failed");
+ log_vmessage(NULL, fmt, argq);
+
+ printEntry(entry, NULL);
+ va_end(argq);
+
+ if (!debug) {
+ once = 1;
+ va_end(argp);
+ return;
+ }
+
+ if (okay) {
+ va_end(argp);
+ return;
+ }
+
+ if (!once)
+ log_message(stderr, "DBG: command line: %s\n",
+ saved_command_line);
once = 1;
- va_end(argp);
- return;
- }
-
- if (okay) {
+ fprintf(stderr, "DBG: Image entry failed: ");
+ vfprintf(stderr, fmt, argp);
+ printEntry(entry, stderr);
va_end(argp);
- return;
- }
-
- if (!once)
- log_message(stderr, "DBG: command line: %s\n", saved_command_line);
- once = 1;
- fprintf(stderr, "DBG: Image entry failed: ");
- vfprintf(stderr, fmt, argp);
- printEntry(entry, stderr);
- va_end(argp);
}
#define beginswith(s, c) ((s) && (s)[0] == (c))
@@ -1867,281 +1993,318 @@ static int endswith(const char *s, char c)
return s[slen] == c;
}
-int suitableImage(struct singleEntry * entry, const char * bootPrefix,
- int skipRemoved, int flags) {
- struct singleLine * line;