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> 16865c675fSPrasad Joshi #include <linux/kernel.h> 170df6b4d9SPekka Enberg #include <linux/types.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; 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; 500df6b4d9SPekka Enberg u64 *l2_table; 51742fce76SPrasad Joshi u64 l1_idx; 52742fce76SPrasad Joshi u64 l2_idx; 5386835cedSPrasad Joshi 540df6b4d9SPekka Enberg l2_table = NULL; 550df6b4d9SPekka Enberg 56dae803fbSPekka Enberg cluster_size = 1 << header->cluster_bits; 5786835cedSPrasad Joshi 58c5e0624bSPrasad Joshi l1_idx = get_l1_index(q, offset); 593dac48d4SPrasad Joshi if (l1_idx >= table->table_size) 6086835cedSPrasad Joshi goto out_error; 6186835cedSPrasad Joshi 623dac48d4SPrasad Joshi clust_offset = get_cluster_offset(q, offset); 633dac48d4SPrasad Joshi if (clust_offset >= cluster_size) 643dac48d4SPrasad Joshi goto out_error; 653dac48d4SPrasad Joshi 663dac48d4SPrasad Joshi length = cluster_size - clust_offset; 673dac48d4SPrasad Joshi if (length > dst_len) 683dac48d4SPrasad Joshi length = dst_len; 693dac48d4SPrasad Joshi 70ad627d62SPekka Enberg l2_table_offset = table->l1_table[l1_idx] & ~header->oflag_mask; 7186835cedSPrasad Joshi if (!l2_table_offset) 723dac48d4SPrasad Joshi goto zero_cluster; 7386835cedSPrasad Joshi 7486835cedSPrasad Joshi l2_table_size = 1 << header->l2_bits; 75742fce76SPrasad Joshi l2_table = calloc(l2_table_size, sizeof(u64)); 7686835cedSPrasad Joshi if (!l2_table) 7786835cedSPrasad Joshi goto out_error; 7886835cedSPrasad Joshi 790df6b4d9SPekka Enberg if (pread_in_full(q->fd, l2_table, l2_table_size * sizeof(u64), l2_table_offset) < 0) 80b6edb0ecSSasha Levin goto out_error; 8186835cedSPrasad Joshi 82c5e0624bSPrasad Joshi l2_idx = get_l2_index(q, offset); 8386835cedSPrasad Joshi if (l2_idx >= l2_table_size) 84b6edb0ecSSasha Levin goto out_error; 8586835cedSPrasad Joshi 86ad627d62SPekka Enberg clust_start = be64_to_cpu(l2_table[l2_idx]) & ~header->oflag_mask; 8786835cedSPrasad Joshi if (!clust_start) 883dac48d4SPrasad Joshi goto zero_cluster; 8986835cedSPrasad Joshi 903dac48d4SPrasad Joshi if (pread_in_full(q->fd, dst, length, clust_start + clust_offset) < 0) 91b6edb0ecSSasha Levin goto out_error; 9286835cedSPrasad Joshi 93179b71f0SPekka Enberg out: 94179b71f0SPekka Enberg free(l2_table); 953dac48d4SPrasad Joshi return length; 9686835cedSPrasad Joshi 97179b71f0SPekka Enberg zero_cluster: 98179b71f0SPekka Enberg memset(dst, 0, length); 99179b71f0SPekka Enberg goto out; 100179b71f0SPekka Enberg 10186835cedSPrasad Joshi out_error: 102179b71f0SPekka Enberg length = -1; 103179b71f0SPekka Enberg goto out; 1043dac48d4SPrasad Joshi } 105b6edb0ecSSasha Levin 1060df6b4d9SPekka Enberg static int qcow1_read_sector(struct disk_image *disk, u64 sector, void *dst, u32 dst_len) 1073dac48d4SPrasad Joshi { 10843835ac9SSasha Levin struct qcow *q = disk->priv; 109ad627d62SPekka Enberg struct qcow_header *header = q->header; 110d8eea993SPekka Enberg u32 nr_read; 1110df6b4d9SPekka Enberg u64 offset; 1120df6b4d9SPekka Enberg char *buf; 1133dac48d4SPrasad Joshi u32 nr; 1143dac48d4SPrasad Joshi 1150df6b4d9SPekka Enberg buf = dst; 116d8eea993SPekka Enberg nr_read = 0; 1170df6b4d9SPekka Enberg 118d8eea993SPekka Enberg while (nr_read < dst_len) { 1193dac48d4SPrasad Joshi offset = sector << SECTOR_SHIFT; 1203dac48d4SPrasad Joshi if (offset >= header->size) 1210df6b4d9SPekka Enberg return -1; 1223dac48d4SPrasad Joshi 123d8eea993SPekka Enberg nr = qcow1_read_cluster(q, offset, buf, dst_len - nr_read); 124a51948ceSPekka Enberg if (nr <= 0) 1250df6b4d9SPekka Enberg return -1; 1263dac48d4SPrasad Joshi 127d8eea993SPekka Enberg nr_read += nr; 1283dac48d4SPrasad Joshi buf += nr; 1293dac48d4SPrasad Joshi sector += (nr >> SECTOR_SHIFT); 1303dac48d4SPrasad Joshi } 1310df6b4d9SPekka Enberg 1323dac48d4SPrasad Joshi return 0; 13386835cedSPrasad Joshi } 13486835cedSPrasad Joshi 135865c675fSPrasad Joshi static inline u64 file_size(int fd) 136865c675fSPrasad Joshi { 137865c675fSPrasad Joshi struct stat st; 1380df6b4d9SPekka Enberg 139865c675fSPrasad Joshi if (fstat(fd, &st) < 0) 140865c675fSPrasad Joshi return 0; 1410df6b4d9SPekka Enberg 142865c675fSPrasad Joshi return st.st_size; 143865c675fSPrasad Joshi } 144865c675fSPrasad Joshi 1450df6b4d9SPekka Enberg #define SYNC_FLAGS (SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE) 1460df6b4d9SPekka Enberg 1470df6b4d9SPekka Enberg static inline int qcow_pwrite_sync(int fd, void *buf, size_t count, off_t offset) 148865c675fSPrasad Joshi { 149865c675fSPrasad Joshi if (pwrite_in_full(fd, buf, count, offset) < 0) 150865c675fSPrasad Joshi return -1; 1510df6b4d9SPekka Enberg 1520df6b4d9SPekka Enberg return sync_file_range(fd, offset, count, SYNC_FLAGS); 153865c675fSPrasad Joshi } 154865c675fSPrasad Joshi 155865c675fSPrasad Joshi /* Writes a level 2 table at the end of the file. */ 156865c675fSPrasad Joshi static u64 qcow1_write_l2_table(struct qcow *q, u64 *table) 157865c675fSPrasad Joshi { 158865c675fSPrasad Joshi struct qcow_header *header = q->header; 159865c675fSPrasad Joshi u64 clust_sz; 160865c675fSPrasad Joshi u64 f_sz; 1610df6b4d9SPekka Enberg u64 off; 1620df6b4d9SPekka Enberg u64 sz; 163865c675fSPrasad Joshi 164865c675fSPrasad Joshi f_sz = file_size(q->fd); 165865c675fSPrasad Joshi if (!f_sz) 166865c675fSPrasad Joshi return 0; 167865c675fSPrasad Joshi 168865c675fSPrasad Joshi sz = 1 << header->l2_bits; 169865c675fSPrasad Joshi clust_sz = 1 << header->cluster_bits; 170865c675fSPrasad Joshi off = ALIGN(f_sz, clust_sz); 171865c675fSPrasad Joshi 1720df6b4d9SPekka Enberg if (qcow_pwrite_sync(q->fd, table, sz * sizeof(u64), off) < 0) 173865c675fSPrasad Joshi return 0; 1740df6b4d9SPekka Enberg 175865c675fSPrasad Joshi return off; 176865c675fSPrasad Joshi } 177865c675fSPrasad Joshi 178865c675fSPrasad Joshi /* 179865c675fSPrasad Joshi * QCOW file might grow during a write operation. Not only data but metadata is 180865c675fSPrasad Joshi * also written at the end of the file. Therefore it is necessary to ensure 1810df6b4d9SPekka Enberg * every write is committed to disk. Hence we use uses qcow_pwrite_sync() to 182865c675fSPrasad Joshi * synchronize the in-core state of QCOW image to disk. 183865c675fSPrasad Joshi * 184865c675fSPrasad Joshi * We also try to restore the image to a consistent state if the metdata 185865c675fSPrasad Joshi * operation fails. The two metadat operations are: level 1 and level 2 table 186865c675fSPrasad Joshi * update. If either of them fails the image is truncated to a consistent state. 187865c675fSPrasad Joshi */ 188865c675fSPrasad Joshi static ssize_t qcow1_write_cluster(struct qcow *q, u64 offset, void *buf, u32 src_len) 189865c675fSPrasad Joshi { 190865c675fSPrasad Joshi struct qcow_header *header = q->header; 191865c675fSPrasad Joshi struct qcow_table *table = &q->table; 1920df6b4d9SPekka Enberg bool update_meta; 1930df6b4d9SPekka Enberg u64 clust_start; 1940df6b4d9SPekka Enberg u64 clust_off; 195865c675fSPrasad Joshi u64 clust_sz; 196865c675fSPrasad Joshi u64 l1t_idx; 197865c675fSPrasad Joshi u64 l2t_idx; 1980df6b4d9SPekka Enberg u64 l2t_off; 1990df6b4d9SPekka Enberg u64 l2t_sz; 200865c675fSPrasad Joshi u64 *l2t; 201865c675fSPrasad Joshi u64 f_sz; 2020df6b4d9SPekka Enberg u64 len; 203865c675fSPrasad Joshi u64 t; 204865c675fSPrasad Joshi 205865c675fSPrasad Joshi l2t_sz = 1 << header->l2_bits; 206865c675fSPrasad Joshi clust_sz = 1 << header->cluster_bits; 207865c675fSPrasad Joshi 208865c675fSPrasad Joshi l1t_idx = get_l1_index(q, offset); 209865c675fSPrasad Joshi if (l1t_idx >= table->table_size) 210865c675fSPrasad Joshi goto error; 211865c675fSPrasad Joshi 212865c675fSPrasad Joshi l2t_idx = get_l2_index(q, offset); 213865c675fSPrasad Joshi if (l2t_idx >= l2t_sz) 214865c675fSPrasad Joshi goto error; 215865c675fSPrasad Joshi 216865c675fSPrasad Joshi clust_off = get_cluster_offset(q, offset); 217865c675fSPrasad Joshi if (clust_off >= clust_sz) 218865c675fSPrasad Joshi goto error; 219865c675fSPrasad Joshi 220865c675fSPrasad Joshi len = clust_sz - clust_off; 221865c675fSPrasad Joshi if (len > src_len) 222865c675fSPrasad Joshi len = src_len; 223865c675fSPrasad Joshi 224865c675fSPrasad Joshi l2t = calloc(l2t_sz, sizeof(u64)); 225865c675fSPrasad Joshi if (!l2t) 226865c675fSPrasad Joshi goto error; 227865c675fSPrasad Joshi 228865c675fSPrasad Joshi l2t_off = table->l1_table[l1t_idx] & ~header->oflag_mask; 229865c675fSPrasad Joshi if (l2t_off) { 230865c675fSPrasad Joshi if (pread_in_full(q->fd, l2t, l2t_sz * sizeof(u64), l2t_off) < 0) 231865c675fSPrasad Joshi goto free_l2; 232865c675fSPrasad Joshi } else { 2330df6b4d9SPekka Enberg /* Capture the state of the consistent QCOW image */ 234865c675fSPrasad Joshi f_sz = file_size(q->fd); 235865c675fSPrasad Joshi if (!f_sz) 236865c675fSPrasad Joshi goto free_l2; 237865c675fSPrasad Joshi 238865c675fSPrasad Joshi /* Write the l2 table of 0's at the end of the file */ 239865c675fSPrasad Joshi l2t_off = qcow1_write_l2_table(q, l2t); 240865c675fSPrasad Joshi if (!l2t_off) 241865c675fSPrasad Joshi goto free_l2; 242865c675fSPrasad Joshi 243865c675fSPrasad Joshi /* Metadata update: update on disk level 1 table */ 244865c675fSPrasad Joshi t = cpu_to_be64(l2t_off); 2450df6b4d9SPekka Enberg 2460df6b4d9SPekka Enberg if (qcow_pwrite_sync(q->fd, &t, sizeof(t), header->l1_table_offset + l1t_idx * sizeof(u64)) < 0) { 247865c675fSPrasad Joshi /* restore file to consistent state */ 248865c675fSPrasad Joshi if (ftruncate(q->fd, f_sz) < 0) 249865c675fSPrasad Joshi goto free_l2; 2500df6b4d9SPekka Enberg 251865c675fSPrasad Joshi goto free_l2; 252865c675fSPrasad Joshi } 253865c675fSPrasad Joshi 2540df6b4d9SPekka Enberg /* Update the in-core entry */ 255865c675fSPrasad Joshi table->l1_table[l1t_idx] = l2t_off; 256865c675fSPrasad Joshi } 257865c675fSPrasad Joshi 2580df6b4d9SPekka Enberg /* Capture the state of the consistent QCOW image */ 259865c675fSPrasad Joshi f_sz = file_size(q->fd); 260865c675fSPrasad Joshi if (!f_sz) 261865c675fSPrasad Joshi goto free_l2; 262865c675fSPrasad Joshi 263865c675fSPrasad Joshi clust_start = be64_to_cpu(l2t[l2t_idx]) & ~header->oflag_mask; 264865c675fSPrasad Joshi if (!clust_start) { 265865c675fSPrasad Joshi clust_start = ALIGN(f_sz, clust_sz); 266865c675fSPrasad Joshi update_meta = true; 2670df6b4d9SPekka Enberg } else 2680df6b4d9SPekka Enberg update_meta = false; 269865c675fSPrasad Joshi 2700df6b4d9SPekka Enberg free(l2t); 2710df6b4d9SPekka Enberg 2720df6b4d9SPekka Enberg /* Write actual data */ 273865c675fSPrasad Joshi if (pwrite_in_full(q->fd, buf, len, clust_start + clust_off) < 0) 274865c675fSPrasad Joshi goto error; 275865c675fSPrasad Joshi 276865c675fSPrasad Joshi if (update_meta) { 277865c675fSPrasad Joshi t = cpu_to_be64(clust_start); 2780df6b4d9SPekka Enberg if (qcow_pwrite_sync(q->fd, &t, sizeof(t), l2t_off + l2t_idx * sizeof(u64)) < 0) { 2790df6b4d9SPekka Enberg /* Restore the file to consistent state */ 280865c675fSPrasad Joshi if (ftruncate(q->fd, f_sz) < 0) 281865c675fSPrasad Joshi goto error; 2820df6b4d9SPekka Enberg 283865c675fSPrasad Joshi goto error; 284865c675fSPrasad Joshi } 285865c675fSPrasad Joshi } 2860df6b4d9SPekka Enberg 287865c675fSPrasad Joshi return len; 288865c675fSPrasad Joshi free_l2: 289865c675fSPrasad Joshi free(l2t); 290865c675fSPrasad Joshi error: 291865c675fSPrasad Joshi return -1; 292865c675fSPrasad Joshi } 293865c675fSPrasad Joshi 29443835ac9SSasha Levin static int qcow1_write_sector(struct disk_image *disk, u64 sector, void *src, u32 src_len) 29586835cedSPrasad Joshi { 296865c675fSPrasad Joshi struct qcow *q = disk->priv; 297865c675fSPrasad Joshi struct qcow_header *header = q->header; 298*c4acb611SIngo Molnar u32 nr_written; 2990df6b4d9SPekka Enberg char *buf; 300865c675fSPrasad Joshi u64 offset; 301865c675fSPrasad Joshi ssize_t nr; 302865c675fSPrasad Joshi 3030df6b4d9SPekka Enberg buf = src; 3040df6b4d9SPekka Enberg nr_written = 0; 305865c675fSPrasad Joshi offset = sector << SECTOR_SHIFT; 3060df6b4d9SPekka Enberg 3070df6b4d9SPekka Enberg while (nr_written < src_len) { 308865c675fSPrasad Joshi if (offset >= header->size) 3090df6b4d9SPekka Enberg return -1; 310865c675fSPrasad Joshi 3110df6b4d9SPekka Enberg nr = qcow1_write_cluster(q, offset, buf, src_len - nr_written); 312865c675fSPrasad Joshi if (nr < 0) 3130df6b4d9SPekka Enberg return -1; 314865c675fSPrasad Joshi 3150df6b4d9SPekka Enberg nr_written += nr; 316865c675fSPrasad Joshi buf += nr; 317865c675fSPrasad Joshi offset += nr; 318865c675fSPrasad Joshi } 3190df6b4d9SPekka Enberg 320865c675fSPrasad Joshi return 0; 32186835cedSPrasad Joshi } 32286835cedSPrasad Joshi 323f10860caSPekka Enberg static int qcow1_nowrite_sector(struct disk_image *disk, u64 sector, void *src, u32 src_len) 324f10860caSPekka Enberg { 325f10860caSPekka Enberg /* I/O error */ 326f10860caSPekka Enberg return -1; 327f10860caSPekka Enberg } 328f10860caSPekka Enberg 32943835ac9SSasha Levin static void qcow1_disk_close(struct disk_image *disk) 33086835cedSPrasad Joshi { 33186835cedSPrasad Joshi struct qcow *q; 33286835cedSPrasad Joshi 33343835ac9SSasha Levin if (!disk) 33486835cedSPrasad Joshi return; 33586835cedSPrasad Joshi 33643835ac9SSasha Levin q = disk->priv; 33786835cedSPrasad Joshi 3386c6f79b6SPrasad Joshi free(q->table.l1_table); 33986835cedSPrasad Joshi free(q->header); 34086835cedSPrasad Joshi free(q); 34186835cedSPrasad Joshi } 34286835cedSPrasad Joshi 343f10860caSPekka Enberg static struct disk_image_operations qcow1_disk_readonly_ops = { 344f10860caSPekka Enberg .read_sector = qcow1_read_sector, 345f10860caSPekka Enberg .write_sector = qcow1_nowrite_sector, 346f10860caSPekka Enberg .close = qcow1_disk_close 347f10860caSPekka Enberg }; 348f10860caSPekka Enberg 349f10860caSPekka Enberg static struct disk_image_operations qcow1_disk_ops = { 35086835cedSPrasad Joshi .read_sector = qcow1_read_sector, 35186835cedSPrasad Joshi .write_sector = qcow1_write_sector, 35286835cedSPrasad Joshi .close = qcow1_disk_close 35386835cedSPrasad Joshi }; 35486835cedSPrasad Joshi 35586835cedSPrasad Joshi static int qcow_read_l1_table(struct qcow *q) 35686835cedSPrasad Joshi { 357ad627d62SPekka Enberg struct qcow_header *header = q->header; 35800adcc1bSPrasad Joshi struct qcow_table *table = &q->table; 35900adcc1bSPrasad Joshi u64 i; 36086835cedSPrasad Joshi 361ad627d62SPekka Enberg table->table_size = header->l1_size; 36286835cedSPrasad Joshi 36300adcc1bSPrasad Joshi table->l1_table = calloc(table->table_size, sizeof(u64)); 36400adcc1bSPrasad Joshi if (!table->l1_table) 36586835cedSPrasad Joshi return -1; 36686835cedSPrasad Joshi 36700adcc1bSPrasad Joshi if (pread_in_full(q->fd, table->l1_table, sizeof(u64) * 36800adcc1bSPrasad Joshi table->table_size, header->l1_table_offset) < 0) 36986835cedSPrasad Joshi return -1; 37086835cedSPrasad Joshi 37100adcc1bSPrasad Joshi for (i = 0; i < table->table_size; i++) 37200adcc1bSPrasad Joshi be64_to_cpus(&table->l1_table[i]); 37300adcc1bSPrasad Joshi 37486835cedSPrasad Joshi return 0; 37586835cedSPrasad Joshi } 37686835cedSPrasad Joshi 377ad627d62SPekka Enberg static void *qcow2_read_header(int fd) 37886835cedSPrasad Joshi { 379ad627d62SPekka Enberg struct qcow2_header_disk f_header; 380ad627d62SPekka Enberg struct qcow_header *header; 38186835cedSPrasad Joshi 382ad627d62SPekka Enberg header = malloc(sizeof(struct qcow_header)); 38386835cedSPrasad Joshi if (!header) 38486835cedSPrasad Joshi return NULL; 38586835cedSPrasad Joshi 3860657f33dSPrasad Joshi if (pread_in_full(fd, &f_header, sizeof(struct qcow2_header_disk), 0) < 0) { 3870657f33dSPrasad Joshi free(header); 38886835cedSPrasad Joshi return NULL; 3890657f33dSPrasad Joshi } 39086835cedSPrasad Joshi 391ad627d62SPekka Enberg be32_to_cpus(&f_header.magic); 392ad627d62SPekka Enberg be32_to_cpus(&f_header.version); 393ad627d62SPekka Enberg be64_to_cpus(&f_header.backing_file_offset); 394ad627d62SPekka Enberg be32_to_cpus(&f_header.backing_file_size); 395ad627d62SPekka Enberg be32_to_cpus(&f_header.cluster_bits); 396ad627d62SPekka Enberg be64_to_cpus(&f_header.size); 397ad627d62SPekka Enberg be32_to_cpus(&f_header.crypt_method); 398ad627d62SPekka Enberg be32_to_cpus(&f_header.l1_size); 399ad627d62SPekka Enberg be64_to_cpus(&f_header.l1_table_offset); 400ad627d62SPekka Enberg be64_to_cpus(&f_header.refcount_table_offset); 401ad627d62SPekka Enberg be32_to_cpus(&f_header.refcount_table_clusters); 402ad627d62SPekka Enberg be32_to_cpus(&f_header.nb_snapshots); 403ad627d62SPekka Enberg be64_to_cpus(&f_header.snapshots_offset); 404ad627d62SPekka Enberg 405ad627d62SPekka Enberg *header = (struct qcow_header) { 406ad627d62SPekka Enberg .size = f_header.size, 407ad627d62SPekka Enberg .l1_table_offset = f_header.l1_table_offset, 408ad627d62SPekka Enberg .l1_size = f_header.l1_size, 409ad627d62SPekka Enberg .cluster_bits = f_header.cluster_bits, 410ad627d62SPekka Enberg .l2_bits = f_header.cluster_bits - 3, 411ad627d62SPekka Enberg .oflag_mask = QCOW2_OFLAG_MASK, 412ad627d62SPekka Enberg }; 413ad627d62SPekka Enberg 414ad627d62SPekka Enberg return header; 415ad627d62SPekka Enberg } 416ad627d62SPekka Enberg 417f10860caSPekka Enberg static struct disk_image *qcow2_probe(int fd, bool readonly) 418ad627d62SPekka Enberg { 419ad627d62SPekka Enberg struct qcow *q; 420ad627d62SPekka Enberg struct qcow_header *h; 421ad627d62SPekka Enberg struct disk_image *disk_image; 422ad627d62SPekka Enberg 423ad627d62SPekka Enberg q = calloc(1, sizeof(struct qcow)); 424ad627d62SPekka Enberg if (!q) 425ad627d62SPekka Enberg goto error; 426ad627d62SPekka Enberg 427ad627d62SPekka Enberg q->fd = fd; 428ad627d62SPekka Enberg 429ad627d62SPekka Enberg h = q->header = qcow2_read_header(fd); 430ad627d62SPekka Enberg if (!h) 431ad627d62SPekka Enberg goto error; 432ad627d62SPekka Enberg 433ad627d62SPekka Enberg if (qcow_read_l1_table(q) < 0) 434ad627d62SPekka Enberg goto error; 435ad627d62SPekka Enberg 436f10860caSPekka Enberg if (readonly) 437f10860caSPekka Enberg disk_image = disk_image__new(fd, h->size, &qcow1_disk_readonly_ops); 438f10860caSPekka Enberg else 439ad627d62SPekka Enberg disk_image = disk_image__new(fd, h->size, &qcow1_disk_ops); 440f10860caSPekka Enberg 441ad627d62SPekka Enberg if (!disk_image) 442ad627d62SPekka Enberg goto error; 443ad627d62SPekka Enberg disk_image->priv = q; 444ad627d62SPekka Enberg 445ad627d62SPekka Enberg return disk_image; 446ad627d62SPekka Enberg error: 447ad627d62SPekka Enberg if (!q) 448ad627d62SPekka Enberg return NULL; 449ad627d62SPekka Enberg 450ad627d62SPekka Enberg free(q->table.l1_table); 451ad627d62SPekka Enberg free(q->header); 452ad627d62SPekka Enberg free(q); 453ad627d62SPekka Enberg 454ad627d62SPekka Enberg return NULL; 455ad627d62SPekka Enberg } 456ad627d62SPekka Enberg 457ad627d62SPekka Enberg static bool qcow2_check_image(int fd) 458ad627d62SPekka Enberg { 459ad627d62SPekka Enberg struct qcow2_header_disk f_header; 460ad627d62SPekka Enberg 461ad627d62SPekka Enberg if (pread_in_full(fd, &f_header, sizeof(struct qcow2_header_disk), 0) < 0) 462ad627d62SPekka Enberg return false; 463ad627d62SPekka Enberg 464ad627d62SPekka Enberg be32_to_cpus(&f_header.magic); 465ad627d62SPekka Enberg be32_to_cpus(&f_header.version); 466ad627d62SPekka Enberg 467ad627d62SPekka Enberg if (f_header.magic != QCOW_MAGIC) 468ad627d62SPekka Enberg return false; 469ad627d62SPekka Enberg 470ad627d62SPekka Enberg if (f_header.version != QCOW2_VERSION) 471ad627d62SPekka Enberg return false; 472ad627d62SPekka Enberg 473ad627d62SPekka Enberg return true; 474ad627d62SPekka Enberg } 475ad627d62SPekka Enberg 476ad627d62SPekka Enberg static void *qcow1_read_header(int fd) 477ad627d62SPekka Enberg { 478ad627d62SPekka Enberg struct qcow1_header_disk f_header; 479ad627d62SPekka Enberg struct qcow_header *header; 480ad627d62SPekka Enberg 481ad627d62SPekka Enberg header = malloc(sizeof(struct qcow_header)); 482ad627d62SPekka Enberg if (!header) 483ad627d62SPekka Enberg return NULL; 484ad627d62SPekka Enberg 485d39cefd2SSasha Levin if (pread_in_full(fd, &f_header, sizeof(struct qcow1_header_disk), 0) < 0) { 486d39cefd2SSasha Levin free(header); 487ad627d62SPekka Enberg return NULL; 488d39cefd2SSasha Levin } 489ad627d62SPekka Enberg 490ad627d62SPekka Enberg be32_to_cpus(&f_header.magic); 491ad627d62SPekka Enberg be32_to_cpus(&f_header.version); 492ad627d62SPekka Enberg be64_to_cpus(&f_header.backing_file_offset); 493ad627d62SPekka Enberg be32_to_cpus(&f_header.backing_file_size); 494ad627d62SPekka Enberg be32_to_cpus(&f_header.mtime); 495ad627d62SPekka Enberg be64_to_cpus(&f_header.size); 496ad627d62SPekka Enberg be32_to_cpus(&f_header.crypt_method); 497ad627d62SPekka Enberg be64_to_cpus(&f_header.l1_table_offset); 498ad627d62SPekka Enberg 499ad627d62SPekka Enberg *header = (struct qcow_header) { 500ad627d62SPekka Enberg .size = f_header.size, 501ad627d62SPekka Enberg .l1_table_offset = f_header.l1_table_offset, 502ad627d62SPekka Enberg .l1_size = f_header.size / ((1 << f_header.l2_bits) * (1 << f_header.cluster_bits)), 503ad627d62SPekka Enberg .cluster_bits = f_header.cluster_bits, 504ad627d62SPekka Enberg .l2_bits = f_header.l2_bits, 505ad627d62SPekka Enberg .oflag_mask = QCOW1_OFLAG_MASK, 506ad627d62SPekka Enberg }; 50786835cedSPrasad Joshi 50886835cedSPrasad Joshi return header; 50986835cedSPrasad Joshi } 51086835cedSPrasad Joshi 511f10860caSPekka Enberg static struct disk_image *qcow1_probe(int fd, bool readonly) 51286835cedSPrasad Joshi { 51386835cedSPrasad Joshi struct qcow *q; 514ad627d62SPekka Enberg struct qcow_header *h; 51586835cedSPrasad Joshi struct disk_image *disk_image; 51686835cedSPrasad Joshi 51786835cedSPrasad Joshi q = calloc(1, sizeof(struct qcow)); 51886835cedSPrasad Joshi if (!q) 51986835cedSPrasad Joshi goto error; 52086835cedSPrasad Joshi 52186835cedSPrasad Joshi q->fd = fd; 52286835cedSPrasad Joshi 52386835cedSPrasad Joshi h = q->header = qcow1_read_header(fd); 52486835cedSPrasad Joshi if (!h) 52586835cedSPrasad Joshi goto error; 52686835cedSPrasad Joshi 52786835cedSPrasad Joshi if (qcow_read_l1_table(q) < 0) 52886835cedSPrasad Joshi goto error; 52986835cedSPrasad Joshi 530f10860caSPekka Enberg if (readonly) 531f10860caSPekka Enberg disk_image = disk_image__new(fd, h->size, &qcow1_disk_readonly_ops); 532f10860caSPekka Enberg else 53386835cedSPrasad Joshi disk_image = disk_image__new(fd, h->size, &qcow1_disk_ops); 534f10860caSPekka Enberg 53586835cedSPrasad Joshi if (!disk_image) 53686835cedSPrasad Joshi goto error; 53786835cedSPrasad Joshi disk_image->priv = q; 53886835cedSPrasad Joshi 53986835cedSPrasad Joshi return disk_image; 54086835cedSPrasad Joshi error: 54186835cedSPrasad Joshi if (!q) 54286835cedSPrasad Joshi return NULL; 54386835cedSPrasad Joshi 5446c6f79b6SPrasad Joshi free(q->table.l1_table); 54586835cedSPrasad Joshi free(q->header); 54686835cedSPrasad Joshi free(q); 54786835cedSPrasad Joshi 54886835cedSPrasad Joshi return NULL; 54986835cedSPrasad Joshi } 55086835cedSPrasad Joshi 551ad627d62SPekka Enberg static bool qcow1_check_image(int fd) 55286835cedSPrasad Joshi { 553ad627d62SPekka Enberg struct qcow1_header_disk f_header; 55486835cedSPrasad Joshi 555ad627d62SPekka Enberg if (pread_in_full(fd, &f_header, sizeof(struct qcow1_header_disk), 0) < 0) 556ad627d62SPekka Enberg return false; 55786835cedSPrasad Joshi 558ad627d62SPekka Enberg be32_to_cpus(&f_header.magic); 559ad627d62SPekka Enberg be32_to_cpus(&f_header.version); 56086835cedSPrasad Joshi 561ad627d62SPekka Enberg if (f_header.magic != QCOW_MAGIC) 562ad627d62SPekka Enberg return false; 56386835cedSPrasad Joshi 564ad627d62SPekka Enberg if (f_header.version != QCOW1_VERSION) 565ad627d62SPekka Enberg return false; 56686835cedSPrasad Joshi 567ad627d62SPekka Enberg return true; 56886835cedSPrasad Joshi } 56986835cedSPrasad Joshi 570f10860caSPekka Enberg struct disk_image *qcow_probe(int fd, bool readonly) 57186835cedSPrasad Joshi { 572ad627d62SPekka Enberg if (qcow1_check_image(fd)) 573f10860caSPekka Enberg return qcow1_probe(fd, readonly); 574ad627d62SPekka Enberg 575ad627d62SPekka Enberg if (qcow2_check_image(fd)) 576f10860caSPekka Enberg return qcow2_probe(fd, readonly); 577ad627d62SPekka Enberg 578ad627d62SPekka Enberg return NULL; 57986835cedSPrasad Joshi } 580