qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: John Snow <jsnow@redhat.com>
To: Peter Wu <peter@lekensteyn.nl>, qemu-devel@nongnu.org
Cc: Kevin Wolf <kwolf@redhat.com>,
	"pbonzini >> Paolo Bonzini" <pbonzini@redhat.com>,
	Stefan Hajnoczi <stefanha@redhat.com>
Subject: Re: [Qemu-devel] [PATCH 09/10] block/dmg: support bzip2 block entry types
Date: Mon, 05 Jan 2015 14:32:29 -0500	[thread overview]
Message-ID: <54AAE6CD.9080007@redhat.com> (raw)
In-Reply-To: <1419692504-29373-10-git-send-email-peter@lekensteyn.nl>



On 12/27/2014 10:01 AM, Peter Wu wrote:
> 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>
> ---
>   block/dmg.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++---
>   configure   | 31 +++++++++++++++++++++++++++++++
>   2 files changed, 84 insertions(+), 3 deletions(-)
>
> diff --git a/block/dmg.c b/block/dmg.c
> index 93b597f..67d4e2b 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;
> @@ -187,6 +194,21 @@ typedef struct DmgHeaderState {
>       uint32_t max_sectors_per_chunk;
>   } DmgHeaderState;
>
> +static bool dmg_is_valid_block_type(uint32_t entry_type)
> +{
> +    switch (entry_type) {
> +    case 0x00000001:    /* uncompressed */
> +    case 0x00000002:    /* zeroes */
> +    case 0x80000005:    /* zlib */
> +#ifdef CONFIG_BZIP2
> +    case 0x80000006:    /* bzip2 */
> +#endif
> +        return true;
> +    default:
> +        return false;
> +    }
> +}
> +

Wish I had read this patch first before trying to read the blob of 
conditionals this replaces. :)

>   static int dmg_read_mish_block(BDRVDMGState *s, DmgHeaderState *ds,
>                                  uint8_t *buffer, uint32_t count)
>   {
> @@ -218,8 +240,7 @@ static int dmg_read_mish_block(BDRVDMGState *s, DmgHeaderState *ds,
>       for (i = s->n_chunks; i < s->n_chunks + chunk_count; i++) {
>           s->types[i] = buff_read_uint32(buffer, offset);
>           offset += 4;
> -        if (s->types[i] != 0x80000005 && s->types[i] != 1 &&
> -            s->types[i] != 2) {
> +        if (!dmg_is_valid_block_type(s->types[i])) {
>               if (s->types[i] == 0xffffffff && i > 0) {
>                   ds->last_in_offset = s->offsets[i - 1] + s->lengths[i - 1];
>                   ds->last_out_offset = s->sectors[i - 1] +
> @@ -534,13 +555,14 @@ 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);
> +        uint64_t total_out;

This breaks compilation when configured with --disable-bzip2. (unused 
variable)

>
>           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. */
> @@ -564,6 +586,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 cae588c..eadae63 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,25 @@ 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
> +        libs_softmmu="$libs_softmmu -lbz2"
> +        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
> @@ -4340,6 +4366,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
> @@ -4695,6 +4722,10 @@ 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
> +fi
> +
>   if test "$libiscsi" = "yes" ; then
>     echo "CONFIG_LIBISCSI=m" >> $config_host_mak
>     echo "LIBISCSI_CFLAGS=$libiscsi_cflags" >> $config_host_mak
>

Looks good otherwise. CCing Paolo so he can take a quick peek at the 
configure script. It looks sane to me, though.

  reply	other threads:[~2015-01-05 19:32 UTC|newest]

Thread overview: 39+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-12-27 15:01 [Qemu-devel] [PATCH 00/10] block/dmg: (compatibility) fixes and bzip2 support Peter Wu
2014-12-27 15:01 ` [Qemu-devel] [PATCH 01/10] block/dmg: properly detect the UDIF trailer Peter Wu
2015-01-02 23:58   ` John Snow
2015-01-03  9:39     ` Peter Wu
2015-01-06 13:35   ` Stefan Hajnoczi
2014-12-27 15:01 ` [Qemu-devel] [PATCH 02/10] block/dmg: extract mish block decoding functionality Peter Wu
2015-01-02 23:59   ` John Snow
2015-01-03 11:05     ` Peter Wu
2015-01-06 13:42   ` Stefan Hajnoczi
2014-12-27 15:01 ` [Qemu-devel] [PATCH 03/10] block/dmg: extract processing of resource forks Peter Wu
2015-01-03  0:01   ` John Snow
2015-01-03 11:24     ` Peter Wu
2014-12-27 15:01 ` [Qemu-devel] [PATCH 04/10] block/dmg: process a buffer instead of reading ints Peter Wu
2015-01-03  0:01   ` John Snow
2014-12-27 15:01 ` [Qemu-devel] [PATCH 05/10] block/dmg: validate chunk size to avoid overflow Peter Wu
2015-01-03  0:02   ` John Snow
2014-12-27 15:01 ` [Qemu-devel] [PATCH 06/10] block/dmg: process XML plists Peter Wu
2015-01-03  0:04   ` John Snow
2015-01-03 11:54     ` Peter Wu
2015-01-05 16:46       ` John Snow
2015-01-05 16:54   ` John Snow
2014-12-27 15:01 ` [Qemu-devel] [PATCH 07/10] block/dmg: set virtual size to a non-zero value Peter Wu
2015-01-03  0:04   ` John Snow
2014-12-27 15:01 ` [Qemu-devel] [PATCH 08/10] block/dmg: fix sector data offset calculation Peter Wu
2015-01-03  0:05   ` John Snow
2015-01-03 12:47     ` Peter Wu
2014-12-27 15:01 ` [Qemu-devel] [PATCH 09/10] block/dmg: support bzip2 block entry types Peter Wu
2015-01-05 19:32   ` John Snow [this message]
2015-01-07 10:29     ` Paolo Bonzini
2015-01-07 10:31       ` Peter Wu
2015-01-07 10:53         ` Paolo Bonzini
2014-12-27 15:01 ` [Qemu-devel] [PATCH 10/10] block/dmg: improve zeroes handling Peter Wu
2015-01-05 19:48   ` John Snow
2015-01-06  0:21     ` Peter Wu
2015-01-02 14:14 ` [Qemu-devel] [PATCH 00/10] block/dmg: (compatibility) fixes and bzip2 support Stefan Hajnoczi
2015-01-02 16:31   ` John Snow
2015-01-02 18:46     ` Peter Wu
2015-01-02 18:58       ` John Snow
2015-01-02 21:49         ` Peter Wu

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=54AAE6CD.9080007@redhat.com \
    --to=jsnow@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=peter@lekensteyn.nl \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@redhat.com \
    /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).