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