+struct discover_device *device_lookup_by_name(struct device_handler *handler,
+ const char *name)
+{
+ if (!strncmp(name, "/dev/", strlen("/dev/")))
+ name += strlen("/dev/");
+
+ return device_lookup_by_id(handler, name);
+}
+
+struct discover_device *device_lookup_by_uuid(
+ struct device_handler *device_handler,
+ const char *uuid)
+{
+ return device_lookup(device_handler, device_match_uuid, uuid);
+}
+
+struct discover_device *device_lookup_by_label(
+ struct device_handler *device_handler,
+ const char *label)
+{
+ return device_lookup(device_handler, device_match_label, label);
+}
+
+struct discover_device *device_lookup_by_id(
+ struct device_handler *device_handler,
+ const char *id)
+{
+ return device_lookup(device_handler, device_match_id, id);
+}
+
+void device_handler_destroy(struct device_handler *handler)
+{
+ talloc_free(handler);
+}
+
+#ifdef PETITBOOT_TEST
+
+/* we have a simplified interface for petitboot testing, but still want
+ * to keep struct device_handler opaque. */
+struct device_handler *device_handler_init(
+ struct discover_server *server __attribute__((unused)),
+ struct waitset *waitset __attribute__((unused)),
+ int dry_run __attribute__((unused)))
+{
+ struct device_handler *handler;
+
+ handler = talloc_zero(NULL, struct device_handler);
+ list_init(&handler->unresolved_boot_options);
+
+ return handler;
+}
+
+void device_handler_add_device(struct device_handler *handler,
+ struct discover_device *dev)
+{
+ handler->n_devices++;
+ handler->devices = talloc_realloc(handler, handler->devices,
+ struct discover_device *, handler->n_devices);
+ handler->devices[handler->n_devices - 1] = dev;
+}
+
+#else
+
+static int mount_device(struct discover_device *dev)
+{
+ int rc;
+
+ if (!dev->device_path)
+ return -1;
+
+ if (!dev->mount_path)
+ dev->mount_path = join_paths(dev, mount_base(),
+ dev->device_path);
+
+ if (pb_mkdir_recursive(dev->mount_path))
+ pb_log("couldn't create mount directory %s: %s\n",
+ dev->mount_path, strerror(errno));
+
+ rc = process_run_simple(dev, pb_system_apps.mount,
+ dev->device_path, dev->mount_path,
+ "-o", "ro", NULL);
+
+ if (!rc)
+ return 0;
+
+ /* Retry mount without ro option. */
+ rc = process_run_simple(dev, pb_system_apps.mount,
+ dev->device_path, dev->mount_path, NULL);
+
+ if (!rc)
+ return 0;
+
+ pb_rmdir_recursive(mount_base(), dev->mount_path);
+ return -1;
+}
+
+static int umount_device(struct discover_device *dev)
+{
+ int status;
+
+ if (!dev->mount_path)
+ return 0;
+
+ status = process_run_simple(dev, pb_system_apps.umount,
+ dev->mount_path, NULL);
+
+ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
+ return -1;
+
+ pb_rmdir_recursive(mount_base(), dev->mount_path);
+
+ return 0;
+}
+
+struct device_handler *device_handler_init(struct discover_server *server,
+ struct waitset *waitset, int dry_run)
+{
+ struct device_handler *handler;
+
+ handler = talloc(NULL, struct device_handler);
+ handler->devices = NULL;
+ handler->n_devices = 0;
+ handler->server = server;
+ handler->waitset = waitset;
+ handler->dry_run = dry_run;
+ handler->default_boot_option = NULL;
+ handler->autoboot_enabled = config_get()->autoboot_enabled;
+ list_init(&handler->unresolved_boot_options);
+
+ /* set up our mount point base */
+ pb_mkdir_recursive(mount_base());
+
+ parser_init();
+
+ return handler;
+}
+
+static int destroy_device(void *arg)
+{
+ struct discover_device *dev = arg;
+
+ umount_device(dev);
+
+ return 0;
+}
+
+static struct discover_device *find_device(struct device_handler *handler,
+ const char *id)
+{
+ struct discover_device *dev;
+ unsigned int i;
+
+ for (i = 0; i < handler->n_devices; i++) {
+ dev = handler->devices[i];
+ if (!strcmp(dev->device->id, id))
+ return dev;