|
|
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: 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:
1.1.1.2 ! root 53: static int cloop_open(BlockDriverState *bs, int flags)
1.1 root 54: {
55: BDRVCloopState *s = bs->opaque;
56: uint32_t offsets_size,max_compressed_block_size=1,i;
57:
58: bs->read_only = 1;
59:
60: /* read header */
1.1.1.2 ! root 61: if (bdrv_pread(bs->file, 128, &s->block_size, 4) < 4) {
! 62: goto cloop_close;
1.1 root 63: }
1.1.1.2 ! root 64: s->block_size = be32_to_cpu(s->block_size);
! 65:
! 66: if (bdrv_pread(bs->file, 128 + 4, &s->n_blocks, 4) < 4) {
! 67: goto cloop_close;
! 68: }
! 69: s->n_blocks = be32_to_cpu(s->n_blocks);
1.1 root 70:
71: /* read offsets */
1.1.1.2 ! root 72: offsets_size = s->n_blocks * sizeof(uint64_t);
! 73: s->offsets = qemu_malloc(offsets_size);
! 74: if (bdrv_pread(bs->file, 128 + 4 + 4, s->offsets, offsets_size) <
! 75: offsets_size) {
1.1 root 76: goto cloop_close;
1.1.1.2 ! root 77: }
1.1 root 78: for(i=0;i<s->n_blocks;i++) {
79: s->offsets[i]=be64_to_cpu(s->offsets[i]);
80: if(i>0) {
81: uint32_t size=s->offsets[i]-s->offsets[i-1];
82: if(size>max_compressed_block_size)
83: max_compressed_block_size=size;
84: }
85: }
86:
87: /* initialize zlib engine */
88: s->compressed_block = qemu_malloc(max_compressed_block_size+1);
89: s->uncompressed_block = qemu_malloc(s->block_size);
90: if(inflateInit(&s->zstream) != Z_OK)
91: goto cloop_close;
92: s->current_block=s->n_blocks;
93:
94: s->sectors_per_block = s->block_size/512;
95: bs->total_sectors = s->n_blocks*s->sectors_per_block;
96: return 0;
1.1.1.2 ! root 97:
! 98: cloop_close:
! 99: return -1;
1.1 root 100: }
101:
1.1.1.2 ! root 102: static inline int cloop_read_block(BlockDriverState *bs, int block_num)
1.1 root 103: {
1.1.1.2 ! root 104: BDRVCloopState *s = bs->opaque;
! 105:
1.1 root 106: if(s->current_block != block_num) {
107: int ret;
108: uint32_t bytes = s->offsets[block_num+1]-s->offsets[block_num];
109:
1.1.1.2 ! root 110: ret = bdrv_pread(bs->file, s->offsets[block_num], s->compressed_block,
! 111: bytes);
1.1 root 112: if (ret != bytes)
113: return -1;
114:
115: s->zstream.next_in = s->compressed_block;
116: s->zstream.avail_in = bytes;
117: s->zstream.next_out = s->uncompressed_block;
118: s->zstream.avail_out = s->block_size;
119: ret = inflateReset(&s->zstream);
120: if(ret != Z_OK)
121: return -1;
122: ret = inflate(&s->zstream, Z_FINISH);
123: if(ret != Z_STREAM_END || s->zstream.total_out != s->block_size)
124: return -1;
125:
126: s->current_block = block_num;
127: }
128: return 0;
129: }
130:
131: static int cloop_read(BlockDriverState *bs, int64_t sector_num,
132: uint8_t *buf, int nb_sectors)
133: {
134: BDRVCloopState *s = bs->opaque;
135: int i;
136:
137: for(i=0;i<nb_sectors;i++) {
138: uint32_t sector_offset_in_block=((sector_num+i)%s->sectors_per_block),
139: block_num=(sector_num+i)/s->sectors_per_block;
1.1.1.2 ! root 140: if(cloop_read_block(bs, block_num) != 0)
1.1 root 141: return -1;
142: memcpy(buf+i*512,s->uncompressed_block+sector_offset_in_block*512,512);
143: }
144: return 0;
145: }
146:
147: static void cloop_close(BlockDriverState *bs)
148: {
149: BDRVCloopState *s = bs->opaque;
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.