186835cedSPrasad Joshi #include "kvm/qcow.h" 286835cedSPrasad Joshi 386835cedSPrasad Joshi #include "kvm/disk-image.h" 486835cedSPrasad Joshi #include "kvm/read-write.h" 586835cedSPrasad Joshi #include "kvm/util.h" 686835cedSPrasad Joshi 786835cedSPrasad Joshi #include <sys/types.h> 886835cedSPrasad Joshi #include <sys/stat.h> 986835cedSPrasad Joshi #include <stdbool.h> 1086835cedSPrasad Joshi #include <stdlib.h> 1186835cedSPrasad Joshi #include <string.h> 1286835cedSPrasad Joshi #include <unistd.h> 1386835cedSPrasad Joshi #include <fcntl.h> 1486835cedSPrasad Joshi 1586835cedSPrasad Joshi #include <linux/byteorder.h> 1686835cedSPrasad Joshi #include <linux/types.h> 1786835cedSPrasad Joshi 18742fce76SPrasad Joshi static inline u64 get_l1_index(struct qcow *q, u64 offset) 1986835cedSPrasad Joshi { 20ad627d62SPekka Enberg struct qcow_header *header = q->header; 2186835cedSPrasad Joshi 2286835cedSPrasad Joshi return offset >> (header->l2_bits + header->cluster_bits); 2386835cedSPrasad Joshi } 2486835cedSPrasad Joshi 25742fce76SPrasad Joshi static inline u64 get_l2_index(struct qcow *q, u64 offset) 2686835cedSPrasad Joshi { 27ad627d62SPekka Enberg struct qcow_header *header = q->header; 2886835cedSPrasad Joshi 2986835cedSPrasad Joshi return (offset >> (header->cluster_bits)) & ((1 << header->l2_bits)-1); 3086835cedSPrasad Joshi } 3186835cedSPrasad Joshi 32742fce76SPrasad Joshi static inline u64 get_cluster_offset(struct qcow *q, u64 offset) 3386835cedSPrasad Joshi { 34ad627d62SPekka Enberg struct qcow_header *header = q->header; 3586835cedSPrasad Joshi 3686835cedSPrasad Joshi return offset & ((1 << header->cluster_bits)-1); 3786835cedSPrasad Joshi } 3886835cedSPrasad Joshi 39a51948ceSPekka Enberg static ssize_t qcow1_read_cluster(struct qcow *q, u64 offset, void *dst, u32 dst_len) 4086835cedSPrasad Joshi { 41ad627d62SPekka Enberg struct qcow_header *header = q->header; 423dac48d4SPrasad Joshi struct qcow_table *table = &q->table; 43179b71f0SPekka Enberg u64 *l2_table = NULL; 44742fce76SPrasad Joshi u64 l2_table_offset; 45742fce76SPrasad Joshi u64 l2_table_size; 463dac48d4SPrasad Joshi u64 cluster_size; 47742fce76SPrasad Joshi u64 clust_offset; 48742fce76SPrasad Joshi u64 clust_start; 49a51948ceSPekka Enberg size_t length; 50742fce76SPrasad Joshi u64 l1_idx; 51742fce76SPrasad Joshi u64 l2_idx; 5286835cedSPrasad Joshi 53dae803fbSPekka Enberg cluster_size = 1 << header->cluster_bits; 5486835cedSPrasad Joshi 55c5e0624bSPrasad Joshi l1_idx = get_l1_index(q, offset); 563dac48d4SPrasad Joshi if (l1_idx >= table->table_size) 5786835cedSPrasad Joshi goto out_error; 5886835cedSPrasad Joshi 593dac48d4SPrasad Joshi clust_offset = get_cluster_offset(q, offset); 603dac48d4SPrasad Joshi if (clust_offset >= cluster_size) 613dac48d4SPrasad Joshi goto out_error; 623dac48d4SPrasad Joshi 633dac48d4SPrasad Joshi length = cluster_size - clust_offset; 643dac48d4SPrasad Joshi if (length > dst_len) 653dac48d4SPrasad Joshi length = dst_len; 663dac48d4SPrasad Joshi 67ad627d62SPekka Enberg l2_table_offset = table->l1_table[l1_idx] & ~header->oflag_mask; 6886835cedSPrasad Joshi if (!l2_table_offset) 693dac48d4SPrasad Joshi goto zero_cluster; 7086835cedSPrasad Joshi 7186835cedSPrasad Joshi l2_table_size = 1 << header->l2_bits; 72742fce76SPrasad Joshi l2_table = calloc(l2_table_size, sizeof(u64)); 7386835cedSPrasad Joshi if (!l2_table) 7486835cedSPrasad Joshi goto out_error; 7586835cedSPrasad Joshi 763dac48d4SPrasad Joshi if (pread_in_full(q->fd, l2_table, l2_table_size * sizeof(u64), 773dac48d4SPrasad Joshi l2_table_offset) < 0) 78b6edb0ecSSasha Levin goto out_error; 7986835cedSPrasad Joshi 80c5e0624bSPrasad Joshi l2_idx = get_l2_index(q, offset); 8186835cedSPrasad Joshi if (l2_idx >= l2_table_size) 82b6edb0ecSSasha Levin goto out_error; 8386835cedSPrasad Joshi 84ad627d62SPekka Enberg clust_start = be64_to_cpu(l2_table[l2_idx]) & ~header->oflag_mask; 8586835cedSPrasad Joshi if (!clust_start) 863dac48d4SPrasad Joshi goto zero_cluster; 8786835cedSPrasad Joshi 883dac48d4SPrasad Joshi if (pread_in_full(q->fd, dst, length, clust_start + clust_offset) < 0) 89b6edb0ecSSasha Levin goto out_error; 9086835cedSPrasad Joshi 91179b71f0SPekka Enberg out: 92179b71f0SPekka Enberg free(l2_table); 933dac48d4SPrasad Joshi return length; 9486835cedSPrasad Joshi 95179b71f0SPekka Enberg zero_cluster: 96179b71f0SPekka Enberg memset(dst, 0, length); 97179b71f0SPekka Enberg goto out; 98179b71f0SPekka Enberg 9986835cedSPrasad Joshi out_error: 100179b71f0SPekka Enberg length = -1; 101179b71f0SPekka Enberg goto out; 1023dac48d4SPrasad Joshi } 103b6edb0ecSSasha Levin 104*43835ac9SSasha Levin static int qcow1_read_sector(struct disk_image *disk, u64 sector, 1053fdf659dSSasha Levin void *dst, u32 dst_len) 1063dac48d4SPrasad Joshi { 107*43835ac9SSasha Levin struct qcow *q = disk->priv; 108ad627d62SPekka Enberg struct qcow_header *header = q->header; 1093dac48d4SPrasad Joshi char *buf = dst; 1103dac48d4SPrasad Joshi u64 offset; 111d8eea993SPekka Enberg u32 nr_read; 1123dac48d4SPrasad Joshi u32 nr; 1133dac48d4SPrasad Joshi 114d8eea993SPekka Enberg nr_read = 0; 115d8eea993SPekka Enberg while (nr_read < dst_len) { 1163dac48d4SPrasad Joshi offset = sector << SECTOR_SHIFT; 1173dac48d4SPrasad Joshi if (offset >= header->size) 1183dac48d4SPrasad Joshi goto out_error; 1193dac48d4SPrasad Joshi 120d8eea993SPekka Enberg nr = qcow1_read_cluster(q, offset, buf, dst_len - nr_read); 121a51948ceSPekka Enberg if (nr <= 0) 1223dac48d4SPrasad Joshi goto out_error; 1233dac48d4SPrasad Joshi 124d8eea993SPekka Enberg nr_read += nr; 1253dac48d4SPrasad Joshi buf += nr; 1263dac48d4SPrasad Joshi sector += (nr >> SECTOR_SHIFT); 1273dac48d4SPrasad Joshi } 1283dac48d4SPrasad Joshi return 0; 1293dac48d4SPrasad Joshi out_error: 13086835cedSPrasad Joshi return -1; 13186835cedSPrasad Joshi } 13286835cedSPrasad Joshi 133*43835ac9SSasha Levin static int qcow1_write_sector(struct disk_image *disk, u64 sector, void *src, u32 src_len) 13486835cedSPrasad Joshi { 13586835cedSPrasad Joshi return -1; 13686835cedSPrasad Joshi } 13786835cedSPrasad Joshi 138*43835ac9SSasha Levin static void qcow1_disk_close(struct disk_image *disk) 13986835cedSPrasad Joshi { 14086835cedSPrasad Joshi struct qcow *q; 14186835cedSPrasad Joshi 142*43835ac9SSasha Levin if (!disk) 14386835cedSPrasad Joshi return; 14486835cedSPrasad Joshi 145*43835ac9SSasha Levin q = disk->priv; 14686835cedSPrasad Joshi 1476c6f79b6SPrasad Joshi free(q->table.l1_table); 14886835cedSPrasad Joshi free(q->header); 14986835cedSPrasad Joshi free(q); 15086835cedSPrasad Joshi } 15186835cedSPrasad Joshi 15286835cedSPrasad Joshi struct disk_image_operations qcow1_disk_ops = { 15386835cedSPrasad Joshi .read_sector = qcow1_read_sector, 15486835cedSPrasad Joshi .write_sector = qcow1_write_sector, 15586835cedSPrasad Joshi .close = qcow1_disk_close 15686835cedSPrasad Joshi }; 15786835cedSPrasad Joshi 15886835cedSPrasad Joshi static int qcow_read_l1_table(struct qcow *q) 15986835cedSPrasad Joshi { 160ad627d62SPekka Enberg struct qcow_header *header = q->header; 16100adcc1bSPrasad Joshi struct qcow_table *table = &q->table; 16200adcc1bSPrasad Joshi u64 i; 16386835cedSPrasad Joshi 164ad627d62SPekka Enberg table->table_size = header->l1_size; 16586835cedSPrasad Joshi 16600adcc1bSPrasad Joshi table->l1_table = calloc(table->table_size, sizeof(u64)); 16700adcc1bSPrasad Joshi if (!table->l1_table) 16886835cedSPrasad Joshi return -1; 16986835cedSPrasad Joshi 17000adcc1bSPrasad Joshi if (pread_in_full(q->fd, table->l1_table, sizeof(u64) * 17100adcc1bSPrasad Joshi table->table_size, header->l1_table_offset) < 0) 17286835cedSPrasad Joshi return -1; 17386835cedSPrasad Joshi 17400adcc1bSPrasad Joshi for (i = 0; i < table->table_size; i++) 17500adcc1bSPrasad Joshi be64_to_cpus(&table->l1_table[i]); 17600adcc1bSPrasad Joshi 17786835cedSPrasad Joshi return 0; 17886835cedSPrasad Joshi } 17986835cedSPrasad Joshi 180ad627d62SPekka Enberg static void *qcow2_read_header(int fd) 18186835cedSPrasad Joshi { 182ad627d62SPekka Enberg struct qcow2_header_disk f_header; 183ad627d62SPekka Enberg struct qcow_header *header; 18486835cedSPrasad Joshi 185ad627d62SPekka Enberg header = malloc(sizeof(struct qcow_header)); 18686835cedSPrasad Joshi if (!header) 18786835cedSPrasad Joshi return NULL; 18886835cedSPrasad Joshi 1890657f33dSPrasad Joshi if (pread_in_full(fd, &f_header, sizeof(struct qcow2_header_disk), 0) < 0) { 1900657f33dSPrasad Joshi free(header); 19186835cedSPrasad Joshi return NULL; 1920657f33dSPrasad Joshi } 19386835cedSPrasad Joshi 194ad627d62SPekka Enberg be32_to_cpus(&f_header.magic); 195ad627d62SPekka Enberg be32_to_cpus(&f_header.version); 196ad627d62SPekka Enberg be64_to_cpus(&f_header.backing_file_offset); 197ad627d62SPekka Enberg be32_to_cpus(&f_header.backing_file_size); 198ad627d62SPekka Enberg be32_to_cpus(&f_header.cluster_bits); 199ad627d62SPekka Enberg be64_to_cpus(&f_header.size); 200ad627d62SPekka Enberg be32_to_cpus(&f_header.crypt_method); 201ad627d62SPekka Enberg be32_to_cpus(&f_header.l1_size); 202ad627d62SPekka Enberg be64_to_cpus(&f_header.l1_table_offset); 203ad627d62SPekka Enberg be64_to_cpus(&f_header.refcount_table_offset); 204ad627d62SPekka Enberg be32_to_cpus(&f_header.refcount_table_clusters); 205ad627d62SPekka Enberg be32_to_cpus(&f_header.nb_snapshots); 206ad627d62SPekka Enberg be64_to_cpus(&f_header.snapshots_offset); 207ad627d62SPekka Enberg 208ad627d62SPekka Enberg *header = (struct qcow_header) { 209ad627d62SPekka Enberg .size = f_header.size, 210ad627d62SPekka Enberg .l1_table_offset = f_header.l1_table_offset, 211ad627d62SPekka Enberg .l1_size = f_header.l1_size, 212ad627d62SPekka Enberg .cluster_bits = f_header.cluster_bits, 213ad627d62SPekka Enberg .l2_bits = f_header.cluster_bits - 3, 214ad627d62SPekka Enberg .oflag_mask = QCOW2_OFLAG_MASK, 215ad627d62SPekka Enberg }; 216ad627d62SPekka Enberg 217ad627d62SPekka Enberg return header; 218ad627d62SPekka Enberg } 219ad627d62SPekka Enberg 220ad627d62SPekka Enberg static struct disk_image *qcow2_probe(int fd) 221ad627d62SPekka Enberg { 222ad627d62SPekka Enberg struct qcow *q; 223ad627d62SPekka Enberg struct qcow_header *h; 224ad627d62SPekka Enberg struct disk_image *disk_image; 225ad627d62SPekka Enberg 226ad627d62SPekka Enberg q = calloc(1, sizeof(struct qcow)); 227ad627d62SPekka Enberg if (!q) 228ad627d62SPekka Enberg goto error; 229ad627d62SPekka Enberg 230ad627d62SPekka Enberg q->fd = fd; 231ad627d62SPekka Enberg 232ad627d62SPekka Enberg h = q->header = qcow2_read_header(fd); 233ad627d62SPekka Enberg if (!h) 234ad627d62SPekka Enberg goto error; 235ad627d62SPekka Enberg 236ad627d62SPekka Enberg if (qcow_read_l1_table(q) < 0) 237ad627d62SPekka Enberg goto error; 238ad627d62SPekka Enberg 239ad627d62SPekka Enberg disk_image = disk_image__new(fd, h->size, &qcow1_disk_ops); 240ad627d62SPekka Enberg if (!disk_image) 241ad627d62SPekka Enberg goto error; 242ad627d62SPekka Enberg disk_image->priv = q; 243ad627d62SPekka Enberg 244ad627d62SPekka Enberg return disk_image; 245ad627d62SPekka Enberg error: 246ad627d62SPekka Enberg if (!q) 247ad627d62SPekka Enberg return NULL; 248ad627d62SPekka Enberg 249ad627d62SPekka Enberg free(q->table.l1_table); 250ad627d62SPekka Enberg free(q->header); 251ad627d62SPekka Enberg free(q); 252ad627d62SPekka Enberg 253ad627d62SPekka Enberg return NULL; 254ad627d62SPekka Enberg } 255ad627d62SPekka Enberg 256ad627d62SPekka Enberg static bool qcow2_check_image(int fd) 257ad627d62SPekka Enberg { 258ad627d62SPekka Enberg struct qcow2_header_disk f_header; 259ad627d62SPekka Enberg 260ad627d62SPekka Enberg if (pread_in_full(fd, &f_header, sizeof(struct qcow2_header_disk), 0) < 0) 261ad627d62SPekka Enberg return false; 262ad627d62SPekka Enberg 263ad627d62SPekka Enberg be32_to_cpus(&f_header.magic); 264ad627d62SPekka Enberg be32_to_cpus(&f_header.version); 265ad627d62SPekka Enberg 266ad627d62SPekka Enberg if (f_header.magic != QCOW_MAGIC) 267ad627d62SPekka Enberg return false; 268ad627d62SPekka Enberg 269ad627d62SPekka Enberg if (f_header.version != QCOW2_VERSION) 270ad627d62SPekka Enberg return false; 271ad627d62SPekka Enberg 272ad627d62SPekka Enberg return true; 273ad627d62SPekka Enberg } 274ad627d62SPekka Enberg 275ad627d62SPekka Enberg static void *qcow1_read_header(int fd) 276ad627d62SPekka Enberg { 277ad627d62SPekka Enberg struct qcow1_header_disk f_header; 278ad627d62SPekka Enberg struct qcow_header *header; 279ad627d62SPekka Enberg 280ad627d62SPekka Enberg header = malloc(sizeof(struct qcow_header)); 281ad627d62SPekka Enberg if (!header) 282ad627d62SPekka Enberg return NULL; 283ad627d62SPekka Enberg 284d39cefd2SSasha Levin if (pread_in_full(fd, &f_header, sizeof(struct qcow1_header_disk), 0) < 0) { 285d39cefd2SSasha Levin free(header); 286ad627d62SPekka Enberg return NULL; 287d39cefd2SSasha Levin } 288ad627d62SPekka Enberg 289ad627d62SPekka Enberg be32_to_cpus(&f_header.magic); 290ad627d62SPekka Enberg be32_to_cpus(&f_header.version); 291ad627d62SPekka Enberg be64_to_cpus(&f_header.backing_file_offset); 292ad627d62SPekka Enberg be32_to_cpus(&f_header.backing_file_size); 293ad627d62SPekka Enberg be32_to_cpus(&f_header.mtime); 294ad627d62SPekka Enberg be64_to_cpus(&f_header.size); 295ad627d62SPekka Enberg be32_to_cpus(&f_header.crypt_method); 296ad627d62SPekka Enberg be64_to_cpus(&f_header.l1_table_offset); 297ad627d62SPekka Enberg 298ad627d62SPekka Enberg *header = (struct qcow_header) { 299ad627d62SPekka Enberg .size = f_header.size, 300ad627d62SPekka Enberg .l1_table_offset = f_header.l1_table_offset, 301ad627d62SPekka Enberg .l1_size = f_header.size / ((1 << f_header.l2_bits) * (1 << f_header.cluster_bits)), 302ad627d62SPekka Enberg .cluster_bits = f_header.cluster_bits, 303ad627d62SPekka Enberg .l2_bits = f_header.l2_bits, 304ad627d62SPekka Enberg .oflag_mask = QCOW1_OFLAG_MASK, 305ad627d62SPekka Enberg }; 30686835cedSPrasad Joshi 30786835cedSPrasad Joshi return header; 30886835cedSPrasad Joshi } 30986835cedSPrasad Joshi 31086835cedSPrasad Joshi static struct disk_image *qcow1_probe(int fd) 31186835cedSPrasad Joshi { 31286835cedSPrasad Joshi struct qcow *q; 313ad627d62SPekka Enberg struct qcow_header *h; 31486835cedSPrasad Joshi struct disk_image *disk_image; 31586835cedSPrasad Joshi 31686835cedSPrasad Joshi q = calloc(1, sizeof(struct qcow)); 31786835cedSPrasad Joshi if (!q) 31886835cedSPrasad Joshi goto error; 31986835cedSPrasad Joshi 32086835cedSPrasad Joshi q->fd = fd; 32186835cedSPrasad Joshi 32286835cedSPrasad Joshi h = q->header = qcow1_read_header(fd); 32386835cedSPrasad Joshi if (!h) 32486835cedSPrasad Joshi goto error; 32586835cedSPrasad Joshi 32686835cedSPrasad Joshi if (qcow_read_l1_table(q) < 0) 32786835cedSPrasad Joshi goto error; 32886835cedSPrasad Joshi 32986835cedSPrasad Joshi disk_image = disk_image__new(fd, h->size, &qcow1_disk_ops); 33086835cedSPrasad Joshi if (!disk_image) 33186835cedSPrasad Joshi goto error; 33286835cedSPrasad Joshi disk_image->priv = q; 33386835cedSPrasad Joshi 33486835cedSPrasad Joshi return disk_image; 33586835cedSPrasad Joshi error: 33686835cedSPrasad Joshi if (!q) 33786835cedSPrasad Joshi return NULL; 33886835cedSPrasad Joshi 3396c6f79b6SPrasad Joshi free(q->table.l1_table); 34086835cedSPrasad Joshi free(q->header); 34186835cedSPrasad Joshi free(q); 34286835cedSPrasad Joshi 34386835cedSPrasad Joshi return NULL; 34486835cedSPrasad Joshi } 34586835cedSPrasad Joshi 346ad627d62SPekka Enberg static bool qcow1_check_image(int fd) 34786835cedSPrasad Joshi { 348ad627d62SPekka Enberg struct qcow1_header_disk f_header; 34986835cedSPrasad Joshi 350ad627d62SPekka Enberg if (pread_in_full(fd, &f_header, sizeof(struct qcow1_header_disk), 0) < 0) 351ad627d62SPekka Enberg return false; 35286835cedSPrasad Joshi 353ad627d62SPekka Enberg be32_to_cpus(&f_header.magic); 354ad627d62SPekka Enberg be32_to_cpus(&f_header.version); 35586835cedSPrasad Joshi 356ad627d62SPekka Enberg if (f_header.magic != QCOW_MAGIC) 357ad627d62SPekka Enberg return false; 35886835cedSPrasad Joshi 359ad627d62SPekka Enberg if (f_header.version != QCOW1_VERSION) 360ad627d62SPekka Enberg return false; 36186835cedSPrasad Joshi 362ad627d62SPekka Enberg return true; 36386835cedSPrasad Joshi } 36486835cedSPrasad Joshi 36586835cedSPrasad Joshi struct disk_image *qcow_probe(int fd) 36686835cedSPrasad Joshi { 367ad627d62SPekka Enberg if (qcow1_check_image(fd)) 36886835cedSPrasad Joshi return qcow1_probe(fd); 369ad627d62SPekka Enberg 370ad627d62SPekka Enberg if (qcow2_check_image(fd)) 371ad627d62SPekka Enberg return qcow2_probe(fd); 372ad627d62SPekka Enberg 373ad627d62SPekka Enberg return NULL; 37486835cedSPrasad Joshi } 375