wok rev 17990

qemu: apply cloop.u (again)
author Pascal Bellard <pascal.bellard@slitaz.org>
date Thu Apr 23 15:15:23 2015 +0200 (2015-04-23)
parents 9c8ef3fd3dcf
children 70c7a787c969
files qemu/stuff/cloop.u
line diff
     1.1 --- a/qemu/stuff/cloop.u	Thu Apr 23 13:30:18 2015 +0200
     1.2 +++ b/qemu/stuff/cloop.u	Thu Apr 23 15:15:23 2015 +0200
     1.3 @@ -117,7 +117,7 @@
     1.4   }
     1.5   
     1.6   static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
     1.7 -@@ -91,79 +169,104 @@
     1.8 +@@ -91,79 +169,97 @@
     1.9                      MAX_BLOCK_SIZE / (1024 * 1024));
    1.10           return -EINVAL;
    1.11       }
    1.12 @@ -128,26 +128,14 @@
    1.13       }
    1.14       s->n_blocks = be32_to_cpu(s->n_blocks);
    1.15   
    1.16 -+    /* initialize zlib engine */
    1.17 -+    max_compressed_block_size =  s->block_size + s->block_size/1000 + 12 + 4;
    1.18 -+    s->compressed_block = g_malloc(max_compressed_block_size + 1);
    1.19 -+    s->uncompressed_block = g_malloc(s->block_size);
    1.20 -+
    1.21 -+    if (inflateInit(&s->zstream) != Z_OK) {
    1.22 -+        ret = -EINVAL;
    1.23 -+        goto fail;
    1.24 -+    }
    1.25 -+
    1.26 -     /* read offsets */
    1.27 +-    /* read offsets */
    1.28  -    if (s->n_blocks > (UINT32_MAX - 1) / sizeof(uint64_t)) {
    1.29 -+    if (s->n_blocks > (UINT32_MAX - 1) / sizeof(block_info)) {
    1.30 -         /* Prevent integer overflow */
    1.31 -         error_setg(errp, "n_blocks %u must be %zu or less",
    1.32 -                    s->n_blocks,
    1.33 +-        /* Prevent integer overflow */
    1.34 +-        error_setg(errp, "n_blocks %u must be %zu or less",
    1.35 +-                   s->n_blocks,
    1.36  -                   (UINT32_MAX - 1) / sizeof(uint64_t));
    1.37 -+                   (UINT32_MAX - 1) / sizeof(block_info));
    1.38 -         return -EINVAL;
    1.39 -     }
    1.40 +-        return -EINVAL;
    1.41 +-    }
    1.42  -    offsets_size = (s->n_blocks + 1) * sizeof(uint64_t);
    1.43  -    if (offsets_size > 512 * 1024 * 1024) {
    1.44  -        /* Prevent ridiculous offsets_size which causes memory allocation to
    1.45 @@ -159,27 +147,40 @@
    1.46  -        return -EINVAL;
    1.47  -    }
    1.48  -    s->offsets = g_malloc(offsets_size);
    1.49 ++    /* initialize zlib engine */
    1.50 ++    max_compressed_block_size =  s->block_size + s->block_size/1000 + 12 + 4;
    1.51 ++    s->compressed_block = g_malloc(max_compressed_block_size + 1);
    1.52 ++    s->uncompressed_block = g_malloc(s->block_size);
    1.53 + 
    1.54 +-    ret = bdrv_pread(bs->file, 128 + 4 + 4, s->offsets, offsets_size);
    1.55 +-    if (ret < 0) {
    1.56 ++    if (inflateInit(&s->zstream) != Z_OK) {
    1.57 ++        ret = -EINVAL;
    1.58 +         goto fail;
    1.59 +     }
    1.60 + 
    1.61 +-    for (i = 0; i < s->n_blocks + 1; i++) {
    1.62 +-        uint64_t size;
    1.63 ++    /* read offsets */
    1.64  +    if (s->n_blocks + 1 == 0) {
    1.65  +        cloop_tail tail;
    1.66  +        int64_t end = bdrv_getlength(bs->file);
    1.67  +	void *p;
    1.68  +	uint32_t toclen, len; 
    1.69   
    1.70 --    ret = bdrv_pread(bs->file, 128 + 4 + 4, s->offsets, offsets_size);
    1.71 --    if (ret < 0) {
    1.72 --        goto fail;
    1.73 --    }
    1.74 --
    1.75 --    for (i = 0; i < s->n_blocks + 1; i++) {
    1.76 --        uint64_t size;
    1.77 +-        s->offsets[i] = be64_to_cpu(s->offsets[i]);
    1.78 +-        if (i == 0) {
    1.79 +-            continue;
    1.80  +        ret = bdrv_pread(bs->file, end - sizeof(tail), &tail, sizeof(tail));
    1.81  +        if (ret < 0) {
    1.82  +            goto fail;
    1.83 -+        }
    1.84 +         }
    1.85   
    1.86 --        s->offsets[i] = be64_to_cpu(s->offsets[i]);
    1.87 --        if (i == 0) {
    1.88 --            continue;
    1.89 +-        if (s->offsets[i] < s->offsets[i - 1]) {
    1.90 +-            error_setg(errp, "offsets not monotonically increasing at "
    1.91 +-                       "index %u, image file is corrupt", i);
    1.92 +-            ret = -EINVAL;
    1.93 +-            goto fail;
    1.94  +        s->n_blocks = be32_to_cpu(tail.num_blocks);
    1.95  +        offsets_size = s->n_blocks * sizeof(block_info);
    1.96  +        if (offsets_size > 512 * 1024 * 1024) {
    1.97 @@ -194,12 +195,18 @@
    1.98  +	len = be32_to_cpu(tail.table_size);
    1.99  +	toclen = (be32_to_cpu(tail.index_size) & 255) * s->n_blocks;
   1.100   
   1.101 --        if (s->offsets[i] < s->offsets[i - 1]) {
   1.102 --            error_setg(errp, "offsets not monotonically increasing at "
   1.103 --                       "index %u, image file is corrupt", i);
   1.104 +-        size = s->offsets[i] - s->offsets[i - 1];
   1.105  +        s->offsets = g_malloc(offsets_size);
   1.106  +	p = g_malloc(len);
   1.107 -+
   1.108 + 
   1.109 +-        /* Compressed blocks should be smaller than the uncompressed block size
   1.110 +-         * but maybe compression performed poorly so the compressed block is
   1.111 +-         * actually bigger.  Clamp down on unrealistic values to prevent
   1.112 +-         * ridiculous s->compressed_block allocation.
   1.113 +-         */
   1.114 +-        if (size > 2 * MAX_BLOCK_SIZE) {
   1.115 +-            error_setg(errp, "invalid compressed block size at index %u, "
   1.116 +-                       "image file is corrupt", i);
   1.117  +        ret = bdrv_pread(bs->file, end - sizeof(tail) - len, p, len);
   1.118  +        if (ret < 0) {
   1.119  +            goto fail;
   1.120 @@ -214,23 +221,15 @@
   1.121               goto fail;
   1.122           }
   1.123  -
   1.124 --        size = s->offsets[i] - s->offsets[i - 1];
   1.125 --
   1.126 --        /* Compressed blocks should be smaller than the uncompressed block size
   1.127 --         * but maybe compression performed poorly so the compressed block is
   1.128 --         * actually bigger.  Clamp down on unrealistic values to prevent
   1.129 --         * ridiculous s->compressed_block allocation.
   1.130 --         */
   1.131 --        if (size > 2 * MAX_BLOCK_SIZE) {
   1.132 --            error_setg(errp, "invalid compressed block size at index %u, "
   1.133 --                       "image file is corrupt", i);
   1.134 +-        if (size > max_compressed_block_size) {
   1.135 +-            max_compressed_block_size = size;
   1.136  +        ret = inflate(&s->zstream, Z_FINISH);
   1.137  +        if (ret != Z_STREAM_END || s->zstream.total_out != toclen) {
   1.138 -             ret = -EINVAL;
   1.139 -             goto fail;
   1.140 ++            ret = -EINVAL;
   1.141 ++            goto fail;
   1.142           }
   1.143  +	g_free(p);
   1.144 -+    }
   1.145 +     }
   1.146  +    else {
   1.147  +        offsets_size = s->n_blocks * sizeof(block_info);
   1.148  +        if (offsets_size > 512 * 1024 * 1024) {
   1.149 @@ -244,18 +243,15 @@
   1.150  +        }
   1.151  +        s->offsets = g_malloc(offsets_size);
   1.152   
   1.153 --        if (size > max_compressed_block_size) {
   1.154 --            max_compressed_block_size = size;
   1.155 -+        ret = bdrv_pread(bs->file, 128 + 4 + 4, s->offsets, offsets_size);
   1.156 -+        if (ret < 0) {
   1.157 -+            goto fail;
   1.158 -         }
   1.159 -     }
   1.160 --
   1.161  -    /* initialize zlib engine */
   1.162  -    s->compressed_block = g_malloc(max_compressed_block_size + 1);
   1.163  -    s->uncompressed_block = g_malloc(s->block_size);
   1.164  -    if (inflateInit(&s->zstream) != Z_OK) {
   1.165 ++        ret = bdrv_pread(bs->file, 128 + 4 + 4, s->offsets, offsets_size);
   1.166 ++        if (ret < 0) {
   1.167 ++            goto fail;
   1.168 ++        }
   1.169 ++    }
   1.170  +    ret = build_index(s->offsets, s->n_blocks);
   1.171  +    if (ret) {
   1.172  +        error_setg(errp, "invalid compressed block size at index %u, "
   1.173 @@ -267,7 +263,7 @@
   1.174       s->current_block = s->n_blocks;
   1.175   
   1.176       s->sectors_per_block = s->block_size/512;
   1.177 -@@ -184,10 +287,10 @@
   1.178 +@@ -184,10 +280,10 @@
   1.179   
   1.180       if (s->current_block != block_num) {
   1.181           int ret;