wok-next annotate qemu/stuff/cloop.u @ rev 17442

qemu/cloop: fix V0-V2
author Pascal Bellard <pascal.bellard@slitaz.org>
date Wed Dec 10 21:59:12 2014 +0100 (2014-12-10)
parents 1f00b27b3afb
children 9c8ef3fd3dcf
rev   line source
pascal@17266 1 --- block/cloop.c
pascal@17266 2 +++ block/cloop.c
pascal@17266 3 @@ -26,11 +26,78 @@
pascal@17266 4 #include "qemu/module.h"
pascal@17266 5 #include <zlib.h>
pascal@17266 6
pascal@17266 7 +typedef struct cloop_tail {
pascal@17266 8 + uint32_t table_size;
pascal@17266 9 + uint32_t index_size;
pascal@17266 10 + uint32_t num_blocks;
pascal@17266 11 +} cloop_tail;
pascal@17266 12 +
pascal@17266 13 +typedef struct block_info {
pascal@17266 14 + uint64_t offset; /* 64-bit offsets of compressed block */
pascal@17266 15 + uint32_t size; /* 32-bit compressed block size */
pascal@17266 16 + uint32_t optidx; /* 32-bit index number */
pascal@17266 17 +} block_info;
pascal@17266 18 +
pascal@17266 19 +static inline void build_index(block_info *offsets, unsigned long n)
pascal@17266 20 +{
pascal@17266 21 + uint32_t *ofs32 = (uint32_t *) offsets;
pascal@17266 22 + uint64_t *ofs64 = (uint64_t *) offsets;
pascal@17266 23 +
pascal@17266 24 + if (ofs32[0] == 0) {
pascal@17266 25 + if (ofs32[2]) { /* ACCELERATED KNOPPIX V1.0 */
pascal@17266 26 + while (n--) {
pascal@17266 27 + offsets[n].offset = be64_to_cpu(offsets[n].offset);
pascal@17266 28 + offsets[n].size = ntohl(offsets[n].size);
pascal@17266 29 + }
pascal@17266 30 + // return (char *) "128BE accelerated knoppix 1.0";
pascal@17266 31 + }
pascal@17266 32 + else { /* V2.0 */
pascal@17442 33 + uint64_t last = be64_to_cpu(ofs64[n - 1]);
pascal@17266 34 + while (n--) {
pascal@17266 35 + offsets[n].size = last -
pascal@17266 36 + (offsets[n].offset = be64_to_cpu(ofs64[n]));
pascal@17266 37 + last = offsets[n].offset;
pascal@17266 38 + }
pascal@17266 39 + // return (char *) "64BE v2.0";
pascal@17266 40 + }
pascal@17266 41 + }
pascal@17266 42 + else if (ofs32[1] == 0) { /* V1.0 */
pascal@17442 43 + uint64_t last = le64_to_cpu(ofs64[n - 1]);
pascal@17266 44 + while (n--) {
pascal@17266 45 + offsets[n].size = last -
pascal@17266 46 + (offsets[n].offset = le64_to_cpu(ofs64[n]));
pascal@17266 47 + last = offsets[n].offset;
pascal@17266 48 + }
pascal@17266 49 + // return (char *) "64LE v1.0";
pascal@17266 50 + }
pascal@17266 51 + else if (ntohl(ofs32[0]) == (4*n) + 0x8C) { /* V0.68 */
pascal@17442 52 + uint64_t last = ntohl(ofs32[n - 1]);
pascal@17266 53 + while (n--) {
pascal@17266 54 + offsets[n].size = last -
pascal@17266 55 + (offsets[n].offset = ntohl(ofs32[n]));
pascal@17266 56 + last = offsets[n].offset;
pascal@17266 57 + }
pascal@17266 58 + // return (char *) "32BE v0.68";
pascal@17266 59 + }
pascal@17266 60 + else { /* V3.0 */
pascal@17266 61 + unsigned long i;
pascal@17266 62 + uint64_t j;
pascal@17266 63 +
pascal@17266 64 + for (i = n; i-- > 0; )
pascal@17266 65 + offsets[i].size = ntohl(ofs32[i]);
pascal@17266 66 + for (i = 0, j = 128 + 4 + 4; i < n; i++) {
pascal@17266 67 + offsets[i].offset = j;
pascal@17266 68 + j += offsets[i].size;
pascal@17266 69 + }
pascal@17266 70 + // return (char *) "32BE v3.0";
pascal@17266 71 + }
pascal@17266 72 +}
pascal@17266 73 +
pascal@17266 74 typedef struct BDRVCloopState {
pascal@17266 75 CoMutex lock;
pascal@17266 76 uint32_t block_size;
pascal@17266 77 uint32_t n_blocks;
pascal@17266 78 - uint64_t *offsets;
pascal@17266 79 + block_info *offsets;
pascal@17266 80 uint32_t sectors_per_block;
pascal@17266 81 uint32_t current_block;
pascal@17266 82 uint8_t *compressed_block;
pascal@17266 83 @@ -40,17 +107,21 @@
pascal@17266 84
pascal@17266 85 static int cloop_probe(const uint8_t *buf, int buf_size, const char *filename)
pascal@17266 86 {
pascal@17266 87 - const char *magic_version_2_0 = "#!/bin/sh\n"
pascal@17266 88 - "#V2.0 Format\n"
pascal@17266 89 + static const uint8_t magic[] =
pascal@17266 90 "modprobe cloop file=$0 && mount -r -t iso9660 /dev/cloop $1\n";
pascal@17266 91 - int length = strlen(magic_version_2_0);
pascal@17266 92 - if (length > buf_size) {
pascal@17266 93 - length = buf_size;
pascal@17266 94 + int i, ret = 0, length = buf_size;
pascal@17266 95 + uint8_t c;
pascal@17266 96 +
pascal@17266 97 + if (length > 127) {
pascal@17266 98 + length = 127;
pascal@17266 99 }
pascal@17266 100 - if (!memcmp(magic_version_2_0, buf, length)) {
pascal@17266 101 - return 2;
pascal@17266 102 + for (i = 0; i < length - sizeof(magic) + 1; i++) {
pascal@17266 103 + if (buf[i] != magic[0]) continue;
pascal@17266 104 + if (strncmp(buf + i, magic, sizeof(magic) - 1)) continue;
pascal@17266 105 + ret = 2;
pascal@17266 106 + break;
pascal@17266 107 }
pascal@17266 108 - return 0;
pascal@17266 109 + return ret;
pascal@17266 110 }
pascal@17266 111
pascal@17266 112 static int cloop_open(BlockDriverState *bs, QDict *options, int flags)
pascal@17266 113 @@ -74,32 +145,67 @@
pascal@17266 114 }
pascal@17266 115 s->n_blocks = be32_to_cpu(s->n_blocks);
pascal@17266 116
pascal@17266 117 - /* read offsets */
pascal@17266 118 - offsets_size = s->n_blocks * sizeof(uint64_t);
pascal@17266 119 - s->offsets = g_malloc(offsets_size);
pascal@17266 120 + /* initialize zlib engine */
pascal@17266 121 + max_compressed_block_size = s->block_size + s->block_size/1000 + 12 + 4;
pascal@17266 122 + s->compressed_block = g_malloc(max_compressed_block_size + 1);
pascal@17266 123 + s->uncompressed_block = g_malloc(s->block_size);
pascal@17266 124
pascal@17266 125 - ret = bdrv_pread(bs->file, 128 + 4 + 4, s->offsets, offsets_size);
pascal@17266 126 - if (ret < 0) {
pascal@17266 127 + if (inflateInit(&s->zstream) != Z_OK) {
pascal@17266 128 + ret = -EINVAL;
pascal@17266 129 goto fail;
pascal@17266 130 }
pascal@17266 131
pascal@17266 132 - for(i=0;i<s->n_blocks;i++) {
pascal@17266 133 - s->offsets[i] = be64_to_cpu(s->offsets[i]);
pascal@17266 134 - if (i > 0) {
pascal@17266 135 - uint32_t size = s->offsets[i] - s->offsets[i - 1];
pascal@17266 136 - if (size > max_compressed_block_size) {
pascal@17266 137 - max_compressed_block_size = size;
pascal@17266 138 - }
pascal@17266 139 + /* read offsets */
pascal@17266 140 + if (s->n_blocks + 1 == 0) {
pascal@17266 141 + cloop_tail tail;
pascal@17266 142 + int64_t end = bdrv_getlength(bs->file);
pascal@17266 143 + void *p;
pascal@17266 144 + uint32_t toclen, len;
pascal@17266 145 +
pascal@17266 146 + ret = bdrv_pread(bs->file, end - sizeof(tail), &tail, sizeof(tail));
pascal@17266 147 + if (ret < 0) {
pascal@17266 148 + goto fail;
pascal@17266 149 }
pascal@17266 150 +
pascal@17266 151 + s->n_blocks = be32_to_cpu(tail.num_blocks);
pascal@17266 152 + offsets_size = s->n_blocks * sizeof(block_info);
pascal@17266 153 + len = be32_to_cpu(tail.table_size);
pascal@17266 154 + toclen = (be32_to_cpu(tail.index_size) & 255) * s->n_blocks;
pascal@17266 155 +
pascal@17266 156 + s->offsets = g_malloc(offsets_size);
pascal@17266 157 + p = g_malloc(len);
pascal@17266 158 +
pascal@17266 159 + ret = bdrv_pread(bs->file, end - sizeof(tail) - len, p, len);
pascal@17266 160 + if (ret < 0) {
pascal@17266 161 + goto fail;
pascal@17266 162 + }
pascal@17266 163 + s->zstream.next_in = p;
pascal@17266 164 + s->zstream.avail_in = len;
pascal@17266 165 + s->zstream.next_out = s->offsets;
pascal@17266 166 + s->zstream.avail_out = toclen;
pascal@17266 167 + ret = inflateReset(&s->zstream);
pascal@17266 168 + if (ret != Z_OK) {
pascal@17266 169 + ret = -EINVAL;
pascal@17266 170 + goto fail;
pascal@17266 171 + }
pascal@17266 172 + ret = inflate(&s->zstream, Z_FINISH);
pascal@17266 173 + if (ret != Z_STREAM_END || s->zstream.total_out != toclen) {
pascal@17266 174 + ret = -EINVAL;
pascal@17266 175 + goto fail;
pascal@17266 176 + }
pascal@17266 177 + g_free(p);
pascal@17266 178 }
pascal@17266 179 + else {
pascal@17266 180 + offsets_size = s->n_blocks * sizeof(block_info);
pascal@17266 181 + s->offsets = g_malloc(offsets_size);
pascal@17266 182
pascal@17266 183 - /* initialize zlib engine */
pascal@17266 184 - s->compressed_block = g_malloc(max_compressed_block_size + 1);
pascal@17266 185 - s->uncompressed_block = g_malloc(s->block_size);
pascal@17266 186 - if (inflateInit(&s->zstream) != Z_OK) {
pascal@17266 187 - ret = -EINVAL;
pascal@17266 188 - goto fail;
pascal@17266 189 + ret = bdrv_pread(bs->file, 128 + 4 + 4, s->offsets, offsets_size);
pascal@17266 190 + if (ret < 0) {
pascal@17266 191 + goto fail;
pascal@17266 192 + }
pascal@17266 193 }
pascal@17266 194 + build_index(s->offsets, s->n_blocks);
pascal@17266 195 +
pascal@17266 196 s->current_block = s->n_blocks;
pascal@17266 197
pascal@17266 198 s->sectors_per_block = s->block_size/512;
pascal@17266 199 @@ -120,10 +226,10 @@
pascal@17266 200
pascal@17266 201 if (s->current_block != block_num) {
pascal@17266 202 int ret;
pascal@17266 203 - uint32_t bytes = s->offsets[block_num + 1] - s->offsets[block_num];
pascal@17266 204 + uint32_t bytes = s->offsets[block_num].size;
pascal@17266 205
pascal@17266 206 - ret = bdrv_pread(bs->file, s->offsets[block_num], s->compressed_block,
pascal@17266 207 - bytes);
pascal@17266 208 + ret = bdrv_pread(bs->file, s->offsets[block_num].offset,
pascal@17266 209 + s->compressed_block, bytes);
pascal@17266 210 if (ret != bytes) {
pascal@17266 211 return -1;
pascal@17266 212 }