|
|
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.