7 #include "tools-util.h"
9 #define QCOW_MAGIC (('Q' << 24) | ('F' << 16) | ('I' << 8) | 0xfb)
10 #define QCOW_VERSION 2
11 #define QCOW_OFLAG_COPIED (1LL << 63)
17 u64 backing_file_offset;
18 u32 backing_file_size;
27 u64 refcount_table_offset;
28 u32 refcount_table_blocks;
44 static void flush_l2(struct qcow2_image *img)
46 if (img->l1_index != -1) {
47 img->l1_table[img->l1_index] =
48 cpu_to_be64(img->offset|QCOW_OFLAG_COPIED);
49 xpwrite(img->fd, img->l2_table, img->block_size, img->offset,
51 img->offset += img->block_size;
53 memset(img->l2_table, 0, img->block_size);
58 static void add_l2(struct qcow2_image *img, u64 src_blk, u64 dst_offset)
60 unsigned l2_size = img->block_size / sizeof(u64);
61 u64 l1_index = src_blk / l2_size;
62 u64 l2_index = src_blk & (l2_size - 1);
64 if (img->l1_index != l1_index) {
66 img->l1_index = l1_index;
69 img->l2_table[l2_index] = cpu_to_be64(dst_offset|QCOW_OFLAG_COPIED);
72 void qcow2_write_image(int infd, int outfd, ranges *data,
75 u64 image_size = get_size(NULL, infd);
76 unsigned l2_size = block_size / sizeof(u64);
77 unsigned l1_size = DIV_ROUND_UP(image_size, (u64) block_size * l2_size);
78 struct qcow2_hdr hdr = { 0 };
79 struct qcow2_image img = {
81 .block_size = block_size,
82 .l2_table = xcalloc(l2_size, sizeof(u64)),
83 .l1_table = xcalloc(l1_size, sizeof(u64)),
85 .offset = round_up(sizeof(hdr), block_size),
88 char *buf = xmalloc(block_size);
89 u64 src_offset, dst_offset;
91 assert(is_power_of_2(block_size));
93 ranges_roundup(data, block_size);
94 ranges_sort_merge(data);
97 darray_foreach(r, *data)
98 for (src_offset = r->start;
100 src_offset += block_size) {
101 dst_offset = img.offset;
102 img.offset += img.block_size;
104 xpread(infd, buf, block_size, src_offset);
105 xpwrite(outfd, buf, block_size, dst_offset,
108 add_l2(&img, src_offset / block_size, dst_offset);
113 /* Write L1 table: */
114 dst_offset = img.offset;
115 img.offset += round_up(l1_size * sizeof(u64), block_size);
116 xpwrite(img.fd, img.l1_table, l1_size * sizeof(u64), dst_offset,
120 hdr.magic = cpu_to_be32(QCOW_MAGIC);
121 hdr.version = cpu_to_be32(QCOW_VERSION);
122 hdr.block_bits = cpu_to_be32(ilog2(block_size));
123 hdr.size = cpu_to_be64(image_size);
124 hdr.l1_size = cpu_to_be32(l1_size);
125 hdr.l1_table_offset = cpu_to_be64(dst_offset);
127 memset(buf, 0, block_size);
128 memcpy(buf, &hdr, sizeof(hdr));
129 xpwrite(img.fd, buf, block_size, 0,