aboutsummaryrefslogtreecommitdiff
path: root/block/dmg.c
diff options
context:
space:
mode:
Diffstat (limited to 'block/dmg.c')
-rw-r--r--block/dmg.c69
1 files changed, 17 insertions, 52 deletions
diff --git a/block/dmg.c b/block/dmg.c
index b0ed89baa7..58a3ae86c1 100644
--- a/block/dmg.c
+++ b/block/dmg.c
@@ -28,10 +28,10 @@
#include "qemu/bswap.h"
#include "qemu/error-report.h"
#include "qemu/module.h"
-#include <zlib.h>
-#ifdef CONFIG_BZIP2
-#include <bzlib.h>
-#endif
+#include "dmg.h"
+
+int (*dmg_uncompress_bz2)(char *next_in, unsigned int avail_in,
+ char *next_out, unsigned int avail_out);
enum {
/* Limit chunk sizes to prevent unreasonable amounts of memory being used
@@ -41,31 +41,6 @@ enum {
DMG_SECTORCOUNTS_MAX = DMG_LENGTHS_MAX / 512,
};
-typedef struct BDRVDMGState {
- CoMutex lock;
- /* each chunk contains a certain number of sectors,
- * offsets[i] is the offset in the .dmg file,
- * lengths[i] is the length of the compressed chunk,
- * sectors[i] is the sector beginning at offsets[i],
- * sectorcounts[i] is the number of sectors in that chunk,
- * the sectors array is ordered
- * 0<=i<n_chunks */
-
- uint32_t n_chunks;
- uint32_t* types;
- uint64_t* offsets;
- uint64_t* lengths;
- uint64_t* sectors;
- uint64_t* sectorcounts;
- uint32_t current_chunk;
- uint8_t *compressed_chunk;
- uint8_t *uncompressed_chunk;
- z_stream zstream;
-#ifdef CONFIG_BZIP2
- bz_stream bzstream;
-#endif
-} BDRVDMGState;
-
static int dmg_probe(const uint8_t *buf, int buf_size, const char *filename)
{
int len;
@@ -210,10 +185,9 @@ static bool dmg_is_known_block_type(uint32_t entry_type)
case 0x00000001: /* uncompressed */
case 0x00000002: /* zeroes */
case 0x80000005: /* zlib */
-#ifdef CONFIG_BZIP2
- case 0x80000006: /* bzip2 */
-#endif
return true;
+ case 0x80000006: /* bzip2 */
+ return !!dmg_uncompress_bz2;
default:
return false;
}
@@ -439,6 +413,7 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
int64_t offset;
int ret;
+ block_module_load_one("dmg-bz2");
bs->read_only = true;
s->n_chunks = 0;
@@ -587,9 +562,6 @@ static inline int dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num)
if (!is_sector_in_chunk(s, s->current_chunk, sector_num)) {
int ret;
uint32_t chunk = search_chunk(s, sector_num);
-#ifdef CONFIG_BZIP2
- uint64_t total_out;
-#endif
if (chunk >= s->n_chunks) {
return -1;
@@ -620,8 +592,10 @@ static inline int dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num)
return -1;
}
break; }
-#ifdef CONFIG_BZIP2
case 0x80000006: /* bzip2 compressed */
+ if (!dmg_uncompress_bz2) {
+ break;
+ }
/* we need to buffer, because only the chunk as whole can be
* inflated. */
ret = bdrv_pread(bs->file, s->offsets[chunk],
@@ -630,24 +604,15 @@ static inline int dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num)
return -1;
}
- ret = BZ2_bzDecompressInit(&s->bzstream, 0, 0);
- if (ret != BZ_OK) {
- return -1;
- }
- s->bzstream.next_in = (char *)s->compressed_chunk;
- s->bzstream.avail_in = (unsigned int) s->lengths[chunk];
- s->bzstream.next_out = (char *)s->uncompressed_chunk;
- s->bzstream.avail_out = (unsigned int) 512 * s->sectorcounts[chunk];
- ret = BZ2_bzDecompress(&s->bzstream);
- total_out = ((uint64_t)s->bzstream.total_out_hi32 << 32) +
- s->bzstream.total_out_lo32;
- BZ2_bzDecompressEnd(&s->bzstream);
- if (ret != BZ_STREAM_END ||
- total_out != 512 * s->sectorcounts[chunk]) {
- return -1;
+ ret = dmg_uncompress_bz2((char *)s->compressed_chunk,
+ (unsigned int) s->lengths[chunk],
+ (char *)s->uncompressed_chunk,
+ (unsigned int)
+ (512 * s->sectorcounts[chunk]));
+ if (ret < 0) {
+ return ret;
}
break;
-#endif /* CONFIG_BZIP2 */
case 1: /* copy */
ret = bdrv_pread(bs->file, s->offsets[chunk],
s->uncompressed_chunk, s->lengths[chunk]);