xref: /kvmtool/disk/qcow.c (revision dae803fb5987f147b45f8ce2945579f239ade59e)
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>
1786835cedSPrasad Joshi 
18742fce76SPrasad Joshi static inline u64 get_l1_index(struct qcow *q, u64 offset)
1986835cedSPrasad Joshi {
2086835cedSPrasad Joshi 	struct qcow1_header *header = q->header;
2186835cedSPrasad Joshi 
2286835cedSPrasad Joshi 	return offset >> (header->l2_bits + header->cluster_bits);
2386835cedSPrasad Joshi }
2486835cedSPrasad Joshi 
25742fce76SPrasad Joshi static inline u64 get_l2_index(struct qcow *q, u64 offset)
2686835cedSPrasad Joshi {
2786835cedSPrasad Joshi 	struct qcow1_header *header = q->header;
2886835cedSPrasad Joshi 
2986835cedSPrasad Joshi 	return (offset >> (header->cluster_bits)) & ((1 << header->l2_bits)-1);
3086835cedSPrasad Joshi }
3186835cedSPrasad Joshi 
32742fce76SPrasad Joshi static inline u64 get_cluster_offset(struct qcow *q, u64 offset)
3386835cedSPrasad Joshi {
3486835cedSPrasad Joshi 	struct qcow1_header *header = q->header;
3586835cedSPrasad Joshi 
3686835cedSPrasad Joshi 	return offset & ((1 << header->cluster_bits)-1);
3786835cedSPrasad Joshi }
3886835cedSPrasad Joshi 
393dac48d4SPrasad Joshi static u32 qcow1_read_cluster(struct qcow *q, u64 offset, void *dst,
403dac48d4SPrasad Joshi 		u32 dst_len)
4186835cedSPrasad Joshi {
4286835cedSPrasad Joshi 	struct qcow1_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;
50742fce76SPrasad Joshi 	u64 l1_idx;
51742fce76SPrasad Joshi 	u64 l2_idx;
523dac48d4SPrasad Joshi 	u32 length;
5386835cedSPrasad Joshi 
54*dae803fbSPekka 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 
683dac48d4SPrasad Joshi 	l2_table_offset = table->l1_table[l1_idx];
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 
8586835cedSPrasad Joshi 	clust_start = be64_to_cpu(l2_table[l2_idx]);
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 
1053dac48d4SPrasad Joshi static int qcow1_read_sector(struct disk_image *self, uint64_t sector,
1063dac48d4SPrasad Joshi 		void *dst, uint32_t dst_len)
1073dac48d4SPrasad Joshi {
1083dac48d4SPrasad Joshi 	struct qcow *q = self->priv;
1093dac48d4SPrasad Joshi 	struct qcow1_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);
1223dac48d4SPrasad Joshi 		if (!nr)
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 
13486835cedSPrasad Joshi static int qcow1_write_sector(struct disk_image *self, uint64_t sector, void *src, uint32_t src_len)
13586835cedSPrasad Joshi {
13686835cedSPrasad Joshi 	return -1;
13786835cedSPrasad Joshi }
13886835cedSPrasad Joshi 
13986835cedSPrasad Joshi static void qcow1_disk_close(struct disk_image *self)
14086835cedSPrasad Joshi {
14186835cedSPrasad Joshi 	struct qcow *q;
14286835cedSPrasad Joshi 
14386835cedSPrasad Joshi 	if (!self)
14486835cedSPrasad Joshi 		return;
14586835cedSPrasad Joshi 
14686835cedSPrasad Joshi 	q = self->priv;
14786835cedSPrasad Joshi 
1486c6f79b6SPrasad Joshi 	free(q->table.l1_table);
14986835cedSPrasad Joshi 	free(q->header);
15086835cedSPrasad Joshi 	free(q);
15186835cedSPrasad Joshi }
15286835cedSPrasad Joshi 
15386835cedSPrasad Joshi struct disk_image_operations qcow1_disk_ops = {
15486835cedSPrasad Joshi 	.read_sector		= qcow1_read_sector,
15586835cedSPrasad Joshi 	.write_sector		= qcow1_write_sector,
15686835cedSPrasad Joshi 	.close			= qcow1_disk_close
15786835cedSPrasad Joshi };
15886835cedSPrasad Joshi 
15986835cedSPrasad Joshi static int qcow_read_l1_table(struct qcow *q)
16086835cedSPrasad Joshi {
16186835cedSPrasad Joshi 	struct qcow1_header *header = q->header;
16200adcc1bSPrasad Joshi 	struct qcow_table *table = &q->table;
16300adcc1bSPrasad Joshi 	u64 i;
16486835cedSPrasad Joshi 
16500adcc1bSPrasad Joshi 	table->table_size = header->size / ((1 << header->l2_bits) *
16600adcc1bSPrasad Joshi 			(1 << header->cluster_bits));
16786835cedSPrasad Joshi 
16800adcc1bSPrasad Joshi 	table->l1_table	= calloc(table->table_size, sizeof(u64));
16900adcc1bSPrasad Joshi 	if (!table->l1_table)
17086835cedSPrasad Joshi 		return -1;
17186835cedSPrasad Joshi 
17200adcc1bSPrasad Joshi 	if (pread_in_full(q->fd, table->l1_table, sizeof(u64) *
17300adcc1bSPrasad Joshi 				table->table_size, header->l1_table_offset) < 0)
17486835cedSPrasad Joshi 		return -1;
17586835cedSPrasad Joshi 
17600adcc1bSPrasad Joshi 	for (i = 0; i < table->table_size; i++)
17700adcc1bSPrasad Joshi 		be64_to_cpus(&table->l1_table[i]);
17800adcc1bSPrasad Joshi 
17986835cedSPrasad Joshi 	return 0;
18086835cedSPrasad Joshi }
18186835cedSPrasad Joshi 
18286835cedSPrasad Joshi static void *qcow1_read_header(int fd)
18386835cedSPrasad Joshi {
18486835cedSPrasad Joshi 	struct qcow1_header *header;
18586835cedSPrasad Joshi 
18686835cedSPrasad Joshi 	header = malloc(sizeof(struct qcow1_header));
18786835cedSPrasad Joshi 	if (!header)
18886835cedSPrasad Joshi 		return NULL;
18986835cedSPrasad Joshi 
19086835cedSPrasad Joshi 	if (pread_in_full(fd, header, sizeof(struct qcow1_header), 0) < 0)
19186835cedSPrasad Joshi 		return NULL;
19286835cedSPrasad Joshi 
19386835cedSPrasad Joshi 	be32_to_cpus(&header->magic);
19486835cedSPrasad Joshi 	be32_to_cpus(&header->version);
19586835cedSPrasad Joshi 	be64_to_cpus(&header->backing_file_offset);
19686835cedSPrasad Joshi 	be32_to_cpus(&header->backing_file_size);
19786835cedSPrasad Joshi 	be32_to_cpus(&header->mtime);
19886835cedSPrasad Joshi 	be64_to_cpus(&header->size);
19986835cedSPrasad Joshi 	be32_to_cpus(&header->crypt_method);
20086835cedSPrasad Joshi 	be64_to_cpus(&header->l1_table_offset);
20186835cedSPrasad Joshi 
20286835cedSPrasad Joshi 	return header;
20386835cedSPrasad Joshi }
20486835cedSPrasad Joshi 
20586835cedSPrasad Joshi static struct disk_image *qcow1_probe(int fd)
20686835cedSPrasad Joshi {
20786835cedSPrasad Joshi 	struct qcow *q;
20886835cedSPrasad Joshi 	struct qcow1_header *h;
20986835cedSPrasad Joshi 	struct disk_image *disk_image;
21086835cedSPrasad Joshi 
21186835cedSPrasad Joshi 	q = calloc(1, sizeof(struct qcow));
21286835cedSPrasad Joshi 	if (!q)
21386835cedSPrasad Joshi 		goto error;
21486835cedSPrasad Joshi 
21586835cedSPrasad Joshi 	q->fd = fd;
21686835cedSPrasad Joshi 
21786835cedSPrasad Joshi 	h = q->header = qcow1_read_header(fd);
21886835cedSPrasad Joshi 	if (!h)
21986835cedSPrasad Joshi 		goto error;
22086835cedSPrasad Joshi 
22186835cedSPrasad Joshi 	if (qcow_read_l1_table(q) < 0)
22286835cedSPrasad Joshi 		goto error;
22386835cedSPrasad Joshi 
22486835cedSPrasad Joshi 	disk_image = disk_image__new(fd, h->size, &qcow1_disk_ops);
22586835cedSPrasad Joshi 	if (!disk_image)
22686835cedSPrasad Joshi 		goto error;
22786835cedSPrasad Joshi 	disk_image->priv = q;
22886835cedSPrasad Joshi 
22986835cedSPrasad Joshi 	return disk_image;
23086835cedSPrasad Joshi error:
23186835cedSPrasad Joshi 	if (!q)
23286835cedSPrasad Joshi 		return NULL;
23386835cedSPrasad Joshi 
2346c6f79b6SPrasad Joshi 	free(q->table.l1_table);
23586835cedSPrasad Joshi 	free(q->header);
23686835cedSPrasad Joshi 	free(q);
23786835cedSPrasad Joshi 
23886835cedSPrasad Joshi 	return NULL;
23986835cedSPrasad Joshi }
24086835cedSPrasad Joshi 
24186835cedSPrasad Joshi static int qcow_check_image(int fd)
24286835cedSPrasad Joshi {
24386835cedSPrasad Joshi 	struct qcow1_header header;
24486835cedSPrasad Joshi 
24586835cedSPrasad Joshi 	if (pread_in_full(fd, &header, sizeof(struct qcow1_header), 0) < 0)
24686835cedSPrasad Joshi 		return -1;
24786835cedSPrasad Joshi 
24886835cedSPrasad Joshi 	be32_to_cpus(&header.magic);
24986835cedSPrasad Joshi 	be32_to_cpus(&header.version);
25086835cedSPrasad Joshi 
25186835cedSPrasad Joshi 	if (header.magic != QCOW_MAGIC)
25286835cedSPrasad Joshi 		return -1;
25386835cedSPrasad Joshi 
25486835cedSPrasad Joshi 	if (header.version != QCOW1_VERSION)
25586835cedSPrasad Joshi 		return -1;
25686835cedSPrasad Joshi 
25786835cedSPrasad Joshi 	return 0;
25886835cedSPrasad Joshi }
25986835cedSPrasad Joshi 
26086835cedSPrasad Joshi struct disk_image *qcow_probe(int fd)
26186835cedSPrasad Joshi {
26286835cedSPrasad Joshi 	if (qcow_check_image(fd) < 0)
26386835cedSPrasad Joshi 		return NULL;
26486835cedSPrasad Joshi 
26586835cedSPrasad Joshi 	return qcow1_probe(fd);
26686835cedSPrasad Joshi }
267