From patchwork Mon Aug 15 12:11:49 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reda Sallahi X-Patchwork-Id: 9280857 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 8CE4C60780 for ; Mon, 15 Aug 2016 12:12:43 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7BF6A28C72 for ; Mon, 15 Aug 2016 12:12:43 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 70C3328C74; Mon, 15 Aug 2016 12:12:43 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id D5A6A28C72 for ; Mon, 15 Aug 2016 12:12:42 +0000 (UTC) Received: from localhost ([::1]:36599 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bZGl0-000882-1i for patchwork-qemu-devel@patchwork.kernel.org; Mon, 15 Aug 2016 08:12:42 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33896) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bZGkj-00087m-Mc for qemu-devel@nongnu.org; Mon, 15 Aug 2016 08:12:26 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bZGkd-0005iJ-IK for qemu-devel@nongnu.org; Mon, 15 Aug 2016 08:12:24 -0400 Received: from mail-wm0-x243.google.com ([2a00:1450:400c:c09::243]:33220) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bZGkd-0005i2-8e; Mon, 15 Aug 2016 08:12:19 -0400 Received: by mail-wm0-x243.google.com with SMTP id o80so10831066wme.0; Mon, 15 Aug 2016 05:12:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id; bh=2rlws7D7PkclOhXPVRWtIQEK0gZdtDxP1wyV44qonNM=; b=ztnZJzBiEobsuP0RzHbHHfGp+Zp/zEWycq0CvA3PIGQA5zC8QimPDFmKXdPwsOUMEG 1OBe0OuXrA4/dNKc+ty5pil6729vVKWar48MlXZOxFdpCGmyN0RHjrurMKSWN/ruf+gN 4ph2p9HbfVpIa9336+hKBHZRb0UJ7KQfHeQIs44IVEMMh/kQAP1+k2IHDHJb42RpY7of awtQujnDjt782RaDok4V2UT5lZ0m0dyA7bhzGlJsv/CAp+ibwvrvhB7ZG06ys3bOQWAb lAaBDEdUDlPWcNXa854uZiwIPU83x3Qd0qproUX3zjLNKfjDwlxghYNedoDs2r3r4AlC u8ZA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=2rlws7D7PkclOhXPVRWtIQEK0gZdtDxP1wyV44qonNM=; b=c+/5ENps6xFL+fuSI66oyKqylLXNVbfa/Qtu+qoSUxvd6AL3H6dsgu07lJ4RbFEkdr 0Pa7fW9WqtY/rCHoVPMnKx7dSjeEm+0FXJM8ihNoOYJ5Umovtey6HKZUJTnPLe6lik4Z /qUStmMSW9mMnhiC/B04yG4QB2ZPbPqk8e8+deqGlBCUjFJA/BqOxTCFkBupuD3KEzSP QaeoMs2CXpO6U1lcoPhwRyDAXux59Ja141LhxblPiR480RwsFMBjlPUvUbzqtYKB+7dP B9jhpjocQsFjWWYaTBQ7i2Fbfif/C5oSrRam+DoRp5NZfH2qp1zzPMcqLQ52gj9Aqspt YRCg== X-Gm-Message-State: AEkoousdjJQai1csBv6n8YZOVIVuKRYscBoZkL2XZXYtNJdhoecPzhV7XoZq5GjF6seMwg== X-Received: by 10.28.31.133 with SMTP id f127mr15051486wmf.90.1471263138412; Mon, 15 Aug 2016 05:12:18 -0700 (PDT) Received: from localhost.localdomain (ram94-2-82-66-69-246.fbx.proxad.net. [82.66.69.246]) by smtp.gmail.com with ESMTPSA id v189sm16255447wmv.12.2016.08.15.05.12.16 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 15 Aug 2016 05:12:17 -0700 (PDT) From: Reda Sallahi To: qemu-devel@nongnu.org Date: Mon, 15 Aug 2016 14:11:49 +0200 Message-Id: <20160815121149.21464-1-fullmanet@gmail.com> X-Mailer: git-send-email 2.9.3 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2a00:1450:400c:c09::243 Subject: [Qemu-devel] [PATCH v3] qemu-img: change opening method for the output in dd X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Fam Zheng , qemu-block@nongnu.org, Max Reitz , Reda Sallahi , Stefan Hajnoczi Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP dd was creating an output image regardless of whether there was one already created. With this patch we try to open first the output image and resize it if necessary. We also make it mandatory to specify conv=notrunc when the file already exists. Signed-off-by: Reda Sallahi --- Depends on: [PATCH v3] qemu-img: add conv=notrunc option to dd Changes from v2: * Remove redundant code Changes from v1: * add --image-opts handling qemu-img.c | 149 ++++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 98 insertions(+), 51 deletions(-) diff --git a/qemu-img.c b/qemu-img.c index d08905b..8af6dd9 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -3919,7 +3919,8 @@ static int img_dd(int argc, char **argv) char *tmp; BlockDriver *drv = NULL, *proto_drv = NULL; BlockBackend *blk1 = NULL, *blk2 = NULL; - QemuOpts *opts = NULL; + QDict *qoptions = NULL; + QemuOpts *opts = NULL, *qopts = NULL; QemuOptsList *create_opts = NULL; Error *local_err = NULL; bool image_opts = false; @@ -4030,36 +4031,6 @@ static int img_dd(int argc, char **argv) goto out; } - drv = bdrv_find_format(out_fmt); - if (!drv) { - error_report("Unknown file format"); - ret = -1; - goto out; - } - proto_drv = bdrv_find_protocol(out.filename, true, &local_err); - - if (!proto_drv) { - error_report_err(local_err); - ret = -1; - goto out; - } - if (!drv->create_opts) { - error_report("Format driver '%s' does not support image creation", - drv->format_name); - ret = -1; - goto out; - } - if (!proto_drv->create_opts) { - error_report("Protocol driver '%s' does not support image creation", - proto_drv->format_name); - ret = -1; - goto out; - } - create_opts = qemu_opts_append(create_opts, drv->create_opts); - create_opts = qemu_opts_append(create_opts, proto_drv->create_opts); - - opts = qemu_opts_create(create_opts, NULL, 0, &error_abort); - size = blk_getlength(blk1); if (size < 0) { error_report("Failed to get size for '%s'", in.filename); @@ -4071,31 +4042,106 @@ static int img_dd(int argc, char **argv) dd.count * in.bsz < size) { size = dd.count * in.bsz; } - - /* Overflow means the specified offset is beyond input image's size */ - if (dd.flags & C_SKIP && (in.offset > INT64_MAX / in.bsz || - size < in.bsz * in.offset)) { - qemu_opt_set_number(opts, BLOCK_OPT_SIZE, 0, &error_abort); + if (image_opts) { + qopts = qemu_opts_parse_noisily(qemu_find_opts("source"), + out.filename, true); + if (!opts) { + ret = -1; + goto out; + } + qoptions = qemu_opts_to_qdict(qopts, NULL); } else { - qemu_opt_set_number(opts, BLOCK_OPT_SIZE, - size - in.bsz * in.offset, &error_abort); + qoptions = qdict_new(); + qdict_put(qoptions, "driver", qstring_from_str(out_fmt)); } - ret = bdrv_create(drv, out.filename, opts, &local_err); - if (ret < 0) { - error_reportf_err(local_err, - "%s: error while creating output image: ", - out.filename); - ret = -1; - goto out; - } - - blk2 = img_open(image_opts, out.filename, out_fmt, BDRV_O_RDWR, - false, false); + blk2 = blk_new_open(image_opts ? NULL : out.filename, + NULL, qoptions, BDRV_O_RDWR, NULL); if (!blk2) { - ret = -1; - goto out; + drv = bdrv_find_format(out_fmt); + if (!drv) { + error_report("Unknown file format"); + ret = -1; + goto out; + } + proto_drv = bdrv_find_protocol(out.filename, true, &local_err); + + if (!proto_drv) { + error_report_err(local_err); + ret = -1; + goto out; + } + if (!drv->create_opts) { + error_report("Format driver '%s' does not support image creation", + drv->format_name); + ret = -1; + goto out; + } + if (!proto_drv->create_opts) { + error_report("Protocol driver '%s' does not support image creation", + proto_drv->format_name); + ret = -1; + goto out; + } + create_opts = qemu_opts_append(create_opts, drv->create_opts); + create_opts = qemu_opts_append(create_opts, proto_drv->create_opts); + + opts = qemu_opts_create(create_opts, NULL, 0, &error_abort); + + /* Overflow means the specified offset is beyond input image's size */ + if (dd.flags & C_SKIP && (in.offset > INT64_MAX / in.bsz || + size < in.offset * in.bsz)) { + qemu_opt_set_number(opts, BLOCK_OPT_SIZE, + 0, &error_abort); + } else { + qemu_opt_set_number(opts, BLOCK_OPT_SIZE, + size - in.offset * in.bsz, &error_abort); + } + + ret = bdrv_create(drv, out.filename, opts, &local_err); + if (ret < 0) { + error_reportf_err(local_err, + "%s: error while creating output image: ", + out.filename); + ret = -1; + goto out; + } + blk2 = img_open(image_opts, out.filename, out_fmt, BDRV_O_RDWR, + false, false); + if (!blk2) { + ret = -1; + goto out; + } + } else { + int64_t blk2sz = 0; + + if (!(dd.conv & C_NOTRUNC)) { + /* We make conv=notrunc mandatory for the moment to avoid + accidental destruction of the output image. Needs to be + changed when a better solution is found */ + error_report("conv=notrunc not specified"); + ret = -1; + goto out; + } + + blk2sz = blk_getlength(blk2); + if (blk2sz < 0) { + error_report("Failed to get size for '%s'", in.filename); + ret = -1; + goto out; + } + + if (!(dd.conv & C_NOTRUNC)) { + blk_truncate(blk2, 0); + } + if (!(dd.flags & C_SKIP) || (in.offset <= INT64_MAX / in.bsz && + size >= in.offset * in.bsz)) { + if (!(dd.conv & C_NOTRUNC) || + blk2sz < size - in.offset * in.bsz) { + blk_truncate(blk2, size - in.offset * in.bsz); + } + } } if (dd.flags & C_SKIP && (in.offset > INT64_MAX / in.bsz || @@ -4141,6 +4187,7 @@ static int img_dd(int argc, char **argv) out: g_free(arg); qemu_opts_del(opts); + qemu_opts_del(qopts); qemu_opts_free(create_opts); blk_unref(blk1); blk_unref(blk2);