]> git.ozlabs.org Git - petitboot/blob - discover/parser.c
discover: Introduce a container type for boot options
[petitboot] / discover / parser.c
1
2 #include <fcntl.h>
3 #include <stdlib.h>
4 #include <sys/types.h>
5 #include <sys/stat.h>
6
7 #include "types/types.h"
8 #include <log/log.h>
9 #include <talloc/talloc.h>
10
11 #include "device-handler.h"
12 #include "parser.h"
13 #include "parser-utils.h"
14 #include "paths.h"
15
16 struct parser __grub2_parser;
17 struct parser __kboot_parser;
18 struct parser __native_parser;
19 struct parser __yaboot_parser;
20
21 static const struct parser *const parsers[] = {
22 //      &__native_parser,
23         &__kboot_parser,
24         &__grub2_parser,
25         &__yaboot_parser,
26         NULL
27 };
28
29 static const int max_file_size = 1024 * 1024;
30
31 static int read_file(struct discover_context *ctx,
32                 const char *filename, char **bufp, int *lenp)
33 {
34         struct stat statbuf;
35         int rc, fd, i, len;
36         char *buf;
37
38         fd = open(filename, O_RDONLY);
39         if (fd < 0)
40                 return -1;
41
42         rc = fstat(fd, &statbuf);
43         if (rc < 0)
44                 goto err_close;
45
46         len = statbuf.st_size;
47         if (len > max_file_size)
48                 goto err_close;
49
50         buf = talloc_array(ctx, char, len);
51         if (!buf)
52                 goto err_close;
53
54         for (i = 0; i < len; i += rc) {
55                 rc = read(fd, buf + i, len - i);
56
57                 /* unexpected EOF: trim and return */
58                 if (rc == 0) {
59                         len = i;
60                         break;
61                 }
62
63                 if (rc < 0)
64                         goto err_free;
65
66         }
67
68         close(fd);
69         *bufp = buf;
70         *lenp = len;
71         return 0;
72
73 err_free:
74         talloc_free(buf);
75 err_close:
76         close(fd);
77         return -1;
78 }
79
80 static void iterate_parser_files(struct discover_context *ctx,
81                 const struct parser *parser)
82 {
83         const char * const *filename;
84         const char *path, *url;
85         unsigned int tempfile;
86
87         if (!parser->filenames)
88                 return;
89
90         for (filename = parser->filenames; *filename; filename++) {
91                 int rc, len;
92                 char *buf;
93
94                 url = resolve_path(ctx, *filename, ctx->device->device_path);
95                 if (!url)
96                         continue;
97
98                 path = load_file(ctx, url, &tempfile);
99
100                 if (!path)
101                         continue;
102
103                 rc = read_file(ctx, path, &buf, &len);
104                 if (!rc) {
105                         parser->parse(ctx, buf, len);
106                         talloc_free(buf);
107                 }
108
109                 if (tempfile)
110                         unlink(path);
111
112         }
113
114 }
115
116 void iterate_parsers(struct discover_context *ctx)
117 {
118         int i;
119
120         pb_log("trying parsers for %s\n", ctx->device->device->id);
121
122         for (i = 0; parsers[i]; i++) {
123                 pb_log("\ttrying parser '%s'\n", parsers[i]->name);
124                 iterate_parser_files(ctx, parsers[i]);
125         }
126 }
127
128 void parser_init(void)
129 {
130 }