From: Kevin Wolf <kwolf@redhat.com>
To: qemu-devel@nongnu.org
Cc: kwolf@redhat.com
Subject: [Qemu-devel] [PULL 30/42] block/dmg: support bzip2 block entry types
Date: Fri, 6 Feb 2015 17:40:37 +0100 [thread overview]
Message-ID: <1423240849-15499-31-git-send-email-kwolf@redhat.com> (raw)
In-Reply-To: <1423240849-15499-1-git-send-email-kwolf@redhat.com>
From: Peter Wu <peter@lekensteyn.nl>
This patch adds support for bzip2-compressed block entries as introduced
with OS X 10.4 (source: https://en.wikipedia.org/wiki/Apple_Disk_Image).
It was tested against a 5.2G "OS X Yosemite" installation image which
stores the BLXX block in the XML property list (instead of resource
forks) and has over 5k chunks.
New configure entries are added (--enable-bzip2 / --disable-bzip2) to
control inclusion of bzip2 functionality (which requires linking against
libbz2). The help message suggests that this option is needed for DMG
files, but the tests are generic enough that other parts of QEMU can use
bzip2 if needed.
The identifiers are based on http://newosxbook.com/DMG.html.
The decompression routines are based on the zlib case, but as there is
no way to reset the decompression state (unlike zlib), memory is
allocated and deallocated for every decompression. This should not be
problematic as the decompression takes most of the time and as blocks
are typically about/over 1 MiB in size, only one allocation is done
every 2000 sectors.
Signed-off-by: Peter Wu <peter@lekensteyn.nl>
Reviewed-by: John Snow <jsnow@redhat.com>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
Message-id: 1420566495-13284-12-git-send-email-peter@lekensteyn.nl
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
block/Makefile.objs | 1 +
block/dmg.c | 43 ++++++++++++++++++++++++++++++++++++++++++-
configure | 31 +++++++++++++++++++++++++++++++
3 files changed, 74 insertions(+), 1 deletion(-)
diff --git a/block/Makefile.objs b/block/Makefile.objs
index 010afad..db2933e 100644
--- a/block/Makefile.objs
+++ b/block/Makefile.objs
@@ -37,5 +37,6 @@ gluster.o-libs := $(GLUSTERFS_LIBS)
ssh.o-cflags := $(LIBSSH2_CFLAGS)
ssh.o-libs := $(LIBSSH2_LIBS)
archipelago.o-libs := $(ARCHIPELAGO_LIBS)
+dmg.o-libs := $(BZIP2_LIBS)
qcow.o-libs := -lz
linux-aio.o-libs := -laio
diff --git a/block/dmg.c b/block/dmg.c
index cc584b5..797fda3 100644
--- a/block/dmg.c
+++ b/block/dmg.c
@@ -26,6 +26,9 @@
#include "qemu/bswap.h"
#include "qemu/module.h"
#include <zlib.h>
+#ifdef CONFIG_BZIP2
+#include <bzlib.h>
+#endif
#include <glib.h>
enum {
@@ -56,6 +59,9 @@ typedef struct BDRVDMGState {
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)
@@ -123,6 +129,7 @@ static void update_max_chunk_size(BDRVDMGState *s, uint32_t chunk,
switch (s->types[chunk]) {
case 0x80000005: /* zlib compressed */
+ case 0x80000006: /* bzip2 compressed */
compressed_size = s->lengths[chunk];
uncompressed_sectors = s->sectorcounts[chunk];
break;
@@ -198,6 +205,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;
default:
return false;
@@ -564,13 +574,16 @@ 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;
}
s->current_chunk = s->n_chunks;
- switch (s->types[chunk]) {
+ switch (s->types[chunk]) { /* block entry type */
case 0x80000005: { /* zlib compressed */
/* we need to buffer, because only the chunk as whole can be
* inflated. */
@@ -594,6 +607,34 @@ static inline int dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num)
return -1;
}
break; }
+#ifdef CONFIG_BZIP2
+ case 0x80000006: /* bzip2 compressed */
+ /* we need to buffer, because only the chunk as whole can be
+ * inflated. */
+ ret = bdrv_pread(bs->file, s->offsets[chunk],
+ s->compressed_chunk, s->lengths[chunk]);
+ if (ret != s->lengths[chunk]) {
+ 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;
+ }
+ break;
+#endif /* CONFIG_BZIP2 */
case 1: /* copy */
ret = bdrv_pread(bs->file, s->offsets[chunk],
s->uncompressed_chunk, s->lengths[chunk]);
diff --git a/configure b/configure
index e00e03a..7ba4bcb 100755
--- a/configure
+++ b/configure
@@ -313,6 +313,7 @@ glx=""
zlib="yes"
lzo=""
snappy=""
+bzip2=""
guest_agent=""
guest_agent_with_vss="no"
vss_win32_sdk=""
@@ -1060,6 +1061,10 @@ for opt do
;;
--enable-snappy) snappy="yes"
;;
+ --disable-bzip2) bzip2="no"
+ ;;
+ --enable-bzip2) bzip2="yes"
+ ;;
--enable-guest-agent) guest_agent="yes"
;;
--disable-guest-agent) guest_agent="no"
@@ -1374,6 +1379,8 @@ Advanced options (experts only):
--enable-usb-redir enable usb network redirection support
--enable-lzo enable the support of lzo compression library
--enable-snappy enable the support of snappy compression library
+ --enable-bzip2 enable the support of bzip2 compression library (for
+ reading bzip2-compressed dmg images)
--disable-guest-agent disable building of the QEMU Guest Agent
--enable-guest-agent enable building of the QEMU Guest Agent
--with-vss-sdk=SDK-path enable Windows VSS support in QEMU Guest Agent
@@ -1820,6 +1827,24 @@ EOF
fi
##########################################
+# bzip2 check
+
+if test "$bzip2" != "no" ; then
+ cat > $TMPC << EOF
+#include <bzlib.h>
+int main(void) { BZ2_bzlibVersion(); return 0; }
+EOF
+ if compile_prog "" "-lbz2" ; then
+ bzip2="yes"
+ else
+ if test "$bzip2" = "yes"; then
+ feature_not_found "libbzip2" "Install libbzip2 devel"
+ fi
+ bzip2="no"
+ fi
+fi
+
+##########################################
# libseccomp check
if test "$seccomp" != "no" ; then
@@ -4385,6 +4410,7 @@ echo "vhdx $vhdx"
echo "Quorum $quorum"
echo "lzo support $lzo"
echo "snappy support $snappy"
+echo "bzip2 support $bzip2"
echo "NUMA host support $numa"
if test "$sdl_too_old" = "yes"; then
@@ -4743,6 +4769,11 @@ if test "$snappy" = "yes" ; then
echo "CONFIG_SNAPPY=y" >> $config_host_mak
fi
+if test "$bzip2" = "yes" ; then
+ echo "CONFIG_BZIP2=y" >> $config_host_mak
+ echo "BZIP2_LIBS=-lbz2" >> $config_host_mak
+fi
+
if test "$libiscsi" = "yes" ; then
echo "CONFIG_LIBISCSI=m" >> $config_host_mak
echo "LIBISCSI_CFLAGS=$libiscsi_cflags" >> $config_host_mak
--
1.8.3.1
next prev parent reply other threads:[~2015-02-06 16:41 UTC|newest]
Thread overview: 45+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-02-06 16:40 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 01/42] Restore atapi_dma flag across migration Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 02/42] atapi migration: Throw recoverable error to avoid recovery Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 03/42] block/raw-posix: create translate_err helper to merge errno values Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 04/42] block/raw-posix: create do_fallocate helper Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 05/42] block/raw-posix: refactor handle_aiocb_write_zeroes a bit Kevin Wolf
2015-02-12 2:29 ` Peter Maydell
2015-02-12 4:44 ` Denis V. Lunev
2015-02-06 16:40 ` [Qemu-devel] [PULL 06/42] block: use fallocate(FALLOC_FL_ZERO_RANGE) in handle_aiocb_write_zeroes Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 07/42] block/raw-posix: call plain fallocate " Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 08/42] block: use fallocate(FALLOC_FL_PUNCH_HOLE) & fallocate(0) to write zeroes Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 09/42] block: change default for discard and write zeroes to INT_MAX Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 10/42] qemu-img: Add QEMU_PKGVERSION to QEMU_IMG_VERSION Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 11/42] qed: Really remove unused field QEDAIOCB.finished Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 12/42] block: add accounting for merged requests Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 13/42] hw/virtio-blk: add a constant for max number of " Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 14/42] block-backend: expose bs->bl.max_transfer_length Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 15/42] virtio-blk: introduce multiread Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 16/42] virtio-blk: add a knob to disable request merging Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 17/42] qemu-iotests: Fix supported_oses check Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 18/42] iotests: Specify format for qemu-nbd Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 19/42] block: add event when disk usage exceeds threshold Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 20/42] block/dmg: properly detect the UDIF trailer Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 21/42] block/dmg: extract mish block decoding functionality Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 22/42] block/dmg: extract processing of resource forks Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 23/42] block/dmg: process a buffer instead of reading ints Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 24/42] block/dmg: validate chunk size to avoid overflow Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 25/42] block/dmg: process XML plists Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 26/42] block/dmg: set virtual size to a non-zero value Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 27/42] block/dmg: fix sector data offset calculation Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 28/42] block/dmg: use SectorNumber from BLKX header Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 29/42] block/dmg: factor out block type check Kevin Wolf
2015-02-06 16:40 ` Kevin Wolf [this message]
2015-02-06 16:40 ` [Qemu-devel] [PULL 31/42] block/dmg: improve zeroes handling Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 32/42] qed: check for header size overflow Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 33/42] qemu-iotests: add 116 invalid QED input file tests Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 34/42] block: fix off-by-one error in qcow and qcow2 Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 35/42] iotests: Fix 083 Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 36/42] iotests: Fix 100 for nbd Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 37/42] iotests: Fix 104 for NBD Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 38/42] nbd: Improve error messages Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 39/42] block: introduce BDRV_REQUEST_MAX_SECTORS Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 40/42] nbd: fix max_discard/max_transfer_length Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 41/42] block: Give always priority to unused entries in the qcow2 L2 cache Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 42/42] qcow2: Rewrite qcow2_alloc_bytes() Kevin Wolf
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1423240849-15499-31-git-send-email-kwolf@redhat.com \
--to=kwolf@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).