qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

dmg.c (24680B)


      1 /*
      2  * QEMU Block driver for DMG images
      3  *
      4  * Copyright (c) 2004 Johannes E. Schindelin
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a copy
      7  * of this software and associated documentation files (the "Software"), to deal
      8  * in the Software without restriction, including without limitation the rights
      9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     10  * copies of the Software, and to permit persons to whom the Software is
     11  * furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be included in
     14  * all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     22  * THE SOFTWARE.
     23  */
     24 #include "qemu/osdep.h"
     25 #include "qapi/error.h"
     26 #include "block/block_int.h"
     27 #include "qemu/bswap.h"
     28 #include "qemu/error-report.h"
     29 #include "qemu/module.h"
     30 #include "qemu/memalign.h"
     31 #include "dmg.h"
     32 
     33 int (*dmg_uncompress_bz2)(char *next_in, unsigned int avail_in,
     34                           char *next_out, unsigned int avail_out);
     35 
     36 int (*dmg_uncompress_lzfse)(char *next_in, unsigned int avail_in,
     37                             char *next_out, unsigned int avail_out);
     38 
     39 enum {
     40     /* Limit chunk sizes to prevent unreasonable amounts of memory being used
     41      * or truncating when converting to 32-bit types
     42      */
     43     DMG_LENGTHS_MAX = 64 * 1024 * 1024, /* 64 MB */
     44     DMG_SECTORCOUNTS_MAX = DMG_LENGTHS_MAX / 512,
     45 };
     46 
     47 enum {
     48     /* DMG Block Type */
     49     UDZE = 0, /* Zeroes */
     50     UDRW,     /* RAW type */
     51     UDIG,     /* Ignore */
     52     UDCO = 0x80000004,
     53     UDZO,
     54     UDBZ,
     55     ULFO,
     56     UDCM = 0x7ffffffe, /* Comments */
     57     UDLE = 0xffffffff  /* Last Entry */
     58 };
     59 
     60 static int dmg_probe(const uint8_t *buf, int buf_size, const char *filename)
     61 {
     62     int len;
     63 
     64     if (!filename) {
     65         return 0;
     66     }
     67 
     68     len = strlen(filename);
     69     if (len > 4 && !strcmp(filename + len - 4, ".dmg")) {
     70         return 2;
     71     }
     72     return 0;
     73 }
     74 
     75 static int read_uint64(BlockDriverState *bs, int64_t offset, uint64_t *result)
     76 {
     77     uint64_t buffer;
     78     int ret;
     79 
     80     ret = bdrv_pread(bs->file, offset, 8, &buffer, 0);
     81     if (ret < 0) {
     82         return ret;
     83     }
     84 
     85     *result = be64_to_cpu(buffer);
     86     return 0;
     87 }
     88 
     89 static int read_uint32(BlockDriverState *bs, int64_t offset, uint32_t *result)
     90 {
     91     uint32_t buffer;
     92     int ret;
     93 
     94     ret = bdrv_pread(bs->file, offset, 4, &buffer, 0);
     95     if (ret < 0) {
     96         return ret;
     97     }
     98 
     99     *result = be32_to_cpu(buffer);
    100     return 0;
    101 }
    102 
    103 static inline uint64_t buff_read_uint64(const uint8_t *buffer, int64_t offset)
    104 {
    105     return be64_to_cpu(*(uint64_t *)&buffer[offset]);
    106 }
    107 
    108 static inline uint32_t buff_read_uint32(const uint8_t *buffer, int64_t offset)
    109 {
    110     return be32_to_cpu(*(uint32_t *)&buffer[offset]);
    111 }
    112 
    113 /* Increase max chunk sizes, if necessary.  This function is used to calculate
    114  * the buffer sizes needed for compressed/uncompressed chunk I/O.
    115  */
    116 static void update_max_chunk_size(BDRVDMGState *s, uint32_t chunk,
    117                                   uint32_t *max_compressed_size,
    118                                   uint32_t *max_sectors_per_chunk)
    119 {
    120     uint32_t compressed_size = 0;
    121     uint32_t uncompressed_sectors = 0;
    122 
    123     switch (s->types[chunk]) {
    124     case UDZO: /* zlib compressed */
    125     case UDBZ: /* bzip2 compressed */
    126     case ULFO: /* lzfse compressed */
    127         compressed_size = s->lengths[chunk];
    128         uncompressed_sectors = s->sectorcounts[chunk];
    129         break;
    130     case UDRW: /* copy */
    131         uncompressed_sectors = DIV_ROUND_UP(s->lengths[chunk], 512);
    132         break;
    133     case UDZE: /* zero */
    134     case UDIG: /* ignore */
    135         /* as the all-zeroes block may be large, it is treated specially: the
    136          * sector is not copied from a large buffer, a simple memset is used
    137          * instead. Therefore uncompressed_sectors does not need to be set. */
    138         break;
    139     }
    140 
    141     if (compressed_size > *max_compressed_size) {
    142         *max_compressed_size = compressed_size;
    143     }
    144     if (uncompressed_sectors > *max_sectors_per_chunk) {
    145         *max_sectors_per_chunk = uncompressed_sectors;
    146     }
    147 }
    148 
    149 static int64_t dmg_find_koly_offset(BdrvChild *file, Error **errp)
    150 {
    151     BlockDriverState *file_bs = file->bs;
    152     int64_t length;
    153     int64_t offset = 0;
    154     uint8_t buffer[515];
    155     int i, ret;
    156 
    157     /* bdrv_getlength returns a multiple of block size (512), rounded up. Since
    158      * dmg images can have odd sizes, try to look for the "koly" magic which
    159      * marks the begin of the UDIF trailer (512 bytes). This magic can be found
    160      * in the last 511 bytes of the second-last sector or the first 4 bytes of
    161      * the last sector (search space: 515 bytes) */
    162     length = bdrv_getlength(file_bs);
    163     if (length < 0) {
    164         error_setg_errno(errp, -length,
    165             "Failed to get file size while reading UDIF trailer");
    166         return length;
    167     } else if (length < 512) {
    168         error_setg(errp, "dmg file must be at least 512 bytes long");
    169         return -EINVAL;
    170     }
    171     if (length > 511 + 512) {
    172         offset = length - 511 - 512;
    173     }
    174     length = length < 515 ? length : 515;
    175     ret = bdrv_pread(file, offset, length, buffer, 0);
    176     if (ret < 0) {
    177         error_setg_errno(errp, -ret, "Failed while reading UDIF trailer");
    178         return ret;
    179     }
    180     for (i = 0; i < length - 3; i++) {
    181         if (buffer[i] == 'k' && buffer[i+1] == 'o' &&
    182             buffer[i+2] == 'l' && buffer[i+3] == 'y') {
    183             return offset + i;
    184         }
    185     }
    186     error_setg(errp, "Could not locate UDIF trailer in dmg file");
    187     return -EINVAL;
    188 }
    189 
    190 /* used when building the sector table */
    191 typedef struct DmgHeaderState {
    192     /* used internally by dmg_read_mish_block to remember offsets of blocks
    193      * across calls */
    194     uint64_t data_fork_offset;
    195     /* exported for dmg_open */
    196     uint32_t max_compressed_size;
    197     uint32_t max_sectors_per_chunk;
    198 } DmgHeaderState;
    199 
    200 static bool dmg_is_known_block_type(uint32_t entry_type)
    201 {
    202     switch (entry_type) {
    203     case UDZE:    /* zeros */
    204     case UDRW:    /* uncompressed */
    205     case UDIG:    /* ignore */
    206     case UDZO:    /* zlib */
    207         return true;
    208     case UDBZ:    /* bzip2 */
    209         return !!dmg_uncompress_bz2;
    210     case ULFO:    /* lzfse */
    211         return !!dmg_uncompress_lzfse;
    212     default:
    213         return false;
    214     }
    215 }
    216 
    217 static int dmg_read_mish_block(BDRVDMGState *s, DmgHeaderState *ds,
    218                                uint8_t *buffer, uint32_t count)
    219 {
    220     uint32_t type, i;
    221     int ret;
    222     size_t new_size;
    223     uint32_t chunk_count;
    224     int64_t offset = 0;
    225     uint64_t data_offset;
    226     uint64_t in_offset = ds->data_fork_offset;
    227     uint64_t out_offset;
    228 
    229     type = buff_read_uint32(buffer, offset);
    230     /* skip data that is not a valid MISH block (invalid magic or too small) */
    231     if (type != 0x6d697368 || count < 244) {
    232         /* assume success for now */
    233         return 0;
    234     }
    235 
    236     /* chunk offsets are relative to this sector number */
    237     out_offset = buff_read_uint64(buffer, offset + 8);
    238 
    239     /* location in data fork for (compressed) blob (in bytes) */
    240     data_offset = buff_read_uint64(buffer, offset + 0x18);
    241     in_offset += data_offset;
    242 
    243     /* move to begin of chunk entries */
    244     offset += 204;
    245 
    246     chunk_count = (count - 204) / 40;
    247     new_size = sizeof(uint64_t) * (s->n_chunks + chunk_count);
    248     s->types = g_realloc(s->types, new_size / 2);
    249     s->offsets = g_realloc(s->offsets, new_size);
    250     s->lengths = g_realloc(s->lengths, new_size);
    251     s->sectors = g_realloc(s->sectors, new_size);
    252     s->sectorcounts = g_realloc(s->sectorcounts, new_size);
    253 
    254     for (i = s->n_chunks; i < s->n_chunks + chunk_count; i++) {
    255         s->types[i] = buff_read_uint32(buffer, offset);
    256         if (!dmg_is_known_block_type(s->types[i])) {
    257             switch (s->types[i]) {
    258             case UDBZ:
    259                 warn_report_once("dmg-bzip2 module is missing, accessing bzip2 "
    260                                  "compressed blocks will result in I/O errors");
    261                 break;
    262             case ULFO:
    263                 warn_report_once("dmg-lzfse module is missing, accessing lzfse "
    264                                  "compressed blocks will result in I/O errors");
    265                 break;
    266             case UDCM:
    267             case UDLE:
    268                 /* Comments and last entry can be ignored without problems */
    269                 break;
    270             default:
    271                 warn_report_once("Image contains chunks of unknown type %x, "
    272                                  "accessing them will result in I/O errors",
    273                                  s->types[i]);
    274                 break;
    275             }
    276             chunk_count--;
    277             i--;
    278             offset += 40;
    279             continue;
    280         }
    281 
    282         /* sector number */
    283         s->sectors[i] = buff_read_uint64(buffer, offset + 8);
    284         s->sectors[i] += out_offset;
    285 
    286         /* sector count */
    287         s->sectorcounts[i] = buff_read_uint64(buffer, offset + 0x10);
    288 
    289         /* all-zeroes sector (type UDZE and UDIG) does not need to be
    290          * "uncompressed" and can therefore be unbounded. */
    291         if (s->types[i] != UDZE && s->types[i] != UDIG
    292             && s->sectorcounts[i] > DMG_SECTORCOUNTS_MAX) {
    293             error_report("sector count %" PRIu64 " for chunk %" PRIu32
    294                          " is larger than max (%u)",
    295                          s->sectorcounts[i], i, DMG_SECTORCOUNTS_MAX);
    296             ret = -EINVAL;
    297             goto fail;
    298         }
    299 
    300         /* offset in (compressed) data fork */
    301         s->offsets[i] = buff_read_uint64(buffer, offset + 0x18);
    302         s->offsets[i] += in_offset;
    303 
    304         /* length in (compressed) data fork */
    305         s->lengths[i] = buff_read_uint64(buffer, offset + 0x20);
    306 
    307         if (s->lengths[i] > DMG_LENGTHS_MAX) {
    308             error_report("length %" PRIu64 " for chunk %" PRIu32
    309                          " is larger than max (%u)",
    310                          s->lengths[i], i, DMG_LENGTHS_MAX);
    311             ret = -EINVAL;
    312             goto fail;
    313         }
    314 
    315         update_max_chunk_size(s, i, &ds->max_compressed_size,
    316                               &ds->max_sectors_per_chunk);
    317         offset += 40;
    318     }
    319     s->n_chunks += chunk_count;
    320     return 0;
    321 
    322 fail:
    323     return ret;
    324 }
    325 
    326 static int dmg_read_resource_fork(BlockDriverState *bs, DmgHeaderState *ds,
    327                                   uint64_t info_begin, uint64_t info_length)
    328 {
    329     BDRVDMGState *s = bs->opaque;
    330     int ret;
    331     uint32_t count, rsrc_data_offset;
    332     uint8_t *buffer = NULL;
    333     uint64_t info_end;
    334     uint64_t offset;
    335 
    336     /* read offset from begin of resource fork (info_begin) to resource data */
    337     ret = read_uint32(bs, info_begin, &rsrc_data_offset);
    338     if (ret < 0) {
    339         goto fail;
    340     } else if (rsrc_data_offset > info_length) {
    341         ret = -EINVAL;
    342         goto fail;
    343     }
    344 
    345     /* read length of resource data */
    346     ret = read_uint32(bs, info_begin + 8, &count);
    347     if (ret < 0) {
    348         goto fail;
    349     } else if (count == 0 || rsrc_data_offset + count > info_length) {
    350         ret = -EINVAL;
    351         goto fail;
    352     }
    353 
    354     /* begin of resource data (consisting of one or more resources) */
    355     offset = info_begin + rsrc_data_offset;
    356 
    357     /* end of resource data (there is possibly a following resource map
    358      * which will be ignored). */
    359     info_end = offset + count;
    360 
    361     /* read offsets (mish blocks) from one or more resources in resource data */
    362     while (offset < info_end) {
    363         /* size of following resource */
    364         ret = read_uint32(bs, offset, &count);
    365         if (ret < 0) {
    366             goto fail;
    367         } else if (count == 0 || count > info_end - offset) {
    368             ret = -EINVAL;
    369             goto fail;
    370         }
    371         offset += 4;
    372 
    373         buffer = g_realloc(buffer, count);
    374         ret = bdrv_pread(bs->file, offset, count, buffer, 0);
    375         if (ret < 0) {
    376             goto fail;
    377         }
    378 
    379         ret = dmg_read_mish_block(s, ds, buffer, count);
    380         if (ret < 0) {
    381             goto fail;
    382         }
    383         /* advance offset by size of resource */
    384         offset += count;
    385     }
    386     ret = 0;
    387 
    388 fail:
    389     g_free(buffer);
    390     return ret;
    391 }
    392 
    393 static int dmg_read_plist_xml(BlockDriverState *bs, DmgHeaderState *ds,
    394                               uint64_t info_begin, uint64_t info_length)
    395 {
    396     BDRVDMGState *s = bs->opaque;
    397     int ret;
    398     uint8_t *buffer = NULL;
    399     char *data_begin, *data_end;
    400 
    401     /* Have at least some length to avoid NULL for g_malloc. Attempt to set a
    402      * safe upper cap on the data length. A test sample had a XML length of
    403      * about 1 MiB. */
    404     if (info_length == 0 || info_length > 16 * 1024 * 1024) {
    405         ret = -EINVAL;
    406         goto fail;
    407     }
    408 
    409     buffer = g_malloc(info_length + 1);
    410     buffer[info_length] = '\0';
    411     ret = bdrv_pread(bs->file, info_begin, info_length, buffer, 0);
    412     if (ret < 0) {
    413         ret = -EINVAL;
    414         goto fail;
    415     }
    416 
    417     /* look for <data>...</data>. The data is 284 (0x11c) bytes after base64
    418      * decode. The actual data element has 431 (0x1af) bytes which includes tabs
    419      * and line feeds. */
    420     data_end = (char *)buffer;
    421     while ((data_begin = strstr(data_end, "<data>")) != NULL) {
    422         guchar *mish;
    423         gsize out_len = 0;
    424 
    425         data_begin += 6;
    426         data_end = strstr(data_begin, "</data>");
    427         /* malformed XML? */
    428         if (data_end == NULL) {
    429             ret = -EINVAL;
    430             goto fail;
    431         }
    432         *data_end++ = '\0';
    433         mish = g_base64_decode(data_begin, &out_len);
    434         ret = dmg_read_mish_block(s, ds, mish, (uint32_t)out_len);
    435         g_free(mish);
    436         if (ret < 0) {
    437             goto fail;
    438         }
    439     }
    440     ret = 0;
    441 
    442 fail:
    443     g_free(buffer);
    444     return ret;
    445 }
    446 
    447 static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
    448                     Error **errp)
    449 {
    450     BDRVDMGState *s = bs->opaque;
    451     DmgHeaderState ds;
    452     uint64_t rsrc_fork_offset, rsrc_fork_length;
    453     uint64_t plist_xml_offset, plist_xml_length;
    454     int64_t offset;
    455     int ret;
    456 
    457     ret = bdrv_apply_auto_read_only(bs, NULL, errp);
    458     if (ret < 0) {
    459         return ret;
    460     }
    461 
    462     ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
    463     if (ret < 0) {
    464         return ret;
    465     }
    466     /*
    467      * NB: if uncompress submodules are absent,
    468      * ie block_module_load return value == 0, the function pointers
    469      * dmg_uncompress_bz2 and dmg_uncompress_lzfse will be NULL.
    470      */
    471     if (block_module_load("dmg-bz2", errp) < 0) {
    472         return -EINVAL;
    473     }
    474     if (block_module_load("dmg-lzfse", errp) < 0) {
    475         return -EINVAL;
    476     }
    477 
    478     s->n_chunks = 0;
    479     s->offsets = s->lengths = s->sectors = s->sectorcounts = NULL;
    480     /* used by dmg_read_mish_block to keep track of the current I/O position */
    481     ds.data_fork_offset = 0;
    482     ds.max_compressed_size = 1;
    483     ds.max_sectors_per_chunk = 1;
    484 
    485     /* locate the UDIF trailer */
    486     offset = dmg_find_koly_offset(bs->file, errp);
    487     if (offset < 0) {
    488         ret = offset;
    489         goto fail;
    490     }
    491 
    492     /* offset of data fork (DataForkOffset) */
    493     ret = read_uint64(bs, offset + 0x18, &ds.data_fork_offset);
    494     if (ret < 0) {
    495         goto fail;
    496     } else if (ds.data_fork_offset > offset) {
    497         ret = -EINVAL;
    498         goto fail;
    499     }
    500 
    501     /* offset of resource fork (RsrcForkOffset) */
    502     ret = read_uint64(bs, offset + 0x28, &rsrc_fork_offset);
    503     if (ret < 0) {
    504         goto fail;
    505     }
    506     ret = read_uint64(bs, offset + 0x30, &rsrc_fork_length);
    507     if (ret < 0) {
    508         goto fail;
    509     }
    510     if (rsrc_fork_offset >= offset ||
    511         rsrc_fork_length > offset - rsrc_fork_offset) {
    512         ret = -EINVAL;
    513         goto fail;
    514     }
    515     /* offset of property list (XMLOffset) */
    516     ret = read_uint64(bs, offset + 0xd8, &plist_xml_offset);
    517     if (ret < 0) {
    518         goto fail;
    519     }
    520     ret = read_uint64(bs, offset + 0xe0, &plist_xml_length);
    521     if (ret < 0) {
    522         goto fail;
    523     }
    524     if (plist_xml_offset >= offset ||
    525         plist_xml_length > offset - plist_xml_offset) {
    526         ret = -EINVAL;
    527         goto fail;
    528     }
    529     ret = read_uint64(bs, offset + 0x1ec, (uint64_t *)&bs->total_sectors);
    530     if (ret < 0) {
    531         goto fail;
    532     }
    533     if (bs->total_sectors < 0) {
    534         ret = -EINVAL;
    535         goto fail;
    536     }
    537     if (rsrc_fork_length != 0) {
    538         ret = dmg_read_resource_fork(bs, &ds,
    539                                      rsrc_fork_offset, rsrc_fork_length);
    540         if (ret < 0) {
    541             goto fail;
    542         }
    543     } else if (plist_xml_length != 0) {
    544         ret = dmg_read_plist_xml(bs, &ds, plist_xml_offset, plist_xml_length);
    545         if (ret < 0) {
    546             goto fail;
    547         }
    548     } else {
    549         ret = -EINVAL;
    550         goto fail;
    551     }
    552 
    553     /* initialize zlib engine */
    554     s->compressed_chunk = qemu_try_blockalign(bs->file->bs,
    555                                               ds.max_compressed_size + 1);
    556     s->uncompressed_chunk = qemu_try_blockalign(bs->file->bs,
    557                                                 512 * ds.max_sectors_per_chunk);
    558     if (s->compressed_chunk == NULL || s->uncompressed_chunk == NULL) {
    559         ret = -ENOMEM;
    560         goto fail;
    561     }
    562 
    563     if (inflateInit(&s->zstream) != Z_OK) {
    564         ret = -EINVAL;
    565         goto fail;
    566     }
    567 
    568     s->current_chunk = s->n_chunks;
    569 
    570     qemu_co_mutex_init(&s->lock);
    571     return 0;
    572 
    573 fail:
    574     g_free(s->types);
    575     g_free(s->offsets);
    576     g_free(s->lengths);
    577     g_free(s->sectors);
    578     g_free(s->sectorcounts);
    579     qemu_vfree(s->compressed_chunk);
    580     qemu_vfree(s->uncompressed_chunk);
    581     return ret;
    582 }
    583 
    584 static void dmg_refresh_limits(BlockDriverState *bs, Error **errp)
    585 {
    586     bs->bl.request_alignment = BDRV_SECTOR_SIZE; /* No sub-sector I/O */
    587 }
    588 
    589 static inline int is_sector_in_chunk(BDRVDMGState *s,
    590                 uint32_t chunk_num, uint64_t sector_num)
    591 {
    592     if (chunk_num >= s->n_chunks || s->sectors[chunk_num] > sector_num ||
    593             s->sectors[chunk_num] + s->sectorcounts[chunk_num] <= sector_num) {
    594         return 0;
    595     } else {
    596         return -1;
    597     }
    598 }
    599 
    600 static inline uint32_t search_chunk(BDRVDMGState *s, uint64_t sector_num)
    601 {
    602     /* binary search */
    603     uint32_t chunk1 = 0, chunk2 = s->n_chunks, chunk3;
    604     while (chunk1 <= chunk2) {
    605         chunk3 = (chunk1 + chunk2) / 2;
    606         if (s->sectors[chunk3] > sector_num) {
    607             if (chunk3 == 0) {
    608                 goto err;
    609             }
    610             chunk2 = chunk3 - 1;
    611         } else if (s->sectors[chunk3] + s->sectorcounts[chunk3] > sector_num) {
    612             return chunk3;
    613         } else {
    614             chunk1 = chunk3 + 1;
    615         }
    616     }
    617 err:
    618     return s->n_chunks; /* error */
    619 }
    620 
    621 static inline int dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num)
    622 {
    623     BDRVDMGState *s = bs->opaque;
    624 
    625     if (!is_sector_in_chunk(s, s->current_chunk, sector_num)) {
    626         int ret;
    627         uint32_t chunk = search_chunk(s, sector_num);
    628 
    629         if (chunk >= s->n_chunks) {
    630             return -1;
    631         }
    632 
    633         s->current_chunk = s->n_chunks;
    634         switch (s->types[chunk]) { /* block entry type */
    635         case UDZO: { /* zlib compressed */
    636             /* we need to buffer, because only the chunk as whole can be
    637              * inflated. */
    638             ret = bdrv_pread(bs->file, s->offsets[chunk], s->lengths[chunk],
    639                              s->compressed_chunk, 0);
    640             if (ret < 0) {
    641                 return -1;
    642             }
    643 
    644             s->zstream.next_in = s->compressed_chunk;
    645             s->zstream.avail_in = s->lengths[chunk];
    646             s->zstream.next_out = s->uncompressed_chunk;
    647             s->zstream.avail_out = 512 * s->sectorcounts[chunk];
    648             ret = inflateReset(&s->zstream);
    649             if (ret != Z_OK) {
    650                 return -1;
    651             }
    652             ret = inflate(&s->zstream, Z_FINISH);
    653             if (ret != Z_STREAM_END ||
    654                 s->zstream.total_out != 512 * s->sectorcounts[chunk]) {
    655                 return -1;
    656             }
    657             break; }
    658         case UDBZ: /* bzip2 compressed */
    659             if (!dmg_uncompress_bz2) {
    660                 break;
    661             }
    662             /* we need to buffer, because only the chunk as whole can be
    663              * inflated. */
    664             ret = bdrv_pread(bs->file, s->offsets[chunk], s->lengths[chunk],
    665                              s->compressed_chunk, 0);
    666             if (ret < 0) {
    667                 return -1;
    668             }
    669 
    670             ret = dmg_uncompress_bz2((char *)s->compressed_chunk,
    671                                      (unsigned int) s->lengths[chunk],
    672                                      (char *)s->uncompressed_chunk,
    673                                      (unsigned int)
    674                                          (512 * s->sectorcounts[chunk]));
    675             if (ret < 0) {
    676                 return ret;
    677             }
    678             break;
    679         case ULFO:
    680             if (!dmg_uncompress_lzfse) {
    681                 break;
    682             }
    683             /* we need to buffer, because only the chunk as whole can be
    684              * inflated. */
    685             ret = bdrv_pread(bs->file, s->offsets[chunk], s->lengths[chunk],
    686                              s->compressed_chunk, 0);
    687             if (ret < 0) {
    688                 return -1;
    689             }
    690 
    691             ret = dmg_uncompress_lzfse((char *)s->compressed_chunk,
    692                                        (unsigned int) s->lengths[chunk],
    693                                        (char *)s->uncompressed_chunk,
    694                                        (unsigned int)
    695                                            (512 * s->sectorcounts[chunk]));
    696             if (ret < 0) {
    697                 return ret;
    698             }
    699             break;
    700         case UDRW: /* copy */
    701             ret = bdrv_pread(bs->file, s->offsets[chunk], s->lengths[chunk],
    702                              s->uncompressed_chunk, 0);
    703             if (ret < 0) {
    704                 return -1;
    705             }
    706             break;
    707         case UDZE: /* zeros */
    708         case UDIG: /* ignore */
    709             /* see dmg_read, it is treated specially. No buffer needs to be
    710              * pre-filled, the zeroes can be set directly. */
    711             break;
    712         }
    713         s->current_chunk = chunk;
    714     }
    715     return 0;
    716 }
    717 
    718 static int coroutine_fn
    719 dmg_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
    720               QEMUIOVector *qiov, BdrvRequestFlags flags)
    721 {
    722     BDRVDMGState *s = bs->opaque;
    723     uint64_t sector_num = offset >> BDRV_SECTOR_BITS;
    724     int nb_sectors = bytes >> BDRV_SECTOR_BITS;
    725     int ret, i;
    726 
    727     assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE));
    728     assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE));
    729 
    730     qemu_co_mutex_lock(&s->lock);
    731 
    732     for (i = 0; i < nb_sectors; i++) {
    733         uint32_t sector_offset_in_chunk;
    734         void *data;
    735 
    736         if (dmg_read_chunk(bs, sector_num + i) != 0) {
    737             ret = -EIO;
    738             goto fail;
    739         }
    740         /* Special case: current chunk is all zeroes. Do not perform a memcpy as
    741          * s->uncompressed_chunk may be too small to cover the large all-zeroes
    742          * section. dmg_read_chunk is called to find s->current_chunk */
    743         if (s->types[s->current_chunk] == UDZE
    744             || s->types[s->current_chunk] == UDIG) { /* all zeroes block entry */
    745             qemu_iovec_memset(qiov, i * 512, 0, 512);
    746             continue;
    747         }
    748         sector_offset_in_chunk = sector_num + i - s->sectors[s->current_chunk];
    749         data = s->uncompressed_chunk + sector_offset_in_chunk * 512;
    750         qemu_iovec_from_buf(qiov, i * 512, data, 512);
    751     }
    752 
    753     ret = 0;
    754 fail:
    755     qemu_co_mutex_unlock(&s->lock);
    756     return ret;
    757 }
    758 
    759 static void dmg_close(BlockDriverState *bs)
    760 {
    761     BDRVDMGState *s = bs->opaque;
    762 
    763     g_free(s->types);
    764     g_free(s->offsets);
    765     g_free(s->lengths);
    766     g_free(s->sectors);
    767     g_free(s->sectorcounts);
    768     qemu_vfree(s->compressed_chunk);
    769     qemu_vfree(s->uncompressed_chunk);
    770 
    771     inflateEnd(&s->zstream);
    772 }
    773 
    774 static BlockDriver bdrv_dmg = {
    775     .format_name    = "dmg",
    776     .instance_size  = sizeof(BDRVDMGState),
    777     .bdrv_probe     = dmg_probe,
    778     .bdrv_open      = dmg_open,
    779     .bdrv_refresh_limits = dmg_refresh_limits,
    780     .bdrv_child_perm     = bdrv_default_perms,
    781     .bdrv_co_preadv = dmg_co_preadv,
    782     .bdrv_close     = dmg_close,
    783     .is_format      = true,
    784 };
    785 
    786 static void bdrv_dmg_init(void)
    787 {
    788     bdrv_register(&bdrv_dmg);
    789 }
    790 
    791 block_init(bdrv_dmg_init);