xref: /kvmtool/disk/qcow.c (revision b1c840953d28e217fa5aaaf0f345bfd982b85e37)
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>
16865c675fSPrasad Joshi #include <linux/kernel.h>
170df6b4d9SPekka Enberg #include <linux/types.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 
40*b1c84095SPekka Enberg static ssize_t qcow_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;
44742fce76SPrasad Joshi 	u64 l2_table_offset;
45742fce76SPrasad Joshi 	u64 l2_table_size;
463dac48d4SPrasad Joshi 	u64 cluster_size;
47742fce76SPrasad Joshi 	u64 clust_offset;
48742fce76SPrasad Joshi 	u64 clust_start;
49a51948ceSPekka Enberg 	size_t length;
500df6b4d9SPekka Enberg 	u64 *l2_table;
51742fce76SPrasad Joshi 	u64 l1_idx;
52742fce76SPrasad Joshi 	u64 l2_idx;
5386835cedSPrasad Joshi 
540df6b4d9SPekka Enberg 	l2_table = NULL;
550df6b4d9SPekka Enberg 
56dae803fbSPekka Enberg 	cluster_size = 1 << header->cluster_bits;
5786835cedSPrasad Joshi 
58c5e0624bSPrasad Joshi 	l1_idx = get_l1_index(q, offset);
593dac48d4SPrasad Joshi 	if (l1_idx >= table->table_size)
6086835cedSPrasad Joshi 		goto out_error;
6186835cedSPrasad Joshi 
623dac48d4SPrasad Joshi 	clust_offset = get_cluster_offset(q, offset);
633dac48d4SPrasad Joshi 	if (clust_offset >= cluster_size)
643dac48d4SPrasad Joshi 		goto out_error;
653dac48d4SPrasad Joshi 
663dac48d4SPrasad Joshi 	length = cluster_size - clust_offset;
673dac48d4SPrasad Joshi 	if (length > dst_len)
683dac48d4SPrasad Joshi 		length = dst_len;
693dac48d4SPrasad Joshi 
70ad627d62SPekka Enberg 	l2_table_offset = table->l1_table[l1_idx] & ~header->oflag_mask;
7186835cedSPrasad Joshi 	if (!l2_table_offset)
723dac48d4SPrasad Joshi 		goto zero_cluster;
7386835cedSPrasad Joshi 
7486835cedSPrasad Joshi 	l2_table_size = 1 << header->l2_bits;
75742fce76SPrasad Joshi 	l2_table = calloc(l2_table_size, sizeof(u64));
7686835cedSPrasad Joshi 	if (!l2_table)
7786835cedSPrasad Joshi 		goto out_error;
7886835cedSPrasad Joshi 
790df6b4d9SPekka Enberg 	if (pread_in_full(q->fd, l2_table, l2_table_size * sizeof(u64), l2_table_offset) < 0)
80b6edb0ecSSasha Levin 		goto out_error;
8186835cedSPrasad Joshi 
82c5e0624bSPrasad Joshi 	l2_idx = get_l2_index(q, offset);
8386835cedSPrasad Joshi 	if (l2_idx >= l2_table_size)
84b6edb0ecSSasha Levin 		goto out_error;
8586835cedSPrasad Joshi 
86ad627d62SPekka Enberg 	clust_start = be64_to_cpu(l2_table[l2_idx]) & ~header->oflag_mask;
8786835cedSPrasad Joshi 	if (!clust_start)
883dac48d4SPrasad Joshi 		goto zero_cluster;
8986835cedSPrasad Joshi 
903dac48d4SPrasad Joshi 	if (pread_in_full(q->fd, dst, length, clust_start + clust_offset) < 0)
91b6edb0ecSSasha Levin 		goto out_error;
9286835cedSPrasad Joshi 
93179b71f0SPekka Enberg out:
94179b71f0SPekka Enberg 	free(l2_table);
953dac48d4SPrasad Joshi 	return length;
9686835cedSPrasad Joshi 
97179b71f0SPekka Enberg zero_cluster:
98179b71f0SPekka Enberg 	memset(dst, 0, length);
99179b71f0SPekka Enberg 	goto out;
100179b71f0SPekka Enberg 
10186835cedSPrasad Joshi out_error:
102179b71f0SPekka Enberg 	length = -1;
103179b71f0SPekka Enberg 	goto out;
1043dac48d4SPrasad Joshi }
105b6edb0ecSSasha Levin 
106*b1c84095SPekka Enberg static ssize_t qcow_read_sector(struct disk_image *disk, u64 sector, void *dst, u32 dst_len)
1073dac48d4SPrasad Joshi {
10843835ac9SSasha Levin 	struct qcow *q = disk->priv;
109ad627d62SPekka Enberg 	struct qcow_header *header = q->header;
110d8eea993SPekka Enberg 	u32 nr_read;
1110df6b4d9SPekka Enberg 	u64 offset;
1120df6b4d9SPekka Enberg 	char *buf;
1133dac48d4SPrasad Joshi 	u32 nr;
1143dac48d4SPrasad Joshi 
1150df6b4d9SPekka Enberg 	buf		= dst;
116d8eea993SPekka Enberg 	nr_read		= 0;
1170df6b4d9SPekka Enberg 
118d8eea993SPekka Enberg 	while (nr_read < dst_len) {
1193dac48d4SPrasad Joshi 		offset		= sector << SECTOR_SHIFT;
1203dac48d4SPrasad Joshi 		if (offset >= header->size)
1210df6b4d9SPekka Enberg 			return -1;
1223dac48d4SPrasad Joshi 
123*b1c84095SPekka Enberg 		nr = qcow_read_cluster(q, offset, buf, dst_len - nr_read);
124a51948ceSPekka Enberg 		if (nr <= 0)
1250df6b4d9SPekka Enberg 			return -1;
1263dac48d4SPrasad Joshi 
127d8eea993SPekka Enberg 		nr_read		+= nr;
1283dac48d4SPrasad Joshi 		buf		+= nr;
1293dac48d4SPrasad Joshi 		sector		+= (nr >> SECTOR_SHIFT);
1303dac48d4SPrasad Joshi 	}
1310df6b4d9SPekka Enberg 
13272133dd2SAsias He 	return dst_len;
13386835cedSPrasad Joshi }
13486835cedSPrasad Joshi 
135865c675fSPrasad Joshi static inline u64 file_size(int fd)
136865c675fSPrasad Joshi {
137865c675fSPrasad Joshi 	struct stat st;
1380df6b4d9SPekka Enberg 
139865c675fSPrasad Joshi 	if (fstat(fd, &st) < 0)
140865c675fSPrasad Joshi 		return 0;
1410df6b4d9SPekka Enberg 
142865c675fSPrasad Joshi 	return st.st_size;
143865c675fSPrasad Joshi }
144865c675fSPrasad Joshi 
1450df6b4d9SPekka Enberg #define SYNC_FLAGS		(SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE)
1460df6b4d9SPekka Enberg 
1470df6b4d9SPekka Enberg static inline int qcow_pwrite_sync(int fd, void *buf, size_t count, off_t offset)
148865c675fSPrasad Joshi {
149865c675fSPrasad Joshi 	if (pwrite_in_full(fd, buf, count, offset) < 0)
150865c675fSPrasad Joshi 		return -1;
1510df6b4d9SPekka Enberg 
1520df6b4d9SPekka Enberg 	return sync_file_range(fd, offset, count, SYNC_FLAGS);
153865c675fSPrasad Joshi }
154865c675fSPrasad Joshi 
155865c675fSPrasad Joshi /* Writes a level 2 table at the end of the file. */
156*b1c84095SPekka Enberg static u64 qcow_write_l2_table(struct qcow *q, u64 *table)
157865c675fSPrasad Joshi {
158865c675fSPrasad Joshi 	struct qcow_header *header = q->header;
159865c675fSPrasad Joshi 	u64 clust_sz;
160865c675fSPrasad Joshi 	u64 f_sz;
1610df6b4d9SPekka Enberg 	u64 off;
1620df6b4d9SPekka Enberg 	u64 sz;
163865c675fSPrasad Joshi 
164865c675fSPrasad Joshi 	f_sz		= file_size(q->fd);
165865c675fSPrasad Joshi 	if (!f_sz)
166865c675fSPrasad Joshi 		return 0;
167865c675fSPrasad Joshi 
168865c675fSPrasad Joshi 	sz		= 1 << header->l2_bits;
169865c675fSPrasad Joshi 	clust_sz	= 1 << header->cluster_bits;
170865c675fSPrasad Joshi 	off		= ALIGN(f_sz, clust_sz);
171865c675fSPrasad Joshi 
1720df6b4d9SPekka Enberg 	if (qcow_pwrite_sync(q->fd, table, sz * sizeof(u64), off) < 0)
173865c675fSPrasad Joshi 		return 0;
1740df6b4d9SPekka Enberg 
175865c675fSPrasad Joshi 	return off;
176865c675fSPrasad Joshi }
177865c675fSPrasad Joshi 
178865c675fSPrasad Joshi /*
179865c675fSPrasad Joshi  * QCOW file might grow during a write operation. Not only data but metadata is
180865c675fSPrasad Joshi  * also written at the end of the file. Therefore it is necessary to ensure
1810df6b4d9SPekka Enberg  * every write is committed to disk. Hence we use uses qcow_pwrite_sync() to
182865c675fSPrasad Joshi  * synchronize the in-core state of QCOW image to disk.
183865c675fSPrasad Joshi  *
184865c675fSPrasad Joshi  * We also try to restore the image to a consistent state if the metdata
185865c675fSPrasad Joshi  * operation fails. The two metadat operations are: level 1 and level 2 table
186865c675fSPrasad Joshi  * update. If either of them fails the image is truncated to a consistent state.
187865c675fSPrasad Joshi  */
188*b1c84095SPekka Enberg static ssize_t qcow_write_cluster(struct qcow *q, u64 offset, void *buf, u32 src_len)
189865c675fSPrasad Joshi {
190865c675fSPrasad Joshi 	struct qcow_header *header = q->header;
191865c675fSPrasad Joshi 	struct qcow_table  *table  = &q->table;
1920df6b4d9SPekka Enberg 	bool update_meta;
1930df6b4d9SPekka Enberg 	u64 clust_start;
1940df6b4d9SPekka Enberg 	u64 clust_off;
195865c675fSPrasad Joshi 	u64 clust_sz;
196865c675fSPrasad Joshi 	u64 l1t_idx;
197865c675fSPrasad Joshi 	u64 l2t_idx;
1980df6b4d9SPekka Enberg 	u64 l2t_off;
1990df6b4d9SPekka Enberg 	u64 l2t_sz;
200865c675fSPrasad Joshi 	u64 *l2t;
201865c675fSPrasad Joshi 	u64 f_sz;
2020df6b4d9SPekka Enberg 	u64 len;
203865c675fSPrasad Joshi 	u64 t;
204865c675fSPrasad Joshi 
205865c675fSPrasad Joshi 	l2t_sz		= 1 << header->l2_bits;
206865c675fSPrasad Joshi 	clust_sz	= 1 << header->cluster_bits;
207865c675fSPrasad Joshi 
208865c675fSPrasad Joshi 	l1t_idx		= get_l1_index(q, offset);
209865c675fSPrasad Joshi 	if (l1t_idx >= table->table_size)
210865c675fSPrasad Joshi 		goto error;
211865c675fSPrasad Joshi 
212865c675fSPrasad Joshi 	l2t_idx		= get_l2_index(q, offset);
213865c675fSPrasad Joshi 	if (l2t_idx >= l2t_sz)
214865c675fSPrasad Joshi 		goto error;
215865c675fSPrasad Joshi 
216865c675fSPrasad Joshi 	clust_off	= get_cluster_offset(q, offset);
217865c675fSPrasad Joshi 	if (clust_off >= clust_sz)
218865c675fSPrasad Joshi 		goto error;
219865c675fSPrasad Joshi 
220865c675fSPrasad Joshi 	len		= clust_sz - clust_off;
221865c675fSPrasad Joshi 	if (len > src_len)
222865c675fSPrasad Joshi 		len = src_len;
223865c675fSPrasad Joshi 
224865c675fSPrasad Joshi 	l2t = calloc(l2t_sz, sizeof(u64));
225865c675fSPrasad Joshi 	if (!l2t)
226865c675fSPrasad Joshi 		goto error;
227865c675fSPrasad Joshi 
228865c675fSPrasad Joshi 	l2t_off		= table->l1_table[l1t_idx] & ~header->oflag_mask;
229865c675fSPrasad Joshi 	if (l2t_off) {
230865c675fSPrasad Joshi 		if (pread_in_full(q->fd, l2t, l2t_sz * sizeof(u64), l2t_off) < 0)
231865c675fSPrasad Joshi 			goto free_l2;
232865c675fSPrasad Joshi 	} else {
2330df6b4d9SPekka Enberg 		/* Capture the state of the consistent QCOW image */
234865c675fSPrasad Joshi 		f_sz		= file_size(q->fd);
235865c675fSPrasad Joshi 		if (!f_sz)
236865c675fSPrasad Joshi 			goto free_l2;
237865c675fSPrasad Joshi 
238865c675fSPrasad Joshi 		/* Write the l2 table of 0's at the end of the file */
239*b1c84095SPekka Enberg 		l2t_off		= qcow_write_l2_table(q, l2t);
240865c675fSPrasad Joshi 		if (!l2t_off)
241865c675fSPrasad Joshi 			goto free_l2;
242865c675fSPrasad Joshi 
243865c675fSPrasad Joshi 		/* Metadata update: update on disk level 1 table */
244865c675fSPrasad Joshi 		t		= cpu_to_be64(l2t_off);
2450df6b4d9SPekka Enberg 
2460df6b4d9SPekka Enberg 		if (qcow_pwrite_sync(q->fd, &t, sizeof(t), header->l1_table_offset + l1t_idx * sizeof(u64)) < 0) {
247865c675fSPrasad Joshi 			/* restore file to consistent state */
248865c675fSPrasad Joshi 			if (ftruncate(q->fd, f_sz) < 0)
249865c675fSPrasad Joshi 				goto free_l2;
2500df6b4d9SPekka Enberg 
251865c675fSPrasad Joshi 			goto free_l2;
252865c675fSPrasad Joshi 		}
253865c675fSPrasad Joshi 
2540df6b4d9SPekka Enberg 		/* Update the in-core entry */
255865c675fSPrasad Joshi 		table->l1_table[l1t_idx] = l2t_off;
256865c675fSPrasad Joshi 	}
257865c675fSPrasad Joshi 
2580df6b4d9SPekka Enberg 	/* Capture the state of the consistent QCOW image */
259865c675fSPrasad Joshi 	f_sz		= file_size(q->fd);
260865c675fSPrasad Joshi 	if (!f_sz)
261865c675fSPrasad Joshi 		goto free_l2;
262865c675fSPrasad Joshi 
263865c675fSPrasad Joshi 	clust_start	= be64_to_cpu(l2t[l2t_idx]) & ~header->oflag_mask;
264865c675fSPrasad Joshi 	if (!clust_start) {
265865c675fSPrasad Joshi 		clust_start	= ALIGN(f_sz, clust_sz);
266865c675fSPrasad Joshi 		update_meta	= true;
2670df6b4d9SPekka Enberg 	} else
2680df6b4d9SPekka Enberg 		update_meta	= false;
269865c675fSPrasad Joshi 
2700df6b4d9SPekka Enberg 	free(l2t);
2710df6b4d9SPekka Enberg 
2720df6b4d9SPekka Enberg 	/* Write actual data */
273865c675fSPrasad Joshi 	if (pwrite_in_full(q->fd, buf, len, clust_start + clust_off) < 0)
274865c675fSPrasad Joshi 		goto error;
275865c675fSPrasad Joshi 
276865c675fSPrasad Joshi 	if (update_meta) {
277865c675fSPrasad Joshi 		t = cpu_to_be64(clust_start);
2780df6b4d9SPekka Enberg 		if (qcow_pwrite_sync(q->fd, &t, sizeof(t), l2t_off + l2t_idx * sizeof(u64)) < 0) {
2790df6b4d9SPekka Enberg 			/* Restore the file to consistent state */
280865c675fSPrasad Joshi 			if (ftruncate(q->fd, f_sz) < 0)
281865c675fSPrasad Joshi 				goto error;
2820df6b4d9SPekka Enberg 
283865c675fSPrasad Joshi 			goto error;
284865c675fSPrasad Joshi 		}
285865c675fSPrasad Joshi 	}
2860df6b4d9SPekka Enberg 
287865c675fSPrasad Joshi 	return len;
288865c675fSPrasad Joshi free_l2:
289865c675fSPrasad Joshi 	free(l2t);
290865c675fSPrasad Joshi error:
291865c675fSPrasad Joshi 	return -1;
292865c675fSPrasad Joshi }
293865c675fSPrasad Joshi 
294*b1c84095SPekka Enberg static ssize_t qcow_write_sector(struct disk_image *disk, u64 sector, void *src, u32 src_len)
29586835cedSPrasad Joshi {
296865c675fSPrasad Joshi 	struct qcow *q = disk->priv;
297865c675fSPrasad Joshi 	struct qcow_header *header = q->header;
298c4acb611SIngo Molnar 	u32 nr_written;
2990df6b4d9SPekka Enberg 	char *buf;
300865c675fSPrasad Joshi 	u64 offset;
301865c675fSPrasad Joshi 	ssize_t nr;
302865c675fSPrasad Joshi 
3030df6b4d9SPekka Enberg 	buf		= src;
3040df6b4d9SPekka Enberg 	nr_written	= 0;
305865c675fSPrasad Joshi 	offset		= sector << SECTOR_SHIFT;
3060df6b4d9SPekka Enberg 
3070df6b4d9SPekka Enberg 	while (nr_written < src_len) {
308865c675fSPrasad Joshi 		if (offset >= header->size)
3090df6b4d9SPekka Enberg 			return -1;
310865c675fSPrasad Joshi 
311*b1c84095SPekka Enberg 		nr = qcow_write_cluster(q, offset, buf, src_len - nr_written);
312865c675fSPrasad Joshi 		if (nr < 0)
3130df6b4d9SPekka Enberg 			return -1;
314865c675fSPrasad Joshi 
3150df6b4d9SPekka Enberg 		nr_written	+= nr;
316865c675fSPrasad Joshi 		buf		+= nr;
317865c675fSPrasad Joshi 		offset		+= nr;
318865c675fSPrasad Joshi 	}
3190df6b4d9SPekka Enberg 
32072133dd2SAsias He 	return nr_written;
32186835cedSPrasad Joshi }
32286835cedSPrasad Joshi 
323*b1c84095SPekka Enberg static ssize_t qcow_nowrite_sector(struct disk_image *disk, u64 sector, void *src, u32 src_len)
324f10860caSPekka Enberg {
325f10860caSPekka Enberg 	/* I/O error */
326*b1c84095SPekka Enberg 	pr_info("%s: no write support\n", __func__);
327f10860caSPekka Enberg 	return -1;
328f10860caSPekka Enberg }
329f10860caSPekka Enberg 
330*b1c84095SPekka Enberg static int qcow_disk_close(struct disk_image *disk)
33186835cedSPrasad Joshi {
33286835cedSPrasad Joshi 	struct qcow *q;
33386835cedSPrasad Joshi 
33443835ac9SSasha Levin 	if (!disk)
33572133dd2SAsias He 		return 0;
33686835cedSPrasad Joshi 
33743835ac9SSasha Levin 	q = disk->priv;
33886835cedSPrasad Joshi 
3396c6f79b6SPrasad Joshi 	free(q->table.l1_table);
34086835cedSPrasad Joshi 	free(q->header);
34186835cedSPrasad Joshi 	free(q);
34272133dd2SAsias He 
34372133dd2SAsias He 	return 0;
34486835cedSPrasad Joshi }
34586835cedSPrasad Joshi 
346*b1c84095SPekka Enberg static struct disk_image_operations qcow_disk_readonly_ops = {
347*b1c84095SPekka Enberg 	.read_sector		= qcow_read_sector,
348*b1c84095SPekka Enberg 	.write_sector		= qcow_nowrite_sector,
349*b1c84095SPekka Enberg 	.close			= qcow_disk_close,
350f10860caSPekka Enberg };
351f10860caSPekka Enberg 
352*b1c84095SPekka Enberg static struct disk_image_operations qcow_disk_ops = {
353*b1c84095SPekka Enberg 	.read_sector		= qcow_read_sector,
354*b1c84095SPekka Enberg 	.write_sector		= qcow_write_sector,
355*b1c84095SPekka Enberg 	.close			= qcow_disk_close,
35686835cedSPrasad Joshi };
35786835cedSPrasad Joshi 
35886835cedSPrasad Joshi static int qcow_read_l1_table(struct qcow *q)
35986835cedSPrasad Joshi {
360ad627d62SPekka Enberg 	struct qcow_header *header = q->header;
36100adcc1bSPrasad Joshi 	struct qcow_table *table = &q->table;
36200adcc1bSPrasad Joshi 	u64 i;
36386835cedSPrasad Joshi 
364ad627d62SPekka Enberg 	table->table_size	= header->l1_size;
36586835cedSPrasad Joshi 
36600adcc1bSPrasad Joshi 	table->l1_table	= calloc(table->table_size, sizeof(u64));
36700adcc1bSPrasad Joshi 	if (!table->l1_table)
36886835cedSPrasad Joshi 		return -1;
36986835cedSPrasad Joshi 
37000adcc1bSPrasad Joshi 	if (pread_in_full(q->fd, table->l1_table, sizeof(u64) *
37100adcc1bSPrasad Joshi 				table->table_size, header->l1_table_offset) < 0)
37286835cedSPrasad Joshi 		return -1;
37386835cedSPrasad Joshi 
37400adcc1bSPrasad Joshi 	for (i = 0; i < table->table_size; i++)
37500adcc1bSPrasad Joshi 		be64_to_cpus(&table->l1_table[i]);
37600adcc1bSPrasad Joshi 
37786835cedSPrasad Joshi 	return 0;
37886835cedSPrasad Joshi }
37986835cedSPrasad Joshi 
380ad627d62SPekka Enberg static void *qcow2_read_header(int fd)
38186835cedSPrasad Joshi {
382ad627d62SPekka Enberg 	struct qcow2_header_disk f_header;
383ad627d62SPekka Enberg 	struct qcow_header *header;
38486835cedSPrasad Joshi 
385ad627d62SPekka Enberg 	header = malloc(sizeof(struct qcow_header));
38686835cedSPrasad Joshi 	if (!header)
38786835cedSPrasad Joshi 		return NULL;
38886835cedSPrasad Joshi 
3890657f33dSPrasad Joshi 	if (pread_in_full(fd, &f_header, sizeof(struct qcow2_header_disk), 0) < 0) {
3900657f33dSPrasad Joshi 		free(header);
39186835cedSPrasad Joshi 		return NULL;
3920657f33dSPrasad Joshi 	}
39386835cedSPrasad Joshi 
394ad627d62SPekka Enberg 	be32_to_cpus(&f_header.magic);
395ad627d62SPekka Enberg 	be32_to_cpus(&f_header.version);
396ad627d62SPekka Enberg 	be64_to_cpus(&f_header.backing_file_offset);
397ad627d62SPekka Enberg 	be32_to_cpus(&f_header.backing_file_size);
398ad627d62SPekka Enberg 	be32_to_cpus(&f_header.cluster_bits);
399ad627d62SPekka Enberg 	be64_to_cpus(&f_header.size);
400ad627d62SPekka Enberg 	be32_to_cpus(&f_header.crypt_method);
401ad627d62SPekka Enberg 	be32_to_cpus(&f_header.l1_size);
402ad627d62SPekka Enberg 	be64_to_cpus(&f_header.l1_table_offset);
403ad627d62SPekka Enberg 	be64_to_cpus(&f_header.refcount_table_offset);
404ad627d62SPekka Enberg 	be32_to_cpus(&f_header.refcount_table_clusters);
405ad627d62SPekka Enberg 	be32_to_cpus(&f_header.nb_snapshots);
406ad627d62SPekka Enberg 	be64_to_cpus(&f_header.snapshots_offset);
407ad627d62SPekka Enberg 
408ad627d62SPekka Enberg 	*header		= (struct qcow_header) {
409ad627d62SPekka Enberg 		.size			= f_header.size,
410ad627d62SPekka Enberg 		.l1_table_offset	= f_header.l1_table_offset,
411ad627d62SPekka Enberg 		.l1_size		= f_header.l1_size,
412ad627d62SPekka Enberg 		.cluster_bits		= f_header.cluster_bits,
413ad627d62SPekka Enberg 		.l2_bits		= f_header.cluster_bits - 3,
414ad627d62SPekka Enberg 		.oflag_mask		= QCOW2_OFLAG_MASK,
415ad627d62SPekka Enberg 	};
416ad627d62SPekka Enberg 
417ad627d62SPekka Enberg 	return header;
418ad627d62SPekka Enberg }
419ad627d62SPekka Enberg 
420f10860caSPekka Enberg static struct disk_image *qcow2_probe(int fd, bool readonly)
421ad627d62SPekka Enberg {
422ad627d62SPekka Enberg 	struct qcow *q;
423ad627d62SPekka Enberg 	struct qcow_header *h;
424ad627d62SPekka Enberg 	struct disk_image *disk_image;
425ad627d62SPekka Enberg 
426ad627d62SPekka Enberg 	q = calloc(1, sizeof(struct qcow));
427ad627d62SPekka Enberg 	if (!q)
428ad627d62SPekka Enberg 		goto error;
429ad627d62SPekka Enberg 
430ad627d62SPekka Enberg 	q->fd = fd;
431ad627d62SPekka Enberg 
432ad627d62SPekka Enberg 	h = q->header = qcow2_read_header(fd);
433ad627d62SPekka Enberg 	if (!h)
434ad627d62SPekka Enberg 		goto error;
435ad627d62SPekka Enberg 
436ad627d62SPekka Enberg 	if (qcow_read_l1_table(q) < 0)
437ad627d62SPekka Enberg 		goto error;
438ad627d62SPekka Enberg 
4397d22135fSAsias He 	/*
4407d22135fSAsias He 	 * Do not use mmap use read/write instead
4417d22135fSAsias He 	 */
442f10860caSPekka Enberg 	if (readonly)
443*b1c84095SPekka Enberg 		disk_image = disk_image__new(fd, h->size, &qcow_disk_readonly_ops, DISK_IMAGE_NOMMAP);
444f10860caSPekka Enberg 	else
445*b1c84095SPekka Enberg 		disk_image = disk_image__new(fd, h->size, &qcow_disk_ops, DISK_IMAGE_NOMMAP);
446f10860caSPekka Enberg 
447ad627d62SPekka Enberg 	if (!disk_image)
448ad627d62SPekka Enberg 		goto error;
449ad627d62SPekka Enberg 	disk_image->priv = q;
450ad627d62SPekka Enberg 
451ad627d62SPekka Enberg 	return disk_image;
452ad627d62SPekka Enberg error:
453ad627d62SPekka Enberg 	if (!q)
454ad627d62SPekka Enberg 		return NULL;
455ad627d62SPekka Enberg 
456ad627d62SPekka Enberg 	free(q->table.l1_table);
457ad627d62SPekka Enberg 	free(q->header);
458ad627d62SPekka Enberg 	free(q);
459ad627d62SPekka Enberg 
460ad627d62SPekka Enberg 	return NULL;
461ad627d62SPekka Enberg }
462ad627d62SPekka Enberg 
463ad627d62SPekka Enberg static bool qcow2_check_image(int fd)
464ad627d62SPekka Enberg {
465ad627d62SPekka Enberg 	struct qcow2_header_disk f_header;
466ad627d62SPekka Enberg 
467ad627d62SPekka Enberg 	if (pread_in_full(fd, &f_header, sizeof(struct qcow2_header_disk), 0) < 0)
468ad627d62SPekka Enberg 		return false;
469ad627d62SPekka Enberg 
470ad627d62SPekka Enberg 	be32_to_cpus(&f_header.magic);
471ad627d62SPekka Enberg 	be32_to_cpus(&f_header.version);
472ad627d62SPekka Enberg 
473ad627d62SPekka Enberg 	if (f_header.magic != QCOW_MAGIC)
474ad627d62SPekka Enberg 		return false;
475ad627d62SPekka Enberg 
476ad627d62SPekka Enberg 	if (f_header.version != QCOW2_VERSION)
477ad627d62SPekka Enberg 		return false;
478ad627d62SPekka Enberg 
479ad627d62SPekka Enberg 	return true;
480ad627d62SPekka Enberg }
481ad627d62SPekka Enberg 
482ad627d62SPekka Enberg static void *qcow1_read_header(int fd)
483ad627d62SPekka Enberg {
484ad627d62SPekka Enberg 	struct qcow1_header_disk f_header;
485ad627d62SPekka Enberg 	struct qcow_header *header;
486ad627d62SPekka Enberg 
487ad627d62SPekka Enberg 	header = malloc(sizeof(struct qcow_header));
488ad627d62SPekka Enberg 	if (!header)
489ad627d62SPekka Enberg 		return NULL;
490ad627d62SPekka Enberg 
491d39cefd2SSasha Levin 	if (pread_in_full(fd, &f_header, sizeof(struct qcow1_header_disk), 0) < 0) {
492d39cefd2SSasha Levin 		free(header);
493ad627d62SPekka Enberg 		return NULL;
494d39cefd2SSasha Levin 	}
495ad627d62SPekka Enberg 
496ad627d62SPekka Enberg 	be32_to_cpus(&f_header.magic);
497ad627d62SPekka Enberg 	be32_to_cpus(&f_header.version);
498ad627d62SPekka Enberg 	be64_to_cpus(&f_header.backing_file_offset);
499ad627d62SPekka Enberg 	be32_to_cpus(&f_header.backing_file_size);
500ad627d62SPekka Enberg 	be32_to_cpus(&f_header.mtime);
501ad627d62SPekka Enberg 	be64_to_cpus(&f_header.size);
502ad627d62SPekka Enberg 	be32_to_cpus(&f_header.crypt_method);
503ad627d62SPekka Enberg 	be64_to_cpus(&f_header.l1_table_offset);
504ad627d62SPekka Enberg 
505ad627d62SPekka Enberg 	*header		= (struct qcow_header) {
506ad627d62SPekka Enberg 		.size			= f_header.size,
507ad627d62SPekka Enberg 		.l1_table_offset	= f_header.l1_table_offset,
508ad627d62SPekka Enberg 		.l1_size		= f_header.size / ((1 << f_header.l2_bits) * (1 << f_header.cluster_bits)),
509ad627d62SPekka Enberg 		.cluster_bits		= f_header.cluster_bits,
510ad627d62SPekka Enberg 		.l2_bits		= f_header.l2_bits,
511ad627d62SPekka Enberg 		.oflag_mask		= QCOW1_OFLAG_MASK,
512ad627d62SPekka Enberg 	};
51386835cedSPrasad Joshi 
51486835cedSPrasad Joshi 	return header;
51586835cedSPrasad Joshi }
51686835cedSPrasad Joshi 
517f10860caSPekka Enberg static struct disk_image *qcow1_probe(int fd, bool readonly)
51886835cedSPrasad Joshi {
51986835cedSPrasad Joshi 	struct qcow *q;
520ad627d62SPekka Enberg 	struct qcow_header *h;
52186835cedSPrasad Joshi 	struct disk_image *disk_image;
52286835cedSPrasad Joshi 
52386835cedSPrasad Joshi 	q = calloc(1, sizeof(struct qcow));
52486835cedSPrasad Joshi 	if (!q)
52586835cedSPrasad Joshi 		goto error;
52686835cedSPrasad Joshi 
52786835cedSPrasad Joshi 	q->fd = fd;
52886835cedSPrasad Joshi 
52986835cedSPrasad Joshi 	h = q->header = qcow1_read_header(fd);
53086835cedSPrasad Joshi 	if (!h)
53186835cedSPrasad Joshi 		goto error;
53286835cedSPrasad Joshi 
53386835cedSPrasad Joshi 	if (qcow_read_l1_table(q) < 0)
53486835cedSPrasad Joshi 		goto error;
53586835cedSPrasad Joshi 
5367d22135fSAsias He 	/*
5377d22135fSAsias He 	 * Do not use mmap use read/write instead
5387d22135fSAsias He 	 */
539f10860caSPekka Enberg 	if (readonly)
540*b1c84095SPekka Enberg 		disk_image = disk_image__new(fd, h->size, &qcow_disk_readonly_ops, DISK_IMAGE_NOMMAP);
541f10860caSPekka Enberg 	else
542*b1c84095SPekka Enberg 		disk_image = disk_image__new(fd, h->size, &qcow_disk_ops, DISK_IMAGE_NOMMAP);
543f10860caSPekka Enberg 
54486835cedSPrasad Joshi 	if (!disk_image)
54586835cedSPrasad Joshi 		goto error;
54686835cedSPrasad Joshi 	disk_image->priv = q;
54786835cedSPrasad Joshi 
54886835cedSPrasad Joshi 	return disk_image;
54986835cedSPrasad Joshi error:
55086835cedSPrasad Joshi 	if (!q)
55186835cedSPrasad Joshi 		return NULL;
55286835cedSPrasad Joshi 
5536c6f79b6SPrasad Joshi 	free(q->table.l1_table);
55486835cedSPrasad Joshi 	free(q->header);
55586835cedSPrasad Joshi 	free(q);
55686835cedSPrasad Joshi 
55786835cedSPrasad Joshi 	return NULL;
55886835cedSPrasad Joshi }
55986835cedSPrasad Joshi 
560ad627d62SPekka Enberg static bool qcow1_check_image(int fd)
56186835cedSPrasad Joshi {
562ad627d62SPekka Enberg 	struct qcow1_header_disk f_header;
56386835cedSPrasad Joshi 
564ad627d62SPekka Enberg 	if (pread_in_full(fd, &f_header, sizeof(struct qcow1_header_disk), 0) < 0)
565ad627d62SPekka Enberg 		return false;
56686835cedSPrasad Joshi 
567ad627d62SPekka Enberg 	be32_to_cpus(&f_header.magic);
568ad627d62SPekka Enberg 	be32_to_cpus(&f_header.version);
56986835cedSPrasad Joshi 
570ad627d62SPekka Enberg 	if (f_header.magic != QCOW_MAGIC)
571ad627d62SPekka Enberg 		return false;
57286835cedSPrasad Joshi 
573ad627d62SPekka Enberg 	if (f_header.version != QCOW1_VERSION)
574ad627d62SPekka Enberg 		return false;
57586835cedSPrasad Joshi 
576ad627d62SPekka Enberg 	return true;
57786835cedSPrasad Joshi }
57886835cedSPrasad Joshi 
579f10860caSPekka Enberg struct disk_image *qcow_probe(int fd, bool readonly)
58086835cedSPrasad Joshi {
581ad627d62SPekka Enberg 	if (qcow1_check_image(fd))
582f10860caSPekka Enberg 		return qcow1_probe(fd, readonly);
583ad627d62SPekka Enberg 
584ad627d62SPekka Enberg 	if (qcow2_check_image(fd))
585f10860caSPekka Enberg 		return qcow2_probe(fd, readonly);
586ad627d62SPekka Enberg 
587ad627d62SPekka Enberg 	return NULL;
58886835cedSPrasad Joshi }
589