xref: /kvmtool/disk/qcow.c (revision 86835ced6d416f4e6471db823b9ad9d1474e3735)
1*86835cedSPrasad Joshi #include "kvm/qcow.h"
2*86835cedSPrasad Joshi 
3*86835cedSPrasad Joshi #include "kvm/disk-image.h"
4*86835cedSPrasad Joshi #include "kvm/read-write.h"
5*86835cedSPrasad Joshi #include "kvm/util.h"
6*86835cedSPrasad Joshi 
7*86835cedSPrasad Joshi #include <sys/types.h>
8*86835cedSPrasad Joshi #include <sys/stat.h>
9*86835cedSPrasad Joshi #include <stdbool.h>
10*86835cedSPrasad Joshi #include <stdlib.h>
11*86835cedSPrasad Joshi #include <string.h>
12*86835cedSPrasad Joshi #include <unistd.h>
13*86835cedSPrasad Joshi #include <fcntl.h>
14*86835cedSPrasad Joshi 
15*86835cedSPrasad Joshi #include <linux/byteorder.h>
16*86835cedSPrasad Joshi #include <linux/types.h>
17*86835cedSPrasad Joshi 
18*86835cedSPrasad Joshi static inline uint64_t sect_to_l1_offset(struct qcow *q, uint64_t offset)
19*86835cedSPrasad Joshi {
20*86835cedSPrasad Joshi 	struct qcow1_header *header = q->header;
21*86835cedSPrasad Joshi 
22*86835cedSPrasad Joshi 	return offset >> (header->l2_bits + header->cluster_bits);
23*86835cedSPrasad Joshi }
24*86835cedSPrasad Joshi 
25*86835cedSPrasad Joshi static inline uint64_t sect_to_l2_offset(struct qcow *q, uint64_t offset)
26*86835cedSPrasad Joshi {
27*86835cedSPrasad Joshi 	struct qcow1_header *header = q->header;
28*86835cedSPrasad Joshi 
29*86835cedSPrasad Joshi 	return (offset >> (header->cluster_bits)) & ((1 << header->l2_bits)-1);
30*86835cedSPrasad Joshi }
31*86835cedSPrasad Joshi 
32*86835cedSPrasad Joshi static inline uint64_t sect_to_cluster_offset(struct qcow *q, uint64_t offset)
33*86835cedSPrasad Joshi {
34*86835cedSPrasad Joshi 	struct qcow1_header *header = q->header;
35*86835cedSPrasad Joshi 
36*86835cedSPrasad Joshi 	return offset & ((1 << header->cluster_bits)-1);
37*86835cedSPrasad Joshi }
38*86835cedSPrasad Joshi 
39*86835cedSPrasad Joshi static int qcow1_read_sector(struct disk_image *self, uint64_t sector, void *dst, uint32_t dst_len)
40*86835cedSPrasad Joshi {
41*86835cedSPrasad Joshi 	struct qcow *q = self->priv;
42*86835cedSPrasad Joshi 	struct qcow1_header *header = q->header;
43*86835cedSPrasad Joshi 	uint64_t l2_table_offset;
44*86835cedSPrasad Joshi 	uint64_t l2_table_size;
45*86835cedSPrasad Joshi 	uint64_t clust_offset;
46*86835cedSPrasad Joshi 	uint64_t clust_start;
47*86835cedSPrasad Joshi 	uint64_t *l2_table;
48*86835cedSPrasad Joshi 	uint64_t l1_idx;
49*86835cedSPrasad Joshi 	uint64_t l2_idx;
50*86835cedSPrasad Joshi 	uint64_t offset;
51*86835cedSPrasad Joshi 
52*86835cedSPrasad Joshi 	offset		= sector << SECTOR_SHIFT;
53*86835cedSPrasad Joshi 	if (offset >= header->size)
54*86835cedSPrasad Joshi 		goto out_error;
55*86835cedSPrasad Joshi 
56*86835cedSPrasad Joshi 	l1_idx		= sect_to_l1_offset(self->priv, offset);
57*86835cedSPrasad Joshi 
58*86835cedSPrasad Joshi 	if (l1_idx >= q->table.table_size)
59*86835cedSPrasad Joshi 		goto out_error;
60*86835cedSPrasad Joshi 
61*86835cedSPrasad Joshi 	l2_table_offset	= be64_to_cpu(q->table.l1_table[l1_idx]);
62*86835cedSPrasad Joshi 	if (!l2_table_offset)
63*86835cedSPrasad Joshi 		goto zero_sector;
64*86835cedSPrasad Joshi 
65*86835cedSPrasad Joshi 	l2_table_size	= 1 << header->l2_bits;
66*86835cedSPrasad Joshi 
67*86835cedSPrasad Joshi 	l2_table	= calloc(l2_table_size, sizeof(uint64_t));
68*86835cedSPrasad Joshi 	if (!l2_table)
69*86835cedSPrasad Joshi 		goto out_error;
70*86835cedSPrasad Joshi 
71*86835cedSPrasad Joshi 	if (pread_in_full(q->fd, l2_table, sizeof(uint64_t) * l2_table_size, l2_table_offset) < 0)
72*86835cedSPrasad Joshi 		goto out_error_free_l2;
73*86835cedSPrasad Joshi 
74*86835cedSPrasad Joshi 	l2_idx		= sect_to_l2_offset(self->priv, offset);
75*86835cedSPrasad Joshi 
76*86835cedSPrasad Joshi 	if (l2_idx >= l2_table_size)
77*86835cedSPrasad Joshi 		goto out_error_free_l2;
78*86835cedSPrasad Joshi 
79*86835cedSPrasad Joshi 	clust_start	= be64_to_cpu(l2_table[l2_idx]);
80*86835cedSPrasad Joshi 
81*86835cedSPrasad Joshi 	if (!clust_start)
82*86835cedSPrasad Joshi 		goto zero_sector;
83*86835cedSPrasad Joshi 
84*86835cedSPrasad Joshi 	clust_offset	= sect_to_cluster_offset(self->priv, offset);
85*86835cedSPrasad Joshi 
86*86835cedSPrasad Joshi 	if (pread_in_full(q->fd, dst, dst_len, clust_start + clust_offset) < 0)
87*86835cedSPrasad Joshi 		goto out_error_free_l2;
88*86835cedSPrasad Joshi 
89*86835cedSPrasad Joshi 	free(l2_table);
90*86835cedSPrasad Joshi 
91*86835cedSPrasad Joshi 	return 0;
92*86835cedSPrasad Joshi 
93*86835cedSPrasad Joshi zero_sector:
94*86835cedSPrasad Joshi 	memset(dst, 0, dst_len);
95*86835cedSPrasad Joshi 
96*86835cedSPrasad Joshi 	return 0;
97*86835cedSPrasad Joshi 
98*86835cedSPrasad Joshi out_error_free_l2:
99*86835cedSPrasad Joshi 	free(l2_table);
100*86835cedSPrasad Joshi out_error:
101*86835cedSPrasad Joshi 	return -1;
102*86835cedSPrasad Joshi }
103*86835cedSPrasad Joshi 
104*86835cedSPrasad Joshi static int qcow1_write_sector(struct disk_image *self, uint64_t sector, void *src, uint32_t src_len)
105*86835cedSPrasad Joshi {
106*86835cedSPrasad Joshi 	return -1;
107*86835cedSPrasad Joshi }
108*86835cedSPrasad Joshi 
109*86835cedSPrasad Joshi static void qcow1_disk_close(struct disk_image *self)
110*86835cedSPrasad Joshi {
111*86835cedSPrasad Joshi 	struct qcow *q;
112*86835cedSPrasad Joshi 
113*86835cedSPrasad Joshi 	if (!self)
114*86835cedSPrasad Joshi 		return;
115*86835cedSPrasad Joshi 
116*86835cedSPrasad Joshi 	q = self->priv;
117*86835cedSPrasad Joshi 
118*86835cedSPrasad Joshi 	free(q->header);
119*86835cedSPrasad Joshi 	free(q);
120*86835cedSPrasad Joshi }
121*86835cedSPrasad Joshi 
122*86835cedSPrasad Joshi struct disk_image_operations qcow1_disk_ops = {
123*86835cedSPrasad Joshi 	.read_sector		= qcow1_read_sector,
124*86835cedSPrasad Joshi 	.write_sector		= qcow1_write_sector,
125*86835cedSPrasad Joshi 	.close			= qcow1_disk_close
126*86835cedSPrasad Joshi };
127*86835cedSPrasad Joshi 
128*86835cedSPrasad Joshi static int qcow_read_l1_table(struct qcow *q)
129*86835cedSPrasad Joshi {
130*86835cedSPrasad Joshi 	struct qcow1_header *header = q->header;
131*86835cedSPrasad Joshi 
132*86835cedSPrasad Joshi 	q->table.table_size	= header->size / ((1 << header->l2_bits) * (1 << header->cluster_bits));
133*86835cedSPrasad Joshi 
134*86835cedSPrasad Joshi 	q->table.l1_table	= calloc(q->table.table_size, sizeof(uint64_t));
135*86835cedSPrasad Joshi 	if (!q->table.l1_table)
136*86835cedSPrasad Joshi 		return -1;
137*86835cedSPrasad Joshi 
138*86835cedSPrasad Joshi 	if (pread_in_full(q->fd, q->table.l1_table, sizeof(uint64_t) * q->table.table_size, header->l1_table_offset) < 0)
139*86835cedSPrasad Joshi 		return -1;
140*86835cedSPrasad Joshi 
141*86835cedSPrasad Joshi 	return 0;
142*86835cedSPrasad Joshi }
143*86835cedSPrasad Joshi 
144*86835cedSPrasad Joshi static void *qcow1_read_header(int fd)
145*86835cedSPrasad Joshi {
146*86835cedSPrasad Joshi 	struct qcow1_header *header;
147*86835cedSPrasad Joshi 
148*86835cedSPrasad Joshi 	header = malloc(sizeof(struct qcow1_header));
149*86835cedSPrasad Joshi 	if (!header)
150*86835cedSPrasad Joshi 		return NULL;
151*86835cedSPrasad Joshi 
152*86835cedSPrasad Joshi 	if (pread_in_full(fd, header, sizeof(struct qcow1_header), 0) < 0)
153*86835cedSPrasad Joshi 		return NULL;
154*86835cedSPrasad Joshi 
155*86835cedSPrasad Joshi 	be32_to_cpus(&header->magic);
156*86835cedSPrasad Joshi 	be32_to_cpus(&header->version);
157*86835cedSPrasad Joshi 	be64_to_cpus(&header->backing_file_offset);
158*86835cedSPrasad Joshi 	be32_to_cpus(&header->backing_file_size);
159*86835cedSPrasad Joshi 	be32_to_cpus(&header->mtime);
160*86835cedSPrasad Joshi 	be64_to_cpus(&header->size);
161*86835cedSPrasad Joshi 	be32_to_cpus(&header->crypt_method);
162*86835cedSPrasad Joshi 	be64_to_cpus(&header->l1_table_offset);
163*86835cedSPrasad Joshi 
164*86835cedSPrasad Joshi 	return header;
165*86835cedSPrasad Joshi }
166*86835cedSPrasad Joshi 
167*86835cedSPrasad Joshi static struct disk_image *qcow1_probe(int fd)
168*86835cedSPrasad Joshi {
169*86835cedSPrasad Joshi 	struct qcow *q;
170*86835cedSPrasad Joshi 	struct qcow1_header *h;
171*86835cedSPrasad Joshi 	struct disk_image *disk_image;
172*86835cedSPrasad Joshi 
173*86835cedSPrasad Joshi 	q = calloc(1, sizeof(struct qcow));
174*86835cedSPrasad Joshi 	if (!q)
175*86835cedSPrasad Joshi 		goto error;
176*86835cedSPrasad Joshi 
177*86835cedSPrasad Joshi 	q->fd = fd;
178*86835cedSPrasad Joshi 
179*86835cedSPrasad Joshi 	h = q->header = qcow1_read_header(fd);
180*86835cedSPrasad Joshi 	if (!h)
181*86835cedSPrasad Joshi 		goto error;
182*86835cedSPrasad Joshi 
183*86835cedSPrasad Joshi 	if (qcow_read_l1_table(q) < 0)
184*86835cedSPrasad Joshi 		goto error;
185*86835cedSPrasad Joshi 
186*86835cedSPrasad Joshi 	disk_image = disk_image__new(fd, h->size, &qcow1_disk_ops);
187*86835cedSPrasad Joshi 	if (!disk_image)
188*86835cedSPrasad Joshi 		goto error;
189*86835cedSPrasad Joshi 	disk_image->priv = q;
190*86835cedSPrasad Joshi 
191*86835cedSPrasad Joshi 	return disk_image;
192*86835cedSPrasad Joshi error:
193*86835cedSPrasad Joshi 	if (!q)
194*86835cedSPrasad Joshi 		return NULL;
195*86835cedSPrasad Joshi 
196*86835cedSPrasad Joshi 	free(q->header);
197*86835cedSPrasad Joshi 	free(q);
198*86835cedSPrasad Joshi 
199*86835cedSPrasad Joshi 	return NULL;
200*86835cedSPrasad Joshi }
201*86835cedSPrasad Joshi 
202*86835cedSPrasad Joshi static int qcow_check_image(int fd)
203*86835cedSPrasad Joshi {
204*86835cedSPrasad Joshi 	struct qcow1_header header;
205*86835cedSPrasad Joshi 
206*86835cedSPrasad Joshi 	if (pread_in_full(fd, &header, sizeof(struct qcow1_header), 0) < 0)
207*86835cedSPrasad Joshi 		return -1;
208*86835cedSPrasad Joshi 
209*86835cedSPrasad Joshi 	be32_to_cpus(&header.magic);
210*86835cedSPrasad Joshi 	be32_to_cpus(&header.version);
211*86835cedSPrasad Joshi 
212*86835cedSPrasad Joshi 	if (header.magic != QCOW_MAGIC)
213*86835cedSPrasad Joshi 		return -1;
214*86835cedSPrasad Joshi 
215*86835cedSPrasad Joshi 	if (header.version != QCOW1_VERSION)
216*86835cedSPrasad Joshi 		return -1;
217*86835cedSPrasad Joshi 
218*86835cedSPrasad Joshi 	return 0;
219*86835cedSPrasad Joshi }
220*86835cedSPrasad Joshi 
221*86835cedSPrasad Joshi struct disk_image *qcow_probe(int fd)
222*86835cedSPrasad Joshi {
223*86835cedSPrasad Joshi 	if (qcow_check_image(fd) < 0)
224*86835cedSPrasad Joshi 		return NULL;
225*86835cedSPrasad Joshi 
226*86835cedSPrasad Joshi 	return qcow1_probe(fd);
227*86835cedSPrasad Joshi }
228