summaryrefslogtreecommitdiffstats
path: root/discover
diff options
context:
space:
mode:
Diffstat (limited to 'discover')
-rw-r--r--discover/device-handler.c28
-rw-r--r--discover/device-handler.h14
-rw-r--r--discover/discover-server.c20
-rw-r--r--discover/discover-server.h5
-rw-r--r--discover/kboot-parser.c155
-rw-r--r--discover/parser-utils.c53
-rw-r--r--discover/parser-utils.h17
-rw-r--r--discover/parser.c69
-rw-r--r--discover/parser.h33
9 files changed, 219 insertions, 175 deletions
diff --git a/discover/device-handler.c b/discover/device-handler.c
index 1f8938f..593b8e0 100644
--- a/discover/device-handler.c
+++ b/discover/device-handler.c
@@ -11,6 +11,8 @@
#include <pb-protocol/pb-protocol.h>
#include "device-handler.h"
+#include "discover-server.h"
+#include "parser.h"
#include "udev.h"
#include "log.h"
#include "paths.h"
@@ -28,18 +30,6 @@ struct device_handler {
struct list contexts;
};
-struct discover_context {
- char *id;
- char *device_path;
- char *mount_path;
- struct udev_event *event;
- struct device *device;
- char **links;
- int n_links;
-
- struct list_item list;
-};
-
struct mount_map {
char *device_path;
char *mount_point;
@@ -335,9 +325,18 @@ static int handle_add_event(struct device_handler *handler,
}
list_add(&handler->contexts, &ctx->list);
-
talloc_set_destructor(ctx, destroy_context);
+ /* set up the top-level device */
+ ctx->device = talloc_zero(ctx, struct device);
+ ctx->device->id = talloc_strdup(ctx->device, ctx->id);
+ list_init(&ctx->device->boot_options);
+
+ /* run the parsers */
+ iterate_parsers(ctx);
+
+ discover_server_notify_add(handler->server, ctx->device);
+
return 0;
}
@@ -350,6 +349,8 @@ static int handle_remove_event(struct device_handler *handler,
if (!ctx)
return 0;
+ discover_server_notify_remove(handler->server, ctx->device);
+
talloc_free(ctx);
return 0;
@@ -381,6 +382,7 @@ struct device_handler *device_handler_init(struct discover_server *server)
handler = talloc(NULL, struct device_handler);
handler->devices = NULL;
handler->n_devices = 0;
+ handler->server = server;
list_init(&handler->contexts);
diff --git a/discover/device-handler.h b/discover/device-handler.h
index ddcb201..cd28420 100644
--- a/discover/device-handler.h
+++ b/discover/device-handler.h
@@ -1,11 +1,25 @@
#ifndef _DEVICE_HANDLER_H
#define _DEVICE_HANDLER_H
+#include <list/list.h>
+
struct device_handler;
struct discover_server;
struct udev_event;
struct device;
+struct discover_context {
+ char *id;
+ char *device_path;
+ char *mount_path;
+ struct udev_event *event;
+ struct device *device;
+ char **links;
+ int n_links;
+
+ struct list_item list;
+};
+
struct device_handler *device_handler_init(struct discover_server *server);
void device_handler_destroy(struct device_handler *devices);
diff --git a/discover/discover-server.c b/discover/discover-server.c
index 225f58c..8ec1949 100644
--- a/discover/discover-server.c
+++ b/discover/discover-server.c
@@ -154,6 +154,26 @@ static int discover_server_process(void *arg)
return 0;
}
+void discover_server_notify_add(struct discover_server *server,
+ struct device *device)
+{
+ struct client *client;
+
+ list_for_each_entry(&server->clients, client, list)
+ write_add_message(server, client, device);
+
+}
+
+void discover_server_notify_remove(struct discover_server *server,
+ struct device *device)
+{
+ struct client *client;
+
+ list_for_each_entry(&server->clients, client, list)
+ write_remove_message(server, client, device->id);
+
+}
+
void discover_server_set_device_source(struct discover_server *server,
struct device_handler *handler)
{
diff --git a/discover/discover-server.h b/discover/discover-server.h
index e5d7881..7c89938 100644
--- a/discover/discover-server.h
+++ b/discover/discover-server.h
@@ -3,6 +3,7 @@
struct discover_server;
struct device_handler;
+struct device;
struct discover_server *discover_server_init(void);
@@ -11,4 +12,8 @@ void discover_server_destroy(struct discover_server *server);
void discover_server_set_device_source(struct discover_server *server,
struct device_handler *handler);
+void discover_server_notify_add(struct discover_server *server,
+ struct device *device);
+void discover_server_notify_remove(struct discover_server *server,
+ struct device *device);
#endif /* _DISCOVER_SERVER_H */
diff --git a/discover/kboot-parser.c b/discover/kboot-parser.c
index df2e762..f227ee3 100644
--- a/discover/kboot-parser.c
+++ b/discover/kboot-parser.c
@@ -10,12 +10,28 @@
#include <sys/types.h>
#include <sys/stat.h>
-#include "parser.h"
+#include <talloc/talloc.h>
+
+#include "log.h"
+#include "pb-protocol/pb-protocol.h"
+#include "paths.h"
#include "params.h"
+#include "parser-utils.h"
+#include "device-handler.h"
#define buf_size 1024
-static const char *devpath;
+struct kboot_context {
+ struct discover_context *discover;
+
+ char *buf;
+
+ struct global_option {
+ char *name;
+ char *value;
+ } *global_options;
+ int n_global_options;
+};
static int param_is_ignored(const char *param)
{
@@ -76,12 +92,6 @@ static char *get_param_pair(char *str, char **name_out, char **value_out,
return tmp ? tmp + 1 : NULL;
}
-struct global_option {
- char *name;
- char *value;
-};
-
-
static struct global_option global_options[] = {
{ .name = "root" },
{ .name = "initrd" },
@@ -93,20 +103,21 @@ static struct global_option global_options[] = {
* Check if an option (name=value) is a global option. If so, store it in
* the global options table, and return 1. Otherwise, return 0.
*/
-static int check_for_global_option(const char *name, const char *value)
+static int check_for_global_option(struct kboot_context *ctx,
+ const char *name, const char *value)
{
int i;
- for (i = 0; global_options[i].name ;i++) {
- if (!strcmp(name, global_options[i].name)) {
+ for (i = 0; i < ctx->n_global_options; i++) {
+ if (!strcmp(name, ctx->global_options[i].name)) {
global_options[i].value = strdup(value);
- return 1;
+ break;
}
}
return 0;
}
-static char *get_global_option(const char *name)
+static char *get_global_option(struct kboot_context *ctx, const char *name)
{
int i;
@@ -117,9 +128,11 @@ static char *get_global_option(const char *name)
return NULL;
}
-static int parse_option(struct boot_option *opt, char *config)
+static int parse_option(struct kboot_context *kboot_ctx, char *opt_name,
+ char *config)
{
char *pos, *name, *value, *root, *initrd, *cmdline, *tmp;
+ struct boot_option *opt;
root = initrd = cmdline = NULL;
@@ -136,17 +149,24 @@ static int parse_option(struct boot_option *opt, char *config)
pos = strchr(config, ' ');
+ opt = talloc_zero(kboot_ctx, struct boot_option);
+ opt->id = talloc_asprintf(opt, "%s#%s",
+ kboot_ctx->discover->device->id, opt_name);
+ opt->name = talloc_strdup(opt, opt_name);
+
/* if there's no space, it's only a kernel image with no params */
if (!pos) {
- opt->boot_image_file = resolve_path(config, devpath);
- opt->description = strdup(config);
- return 1;
+ opt->boot_image_file = resolve_path(opt, config,
+ kboot_ctx->discover->device_path);
+ opt->description = talloc_strdup(opt, config);
+ goto out_add;
}
*pos = 0;
- opt->boot_image_file = resolve_path(config, devpath);
+ opt->boot_image_file = resolve_path(opt, config,
+ kboot_ctx->discover->device_path);
- cmdline = malloc(buf_size);
+ cmdline = talloc_array(opt, char, buf_size);
*cmdline = 0;
for (pos++; pos;) {
@@ -170,119 +190,108 @@ static int parse_option(struct boot_option *opt, char *config)
}
if (!root)
- root = get_global_option("root");
+ root = get_global_option(kboot_ctx, "root");
if (!initrd)
- initrd = get_global_option("initrd");
+ initrd = get_global_option(kboot_ctx, "initrd");
if (initrd) {
- asprintf(&tmp, "initrd=%s %s", initrd, cmdline);
- free(cmdline);
+ tmp = talloc_asprintf(opt, "initrd=%s %s", initrd, cmdline);
+ talloc_free(cmdline);
cmdline = tmp;
- opt->initrd_file = resolve_path(initrd, devpath);
+ opt->initrd_file = resolve_path(opt, initrd,
+ kboot_ctx->discover->device_path);
}
if (root) {
- asprintf(&tmp, "root=%s %s", root, cmdline);
- free(cmdline);
+ tmp = talloc_asprintf(opt, "root=%s %s", root, cmdline);
+ talloc_free(cmdline);
cmdline = tmp;
} else if (initrd) {
/* if there's an initrd but no root, fake up /dev/ram0 */
- asprintf(&tmp, "root=/dev/ram0 %s", cmdline);
- free(cmdline);
+ tmp = talloc_asprintf(opt, "root=/dev/ram0 %s", cmdline);
+ talloc_free(cmdline);
cmdline = tmp;
}
- pb_log("kboot cmdline: %s\n", cmdline);
opt->boot_args = cmdline;
- asprintf(&opt->description, "%s %s",
+ opt->description = talloc_asprintf(opt, "%s %s",
config, opt->boot_args);
+out_add:
+ device_add_boot_option(kboot_ctx->discover->device, opt);
return 1;
}
-static void parse_buf(struct device *dev, char *buf)
+static void parse_buf(struct kboot_context *kboot_ctx)
{
char *pos, *name, *value;
- int sent_device = 0;
-
- for (pos = buf; pos;) {
- struct boot_option opt;
+ for (pos = kboot_ctx->buf; pos;) {
pos = get_param_pair(pos, &name, &value, '\n');
- pb_log("kboot param: '%s' = '%s'\n", name, value);
-
if (name == NULL || param_is_ignored(name))
continue;
if (*name == '#')
continue;
- if (check_for_global_option(name, value))
+ if (check_for_global_option(kboot_ctx, name, value))
continue;
- memset(&opt, 0, sizeof(opt));
- opt.name = strdup(name);
-
- if (parse_option(&opt, value))
- if (!sent_device++)
- add_device(dev);
- add_boot_option(&opt);
-
- free(opt.name);
+ parse_option(kboot_ctx, name, value);
}
}
-static int parse(const char *device)
+
+static int parse(struct discover_context *ctx)
{
- char *filepath, *buf;
- int fd, len, rc = 0;
+ struct kboot_context *kboot_ctx;
+ char *filepath;
+ int fd, len, rc;
struct stat stat;
- struct device *dev;
- devpath = device;
+ rc = 0;
+ fd = -1;
+
+ kboot_ctx = talloc_zero(ctx, struct kboot_context);
+ kboot_ctx->discover = ctx;
- filepath = resolve_path("/etc/kboot.conf", devpath);
+ filepath = resolve_path(kboot_ctx, "/etc/kboot.conf", ctx->device_path);
fd = open(filepath, O_RDONLY);
if (fd < 0)
- goto out_free_path;
+ goto out;
if (fstat(fd, &stat))
- goto out_close;
+ goto out;
- buf = malloc(stat.st_size + 1);
- if (!buf)
- goto out_close;;
+ kboot_ctx->buf = talloc_array(kboot_ctx, char, stat.st_size + 1);
- len = read(fd, buf, stat.st_size);
+ len = read(fd, kboot_ctx->buf, stat.st_size);
if (len < 0)
- goto out_free_buf;
- buf[len] = 0;
+ goto out;
+ kboot_ctx->buf[len] = 0;
- dev = malloc(sizeof(*dev));
- memset(dev, 0, sizeof(*dev));
- dev->id = strdup(device);
- dev->icon_file = strdup(generic_icon_file(guess_device_type()));
+ if (!ctx->device->icon_file)
+ ctx->device->icon_file = talloc_strdup(ctx,
+ generic_icon_file(guess_device_type(ctx)));
- parse_buf(dev, buf);
+ parse_buf(kboot_ctx);
rc = 1;
-out_free_buf:
- free(buf);
-out_close:
- close(fd);
-out_free_path:
- free(filepath);
+out:
+ if (fd >= 0)
+ close(fd);
+ talloc_free(kboot_ctx);
return rc;
}
struct parser kboot_parser = {
- .name = "kboot.conf parser",
+ .name = "kboot.conf parser",
.priority = 98,
.parse = parse
};
diff --git a/discover/parser-utils.c b/discover/parser-utils.c
new file mode 100644
index 0000000..4982112
--- /dev/null
+++ b/discover/parser-utils.c
@@ -0,0 +1,53 @@
+
+#include <string.h>
+
+#include <talloc/talloc.h>
+
+#include "pb-protocol/pb-protocol.h"
+#include "udev.h"
+#include "device-handler.h"
+#include "parser-utils.h"
+
+void device_add_boot_option(struct device *device,
+ struct boot_option *boot_option)
+{
+ list_add(&device->boot_options, &boot_option->list);
+ talloc_steal(device, boot_option);
+}
+
+const char *generic_icon_file(enum generic_icon_type type)
+{
+ switch (type) {
+ case ICON_TYPE_DISK:
+ return artwork_pathname("hdd.png");
+ case ICON_TYPE_USB:
+ return artwork_pathname("usbpen.png");
+ case ICON_TYPE_OPTICAL:
+ return artwork_pathname("cdrom.png");
+ case ICON_TYPE_NETWORK:
+ case ICON_TYPE_UNKNOWN:
+ break;
+ }
+ return artwork_pathname("hdd.png");
+}
+
+enum generic_icon_type guess_device_type(struct discover_context *ctx)
+{
+ struct udev_event *event;
+ const char *type, *bus;
+
+ event = ctx->event;
+
+ type = udev_event_param(event, "ID_TYPE");
+ bus = udev_event_param(event, "ID_BUS");
+
+ if (type && streq(type, "cd"))
+ return ICON_TYPE_OPTICAL;
+ if (!bus)
+ return ICON_TYPE_UNKNOWN;
+ if (streq(bus, "usb"))
+ return ICON_TYPE_USB;
+ if (streq(bus, "ata") || streq(bus, "scsi"))
+ return ICON_TYPE_DISK;
+ return ICON_TYPE_UNKNOWN;
+}
diff --git a/discover/parser-utils.h b/discover/parser-utils.h
new file mode 100644
index 0000000..e82e3f9
--- /dev/null
+++ b/discover/parser-utils.h
@@ -0,0 +1,17 @@
+#ifndef PARSER_UTILS_H
+#define PARSER_UTILS_H
+
+#include "parser.h"
+
+#define streq(a,b) (!strcasecmp((a),(b)))
+
+#define artwork_pathname(file) (PKG_SHARE_DIR "/artwork/" file)
+
+void device_add_boot_option(struct device *device,
+ struct boot_option *boot_option);
+
+const char *generic_icon_file(enum generic_icon_type type);
+
+enum generic_icon_type guess_device_type(struct discover_context *ctx);
+
+#endif /* PARSER_UTILS_H */
diff --git a/discover/parser.c b/discover/parser.c
index 5e50dcb..5b1a7ab 100644
--- a/discover/parser.c
+++ b/discover/parser.c
@@ -1,85 +1,30 @@
-#include <petitboot-paths.h>
#include <stdlib.h>
-#include <string.h>
-#include "parser.h"
+#include "pb-protocol/pb-protocol.h"
-extern struct parser native_parser;
-extern struct parser yaboot_parser;
+#include "device-handler.h"
+#include "log.h"
+#include "parser.h"
extern struct parser kboot_parser;
/* array of parsers, ordered by priority */
static struct parser *parsers[] = {
- &native_parser,
- &yaboot_parser,
&kboot_parser,
NULL
};
-void iterate_parsers(const char *devpath, const char *mountpoint)
+void iterate_parsers(struct discover_context *ctx)
{
int i;
- pb_log("trying parsers for %s\n", devpath);
+ pb_log("trying parsers for %s\n", ctx->device_path);
for (i = 0; parsers[i]; i++) {
pb_log("\ttrying parser '%s'\n", parsers[i]->name);
/* just use a dummy device path for now */
- if (parsers[i]->parse(devpath))
+ if (parsers[i]->parse(ctx))
return;
}
pb_log("\tno boot_options found\n");
}
-
-/* convenience functions for parsers */
-void free_device(struct device *dev)
-{
- if (!dev)
- return;
- if (dev->id)
- free(dev->id);
- if (dev->name)
- free(dev->name);
- if (dev->description)
- free(dev->description);
- if (dev->icon_file)
- free(dev->icon_file);
- free(dev);
-}
-
-void free_boot_option(struct boot_option *opt)
-{
- if (!opt)
- return;
- if (opt->name)
- free(opt->name);
- if (opt->description)
- free(opt->description);
- if (opt->icon_file)
- free(opt->icon_file);
- if (opt->boot_image_file)
- free(opt->boot_image_file);
- if (opt->initrd_file)
- free(opt->initrd_file);
- if (opt->boot_args)
- free(opt->boot_args);
- free(opt);
-}
-
-const char *generic_icon_file(enum generic_icon_type type)
-{
- switch (type) {
- case ICON_TYPE_DISK:
- return artwork_pathname("hdd.png");
- case ICON_TYPE_USB:
- return artwork_pathname("usbpen.png");
- case ICON_TYPE_OPTICAL:
- return artwork_pathname("cdrom.png");
- case ICON_TYPE_NETWORK:
- case ICON_TYPE_UNKNOWN:
- break;
- }
- return artwork_pathname("hdd.png");
-}
-
diff --git a/discover/parser.h b/discover/parser.h
index 9c6fb35..bf9a4d0 100644
--- a/discover/parser.h
+++ b/discover/parser.h
@@ -1,14 +1,12 @@
+#ifndef _PARSER_H
+#define _PARSER_H
-#ifndef _PARSERS_H
-#define _PARSERS_H
-
-#include <stdarg.h>
-#include "message.h"
+struct discover_context;
struct parser {
char *name;
int priority;
- int (*parse)(const char *device);
+ int (*parse)(struct discover_context *ctx);
struct parser *next;
};
@@ -22,25 +20,6 @@ enum generic_icon_type {
#define streq(a,b) (!strcasecmp((a),(b)))
-/* general functions provided by parsers.c */
-void iterate_parsers(const char *devpath, const char *mountpoint);
-
-void free_device(struct device *dev);
-void free_boot_option(struct boot_option *opt);
-
-const char *generic_icon_file(enum generic_icon_type type);
-
-/* functions provided by udev-helper or the test wrapper */
-void pb_log(const char *fmt, ...);
-
-int mount_device(const char *dev_path);
-
-char *resolve_path(const char *path, const char *current_dev);
-const char *mountpoint_for_device(const char *dev_path);
-
-enum generic_icon_type guess_device_type(void);
-
-int add_device(const struct device *dev);
-int add_boot_option(const struct boot_option *opt);
+void iterate_parsers(struct discover_context *ctx);
-#endif /* _PARSERS_H */
+#endif /* _PARSER_H */
OpenPOWER on IntegriCloud