File:  [Qemu by Fabrice Bellard] / qemu / block-cloop.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 16:37:52 2018 UTC (3 years, 7 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu0080, qemu0072, HEAD
qemu 0.7.2

    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;
   35:     char* compressed_block;
   36:     char* 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)
   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 | O_LARGEFILE);
   59:     if (s->fd < 0)
   60:         return -1;
   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=(char*)malloc(max_compressed_block_size+1)))
   93: 	goto cloop_close;
   94:     if(!(s->uncompressed_block=(char*)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: };
  168: 
  169: 

unix.superglobalmegacorp.com