]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/import/qcow2-util.c
Merge pull request #7379 from yuwata/follow-up-7309
[thirdparty/systemd.git] / src / import / qcow2-util.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 This file is part of systemd.
4
5 Copyright 2015 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include <zlib.h>
22
23 #include "alloc-util.h"
24 #include "btrfs-util.h"
25 #include "qcow2-util.h"
26 #include "sparse-endian.h"
27 #include "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 (!IN_SET(HEADER_VERSION(header), 2, 3))
218 return -EOPNOTSUPP;
219
220 if (HEADER_CRYPT_METHOD(header) != 0)
221 return -EOPNOTSUPP;
222
223 if (HEADER_CLUSTER_BITS(header) < 9) /* 512K */
224 return -EBADMSG;
225
226 if (HEADER_CLUSTER_BITS(header) > 21) /* 2MB */
227 return -EBADMSG;
228
229 if (HEADER_SIZE(header) % HEADER_CLUSTER_SIZE(header) != 0)
230 return -EBADMSG;
231
232 if (HEADER_L1_SIZE(header) > 32*1024*1024) /* 32MB */
233 return -EBADMSG;
234
235 if (HEADER_VERSION(header) == 3) {
236
237 if (header->incompatible_features != 0)
238 return -EOPNOTSUPP;
239
240 if (HEADER_HEADER_LENGTH(header) < sizeof(Header))
241 return -EBADMSG;
242 }
243
244 return 0;
245 }
246
247 int qcow2_convert(int qcow2_fd, int raw_fd) {
248 _cleanup_free_ void *buffer1 = NULL, *buffer2 = NULL;
249 _cleanup_free_ be64_t *l1_table = NULL, *l2_table = NULL;
250 uint64_t sz, i;
251 Header header;
252 ssize_t l;
253 int r;
254
255 l = pread(qcow2_fd, &header, sizeof(header), 0);
256 if (l < 0)
257 return -errno;
258 if (l != sizeof(header))
259 return -EIO;
260
261 r = verify_header(&header);
262 if (r < 0)
263 return r;
264
265 l1_table = new(be64_t, HEADER_L1_SIZE(&header));
266 if (!l1_table)
267 return -ENOMEM;
268
269 l2_table = malloc(HEADER_CLUSTER_SIZE(&header));
270 if (!l2_table)
271 return -ENOMEM;
272
273 buffer1 = malloc(HEADER_CLUSTER_SIZE(&header));
274 if (!buffer1)
275 return -ENOMEM;
276
277 buffer2 = malloc(HEADER_CLUSTER_SIZE(&header));
278 if (!buffer2)
279 return -ENOMEM;
280
281 /* Empty the file if it exists, we rely on zero bits */
282 if (ftruncate(raw_fd, 0) < 0)
283 return -errno;
284
285 if (ftruncate(raw_fd, HEADER_SIZE(&header)) < 0)
286 return -errno;
287
288 sz = sizeof(uint64_t) * HEADER_L1_SIZE(&header);
289 l = pread(qcow2_fd, l1_table, sz, HEADER_L1_TABLE_OFFSET(&header));
290 if (l < 0)
291 return -errno;
292 if ((uint64_t) l != sz)
293 return -EIO;
294
295 for (i = 0; i < HEADER_L1_SIZE(&header); i ++) {
296 uint64_t l2_begin, j;
297
298 r = normalize_offset(&header, l1_table[i], &l2_begin, NULL, NULL);
299 if (r < 0)
300 return r;
301 if (r == 0)
302 continue;
303
304 l = pread(qcow2_fd, l2_table, HEADER_CLUSTER_SIZE(&header), l2_begin);
305 if (l < 0)
306 return -errno;
307 if ((uint64_t) l != HEADER_CLUSTER_SIZE(&header))
308 return -EIO;
309
310 for (j = 0; j < HEADER_L2_SIZE(&header); j++) {
311 uint64_t data_begin, p, compressed_size;
312 bool compressed;
313
314 p = ((i << HEADER_L2_BITS(&header)) + j) << HEADER_CLUSTER_BITS(&header);
315
316 r = normalize_offset(&header, l2_table[j], &data_begin, &compressed, &compressed_size);
317 if (r < 0)
318 return r;
319 if (r == 0)
320 continue;
321
322 if (compressed)
323 r = decompress_cluster(
324 qcow2_fd, data_begin,
325 raw_fd, p,
326 compressed_size, HEADER_CLUSTER_SIZE(&header),
327 buffer1, buffer2);
328 else
329 r = copy_cluster(
330 qcow2_fd, data_begin,
331 raw_fd, p,
332 HEADER_CLUSTER_SIZE(&header), buffer1);
333 if (r < 0)
334 return r;
335 }
336 }
337
338 return 0;
339 }
340
341 int qcow2_detect(int fd) {
342 be32_t id;
343 ssize_t l;
344
345 l = pread(fd, &id, sizeof(id), 0);
346 if (l < 0)
347 return -errno;
348 if (l != sizeof(id))
349 return -EIO;
350
351 return htobe32(QCOW2_MAGIC) == id;
352 }