Revision f965509c
b/block-qcow2.c | ||
---|---|---|
84 | 84 |
uint32_t len; |
85 | 85 |
} QCowExtension; |
86 | 86 |
#define QCOW_EXT_MAGIC_END 0 |
87 |
#define QCOW_EXT_MAGIC_BACKING_FORMAT 0xE2792ACA |
|
87 | 88 |
|
88 | 89 |
|
89 | 90 |
typedef struct __attribute__((packed)) QCowSnapshotHeader { |
... | ... | |
235 | 236 |
switch (ext.magic) { |
236 | 237 |
case QCOW_EXT_MAGIC_END: |
237 | 238 |
return 0; |
239 |
|
|
240 |
case QCOW_EXT_MAGIC_BACKING_FORMAT: |
|
241 |
if (ext.len >= sizeof(bs->backing_format)) { |
|
242 |
fprintf(stderr, "ERROR: ext_backing_format: len=%u too large" |
|
243 |
" (>=%lu)\n", |
|
244 |
ext.len, sizeof(bs->backing_format)); |
|
245 |
return 2; |
|
246 |
} |
|
247 |
if (bdrv_pread(s->hd, offset , bs->backing_format, |
|
248 |
ext.len) != ext.len) |
|
249 |
return 3; |
|
250 |
bs->backing_format[ext.len] = '\0'; |
|
251 |
#ifdef DEBUG_EXT |
|
252 |
printf("Qcow2: Got format extension %s\n", bs->backing_format); |
|
253 |
#endif |
|
254 |
offset += ((ext.len + 7) & ~7); |
|
255 |
break; |
|
256 |
|
|
238 | 257 |
default: |
239 | 258 |
/* unknown magic -- just skip it */ |
240 | 259 |
offset += ((ext.len + 7) & ~7); |
... | ... | |
1526 | 1545 |
} |
1527 | 1546 |
} |
1528 | 1547 |
|
1529 |
static int qcow_create(const char *filename, int64_t total_size, |
|
1530 |
const char *backing_file, int flags) |
|
1548 |
static int qcow_create2(const char *filename, int64_t total_size, |
|
1549 |
const char *backing_file, const char *backing_format, |
|
1550 |
int flags) |
|
1531 | 1551 |
{ |
1552 |
|
|
1532 | 1553 |
int fd, header_size, backing_filename_len, l1_size, i, shift, l2_bits; |
1554 |
int backing_format_len = 0; |
|
1533 | 1555 |
QCowHeader header; |
1534 | 1556 |
uint64_t tmp, offset; |
1535 | 1557 |
QCowCreateState s1, *s = &s1; |
1558 |
QCowExtension ext_bf = {0, 0}; |
|
1559 |
|
|
1536 | 1560 |
|
1537 | 1561 |
memset(s, 0, sizeof(*s)); |
1538 | 1562 |
|
... | ... | |
1546 | 1570 |
header_size = sizeof(header); |
1547 | 1571 |
backing_filename_len = 0; |
1548 | 1572 |
if (backing_file) { |
1573 |
if (backing_format) { |
|
1574 |
ext_bf.magic = QCOW_EXT_MAGIC_BACKING_FORMAT; |
|
1575 |
backing_format_len = strlen(backing_format); |
|
1576 |
ext_bf.len = (backing_format_len + 7) & ~7; |
|
1577 |
header_size += ((sizeof(ext_bf) + ext_bf.len + 7) & ~7); |
|
1578 |
} |
|
1549 | 1579 |
header.backing_file_offset = cpu_to_be64(header_size); |
1550 | 1580 |
backing_filename_len = strlen(backing_file); |
1551 | 1581 |
header.backing_file_size = cpu_to_be32(backing_filename_len); |
... | ... | |
1590 | 1620 |
/* write all the data */ |
1591 | 1621 |
write(fd, &header, sizeof(header)); |
1592 | 1622 |
if (backing_file) { |
1623 |
if (backing_format_len) { |
|
1624 |
char zero[16]; |
|
1625 |
int d = ext_bf.len - backing_format_len; |
|
1626 |
|
|
1627 |
memset(zero, 0, sizeof(zero)); |
|
1628 |
cpu_to_be32s(&ext_bf.magic); |
|
1629 |
cpu_to_be32s(&ext_bf.len); |
|
1630 |
write(fd, &ext_bf, sizeof(ext_bf)); |
|
1631 |
write(fd, backing_format, backing_format_len); |
|
1632 |
if (d>0) { |
|
1633 |
write(fd, zero, d); |
|
1634 |
} |
|
1635 |
} |
|
1593 | 1636 |
write(fd, backing_file, backing_filename_len); |
1594 | 1637 |
} |
1595 | 1638 |
lseek(fd, s->l1_table_offset, SEEK_SET); |
... | ... | |
1609 | 1652 |
return 0; |
1610 | 1653 |
} |
1611 | 1654 |
|
1655 |
static int qcow_create(const char *filename, int64_t total_size, |
|
1656 |
const char *backing_file, int flags) |
|
1657 |
{ |
|
1658 |
return qcow_create2(filename, total_size, backing_file, NULL, flags); |
|
1659 |
} |
|
1660 |
|
|
1612 | 1661 |
static int qcow_make_empty(BlockDriverState *bs) |
1613 | 1662 |
{ |
1614 | 1663 |
#if 0 |
... | ... | |
2685 | 2734 |
.bdrv_snapshot_delete = qcow_snapshot_delete, |
2686 | 2735 |
.bdrv_snapshot_list = qcow_snapshot_list, |
2687 | 2736 |
.bdrv_get_info = qcow_get_info, |
2737 |
|
|
2738 |
.bdrv_create2 = qcow_create2, |
|
2688 | 2739 |
}; |
Also available in: Unified diff