From patchwork Tue Oct 25 03:44:47 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sam Mendoza-Jonas X-Patchwork-Id: 686304 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3t2zZK5q0pz9t1L for ; Tue, 25 Oct 2016 14:45:29 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=mendozajonas.com header.i=@mendozajonas.com header.b=MlXzZOfh; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 3t2zZK4BPYzDvjs for ; Tue, 25 Oct 2016 14:45:29 +1100 (AEDT) Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=mendozajonas.com header.i=@mendozajonas.com header.b=MlXzZOfh; dkim-atps=neutral X-Original-To: petitboot@lists.ozlabs.org Delivered-To: petitboot@lists.ozlabs.org Received: from mendozajonas.com (mendozajonas.com [188.166.185.233]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 3t2zYt2w4szDvjj for ; Tue, 25 Oct 2016 14:45:06 +1100 (AEDT) Authentication-Results: lists.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=mendozajonas.com header.i=@mendozajonas.com header.b=MlXzZOfh; dkim-atps=neutral Received: from skellige.ozlabs.ibm.com (unknown [122.99.82.10]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (Client did not present a certificate) (Authenticated sender: sam@mendozajonas.com) by mendozajonas.com (Postfix) with ESMTPSA id D0126143FB4; Tue, 25 Oct 2016 11:45:02 +0800 (SGT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mendozajonas.com; s=mail; t=1477367103; bh=DHbJM914NeR9AhLFIK/rK+ZHiUkeG78+AzNFsaYskBE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=MlXzZOfhF4kKysU4yHfzvLUtFc3JmbZnENH6BmFpy1CDC3eyKjs3J28/yksD4badt k33R9Ipuk8Ss5yE9AHtsgumkiDeWvjietP2CqeFrLkUbe4QlaTJ+SUNrJBSE0x7qsx yYhnyxSr77MNaWvyNUPoQULdA0sqZa4fLnDeLMWc= From: Samuel Mendoza-Jonas To: petitboot@lists.ozlabs.org Subject: [PATCH 5/6] discover: Mount and parse ISO images. Date: Tue, 25 Oct 2016 14:44:47 +1100 Message-Id: <20161025034448.28723-5-sam@mendozajonas.com> X-Mailer: git-send-email 2.10.0 In-Reply-To: <20161025034448.28723-1-sam@mendozajonas.com> References: <20161025034448.28723-1-sam@mendozajonas.com> X-BeenThere: petitboot@lists.ozlabs.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Petitboot bootloader development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Samuel Mendoza-Jonas MIME-Version: 1.0 Errors-To: petitboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Petitboot" 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 --- 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")) {