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 "vl.h"
                     25: #include "block_int.h"
                     26: #include <zlib.h>
                     27: 
                     28: typedef struct BDRVCloopState {
                     29:     int fd;
                     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;
1.1.1.2   root       35:     uint8_t *compressed_block;
                     36:     uint8_t *uncompressed_block;
1.1       root       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.3 ! root       53: static int cloop_open(BlockDriverState *bs, const char *filename, int flags)
1.1       root       54: {
                     55:     BDRVCloopState *s = bs->opaque;
                     56:     uint32_t offsets_size,max_compressed_block_size=1,i;
                     57: 
1.1.1.3 ! root       58:     s->fd = open(filename, O_RDONLY | O_BINARY);
1.1       root       59:     if (s->fd < 0)
1.1.1.3 ! root       60:         return -errno;
1.1       root       61:     bs->read_only = 1;
                     62: 
                     63:     /* read header */
                     64:     if(lseek(s->fd,128,SEEK_SET)<0) {
                     65: cloop_close:
                     66:        close(s->fd);
                     67:        return -1;
                     68:     }
                     69:     if(read(s->fd,&s->block_size,4)<4)
                     70:        goto cloop_close;
                     71:     s->block_size=be32_to_cpu(s->block_size);
                     72:     if(read(s->fd,&s->n_blocks,4)<4)
                     73:        goto cloop_close;
                     74:     s->n_blocks=be32_to_cpu(s->n_blocks);
                     75: 
                     76:     /* read offsets */
                     77:     offsets_size=s->n_blocks*sizeof(uint64_t);
                     78:     if(!(s->offsets=(uint64_t*)malloc(offsets_size)))
                     79:        goto cloop_close;
                     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 */
1.1.1.2   root       92:     if(!(s->compressed_block = malloc(max_compressed_block_size+1)))
1.1       root       93:        goto cloop_close;
1.1.1.2   root       94:     if(!(s->uncompressed_block = malloc(s->block_size)))
1.1       root       95:        goto cloop_close;
                     96:     if(inflateInit(&s->zstream) != Z_OK)
                     97:        goto cloop_close;
                     98:     s->current_block=s->n_blocks;
                     99:     
                    100:     s->sectors_per_block = s->block_size/512;
                    101:     bs->total_sectors = s->n_blocks*s->sectors_per_block;
                    102:     return 0;
                    103: }
                    104: 
                    105: static inline int cloop_read_block(BDRVCloopState *s,int block_num)
                    106: {
                    107:     if(s->current_block != block_num) {
                    108:        int ret;
                    109:         uint32_t bytes = s->offsets[block_num+1]-s->offsets[block_num];
                    110:            
                    111:        lseek(s->fd, s->offsets[block_num], SEEK_SET);
                    112:         ret = read(s->fd, s->compressed_block, bytes);
                    113:         if (ret != bytes) 
                    114:             return -1;
                    115:        
                    116:        s->zstream.next_in = s->compressed_block;
                    117:        s->zstream.avail_in = bytes;
                    118:        s->zstream.next_out = s->uncompressed_block;
                    119:        s->zstream.avail_out = s->block_size;
                    120:        ret = inflateReset(&s->zstream);
                    121:        if(ret != Z_OK)
                    122:            return -1;
                    123:        ret = inflate(&s->zstream, Z_FINISH);
                    124:        if(ret != Z_STREAM_END || s->zstream.total_out != s->block_size)
                    125:            return -1;
                    126:        
                    127:        s->current_block = block_num;
                    128:     }
                    129:     return 0;
                    130: }
                    131: 
                    132: static int cloop_read(BlockDriverState *bs, int64_t sector_num, 
                    133:                     uint8_t *buf, int nb_sectors)
                    134: {
                    135:     BDRVCloopState *s = bs->opaque;
                    136:     int i;
                    137: 
                    138:     for(i=0;i<nb_sectors;i++) {
                    139:        uint32_t sector_offset_in_block=((sector_num+i)%s->sectors_per_block),
                    140:            block_num=(sector_num+i)/s->sectors_per_block;
                    141:        if(cloop_read_block(s, block_num) != 0)
                    142:            return -1;
                    143:        memcpy(buf+i*512,s->uncompressed_block+sector_offset_in_block*512,512);
                    144:     }
                    145:     return 0;
                    146: }
                    147: 
                    148: static void cloop_close(BlockDriverState *bs)
                    149: {
                    150:     BDRVCloopState *s = bs->opaque;
                    151:     close(s->fd);
                    152:     if(s->n_blocks>0)
                    153:        free(s->offsets);
                    154:     free(s->compressed_block);
                    155:     free(s->uncompressed_block);
                    156:     inflateEnd(&s->zstream);
                    157: }
                    158: 
                    159: BlockDriver bdrv_cloop = {
                    160:     "cloop",
                    161:     sizeof(BDRVCloopState),
                    162:     cloop_probe,
                    163:     cloop_open,
                    164:     cloop_read,
                    165:     NULL,
                    166:     cloop_close,
                    167: };
                    168: 
                    169: 

unix.superglobalmegacorp.com