From 8b46ab92aeff52b7354bf4f250835f75b4bd824c Mon Sep 17 00:00:00 2001 From: Samuel Mendoza-Jonas Date: Tue, 25 Jul 2017 15:55:19 +1000 Subject: discover: Add 'plugin' user-event Add a new user event to advertise pb-plugins and add them to the device_handler. Plugins described by this event can either be uninstalled pb-plugin files or successfully installed pb-plugins depending on the associated parameters. The is primarily intended for use by the pb-plugin utility itself to notify Petitboot as it operates on pb-plugin files. Signed-off-by: Samuel Mendoza-Jonas --- discover/event.c | 2 + discover/event.h | 1 + discover/user-event.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 113 insertions(+) diff --git a/discover/event.c b/discover/event.c index 1be19eb..047e928 100644 --- a/discover/event.c +++ b/discover/event.c @@ -55,6 +55,8 @@ static int event_parse_ad_header(char *buf, int len, enum event_action *action, *action = EVENT_ACTION_BOOT; else if (streq(buf, "sync")) *action = EVENT_ACTION_SYNC; + else if (streq(buf, "plugin")) + *action = EVENT_ACTION_PLUGIN; else { pb_log("%s: unknown action: %s\n", __func__, buf); return -1; diff --git a/discover/event.h b/discover/event.h index a639d9c..1f6966c 100644 --- a/discover/event.h +++ b/discover/event.h @@ -14,6 +14,7 @@ enum event_action { EVENT_ACTION_DHCP, EVENT_ACTION_BOOT, EVENT_ACTION_SYNC, + EVENT_ACTION_PLUGIN, EVENT_ACTION_MAX, }; diff --git a/discover/user-event.c b/discover/user-event.c index fb3fddb..77d28c1 100644 --- a/discover/user-event.c +++ b/discover/user-event.c @@ -63,6 +63,8 @@ static const char *event_action_name(enum event_action action) return "boot"; case EVENT_ACTION_SYNC: return "sync"; + case EVENT_ACTION_PLUGIN: + return "plugin"; default: break; } @@ -486,6 +488,111 @@ static int user_event_sync(struct user_event *uev, struct event *event) return 0; } +static int process_uninstalled_plugin(struct user_event *uev, + struct event *event) +{ + struct device_handler *handler = uev->handler; + struct discover_boot_option *file_opt; + struct discover_device *device; + struct discover_context *ctx; + const char *path; + struct resource *res; + + if (!event_get_param(event, "path")) { + pb_log("Uninstalled pb-plugin event missing path param\n"); + return -1; + } + + device = device_lookup_by_name(handler, event->device); + if (!device) { + pb_log("Couldn't find device matching %s for plugin\n", + event->device); + return -1; + } + + ctx = device_handler_discover_context_create(handler, device); + file_opt = discover_boot_option_create(ctx, device); + file_opt->option->name = talloc_strdup(file_opt, + event_get_param(event, "name")); + file_opt->option->id = talloc_asprintf(file_opt, "%s@%p", + device->device->id, file_opt); + file_opt->option->type = DISCOVER_PLUGIN_OPTION; + + + path = event_get_param(event, "path"); + /* path may be relative to root */ + if (strncmp(device->mount_path, path, strlen(device->mount_path)) == 0) { + path += strlen(device->mount_path) + 1; + } + + res = talloc(file_opt, struct resource); + resolve_resource_against_device(res, device, path); + file_opt->boot_image = res; + + discover_context_add_boot_option(ctx, file_opt); + device_handler_discover_context_commit(handler, ctx); + + return 0; +} + +/* + * Notification of a plugin event. This can either be for an uninstalled plugin + * that pb-plugin has scanned, or the result of a plugin that pb-plugin has + * installed. + */ +static int user_event_plugin(struct user_event *uev, struct event *event) +{ + struct device_handler *handler = uev->handler; + char *executable, *executables, *saveptr; + struct plugin_option *opt; + const char *installed; + + installed = event_get_param(event, "installed"); + if (!installed || strncmp(installed, "no", strlen("no")) == 0) + return process_uninstalled_plugin(uev, event); + + opt = talloc_zero(handler, struct plugin_option); + if (!opt) + return -1; + opt->name = talloc_strdup(opt, event_get_param(event, "name")); + opt->id = talloc_strdup(opt, event_get_param(event, "id")); + opt->version = talloc_strdup(opt, event_get_param(event, "version")); + opt->vendor = talloc_strdup(opt, event_get_param(event, "vendor")); + opt->vendor_id = talloc_strdup(opt, event_get_param(event, "vendor_id")); + opt->date = talloc_strdup(opt, event_get_param(event, "date")); + opt->plugin_file = talloc_strdup(opt, + event_get_param(event, "source_file")); + + executables = talloc_strdup(opt, event_get_param(event, "executables")); + if (!executables) { + talloc_free(opt); + return -1; + } + + /* + * The 'executables' parameter is a space-delimited list of installed + * executables + */ + executable = strtok_r(executables, " ", &saveptr); + while (executable) { + opt->executables = talloc_realloc(opt, opt->executables, + char *, opt->n_executables + 1); + if (!opt->executables) { + talloc_free(opt); + return -1; + } + opt->executables[opt->n_executables++] = talloc_strdup(opt, + executable); + executable = strtok_r(NULL, " ", &saveptr); + } + + device_handler_add_plugin_option(handler, opt); + + talloc_free(executables); + + return 0; +} + static void user_event_handle_message(struct user_event *uev, char *buf, int len) { @@ -521,6 +628,9 @@ static void user_event_handle_message(struct user_event *uev, char *buf, case EVENT_ACTION_SYNC: result = user_event_sync(uev, event); break; + case EVENT_ACTION_PLUGIN: + result = user_event_plugin(uev, event); + break; default: break; } -- cgit v1.2.1