]> git.proxmox.com Git - pve-qemu.git/blame - debian/patches/pve/0010-PVE-Up-qemu-img-dd-add-osize-and-read-from-to-stdin-.patch
bump version to 6.2.0-11
[pve-qemu.git] / debian / patches / pve / 0010-PVE-Up-qemu-img-dd-add-osize-and-read-from-to-stdin-.patch
CommitLineData
23102ed6 1From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
3c6facff 2From: Wolfgang Bumiller <w.bumiller@proxmox.com>
83faa3fe
TL
3Date: Mon, 6 Apr 2020 12:16:40 +0200
4Subject: [PATCH] PVE: [Up] qemu-img dd: add osize and read from/to
53e83913 5 stdin/stdout
3c6facff
WB
6
7Neither convert nor dd were previously able to write to or
8read from a pipe. Particularly serializing an image file
9into a raw stream or vice versa can be useful, but using
10`qemu-img convert -f qcow2 -O raw foo.qcow2 /dev/stdout` in
11a pipe will fail trying to seek.
12
13While dd and convert have overlapping use cases, `dd` is a
14simple read/write loop while convert is much more
15sophisticated and has ways to dealing with holes and blocks
16of zeroes.
17Since these typically can't be detected in pipes via
18SEEK_DATA/HOLE or skipped while writing, dd seems to be the
19better choice for implementing stdin/stdout streams.
20
21This patch causes "if" and "of" to default to stdin and
22stdout respectively, allowing only the "raw" format to be
23used in these cases.
24Since the input can now be a pipe we have no way of
25detecting the size of the output image to create. Since we
26also want to support images with a size not matching the
27dd command's "bs" parameter (which, together with "count"
28could be used to calculate the desired size, and is already
29used to limit it), the "osize" option is added to explicitly
30override the output file's size.
31
32Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
b855dce7 33Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
3c6facff 34---
67af0fa4 35 qemu-img-cmds.hx | 4 +-
8dca018b
SR
36 qemu-img.c | 187 +++++++++++++++++++++++++++++------------------
37 2 files changed, 119 insertions(+), 72 deletions(-)
3c6facff 38
67af0fa4 39diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
4567474e 40index 72bcdcfbfa..0b2999f3ab 100644
67af0fa4
WB
41--- a/qemu-img-cmds.hx
42+++ b/qemu-img-cmds.hx
60ae3775 43@@ -58,9 +58,9 @@ SRST
83faa3fe 44 ERST
67af0fa4
WB
45
46 DEF("dd", img_dd,
6838f038
WB
47- "dd [--image-opts] [-U] [-f fmt] [-O output_fmt] [bs=block_size] [count=blocks] [skip=blocks] if=input of=output")
48+ "dd [--image-opts] [-U] [-f fmt] [-O output_fmt] [bs=block_size] [count=blocks] [skip=blocks] [osize=output_size] if=input of=output")
83faa3fe
TL
49 SRST
50-.. option:: dd [--image-opts] [-U] [-f FMT] [-O OUTPUT_FMT] [bs=BLOCK_SIZE] [count=BLOCKS] [skip=BLOCKS] if=INPUT of=OUTPUT
51+.. option:: dd [--image-opts] [-U] [-f FMT] [-O OUTPUT_FMT] [bs=BLOCK_SIZE] [count=BLOCKS] [skip=BLOCKS] [osize=OUTPUT_SIZE] if=INPUT of=OUTPUT
52 ERST
67af0fa4
WB
53
54 DEF("info", img_info,
3c6facff 55diff --git a/qemu-img.c b/qemu-img.c
4567474e 56index 080ad9bca7..1f457d9e80 100644
3c6facff
WB
57--- a/qemu-img.c
58+++ b/qemu-img.c
4567474e 59@@ -4805,10 +4805,12 @@ static int img_bitmap(int argc, char **argv)
3c6facff
WB
60 #define C_IF 04
61 #define C_OF 010
62 #define C_SKIP 020
63+#define C_OSIZE 040
64
65 struct DdInfo {
66 unsigned int flags;
67 int64_t count;
68+ int64_t osize;
69 };
70
71 struct DdIo {
4567474e 72@@ -4884,6 +4886,19 @@ static int img_dd_skip(const char *arg,
3c6facff
WB
73 return 0;
74 }
75
76+static int img_dd_osize(const char *arg,
77+ struct DdIo *in, struct DdIo *out,
78+ struct DdInfo *dd)
79+{
60ae3775 80+ dd->osize = cvtnum("size", arg);
3c6facff
WB
81+
82+ if (dd->osize < 0) {
3c6facff
WB
83+ return 1;
84+ }
85+
86+ return 0;
87+}
88+
89 static int img_dd(int argc, char **argv)
90 {
91 int ret = 0;
4567474e 92@@ -4924,6 +4939,7 @@ static int img_dd(int argc, char **argv)
3c6facff
WB
93 { "if", img_dd_if, C_IF },
94 { "of", img_dd_of, C_OF },
95 { "skip", img_dd_skip, C_SKIP },
96+ { "osize", img_dd_osize, C_OSIZE },
97 { NULL, NULL, 0 }
98 };
99 const struct option long_options[] = {
4567474e 100@@ -4999,91 +5015,112 @@ static int img_dd(int argc, char **argv)
3c6facff
WB
101 arg = NULL;
102 }
103
104- if (!(dd.flags & C_IF && dd.flags & C_OF)) {
105- error_report("Must specify both input and output files");
106+ if (!(dd.flags & C_IF) && (!fmt || strcmp(fmt, "raw") != 0)) {
107+ error_report("Input format must be raw when readin from stdin");
3c6facff
WB
108 ret = -1;
109 goto out;
110 }
8dca018b
SR
111-
112- blk1 = img_open(image_opts, in.filename, fmt, 0, false, false,
113- force_share);
114-
115- if (!blk1) {
116+ if (!(dd.flags & C_OF) && strcmp(out_fmt, "raw") != 0) {
117+ error_report("Output format must be raw when writing to stdout");
118 ret = -1;
6838f038
WB
119 goto out;
120 }
121
8dca018b
SR
122- drv = bdrv_find_format(out_fmt);
123- if (!drv) {
124- error_report("Unknown file format");
125- ret = -1;
126- goto out;
127- }
128- proto_drv = bdrv_find_protocol(out.filename, true, &local_err);
3c6facff 129+ if (dd.flags & C_IF) {
6838f038
WB
130+ blk1 = img_open(image_opts, in.filename, fmt, 0, false, false,
131+ force_share);
3c6facff 132
8dca018b
SR
133- if (!proto_drv) {
134- error_report_err(local_err);
135- ret = -1;
136- goto out;
4fd0fa7f 137- }
8dca018b
SR
138- if (!drv->create_opts) {
139- error_report("Format driver '%s' does not support image creation",
140- drv->format_name);
141- ret = -1;
142- goto out;
143- }
144- if (!proto_drv->create_opts) {
145- error_report("Protocol driver '%s' does not support image creation",
146- proto_drv->format_name);
3c6facff
WB
147- ret = -1;
148- goto out;
4fd0fa7f
TL
149+ if (!blk1) {
150+ ret = -1;
151+ goto out;
152+ }
153 }
8dca018b
SR
154- create_opts = qemu_opts_append(create_opts, drv->create_opts);
155- create_opts = qemu_opts_append(create_opts, proto_drv->create_opts);
ddbf7a87 156
4fd0fa7f
TL
157- opts = qemu_opts_create(create_opts, NULL, 0, &error_abort);
158-
8dca018b
SR
159- size = blk_getlength(blk1);
160- if (size < 0) {
161- error_report("Failed to get size for '%s'", in.filename);
b855dce7
TL
162+ if (dd.flags & C_OSIZE) {
163+ size = dd.osize;
164+ } else if (dd.flags & C_IF) {
165+ size = blk_getlength(blk1);
166+ if (size < 0) {
167+ error_report("Failed to get size for '%s'", in.filename);
168+ ret = -1;
169+ goto out;
170+ }
171+ } else if (dd.flags & C_COUNT) {
172+ size = dd.count * in.bsz;
173+ } else {
174+ error_report("Output size must be known when reading from stdin");
175 ret = -1;
176 goto out;
177 }
178
8dca018b 179- if (dd.flags & C_COUNT && dd.count <= INT64_MAX / in.bsz &&
b855dce7 180+ if (!(dd.flags & C_OSIZE) && dd.flags & C_COUNT && dd.count <= INT64_MAX / in.bsz &&
8dca018b
SR
181 dd.count * in.bsz < size) {
182 size = dd.count * in.bsz;
b855dce7
TL
183 }
184
8dca018b
SR
185- /* Overflow means the specified offset is beyond input image's size */
186- if (dd.flags & C_SKIP && (in.offset > INT64_MAX / in.bsz ||
187- size < in.bsz * in.offset)) {
188- qemu_opt_set_number(opts, BLOCK_OPT_SIZE, 0, &error_abort);
189- } else {
190- qemu_opt_set_number(opts, BLOCK_OPT_SIZE,
191- size - in.bsz * in.offset, &error_abort);
192- }
3c6facff
WB
193+ if (dd.flags & C_OF) {
194+ drv = bdrv_find_format(out_fmt);
195+ if (!drv) {
196+ error_report("Unknown file format");
197+ ret = -1;
198+ goto out;
199+ }
200+ proto_drv = bdrv_find_protocol(out.filename, true, &local_err);
6838f038 201
8dca018b
SR
202- ret = bdrv_create(drv, out.filename, opts, &local_err);
203- if (ret < 0) {
204- error_reportf_err(local_err,
205- "%s: error while creating output image: ",
206- out.filename);
6838f038
WB
207- ret = -1;
208- goto out;
209- }
3c6facff
WB
210+ if (!proto_drv) {
211+ error_report_err(local_err);
212+ ret = -1;
213+ goto out;
214+ }
215+ if (!drv->create_opts) {
216+ error_report("Format driver '%s' does not support image creation",
217+ drv->format_name);
218+ ret = -1;
219+ goto out;
220+ }
221+ if (!proto_drv->create_opts) {
222+ error_report("Protocol driver '%s' does not support image creation",
223+ proto_drv->format_name);
224+ ret = -1;
225+ goto out;
226+ }
227+ create_opts = qemu_opts_append(create_opts, drv->create_opts);
228+ create_opts = qemu_opts_append(create_opts, proto_drv->create_opts);
229
8dca018b
SR
230- /* TODO, we can't honour --image-opts for the target,
231- * since it needs to be given in a format compatible
232- * with the bdrv_create() call above which does not
233- * support image-opts style.
234- */
235- blk2 = img_open_file(out.filename, NULL, out_fmt, BDRV_O_RDWR,
236- false, false, false);
3c6facff
WB
237+ opts = qemu_opts_create(create_opts, NULL, 0, &error_abort);
238
8dca018b
SR
239- if (!blk2) {
240- ret = -1;
241- goto out;
3c6facff
WB
242+ /* Overflow means the specified offset is beyond input image's size */
243+ if (dd.flags & C_OSIZE) {
244+ qemu_opt_set_number(opts, BLOCK_OPT_SIZE, size, &error_abort);
245+ } else if (dd.flags & C_SKIP && (in.offset > INT64_MAX / in.bsz ||
6838f038 246+ size < in.bsz * in.offset)) {
3c6facff
WB
247+ qemu_opt_set_number(opts, BLOCK_OPT_SIZE, 0, &error_abort);
248+ } else {
249+ qemu_opt_set_number(opts, BLOCK_OPT_SIZE,
250+ size - in.bsz * in.offset, &error_abort);
251+ }
8dca018b 252+
3c6facff
WB
253+ ret = bdrv_create(drv, out.filename, opts, &local_err);
254+ if (ret < 0) {
255+ error_reportf_err(local_err,
256+ "%s: error while creating output image: ",
257+ out.filename);
258+ ret = -1;
259+ goto out;
260+ }
8dca018b 261+
6838f038
WB
262+ /* TODO, we can't honour --image-opts for the target,
263+ * since it needs to be given in a format compatible
264+ * with the bdrv_create() call above which does not
265+ * support image-opts style.
266+ */
267+ blk2 = img_open_file(out.filename, NULL, out_fmt, BDRV_O_RDWR,
268+ false, false, false);
8dca018b 269+
3c6facff
WB
270+ if (!blk2) {
271+ ret = -1;
272+ goto out;
273+ }
274 }
275
276 if (dd.flags & C_SKIP && (in.offset > INT64_MAX / in.bsz ||
4567474e 277@@ -5101,11 +5138,17 @@ static int img_dd(int argc, char **argv)
3c6facff
WB
278
279 for (out_pos = 0; in_pos < size; block_count++) {
280 int in_ret, out_ret;
6838f038 281-
3c6facff
WB
282- if (in_pos + in.bsz > size) {
283- in_ret = blk_pread(blk1, in_pos, in.buf, size - in_pos);
6838f038 284+ size_t in_bsz = in_pos + in.bsz > size ? size - in_pos : in.bsz;
3c6facff
WB
285+ if (blk1) {
286+ in_ret = blk_pread(blk1, in_pos, in.buf, in_bsz);
287 } else {
288- in_ret = blk_pread(blk1, in_pos, in.buf, in.bsz);
289+ in_ret = read(STDIN_FILENO, in.buf, in_bsz);
290+ if (in_ret == 0) {
291+ /* early EOF is considered an error */
292+ error_report("Input ended unexpectedly");
293+ ret = -1;
294+ goto out;
295+ }
296 }
297 if (in_ret < 0) {
298 error_report("error while reading from input image file: %s",
4567474e 299@@ -5115,9 +5158,13 @@ static int img_dd(int argc, char **argv)
3c6facff
WB
300 }
301 in_pos += in_ret;
302
303- out_ret = blk_pwrite(blk2, out_pos, in.buf, in_ret, 0);
304+ if (blk2) {
305+ out_ret = blk_pwrite(blk2, out_pos, in.buf, in_ret, 0);
306+ } else {
307+ out_ret = write(STDOUT_FILENO, in.buf, in_ret);
308+ }
309
310- if (out_ret < 0) {
311+ if (out_ret != in_ret) {
312 error_report("error while writing to output image file: %s",
313 strerror(-out_ret));
314 ret = -1;