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

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