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

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:     int fd;
                     31:     uint32_t block_size;
                     32:     uint32_t n_blocks;
                     33:     uint64_t* offsets;
                     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: {
                     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:     if(!memcmp(magic_version_2_0,buf,length))
                     50:        return 2;
                     51:     return 0;
                     52: }
                     53: 
                     54: static int cloop_open(BlockDriverState *bs, const char *filename, int flags)
                     55: {
                     56:     BDRVCloopState *s = bs->opaque;
                     57:     uint32_t offsets_size,max_compressed_block_size=1,i;
                     58: 
                     59:     s->fd = open(filename, O_RDONLY | O_BINARY);
                     60:     if (s->fd < 0)
                     61:         return -errno;
                     62:     bs->read_only = 1;
                     63: 
                     64:     /* read header */
                     65:     if(lseek(s->fd,128,SEEK_SET)<0) {
                     66: cloop_close:
                     67:        close(s->fd);
                     68:        return -1;
                     69:     }
                     70:     if(read(s->fd,&s->block_size,4)<4)
                     71:        goto cloop_close;
                     72:     s->block_size=be32_to_cpu(s->block_size);
                     73:     if(read(s->fd,&s->n_blocks,4)<4)
                     74:        goto cloop_close;
                     75:     s->n_blocks=be32_to_cpu(s->n_blocks);
                     76: 
                     77:     /* read offsets */
                     78:     offsets_size=s->n_blocks*sizeof(uint64_t);
                     79:     s->offsets=(uint64_t*)qemu_malloc(offsets_size);
                     80:     if(read(s->fd,s->offsets,offsets_size)<offsets_size)
                     81:        goto cloop_close;
                     82:     for(i=0;i<s->n_blocks;i++) {
                     83:        s->offsets[i]=be64_to_cpu(s->offsets[i]);
                     84:        if(i>0) {
                     85:            uint32_t size=s->offsets[i]-s->offsets[i-1];
                     86:            if(size>max_compressed_block_size)
                     87:                max_compressed_block_size=size;
                     88:        }
                     89:     }
                     90: 
                     91:     /* initialize zlib engine */
                     92:     s->compressed_block = qemu_malloc(max_compressed_block_size+1);
                     93:     s->uncompressed_block = qemu_malloc(s->block_size);
                     94:     if(inflateInit(&s->zstream) != Z_OK)
                     95:        goto cloop_close;
                     96:     s->current_block=s->n_blocks;
                     97: 
                     98:     s->sectors_per_block = s->block_size/512;
                     99:     bs->total_sectors = s->n_blocks*s->sectors_per_block;
                    100:     return 0;
                    101: }
                    102: 
                    103: static inline int cloop_read_block(BDRVCloopState *s,int block_num)
                    104: {
                    105:     if(s->current_block != block_num) {
                    106:        int ret;
                    107:         uint32_t bytes = s->offsets[block_num+1]-s->offsets[block_num];
                    108: 
                    109:        lseek(s->fd, s->offsets[block_num], SEEK_SET);
                    110:         ret = read(s->fd, s->compressed_block, bytes);
                    111:         if (ret != bytes)
                    112:             return -1;
                    113: 
                    114:        s->zstream.next_in = s->compressed_block;
                    115:        s->zstream.avail_in = bytes;
                    116:        s->zstream.next_out = s->uncompressed_block;
                    117:        s->zstream.avail_out = s->block_size;
                    118:        ret = inflateReset(&s->zstream);
                    119:        if(ret != Z_OK)
                    120:            return -1;
                    121:        ret = inflate(&s->zstream, Z_FINISH);
                    122:        if(ret != Z_STREAM_END || s->zstream.total_out != s->block_size)
                    123:            return -1;
                    124: 
                    125:        s->current_block = block_num;
                    126:     }
                    127:     return 0;
                    128: }
                    129: 
                    130: static int cloop_read(BlockDriverState *bs, int64_t sector_num,
                    131:                     uint8_t *buf, int nb_sectors)
                    132: {
                    133:     BDRVCloopState *s = bs->opaque;
                    134:     int i;
                    135: 
                    136:     for(i=0;i<nb_sectors;i++) {
                    137:        uint32_t sector_offset_in_block=((sector_num+i)%s->sectors_per_block),
                    138:            block_num=(sector_num+i)/s->sectors_per_block;
                    139:        if(cloop_read_block(s, block_num) != 0)
                    140:            return -1;
                    141:        memcpy(buf+i*512,s->uncompressed_block+sector_offset_in_block*512,512);
                    142:     }
                    143:     return 0;
                    144: }
                    145: 
                    146: static void cloop_close(BlockDriverState *bs)
                    147: {
                    148:     BDRVCloopState *s = bs->opaque;
                    149:     close(s->fd);
                    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.