]> git.ozlabs.org Git - petitboot/blobdiff - discover/syslinux-parser.c
discover/parser: Hookup parser_is_unique
[petitboot] / discover / syslinux-parser.c
index 8aef9c3b5ea878fefce296bb6e628f1edf2db830..38cfd1d32a5925f256457c1a5ab8552823c0da14 100644 (file)
@@ -36,7 +36,6 @@ struct syslinux_options {
        char *cfg_dir;
 };
 
-
 static const char *const syslinux_conf_files[] = {
        "/boot/syslinux/syslinux.cfg",
        "/syslinux/syslinux.cfg",
@@ -83,7 +82,7 @@ static const char *const syslinux_ignored_names[] = {
        "f2",
        "f3",
        "f4",
-       "f5"
+       "f5",
        "f6",
        "f7",
        "f8",
@@ -285,7 +284,7 @@ static void syslinux_process_pair(struct conf_context *conf, const char *name, c
 static void syslinux_finalize(struct conf_context *conf)
 {
        struct syslinux_options *state = conf->parser_info;
-       struct syslinux_boot_option *syslinux_opt;
+       struct syslinux_boot_option *syslinux_opt, *tmp;
        struct discover_context *dc = conf->dc;
        struct discover_boot_option *d_opt;
        bool implicit_image = true;
@@ -333,11 +332,13 @@ static void syslinux_finalize(struct conf_context *conf)
                        /* '-' can signal do not use global APPEND */
                        if (!strcmp(syslinux_opt->append, "-"))
                                opt->boot_args = talloc_strdup(opt, "");
-                       else
+                       else if (global_append)
                                opt->boot_args = talloc_asprintf(opt, "%s %s",
                                                                 global_append,
                                                                 syslinux_opt->append);
-               } else
+                       else
+                               opt->boot_args = talloc_strdup(opt, syslinux_opt->append);
+               } else if (global_append)
                        opt->boot_args = talloc_strdup(opt, global_append);
 
                if (!opt->boot_args)
@@ -403,10 +404,16 @@ static void syslinux_finalize(struct conf_context *conf)
                conf_strip_str(opt->description);
 
                discover_context_add_boot_option(dc, d_opt);
+               d_opt = NULL;
                continue;
+
 fail:
                talloc_free(d_opt);
        }
+
+       list_for_each_entry_safe(&state->processed_options, syslinux_opt, tmp, list)
+               talloc_free(syslinux_opt);
+       list_init(&state->processed_options);
 }
 
 static int syslinux_parse(struct discover_context *dc)
@@ -414,19 +421,21 @@ static int syslinux_parse(struct discover_context *dc)
        struct syslinux_options *state;
        const char * const *filename;
        struct conf_context *conf;
-       char *cfg_dir;
-       int len, rc;
-       char *buf;
+       struct list *found_list;
 
        /* Support block device boot only at present */
        if (dc->event)
                return -1;
 
        conf = talloc_zero(dc, struct conf_context);
-
        if (!conf)
                return -1;
 
+       found_list = talloc(conf, struct list);
+       if (!found_list)
+               return -1;
+       list_init(found_list);
+
        conf->dc = dc;
        conf->global_options = syslinux_global_options,
        conf_init_global_options(conf);
@@ -439,15 +448,23 @@ static int syslinux_parse(struct discover_context *dc)
        /*
         * set the global defaults
         * by spec 'default' defaults to 'linux' and
-        * 'implicit' defaults to '1', we also just set
-        * and empty string in 'append' to make it easier
-        * in syslinux_finish
+        * 'implicit' defaults to '1'
         */
        conf_set_global_option(conf, "default", "linux");
        conf_set_global_option(conf, "implicit", "1");
-       conf_set_global_option(conf, "append", "");
 
        for (filename = syslinux_conf_files; *filename; filename++) {
+               char *cfg_dir;
+               int len, rc;
+               char *buf;
+
+               /*
+                * guard against duplicate entries in case-insensitive
+                * filesystems, mainly vfat boot partitions
+                */
+               if (!parser_is_unique(dc, dc->device, *filename, found_list))
+                       continue;
+
                rc = parser_request_file(dc, dc->device, *filename, &buf, &len);
                if (rc)
                        continue;