Annotation of qemu/block-cloop.c, revision 1.1.1.5

1.1       root        1: /*
                      2:  * QEMU Block driver for CLOOP images
1.1.1.4   root        3:  *
1.1       root        4:  * Copyright (c) 2004 Johannes E. Schindelin
1.1.1.4   root        5:  *
1.1       root        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:  */
1.1.1.4   root       24: #include "qemu-common.h"
1.1       root       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);
1.1.1.5 ! root       78:     s->offsets=(uint64_t*)qemu_malloc(offsets_size);
1.1       root       79:     if(read(s->fd,s->offsets,offsets_size)<offsets_size)
                     80:        goto cloop_close;
                     81:     for(i=0;i<s->n_blocks;i++) {
                     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:     }
                     89: 
                     90:     /* initialize zlib engine */
1.1.1.5 ! root       91:     s->compressed_block = qemu_malloc(max_compressed_block_size+1);
        !            92:     s->uncompressed_block = qemu_malloc(s->block_size);
1.1       root       93:     if(inflateInit(&s->zstream) != Z_OK)
                     94:        goto cloop_close;
                     95:     s->current_block=s->n_blocks;
1.1.1.4   root       96: 
1.1       root       97:     s->sectors_per_block = s->block_size/512;
                     98:     bs->total_sectors = s->n_blocks*s->sectors_per_block;
                     99:     return 0;
                    100: }
                    101: 
                    102: static inline int cloop_read_block(BDRVCloopState *s,int block_num)
                    103: {
                    104:     if(s->current_block != block_num) {
                    105:        int ret;
                    106:         uint32_t bytes = s->offsets[block_num+1]-s->offsets[block_num];
1.1.1.4   root      107: 
1.1       root      108:        lseek(s->fd, s->offsets[block_num], SEEK_SET);
                    109:         ret = read(s->fd, s->compressed_block, bytes);
1.1.1.4   root      110:         if (ret != bytes)
1.1       root      111:             return -1;
1.1.1.4   root      112: 
1.1       root      113:        s->zstream.next_in = s->compressed_block;
                    114:        s->zstream.avail_in = bytes;
                    115:        s->zstream.next_out = s->uncompressed_block;
                    116:        s->zstream.avail_out = s->block_size;
                    117:        ret = inflateReset(&s->zstream);
                    118:        if(ret != Z_OK)
                    119:            return -1;
                    120:        ret = inflate(&s->zstream, Z_FINISH);
                    121:        if(ret != Z_STREAM_END || s->zstream.total_out != s->block_size)
                    122:            return -1;
1.1.1.4   root      123: 
1.1       root      124:        s->current_block = block_num;
                    125:     }
                    126:     return 0;
                    127: }
                    128: 
1.1.1.4   root      129: static int cloop_read(BlockDriverState *bs, int64_t sector_num,
1.1       root      130:                     uint8_t *buf, int nb_sectors)
                    131: {
                    132:     BDRVCloopState *s = bs->opaque;
                    133:     int i;
                    134: 
                    135:     for(i=0;i<nb_sectors;i++) {
                    136:        uint32_t sector_offset_in_block=((sector_num+i)%s->sectors_per_block),
                    137:            block_num=(sector_num+i)/s->sectors_per_block;
                    138:        if(cloop_read_block(s, block_num) != 0)
                    139:            return -1;
                    140:        memcpy(buf+i*512,s->uncompressed_block+sector_offset_in_block*512,512);
                    141:     }
                    142:     return 0;
                    143: }
                    144: 
                    145: static void cloop_close(BlockDriverState *bs)
                    146: {
                    147:     BDRVCloopState *s = bs->opaque;
                    148:     close(s->fd);
                    149:     if(s->n_blocks>0)
                    150:        free(s->offsets);
                    151:     free(s->compressed_block);
                    152:     free(s->uncompressed_block);
                    153:     inflateEnd(&s->zstream);
                    154: }
                    155: 
                    156: BlockDriver bdrv_cloop = {
                    157:     "cloop",
                    158:     sizeof(BDRVCloopState),
                    159:     cloop_probe,
                    160:     cloop_open,
                    161:     cloop_read,
                    162:     NULL,
                    163:     cloop_close,
                    164: };

unix.superglobalmegacorp.com