@@ -46,9 +46,9 @@ STEXI
ETEXI
DEF("dd", img_dd,
- "dd [--image-opts] [-f fmt] [-O output_fmt] [bs=block_size] [count=blocks] [skip=blocks] [seek=blocks] [conv=notrunc] if=input of=output")
+ "dd [--image-opts] [-f fmt] [-O output_fmt] [bs=block_size] [count=blocks] [skip=blocks] [seek=blocks] [conv=notrunc] [iflag=flags] [oflag=flags] if=input of=output")
STEXI
- @item dd [--image-opts] [-f @var{fmt}] [-O @var{output_fmt}] [bs=@var{block_size}] [count=@var{blocks}] [skip=@var{blocks}] [seek=@var{blocks}] [conv=notrunc] 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}] [seek=@var{blocks}] [conv=notrunc] [iflag=@var{flags}] [oflag=@var{flags}] if=@var{input} of=@var{output}
ETEXI
DEF("info", img_info,
@@ -176,7 +176,16 @@ static void QEMU_NORETURN help(void)
" 'of=FILE' write to FILE\n"
" 'skip=N' skip N bs-sized blocks at the start of input\n"
" 'seek=N' seek N bs-sized blocks at the start of output\n"
- " 'conv=notrunc' do not truncate the output file\n";
+ " 'conv=notrunc' do not truncate the output file\n"
+ " 'iflags=FLAGS' read using the comma-separated flags list\n"
+ " 'oflags=FLAGS' read using the comma-separated flags list\n\n"
+ "List of FLAGS for dd:\n"
+ " 'direct' use direct I/O for data\n"
+ " 'dsync' use synchronized I/O for data\n"
+ " 'sync' use synchronized I/O for data\n"
+ " 'count_bytes' use 'count=N' as a byte count (iflag only)\n"
+ " 'skip_bytes' use 'skip=N' as a byte count (iflag only)\n"
+ " 'seek_bytes' use 'seek=N' as a byte count (oflag only)\n";
printf("%s\nSupported formats:", help_msg);
bdrv_iterate_format(format_print, NULL);
@@ -3811,6 +3820,8 @@ out:
#define C_SKIP 020
#define C_SEEK 040
#define C_CONV 0100
+#define C_IFLAG 0200
+#define C_OFLAG 0400
struct DdInfo {
unsigned int flags;
@@ -3823,6 +3834,7 @@ struct DdIo {
char *filename;
uint8_t *buf;
int64_t offset;
+ unsigned int flags;
};
struct DdOpts {
@@ -3831,6 +3843,11 @@ struct DdOpts {
unsigned int flag;
};
+struct DdSymbols {
+ const char *name;
+ unsigned int value;
+};
+
static int img_dd_bs(const char *arg,
struct DdIo *in, struct DdIo *out,
struct DdInfo *dd)
@@ -3930,6 +3947,73 @@ static int img_dd_conv(const char *arg,
}
}
+#define C_DIRECT 01
+#define C_IOFLAG_SYNC 02
+#define C_DSYNC 04
+#define C_COUNT_BYTES 010
+#define C_SKIP_BYTES 020
+#define C_SEEK_BYTES 040
+
+static int img_dd_flag(const char *arg, struct DdIo *io,
+ const struct DdSymbols *flags, const char *err_str)
+{
+ int ret = 0;
+ const char *tok;
+ char *str, *tmp;
+
+ tmp = str = g_strdup(arg);
+
+ while (tmp != NULL && !ret) {
+ tok = qemu_strsep(&tmp, ",");
+ int j;
+ for (j = 0; flags[j].name != NULL; j++) {
+ if (!strcmp(tok, flags[j].name)) {
+ io->flags |= flags[j].value;
+ break;
+ }
+ }
+ if (flags[j].name == NULL) {
+ error_report("%s: '%s'", err_str, tok);
+ ret = 1;
+ }
+ }
+
+ g_free(str);
+
+ return ret;
+}
+
+static int img_dd_iflag(const char *arg,
+ struct DdIo *in, struct DdIo *out,
+ struct DdInfo *dd)
+{
+ const struct DdSymbols flags[] = {
+ { "direct", C_DIRECT },
+ { "dsync", C_DSYNC },
+ { "sync", C_IOFLAG_SYNC },
+ { "count_bytes", C_COUNT_BYTES },
+ { "skip_bytes", C_SKIP_BYTES },
+ { NULL, 0}
+ };
+
+ return img_dd_flag(arg, in, flags, "invalid input flag");
+}
+
+static int img_dd_oflag(const char *arg,
+ struct DdIo *in, struct DdIo *out,
+ struct DdInfo *dd)
+{
+ const struct DdSymbols flags[] = {
+ { "direct", C_DIRECT },
+ { "dsync", C_DSYNC },
+ { "sync", C_IOFLAG_SYNC },
+ { "seek_bytes", C_SEEK_BYTES },
+ { NULL, 0 }
+ };
+
+ return img_dd_flag(arg, out, flags, "invalid output flag");
+}
+
static int img_dd(int argc, char **argv)
{
int ret = 0;
@@ -3947,6 +4031,9 @@ static int img_dd(int argc, char **argv)
const char *out_filename;
int64_t size = 0, out_size = 0;
int64_t block_count = 0, out_pos, in_pos;
+ bool writethrough = false;
+ int flags = 0;
+ int ibsz = 0, obsz = 0;
struct DdInfo dd = {
.flags = 0,
.count = 0,
@@ -3956,13 +4043,15 @@ static int img_dd(int argc, char **argv)
.bsz = 512, /* Block size is by default 512 bytes */
.filename = NULL,
.buf = NULL,
- .offset = 0
+ .offset = 0,
+ .flags = 0
};
struct DdIo out = {
.bsz = 512,
.filename = NULL,
.buf = NULL,
- .offset = 0
+ .offset = 0,
+ .flags = 0
};
const struct DdOpts options[] = {
@@ -3973,6 +4062,8 @@ static int img_dd(int argc, char **argv)
{ "skip", img_dd_skip, C_SKIP },
{ "seek", img_dd_seek, C_SEEK },
{ "conv", img_dd_conv, C_CONV },
+ { "iflag", img_dd_iflag, C_IFLAG },
+ { "oflag", img_dd_oflag, C_OFLAG },
{ NULL, NULL, 0 }
};
const struct option long_options[] = {
@@ -4038,8 +4129,13 @@ static int img_dd(int argc, char **argv)
arg = NULL;
}
+ obsz = out.bsz;
+ if (out.flags & C_SEEK_BYTES) {
+ obsz = 1;
+ }
+
/* Overflow check for seek */
- if (out.offset > INT64_MAX / out.bsz) {
+ if (out.offset > INT64_MAX / obsz) {
error_report("seek with the block size specified is too large "
"for data type used");
ret = -1;
@@ -4051,29 +4147,50 @@ static int img_dd(int argc, char **argv)
ret = -1;
goto out;
}
- blk1 = img_open(image_opts, in.filename, fmt, 0, false, false);
+ /* These flags make sense only for output but we're adding them anyway
+ to have something close to GNU dd(1) */
+ if (in.flags & C_DSYNC || in.flags & C_IOFLAG_SYNC) {
+ writethrough = true;
+ }
+ if (in.flags & C_DIRECT) {
+ flags |= BDRV_O_NOCACHE;
+ }
+
+ blk1 = img_open(image_opts, in.filename, fmt, flags, writethrough, false);
if (!blk1) {
ret = -1;
goto out;
}
+ writethrough = false; /* Reset to the default value */
size = blk_getlength(blk1);
+
if (size < 0) {
error_report("Failed to get size for '%s'", in.filename);
ret = -1;
goto out;
}
- if (dd.flags & C_COUNT && dd.count <= INT64_MAX / in.bsz &&
- dd.count * in.bsz < size) {
- size = dd.count * in.bsz;
+ ibsz = in.bsz;
+
+ if (in.flags & C_COUNT_BYTES) {
+ ibsz = 1;
+ }
+ if (dd.flags & C_COUNT && dd.count <= INT64_MAX / ibsz &&
+ dd.count * ibsz < size) {
+ size = dd.count * ibsz;
+ }
+
+ ibsz = in.bsz; /* Reset ibsz for the skip option */
+ if (in.flags & C_SKIP_BYTES) {
+ ibsz = 1;
}
/* Overflow means the specified offset is beyond input image's size */
- if (in.offset > INT64_MAX / in.bsz || size < in.offset * in.bsz) {
- out_size = out.offset * out.bsz;
+ if (in.offset > INT64_MAX / ibsz || size < in.offset * ibsz) {
+ out_size = out.offset * obsz;
} else {
- out_size = size - in.offset * in.bsz + out.offset * out.bsz;
+ out_size = size - in.offset * ibsz + out.offset * obsz;
}
out_filename = out.filename;
@@ -4083,6 +4200,15 @@ static int img_dd(int argc, char **argv)
out_filename = qemu_opt_get(qopts, "filename");
}
+ flags = BDRV_O_RDWR;
+
+ if (out.flags & C_DSYNC || out.flags & C_IOFLAG_SYNC) {
+ writethrough = true;
+ }
+ if (out.flags & C_DIRECT) {
+ flags |= BDRV_O_NOCACHE;
+ }
+
ret = access(out_filename, F_OK); /* Check if file exists */
if (ret == -1) {
@@ -4127,8 +4253,10 @@ static int img_dd(int argc, char **argv)
ret = -1;
goto out;
}
- blk2 = img_open(image_opts, out.filename, out_fmt, BDRV_O_RDWR,
- false, false);
+
+ blk2 = img_open(image_opts, out.filename, out_fmt, flags,
+ writethrough, false);
+
if (!blk2) {
ret = -1;
goto out;
@@ -4136,8 +4264,8 @@ static int img_dd(int argc, char **argv)
} else {
int64_t blk2sz = 0;
- blk2 = img_open(image_opts, out.filename, out_fmt, BDRV_O_RDWR,
- false, false);
+ blk2 = img_open(image_opts, out.filename, out_fmt, flags,
+ writethrough, false);
if (!blk2) {
ret = -1;
goto out;
@@ -4159,29 +4287,29 @@ static int img_dd(int argc, char **argv)
goto out;
}
- if (in.offset > INT64_MAX / in.bsz || size < in.offset * in.bsz) {
- if (blk2sz < out.offset * out.bsz) {
- blk_truncate(blk2, out.offset * out.bsz);
+ if (in.offset > INT64_MAX / ibsz || size < in.offset * ibsz) {
+ if (blk2sz < out.offset * obsz) {
+ blk_truncate(blk2, out.offset * obsz);
}
} else if (blk2sz < out_size) {
blk_truncate(blk2, out_size);
}
}
- if (dd.flags & C_SKIP && (in.offset > INT64_MAX / in.bsz ||
- size < in.offset * in.bsz)) {
+ if (dd.flags & C_SKIP && (in.offset > INT64_MAX / ibsz ||
+ size < in.offset * ibsz)) {
/* 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_pos = in.offset * ibsz;
}
in.buf = g_new(uint8_t, in.bsz);
- for (out_pos = out.offset * out.bsz; in_pos < size; block_count++) {
+ for (out_pos = out.offset * obsz; in_pos < size; block_count++) {
int in_ret, out_ret;
if (in_pos + in.bsz > size) {
@@ -146,18 +146,42 @@ Parameters to dd subcommand:
@item bs=@var{block_size}
defines the block size
@item count=@var{blocks}
-sets the number of input blocks to copy
+sets the number of input blocks to copy. In case 'iflags=count_bytes' is
+specified, 'blocks' is interpreted as a byte count instead of a block count.
@item if=@var{input}
sets the input file
@item of=@var{output}
sets the output file. dd truncates the output file to zero if 'conv=notrunc'
is not specified.
@item skip=@var{blocks}
-sets the number of input blocks to skip
+sets the number of input blocks to skip. In case 'iflags=skip_bytes' is
+specified, 'blocks' is interpreted as a byte count instead of a block count.
@item seek=@var{blocks}
-sets the number of output blocks to skip
+sets the number of output blocks to skip. In case 'oflags=seek_bytes' is
+specified, 'blocks' is interpreted as a byte count instead of a block count.
@item conv=notrunc
makes dd not truncate output file to zero
+@item iflag=@var{flags}
+defines the flags used to read the input file. The flag list is seprated using
+commas.
+@item oflag=@var{flags}
+defines the flags used to write the output file. The flag list is seprated
+using commas.
+
+The flag list:
+@item direct
+direct I/O for data.
+@item dsync
+synchronised I/O for data.
+@item sync
+synchronised I/O for data.
+@item count_bytes
+interpret 'count=blocks' as a byte count. Only iflag.
+@item skip_bytes
+interpret 'skip=blocks' as a byte count. Only iflag.
+@item seek_bytes
+interpret 'seek=blocks' as a byte count. Only oflag.
+
@end table
Command description:
@@ -331,7 +355,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
be supplied through qemu-img.
-@item dd [-f @var{fmt}] [-O @var{output_fmt}] [bs=@var{block_size}] [count=@var{blocks}] [skip=@var{blocks}] [seek=@var{blocks}] [conv=notrunc] 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}] [seek=@var{blocks}] [conv=notrunc] [iflag=@var{flags}] [oflag=@var{flags}] if=@var{input} of=@var{output}
Dd copies from @var{input} file to @var{output} file converting it from
@var{fmt} format to @var{output_fmt} format.
new file mode 100755
@@ -0,0 +1,103 @@
+#! /bin/bash
+#
+# qemu-img dd test for the iflag 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 9 37 90K 12M"
+
+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 142k 512k" "$TEST_IMG" | _filter_qemu_io
+
+ echo
+ echo "== Converting the image with dd with skip=$skip iflag=skip_bytes =="
+
+ $QEMU_IMG dd if="$TEST_IMG" of="$TEST_IMG.out" skip="$skip" \
+ iflag=skip_bytes conv=notrunc -O "$IMGFMT" 2> /dev/null
+ TEST_IMG="$TEST_IMG.out" _check_test_img
+ dd if="$TEST_IMG" of="$TEST_IMG.out.dd" skip="$skip" iflag=skip_bytes \
+ conv=notrunc status=none
+
+ echo
+ echo "== Compare the images with qemu-img compare =="
+
+ $QEMU_IMG compare "$TEST_IMG.out.dd" "$TEST_IMG.out"
+done
+
+TEST_COUNT_BLOCKS="2 19 75 24K 12M 143G"
+
+for count in $TEST_COUNT_BLOCKS; do
+ echo
+ echo "== Creating image =="
+
+ size=1M
+ _make_test_img $size
+ _check_test_img
+
+ $QEMU_IO -c "write -P 0xa 342k 512k" "$TEST_IMG" | _filter_qemu_io
+
+ echo
+ echo "== Converting the image with dd with count=$count" \
+ "iflag=count_bytes =="
+
+ $QEMU_IMG dd if="$TEST_IMG" of="$TEST_IMG.out" count="$skip" \
+ iflag=count_bytes conv=notrunc -O "$IMGFMT" 2> /dev/null
+ TEST_IMG="$TEST_IMG.out" _check_test_img
+ dd if="$TEST_IMG" of="$TEST_IMG.out.dd" count="$skip" iflag=count_bytes \
+ conv=notrunc 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
new file mode 100644
@@ -0,0 +1,135 @@
+QA output created by 163
+
+== Creating image ==
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
+No errors were found on the image.
+wrote 524288/524288 bytes at offset 145408
+512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== Converting the image with dd with skip=1 iflag=skip_bytes ==
+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 145408
+512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== Converting the image with dd with skip=9 iflag=skip_bytes ==
+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 145408
+512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== Converting the image with dd with skip=37 iflag=skip_bytes ==
+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 145408
+512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== Converting the image with dd with skip=90K iflag=skip_bytes ==
+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 145408
+512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== Converting the image with dd with skip=12M iflag=skip_bytes ==
+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 350208
+512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== Converting the image with dd with count=2 iflag=count_bytes ==
+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 350208
+512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== Converting the image with dd with count=19 iflag=count_bytes ==
+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 350208
+512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== Converting the image with dd with count=75 iflag=count_bytes ==
+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 350208
+512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== Converting the image with dd with count=24K iflag=count_bytes ==
+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 350208
+512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== Converting the image with dd with count=12M iflag=count_bytes ==
+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 350208
+512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== Converting the image with dd with count=143G iflag=count_bytes ==
+No errors were found on the image.
+
+== Compare the images with qemu-img compare ==
+Images are identical.
+
+*** done
new file mode 100755
@@ -0,0 +1,100 @@
+#! /bin/bash
+#
+# qemu-img dd test for the oflag 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_SEEK_BLOCKS="1 3 15 10K 20M"
+
+for seek in $TEST_SEEK_BLOCKS; do
+ echo
+ echo "== Creating image =="
+
+ size=1M
+ _make_test_img $size
+ _check_test_img
+
+ $QEMU_IO -c "write -P 0xa 235k 512k" "$TEST_IMG" | _filter_qemu_io
+
+ echo
+ echo "== Converting the image with dd with seek=$seek oflag=seek_bytes =="
+
+ $QEMU_IMG dd if="$TEST_IMG" of="$TEST_IMG.out" seek="$seek" \
+ oflag=seek_bytes conv=notrunc -O "$IMGFMT" 2> /dev/null
+ TEST_IMG="$TEST_IMG.out" _check_test_img
+ dd if="$TEST_IMG" of="$TEST_IMG.out.dd" seek="$seek" \
+ oflag=seek_bytes status=none
+
+ echo
+ echo "== Compare the images with qemu-img compare =="
+
+ $QEMU_IMG compare "$TEST_IMG.out.dd" "$TEST_IMG.out"
+done
+
+echo
+echo "== Creating image =="
+
+size=1M
+_make_test_img $size
+_check_test_img
+seek=13K
+
+$QEMU_IO -c "write -P 0xa 235k 512k" "$TEST_IMG" | _filter_qemu_io
+
+echo
+echo "== Converting the image with dd with seek=$seek" \
+ "oflag=seek_bytes,direct =="
+
+$QEMU_IMG dd if="$TEST_IMG" of="$TEST_IMG.out" seek="$seek" \
+ oflag=seek_bytes conv=notrunc -O "$IMGFMT" 2> /dev/null
+TEST_IMG="$TEST_IMG.out" _check_test_img
+dd if="$TEST_IMG" of="$TEST_IMG.out.dd" seek="$seek" \
+ oflag=seek_bytes,direct conv=notrunc status=none
+
+echo
+echo "== Compare the images with qemu-img compare =="
+
+$QEMU_IMG compare "$TEST_IMG.out.dd" "$TEST_IMG.out"
+
+
+echo
+echo "*** done"
+rm -f "$seq.full"
+status=0
new file mode 100644
@@ -0,0 +1,75 @@
+QA output created by 164
+
+== Creating image ==
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
+No errors were found on the image.
+wrote 524288/524288 bytes at offset 240640
+512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== Converting the image with dd with seek=1 oflag=seek_bytes ==
+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 240640
+512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== Converting the image with dd with seek=3 oflag=seek_bytes ==
+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 240640
+512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== Converting the image with dd with seek=15 oflag=seek_bytes ==
+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 240640
+512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== Converting the image with dd with seek=10K oflag=seek_bytes ==
+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 240640
+512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== Converting the image with dd with seek=20M oflag=seek_bytes ==
+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 240640
+512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== Converting the image with dd with seek=13K oflag=seek_bytes,direct ==
+No errors were found on the image.
+
+== Compare the images with qemu-img compare ==
+Images are identical.
+
+*** done
@@ -162,3 +162,5 @@
160 rw auto quick
161 rw auto quick
162 auto quick
+163 rw auto quick
+164 rw auto quick
This adds the iflag and oflag options which defines the list of flags used for reading and writing respectively. The list is comma-separated. The iflag option supports direct, dsync, sync, count_bytes and skip_bytes and oflag supports direct, dsync, sync and seek_bytes. They are similar to their counterparts on GNU dd(1). Two tests were added to test iflag and oflag. Signed-off-by: Reda Sallahi <fullmanet@gmail.com> --- qemu-img-cmds.hx | 4 +- qemu-img.c | 172 +++++++++++++++++++++++++++++++++++++++------ qemu-img.texi | 32 +++++++-- tests/qemu-iotests/163 | 103 +++++++++++++++++++++++++++ tests/qemu-iotests/163.out | 135 +++++++++++++++++++++++++++++++++++ tests/qemu-iotests/164 | 100 ++++++++++++++++++++++++++ tests/qemu-iotests/164.out | 75 ++++++++++++++++++++ tests/qemu-iotests/group | 2 + 8 files changed, 595 insertions(+), 28 deletions(-) create mode 100755 tests/qemu-iotests/163 create mode 100644 tests/qemu-iotests/163.out create mode 100755 tests/qemu-iotests/164 create mode 100644 tests/qemu-iotests/164.out