+ 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;
+ }
+
+ return NULL;
+}
+
+static enum device_type event_device_type(struct device *device,
+ struct event *event)
+{
+ const char *param;
+
+ param = event_get_param(event, "type");
+ if (!param) {
+ pb_log("%s: empty type\n", device->id);
+ return DEVICE_TYPE_UNKNOWN;
+ }
+
+ if (!strcmp(param, "disk") || !strcmp(param, "partition"))
+ return DEVICE_TYPE_DISK;
+
+ if (!strcmp(param, "net"))
+ return DEVICE_TYPE_NETWORK;
+
+ pb_log("%s: unknown type '%s'\n", device->id, param);
+ return DEVICE_TYPE_UNKNOWN;
+}
+
+static struct discover_device *discover_device_create(
+ struct device_handler *handler,
+ struct discover_context *ctx,
+ struct event *event)
+{
+ struct discover_device *dev;
+ const char *devname;
+
+ dev = find_device(handler, event->device);
+ if (dev)
+ return dev;
+
+ dev = talloc_zero(ctx, struct discover_device);
+ dev->device = talloc_zero(dev, struct device);
+ list_init(&dev->boot_options);
+
+ devname = event_get_param(ctx->event, "DEVNAME");
+ if (devname)
+ dev->device_path = talloc_strdup(dev, devname);
+
+ dev->device->id = talloc_strdup(dev, event->device);
+ dev->device->type = event_device_type(dev->device, event);
+
+ talloc_set_destructor(dev, destroy_device);
+
+ return dev;