From patchwork Sat Aug 20 15:52: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: 9291747 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 BD901600CB for ; Sat, 20 Aug 2016 15:55:56 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A40F3286BF for ; Sat, 20 Aug 2016 15:55:56 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 807C9287B5; Sat, 20 Aug 2016 15:55:56 +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 D2B70286BF for ; Sat, 20 Aug 2016 15:55:55 +0000 (UTC) Received: from localhost ([::1]:33544 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bb8ci-0002KZ-2p for patchwork-qemu-devel@patchwork.kernel.org; Sat, 20 Aug 2016 11:55:52 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45742) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bb8cR-0002KD-1C for qemu-devel@nongnu.org; Sat, 20 Aug 2016 11:55:36 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bb8cN-0002Ev-TZ for qemu-devel@nongnu.org; Sat, 20 Aug 2016 11:55:35 -0400 Received: from mail-wm0-x244.google.com ([2a00:1450:400c:c09::244]:33137) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bb8cN-0002Ei-GS; Sat, 20 Aug 2016 11:55:31 -0400 Received: by mail-wm0-x244.google.com with SMTP id o80so7166543wme.0; Sat, 20 Aug 2016 08:55:30 -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=7ytgATGZoMqOcnQgz79b7I9MwyWEH37C9Pj3D0N+NEk=; b=VV290GvnEKogwF2f0qISR5vhjAtqqXChYns3VE99DNk+fiOTnKjGq8vM7DG8ptvxFX NaxBMw1Q3ts9/v1S0+FwrB7k9r8fzphW4vFEp2Igpys8OUIC2oKv5oTTNCbAYRwlZZqr Mi0XJPy7FXjsw4q6oHsxbVpwMf7SZFyiB1SGi/fLwN0trrlHvrZffIiUGcNOlfj4/gsP k9HbE7eluW1fGaW28icRV6RpvFjTOzR8hR9clVh9tJeqNglNfORS3khGh0syfhH/IEsJ jH5sDcEr0GY1lCkCVm5UsCkMhr1iD30ZD+M9WVNu25ZkMWs3PPRd/6JEEhvuZw/Iniuq nejg== 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=7ytgATGZoMqOcnQgz79b7I9MwyWEH37C9Pj3D0N+NEk=; b=hgfUQ6D1yW8SR+ZNbE4iu5JBFZZu7RvtrorpgArVKVhvXXXCTRtcKFWMky7jjTTwsQ LT8zadZ+HRB+ujh58rFXa4o2zKgBJxwB/JwviK5VDFgM1HhRZq++RRoGW5Myw9+Wj6lx bePrrunBWLjdkyXKsni/pypLmpwpONrPW0TU7gyGe/BWRmVK64h5tlwpVAVHEfLwhzQM +tEx2ivdpEkyzUkRP9oHlGx1eWoEZ97VW4inyBUjiKeU7DBhW2xB9eQSg3t5ciFml5Bk LbDNJIh3NY7RKHPZjPQ96cTN8YfmU3X+99cZFmrtpe9Uosp2uP0YuB4Q46uhGB8QKycl SWoQ== X-Gm-Message-State: AEkoous9TPiOl8xsd3ynkq8/G9I4xIlsN0h27CCMrOCVW9NxAX8CtWJOOEn7zNWsqWy2aQ== X-Received: by 10.28.131.199 with SMTP id f190mr8651704wmd.30.1471708498487; Sat, 20 Aug 2016 08:54:58 -0700 (PDT) Received: from cinque_stelle.sm14.sm.cri.epita.net ([163.5.208.89]) by smtp.gmail.com with ESMTPSA id u2sm5010595wmf.5.2016.08.20.08.54.57 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sat, 20 Aug 2016 08:54:57 -0700 (PDT) From: Reda Sallahi To: qemu-devel@nongnu.org Date: Sat, 20 Aug 2016 17:52:49 +0200 Message-Id: <20160820155249.20598-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::244 Subject: [Qemu-devel] [PATCH v4] 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 The subcommand 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 v3: * Remove unnecessary checks Changes from v2: * Remove redundant code Changes from v1: * add --image-opts handling qemu-img.c | 139 +++++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 90 insertions(+), 49 deletions(-) diff --git a/qemu-img.c b/qemu-img.c index f8ba5e5..57b99d8 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -3919,14 +3919,15 @@ 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; int c, i; const char *out_fmt = "raw"; const char *fmt = NULL; - int64_t size = 0; + int64_t size = 0, out_size; int64_t block_count = 0, out_pos, in_pos; struct DdInfo dd = { .flags = 0, @@ -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,100 @@ 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 (in.offset > INT64_MAX / in.bsz || size < in.offset * in.bsz) { + out_size = 0; } else { - qemu_opt_set_number(opts, BLOCK_OPT_SIZE, - size - in.bsz * in.offset, &error_abort); + out_size = size - in.offset * in.bsz; } - 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; + 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 { + qoptions = qdict_new(); + qdict_put(qoptions, "driver", qstring_from_str(out_fmt)); } - 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); + + qemu_opt_set_number(opts, BLOCK_OPT_SIZE, out_size, &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 (in.offset <= INT64_MAX / in.bsz && size >= in.offset * in.bsz) { + if (blk2sz < out_size) { + blk_truncate(blk2, out_size); + } + } } if (dd.flags & C_SKIP && (in.offset > INT64_MAX / in.bsz || @@ -4141,6 +4181,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);