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, ©_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(©_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