diff options
Diffstat (limited to 'block/dmg.c')
-rw-r--r-- | block/dmg.c | 224 |
1 files changed, 120 insertions, 104 deletions
diff --git a/block/dmg.c b/block/dmg.c index d5e9b1f..be2f26e 100644 --- a/block/dmg.c +++ b/block/dmg.c @@ -96,9 +96,9 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags, Error **errp) { BDRVDMGState *s = bs->opaque; - uint64_t info_begin,info_end,last_in_offset,last_out_offset; + uint64_t info_begin, info_end, last_in_offset, last_out_offset; uint32_t count, tmp; - uint32_t max_compressed_size=1,max_sectors_per_chunk=1,i; + uint32_t max_compressed_size = 1, max_sectors_per_chunk = 1, i; int64_t offset; int ret; @@ -160,37 +160,39 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags, goto fail; } - if (type == 0x6d697368 && count >= 244) { - int new_size, chunk_count; + if (type == 0x6d697368 && count >= 244) { + int new_size, chunk_count; offset += 4; offset += 200; - chunk_count = (count-204)/40; - new_size = sizeof(uint64_t) * (s->n_chunks + chunk_count); - s->types = g_realloc(s->types, new_size/2); - s->offsets = g_realloc(s->offsets, new_size); - s->lengths = g_realloc(s->lengths, new_size); - s->sectors = g_realloc(s->sectors, new_size); - s->sectorcounts = g_realloc(s->sectorcounts, new_size); + chunk_count = (count - 204) / 40; + new_size = sizeof(uint64_t) * (s->n_chunks + chunk_count); + s->types = g_realloc(s->types, new_size / 2); + s->offsets = g_realloc(s->offsets, new_size); + s->lengths = g_realloc(s->lengths, new_size); + s->sectors = g_realloc(s->sectors, new_size); + s->sectorcounts = g_realloc(s->sectorcounts, new_size); for (i = s->n_chunks; i < s->n_chunks + chunk_count; i++) { ret = read_uint32(bs, offset, &s->types[i]); if (ret < 0) { goto fail; } - offset += 4; - if(s->types[i]!=0x80000005 && s->types[i]!=1 && s->types[i]!=2) { - if(s->types[i]==0xffffffff) { - last_in_offset = s->offsets[i-1]+s->lengths[i-1]; - last_out_offset = s->sectors[i-1]+s->sectorcounts[i-1]; - } - chunk_count--; - i--; - offset += 36; - continue; - } - offset += 4; + offset += 4; + if (s->types[i] != 0x80000005 && s->types[i] != 1 && + s->types[i] != 2) { + if (s->types[i] == 0xffffffff) { + last_in_offset = s->offsets[i - 1] + s->lengths[i - 1]; + last_out_offset = s->sectors[i - 1] + + s->sectorcounts[i - 1]; + } + chunk_count--; + i--; + offset += 36; + continue; + } + offset += 4; ret = read_uint64(bs, offset, &s->sectors[i]); if (ret < 0) { @@ -218,19 +220,21 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags, } offset += 8; - if(s->lengths[i]>max_compressed_size) - max_compressed_size = s->lengths[i]; - if(s->sectorcounts[i]>max_sectors_per_chunk) - max_sectors_per_chunk = s->sectorcounts[i]; - } - s->n_chunks+=chunk_count; - } + if (s->lengths[i] > max_compressed_size) { + max_compressed_size = s->lengths[i]; + } + if (s->sectorcounts[i] > max_sectors_per_chunk) { + max_sectors_per_chunk = s->sectorcounts[i]; + } + } + s->n_chunks += chunk_count; + } } /* initialize zlib engine */ - s->compressed_chunk = g_malloc(max_compressed_size+1); - s->uncompressed_chunk = g_malloc(512*max_sectors_per_chunk); - if(inflateInit(&s->zstream) != Z_OK) { + s->compressed_chunk = g_malloc(max_compressed_size + 1); + s->uncompressed_chunk = g_malloc(512 * max_sectors_per_chunk); + if (inflateInit(&s->zstream) != Z_OK) { ret = -EINVAL; goto fail; } @@ -252,27 +256,29 @@ fail: } static inline int is_sector_in_chunk(BDRVDMGState* s, - uint32_t chunk_num,int sector_num) + uint32_t chunk_num, int sector_num) { - if(chunk_num>=s->n_chunks || s->sectors[chunk_num]>sector_num || - s->sectors[chunk_num]+s->sectorcounts[chunk_num]<=sector_num) - return 0; - else - return -1; + if (chunk_num >= s->n_chunks || s->sectors[chunk_num] > sector_num || + s->sectors[chunk_num] + s->sectorcounts[chunk_num] <= sector_num) { + return 0; + } else { + return -1; + } } -static inline uint32_t search_chunk(BDRVDMGState* s,int sector_num) +static inline uint32_t search_chunk(BDRVDMGState *s, int sector_num) { /* binary search */ - uint32_t chunk1=0,chunk2=s->n_chunks,chunk3; - while(chunk1!=chunk2) { - chunk3 = (chunk1+chunk2)/2; - if(s->sectors[chunk3]>sector_num) - chunk2 = chunk3; - else if(s->sectors[chunk3]+s->sectorcounts[chunk3]>sector_num) - return chunk3; - else - chunk1 = chunk3; + uint32_t chunk1 = 0, chunk2 = s->n_chunks, chunk3; + while (chunk1 != chunk2) { + chunk3 = (chunk1 + chunk2) / 2; + if (s->sectors[chunk3] > sector_num) { + chunk2 = chunk3; + } else if (s->sectors[chunk3] + s->sectorcounts[chunk3] > sector_num) { + return chunk3; + } else { + chunk1 = chunk3; + } } return s->n_chunks; /* error */ } @@ -281,54 +287,62 @@ static inline int dmg_read_chunk(BlockDriverState *bs, int sector_num) { BDRVDMGState *s = bs->opaque; - if(!is_sector_in_chunk(s,s->current_chunk,sector_num)) { - int ret; - uint32_t chunk = search_chunk(s,sector_num); + if (!is_sector_in_chunk(s, s->current_chunk, sector_num)) { + int ret; + uint32_t chunk = search_chunk(s, sector_num); - if(chunk>=s->n_chunks) - return -1; + if (chunk >= s->n_chunks) { + return -1; + } - s->current_chunk = s->n_chunks; - switch(s->types[chunk]) { - case 0x80000005: { /* zlib compressed */ - int i; + s->current_chunk = s->n_chunks; + switch (s->types[chunk]) { + case 0x80000005: { /* zlib compressed */ + int i; - /* we need to buffer, because only the chunk as whole can be - * inflated. */ - i=0; - do { + /* we need to buffer, because only the chunk as whole can be + * inflated. */ + i = 0; + do { ret = bdrv_pread(bs->file, s->offsets[chunk] + i, - s->compressed_chunk+i, s->lengths[chunk]-i); - if(ret<0 && errno==EINTR) - ret=0; - i+=ret; - } while(ret>=0 && ret+i<s->lengths[chunk]); - - if (ret != s->lengths[chunk]) - return -1; - - s->zstream.next_in = s->compressed_chunk; - s->zstream.avail_in = s->lengths[chunk]; - s->zstream.next_out = s->uncompressed_chunk; - s->zstream.avail_out = 512*s->sectorcounts[chunk]; - ret = inflateReset(&s->zstream); - if(ret != Z_OK) - return -1; - ret = inflate(&s->zstream, Z_FINISH); - if(ret != Z_STREAM_END || s->zstream.total_out != 512*s->sectorcounts[chunk]) - return -1; - break; } - case 1: /* copy */ - ret = bdrv_pread(bs->file, s->offsets[chunk], + s->compressed_chunk + i, + s->lengths[chunk] - i); + if (ret < 0 && errno == EINTR) { + ret = 0; + } + i += ret; + } while (ret >= 0 && ret + i < s->lengths[chunk]); + + if (ret != s->lengths[chunk]) { + return -1; + } + + s->zstream.next_in = s->compressed_chunk; + s->zstream.avail_in = s->lengths[chunk]; + s->zstream.next_out = s->uncompressed_chunk; + s->zstream.avail_out = 512 * s->sectorcounts[chunk]; + ret = inflateReset(&s->zstream); + if (ret != Z_OK) { + return -1; + } + ret = inflate(&s->zstream, Z_FINISH); + if (ret != Z_STREAM_END || + s->zstream.total_out != 512 * s->sectorcounts[chunk]) { + return -1; + } + break; } + case 1: /* copy */ + ret = bdrv_pread(bs->file, s->offsets[chunk], s->uncompressed_chunk, s->lengths[chunk]); - if (ret != s->lengths[chunk]) - return -1; - break; - case 2: /* zero */ - memset(s->uncompressed_chunk, 0, 512*s->sectorcounts[chunk]); - break; - } - s->current_chunk = chunk; + if (ret != s->lengths[chunk]) { + return -1; + } + break; + case 2: /* zero */ + memset(s->uncompressed_chunk, 0, 512 * s->sectorcounts[chunk]); + break; + } + s->current_chunk = chunk; } return 0; } @@ -339,12 +353,14 @@ static int dmg_read(BlockDriverState *bs, int64_t sector_num, BDRVDMGState *s = bs->opaque; int i; - for(i=0;i<nb_sectors;i++) { - uint32_t sector_offset_in_chunk; - if(dmg_read_chunk(bs, sector_num+i) != 0) - return -1; - sector_offset_in_chunk = sector_num+i-s->sectors[s->current_chunk]; - memcpy(buf+i*512,s->uncompressed_chunk+sector_offset_in_chunk*512,512); + for (i = 0; i < nb_sectors; i++) { + uint32_t sector_offset_in_chunk; + if (dmg_read_chunk(bs, sector_num + i) != 0) { + return -1; + } + sector_offset_in_chunk = sector_num + i - s->sectors[s->current_chunk]; + memcpy(buf + i * 512, + s->uncompressed_chunk + sector_offset_in_chunk * 512, 512); } return 0; } @@ -376,12 +392,12 @@ static void dmg_close(BlockDriverState *bs) } static BlockDriver bdrv_dmg = { - .format_name = "dmg", - .instance_size = sizeof(BDRVDMGState), - .bdrv_probe = dmg_probe, - .bdrv_open = dmg_open, - .bdrv_read = dmg_co_read, - .bdrv_close = dmg_close, + .format_name = "dmg", + .instance_size = sizeof(BDRVDMGState), + .bdrv_probe = dmg_probe, + .bdrv_open = dmg_open, + .bdrv_read = dmg_co_read, + .bdrv_close = dmg_close, }; static void bdrv_dmg_init(void) |