提交 f7c15533 编写于 作者: R Reda Sallahi 提交者: Max Reitz

qemu-img: add skip option to dd

This adds the skip option which allows qemu-img dd to skip a number of blocks
before copying the input.

A test case was added to test the skip option.
Signed-off-by: NReda Sallahi <fullmanet@gmail.com>
Message-id: 20160810141609.32727-1-fullmanet@gmail.com
Signed-off-by: NMax Reitz <mreitz@redhat.com>
上级 86ce1f6e
...@@ -46,9 +46,9 @@ STEXI ...@@ -46,9 +46,9 @@ STEXI
ETEXI ETEXI
DEF("dd", img_dd, DEF("dd", img_dd,
"dd [--image-opts] [-f fmt] [-O output_fmt] [bs=block_size] [count=blocks] if=input of=output") "dd [--image-opts] [-f fmt] [-O output_fmt] [bs=block_size] [count=blocks] [skip=blocks] if=input of=output")
STEXI STEXI
@item dd [--image-opts] [-f @var{fmt}] [-O @var{output_fmt}] [bs=@var{block_size}] [count=@var{blocks}] if=@var{input} of=@var{output} @item dd [--image-opts] [-f @var{fmt}] [-O @var{output_fmt}] [bs=@var{block_size}] [count=@var{blocks}] [skip=@var{blocks}] if=@var{input} of=@var{output}
ETEXI ETEXI
DEF("info", img_info, DEF("info", img_info,
......
...@@ -173,7 +173,8 @@ static void QEMU_NORETURN help(void) ...@@ -173,7 +173,8 @@ static void QEMU_NORETURN help(void)
"(default: 512)\n" "(default: 512)\n"
" 'count=N' copy only N input blocks\n" " 'count=N' copy only N input blocks\n"
" 'if=FILE' read from FILE\n" " 'if=FILE' read from FILE\n"
" 'of=FILE' write to FILE\n"; " 'of=FILE' write to FILE\n"
" 'skip=N' skip N bs-sized blocks at the start of input\n";
printf("%s\nSupported formats:", help_msg); printf("%s\nSupported formats:", help_msg);
bdrv_iterate_format(format_print, NULL); bdrv_iterate_format(format_print, NULL);
...@@ -3807,6 +3808,7 @@ out: ...@@ -3807,6 +3808,7 @@ out:
#define C_COUNT 02 #define C_COUNT 02
#define C_IF 04 #define C_IF 04
#define C_OF 010 #define C_OF 010
#define C_SKIP 020
struct DdInfo { struct DdInfo {
unsigned int flags; unsigned int flags;
...@@ -3817,6 +3819,7 @@ struct DdIo { ...@@ -3817,6 +3819,7 @@ struct DdIo {
int bsz; /* Block size */ int bsz; /* Block size */
char *filename; char *filename;
uint8_t *buf; uint8_t *buf;
int64_t offset;
}; };
struct DdOpts { struct DdOpts {
...@@ -3877,6 +3880,22 @@ static int img_dd_of(const char *arg, ...@@ -3877,6 +3880,22 @@ static int img_dd_of(const char *arg,
return 0; return 0;
} }
static int img_dd_skip(const char *arg,
struct DdIo *in, struct DdIo *out,
struct DdInfo *dd)
{
char *end;
in->offset = qemu_strtosz_suffix(arg, &end, QEMU_STRTOSZ_DEFSUFFIX_B);
if (in->offset < 0 || *end) {
error_report("invalid number: '%s'", arg);
return 1;
}
return 0;
}
static int img_dd(int argc, char **argv) static int img_dd(int argc, char **argv)
{ {
int ret = 0; int ret = 0;
...@@ -3900,12 +3919,14 @@ static int img_dd(int argc, char **argv) ...@@ -3900,12 +3919,14 @@ static int img_dd(int argc, char **argv)
struct DdIo in = { struct DdIo in = {
.bsz = 512, /* Block size is by default 512 bytes */ .bsz = 512, /* Block size is by default 512 bytes */
.filename = NULL, .filename = NULL,
.buf = NULL .buf = NULL,
.offset = 0
}; };
struct DdIo out = { struct DdIo out = {
.bsz = 512, .bsz = 512,
.filename = NULL, .filename = NULL,
.buf = NULL .buf = NULL,
.offset = 0
}; };
const struct DdOpts options[] = { const struct DdOpts options[] = {
...@@ -3913,6 +3934,7 @@ static int img_dd(int argc, char **argv) ...@@ -3913,6 +3934,7 @@ static int img_dd(int argc, char **argv)
{ "count", img_dd_count, C_COUNT }, { "count", img_dd_count, C_COUNT },
{ "if", img_dd_if, C_IF }, { "if", img_dd_if, C_IF },
{ "of", img_dd_of, C_OF }, { "of", img_dd_of, C_OF },
{ "skip", img_dd_skip, C_SKIP },
{ NULL, NULL, 0 } { NULL, NULL, 0 }
}; };
const struct option long_options[] = { const struct option long_options[] = {
...@@ -4032,7 +4054,14 @@ static int img_dd(int argc, char **argv) ...@@ -4032,7 +4054,14 @@ static int img_dd(int argc, char **argv)
size = dd.count * in.bsz; size = dd.count * in.bsz;
} }
qemu_opt_set_number(opts, BLOCK_OPT_SIZE, size, &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.bsz * in.offset)) {
qemu_opt_set_number(opts, BLOCK_OPT_SIZE, 0, &error_abort);
} else {
qemu_opt_set_number(opts, BLOCK_OPT_SIZE,
size - in.bsz * in.offset, &error_abort);
}
ret = bdrv_create(drv, out.filename, opts, &local_err); ret = bdrv_create(drv, out.filename, opts, &local_err);
if (ret < 0) { if (ret < 0) {
...@@ -4051,9 +4080,20 @@ static int img_dd(int argc, char **argv) ...@@ -4051,9 +4080,20 @@ static int img_dd(int argc, char **argv)
goto out; goto out;
} }
if (dd.flags & C_SKIP && (in.offset > INT64_MAX / in.bsz ||
size < in.offset * in.bsz)) {
/* We give a warning if the skip option is bigger than the input
* size and create an empty output disk image (i.e. like dd(1)).
*/
error_report("%s: cannot skip to specified offset", in.filename);
in_pos = size;
} else {
in_pos = in.offset * in.bsz;
}
in.buf = g_new(uint8_t, in.bsz); in.buf = g_new(uint8_t, in.bsz);
for (in_pos = 0, out_pos = 0; in_pos < size; block_count++) { for (out_pos = 0; in_pos < size; block_count++) {
int in_ret, out_ret; int in_ret, out_ret;
if (in_pos + in.bsz > size) { if (in_pos + in.bsz > size) {
......
...@@ -151,6 +151,8 @@ sets the number of input blocks to copy ...@@ -151,6 +151,8 @@ sets the number of input blocks to copy
sets the input file sets the input file
@item of=@var{output} @item of=@var{output}
sets the output file sets the output file
@item skip=@var{blocks}
sets the number of input blocks to skip
@end table @end table
Command description: Command description:
...@@ -324,7 +326,7 @@ skipped. This is useful for formats such as @code{rbd} if the target ...@@ -324,7 +326,7 @@ skipped. This is useful for formats such as @code{rbd} if the target
volume has already been created with site specific options that cannot volume has already been created with site specific options that cannot
be supplied through qemu-img. be supplied through qemu-img.
@item dd [-f @var{fmt}] [-O @var{output_fmt}] [bs=@var{block_size}] [count=@var{blocks}] if=@var{input} of=@var{output} @item dd [-f @var{fmt}] [-O @var{output_fmt}] [bs=@var{block_size}] [count=@var{blocks}] [skip=@var{blocks}] if=@var{input} of=@var{output}
Dd copies from @var{input} file to @var{output} file converting it from Dd copies from @var{input} file to @var{output} file converting it from
@var{fmt} format to @var{output_fmt} format. @var{fmt} format to @var{output_fmt} format.
......
#! /bin/bash
#
# qemu-img dd test for the skip option
#
# Copyright (C) 2016 Reda Sallahi
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
owner=fullmanet@gmail.com
seq="$(basename $0)"
echo "QA output created by $seq"
here="$PWD"
status=1
_cleanup()
{
_cleanup_test_img
rm -f "$TEST_IMG.out" "$TEST_IMG.out.dd"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
. ./common.rc
. ./common.filter
. ./common.pattern
_supported_fmt raw
_supported_proto file
_supported_os Linux
TEST_SKIP_BLOCKS="1 2 30 30K"
for skip in $TEST_SKIP_BLOCKS; do
echo
echo "== Creating image =="
size=1M
_make_test_img $size
_check_test_img
$QEMU_IO -c "write -P 0xa 24 512k" "$TEST_IMG" | _filter_qemu_io
echo
echo "== Converting the image with dd with skip=$skip =="
$QEMU_IMG dd if="$TEST_IMG" of="$TEST_IMG.out" skip="$skip" -O "$IMGFMT" \
2> /dev/null
TEST_IMG="$TEST_IMG.out" _check_test_img
dd if="$TEST_IMG" of="$TEST_IMG.out.dd" skip="$skip" status=none
echo
echo "== Compare the images with qemu-img compare =="
$QEMU_IMG compare "$TEST_IMG.out.dd" "$TEST_IMG.out"
done
echo
echo "*** done"
rm -f "$seq.full"
status=0
QA output created by 160
== Creating image ==
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
No errors were found on the image.
wrote 524288/524288 bytes at offset 24
512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
== Converting the image with dd with skip=1 ==
No errors were found on the image.
== Compare the images with qemu-img compare ==
Images are identical.
== Creating image ==
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
No errors were found on the image.
wrote 524288/524288 bytes at offset 24
512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
== Converting the image with dd with skip=2 ==
No errors were found on the image.
== Compare the images with qemu-img compare ==
Images are identical.
== Creating image ==
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
No errors were found on the image.
wrote 524288/524288 bytes at offset 24
512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
== Converting the image with dd with skip=30 ==
No errors were found on the image.
== Compare the images with qemu-img compare ==
Images are identical.
== Creating image ==
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
No errors were found on the image.
wrote 524288/524288 bytes at offset 24
512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
== Converting the image with dd with skip=30K ==
No errors were found on the image.
== Compare the images with qemu-img compare ==
Images are identical.
*** done
...@@ -158,5 +158,6 @@ ...@@ -158,5 +158,6 @@
156 rw auto quick 156 rw auto quick
157 auto 157 auto
159 rw auto quick 159 rw auto quick
160 rw auto quick
162 auto quick 162 auto quick
170 rw auto quick 170 rw auto quick
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册