qcow2.c revision 00eb0eee0addfd3b7ede98b85e00dff1547838a0
15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)/*
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * qcow2.c --- Functions to generate qcow2 formatted disk images.  This
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * format is used originally by QEMU for virtual machines, and stores the
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * filesystem data on disk in a packed format to avoid creating sparse
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * image files that need lots of seeking to read and write.
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *
7a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * The qcow2 format supports zlib compression, but that is not yet
8a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * implemented.
9a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) *
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * It is possible to directly mount a qcow2 image using qemu-nbd:
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * [root]# modprobe nbd max_part=63
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * [root]# qemu-nbd -c /dev/nbd0 image.img
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * [root]# mount /dev/nbd0p1 /mnt/qemu
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Format details at http://people.gnome.org/~markmc/qcow-image-format.html
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Copyright (C) 2010 Red Hat, Inc., Lukas Czerner <lczerner@redhat.com>
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * %Begin-Header%
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * This file may be redistributed under the terms of the GNU Public
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * License.
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * %End-Header%
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define _LARGEFILE_SOURCE
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define _LARGEFILE64_SOURCE
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "config.h"
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <fcntl.h>
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <grp.h>
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <pwd.h>
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <stdio.h>
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifdef HAVE_STDLIB_H
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <stdlib.h>
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <string.h>
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <time.h>
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <unistd.h>
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <fcntl.h>
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <errno.h>
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <sys/stat.h>
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <sys/types.h>
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <assert.h>
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ext2fs/ext2fs.h"
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "qcow2.h"
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/* Functions for converting qcow2 image into raw image */
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)struct ext2_qcow2_hdr *qcow2_read_header(int fd)
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	void *buffer = NULL;
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	struct ext2_qcow2_hdr *hdr = NULL;
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	size_t size;
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	errcode_t ret;
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	ret = ext2fs_get_mem(sizeof(struct ext2_qcow2_hdr), &buffer);
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	if (ret)
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		return NULL;
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	memset(buffer, 0, sizeof(struct ext2_qcow2_hdr));
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	if (ext2fs_llseek(fd, 0, SEEK_SET < 0))
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		return NULL;
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	size = read(fd, buffer, sizeof(struct ext2_qcow2_hdr));
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	if (size != sizeof(struct ext2_qcow2_hdr)) {
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		ext2fs_free_mem(&buffer);
6958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		return NULL;
7058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	}
7158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
7258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	hdr = (struct ext2_qcow2_hdr *)(buffer);
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	if ((ext2fs_be32_to_cpu(hdr->magic) != QCOW_MAGIC) ||
7558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	    (ext2fs_be32_to_cpu(hdr->version) != 2)) {
7658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		ext2fs_free_mem(&hdr);
7758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		return NULL;
7858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	}
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	return hdr;
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
8358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)static int qcow2_read_l1_table(struct ext2_qcow2_image *img)
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	int fd = img->fd;
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	size_t size, l1_size = img->l1_size * sizeof(blk64_t);
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	blk64_t *table;
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	errcode_t ret;
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	ret = ext2fs_get_memzero(l1_size, &table);
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	if (ret)
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		return ret;
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	if (ext2fs_llseek(fd, img->l1_offset, SEEK_SET) < 0)
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		return errno;
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	size = read(fd, table, l1_size);
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	if (size != l1_size) {
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		ext2fs_free_mem(&table);
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		return errno;
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	}
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	img->l1_table = table;
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	return 0;
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static int qcow2_read_l2_table(struct ext2_qcow2_image *img,
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			       ext2_off64_t offset, blk64_t **l2_table)
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	int fd = img->fd;
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	size_t size;
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	assert(*l2_table);
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	if (ext2fs_llseek(fd, offset, SEEK_SET) < 0)
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		return errno;
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	size = read(fd, *l2_table, img->cluster_size);
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	if (size != img->cluster_size)
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		return errno;
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	return 0;
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static int qcow2_copy_data(int fdin, int fdout, ext2_off64_t off_in,
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			   ext2_off64_t off_out, void *buf, size_t count)
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	size_t size;
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	assert(buf);
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	if (ext2fs_llseek(fdout, off_out, SEEK_SET) < 0)
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		return errno;
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	if (ext2fs_llseek(fdin, off_in, SEEK_SET) < 0)
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		return errno;
138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	size = read(fdin, buf, count);
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	if (size != count)
141116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch		return errno;
142116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
143116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch	size = write(fdout, buf, count);
144116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch	if (size != count)
145116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch		return errno;
146116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
147116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch	return 0;
148116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
149116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
150116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
151116680a4aac90f2aa7413d9095a592090648e557Ben Murdochint qcow2_write_raw_image(int qcow2_fd, int raw_fd,
152116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch			      struct ext2_qcow2_hdr *hdr)
153116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch{
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	struct ext2_qcow2_image img;
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	errcode_t ret = 0;
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	unsigned int l1_index, l2_index;
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	ext2_off64_t offset;
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	blk64_t *l1_table, *l2_table = NULL;
159	void *copy_buf = NULL;
160	size_t size;
161
162	if (hdr->crypt_method)
163		return -QCOW_ENCRYPTED;
164
165	img.fd = qcow2_fd;
166	img.hdr = hdr;
167	img.l2_cache = NULL;
168	img.l1_table = NULL;
169	img.cluster_bits = ext2fs_be32_to_cpu(hdr->cluster_bits);
170	img.cluster_size = 1 << img.cluster_bits;
171	img.l1_size = ext2fs_be32_to_cpu(hdr->l1_size);
172	img.l1_offset = ext2fs_be64_to_cpu(hdr->l1_table_offset);
173	img.l2_size = 1 << (img.cluster_bits - 3);
174	img.image_size = ext2fs_be64_to_cpu(hdr->size);
175
176
177	ret = ext2fs_get_memzero(img.cluster_size, &l2_table);
178	if (ret)
179		goto out;
180
181	ret = ext2fs_get_memzero(1 << img.cluster_bits, &copy_buf);
182	if (ret)
183		goto out;
184
185	if (ext2fs_llseek(raw_fd, 0, SEEK_SET) < 0) {
186		ret = errno;
187		goto out;
188	}
189
190	ret = qcow2_read_l1_table(&img);
191	if (ret)
192		goto out;
193
194	l1_table = img.l1_table;
195	/* Walk through l1 table */
196	for (l1_index = 0; l1_index < img.l1_size; l1_index++) {
197		ext2_off64_t off_out;
198
199		offset = ext2fs_be64_to_cpu(l1_table[l1_index]) &
200			 ~QCOW_OFLAG_COPIED;
201
202		if ((offset > img.image_size) ||
203		    (offset <= 0))
204			continue;
205
206		if (offset & QCOW_OFLAG_COMPRESSED) {
207			ret = -QCOW_COMPRESSED;
208			goto out;
209		}
210
211		ret = qcow2_read_l2_table(&img, offset, &l2_table);
212		if (ret)
213			break;
214
215		/* Walk through l2 table and copy data blocks into raw image */
216		for (l2_index = 0; l2_index < img.l2_size; l2_index++) {
217			offset = ext2fs_be64_to_cpu(l2_table[l2_index]) &
218				 ~QCOW_OFLAG_COPIED;
219
220			if (offset == 0)
221				continue;
222
223			off_out = (l1_index * img.l2_size) +
224				  l2_index;
225			off_out <<= img.cluster_bits;
226			ret = qcow2_copy_data(qcow2_fd, raw_fd, offset,
227					off_out, copy_buf, img.cluster_size);
228			if (ret)
229				goto out;
230		}
231	}
232
233	/* Resize the output image to the filesystem size */
234	if (ext2fs_llseek(raw_fd, img.image_size - 1, SEEK_SET) < 0)
235		return errno;
236
237	((char *)copy_buf)[0] = 0;
238	size = write(raw_fd, copy_buf, 1);
239	if (size != 1)
240		return errno;
241
242out:
243	if (copy_buf)
244		ext2fs_free_mem(&copy_buf);
245	if (img.l1_table)
246		ext2fs_free_mem(&img.l1_table);
247	if (l2_table)
248		ext2fs_free_mem(&l2_table);
249	return ret;
250}
251