From patchwork Thu Aug 11 13:04:55 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reda Sallahi X-Patchwork-Id: 9275261 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 187656022E for ; Thu, 11 Aug 2016 13:05:40 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 04DCA28627 for ; Thu, 11 Aug 2016 13:05:40 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E794D2863E; Thu, 11 Aug 2016 13:05:39 +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 5B47128627 for ; Thu, 11 Aug 2016 13:05:39 +0000 (UTC) Received: from localhost ([::1]:48524 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bXpg2-00042T-DV for patchwork-qemu-devel@patchwork.kernel.org; Thu, 11 Aug 2016 09:05:38 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52715) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bXpfe-00042K-7j for qemu-devel@nongnu.org; Thu, 11 Aug 2016 09:05:20 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bXpfZ-0005St-6Q for qemu-devel@nongnu.org; Thu, 11 Aug 2016 09:05:13 -0400 Received: from mail-wm0-x241.google.com ([2a00:1450:400c:c09::241]:33452) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bXpfY-0005RT-Su; Thu, 11 Aug 2016 09:05:09 -0400 Received: by mail-wm0-x241.google.com with SMTP id o80so1290445wme.0; Thu, 11 Aug 2016 06:05:08 -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=VLGwYRX3TVwPkGdWcikhS6x8m3BIPMEUN9d7BncX+Jg=; b=Vum1TXXJ3DrGFmjPYZfqy6dn8wi+1mPP9Q1F4tTgRWZY/nliYigsWjYuniFyzR0zsB 1GlBvipjPhaNEwHRRYV7PE9IKc1Vw4x5BzqScP3Q8tGtQo/9s8nuNwHOKnBc5L79qSlx mLcedK1UKjEB44/Po1Rg9SROmIxRn2j6ItpfLEP18bMT06RLkFmeKaYD5yK9OpDtV6hz ye5aoddzM9ja6n1cOYyRw/qSUAUlbB/uVQi7tcjxW+syQ4qA9aeKC/Tl1K+cgVC8y3Kq NXUZCTVW9WkuP9mwIV/ZjJXFVuN/eXjrM2IPuKvpPq7fjt/+Ii/oVZj2fGai4mUBNvsd oaGA== 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=VLGwYRX3TVwPkGdWcikhS6x8m3BIPMEUN9d7BncX+Jg=; b=AsVtmwPI0bo1TsabyPlZAvj4eV9LkkrCaMEmZdimQClzh7jsOg/fMUheUQA5G6aGYN pwRFAfP8gpoAeKSnV4i9a1NYY74FP6sjYfayV5qi3D/UVYUvr3N1LKeXowv5IZmbRpgV CecCvWkTk13teELR9yxpGY9vJ89VFBKxdX9FReyA+CsmsrmCS3Kjg0BRelMa30o5Fx47 cQgpcSN5h9KAqIMTxyoPWGR0Gwkm+UzYMPncQP+biJY4KkYom/gVMXIAnLREjPa5MrZ6 QWvXfu1jX7hITt2jpCMTVPjA3WYSeqZhgYJIABwNLSPnLYU1lQleCbzRG4zePZ0v+5K5 AAAA== X-Gm-Message-State: AEkoouuKjVJx6KcMTHgm6YLurZTn576DAhPur/ml9KJgwB7CPmnKhNfemNFkLzEr4IfpnA== X-Received: by 10.194.32.73 with SMTP id g9mr11553477wji.80.1470920708091; Thu, 11 Aug 2016 06:05:08 -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 a203sm15083074wma.0.2016.08.11.06.05.06 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 11 Aug 2016 06:05:07 -0700 (PDT) From: Reda Sallahi To: qemu-devel@nongnu.org Date: Thu, 11 Aug 2016 15:04:55 +0200 Message-Id: <20160811130455.18964-1-fullmanet@gmail.com> X-Mailer: git-send-email 2.9.2 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2a00:1450:400c:c09::241 Subject: [Qemu-devel] [PATCH v2] 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 v1: * add --image-opts handling qemu-img.c | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 98 insertions(+), 21 deletions(-) diff --git a/qemu-img.c b/qemu-img.c index d08905b..3973990 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; @@ -4071,31 +4072,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 +4217,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);