cloop.c revision 5d8f37ad78fc66901af50c762029a501561f3b23
1dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat/* 2dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * QEMU Block driver for CLOOP images 3dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * 4dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * Copyright (c) 2004 Johannes E. Schindelin 5dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * 6dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * Permission is hereby granted, free of charge, to any person obtaining a copy 7dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * of this software and associated documentation files (the "Software"), to deal 8dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * in the Software without restriction, including without limitation the rights 9dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * copies of the Software, and to permit persons to whom the Software is 11dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * furnished to do so, subject to the following conditions: 12dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * 13dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * The above copyright notice and this permission notice shall be included in 14dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * all copies or substantial portions of the Software. 15dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * 16dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * THE SOFTWARE. 23dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat */ 24dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include "qemu-common.h" 25dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include "block_int.h" 26dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include "module.h" 27dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <zlib.h> 28dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 29dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehattypedef struct BDRVCloopState { 30dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int fd; 31dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat uint32_t block_size; 32dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat uint32_t n_blocks; 33dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat uint64_t* offsets; 34dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat uint32_t sectors_per_block; 35dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat uint32_t current_block; 36dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat uint8_t *compressed_block; 37dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat uint8_t *uncompressed_block; 38dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat z_stream zstream; 39dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} BDRVCloopState; 40dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 41dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic int cloop_probe(const uint8_t *buf, int buf_size, const char *filename) 42dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 43dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat const char* magic_version_2_0="#!/bin/sh\n" 44dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat "#V2.0 Format\n" 45dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat "modprobe cloop file=$0 && mount -r -t iso9660 /dev/cloop $1\n"; 46dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int length=strlen(magic_version_2_0); 47b856938e2c00fefb701f906a90d545f92007ac96San Mehat if(length>buf_size) 48b856938e2c00fefb701f906a90d545f92007ac96San Mehat length=buf_size; 4995e6324d6688526258024064f7603e598a7e6159San Mehat if(!memcmp(magic_version_2_0,buf,length)) 50c5b66ed439aab1843d40a629347852359ba2ae70San Mehat return 2; 51b856938e2c00fefb701f906a90d545f92007ac96San Mehat return 0; 52b856938e2c00fefb701f906a90d545f92007ac96San Mehat} 53b856938e2c00fefb701f906a90d545f92007ac96San Mehat 54dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic int cloop_open(BlockDriverState *bs, const char *filename, int flags) 55dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 56dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat BDRVCloopState *s = bs->opaque; 57dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat uint32_t offsets_size,max_compressed_block_size=1,i; 58dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 59dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat s->fd = open(filename, O_RDONLY | O_BINARY); 60dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (s->fd < 0) 61dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -errno; 62dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat bs->read_only = 1; 63dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 64dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat /* read header */ 65dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if(lseek(s->fd,128,SEEK_SET)<0) { 66dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatcloop_close: 67dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat close(s->fd); 68dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 69dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 70dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if(read(s->fd,&s->block_size,4)<4) 71dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat goto cloop_close; 72dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat s->block_size=be32_to_cpu(s->block_size); 73dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if(read(s->fd,&s->n_blocks,4)<4) 74dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat goto cloop_close; 75dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat s->n_blocks=be32_to_cpu(s->n_blocks); 76dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 77dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat /* read offsets */ 78dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat offsets_size=s->n_blocks*sizeof(uint64_t); 79dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat s->offsets=(uint64_t*)qemu_malloc(offsets_size); 80dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if(read(s->fd,s->offsets,offsets_size)<offsets_size) 81dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat goto cloop_close; 82dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat for(i=0;i<s->n_blocks;i++) { 83dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat s->offsets[i]=be64_to_cpu(s->offsets[i]); 84dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if(i>0) { 85dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat uint32_t size=s->offsets[i]-s->offsets[i-1]; 86dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if(size>max_compressed_block_size) 87dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat max_compressed_block_size=size; 88dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 89dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 90dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 91dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat /* initialize zlib engine */ 92dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat s->compressed_block = qemu_malloc(max_compressed_block_size+1); 93dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat s->uncompressed_block = qemu_malloc(s->block_size); 94dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if(inflateInit(&s->zstream) != Z_OK) 95dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat goto cloop_close; 96dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat s->current_block=s->n_blocks; 97dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 98dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat s->sectors_per_block = s->block_size/512; 99dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat bs->total_sectors = s->n_blocks*s->sectors_per_block; 100dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 0; 101dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 102dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 103dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic inline int cloop_read_block(BDRVCloopState *s,int block_num) 104dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 105dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if(s->current_block != block_num) { 106dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int ret; 107b856938e2c00fefb701f906a90d545f92007ac96San Mehat uint32_t bytes = s->offsets[block_num+1]-s->offsets[block_num]; 108b856938e2c00fefb701f906a90d545f92007ac96San Mehat 109b856938e2c00fefb701f906a90d545f92007ac96San Mehat lseek(s->fd, s->offsets[block_num], SEEK_SET); 11095e6324d6688526258024064f7603e598a7e6159San Mehat ret = read(s->fd, s->compressed_block, bytes); 11195e6324d6688526258024064f7603e598a7e6159San Mehat if (ret != bytes) 112c5b66ed439aab1843d40a629347852359ba2ae70San Mehat return -1; 113c5b66ed439aab1843d40a629347852359ba2ae70San Mehat 114b856938e2c00fefb701f906a90d545f92007ac96San Mehat s->zstream.next_in = s->compressed_block; 11595e6324d6688526258024064f7603e598a7e6159San Mehat s->zstream.avail_in = bytes; 116b856938e2c00fefb701f906a90d545f92007ac96San Mehat s->zstream.next_out = s->uncompressed_block; 117b856938e2c00fefb701f906a90d545f92007ac96San Mehat s->zstream.avail_out = s->block_size; 118b856938e2c00fefb701f906a90d545f92007ac96San Mehat ret = inflateReset(&s->zstream); 119dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if(ret != Z_OK) 120dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 121dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat ret = inflate(&s->zstream, Z_FINISH); 122dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if(ret != Z_STREAM_END || s->zstream.total_out != s->block_size) 123dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 124dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 125dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat s->current_block = block_num; 126dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 127dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 0; 128dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 129dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 130dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic int cloop_read(BlockDriverState *bs, int64_t sector_num, 131dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat uint8_t *buf, int nb_sectors) 132dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 133dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat BDRVCloopState *s = bs->opaque; 134dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int i; 135dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 136dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat for(i=0;i<nb_sectors;i++) { 137dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat uint32_t sector_offset_in_block=((sector_num+i)%s->sectors_per_block), 138dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat block_num=(sector_num+i)/s->sectors_per_block; 139dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if(cloop_read_block(s, block_num) != 0) 140dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 141dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat memcpy(buf+i*512,s->uncompressed_block+sector_offset_in_block*512,512); 142dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 143dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 0; 144dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 145dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 146dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic void cloop_close(BlockDriverState *bs) 147dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 148dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat BDRVCloopState *s = bs->opaque; 149dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat close(s->fd); 150dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if(s->n_blocks>0) 151dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat free(s->offsets); 152dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat free(s->compressed_block); 153dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat free(s->uncompressed_block); 154dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat inflateEnd(&s->zstream); 155dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 156dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 157dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic BlockDriver bdrv_cloop = { 158dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat .format_name = "cloop", 159dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat .instance_size = sizeof(BDRVCloopState), 160dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat .bdrv_probe = cloop_probe, 161dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat .bdrv_open = cloop_open, 162dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat .bdrv_read = cloop_read, 163dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat .bdrv_close = cloop_close, 164b856938e2c00fefb701f906a90d545f92007ac96San Mehat}; 165b856938e2c00fefb701f906a90d545f92007ac96San Mehat 166b856938e2c00fefb701f906a90d545f92007ac96San Mehatstatic void bdrv_cloop_init(void) 167b856938e2c00fefb701f906a90d545f92007ac96San Mehat{ 16895e6324d6688526258024064f7603e598a7e6159San Mehat bdrv_register(&bdrv_cloop); 169b856938e2c00fefb701f906a90d545f92007ac96San Mehat} 170b856938e2c00fefb701f906a90d545f92007ac96San Mehat 171b856938e2c00fefb701f906a90d545f92007ac96San Mehatblock_init(bdrv_cloop_init); 172dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat