|
|
1.1 ! root 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 "module.h" ! 27: #include <zlib.h> ! 28: ! 29: typedef struct BDRVCloopState { ! 30: int fd; ! 31: uint32_t block_size; ! 32: uint32_t n_blocks; ! 33: uint64_t* offsets; ! 34: uint32_t sectors_per_block; ! 35: uint32_t current_block; ! 36: uint8_t *compressed_block; ! 37: uint8_t *uncompressed_block; ! 38: z_stream zstream; ! 39: } BDRVCloopState; ! 40: ! 41: static int cloop_probe(const uint8_t *buf, int buf_size, const char *filename) ! 42: { ! 43: const char* magic_version_2_0="#!/bin/sh\n" ! 44: "#V2.0 Format\n" ! 45: "modprobe cloop file=$0 && mount -r -t iso9660 /dev/cloop $1\n"; ! 46: int length=strlen(magic_version_2_0); ! 47: if(length>buf_size) ! 48: length=buf_size; ! 49: if(!memcmp(magic_version_2_0,buf,length)) ! 50: return 2; ! 51: return 0; ! 52: } ! 53: ! 54: static int cloop_open(BlockDriverState *bs, const char *filename, int flags) ! 55: { ! 56: BDRVCloopState *s = bs->opaque; ! 57: uint32_t offsets_size,max_compressed_block_size=1,i; ! 58: ! 59: s->fd = open(filename, O_RDONLY | O_BINARY); ! 60: if (s->fd < 0) ! 61: return -errno; ! 62: bs->read_only = 1; ! 63: ! 64: /* read header */ ! 65: if(lseek(s->fd,128,SEEK_SET)<0) { ! 66: cloop_close: ! 67: close(s->fd); ! 68: return -1; ! 69: } ! 70: if(read(s->fd,&s->block_size,4)<4) ! 71: goto cloop_close; ! 72: s->block_size=be32_to_cpu(s->block_size); ! 73: if(read(s->fd,&s->n_blocks,4)<4) ! 74: goto cloop_close; ! 75: s->n_blocks=be32_to_cpu(s->n_blocks); ! 76: ! 77: /* read offsets */ ! 78: offsets_size=s->n_blocks*sizeof(uint64_t); ! 79: s->offsets=(uint64_t*)qemu_malloc(offsets_size); ! 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: s->compressed_block = qemu_malloc(max_compressed_block_size+1); ! 93: s->uncompressed_block = qemu_malloc(s->block_size); ! 94: if(inflateInit(&s->zstream) != Z_OK) ! 95: goto cloop_close; ! 96: s->current_block=s->n_blocks; ! 97: ! 98: s->sectors_per_block = s->block_size/512; ! 99: bs->total_sectors = s->n_blocks*s->sectors_per_block; ! 100: return 0; ! 101: } ! 102: ! 103: static inline int cloop_read_block(BDRVCloopState *s,int block_num) ! 104: { ! 105: if(s->current_block != block_num) { ! 106: int ret; ! 107: uint32_t bytes = s->offsets[block_num+1]-s->offsets[block_num]; ! 108: ! 109: lseek(s->fd, s->offsets[block_num], SEEK_SET); ! 110: ret = read(s->fd, s->compressed_block, bytes); ! 111: if (ret != bytes) ! 112: return -1; ! 113: ! 114: s->zstream.next_in = s->compressed_block; ! 115: s->zstream.avail_in = bytes; ! 116: s->zstream.next_out = s->uncompressed_block; ! 117: s->zstream.avail_out = s->block_size; ! 118: ret = inflateReset(&s->zstream); ! 119: if(ret != Z_OK) ! 120: return -1; ! 121: ret = inflate(&s->zstream, Z_FINISH); ! 122: if(ret != Z_STREAM_END || s->zstream.total_out != s->block_size) ! 123: return -1; ! 124: ! 125: s->current_block = block_num; ! 126: } ! 127: return 0; ! 128: } ! 129: ! 130: static int cloop_read(BlockDriverState *bs, int64_t sector_num, ! 131: uint8_t *buf, int nb_sectors) ! 132: { ! 133: BDRVCloopState *s = bs->opaque; ! 134: int i; ! 135: ! 136: for(i=0;i<nb_sectors;i++) { ! 137: uint32_t sector_offset_in_block=((sector_num+i)%s->sectors_per_block), ! 138: block_num=(sector_num+i)/s->sectors_per_block; ! 139: if(cloop_read_block(s, block_num) != 0) ! 140: return -1; ! 141: memcpy(buf+i*512,s->uncompressed_block+sector_offset_in_block*512,512); ! 142: } ! 143: return 0; ! 144: } ! 145: ! 146: static void cloop_close(BlockDriverState *bs) ! 147: { ! 148: BDRVCloopState *s = bs->opaque; ! 149: close(s->fd); ! 150: if(s->n_blocks>0) ! 151: free(s->offsets); ! 152: free(s->compressed_block); ! 153: free(s->uncompressed_block); ! 154: inflateEnd(&s->zstream); ! 155: } ! 156: ! 157: static BlockDriver bdrv_cloop = { ! 158: .format_name = "cloop", ! 159: .instance_size = sizeof(BDRVCloopState), ! 160: .bdrv_probe = cloop_probe, ! 161: .bdrv_open = cloop_open, ! 162: .bdrv_read = cloop_read, ! 163: .bdrv_close = cloop_close, ! 164: }; ! 165: ! 166: static void bdrv_cloop_init(void) ! 167: { ! 168: bdrv_register(&bdrv_cloop); ! 169: } ! 170: ! 171: block_init(bdrv_cloop_init);
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.