symbian-qemu-0.9.1-12/qemu-symbian-svp/block-cloop.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     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 <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;
       
    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 
       
    53 static int cloop_open(BlockDriverState *bs, const char *filename, int flags)
       
    54 {
       
    55     BDRVCloopState *s = bs->opaque;
       
    56     uint32_t offsets_size,max_compressed_block_size=1,i;
       
    57 
       
    58     s->fd = open(filename, O_RDONLY | O_BINARY);
       
    59     if (s->fd < 0)
       
    60         return -errno;
       
    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 */
       
    92     if(!(s->compressed_block = malloc(max_compressed_block_size+1)))
       
    93 	goto cloop_close;
       
    94     if(!(s->uncompressed_block = malloc(s->block_size)))
       
    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 };