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> 17*865c675fSPrasad Joshi #include <linux/kernel.h> 1886835cedSPrasad Joshi 19742fce76SPrasad Joshi static inline u64 get_l1_index(struct qcow *q, u64 offset) 2086835cedSPrasad Joshi { 21ad627d62SPekka Enberg struct qcow_header *header = q->header; 2286835cedSPrasad Joshi 2386835cedSPrasad Joshi return offset >> (header->l2_bits + header->cluster_bits); 2486835cedSPrasad Joshi } 2586835cedSPrasad Joshi 26742fce76SPrasad Joshi static inline u64 get_l2_index(struct qcow *q, u64 offset) 2786835cedSPrasad Joshi { 28ad627d62SPekka Enberg struct qcow_header *header = q->header; 2986835cedSPrasad Joshi 3086835cedSPrasad Joshi return (offset >> (header->cluster_bits)) & ((1 << header->l2_bits)-1); 3186835cedSPrasad Joshi } 3286835cedSPrasad Joshi 33742fce76SPrasad Joshi static inline u64 get_cluster_offset(struct qcow *q, u64 offset) 3486835cedSPrasad Joshi { 35ad627d62SPekka Enberg struct qcow_header *header = q->header; 3686835cedSPrasad Joshi 3786835cedSPrasad Joshi return offset & ((1 << header->cluster_bits)-1); 3886835cedSPrasad Joshi } 3986835cedSPrasad Joshi 40a51948ceSPekka Enberg static ssize_t qcow1_read_cluster(struct qcow *q, u64 offset, void *dst, u32 dst_len) 4186835cedSPrasad Joshi { 42ad627d62SPekka Enberg struct qcow_header *header = q->header; 433dac48d4SPrasad Joshi struct qcow_table *table = &q->table; 44179b71f0SPekka Enberg u64 *l2_table = NULL; 45742fce76SPrasad Joshi u64 l2_table_offset; 46742fce76SPrasad Joshi u64 l2_table_size; 473dac48d4SPrasad Joshi u64 cluster_size; 48742fce76SPrasad Joshi u64 clust_offset; 49742fce76SPrasad Joshi u64 clust_start; 50a51948ceSPekka Enberg size_t length; 51742fce76SPrasad Joshi u64 l1_idx; 52742fce76SPrasad Joshi u64 l2_idx; 5386835cedSPrasad Joshi 54dae803fbSPekka Enberg cluster_size = 1 << header->cluster_bits; 5586835cedSPrasad Joshi 56c5e0624bSPrasad Joshi l1_idx = get_l1_index(q, offset); 573dac48d4SPrasad Joshi if (l1_idx >= table->table_size) 5886835cedSPrasad Joshi goto out_error; 5986835cedSPrasad Joshi 603dac48d4SPrasad Joshi clust_offset = get_cluster_offset(q, offset); 613dac48d4SPrasad Joshi if (clust_offset >= cluster_size) 623dac48d4SPrasad Joshi goto out_error; 633dac48d4SPrasad Joshi 643dac48d4SPrasad Joshi length = cluster_size - clust_offset; 653dac48d4SPrasad Joshi if (length > dst_len) 663dac48d4SPrasad Joshi length = dst_len; 673dac48d4SPrasad Joshi 68ad627d62SPekka Enberg l2_table_offset = table->l1_table[l1_idx] & ~header->oflag_mask; 6986835cedSPrasad Joshi if (!l2_table_offset) 703dac48d4SPrasad Joshi goto zero_cluster; 7186835cedSPrasad Joshi 7286835cedSPrasad Joshi l2_table_size = 1 << header->l2_bits; 73742fce76SPrasad Joshi l2_table = calloc(l2_table_size, sizeof(u64)); 7486835cedSPrasad Joshi if (!l2_table) 7586835cedSPrasad Joshi goto out_error; 7686835cedSPrasad Joshi 773dac48d4SPrasad Joshi if (pread_in_full(q->fd, l2_table, l2_table_size * sizeof(u64), 783dac48d4SPrasad Joshi l2_table_offset) < 0) 79b6edb0ecSSasha Levin goto out_error; 8086835cedSPrasad Joshi 81c5e0624bSPrasad Joshi l2_idx = get_l2_index(q, offset); 8286835cedSPrasad Joshi if (l2_idx >= l2_table_size) 83b6edb0ecSSasha Levin goto out_error; 8486835cedSPrasad Joshi 85ad627d62SPekka Enberg clust_start = be64_to_cpu(l2_table[l2_idx]) & ~header->oflag_mask; 8686835cedSPrasad Joshi if (!clust_start) 873dac48d4SPrasad Joshi goto zero_cluster; 8886835cedSPrasad Joshi 893dac48d4SPrasad Joshi if (pread_in_full(q->fd, dst, length, clust_start + clust_offset) < 0) 90b6edb0ecSSasha Levin goto out_error; 9186835cedSPrasad Joshi 92179b71f0SPekka Enberg out: 93179b71f0SPekka Enberg free(l2_table); 943dac48d4SPrasad Joshi return length; 9586835cedSPrasad Joshi 96179b71f0SPekka Enberg zero_cluster: 97179b71f0SPekka Enberg memset(dst, 0, length); 98179b71f0SPekka Enberg goto out; 99179b71f0SPekka Enberg 10086835cedSPrasad Joshi out_error: 101179b71f0SPekka Enberg length = -1; 102179b71f0SPekka Enberg goto out; 1033dac48d4SPrasad Joshi } 104b6edb0ecSSasha Levin 10543835ac9SSasha Levin static int qcow1_read_sector(struct disk_image *disk, u64 sector, 1063fdf659dSSasha Levin void *dst, u32 dst_len) 1073dac48d4SPrasad Joshi { 10843835ac9SSasha Levin struct qcow *q = disk->priv; 109ad627d62SPekka Enberg struct qcow_header *header = q->header; 1103dac48d4SPrasad Joshi char *buf = dst; 1113dac48d4SPrasad Joshi u64 offset; 112d8eea993SPekka Enberg u32 nr_read; 1133dac48d4SPrasad Joshi u32 nr; 1143dac48d4SPrasad Joshi 115d8eea993SPekka Enberg nr_read = 0; 116d8eea993SPekka Enberg while (nr_read < dst_len) { 1173dac48d4SPrasad Joshi offset = sector << SECTOR_SHIFT; 1183dac48d4SPrasad Joshi if (offset >= header->size) 1193dac48d4SPrasad Joshi goto out_error; 1203dac48d4SPrasad Joshi 121d8eea993SPekka Enberg nr = qcow1_read_cluster(q, offset, buf, dst_len - nr_read); 122a51948ceSPekka Enberg if (nr <= 0) 1233dac48d4SPrasad Joshi goto out_error; 1243dac48d4SPrasad Joshi 125d8eea993SPekka Enberg nr_read += nr; 1263dac48d4SPrasad Joshi buf += nr; 1273dac48d4SPrasad Joshi sector += (nr >> SECTOR_SHIFT); 1283dac48d4SPrasad Joshi } 1293dac48d4SPrasad Joshi return 0; 1303dac48d4SPrasad Joshi out_error: 13186835cedSPrasad Joshi return -1; 13286835cedSPrasad Joshi } 13386835cedSPrasad Joshi 134*865c675fSPrasad Joshi static inline u64 file_size(int fd) 135*865c675fSPrasad Joshi { 136*865c675fSPrasad Joshi struct stat st; 137*865c675fSPrasad Joshi if (fstat(fd, &st) < 0) 138*865c675fSPrasad Joshi return 0; 139*865c675fSPrasad Joshi return st.st_size; 140*865c675fSPrasad Joshi } 141*865c675fSPrasad Joshi 142*865c675fSPrasad Joshi static inline int pwrite_sync(int fd, void *buf, size_t count, off_t offset) 143*865c675fSPrasad Joshi { 144*865c675fSPrasad Joshi if (pwrite_in_full(fd, buf, count, offset) < 0) 145*865c675fSPrasad Joshi return -1; 146*865c675fSPrasad Joshi if (sync_file_range(fd, offset, count, 147*865c675fSPrasad Joshi SYNC_FILE_RANGE_WAIT_BEFORE | 148*865c675fSPrasad Joshi SYNC_FILE_RANGE_WRITE) < 0) 149*865c675fSPrasad Joshi return -1; 150*865c675fSPrasad Joshi return 0; 151*865c675fSPrasad Joshi } 152*865c675fSPrasad Joshi 153*865c675fSPrasad Joshi /* Writes a level 2 table at the end of the file. */ 154*865c675fSPrasad Joshi static u64 qcow1_write_l2_table(struct qcow *q, u64 *table) 155*865c675fSPrasad Joshi { 156*865c675fSPrasad Joshi struct qcow_header *header = q->header; 157*865c675fSPrasad Joshi u64 sz; 158*865c675fSPrasad Joshi u64 clust_sz; 159*865c675fSPrasad Joshi u64 off; 160*865c675fSPrasad Joshi u64 f_sz; 161*865c675fSPrasad Joshi 162*865c675fSPrasad Joshi f_sz = file_size(q->fd); 163*865c675fSPrasad Joshi if (!f_sz) 164*865c675fSPrasad Joshi return 0; 165*865c675fSPrasad Joshi 166*865c675fSPrasad Joshi sz = 1 << header->l2_bits; 167*865c675fSPrasad Joshi clust_sz = 1 << header->cluster_bits; 168*865c675fSPrasad Joshi off = ALIGN(f_sz, clust_sz); 169*865c675fSPrasad Joshi 170*865c675fSPrasad Joshi if (pwrite_sync(q->fd, table, sz * sizeof(u64), off) < 0) 171*865c675fSPrasad Joshi return 0; 172*865c675fSPrasad Joshi return off; 173*865c675fSPrasad Joshi } 174*865c675fSPrasad Joshi 175*865c675fSPrasad Joshi /* 176*865c675fSPrasad Joshi * QCOW file might grow during a write operation. Not only data but metadata is 177*865c675fSPrasad Joshi * also written at the end of the file. Therefore it is necessary to ensure 178*865c675fSPrasad Joshi * every write is committed to disk. Hence we use uses pwrite_sync() to 179*865c675fSPrasad Joshi * synchronize the in-core state of QCOW image to disk. 180*865c675fSPrasad Joshi * 181*865c675fSPrasad Joshi * We also try to restore the image to a consistent state if the metdata 182*865c675fSPrasad Joshi * operation fails. The two metadat operations are: level 1 and level 2 table 183*865c675fSPrasad Joshi * update. If either of them fails the image is truncated to a consistent state. 184*865c675fSPrasad Joshi */ 185*865c675fSPrasad Joshi static ssize_t qcow1_write_cluster(struct qcow *q, u64 offset, void *buf, u32 src_len) 186*865c675fSPrasad Joshi { 187*865c675fSPrasad Joshi struct qcow_header *header = q->header; 188*865c675fSPrasad Joshi struct qcow_table *table = &q->table; 189*865c675fSPrasad Joshi 190*865c675fSPrasad Joshi u64 l2t_sz; 191*865c675fSPrasad Joshi u64 clust_sz; 192*865c675fSPrasad Joshi u64 l1t_idx; 193*865c675fSPrasad Joshi u64 l2t_idx; 194*865c675fSPrasad Joshi u64 clust_off; 195*865c675fSPrasad Joshi u64 len; 196*865c675fSPrasad Joshi u64 *l2t; 197*865c675fSPrasad Joshi u64 f_sz; 198*865c675fSPrasad Joshi u64 l2t_off; 199*865c675fSPrasad Joshi u64 t; 200*865c675fSPrasad Joshi u64 clust_start; 201*865c675fSPrasad Joshi bool update_meta = false; 202*865c675fSPrasad Joshi 203*865c675fSPrasad Joshi l2t_sz = 1 << header->l2_bits; 204*865c675fSPrasad Joshi clust_sz = 1 << header->cluster_bits; 205*865c675fSPrasad Joshi 206*865c675fSPrasad Joshi l1t_idx = get_l1_index(q, offset); 207*865c675fSPrasad Joshi if (l1t_idx >= table->table_size) 208*865c675fSPrasad Joshi goto error; 209*865c675fSPrasad Joshi 210*865c675fSPrasad Joshi l2t_idx = get_l2_index(q, offset); 211*865c675fSPrasad Joshi if (l2t_idx >= l2t_sz) 212*865c675fSPrasad Joshi goto error; 213*865c675fSPrasad Joshi 214*865c675fSPrasad Joshi clust_off = get_cluster_offset(q, offset); 215*865c675fSPrasad Joshi if (clust_off >= clust_sz) 216*865c675fSPrasad Joshi goto error; 217*865c675fSPrasad Joshi 218*865c675fSPrasad Joshi len = clust_sz - clust_off; 219*865c675fSPrasad Joshi if (len > src_len) 220*865c675fSPrasad Joshi len = src_len; 221*865c675fSPrasad Joshi 222*865c675fSPrasad Joshi l2t = calloc(l2t_sz, sizeof(u64)); 223*865c675fSPrasad Joshi if (!l2t) 224*865c675fSPrasad Joshi goto error; 225*865c675fSPrasad Joshi 226*865c675fSPrasad Joshi l2t_off = table->l1_table[l1t_idx] & ~header->oflag_mask; 227*865c675fSPrasad Joshi if (l2t_off) { 228*865c675fSPrasad Joshi if (pread_in_full(q->fd, l2t, l2t_sz * sizeof(u64), l2t_off) < 0) 229*865c675fSPrasad Joshi goto free_l2; 230*865c675fSPrasad Joshi } else { 231*865c675fSPrasad Joshi /* capture the state of the consistent QCOW image */ 232*865c675fSPrasad Joshi f_sz = file_size(q->fd); 233*865c675fSPrasad Joshi if (!f_sz) 234*865c675fSPrasad Joshi goto free_l2; 235*865c675fSPrasad Joshi 236*865c675fSPrasad Joshi /* Write the l2 table of 0's at the end of the file */ 237*865c675fSPrasad Joshi l2t_off = qcow1_write_l2_table(q, l2t); 238*865c675fSPrasad Joshi if (!l2t_off) 239*865c675fSPrasad Joshi goto free_l2; 240*865c675fSPrasad Joshi 241*865c675fSPrasad Joshi /* Metadata update: update on disk level 1 table */ 242*865c675fSPrasad Joshi t = cpu_to_be64(l2t_off); 243*865c675fSPrasad Joshi if (pwrite_sync(q->fd, &t, sizeof(t), header->l1_table_offset + 244*865c675fSPrasad Joshi l1t_idx * sizeof(u64)) < 0) { 245*865c675fSPrasad Joshi /* restore file to consistent state */ 246*865c675fSPrasad Joshi if (ftruncate(q->fd, f_sz) < 0) 247*865c675fSPrasad Joshi goto free_l2; 248*865c675fSPrasad Joshi goto free_l2; 249*865c675fSPrasad Joshi } 250*865c675fSPrasad Joshi 251*865c675fSPrasad Joshi /* update the in-core entry */ 252*865c675fSPrasad Joshi table->l1_table[l1t_idx] = l2t_off; 253*865c675fSPrasad Joshi } 254*865c675fSPrasad Joshi 255*865c675fSPrasad Joshi /* capture the state of the consistent QCOW image */ 256*865c675fSPrasad Joshi f_sz = file_size(q->fd); 257*865c675fSPrasad Joshi if (!f_sz) 258*865c675fSPrasad Joshi goto free_l2; 259*865c675fSPrasad Joshi 260*865c675fSPrasad Joshi clust_start = be64_to_cpu(l2t[l2t_idx]) & ~header->oflag_mask; 261*865c675fSPrasad Joshi free(l2t); 262*865c675fSPrasad Joshi if (!clust_start) { 263*865c675fSPrasad Joshi clust_start = ALIGN(f_sz, clust_sz); 264*865c675fSPrasad Joshi update_meta = true; 265*865c675fSPrasad Joshi } 266*865c675fSPrasad Joshi 267*865c675fSPrasad Joshi /* write actual data */ 268*865c675fSPrasad Joshi if (pwrite_in_full(q->fd, buf, len, clust_start + clust_off) < 0) 269*865c675fSPrasad Joshi goto error; 270*865c675fSPrasad Joshi 271*865c675fSPrasad Joshi if (update_meta) { 272*865c675fSPrasad Joshi t = cpu_to_be64(clust_start); 273*865c675fSPrasad Joshi if (pwrite_sync(q->fd, &t, sizeof(t), l2t_off + 274*865c675fSPrasad Joshi l2t_idx * sizeof(u64)) < 0) { 275*865c675fSPrasad Joshi /* restore the file to consistent state */ 276*865c675fSPrasad Joshi if (ftruncate(q->fd, f_sz) < 0) 277*865c675fSPrasad Joshi goto error; 278*865c675fSPrasad Joshi goto error; 279*865c675fSPrasad Joshi } 280*865c675fSPrasad Joshi } 281*865c675fSPrasad Joshi return len; 282*865c675fSPrasad Joshi free_l2: 283*865c675fSPrasad Joshi free(l2t); 284*865c675fSPrasad Joshi error: 285*865c675fSPrasad Joshi return -1; 286*865c675fSPrasad Joshi } 287*865c675fSPrasad Joshi 28843835ac9SSasha Levin static int qcow1_write_sector(struct disk_image *disk, u64 sector, void *src, u32 src_len) 28986835cedSPrasad Joshi { 290*865c675fSPrasad Joshi struct qcow *q = disk->priv; 291*865c675fSPrasad Joshi struct qcow_header *header = q->header; 292*865c675fSPrasad Joshi char *buf = src; 293*865c675fSPrasad Joshi ssize_t nr_write; 294*865c675fSPrasad Joshi u64 offset; 295*865c675fSPrasad Joshi ssize_t nr; 296*865c675fSPrasad Joshi 297*865c675fSPrasad Joshi nr_write = 0; 298*865c675fSPrasad Joshi offset = sector << SECTOR_SHIFT; 299*865c675fSPrasad Joshi while (nr_write < src_len) { 300*865c675fSPrasad Joshi if (offset >= header->size) 301*865c675fSPrasad Joshi goto error; 302*865c675fSPrasad Joshi 303*865c675fSPrasad Joshi nr = qcow1_write_cluster(q, offset, buf, src_len - nr_write); 304*865c675fSPrasad Joshi if (nr < 0) 305*865c675fSPrasad Joshi goto error; 306*865c675fSPrasad Joshi 307*865c675fSPrasad Joshi nr_write += nr; 308*865c675fSPrasad Joshi buf += nr; 309*865c675fSPrasad Joshi offset += nr; 310*865c675fSPrasad Joshi } 311*865c675fSPrasad Joshi return 0; 312*865c675fSPrasad Joshi error: 31386835cedSPrasad Joshi return -1; 31486835cedSPrasad Joshi } 31586835cedSPrasad Joshi 31643835ac9SSasha Levin static void qcow1_disk_close(struct disk_image *disk) 31786835cedSPrasad Joshi { 31886835cedSPrasad Joshi struct qcow *q; 31986835cedSPrasad Joshi 32043835ac9SSasha Levin if (!disk) 32186835cedSPrasad Joshi return; 32286835cedSPrasad Joshi 32343835ac9SSasha Levin q = disk->priv; 32486835cedSPrasad Joshi 3256c6f79b6SPrasad Joshi free(q->table.l1_table); 32686835cedSPrasad Joshi free(q->header); 32786835cedSPrasad Joshi free(q); 32886835cedSPrasad Joshi } 32986835cedSPrasad Joshi 33086835cedSPrasad Joshi struct disk_image_operations qcow1_disk_ops = { 33186835cedSPrasad Joshi .read_sector = qcow1_read_sector, 33286835cedSPrasad Joshi .write_sector = qcow1_write_sector, 33386835cedSPrasad Joshi .close = qcow1_disk_close 33486835cedSPrasad Joshi }; 33586835cedSPrasad Joshi 33686835cedSPrasad Joshi static int qcow_read_l1_table(struct qcow *q) 33786835cedSPrasad Joshi { 338ad627d62SPekka Enberg struct qcow_header *header = q->header; 33900adcc1bSPrasad Joshi struct qcow_table *table = &q->table; 34000adcc1bSPrasad Joshi u64 i; 34186835cedSPrasad Joshi 342ad627d62SPekka Enberg table->table_size = header->l1_size; 34386835cedSPrasad Joshi 34400adcc1bSPrasad Joshi table->l1_table = calloc(table->table_size, sizeof(u64)); 34500adcc1bSPrasad Joshi if (!table->l1_table) 34686835cedSPrasad Joshi return -1; 34786835cedSPrasad Joshi 34800adcc1bSPrasad Joshi if (pread_in_full(q->fd, table->l1_table, sizeof(u64) * 34900adcc1bSPrasad Joshi table->table_size, header->l1_table_offset) < 0) 35086835cedSPrasad Joshi return -1; 35186835cedSPrasad Joshi 35200adcc1bSPrasad Joshi for (i = 0; i < table->table_size; i++) 35300adcc1bSPrasad Joshi be64_to_cpus(&table->l1_table[i]); 35400adcc1bSPrasad Joshi 35586835cedSPrasad Joshi return 0; 35686835cedSPrasad Joshi } 35786835cedSPrasad Joshi 358ad627d62SPekka Enberg static void *qcow2_read_header(int fd) 35986835cedSPrasad Joshi { 360ad627d62SPekka Enberg struct qcow2_header_disk f_header; 361ad627d62SPekka Enberg struct qcow_header *header; 36286835cedSPrasad Joshi 363ad627d62SPekka Enberg header = malloc(sizeof(struct qcow_header)); 36486835cedSPrasad Joshi if (!header) 36586835cedSPrasad Joshi return NULL; 36686835cedSPrasad Joshi 3670657f33dSPrasad Joshi if (pread_in_full(fd, &f_header, sizeof(struct qcow2_header_disk), 0) < 0) { 3680657f33dSPrasad Joshi free(header); 36986835cedSPrasad Joshi return NULL; 3700657f33dSPrasad Joshi } 37186835cedSPrasad Joshi 372ad627d62SPekka Enberg be32_to_cpus(&f_header.magic); 373ad627d62SPekka Enberg be32_to_cpus(&f_header.version); 374ad627d62SPekka Enberg be64_to_cpus(&f_header.backing_file_offset); 375ad627d62SPekka Enberg be32_to_cpus(&f_header.backing_file_size); 376ad627d62SPekka Enberg be32_to_cpus(&f_header.cluster_bits); 377ad627d62SPekka Enberg be64_to_cpus(&f_header.size); 378ad627d62SPekka Enberg be32_to_cpus(&f_header.crypt_method); 379ad627d62SPekka Enberg be32_to_cpus(&f_header.l1_size); 380ad627d62SPekka Enberg be64_to_cpus(&f_header.l1_table_offset); 381ad627d62SPekka Enberg be64_to_cpus(&f_header.refcount_table_offset); 382ad627d62SPekka Enberg be32_to_cpus(&f_header.refcount_table_clusters); 383ad627d62SPekka Enberg be32_to_cpus(&f_header.nb_snapshots); 384ad627d62SPekka Enberg be64_to_cpus(&f_header.snapshots_offset); 385ad627d62SPekka Enberg 386ad627d62SPekka Enberg *header = (struct qcow_header) { 387ad627d62SPekka Enberg .size = f_header.size, 388ad627d62SPekka Enberg .l1_table_offset = f_header.l1_table_offset, 389ad627d62SPekka Enberg .l1_size = f_header.l1_size, 390ad627d62SPekka Enberg .cluster_bits = f_header.cluster_bits, 391ad627d62SPekka Enberg .l2_bits = f_header.cluster_bits - 3, 392ad627d62SPekka Enberg .oflag_mask = QCOW2_OFLAG_MASK, 393ad627d62SPekka Enberg }; 394ad627d62SPekka Enberg 395ad627d62SPekka Enberg return header; 396ad627d62SPekka Enberg } 397ad627d62SPekka Enberg 398ad627d62SPekka Enberg static struct disk_image *qcow2_probe(int fd) 399ad627d62SPekka Enberg { 400ad627d62SPekka Enberg struct qcow *q; 401ad627d62SPekka Enberg struct qcow_header *h; 402ad627d62SPekka Enberg struct disk_image *disk_image; 403ad627d62SPekka Enberg 404ad627d62SPekka Enberg q = calloc(1, sizeof(struct qcow)); 405ad627d62SPekka Enberg if (!q) 406ad627d62SPekka Enberg goto error; 407ad627d62SPekka Enberg 408ad627d62SPekka Enberg q->fd = fd; 409ad627d62SPekka Enberg 410ad627d62SPekka Enberg h = q->header = qcow2_read_header(fd); 411ad627d62SPekka Enberg if (!h) 412ad627d62SPekka Enberg goto error; 413ad627d62SPekka Enberg 414ad627d62SPekka Enberg if (qcow_read_l1_table(q) < 0) 415ad627d62SPekka Enberg goto error; 416ad627d62SPekka Enberg 417ad627d62SPekka Enberg disk_image = disk_image__new(fd, h->size, &qcow1_disk_ops); 418ad627d62SPekka Enberg if (!disk_image) 419ad627d62SPekka Enberg goto error; 420ad627d62SPekka Enberg disk_image->priv = q; 421ad627d62SPekka Enberg 422ad627d62SPekka Enberg return disk_image; 423ad627d62SPekka Enberg error: 424ad627d62SPekka Enberg if (!q) 425ad627d62SPekka Enberg return NULL; 426ad627d62SPekka Enberg 427ad627d62SPekka Enberg free(q->table.l1_table); 428ad627d62SPekka Enberg free(q->header); 429ad627d62SPekka Enberg free(q); 430ad627d62SPekka Enberg 431ad627d62SPekka Enberg return NULL; 432ad627d62SPekka Enberg } 433ad627d62SPekka Enberg 434ad627d62SPekka Enberg static bool qcow2_check_image(int fd) 435ad627d62SPekka Enberg { 436ad627d62SPekka Enberg struct qcow2_header_disk f_header; 437ad627d62SPekka Enberg 438ad627d62SPekka Enberg if (pread_in_full(fd, &f_header, sizeof(struct qcow2_header_disk), 0) < 0) 439ad627d62SPekka Enberg return false; 440ad627d62SPekka Enberg 441ad627d62SPekka Enberg be32_to_cpus(&f_header.magic); 442ad627d62SPekka Enberg be32_to_cpus(&f_header.version); 443ad627d62SPekka Enberg 444ad627d62SPekka Enberg if (f_header.magic != QCOW_MAGIC) 445ad627d62SPekka Enberg return false; 446ad627d62SPekka Enberg 447ad627d62SPekka Enberg if (f_header.version != QCOW2_VERSION) 448ad627d62SPekka Enberg return false; 449ad627d62SPekka Enberg 450ad627d62SPekka Enberg return true; 451ad627d62SPekka Enberg } 452ad627d62SPekka Enberg 453ad627d62SPekka Enberg static void *qcow1_read_header(int fd) 454ad627d62SPekka Enberg { 455ad627d62SPekka Enberg struct qcow1_header_disk f_header; 456ad627d62SPekka Enberg struct qcow_header *header; 457ad627d62SPekka Enberg 458ad627d62SPekka Enberg header = malloc(sizeof(struct qcow_header)); 459ad627d62SPekka Enberg if (!header) 460ad627d62SPekka Enberg return NULL; 461ad627d62SPekka Enberg 462d39cefd2SSasha Levin if (pread_in_full(fd, &f_header, sizeof(struct qcow1_header_disk), 0) < 0) { 463d39cefd2SSasha Levin free(header); 464ad627d62SPekka Enberg return NULL; 465d39cefd2SSasha Levin } 466ad627d62SPekka Enberg 467ad627d62SPekka Enberg be32_to_cpus(&f_header.magic); 468ad627d62SPekka Enberg be32_to_cpus(&f_header.version); 469ad627d62SPekka Enberg be64_to_cpus(&f_header.backing_file_offset); 470ad627d62SPekka Enberg be32_to_cpus(&f_header.backing_file_size); 471ad627d62SPekka Enberg be32_to_cpus(&f_header.mtime); 472ad627d62SPekka Enberg be64_to_cpus(&f_header.size); 473ad627d62SPekka Enberg be32_to_cpus(&f_header.crypt_method); 474ad627d62SPekka Enberg be64_to_cpus(&f_header.l1_table_offset); 475ad627d62SPekka Enberg 476ad627d62SPekka Enberg *header = (struct qcow_header) { 477ad627d62SPekka Enberg .size = f_header.size, 478ad627d62SPekka Enberg .l1_table_offset = f_header.l1_table_offset, 479ad627d62SPekka Enberg .l1_size = f_header.size / ((1 << f_header.l2_bits) * (1 << f_header.cluster_bits)), 480ad627d62SPekka Enberg .cluster_bits = f_header.cluster_bits, 481ad627d62SPekka Enberg .l2_bits = f_header.l2_bits, 482ad627d62SPekka Enberg .oflag_mask = QCOW1_OFLAG_MASK, 483ad627d62SPekka Enberg }; 48486835cedSPrasad Joshi 48586835cedSPrasad Joshi return header; 48686835cedSPrasad Joshi } 48786835cedSPrasad Joshi 48886835cedSPrasad Joshi static struct disk_image *qcow1_probe(int fd) 48986835cedSPrasad Joshi { 49086835cedSPrasad Joshi struct qcow *q; 491ad627d62SPekka Enberg struct qcow_header *h; 49286835cedSPrasad Joshi struct disk_image *disk_image; 49386835cedSPrasad Joshi 49486835cedSPrasad Joshi q = calloc(1, sizeof(struct qcow)); 49586835cedSPrasad Joshi if (!q) 49686835cedSPrasad Joshi goto error; 49786835cedSPrasad Joshi 49886835cedSPrasad Joshi q->fd = fd; 49986835cedSPrasad Joshi 50086835cedSPrasad Joshi h = q->header = qcow1_read_header(fd); 50186835cedSPrasad Joshi if (!h) 50286835cedSPrasad Joshi goto error; 50386835cedSPrasad Joshi 50486835cedSPrasad Joshi if (qcow_read_l1_table(q) < 0) 50586835cedSPrasad Joshi goto error; 50686835cedSPrasad Joshi 50786835cedSPrasad Joshi disk_image = disk_image__new(fd, h->size, &qcow1_disk_ops); 50886835cedSPrasad Joshi if (!disk_image) 50986835cedSPrasad Joshi goto error; 51086835cedSPrasad Joshi disk_image->priv = q; 51186835cedSPrasad Joshi 51286835cedSPrasad Joshi return disk_image; 51386835cedSPrasad Joshi error: 51486835cedSPrasad Joshi if (!q) 51586835cedSPrasad Joshi return NULL; 51686835cedSPrasad Joshi 5176c6f79b6SPrasad Joshi free(q->table.l1_table); 51886835cedSPrasad Joshi free(q->header); 51986835cedSPrasad Joshi free(q); 52086835cedSPrasad Joshi 52186835cedSPrasad Joshi return NULL; 52286835cedSPrasad Joshi } 52386835cedSPrasad Joshi 524ad627d62SPekka Enberg static bool qcow1_check_image(int fd) 52586835cedSPrasad Joshi { 526ad627d62SPekka Enberg struct qcow1_header_disk f_header; 52786835cedSPrasad Joshi 528ad627d62SPekka Enberg if (pread_in_full(fd, &f_header, sizeof(struct qcow1_header_disk), 0) < 0) 529ad627d62SPekka Enberg return false; 53086835cedSPrasad Joshi 531ad627d62SPekka Enberg be32_to_cpus(&f_header.magic); 532ad627d62SPekka Enberg be32_to_cpus(&f_header.version); 53386835cedSPrasad Joshi 534ad627d62SPekka Enberg if (f_header.magic != QCOW_MAGIC) 535ad627d62SPekka Enberg return false; 53686835cedSPrasad Joshi 537ad627d62SPekka Enberg if (f_header.version != QCOW1_VERSION) 538ad627d62SPekka Enberg return false; 53986835cedSPrasad Joshi 540ad627d62SPekka Enberg return true; 54186835cedSPrasad Joshi } 54286835cedSPrasad Joshi 54386835cedSPrasad Joshi struct disk_image *qcow_probe(int fd) 54486835cedSPrasad Joshi { 545ad627d62SPekka Enberg if (qcow1_check_image(fd)) 54686835cedSPrasad Joshi return qcow1_probe(fd); 547ad627d62SPekka Enberg 548ad627d62SPekka Enberg if (qcow2_check_image(fd)) 549ad627d62SPekka Enberg return qcow2_probe(fd); 550ad627d62SPekka Enberg 551ad627d62SPekka Enberg return NULL; 55286835cedSPrasad Joshi } 553