File:  [Qemu by Fabrice Bellard] / qemu / block-cloop.c
Revision 1.1.1.5 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 16:50:26 2018 UTC (23 months, 1 week ago) by root
Branches: qemu, MAIN
CVS tags: qemu0105, qemu0104, qemu0103, qemu0102, qemu0101, qemu0100, HEAD
qemu 0.10.0

    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:     s->offsets=(uint64_t*)qemu_malloc(offsets_size);
   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 */
   91:     s->compressed_block = qemu_malloc(max_compressed_block_size+1);
   92:     s->uncompressed_block = qemu_malloc(s->block_size);
   93:     if(inflateInit(&s->zstream) != Z_OK)
   94: 	goto cloop_close;
   95:     s->current_block=s->n_blocks;
   96: 
   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];
  107: 
  108: 	lseek(s->fd, s->offsets[block_num], SEEK_SET);
  109:         ret = read(s->fd, s->compressed_block, bytes);
  110:         if (ret != bytes)
  111:             return -1;
  112: 
  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;
  123: 
  124: 	s->current_block = block_num;
  125:     }
  126:     return 0;
  127: }
  128: 
  129: static int cloop_read(BlockDriverState *bs, int64_t sector_num,
  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