138501a46SMarcel Moolenaar /*-
238501a46SMarcel Moolenaar * Copyright (c) 2014 Marcel Moolenaar
338501a46SMarcel Moolenaar * All rights reserved.
438501a46SMarcel Moolenaar *
538501a46SMarcel Moolenaar * Redistribution and use in source and binary forms, with or without
638501a46SMarcel Moolenaar * modification, are permitted provided that the following conditions
738501a46SMarcel Moolenaar * are met:
838501a46SMarcel Moolenaar * 1. Redistributions of source code must retain the above copyright
938501a46SMarcel Moolenaar * notice, this list of conditions and the following disclaimer.
1038501a46SMarcel Moolenaar * 2. Redistributions in binary form must reproduce the above copyright
1138501a46SMarcel Moolenaar * notice, this list of conditions and the following disclaimer in the
1238501a46SMarcel Moolenaar * documentation and/or other materials provided with the distribution.
1338501a46SMarcel Moolenaar *
1438501a46SMarcel Moolenaar * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1538501a46SMarcel Moolenaar * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1638501a46SMarcel Moolenaar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1738501a46SMarcel Moolenaar * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1838501a46SMarcel Moolenaar * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1938501a46SMarcel Moolenaar * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2038501a46SMarcel Moolenaar * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2138501a46SMarcel Moolenaar * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2238501a46SMarcel Moolenaar * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2338501a46SMarcel Moolenaar * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2438501a46SMarcel Moolenaar * SUCH DAMAGE.
2538501a46SMarcel Moolenaar */
2638501a46SMarcel Moolenaar
2738501a46SMarcel Moolenaar #include <sys/cdefs.h>
2838501a46SMarcel Moolenaar #include <sys/errno.h>
294039ea7cSMarcel Moolenaar #include <assert.h>
3038501a46SMarcel Moolenaar #include <stdio.h>
3138501a46SMarcel Moolenaar #include <stdlib.h>
3238501a46SMarcel Moolenaar #include <string.h>
3338501a46SMarcel Moolenaar
345aad7d9aSMarcel Moolenaar #include "endian.h"
3538501a46SMarcel Moolenaar #include "image.h"
3638501a46SMarcel Moolenaar #include "format.h"
3738501a46SMarcel Moolenaar #include "mkimg.h"
3838501a46SMarcel Moolenaar
3938501a46SMarcel Moolenaar /* Default cluster sizes. */
4038501a46SMarcel Moolenaar #define QCOW1_CLSTR_LOG2SZ 12 /* 4KB */
4138501a46SMarcel Moolenaar #define QCOW2_CLSTR_LOG2SZ 16 /* 64KB */
4238501a46SMarcel Moolenaar
430e651cfeSMarcel Moolenaar /* Flag bits in cluster offsets */
440e651cfeSMarcel Moolenaar #define QCOW_CLSTR_COMPRESSED (1ULL << 62)
450e651cfeSMarcel Moolenaar #define QCOW_CLSTR_COPIED (1ULL << 63)
460e651cfeSMarcel Moolenaar
4738501a46SMarcel Moolenaar struct qcow_header {
4838501a46SMarcel Moolenaar uint32_t magic;
4938501a46SMarcel Moolenaar #define QCOW_MAGIC 0x514649fb
5038501a46SMarcel Moolenaar uint32_t version;
5138501a46SMarcel Moolenaar #define QCOW_VERSION_1 1
5238501a46SMarcel Moolenaar #define QCOW_VERSION_2 2
5338501a46SMarcel Moolenaar uint64_t path_offset;
5438501a46SMarcel Moolenaar uint32_t path_length;
5538501a46SMarcel Moolenaar uint32_t clstr_log2sz; /* v2 only */
5638501a46SMarcel Moolenaar uint64_t disk_size;
5738501a46SMarcel Moolenaar union {
5838501a46SMarcel Moolenaar struct {
5938501a46SMarcel Moolenaar uint8_t clstr_log2sz;
6038501a46SMarcel Moolenaar uint8_t l2_log2sz;
6138501a46SMarcel Moolenaar uint16_t _pad;
6238501a46SMarcel Moolenaar uint32_t encryption;
6338501a46SMarcel Moolenaar uint64_t l1_offset;
6438501a46SMarcel Moolenaar } v1;
6538501a46SMarcel Moolenaar struct {
6638501a46SMarcel Moolenaar uint32_t encryption;
6738501a46SMarcel Moolenaar uint32_t l1_entries;
6838501a46SMarcel Moolenaar uint64_t l1_offset;
6938501a46SMarcel Moolenaar uint64_t refcnt_offset;
700f49f146SMarcel Moolenaar uint32_t refcnt_clstrs;
7138501a46SMarcel Moolenaar uint32_t snapshot_count;
7238501a46SMarcel Moolenaar uint64_t snapshot_offset;
7338501a46SMarcel Moolenaar } v2;
7438501a46SMarcel Moolenaar } u;
7538501a46SMarcel Moolenaar };
7638501a46SMarcel Moolenaar
7738501a46SMarcel Moolenaar static u_int clstr_log2sz;
7838501a46SMarcel Moolenaar
7938501a46SMarcel Moolenaar static uint64_t
round_clstr(uint64_t ofs)8038501a46SMarcel Moolenaar round_clstr(uint64_t ofs)
8138501a46SMarcel Moolenaar {
8238501a46SMarcel Moolenaar uint64_t clstrsz;
8338501a46SMarcel Moolenaar
8438501a46SMarcel Moolenaar clstrsz = 1UL << clstr_log2sz;
8538501a46SMarcel Moolenaar return ((ofs + clstrsz - 1) & ~(clstrsz - 1));
8638501a46SMarcel Moolenaar }
8738501a46SMarcel Moolenaar
8838501a46SMarcel Moolenaar static int
qcow_resize(lba_t imgsz,u_int version)8938501a46SMarcel Moolenaar qcow_resize(lba_t imgsz, u_int version)
9038501a46SMarcel Moolenaar {
910e651cfeSMarcel Moolenaar uint64_t imagesz;
9238501a46SMarcel Moolenaar
9338501a46SMarcel Moolenaar switch (version) {
9438501a46SMarcel Moolenaar case QCOW_VERSION_1:
9538501a46SMarcel Moolenaar clstr_log2sz = QCOW1_CLSTR_LOG2SZ;
9638501a46SMarcel Moolenaar break;
9738501a46SMarcel Moolenaar case QCOW_VERSION_2:
9838501a46SMarcel Moolenaar clstr_log2sz = QCOW2_CLSTR_LOG2SZ;
9938501a46SMarcel Moolenaar break;
10038501a46SMarcel Moolenaar default:
1014039ea7cSMarcel Moolenaar assert(0);
10238501a46SMarcel Moolenaar }
10338501a46SMarcel Moolenaar
10438501a46SMarcel Moolenaar imagesz = round_clstr(imgsz * secsz);
10538501a46SMarcel Moolenaar
10638501a46SMarcel Moolenaar if (verbose)
1070e651cfeSMarcel Moolenaar fprintf(stderr, "QCOW: image size = %ju, cluster size = %u\n",
1080e651cfeSMarcel Moolenaar (uintmax_t)imagesz, (u_int)(1U << clstr_log2sz));
10938501a46SMarcel Moolenaar
11038501a46SMarcel Moolenaar return (image_set_size(imagesz / secsz));
11138501a46SMarcel Moolenaar }
11238501a46SMarcel Moolenaar
11338501a46SMarcel Moolenaar static int
qcow1_resize(lba_t imgsz)11438501a46SMarcel Moolenaar qcow1_resize(lba_t imgsz)
11538501a46SMarcel Moolenaar {
11638501a46SMarcel Moolenaar
11738501a46SMarcel Moolenaar return (qcow_resize(imgsz, QCOW_VERSION_1));
11838501a46SMarcel Moolenaar }
11938501a46SMarcel Moolenaar
12038501a46SMarcel Moolenaar static int
qcow2_resize(lba_t imgsz)12138501a46SMarcel Moolenaar qcow2_resize(lba_t imgsz)
12238501a46SMarcel Moolenaar {
12338501a46SMarcel Moolenaar
12438501a46SMarcel Moolenaar return (qcow_resize(imgsz, QCOW_VERSION_2));
12538501a46SMarcel Moolenaar }
12638501a46SMarcel Moolenaar
12738501a46SMarcel Moolenaar static int
qcow_write(int fd,u_int version)12838501a46SMarcel Moolenaar qcow_write(int fd, u_int version)
12938501a46SMarcel Moolenaar {
13038501a46SMarcel Moolenaar struct qcow_header *hdr;
131e1870642SMarcel Moolenaar uint64_t *l1tbl, *l2tbl, *rctbl;
132e1870642SMarcel Moolenaar uint16_t *rcblk;
1330e651cfeSMarcel Moolenaar uint64_t clstr_imgsz, clstr_l2tbls, clstr_l1tblsz;
1340e651cfeSMarcel Moolenaar uint64_t clstr_rcblks, clstr_rctblsz;
1350e651cfeSMarcel Moolenaar uint64_t n, imagesz, nclstrs, ofs, ofsflags;
1360e651cfeSMarcel Moolenaar lba_t blk, blkofs, blk_imgsz;
1370e651cfeSMarcel Moolenaar u_int l1clno, l2clno, rcclno;
1380f49f146SMarcel Moolenaar u_int blk_clstrsz, refcnt_clstrs;
1390e651cfeSMarcel Moolenaar u_int clstrsz, l1idx, l2idx;
14038501a46SMarcel Moolenaar int error;
14138501a46SMarcel Moolenaar
1424039ea7cSMarcel Moolenaar assert(clstr_log2sz != 0);
14338501a46SMarcel Moolenaar
1440e651cfeSMarcel Moolenaar clstrsz = 1U << clstr_log2sz;
1450e651cfeSMarcel Moolenaar blk_clstrsz = clstrsz / secsz;
1460e651cfeSMarcel Moolenaar blk_imgsz = image_get_size();
1470e651cfeSMarcel Moolenaar imagesz = blk_imgsz * secsz;
1480e651cfeSMarcel Moolenaar clstr_imgsz = imagesz >> clstr_log2sz;
1490e651cfeSMarcel Moolenaar clstr_l2tbls = round_clstr(clstr_imgsz * 8) >> clstr_log2sz;
1500e651cfeSMarcel Moolenaar clstr_l1tblsz = round_clstr(clstr_l2tbls * 8) >> clstr_log2sz;
1510e651cfeSMarcel Moolenaar nclstrs = clstr_imgsz + clstr_l2tbls + clstr_l1tblsz + 1;
1520e651cfeSMarcel Moolenaar clstr_rcblks = clstr_rctblsz = 0;
1530e651cfeSMarcel Moolenaar do {
1540e651cfeSMarcel Moolenaar n = clstr_rcblks + clstr_rctblsz;
1550e651cfeSMarcel Moolenaar clstr_rcblks = round_clstr((nclstrs + n) * 2) >> clstr_log2sz;
1560e651cfeSMarcel Moolenaar clstr_rctblsz = round_clstr(clstr_rcblks * 8) >> clstr_log2sz;
1570e651cfeSMarcel Moolenaar } while (n < (clstr_rcblks + clstr_rctblsz));
15838501a46SMarcel Moolenaar
1590e651cfeSMarcel Moolenaar /*
1600e651cfeSMarcel Moolenaar * We got all the sizes in clusters. Start the layout.
1610e651cfeSMarcel Moolenaar * 0 - header
1620e651cfeSMarcel Moolenaar * 1 - L1 table
1630e651cfeSMarcel Moolenaar * 2 - RC table (v2 only)
164e1870642SMarcel Moolenaar * 3 - L2 tables
165e1870642SMarcel Moolenaar * 4 - RC block (v2 only)
166e1870642SMarcel Moolenaar * 5 - data
1670e651cfeSMarcel Moolenaar */
1680e651cfeSMarcel Moolenaar
1690e651cfeSMarcel Moolenaar l1clno = 1;
1700e651cfeSMarcel Moolenaar rcclno = 0;
171e1870642SMarcel Moolenaar rctbl = l2tbl = l1tbl = NULL;
172e1870642SMarcel Moolenaar rcblk = NULL;
17338501a46SMarcel Moolenaar
17438501a46SMarcel Moolenaar hdr = calloc(1, clstrsz);
17538501a46SMarcel Moolenaar if (hdr == NULL)
17638501a46SMarcel Moolenaar return (errno);
17738501a46SMarcel Moolenaar
17838501a46SMarcel Moolenaar be32enc(&hdr->magic, QCOW_MAGIC);
17938501a46SMarcel Moolenaar be32enc(&hdr->version, version);
18038501a46SMarcel Moolenaar be64enc(&hdr->disk_size, imagesz);
18138501a46SMarcel Moolenaar switch (version) {
18238501a46SMarcel Moolenaar case QCOW_VERSION_1:
1830e651cfeSMarcel Moolenaar ofsflags = 0;
1840e651cfeSMarcel Moolenaar l2clno = l1clno + clstr_l1tblsz;
18538501a46SMarcel Moolenaar hdr->u.v1.clstr_log2sz = clstr_log2sz;
18638501a46SMarcel Moolenaar hdr->u.v1.l2_log2sz = clstr_log2sz - 3;
1870e651cfeSMarcel Moolenaar be64enc(&hdr->u.v1.l1_offset, clstrsz * l1clno);
18838501a46SMarcel Moolenaar break;
18938501a46SMarcel Moolenaar case QCOW_VERSION_2:
1900e651cfeSMarcel Moolenaar ofsflags = QCOW_CLSTR_COPIED;
1910e651cfeSMarcel Moolenaar rcclno = l1clno + clstr_l1tblsz;
192e1870642SMarcel Moolenaar l2clno = rcclno + clstr_rctblsz;
19338501a46SMarcel Moolenaar be32enc(&hdr->clstr_log2sz, clstr_log2sz);
1940e651cfeSMarcel Moolenaar be32enc(&hdr->u.v2.l1_entries, clstr_l2tbls);
1950e651cfeSMarcel Moolenaar be64enc(&hdr->u.v2.l1_offset, clstrsz * l1clno);
1960e651cfeSMarcel Moolenaar be64enc(&hdr->u.v2.refcnt_offset, clstrsz * rcclno);
1970f49f146SMarcel Moolenaar refcnt_clstrs = round_clstr(clstr_rcblks * 8) >> clstr_log2sz;
1980f49f146SMarcel Moolenaar be32enc(&hdr->u.v2.refcnt_clstrs, refcnt_clstrs);
19938501a46SMarcel Moolenaar break;
20038501a46SMarcel Moolenaar default:
2014039ea7cSMarcel Moolenaar assert(0);
20238501a46SMarcel Moolenaar }
20338501a46SMarcel Moolenaar
204e1870642SMarcel Moolenaar if (sparse_write(fd, hdr, clstrsz) < 0) {
205e1870642SMarcel Moolenaar error = errno;
206e1870642SMarcel Moolenaar goto out;
207e1870642SMarcel Moolenaar }
208e1870642SMarcel Moolenaar
209e1870642SMarcel Moolenaar free(hdr);
210e1870642SMarcel Moolenaar hdr = NULL;
211e1870642SMarcel Moolenaar
212e1870642SMarcel Moolenaar ofs = clstrsz * l2clno;
213e1870642SMarcel Moolenaar nclstrs = 1 + clstr_l1tblsz + clstr_rctblsz;
21438501a46SMarcel Moolenaar
215*6613eaa4SPedro F. Giffuni l1tbl = calloc(clstr_l1tblsz, clstrsz);
21638501a46SMarcel Moolenaar if (l1tbl == NULL) {
21738501a46SMarcel Moolenaar error = ENOMEM;
21838501a46SMarcel Moolenaar goto out;
21938501a46SMarcel Moolenaar }
220e1870642SMarcel Moolenaar
221e1870642SMarcel Moolenaar for (n = 0; n < clstr_imgsz; n++) {
222e1870642SMarcel Moolenaar blk = n * blk_clstrsz;
223e1870642SMarcel Moolenaar if (image_data(blk, blk_clstrsz)) {
224e1870642SMarcel Moolenaar nclstrs++;
225e1870642SMarcel Moolenaar l1idx = n >> (clstr_log2sz - 3);
226e1870642SMarcel Moolenaar if (l1tbl[l1idx] == 0) {
227e1870642SMarcel Moolenaar be64enc(l1tbl + l1idx, ofs + ofsflags);
228e1870642SMarcel Moolenaar ofs += clstrsz;
229e1870642SMarcel Moolenaar nclstrs++;
230e1870642SMarcel Moolenaar }
231e1870642SMarcel Moolenaar }
232e1870642SMarcel Moolenaar }
233e1870642SMarcel Moolenaar
234e1870642SMarcel Moolenaar if (sparse_write(fd, l1tbl, clstrsz * clstr_l1tblsz) < 0) {
235e1870642SMarcel Moolenaar error = errno;
236e1870642SMarcel Moolenaar goto out;
237e1870642SMarcel Moolenaar }
238e1870642SMarcel Moolenaar
239e1870642SMarcel Moolenaar clstr_rcblks = 0;
240e1870642SMarcel Moolenaar do {
241e1870642SMarcel Moolenaar n = clstr_rcblks;
242e1870642SMarcel Moolenaar clstr_rcblks = round_clstr((nclstrs + n) * 2) >> clstr_log2sz;
243e1870642SMarcel Moolenaar } while (n < clstr_rcblks);
244e1870642SMarcel Moolenaar
2450e651cfeSMarcel Moolenaar if (rcclno > 0) {
246*6613eaa4SPedro F. Giffuni rctbl = calloc(clstr_rctblsz, clstrsz);
24738501a46SMarcel Moolenaar if (rctbl == NULL) {
24838501a46SMarcel Moolenaar error = ENOMEM;
24938501a46SMarcel Moolenaar goto out;
25038501a46SMarcel Moolenaar }
251e1870642SMarcel Moolenaar for (n = 0; n < clstr_rcblks; n++) {
252e1870642SMarcel Moolenaar be64enc(rctbl + n, ofs);
25338501a46SMarcel Moolenaar ofs += clstrsz;
254e1870642SMarcel Moolenaar nclstrs++;
25538501a46SMarcel Moolenaar }
256e1870642SMarcel Moolenaar if (sparse_write(fd, rctbl, clstrsz * clstr_rctblsz) < 0) {
25738501a46SMarcel Moolenaar error = errno;
25838501a46SMarcel Moolenaar goto out;
259e1870642SMarcel Moolenaar }
26038501a46SMarcel Moolenaar free(rctbl);
26138501a46SMarcel Moolenaar rctbl = NULL;
26238501a46SMarcel Moolenaar }
26338501a46SMarcel Moolenaar
26438501a46SMarcel Moolenaar l2tbl = malloc(clstrsz);
26538501a46SMarcel Moolenaar if (l2tbl == NULL) {
26638501a46SMarcel Moolenaar error = ENOMEM;
26738501a46SMarcel Moolenaar goto out;
26838501a46SMarcel Moolenaar }
26938501a46SMarcel Moolenaar
2700e651cfeSMarcel Moolenaar for (l1idx = 0; l1idx < clstr_l2tbls; l1idx++) {
27138501a46SMarcel Moolenaar if (l1tbl[l1idx] == 0)
27238501a46SMarcel Moolenaar continue;
27338501a46SMarcel Moolenaar memset(l2tbl, 0, clstrsz);
2740e651cfeSMarcel Moolenaar blkofs = (lba_t)l1idx * blk_clstrsz * (clstrsz >> 3);
27538501a46SMarcel Moolenaar for (l2idx = 0; l2idx < (clstrsz >> 3); l2idx++) {
2760e651cfeSMarcel Moolenaar blk = blkofs + (lba_t)l2idx * blk_clstrsz;
2770e651cfeSMarcel Moolenaar if (blk >= blk_imgsz)
27838501a46SMarcel Moolenaar break;
2790e651cfeSMarcel Moolenaar if (image_data(blk, blk_clstrsz)) {
2800e651cfeSMarcel Moolenaar be64enc(l2tbl + l2idx, ofs + ofsflags);
28138501a46SMarcel Moolenaar ofs += clstrsz;
28238501a46SMarcel Moolenaar }
28338501a46SMarcel Moolenaar }
28438501a46SMarcel Moolenaar if (sparse_write(fd, l2tbl, clstrsz) < 0) {
28538501a46SMarcel Moolenaar error = errno;
28638501a46SMarcel Moolenaar goto out;
28738501a46SMarcel Moolenaar }
28838501a46SMarcel Moolenaar }
28938501a46SMarcel Moolenaar
29038501a46SMarcel Moolenaar free(l2tbl);
29138501a46SMarcel Moolenaar l2tbl = NULL;
29238501a46SMarcel Moolenaar free(l1tbl);
29338501a46SMarcel Moolenaar l1tbl = NULL;
29438501a46SMarcel Moolenaar
295e1870642SMarcel Moolenaar if (rcclno > 0) {
296*6613eaa4SPedro F. Giffuni rcblk = calloc(clstr_rcblks, clstrsz);
297e1870642SMarcel Moolenaar if (rcblk == NULL) {
298e1870642SMarcel Moolenaar error = ENOMEM;
299e1870642SMarcel Moolenaar goto out;
300e1870642SMarcel Moolenaar }
301e1870642SMarcel Moolenaar for (n = 0; n < nclstrs; n++)
302e1870642SMarcel Moolenaar be16enc(rcblk + n, 1);
303e1870642SMarcel Moolenaar if (sparse_write(fd, rcblk, clstrsz * clstr_rcblks) < 0) {
304e1870642SMarcel Moolenaar error = errno;
305e1870642SMarcel Moolenaar goto out;
306e1870642SMarcel Moolenaar }
307e1870642SMarcel Moolenaar free(rcblk);
308e1870642SMarcel Moolenaar rcblk = NULL;
309e1870642SMarcel Moolenaar }
310e1870642SMarcel Moolenaar
31138501a46SMarcel Moolenaar error = 0;
3120e651cfeSMarcel Moolenaar for (n = 0; n < clstr_imgsz; n++) {
3130e651cfeSMarcel Moolenaar blk = n * blk_clstrsz;
3140e651cfeSMarcel Moolenaar if (image_data(blk, blk_clstrsz)) {
3150e651cfeSMarcel Moolenaar error = image_copyout_region(fd, blk, blk_clstrsz);
31638501a46SMarcel Moolenaar if (error)
31738501a46SMarcel Moolenaar break;
31838501a46SMarcel Moolenaar }
31938501a46SMarcel Moolenaar }
32038501a46SMarcel Moolenaar if (!error)
32138501a46SMarcel Moolenaar error = image_copyout_done(fd);
32238501a46SMarcel Moolenaar
32338501a46SMarcel Moolenaar out:
324e1870642SMarcel Moolenaar if (rcblk != NULL)
325e1870642SMarcel Moolenaar free(rcblk);
32638501a46SMarcel Moolenaar if (l2tbl != NULL)
32738501a46SMarcel Moolenaar free(l2tbl);
32838501a46SMarcel Moolenaar if (rctbl != NULL)
32938501a46SMarcel Moolenaar free(rctbl);
33038501a46SMarcel Moolenaar if (l1tbl != NULL)
33138501a46SMarcel Moolenaar free(l1tbl);
33238501a46SMarcel Moolenaar if (hdr != NULL)
33338501a46SMarcel Moolenaar free(hdr);
33438501a46SMarcel Moolenaar return (error);
33538501a46SMarcel Moolenaar }
33638501a46SMarcel Moolenaar
33738501a46SMarcel Moolenaar static int
qcow1_write(int fd)33838501a46SMarcel Moolenaar qcow1_write(int fd)
33938501a46SMarcel Moolenaar {
34038501a46SMarcel Moolenaar
34138501a46SMarcel Moolenaar return (qcow_write(fd, QCOW_VERSION_1));
34238501a46SMarcel Moolenaar }
34338501a46SMarcel Moolenaar
34438501a46SMarcel Moolenaar static int
qcow2_write(int fd)34538501a46SMarcel Moolenaar qcow2_write(int fd)
34638501a46SMarcel Moolenaar {
34738501a46SMarcel Moolenaar
34838501a46SMarcel Moolenaar return (qcow_write(fd, QCOW_VERSION_2));
34938501a46SMarcel Moolenaar }
35038501a46SMarcel Moolenaar
35138501a46SMarcel Moolenaar static struct mkimg_format qcow1_format = {
35238501a46SMarcel Moolenaar .name = "qcow",
35338501a46SMarcel Moolenaar .description = "QEMU Copy-On-Write, version 1",
35438501a46SMarcel Moolenaar .resize = qcow1_resize,
35538501a46SMarcel Moolenaar .write = qcow1_write,
35638501a46SMarcel Moolenaar };
35738501a46SMarcel Moolenaar FORMAT_DEFINE(qcow1_format);
35838501a46SMarcel Moolenaar
35938501a46SMarcel Moolenaar static struct mkimg_format qcow2_format = {
36038501a46SMarcel Moolenaar .name = "qcow2",
36138501a46SMarcel Moolenaar .description = "QEMU Copy-On-Write, version 2",
36238501a46SMarcel Moolenaar .resize = qcow2_resize,
36338501a46SMarcel Moolenaar .write = qcow2_write,
36438501a46SMarcel Moolenaar };
36538501a46SMarcel Moolenaar FORMAT_DEFINE(qcow2_format);
366