discover: Change parsers to emit resources rather than filenames
[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 char *local_path(struct discover_context *ctx,
81                 const char *filename)
82 {
83         return join_paths(ctx, ctx->device->mount_path, filename);
84 }
85
86 static void iterate_parser_files(struct discover_context *ctx,
87                 const struct parser *parser)
88 {
89         const char * const *filename;
90         const char *path;
91
92         if (!parser->filenames)
93                 return;
94
95         for (filename = parser->filenames; *filename; filename++) {
96                 int rc, len;
97                 char *buf;
98
99                 path = local_path(ctx, *filename);
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 }
110
111 void iterate_parsers(struct discover_context *ctx)
112 {
113         int i;
114
115         pb_log("trying parsers for %s\n", ctx->device->device->id);
116
117         for (i = 0; parsers[i]; i++) {
118                 pb_log("\ttrying parser '%s'\n", parsers[i]->name);
119                 iterate_parser_files(ctx, parsers[i]);
120         }
121 }
122
123 void parser_init(void)
124 {
125 }