xref: /kvmtool/disk/qcow.c (revision 865c675f3debd6670af34930ccaa7317a5fd0b4a)
186835cedSPrasad Joshi #include "kvm/qcow.h"
286835cedSPrasad Joshi 
386835cedSPrasad Joshi #include "kvm/disk-image.h"
486835cedSPrasad Joshi #include "kvm/read-write.h"
586835cedSPrasad Joshi #include "kvm/util.h"
686835cedSPrasad Joshi 
786835cedSPrasad Joshi #include <sys/types.h>
886835cedSPrasad Joshi #include <sys/stat.h>
986835cedSPrasad Joshi #include <stdbool.h>
1086835cedSPrasad Joshi #include <stdlib.h>
1186835cedSPrasad Joshi #include <string.h>
1286835cedSPrasad Joshi #include <unistd.h>
1386835cedSPrasad Joshi #include <fcntl.h>
1486835cedSPrasad Joshi 
1586835cedSPrasad Joshi #include <linux/byteorder.h>
1686835cedSPrasad Joshi #include <linux/types.h>
17*865c675fSPrasad Joshi #include <linux/kernel.h>
1886835cedSPrasad Joshi 
19742fce76SPrasad Joshi static inline u64 get_l1_index(struct qcow *q, u64 offset)
2086835cedSPrasad Joshi {
21ad627d62SPekka Enberg 	struct qcow_header *header = q->header;
2286835cedSPrasad Joshi 
2386835cedSPrasad Joshi 	return offset >> (header->l2_bits + header->cluster_bits);
2486835cedSPrasad Joshi }
2586835cedSPrasad Joshi 
26742fce76SPrasad Joshi static inline u64 get_l2_index(struct qcow *q, u64 offset)
2786835cedSPrasad Joshi {
28ad627d62SPekka Enberg 	struct qcow_header *header = q->header;
2986835cedSPrasad Joshi 
3086835cedSPrasad Joshi 	return (offset >> (header->cluster_bits)) & ((1 << header->l2_bits)-1);
3186835cedSPrasad Joshi }
3286835cedSPrasad Joshi 
33742fce76SPrasad Joshi static inline u64 get_cluster_offset(struct qcow *q, u64 offset)
3486835cedSPrasad Joshi {
35ad627d62SPekka Enberg 	struct qcow_header *header = q->header;
3686835cedSPrasad Joshi 
3786835cedSPrasad Joshi 	return offset & ((1 << header->cluster_bits)-1);
3886835cedSPrasad Joshi }
3986835cedSPrasad Joshi 
40a51948ceSPekka Enberg static ssize_t qcow1_read_cluster(struct qcow *q, u64 offset, void *dst, u32 dst_len)
4186835cedSPrasad Joshi {
42ad627d62SPekka Enberg 	struct qcow_header *header = q->header;
433dac48d4SPrasad Joshi 	struct qcow_table *table  = &q->table;
44179b71f0SPekka Enberg 	u64 *l2_table = NULL;
45742fce76SPrasad Joshi 	u64 l2_table_offset;
46742fce76SPrasad Joshi 	u64 l2_table_size;
473dac48d4SPrasad Joshi 	u64 cluster_size;
48742fce76SPrasad Joshi 	u64 clust_offset;
49742fce76SPrasad Joshi 	u64 clust_start;
50a51948ceSPekka Enberg 	size_t length;
51742fce76SPrasad Joshi 	u64 l1_idx;
52742fce76SPrasad Joshi 	u64 l2_idx;
5386835cedSPrasad Joshi 
54dae803fbSPekka Enberg 	cluster_size = 1 << header->cluster_bits;
5586835cedSPrasad Joshi 
56c5e0624bSPrasad Joshi 	l1_idx = get_l1_index(q, offset);
573dac48d4SPrasad Joshi 	if (l1_idx >= table->table_size)
5886835cedSPrasad Joshi 		goto out_error;
5986835cedSPrasad Joshi 
603dac48d4SPrasad Joshi 	clust_offset = get_cluster_offset(q, offset);
613dac48d4SPrasad Joshi 	if (clust_offset >= cluster_size)
623dac48d4SPrasad Joshi 		goto out_error;
633dac48d4SPrasad Joshi 
643dac48d4SPrasad Joshi 	length = cluster_size - clust_offset;
653dac48d4SPrasad Joshi 	if (length > dst_len)
663dac48d4SPrasad Joshi 		length = dst_len;
673dac48d4SPrasad Joshi 
68ad627d62SPekka Enberg 	l2_table_offset = table->l1_table[l1_idx] & ~header->oflag_mask;
6986835cedSPrasad Joshi 	if (!l2_table_offset)
703dac48d4SPrasad Joshi 		goto zero_cluster;
7186835cedSPrasad Joshi 
7286835cedSPrasad Joshi 	l2_table_size = 1 << header->l2_bits;
73742fce76SPrasad Joshi 	l2_table = calloc(l2_table_size, sizeof(u64));
7486835cedSPrasad Joshi 	if (!l2_table)
7586835cedSPrasad Joshi 		goto out_error;
7686835cedSPrasad Joshi 
773dac48d4SPrasad Joshi 	if (pread_in_full(q->fd, l2_table, l2_table_size * sizeof(u64),
783dac48d4SPrasad Joshi 				l2_table_offset) < 0)
79b6edb0ecSSasha Levin 		goto out_error;
8086835cedSPrasad Joshi 
81c5e0624bSPrasad Joshi 	l2_idx = get_l2_index(q, offset);
8286835cedSPrasad Joshi 	if (l2_idx >= l2_table_size)
83b6edb0ecSSasha Levin 		goto out_error;
8486835cedSPrasad Joshi 
85ad627d62SPekka Enberg 	clust_start = be64_to_cpu(l2_table[l2_idx]) & ~header->oflag_mask;
8686835cedSPrasad Joshi 	if (!clust_start)
873dac48d4SPrasad Joshi 		goto zero_cluster;
8886835cedSPrasad Joshi 
893dac48d4SPrasad Joshi 	if (pread_in_full(q->fd, dst, length, clust_start + clust_offset) < 0)
90b6edb0ecSSasha Levin 		goto out_error;
9186835cedSPrasad Joshi 
92179b71f0SPekka Enberg out:
93179b71f0SPekka Enberg 	free(l2_table);
943dac48d4SPrasad Joshi 	return length;
9586835cedSPrasad Joshi 
96179b71f0SPekka Enberg zero_cluster:
97179b71f0SPekka Enberg 	memset(dst, 0, length);
98179b71f0SPekka Enberg 	goto out;
99179b71f0SPekka Enberg 
10086835cedSPrasad Joshi out_error:
101179b71f0SPekka Enberg 	length = -1;
102179b71f0SPekka Enberg 	goto out;
1033dac48d4SPrasad Joshi }
104b6edb0ecSSasha Levin 
10543835ac9SSasha Levin static int qcow1_read_sector(struct disk_image *disk, u64 sector,
1063fdf659dSSasha Levin 		void *dst, u32 dst_len)
1073dac48d4SPrasad Joshi {
10843835ac9SSasha Levin 	struct qcow *q = disk->priv;
109ad627d62SPekka Enberg 	struct qcow_header *header = q->header;
1103dac48d4SPrasad Joshi 	char *buf = dst;
1113dac48d4SPrasad Joshi 	u64 offset;
112d8eea993SPekka Enberg 	u32 nr_read;
1133dac48d4SPrasad Joshi 	u32 nr;
1143dac48d4SPrasad Joshi 
115d8eea993SPekka Enberg 	nr_read = 0;
116d8eea993SPekka Enberg 	while (nr_read < dst_len) {
1173dac48d4SPrasad Joshi 		offset = sector << SECTOR_SHIFT;
1183dac48d4SPrasad Joshi 		if (offset >= header->size)
1193dac48d4SPrasad Joshi 			goto out_error;
1203dac48d4SPrasad Joshi 
121d8eea993SPekka Enberg 		nr = qcow1_read_cluster(q, offset, buf, dst_len - nr_read);
122a51948ceSPekka Enberg 		if (nr <= 0)
1233dac48d4SPrasad Joshi 			goto out_error;
1243dac48d4SPrasad Joshi 
125d8eea993SPekka Enberg 		nr_read		+= nr;
1263dac48d4SPrasad Joshi 		buf		+= nr;
1273dac48d4SPrasad Joshi 		sector		+= (nr >> SECTOR_SHIFT);
1283dac48d4SPrasad Joshi 	}
1293dac48d4SPrasad Joshi 	return 0;
1303dac48d4SPrasad Joshi out_error:
13186835cedSPrasad Joshi 	return -1;
13286835cedSPrasad Joshi }
13386835cedSPrasad Joshi 
134*865c675fSPrasad Joshi static inline u64 file_size(int fd)
135*865c675fSPrasad Joshi {
136*865c675fSPrasad Joshi 	struct stat st;
137*865c675fSPrasad Joshi 	if (fstat(fd, &st) < 0)
138*865c675fSPrasad Joshi 		return 0;
139*865c675fSPrasad Joshi 	return st.st_size;
140*865c675fSPrasad Joshi }
141*865c675fSPrasad Joshi 
142*865c675fSPrasad Joshi static inline int pwrite_sync(int fd, void *buf, size_t count, off_t offset)
143*865c675fSPrasad Joshi {
144*865c675fSPrasad Joshi 	if (pwrite_in_full(fd, buf, count, offset) < 0)
145*865c675fSPrasad Joshi 		return -1;
146*865c675fSPrasad Joshi 	if (sync_file_range(fd, offset, count,
147*865c675fSPrasad Joshi 				SYNC_FILE_RANGE_WAIT_BEFORE |
148*865c675fSPrasad Joshi 				SYNC_FILE_RANGE_WRITE) < 0)
149*865c675fSPrasad Joshi 		return -1;
150*865c675fSPrasad Joshi 	return 0;
151*865c675fSPrasad Joshi }
152*865c675fSPrasad Joshi 
153*865c675fSPrasad Joshi /* Writes a level 2 table at the end of the file. */
154*865c675fSPrasad Joshi static u64 qcow1_write_l2_table(struct qcow *q, u64 *table)
155*865c675fSPrasad Joshi {
156*865c675fSPrasad Joshi 	struct qcow_header *header = q->header;
157*865c675fSPrasad Joshi 	u64 sz;
158*865c675fSPrasad Joshi 	u64 clust_sz;
159*865c675fSPrasad Joshi 	u64 off;
160*865c675fSPrasad Joshi 	u64 f_sz;
161*865c675fSPrasad Joshi 
162*865c675fSPrasad Joshi 	f_sz     = file_size(q->fd);
163*865c675fSPrasad Joshi 	if (!f_sz)
164*865c675fSPrasad Joshi 		return 0;
165*865c675fSPrasad Joshi 
166*865c675fSPrasad Joshi 	sz       = 1 << header->l2_bits;
167*865c675fSPrasad Joshi 	clust_sz = 1 << header->cluster_bits;
168*865c675fSPrasad Joshi 	off      = ALIGN(f_sz, clust_sz);
169*865c675fSPrasad Joshi 
170*865c675fSPrasad Joshi 	if (pwrite_sync(q->fd, table, sz * sizeof(u64), off) < 0)
171*865c675fSPrasad Joshi 		return 0;
172*865c675fSPrasad Joshi 	return off;
173*865c675fSPrasad Joshi }
174*865c675fSPrasad Joshi 
175*865c675fSPrasad Joshi /*
176*865c675fSPrasad Joshi  * QCOW file might grow during a write operation. Not only data but metadata is
177*865c675fSPrasad Joshi  * also written at the end of the file. Therefore it is necessary to ensure
178*865c675fSPrasad Joshi  * every write is committed to disk. Hence we use uses pwrite_sync() to
179*865c675fSPrasad Joshi  * synchronize the in-core state of QCOW image to disk.
180*865c675fSPrasad Joshi  *
181*865c675fSPrasad Joshi  * We also try to restore the image to a consistent state if the metdata
182*865c675fSPrasad Joshi  * operation fails. The two metadat operations are: level 1 and level 2 table
183*865c675fSPrasad Joshi  * update. If either of them fails the image is truncated to a consistent state.
184*865c675fSPrasad Joshi  */
185*865c675fSPrasad Joshi static ssize_t qcow1_write_cluster(struct qcow *q, u64 offset, void *buf, u32 src_len)
186*865c675fSPrasad Joshi {
187*865c675fSPrasad Joshi 	struct qcow_header *header = q->header;
188*865c675fSPrasad Joshi 	struct qcow_table  *table  = &q->table;
189*865c675fSPrasad Joshi 
190*865c675fSPrasad Joshi 	u64 l2t_sz;
191*865c675fSPrasad Joshi 	u64 clust_sz;
192*865c675fSPrasad Joshi 	u64 l1t_idx;
193*865c675fSPrasad Joshi 	u64 l2t_idx;
194*865c675fSPrasad Joshi 	u64 clust_off;
195*865c675fSPrasad Joshi 	u64 len;
196*865c675fSPrasad Joshi 	u64 *l2t;
197*865c675fSPrasad Joshi 	u64 f_sz;
198*865c675fSPrasad Joshi 	u64 l2t_off;
199*865c675fSPrasad Joshi 	u64 t;
200*865c675fSPrasad Joshi 	u64 clust_start;
201*865c675fSPrasad Joshi 	bool update_meta = false;
202*865c675fSPrasad Joshi 
203*865c675fSPrasad Joshi 	l2t_sz   = 1 << header->l2_bits;
204*865c675fSPrasad Joshi 	clust_sz = 1 << header->cluster_bits;
205*865c675fSPrasad Joshi 
206*865c675fSPrasad Joshi 	l1t_idx = get_l1_index(q, offset);
207*865c675fSPrasad Joshi 	if (l1t_idx >= table->table_size)
208*865c675fSPrasad Joshi 		goto error;
209*865c675fSPrasad Joshi 
210*865c675fSPrasad Joshi 	l2t_idx = get_l2_index(q, offset);
211*865c675fSPrasad Joshi 	if (l2t_idx >= l2t_sz)
212*865c675fSPrasad Joshi 		goto error;
213*865c675fSPrasad Joshi 
214*865c675fSPrasad Joshi 	clust_off = get_cluster_offset(q, offset);
215*865c675fSPrasad Joshi 	if (clust_off >= clust_sz)
216*865c675fSPrasad Joshi 		goto error;
217*865c675fSPrasad Joshi 
218*865c675fSPrasad Joshi 	len = clust_sz - clust_off;
219*865c675fSPrasad Joshi 	if (len > src_len)
220*865c675fSPrasad Joshi 		len = src_len;
221*865c675fSPrasad Joshi 
222*865c675fSPrasad Joshi 	l2t = calloc(l2t_sz, sizeof(u64));
223*865c675fSPrasad Joshi 	if (!l2t)
224*865c675fSPrasad Joshi 		goto error;
225*865c675fSPrasad Joshi 
226*865c675fSPrasad Joshi 	l2t_off = table->l1_table[l1t_idx] & ~header->oflag_mask;
227*865c675fSPrasad Joshi 	if (l2t_off) {
228*865c675fSPrasad Joshi 		if (pread_in_full(q->fd, l2t, l2t_sz * sizeof(u64), l2t_off) < 0)
229*865c675fSPrasad Joshi 			goto free_l2;
230*865c675fSPrasad Joshi 	} else {
231*865c675fSPrasad Joshi 		/* capture the state of the consistent QCOW image */
232*865c675fSPrasad Joshi 		f_sz = file_size(q->fd);
233*865c675fSPrasad Joshi 		if (!f_sz)
234*865c675fSPrasad Joshi 			goto free_l2;
235*865c675fSPrasad Joshi 
236*865c675fSPrasad Joshi 		/* Write the l2 table of 0's at the end of the file */
237*865c675fSPrasad Joshi 		l2t_off = qcow1_write_l2_table(q, l2t);
238*865c675fSPrasad Joshi 		if (!l2t_off)
239*865c675fSPrasad Joshi 			goto free_l2;
240*865c675fSPrasad Joshi 
241*865c675fSPrasad Joshi 		/* Metadata update: update on disk level 1 table */
242*865c675fSPrasad Joshi 		t = cpu_to_be64(l2t_off);
243*865c675fSPrasad Joshi 		if (pwrite_sync(q->fd, &t, sizeof(t), header->l1_table_offset +
244*865c675fSPrasad Joshi 					l1t_idx * sizeof(u64)) < 0) {
245*865c675fSPrasad Joshi 			/* restore file to consistent state */
246*865c675fSPrasad Joshi 			if (ftruncate(q->fd, f_sz) < 0)
247*865c675fSPrasad Joshi 				goto free_l2;
248*865c675fSPrasad Joshi 			goto free_l2;
249*865c675fSPrasad Joshi 		}
250*865c675fSPrasad Joshi 
251*865c675fSPrasad Joshi 		/* update the in-core entry */
252*865c675fSPrasad Joshi 		table->l1_table[l1t_idx] = l2t_off;
253*865c675fSPrasad Joshi 	}
254*865c675fSPrasad Joshi 
255*865c675fSPrasad Joshi 	/* capture the state of the consistent QCOW image */
256*865c675fSPrasad Joshi 	f_sz = file_size(q->fd);
257*865c675fSPrasad Joshi 	if (!f_sz)
258*865c675fSPrasad Joshi 		goto free_l2;
259*865c675fSPrasad Joshi 
260*865c675fSPrasad Joshi 	clust_start = be64_to_cpu(l2t[l2t_idx]) & ~header->oflag_mask;
261*865c675fSPrasad Joshi 	free(l2t);
262*865c675fSPrasad Joshi 	if (!clust_start) {
263*865c675fSPrasad Joshi 		clust_start = ALIGN(f_sz, clust_sz);
264*865c675fSPrasad Joshi 		update_meta = true;
265*865c675fSPrasad Joshi 	}
266*865c675fSPrasad Joshi 
267*865c675fSPrasad Joshi 	/* write actual data */
268*865c675fSPrasad Joshi 	if (pwrite_in_full(q->fd, buf, len, clust_start + clust_off) < 0)
269*865c675fSPrasad Joshi 		goto error;
270*865c675fSPrasad Joshi 
271*865c675fSPrasad Joshi 	if (update_meta) {
272*865c675fSPrasad Joshi 		t = cpu_to_be64(clust_start);
273*865c675fSPrasad Joshi 		if (pwrite_sync(q->fd, &t, sizeof(t), l2t_off +
274*865c675fSPrasad Joshi 					l2t_idx * sizeof(u64)) < 0) {
275*865c675fSPrasad Joshi 			/* restore the file to consistent state */
276*865c675fSPrasad Joshi 			if (ftruncate(q->fd, f_sz) < 0)
277*865c675fSPrasad Joshi 				goto error;
278*865c675fSPrasad Joshi 			goto error;
279*865c675fSPrasad Joshi 		}
280*865c675fSPrasad Joshi 	}
281*865c675fSPrasad Joshi 	return len;
282*865c675fSPrasad Joshi free_l2:
283*865c675fSPrasad Joshi 	free(l2t);
284*865c675fSPrasad Joshi error:
285*865c675fSPrasad Joshi 	return -1;
286*865c675fSPrasad Joshi }
287*865c675fSPrasad Joshi 
28843835ac9SSasha Levin static int qcow1_write_sector(struct disk_image *disk, u64 sector, void *src, u32 src_len)
28986835cedSPrasad Joshi {
290*865c675fSPrasad Joshi 	struct qcow *q = disk->priv;
291*865c675fSPrasad Joshi 	struct qcow_header *header = q->header;
292*865c675fSPrasad Joshi 	char *buf = src;
293*865c675fSPrasad Joshi 	ssize_t nr_write;
294*865c675fSPrasad Joshi 	u64 offset;
295*865c675fSPrasad Joshi 	ssize_t nr;
296*865c675fSPrasad Joshi 
297*865c675fSPrasad Joshi 	nr_write = 0;
298*865c675fSPrasad Joshi 	offset = sector << SECTOR_SHIFT;
299*865c675fSPrasad Joshi 	while (nr_write < src_len) {
300*865c675fSPrasad Joshi 		if (offset >= header->size)
301*865c675fSPrasad Joshi 			goto error;
302*865c675fSPrasad Joshi 
303*865c675fSPrasad Joshi 		nr = qcow1_write_cluster(q, offset, buf, src_len - nr_write);
304*865c675fSPrasad Joshi 		if (nr < 0)
305*865c675fSPrasad Joshi 			goto error;
306*865c675fSPrasad Joshi 
307*865c675fSPrasad Joshi 		nr_write += nr;
308*865c675fSPrasad Joshi 		buf      += nr;
309*865c675fSPrasad Joshi 		offset   += nr;
310*865c675fSPrasad Joshi 	}
311*865c675fSPrasad Joshi 	return 0;
312*865c675fSPrasad Joshi error:
31386835cedSPrasad Joshi 	return -1;
31486835cedSPrasad Joshi }
31586835cedSPrasad Joshi 
31643835ac9SSasha Levin static void qcow1_disk_close(struct disk_image *disk)
31786835cedSPrasad Joshi {
31886835cedSPrasad Joshi 	struct qcow *q;
31986835cedSPrasad Joshi 
32043835ac9SSasha Levin 	if (!disk)
32186835cedSPrasad Joshi 		return;
32286835cedSPrasad Joshi 
32343835ac9SSasha Levin 	q = disk->priv;
32486835cedSPrasad Joshi 
3256c6f79b6SPrasad Joshi 	free(q->table.l1_table);
32686835cedSPrasad Joshi 	free(q->header);
32786835cedSPrasad Joshi 	free(q);
32886835cedSPrasad Joshi }
32986835cedSPrasad Joshi 
33086835cedSPrasad Joshi struct disk_image_operations qcow1_disk_ops = {
33186835cedSPrasad Joshi 	.read_sector		= qcow1_read_sector,
33286835cedSPrasad Joshi 	.write_sector		= qcow1_write_sector,
33386835cedSPrasad Joshi 	.close			= qcow1_disk_close
33486835cedSPrasad Joshi };
33586835cedSPrasad Joshi 
33686835cedSPrasad Joshi static int qcow_read_l1_table(struct qcow *q)
33786835cedSPrasad Joshi {
338ad627d62SPekka Enberg 	struct qcow_header *header = q->header;
33900adcc1bSPrasad Joshi 	struct qcow_table *table = &q->table;
34000adcc1bSPrasad Joshi 	u64 i;
34186835cedSPrasad Joshi 
342ad627d62SPekka Enberg 	table->table_size	= header->l1_size;
34386835cedSPrasad Joshi 
34400adcc1bSPrasad Joshi 	table->l1_table	= calloc(table->table_size, sizeof(u64));
34500adcc1bSPrasad Joshi 	if (!table->l1_table)
34686835cedSPrasad Joshi 		return -1;
34786835cedSPrasad Joshi 
34800adcc1bSPrasad Joshi 	if (pread_in_full(q->fd, table->l1_table, sizeof(u64) *
34900adcc1bSPrasad Joshi 				table->table_size, header->l1_table_offset) < 0)
35086835cedSPrasad Joshi 		return -1;
35186835cedSPrasad Joshi 
35200adcc1bSPrasad Joshi 	for (i = 0; i < table->table_size; i++)
35300adcc1bSPrasad Joshi 		be64_to_cpus(&table->l1_table[i]);
35400adcc1bSPrasad Joshi 
35586835cedSPrasad Joshi 	return 0;
35686835cedSPrasad Joshi }
35786835cedSPrasad Joshi 
358ad627d62SPekka Enberg static void *qcow2_read_header(int fd)
35986835cedSPrasad Joshi {
360ad627d62SPekka Enberg 	struct qcow2_header_disk f_header;
361ad627d62SPekka Enberg 	struct qcow_header *header;
36286835cedSPrasad Joshi 
363ad627d62SPekka Enberg 	header = malloc(sizeof(struct qcow_header));
36486835cedSPrasad Joshi 	if (!header)
36586835cedSPrasad Joshi 		return NULL;
36686835cedSPrasad Joshi 
3670657f33dSPrasad Joshi 	if (pread_in_full(fd, &f_header, sizeof(struct qcow2_header_disk), 0) < 0) {
3680657f33dSPrasad Joshi 		free(header);
36986835cedSPrasad Joshi 		return NULL;
3700657f33dSPrasad Joshi 	}
37186835cedSPrasad Joshi 
372ad627d62SPekka Enberg 	be32_to_cpus(&f_header.magic);
373ad627d62SPekka Enberg 	be32_to_cpus(&f_header.version);
374ad627d62SPekka Enberg 	be64_to_cpus(&f_header.backing_file_offset);
375ad627d62SPekka Enberg 	be32_to_cpus(&f_header.backing_file_size);
376ad627d62SPekka Enberg 	be32_to_cpus(&f_header.cluster_bits);
377ad627d62SPekka Enberg 	be64_to_cpus(&f_header.size);
378ad627d62SPekka Enberg 	be32_to_cpus(&f_header.crypt_method);
379ad627d62SPekka Enberg 	be32_to_cpus(&f_header.l1_size);
380ad627d62SPekka Enberg 	be64_to_cpus(&f_header.l1_table_offset);
381ad627d62SPekka Enberg 	be64_to_cpus(&f_header.refcount_table_offset);
382ad627d62SPekka Enberg 	be32_to_cpus(&f_header.refcount_table_clusters);
383ad627d62SPekka Enberg 	be32_to_cpus(&f_header.nb_snapshots);
384ad627d62SPekka Enberg 	be64_to_cpus(&f_header.snapshots_offset);
385ad627d62SPekka Enberg 
386ad627d62SPekka Enberg 	*header		= (struct qcow_header) {
387ad627d62SPekka Enberg 		.size			= f_header.size,
388ad627d62SPekka Enberg 		.l1_table_offset	= f_header.l1_table_offset,
389ad627d62SPekka Enberg 		.l1_size		= f_header.l1_size,
390ad627d62SPekka Enberg 		.cluster_bits		= f_header.cluster_bits,
391ad627d62SPekka Enberg 		.l2_bits		= f_header.cluster_bits - 3,
392ad627d62SPekka Enberg 		.oflag_mask		= QCOW2_OFLAG_MASK,
393ad627d62SPekka Enberg 	};
394ad627d62SPekka Enberg 
395ad627d62SPekka Enberg 	return header;
396ad627d62SPekka Enberg }
397ad627d62SPekka Enberg 
398ad627d62SPekka Enberg static struct disk_image *qcow2_probe(int fd)
399ad627d62SPekka Enberg {
400ad627d62SPekka Enberg 	struct qcow *q;
401ad627d62SPekka Enberg 	struct qcow_header *h;
402ad627d62SPekka Enberg 	struct disk_image *disk_image;
403ad627d62SPekka Enberg 
404ad627d62SPekka Enberg 	q = calloc(1, sizeof(struct qcow));
405ad627d62SPekka Enberg 	if (!q)
406ad627d62SPekka Enberg 		goto error;
407ad627d62SPekka Enberg 
408ad627d62SPekka Enberg 	q->fd = fd;
409ad627d62SPekka Enberg 
410ad627d62SPekka Enberg 	h = q->header = qcow2_read_header(fd);
411ad627d62SPekka Enberg 	if (!h)
412ad627d62SPekka Enberg 		goto error;
413ad627d62SPekka Enberg 
414ad627d62SPekka Enberg 	if (qcow_read_l1_table(q) < 0)
415ad627d62SPekka Enberg 		goto error;
416ad627d62SPekka Enberg 
417ad627d62SPekka Enberg 	disk_image = disk_image__new(fd, h->size, &qcow1_disk_ops);
418ad627d62SPekka Enberg 	if (!disk_image)
419ad627d62SPekka Enberg 		goto error;
420ad627d62SPekka Enberg 	disk_image->priv = q;
421ad627d62SPekka Enberg 
422ad627d62SPekka Enberg 	return disk_image;
423ad627d62SPekka Enberg error:
424ad627d62SPekka Enberg 	if (!q)
425ad627d62SPekka Enberg 		return NULL;
426ad627d62SPekka Enberg 
427ad627d62SPekka Enberg 	free(q->table.l1_table);
428ad627d62SPekka Enberg 	free(q->header);
429ad627d62SPekka Enberg 	free(q);
430ad627d62SPekka Enberg 
431ad627d62SPekka Enberg 	return NULL;
432ad627d62SPekka Enberg }
433ad627d62SPekka Enberg 
434ad627d62SPekka Enberg static bool qcow2_check_image(int fd)
435ad627d62SPekka Enberg {
436ad627d62SPekka Enberg 	struct qcow2_header_disk f_header;
437ad627d62SPekka Enberg 
438ad627d62SPekka Enberg 	if (pread_in_full(fd, &f_header, sizeof(struct qcow2_header_disk), 0) < 0)
439ad627d62SPekka Enberg 		return false;
440ad627d62SPekka Enberg 
441ad627d62SPekka Enberg 	be32_to_cpus(&f_header.magic);
442ad627d62SPekka Enberg 	be32_to_cpus(&f_header.version);
443ad627d62SPekka Enberg 
444ad627d62SPekka Enberg 	if (f_header.magic != QCOW_MAGIC)
445ad627d62SPekka Enberg 		return false;
446ad627d62SPekka Enberg 
447ad627d62SPekka Enberg 	if (f_header.version != QCOW2_VERSION)
448ad627d62SPekka Enberg 		return false;
449ad627d62SPekka Enberg 
450ad627d62SPekka Enberg 	return true;
451ad627d62SPekka Enberg }
452ad627d62SPekka Enberg 
453ad627d62SPekka Enberg static void *qcow1_read_header(int fd)
454ad627d62SPekka Enberg {
455ad627d62SPekka Enberg 	struct qcow1_header_disk f_header;
456ad627d62SPekka Enberg 	struct qcow_header *header;
457ad627d62SPekka Enberg 
458ad627d62SPekka Enberg 	header = malloc(sizeof(struct qcow_header));
459ad627d62SPekka Enberg 	if (!header)
460ad627d62SPekka Enberg 		return NULL;
461ad627d62SPekka Enberg 
462d39cefd2SSasha Levin 	if (pread_in_full(fd, &f_header, sizeof(struct qcow1_header_disk), 0) < 0) {
463d39cefd2SSasha Levin 		free(header);
464ad627d62SPekka Enberg 		return NULL;
465d39cefd2SSasha Levin 	}
466ad627d62SPekka Enberg 
467ad627d62SPekka Enberg 	be32_to_cpus(&f_header.magic);
468ad627d62SPekka Enberg 	be32_to_cpus(&f_header.version);
469ad627d62SPekka Enberg 	be64_to_cpus(&f_header.backing_file_offset);
470ad627d62SPekka Enberg 	be32_to_cpus(&f_header.backing_file_size);
471ad627d62SPekka Enberg 	be32_to_cpus(&f_header.mtime);
472ad627d62SPekka Enberg 	be64_to_cpus(&f_header.size);
473ad627d62SPekka Enberg 	be32_to_cpus(&f_header.crypt_method);
474ad627d62SPekka Enberg 	be64_to_cpus(&f_header.l1_table_offset);
475ad627d62SPekka Enberg 
476ad627d62SPekka Enberg 	*header		= (struct qcow_header) {
477ad627d62SPekka Enberg 		.size			= f_header.size,
478ad627d62SPekka Enberg 		.l1_table_offset	= f_header.l1_table_offset,
479ad627d62SPekka Enberg 		.l1_size		= f_header.size / ((1 << f_header.l2_bits) * (1 << f_header.cluster_bits)),
480ad627d62SPekka Enberg 		.cluster_bits		= f_header.cluster_bits,
481ad627d62SPekka Enberg 		.l2_bits		= f_header.l2_bits,
482ad627d62SPekka Enberg 		.oflag_mask		= QCOW1_OFLAG_MASK,
483ad627d62SPekka Enberg 	};
48486835cedSPrasad Joshi 
48586835cedSPrasad Joshi 	return header;
48686835cedSPrasad Joshi }
48786835cedSPrasad Joshi 
48886835cedSPrasad Joshi static struct disk_image *qcow1_probe(int fd)
48986835cedSPrasad Joshi {
49086835cedSPrasad Joshi 	struct qcow *q;
491ad627d62SPekka Enberg 	struct qcow_header *h;
49286835cedSPrasad Joshi 	struct disk_image *disk_image;
49386835cedSPrasad Joshi 
49486835cedSPrasad Joshi 	q = calloc(1, sizeof(struct qcow));
49586835cedSPrasad Joshi 	if (!q)
49686835cedSPrasad Joshi 		goto error;
49786835cedSPrasad Joshi 
49886835cedSPrasad Joshi 	q->fd = fd;
49986835cedSPrasad Joshi 
50086835cedSPrasad Joshi 	h = q->header = qcow1_read_header(fd);
50186835cedSPrasad Joshi 	if (!h)
50286835cedSPrasad Joshi 		goto error;
50386835cedSPrasad Joshi 
50486835cedSPrasad Joshi 	if (qcow_read_l1_table(q) < 0)
50586835cedSPrasad Joshi 		goto error;
50686835cedSPrasad Joshi 
50786835cedSPrasad Joshi 	disk_image = disk_image__new(fd, h->size, &qcow1_disk_ops);
50886835cedSPrasad Joshi 	if (!disk_image)
50986835cedSPrasad Joshi 		goto error;
51086835cedSPrasad Joshi 	disk_image->priv = q;
51186835cedSPrasad Joshi 
51286835cedSPrasad Joshi 	return disk_image;
51386835cedSPrasad Joshi error:
51486835cedSPrasad Joshi 	if (!q)
51586835cedSPrasad Joshi 		return NULL;
51686835cedSPrasad Joshi 
5176c6f79b6SPrasad Joshi 	free(q->table.l1_table);
51886835cedSPrasad Joshi 	free(q->header);
51986835cedSPrasad Joshi 	free(q);
52086835cedSPrasad Joshi 
52186835cedSPrasad Joshi 	return NULL;
52286835cedSPrasad Joshi }
52386835cedSPrasad Joshi 
524ad627d62SPekka Enberg static bool qcow1_check_image(int fd)
52586835cedSPrasad Joshi {
526ad627d62SPekka Enberg 	struct qcow1_header_disk f_header;
52786835cedSPrasad Joshi 
528ad627d62SPekka Enberg 	if (pread_in_full(fd, &f_header, sizeof(struct qcow1_header_disk), 0) < 0)
529ad627d62SPekka Enberg 		return false;
53086835cedSPrasad Joshi 
531ad627d62SPekka Enberg 	be32_to_cpus(&f_header.magic);
532ad627d62SPekka Enberg 	be32_to_cpus(&f_header.version);
53386835cedSPrasad Joshi 
534ad627d62SPekka Enberg 	if (f_header.magic != QCOW_MAGIC)
535ad627d62SPekka Enberg 		return false;
53686835cedSPrasad Joshi 
537ad627d62SPekka Enberg 	if (f_header.version != QCOW1_VERSION)
538ad627d62SPekka Enberg 		return false;
53986835cedSPrasad Joshi 
540ad627d62SPekka Enberg 	return true;
54186835cedSPrasad Joshi }
54286835cedSPrasad Joshi 
54386835cedSPrasad Joshi struct disk_image *qcow_probe(int fd)
54486835cedSPrasad Joshi {
545ad627d62SPekka Enberg 	if (qcow1_check_image(fd))
54686835cedSPrasad Joshi 		return qcow1_probe(fd);
547ad627d62SPekka Enberg 
548ad627d62SPekka Enberg 	if (qcow2_check_image(fd))
549ad627d62SPekka Enberg 		return qcow2_probe(fd);
550ad627d62SPekka Enberg 
551ad627d62SPekka Enberg 	return NULL;
55286835cedSPrasad Joshi }
553