Annotation of qemu/block/cloop.c, revision 1.1.1.3

1.1       root        1: /*
                      2:  * QEMU Block driver for CLOOP 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-common.h"
                     25: #include "block_int.h"
                     26: #include "module.h"
                     27: #include <zlib.h>
                     28: 
                     29: typedef struct BDRVCloopState {
1.1.1.3 ! root       30:     CoMutex lock;
1.1       root       31:     uint32_t block_size;
                     32:     uint32_t n_blocks;
1.1.1.3 ! root       33:     uint64_t *offsets;
1.1       root       34:     uint32_t sectors_per_block;
                     35:     uint32_t current_block;
                     36:     uint8_t *compressed_block;
                     37:     uint8_t *uncompressed_block;
                     38:     z_stream zstream;
                     39: } BDRVCloopState;
                     40: 
                     41: static int cloop_probe(const uint8_t *buf, int buf_size, const char *filename)
                     42: {
1.1.1.3 ! root       43:     const char *magic_version_2_0 = "#!/bin/sh\n"
        !            44:         "#V2.0 Format\n"
        !            45:         "modprobe cloop file=$0 && mount -r -t iso9660 /dev/cloop $1\n";
        !            46:     int length = strlen(magic_version_2_0);
        !            47:     if (length > buf_size) {
        !            48:         length = buf_size;
        !            49:     }
        !            50:     if (!memcmp(magic_version_2_0, buf, length)) {
        !            51:         return 2;
        !            52:     }
1.1       root       53:     return 0;
                     54: }
                     55: 
1.1.1.2   root       56: static int cloop_open(BlockDriverState *bs, int flags)
1.1       root       57: {
                     58:     BDRVCloopState *s = bs->opaque;
1.1.1.3 ! root       59:     uint32_t offsets_size, max_compressed_block_size = 1, i;
1.1       root       60: 
                     61:     bs->read_only = 1;
                     62: 
                     63:     /* read header */
1.1.1.2   root       64:     if (bdrv_pread(bs->file, 128, &s->block_size, 4) < 4) {
                     65:         goto cloop_close;
1.1       root       66:     }
1.1.1.2   root       67:     s->block_size = be32_to_cpu(s->block_size);
                     68: 
                     69:     if (bdrv_pread(bs->file, 128 + 4, &s->n_blocks, 4) < 4) {
                     70:         goto cloop_close;
                     71:     }
                     72:     s->n_blocks = be32_to_cpu(s->n_blocks);
1.1       root       73: 
                     74:     /* read offsets */
1.1.1.2   root       75:     offsets_size = s->n_blocks * sizeof(uint64_t);
1.1.1.3 ! root       76:     s->offsets = g_malloc(offsets_size);
1.1.1.2   root       77:     if (bdrv_pread(bs->file, 128 + 4 + 4, s->offsets, offsets_size) <
                     78:             offsets_size) {
1.1.1.3 ! root       79:         goto cloop_close;
1.1.1.2   root       80:     }
1.1       root       81:     for(i=0;i<s->n_blocks;i++) {
1.1.1.3 ! root       82:         s->offsets[i] = be64_to_cpu(s->offsets[i]);
        !            83:         if (i > 0) {
        !            84:             uint32_t size = s->offsets[i] - s->offsets[i - 1];
        !            85:             if (size > max_compressed_block_size) {
        !            86:                 max_compressed_block_size = size;
        !            87:             }
        !            88:         }
1.1       root       89:     }
                     90: 
                     91:     /* initialize zlib engine */
1.1.1.3 ! root       92:     s->compressed_block = g_malloc(max_compressed_block_size + 1);
        !            93:     s->uncompressed_block = g_malloc(s->block_size);
        !            94:     if (inflateInit(&s->zstream) != Z_OK) {
        !            95:         goto cloop_close;
        !            96:     }
        !            97:     s->current_block = s->n_blocks;
1.1       root       98: 
                     99:     s->sectors_per_block = s->block_size/512;
1.1.1.3 ! root      100:     bs->total_sectors = s->n_blocks * s->sectors_per_block;
        !           101:     qemu_co_mutex_init(&s->lock);
1.1       root      102:     return 0;
1.1.1.2   root      103: 
                    104: cloop_close:
                    105:     return -1;
1.1       root      106: }
                    107: 
1.1.1.2   root      108: static inline int cloop_read_block(BlockDriverState *bs, int block_num)
1.1       root      109: {
1.1.1.2   root      110:     BDRVCloopState *s = bs->opaque;
                    111: 
1.1.1.3 ! root      112:     if (s->current_block != block_num) {
        !           113:         int ret;
        !           114:         uint32_t bytes = s->offsets[block_num + 1] - s->offsets[block_num];
1.1       root      115: 
1.1.1.2   root      116:         ret = bdrv_pread(bs->file, s->offsets[block_num], s->compressed_block,
                    117:                          bytes);
1.1.1.3 ! root      118:         if (ret != bytes) {
1.1       root      119:             return -1;
1.1.1.3 ! root      120:         }
1.1       root      121: 
1.1.1.3 ! root      122:         s->zstream.next_in = s->compressed_block;
        !           123:         s->zstream.avail_in = bytes;
        !           124:         s->zstream.next_out = s->uncompressed_block;
        !           125:         s->zstream.avail_out = s->block_size;
        !           126:         ret = inflateReset(&s->zstream);
        !           127:         if (ret != Z_OK) {
        !           128:             return -1;
        !           129:         }
        !           130:         ret = inflate(&s->zstream, Z_FINISH);
        !           131:         if (ret != Z_STREAM_END || s->zstream.total_out != s->block_size) {
        !           132:             return -1;
        !           133:         }
1.1       root      134: 
1.1.1.3 ! root      135:         s->current_block = block_num;
1.1       root      136:     }
                    137:     return 0;
                    138: }
                    139: 
                    140: static int cloop_read(BlockDriverState *bs, int64_t sector_num,
                    141:                     uint8_t *buf, int nb_sectors)
                    142: {
                    143:     BDRVCloopState *s = bs->opaque;
                    144:     int i;
                    145: 
1.1.1.3 ! root      146:     for (i = 0; i < nb_sectors; i++) {
        !           147:         uint32_t sector_offset_in_block =
        !           148:             ((sector_num + i) % s->sectors_per_block),
        !           149:             block_num = (sector_num + i) / s->sectors_per_block;
        !           150:         if (cloop_read_block(bs, block_num) != 0) {
        !           151:             return -1;
        !           152:         }
        !           153:         memcpy(buf + i * 512,
        !           154:             s->uncompressed_block + sector_offset_in_block * 512, 512);
1.1       root      155:     }
                    156:     return 0;
                    157: }
                    158: 
1.1.1.3 ! root      159: static coroutine_fn int cloop_co_read(BlockDriverState *bs, int64_t sector_num,
        !           160:                                       uint8_t *buf, int nb_sectors)
        !           161: {
        !           162:     int ret;
        !           163:     BDRVCloopState *s = bs->opaque;
        !           164:     qemu_co_mutex_lock(&s->lock);
        !           165:     ret = cloop_read(bs, sector_num, buf, nb_sectors);
        !           166:     qemu_co_mutex_unlock(&s->lock);
        !           167:     return ret;
        !           168: }
        !           169: 
1.1       root      170: static void cloop_close(BlockDriverState *bs)
                    171: {
                    172:     BDRVCloopState *s = bs->opaque;
1.1.1.3 ! root      173:     if (s->n_blocks > 0) {
        !           174:         g_free(s->offsets);
        !           175:     }
        !           176:     g_free(s->compressed_block);
        !           177:     g_free(s->uncompressed_block);
1.1       root      178:     inflateEnd(&s->zstream);
                    179: }
                    180: 
                    181: static BlockDriver bdrv_cloop = {
1.1.1.3 ! root      182:     .format_name    = "cloop",
        !           183:     .instance_size  = sizeof(BDRVCloopState),
        !           184:     .bdrv_probe     = cloop_probe,
        !           185:     .bdrv_open      = cloop_open,
        !           186:     .bdrv_read      = cloop_co_read,
        !           187:     .bdrv_close     = cloop_close,
1.1       root      188: };
                    189: 
                    190: static void bdrv_cloop_init(void)
                    191: {
                    192:     bdrv_register(&bdrv_cloop);
                    193: }
                    194: 
                    195: block_init(bdrv_cloop_init);

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.