parsers: change parser.parse to accept a buffer
[petitboot] / discover / kboot-parser.c
1 #define _GNU_SOURCE
2
3 #include <assert.h>
4 #include <stdlib.h>
5 #include <string.h>
6
7 #include "log/log.h"
8 #include "talloc/talloc.h"
9 #include "types/types.h"
10 #include "parser-conf.h"
11 #include "parser-utils.h"
12 #include "paths.h"
13
14 static void kboot_process_pair(struct conf_context *conf, const char *name,
15                 char *value)
16 {
17         const char *const *ignored_names = conf->parser_info;
18         struct device *dev;
19         char *pos;
20         char *args;
21         const char *initrd;
22         const char *root;
23         struct boot_option *opt;
24
25         /* ignore bare values */
26
27         if (!name)
28                 return;
29
30         if (conf_param_in_list(ignored_names, name))
31                 return;
32
33         if (conf_set_global_option(conf, name, value))
34                 return;
35
36         /* opt must be associated with dc */
37
38         dev = conf->dc->device->device;
39         opt = talloc_zero(dev, struct boot_option);
40
41         if (!opt)
42                 return;
43
44         opt->id = talloc_asprintf(opt, "%s#%s", dev->id, name);
45         opt->name = talloc_strdup(opt, name);
46
47         args = talloc_strdup(opt, "");
48         initrd = conf_get_global_option(conf, "initrd");
49         root = conf_get_global_option(conf, "root");
50
51         pos = strchr(value, ' ');
52
53         /* if there's no space, it's only a kernel image with no params */
54
55         if (!pos)
56                 goto out_add;
57         *pos = 0;
58
59         for (pos++; pos;) {
60                 char *cl_name, *cl_value;
61
62                 pos = conf_get_pair_equal(conf, pos, &cl_name, &cl_value, ' ');
63
64                 if (!cl_name) {
65                         args = talloc_asprintf_append(args, "%s ", cl_value);
66                         continue;
67                 }
68
69                 if (streq(cl_name, "initrd")) {
70                         initrd = cl_value;
71                         continue;
72                 }
73
74                 if (streq(cl_name, "root")) {
75                         root = cl_value;
76                         continue;
77                 }
78
79                 args = talloc_asprintf_append(args, "%s=%s ", cl_name,
80                         cl_value);
81         }
82
83 out_add:
84         opt->boot_image_file = resolve_path(opt, value,
85                         conf->dc->device->device_path);
86
87         if (root) {
88                 opt->boot_args = talloc_asprintf(opt, "root=%s %s", root, args);
89                 talloc_free(args);
90         } else
91                 opt->boot_args = args;
92
93         if (initrd) {
94                 opt->initrd_file = resolve_path(opt, initrd,
95                                 conf->dc->device->device_path);
96
97                 opt->description = talloc_asprintf(opt, "%s initrd=%s %s",
98                         value, initrd, opt->boot_args);
99         } else
100                 opt->description = talloc_asprintf(opt, "%s %s", value,
101                         opt->boot_args);
102
103         conf_strip_str(opt->boot_args);
104         conf_strip_str(opt->description);
105
106         discover_context_add_boot_option(conf->dc, opt);
107 }
108
109 static struct conf_global_option kboot_global_options[] = {
110         { .name = "initrd" },
111         { .name = "root" },
112         { .name = "video" },
113         { .name = NULL }
114 };
115
116 static const char *const kboot_conf_files[] = {
117         "/kboot.conf",
118         "/kboot.cnf",
119         "/etc/kboot.conf",
120         "/etc/kboot.cnf",
121         "/KBOOT.CONF",
122         "/KBOOT.CNF",
123         "/ETC/KBOOT.CONF",
124         "/ETC/KBOOT.CNF",
125         NULL
126 };
127
128 static const char *const kboot_ignored_names[] = {
129         "default",
130         "delay",
131         "message",
132         "timeout",
133         NULL
134 };
135
136 static int kboot_parse(struct discover_context *dc, char *buf, int len)
137 {
138         struct conf_context *conf;
139
140         conf = talloc_zero(dc, struct conf_context);
141
142         if (!conf)
143                 return 0;
144
145         conf->dc = dc;
146         conf->global_options = kboot_global_options,
147         conf_init_global_options(conf);
148         conf->get_pair = conf_get_pair_equal;
149         conf->process_pair = kboot_process_pair;
150         conf->parser_info = (void *)kboot_ignored_names,
151
152         conf_parse_buf(conf, buf, len);
153
154         talloc_free(conf);
155         return 1;
156 }
157
158 struct parser __kboot_parser = {
159         .name           = "kboot",
160         .parse          = kboot_parse,
161         .filenames      = kboot_conf_files,
162 };