]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/import/qcow2-util.c
Merge pull request #57 from pwithnall/wip/pwithnall/udev-virtualbox-rules
[thirdparty/systemd.git] / src / import / qcow2-util.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2015 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <zlib.h>
23
24 #include "util.h"
25 #include "sparse-endian.h"
26 #include "qcow2-util.h"
27 #include "btrfs-util.h"
28
29 #define QCOW2_MAGIC 0x514649fb
30
31 #define QCOW2_COPIED (1ULL << 63)
32 #define QCOW2_COMPRESSED (1ULL << 62)
33 #define QCOW2_ZERO (1ULL << 0)
34
35 typedef struct _packed_ Header {
36 be32_t magic;
37 be32_t version;
38
39 be64_t backing_file_offset;
40 be32_t backing_file_size;
41
42 be32_t cluster_bits;
43 be64_t size;
44 be32_t crypt_method;
45
46 be32_t l1_size;
47 be64_t l1_table_offset;
48
49 be64_t refcount_table_offset;
50 be32_t refcount_table_clusters;
51
52 be32_t nb_snapshots;
53 be64_t snapshots_offset;
54
55 /* The remainder is only present on QCOW3 */
56 be64_t incompatible_features;
57 be64_t compatible_features;
58 be64_t autoclear_features;
59
60 be32_t refcount_order;
61 be32_t header_length;
62 } Header;
63
64 #define HEADER_MAGIC(header) be32toh((header)->magic)
65 #define HEADER_VERSION(header) be32toh((header)->version)
66 #define HEADER_CLUSTER_BITS(header) be32toh((header)->cluster_bits)
67 #define HEADER_CLUSTER_SIZE(header) (1ULL << HEADER_CLUSTER_BITS(header))
68 #define HEADER_L2_BITS(header) (HEADER_CLUSTER_BITS(header) - 3)
69 #define HEADER_SIZE(header) be64toh((header)->size)
70 #define HEADER_CRYPT_METHOD(header) be32toh((header)->crypt_method)
71 #define HEADER_L1_SIZE(header) be32toh((header)->l1_size)
72 #define HEADER_L2_SIZE(header) (HEADER_CLUSTER_SIZE(header)/sizeof(uint64_t))
73 #define HEADER_L1_TABLE_OFFSET(header) be64toh((header)->l1_table_offset)
74
75 static uint32_t HEADER_HEADER_LENGTH(const Header *h) {
76 if (HEADER_VERSION(h) < 3)
77 return offsetof(Header, incompatible_features);
78
79 return be32toh(h->header_length);
80 }
81
82 static int copy_cluster(
83 int sfd, uint64_t soffset,
84 int dfd, uint64_t doffset,
85 uint64_t cluster_size,
86 void *buffer) {
87
88 ssize_t l;
89 int r;
90
91 r = btrfs_clone_range(sfd, soffset, dfd, doffset, cluster_size);
92 if (r >= 0)
93 return r;
94
95 l = pread(sfd, buffer, cluster_size, soffset);
96 if (l < 0)
97 return -errno;
98 if ((uint64_t) l != cluster_size)
99 return -EIO;
100
101 l = pwrite(dfd, buffer, cluster_size, doffset);
102 if (l < 0)
103 return -errno;
104 if ((uint64_t) l != cluster_size)
105 return -EIO;
106
107 return 0;
108 }
109
110 static int decompress_cluster(
111 int sfd, uint64_t soffset,
112 int dfd, uint64_t doffset,
113 uint64_t compressed_size,
114 uint64_t cluster_size,
115 void *buffer1,
116 void *buffer2) {
117
118 _cleanup_free_ void *large_buffer = NULL;
119 z_stream s = {};
120 uint64_t sz;
121 ssize_t l;
122 int r;
123
124 if (compressed_size > cluster_size) {
125 /* The usual cluster buffer doesn't suffice, let's
126 * allocate a larger one, temporarily */
127
128 large_buffer = malloc(compressed_size);
129 if (!large_buffer)
130 return -ENOMEM;
131
132 buffer1 = large_buffer;
133 }
134
135 l = pread(sfd, buffer1, compressed_size, soffset);
136 if (l < 0)
137 return -errno;
138 if ((uint64_t) l != compressed_size)
139 return -EIO;
140
141 s.next_in = buffer1;
142 s.avail_in = compressed_size;
143 s.next_out = buffer2;
144 s.avail_out = cluster_size;
145
146 r = inflateInit2(&s, -12);
147 if (r != Z_OK)
148 return -EIO;
149
150 r = inflate(&s, Z_FINISH);
151 sz = (uint8_t*) s.next_out - (uint8_t*) buffer2;
152 inflateEnd(&s);
153 if (r != Z_STREAM_END || sz != cluster_size)
154 return -EIO;
155
156 l = pwrite(dfd, buffer2, cluster_size, doffset);
157 if (l < 0)
158 return -errno;
159 if ((uint64_t) l != cluster_size)
160 return -EIO;
161
162 return 0;
163 }
164
165 static int normalize_offset(
166 const Header *header,
167 uint64_t p,
168 uint64_t *ret,
169 bool *compressed,
170 uint64_t *compressed_size) {
171
172 uint64_t q;
173
174 q = be64toh(p);
175
176 if (q & QCOW2_COMPRESSED) {
177 uint64_t sz, csize_shift, csize_mask;
178
179 if (!compressed)
180 return -EOPNOTSUPP;
181
182 csize_shift = 64 - 2 - (HEADER_CLUSTER_BITS(header) - 8);
183 csize_mask = (1ULL << (HEADER_CLUSTER_BITS(header) - 8)) - 1;
184 sz = (((q >> csize_shift) & csize_mask) + 1) * 512 - (q & 511);
185 q &= ((1ULL << csize_shift) - 1);
186
187 if (compressed_size)
188 *compressed_size = sz;
189
190 *compressed = true;
191
192 } else {
193 if (compressed) {
194 *compressed = false;
195 *compressed_size = 0;
196 }
197
198 if (q & QCOW2_ZERO) {
199 /* We make no distinction between zero blocks and holes */
200 *ret = 0;
201 return 0;
202 }
203
204 q &= ~QCOW2_COPIED;
205 }
206
207 *ret = q;
208 return q > 0; /* returns positive if not a hole */
209 }
210
211 static int verify_header(const Header *header) {
212 assert(header);
213
214 if (HEADER_MAGIC(header) != QCOW2_MAGIC)
215 return -EBADMSG;
216
217 if (HEADER_VERSION(header) != 2 &&
218 HEADER_VERSION(header) != 3)
219 return -EOPNOTSUPP;
220
221 if (HEADER_CRYPT_METHOD(header) != 0)
222 return -EOPNOTSUPP;
223
224 if (HEADER_CLUSTER_BITS(header) < 9) /* 512K */
225 return -EBADMSG;
226
227 if (HEADER_CLUSTER_BITS(header) > 21) /* 2MB */
228 return -EBADMSG;
229
230 if (HEADER_SIZE(header) % HEADER_CLUSTER_SIZE(header) != 0)
231 return -EBADMSG;
232
233 if (HEADER_L1_SIZE(header) > 32*1024*1024) /* 32MB */
234 return -EBADMSG;
235
236 if (HEADER_VERSION(header) == 3) {
237
238 if (header->incompatible_features != 0)
239 return -EOPNOTSUPP;
240
241 if (HEADER_HEADER_LENGTH(header) < sizeof(Header))
242 return -EBADMSG;
243 }
244
245 return 0;
246 }
247
248 int qcow2_convert(int qcow2_fd, int raw_fd) {
249 _cleanup_free_ void *buffer1 = NULL, *buffer2 = NULL;
250 _cleanup_free_ be64_t *l1_table = NULL, *l2_table = NULL;
251 uint64_t sz, i;
252 Header header;
253 ssize_t l;
254 int r;
255
256 l = pread(qcow2_fd, &header, sizeof(header), 0);
257 if (l < 0)
258 return -errno;
259 if (l != sizeof(header))
260 return -EIO;
261
262 r = verify_header(&header);
263 if (r < 0)
264 return r;
265
266 l1_table = new(be64_t, HEADER_L1_SIZE(&header));
267 if (!l1_table)
268 return -ENOMEM;
269
270 l2_table = malloc(HEADER_CLUSTER_SIZE(&header));
271 if (!l2_table)
272 return -ENOMEM;
273
274 buffer1 = malloc(HEADER_CLUSTER_SIZE(&header));
275 if (!buffer1)
276 return -ENOMEM;
277
278 buffer2 = malloc(HEADER_CLUSTER_SIZE(&header));
279 if (!buffer2)
280 return -ENOMEM;
281
282 /* Empty the file if it exists, we rely on zero bits */
283 if (ftruncate(raw_fd, 0) < 0)
284 return -errno;
285
286 if (ftruncate(raw_fd, HEADER_SIZE(&header)) < 0)
287 return -errno;
288
289 sz = sizeof(uint64_t) * HEADER_L1_SIZE(&header);
290 l = pread(qcow2_fd, l1_table, sz, HEADER_L1_TABLE_OFFSET(&header));
291 if (l < 0)
292 return -errno;
293 if ((uint64_t) l != sz)
294 return -EIO;
295
296 for (i = 0; i < HEADER_L1_SIZE(&header); i ++) {
297 uint64_t l2_begin, j;
298
299 r = normalize_offset(&header, l1_table[i], &l2_begin, NULL, NULL);
300 if (r < 0)
301 return r;
302 if (r == 0)
303 continue;
304
305 l = pread(qcow2_fd, l2_table, HEADER_CLUSTER_SIZE(&header), l2_begin);
306 if (l < 0)
307 return -errno;
308 if ((uint64_t) l != HEADER_CLUSTER_SIZE(&header))
309 return -EIO;
310
311 for (j = 0; j < HEADER_L2_SIZE(&header); j++) {
312 uint64_t data_begin, p, compressed_size;
313 bool compressed;
314
315 p = ((i << HEADER_L2_BITS(&header)) + j) << HEADER_CLUSTER_BITS(&header);
316
317 r = normalize_offset(&header, l2_table[j], &data_begin, &compressed, &compressed_size);
318 if (r < 0)
319 return r;
320 if (r == 0)
321 continue;
322
323 if (compressed)
324 r = decompress_cluster(
325 qcow2_fd, data_begin,
326 raw_fd, p,
327 compressed_size, HEADER_CLUSTER_SIZE(&header),
328 buffer1, buffer2);
329 else
330 r = copy_cluster(
331 qcow2_fd, data_begin,
332 raw_fd, p,
333 HEADER_CLUSTER_SIZE(&header), buffer1);
334 if (r < 0)
335 return r;
336 }
337 }
338
339 return 0;
340 }
341
342 int qcow2_detect(int fd) {
343 be32_t id;
344 ssize_t l;
345
346 l = pread(fd, &id, sizeof(id), 0);
347 if (l < 0)
348 return -errno;
349 if (l != sizeof(id))
350 return -EIO;
351
352 return htobe32(QCOW2_MAGIC) == id;
353 }