[PATCH 5/6] discover: Mount and parse ISO images.
Samuel Mendoza-Jonas
sam at mendozajonas.com
Tue Oct 25 14:44:47 AEDT 2016
Allow users to specify an ISO file via device_handler_process_url(), and
load it asynchronously. The load task makes use of a custom IO callback
in order to relay live progress to the UI. At the moment this is
primarily targeted at the progress meter from programs such as wget.
On a successful load the ISO file is mounted via losetup, and th
resulting loop device is recognised as a mountable device by
discover/udev.
Signed-off-by: Samuel Mendoza-Jonas <sam at mendozajonas.com>
---
discover/device-handler.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++
discover/udev.c | 8 +++-
2 files changed, 109 insertions(+), 2 deletions(-)
diff --git a/discover/device-handler.c b/discover/device-handler.c
index 70e4506..e4a3fc3 100644
--- a/discover/device-handler.c
+++ b/discover/device-handler.c
@@ -1007,6 +1007,51 @@ void device_handler_update_config(struct device_handler *handler,
device_handler_reinit(handler);
}
+/*
+ * Process the download of an ISO file. Mount the image with losetup which if
+ * successfull should be noticed as a new udev event.
+ */
+static void device_handler_process_image(struct load_url_result *result,
+ void *data)
+{
+ struct device_handler *handler = data;
+ struct boot_status *status;
+ struct process *p;
+ int rc;
+
+ if (!result || result->status != LOAD_OK) {
+ pb_log("%s: load failed\n", __func__);
+ return;
+ }
+
+ status = talloc_zero(handler, struct boot_status);
+ status->type = BOOT_STATUS_INFO;
+ status->message = talloc_asprintf(status, _("ISO downloaded to %s"),
+ result->local);
+ device_handler_boot_status(handler, status);
+
+ const char *argv[] = {
+ pb_system_apps.losetup,
+ "-r", "-f",
+ result->local,
+ NULL
+ };
+
+ p = process_create(handler);
+ p->path = pb_system_apps.losetup;
+ p->argv = argv;
+
+ rc = process_run_sync(p);
+
+ if (rc || p->exit_status) {
+ pb_log("Failed to create loopback device (%d)\n", rc);
+ pb_debug("%s\n", p->stdout_buf);
+ }
+
+ talloc_free(status);
+ talloc_free(p);
+}
+
static char *device_from_addr(void *ctx, struct pb_url *url)
{
char *ipaddr, *buf, *tok, *dev = NULL;
@@ -1077,9 +1122,46 @@ static char *device_from_addr(void *ctx, struct pb_url *url)
return dev;
}
+/*
+ * Callback to retrieve output from a running asynchronous process. If output
+ * exists it is sent as a status update to the UI
+ */
+static int live_stdout_cb(void *arg)
+{
+ struct process_info *procinfo = arg;
+ struct device_handler *handler;
+ struct boot_status *status;
+ struct process *p;
+ char *line = NULL;
+ int rc;
+
+ if (!arg)
+ return -1;
+
+ p = procinfo_get_process(procinfo);
+ handler = load_task_async_data(p);
+
+ status = talloc_zero(arg, struct boot_status);
+
+ rc = process_stdout_custom(procinfo, &line);
+
+ if (rc || !line)
+ return rc;
+
+ status->type = BOOT_STATUS_INFO;
+ status->message = line;
+ device_handler_boot_status(handler, status);
+
+ talloc_free(status);
+ talloc_free(line);
+
+ return rc;
+}
+
void device_handler_process_url(struct device_handler *handler,
const char *url, const char *mac, const char *ip)
{
+ struct load_url_result *result;
struct discover_context *ctx;
struct discover_device *dev;
struct boot_status *status;
@@ -1143,6 +1225,27 @@ void device_handler_process_url(struct device_handler *handler,
goto msg;
}
+ /*
+ * An ISO download may take some time - start an asynchronous job and
+ * watch output to let the user know progress is being made.
+ */
+ if (pb_url && pb_url->file && strstr(pb_url->file, ".iso")) {
+ result = load_url_async(handler, pb_url,
+ device_handler_process_image, handler,
+ live_stdout_cb);
+ if (!result) {
+ status->message = talloc_asprintf(status,
+ _("Failed to download image \"%s\""),
+ pb_url->file);
+ } else {
+ status->message = talloc_asprintf(status,
+ _("Retrieving image \"%s\""),
+ pb_url->file);
+ status->type = BOOT_STATUS_INFO;
+ }
+ goto msg;
+ }
+
dev = discover_device_create(handler, mac, event->device);
if (pb_url->scheme == pb_url_file)
dev->device->type = DEVICE_TYPE_ANY;
diff --git a/discover/udev.c b/discover/udev.c
index 1e04313..d3824f7 100644
--- a/discover/udev.c
+++ b/discover/udev.c
@@ -104,8 +104,12 @@ static int udev_handle_block_add(struct pb_udev *udev, struct udev_device *dev,
node = udev_device_get_devnode(dev);
path = udev_device_get_devpath(dev);
if (path && strstr(path, "virtual/block/loop")) {
- pb_log("SKIP: %s: ignored (path=%s)\n", name, path);
- return 0;
+ type = udev_device_get_property_value(dev, "ID_FS_TYPE");
+ /* Don't skip if an ISO has been mounted on this loop device */
+ if (strcasestr(path, "iso9660") != 0) {
+ pb_log("SKIP: %s: ignored (path=%s)\n", name, path);
+ return 0;
+ }
}
if (path && strstr(path, "virtual/block/ram")) {
--
2.10.0
More information about the Petitboot
mailing list