Revision 019d6b8f

b/Makefile
64 64
# BLOCK_OBJS is code used by both qemu system emulation and qemu-img
65 65

  
66 66
BLOCK_OBJS=cutils.o cache-utils.o qemu-malloc.o module.o
67
BLOCK_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o
68
BLOCK_OBJS+=block-dmg.o block-bochs.o block-vpc.o block-vvfat.o
69
BLOCK_OBJS+=block-qcow2.o block-parallels.o block-nbd.o
67
BLOCK_OBJS+=block/cow.o block/qcow.o aes.o block/vmdk.o block/cloop.o
68
BLOCK_OBJS+=block/dmg.o block/bochs.o block/vpc.o block/vvfat.o
69
BLOCK_OBJS+=block/qcow2.o block/parallels.o block/nbd.o
70 70
BLOCK_OBJS+=nbd.o block.o aio.o
71 71

  
72 72
ifdef CONFIG_WIN32
73
BLOCK_OBJS += block-raw-win32.o
73
BLOCK_OBJS += block/raw-win32.o
74 74
else
75 75
ifdef CONFIG_AIO
76 76
BLOCK_OBJS += posix-aio-compat.o
77 77
endif
78
BLOCK_OBJS += block-raw-posix.o
78
BLOCK_OBJS += block/raw-posix.o
79 79
endif
80 80

  
81 81
######################################################################
......
234 234
# avoid old build problems by removing potentially incorrect old files
235 235
	rm -f config.mak config.h op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h
236 236
	rm -f *.o *.d *.a $(TOOLS) TAGS cscope.* *.pod *~ */*~
237
	rm -f slirp/*.o slirp/*.d audio/*.o audio/*.d
237
	rm -f slirp/*.o slirp/*.d audio/*.o audio/*.d block/*.o block/*.d
238 238
	$(MAKE) -C tests clean
239 239
	for d in $(TARGET_DIRS); do \
240 240
	$(MAKE) -C $$d $@ || exit 1 ; \
......
408 408
	$(mandir)/man8/qemu-nbd.8
409 409

  
410 410
# Include automatically generated dependency files
411
-include $(wildcard *.d audio/*.d slirp/*.d)
411
-include $(wildcard *.d audio/*.d slirp/*.d block/*.d)
/dev/null
1
/*
2
 * Block driver for the various disk image formats used by Bochs
3
 * Currently only for "growing" type in read-only mode
4
 *
5
 * Copyright (c) 2005 Alex Beregszaszi
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8
 * of this software and associated documentation files (the "Software"), to deal
9
 * in the Software without restriction, including without limitation the rights
10
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
 * copies of the Software, and to permit persons to whom the Software is
12
 * furnished to do so, subject to the following conditions:
13
 *
14
 * The above copyright notice and this permission notice shall be included in
15
 * all copies or substantial portions of the Software.
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
 * THE SOFTWARE.
24
 */
25
#include "qemu-common.h"
26
#include "block_int.h"
27
#include "module.h"
28

  
29
/**************************************************************/
30

  
31
#define HEADER_MAGIC "Bochs Virtual HD Image"
32
#define HEADER_VERSION 0x00020000
33
#define HEADER_V1 0x00010000
34
#define HEADER_SIZE 512
35

  
36
#define REDOLOG_TYPE "Redolog"
37
#define GROWING_TYPE "Growing"
38

  
39
// not allocated: 0xffffffff
40

  
41
// always little-endian
42
struct bochs_header_v1 {
43
    char magic[32]; // "Bochs Virtual HD Image"
44
    char type[16]; // "Redolog"
45
    char subtype[16]; // "Undoable" / "Volatile" / "Growing"
46
    uint32_t version;
47
    uint32_t header; // size of header
48

  
49
    union {
50
	struct {
51
	    uint32_t catalog; // num of entries
52
	    uint32_t bitmap; // bitmap size
53
	    uint32_t extent; // extent size
54
	    uint64_t disk; // disk size
55
	    char padding[HEADER_SIZE - 64 - 8 - 20];
56
	} redolog;
57
	char padding[HEADER_SIZE - 64 - 8];
58
    } extra;
59
};
60

  
61
// always little-endian
62
struct bochs_header {
63
    char magic[32]; // "Bochs Virtual HD Image"
64
    char type[16]; // "Redolog"
65
    char subtype[16]; // "Undoable" / "Volatile" / "Growing"
66
    uint32_t version;
67
    uint32_t header; // size of header
68

  
69
    union {
70
	struct {
71
	    uint32_t catalog; // num of entries
72
	    uint32_t bitmap; // bitmap size
73
	    uint32_t extent; // extent size
74
	    uint32_t reserved; // for ???
75
	    uint64_t disk; // disk size
76
	    char padding[HEADER_SIZE - 64 - 8 - 24];
77
	} redolog;
78
	char padding[HEADER_SIZE - 64 - 8];
79
    } extra;
80
};
81

  
82
typedef struct BDRVBochsState {
83
    int fd;
84

  
85
    uint32_t *catalog_bitmap;
86
    int catalog_size;
87

  
88
    int data_offset;
89

  
90
    int bitmap_blocks;
91
    int extent_blocks;
92
    int extent_size;
93
} BDRVBochsState;
94

  
95
static int bochs_probe(const uint8_t *buf, int buf_size, const char *filename)
96
{
97
    const struct bochs_header *bochs = (const void *)buf;
98

  
99
    if (buf_size < HEADER_SIZE)
100
	return 0;
101

  
102
    if (!strcmp(bochs->magic, HEADER_MAGIC) &&
103
	!strcmp(bochs->type, REDOLOG_TYPE) &&
104
	!strcmp(bochs->subtype, GROWING_TYPE) &&
105
	((le32_to_cpu(bochs->version) == HEADER_VERSION) ||
106
	(le32_to_cpu(bochs->version) == HEADER_V1)))
107
	return 100;
108

  
109
    return 0;
110
}
111

  
112
static int bochs_open(BlockDriverState *bs, const char *filename, int flags)
113
{
114
    BDRVBochsState *s = bs->opaque;
115
    int fd, i;
116
    struct bochs_header bochs;
117
    struct bochs_header_v1 header_v1;
118

  
119
    fd = open(filename, O_RDWR | O_BINARY);
120
    if (fd < 0) {
121
        fd = open(filename, O_RDONLY | O_BINARY);
122
        if (fd < 0)
123
            return -1;
124
    }
125

  
126
    bs->read_only = 1; // no write support yet
127

  
128
    s->fd = fd;
129

  
130
    if (read(fd, &bochs, sizeof(bochs)) != sizeof(bochs)) {
131
        goto fail;
132
    }
133

  
134
    if (strcmp(bochs.magic, HEADER_MAGIC) ||
135
        strcmp(bochs.type, REDOLOG_TYPE) ||
136
        strcmp(bochs.subtype, GROWING_TYPE) ||
137
	((le32_to_cpu(bochs.version) != HEADER_VERSION) &&
138
	(le32_to_cpu(bochs.version) != HEADER_V1))) {
139
        goto fail;
140
    }
141

  
142
    if (le32_to_cpu(bochs.version) == HEADER_V1) {
143
      memcpy(&header_v1, &bochs, sizeof(bochs));
144
      bs->total_sectors = le64_to_cpu(header_v1.extra.redolog.disk) / 512;
145
    } else {
146
      bs->total_sectors = le64_to_cpu(bochs.extra.redolog.disk) / 512;
147
    }
148

  
149
    lseek(s->fd, le32_to_cpu(bochs.header), SEEK_SET);
150

  
151
    s->catalog_size = le32_to_cpu(bochs.extra.redolog.catalog);
152
    s->catalog_bitmap = qemu_malloc(s->catalog_size * 4);
153
    if (read(s->fd, s->catalog_bitmap, s->catalog_size * 4) !=
154
	s->catalog_size * 4)
155
	goto fail;
156
    for (i = 0; i < s->catalog_size; i++)
157
	le32_to_cpus(&s->catalog_bitmap[i]);
158

  
159
    s->data_offset = le32_to_cpu(bochs.header) + (s->catalog_size * 4);
160

  
161
    s->bitmap_blocks = 1 + (le32_to_cpu(bochs.extra.redolog.bitmap) - 1) / 512;
162
    s->extent_blocks = 1 + (le32_to_cpu(bochs.extra.redolog.extent) - 1) / 512;
163

  
164
    s->extent_size = le32_to_cpu(bochs.extra.redolog.extent);
165

  
166
    return 0;
167
 fail:
168
    close(fd);
169
    return -1;
170
}
171

  
172
static inline int seek_to_sector(BlockDriverState *bs, int64_t sector_num)
173
{
174
    BDRVBochsState *s = bs->opaque;
175
    int64_t offset = sector_num * 512;
176
    int64_t extent_index, extent_offset, bitmap_offset, block_offset;
177
    char bitmap_entry;
178

  
179
    // seek to sector
180
    extent_index = offset / s->extent_size;
181
    extent_offset = (offset % s->extent_size) / 512;
182

  
183
    if (s->catalog_bitmap[extent_index] == 0xffffffff)
184
    {
185
//	fprintf(stderr, "page not allocated [%x - %x:%x]\n",
186
//	    sector_num, extent_index, extent_offset);
187
	return -1; // not allocated
188
    }
189

  
190
    bitmap_offset = s->data_offset + (512 * s->catalog_bitmap[extent_index] *
191
	(s->extent_blocks + s->bitmap_blocks));
192
    block_offset = bitmap_offset + (512 * (s->bitmap_blocks + extent_offset));
193

  
194
//    fprintf(stderr, "sect: %x [ext i: %x o: %x] -> %x bitmap: %x block: %x\n",
195
//	sector_num, extent_index, extent_offset,
196
//	le32_to_cpu(s->catalog_bitmap[extent_index]),
197
//	bitmap_offset, block_offset);
198

  
199
    // read in bitmap for current extent
200
    lseek(s->fd, bitmap_offset + (extent_offset / 8), SEEK_SET);
201

  
202
    read(s->fd, &bitmap_entry, 1);
203

  
204
    if (!((bitmap_entry >> (extent_offset % 8)) & 1))
205
    {
206
//	fprintf(stderr, "sector (%x) in bitmap not allocated\n",
207
//	    sector_num);
208
	return -1; // not allocated
209
    }
210

  
211
    lseek(s->fd, block_offset, SEEK_SET);
212

  
213
    return 0;
214
}
215

  
216
static int bochs_read(BlockDriverState *bs, int64_t sector_num,
217
                    uint8_t *buf, int nb_sectors)
218
{
219
    BDRVBochsState *s = bs->opaque;
220
    int ret;
221

  
222
    while (nb_sectors > 0) {
223
	if (!seek_to_sector(bs, sector_num))
224
	{
225
	    ret = read(s->fd, buf, 512);
226
	    if (ret != 512)
227
		return -1;
228
	}
229
	else
230
            memset(buf, 0, 512);
231
        nb_sectors--;
232
        sector_num++;
233
        buf += 512;
234
    }
235
    return 0;
236
}
237

  
238
static void bochs_close(BlockDriverState *bs)
239
{
240
    BDRVBochsState *s = bs->opaque;
241
    qemu_free(s->catalog_bitmap);
242
    close(s->fd);
243
}
244

  
245
static BlockDriver bdrv_bochs = {
246
    .format_name	= "bochs",
247
    .instance_size	= sizeof(BDRVBochsState),
248
    .bdrv_probe		= bochs_probe,
249
    .bdrv_open		= bochs_open,
250
    .bdrv_read		= bochs_read,
251
    .bdrv_close		= bochs_close,
252
};
253

  
254
static void bdrv_bochs_init(void)
255
{
256
    bdrv_register(&bdrv_bochs);
257
}
258

  
259
block_init(bdrv_bochs_init);
/dev/null
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);
/dev/null
1
/*
2
 * Block driver for the COW format
3
 *
4
 * Copyright (c) 2004 Fabrice Bellard
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
#ifndef _WIN32
25
#include "qemu-common.h"
26
#include "block_int.h"
27
#include "module.h"
28
#include <sys/mman.h>
29

  
30
/**************************************************************/
31
/* COW block driver using file system holes */
32

  
33
/* user mode linux compatible COW file */
34
#define COW_MAGIC 0x4f4f4f4d  /* MOOO */
35
#define COW_VERSION 2
36

  
37
struct cow_header_v2 {
38
    uint32_t magic;
39
    uint32_t version;
40
    char backing_file[1024];
41
    int32_t mtime;
42
    uint64_t size;
43
    uint32_t sectorsize;
44
};
45

  
46
typedef struct BDRVCowState {
47
    int fd;
48
    uint8_t *cow_bitmap; /* if non NULL, COW mappings are used first */
49
    uint8_t *cow_bitmap_addr; /* mmap address of cow_bitmap */
50
    int cow_bitmap_size;
51
    int64_t cow_sectors_offset;
52
} BDRVCowState;
53

  
54
static int cow_probe(const uint8_t *buf, int buf_size, const char *filename)
55
{
56
    const struct cow_header_v2 *cow_header = (const void *)buf;
57

  
58
    if (buf_size >= sizeof(struct cow_header_v2) &&
59
        be32_to_cpu(cow_header->magic) == COW_MAGIC &&
60
        be32_to_cpu(cow_header->version) == COW_VERSION)
61
        return 100;
62
    else
63
        return 0;
64
}
65

  
66
static int cow_open(BlockDriverState *bs, const char *filename, int flags)
67
{
68
    BDRVCowState *s = bs->opaque;
69
    int fd;
70
    struct cow_header_v2 cow_header;
71
    int64_t size;
72

  
73
    fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
74
    if (fd < 0) {
75
        fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
76
        if (fd < 0)
77
            return -1;
78
    }
79
    s->fd = fd;
80
    /* see if it is a cow image */
81
    if (read(fd, &cow_header, sizeof(cow_header)) != sizeof(cow_header)) {
82
        goto fail;
83
    }
84

  
85
    if (be32_to_cpu(cow_header.magic) != COW_MAGIC ||
86
        be32_to_cpu(cow_header.version) != COW_VERSION) {
87
        goto fail;
88
    }
89

  
90
    /* cow image found */
91
    size = be64_to_cpu(cow_header.size);
92
    bs->total_sectors = size / 512;
93

  
94
    pstrcpy(bs->backing_file, sizeof(bs->backing_file),
95
            cow_header.backing_file);
96

  
97
    /* mmap the bitmap */
98
    s->cow_bitmap_size = ((bs->total_sectors + 7) >> 3) + sizeof(cow_header);
99
    s->cow_bitmap_addr = (void *)mmap(get_mmap_addr(s->cow_bitmap_size),
100
                                      s->cow_bitmap_size,
101
                                      PROT_READ | PROT_WRITE,
102
                                      MAP_SHARED, s->fd, 0);
103
    if (s->cow_bitmap_addr == MAP_FAILED)
104
        goto fail;
105
    s->cow_bitmap = s->cow_bitmap_addr + sizeof(cow_header);
106
    s->cow_sectors_offset = (s->cow_bitmap_size + 511) & ~511;
107
    return 0;
108
 fail:
109
    close(fd);
110
    return -1;
111
}
112

  
113
static inline void cow_set_bit(uint8_t *bitmap, int64_t bitnum)
114
{
115
    bitmap[bitnum / 8] |= (1 << (bitnum%8));
116
}
117

  
118
static inline int is_bit_set(const uint8_t *bitmap, int64_t bitnum)
119
{
120
    return !!(bitmap[bitnum / 8] & (1 << (bitnum%8)));
121
}
122

  
123

  
124
/* Return true if first block has been changed (ie. current version is
125
 * in COW file).  Set the number of continuous blocks for which that
126
 * is true. */
127
static inline int is_changed(uint8_t *bitmap,
128
                             int64_t sector_num, int nb_sectors,
129
                             int *num_same)
130
{
131
    int changed;
132

  
133
    if (!bitmap || nb_sectors == 0) {
134
	*num_same = nb_sectors;
135
	return 0;
136
    }
137

  
138
    changed = is_bit_set(bitmap, sector_num);
139
    for (*num_same = 1; *num_same < nb_sectors; (*num_same)++) {
140
	if (is_bit_set(bitmap, sector_num + *num_same) != changed)
141
	    break;
142
    }
143

  
144
    return changed;
145
}
146

  
147
static int cow_is_allocated(BlockDriverState *bs, int64_t sector_num,
148
                            int nb_sectors, int *pnum)
149
{
150
    BDRVCowState *s = bs->opaque;
151
    return is_changed(s->cow_bitmap, sector_num, nb_sectors, pnum);
152
}
153

  
154
static int cow_read(BlockDriverState *bs, int64_t sector_num,
155
                    uint8_t *buf, int nb_sectors)
156
{
157
    BDRVCowState *s = bs->opaque;
158
    int ret, n;
159

  
160
    while (nb_sectors > 0) {
161
        if (is_changed(s->cow_bitmap, sector_num, nb_sectors, &n)) {
162
            lseek(s->fd, s->cow_sectors_offset + sector_num * 512, SEEK_SET);
163
            ret = read(s->fd, buf, n * 512);
164
            if (ret != n * 512)
165
                return -1;
166
        } else {
167
            if (bs->backing_hd) {
168
                /* read from the base image */
169
                ret = bdrv_read(bs->backing_hd, sector_num, buf, n);
170
                if (ret < 0)
171
                    return -1;
172
            } else {
173
            memset(buf, 0, n * 512);
174
        }
175
        }
176
        nb_sectors -= n;
177
        sector_num += n;
178
        buf += n * 512;
179
    }
180
    return 0;
181
}
182

  
183
static int cow_write(BlockDriverState *bs, int64_t sector_num,
184
                     const uint8_t *buf, int nb_sectors)
185
{
186
    BDRVCowState *s = bs->opaque;
187
    int ret, i;
188

  
189
    lseek(s->fd, s->cow_sectors_offset + sector_num * 512, SEEK_SET);
190
    ret = write(s->fd, buf, nb_sectors * 512);
191
    if (ret != nb_sectors * 512)
192
        return -1;
193
    for (i = 0; i < nb_sectors; i++)
194
        cow_set_bit(s->cow_bitmap, sector_num + i);
195
    return 0;
196
}
197

  
198
static void cow_close(BlockDriverState *bs)
199
{
200
    BDRVCowState *s = bs->opaque;
201
    munmap((void *)s->cow_bitmap_addr, s->cow_bitmap_size);
202
    close(s->fd);
203
}
204

  
205
static int cow_create(const char *filename, int64_t image_sectors,
206
                      const char *image_filename, int flags)
207
{
208
    int fd, cow_fd;
209
    struct cow_header_v2 cow_header;
210
    struct stat st;
211

  
212
    if (flags)
213
        return -ENOTSUP;
214

  
215
    cow_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
216
              0644);
217
    if (cow_fd < 0)
218
        return -1;
219
    memset(&cow_header, 0, sizeof(cow_header));
220
    cow_header.magic = cpu_to_be32(COW_MAGIC);
221
    cow_header.version = cpu_to_be32(COW_VERSION);
222
    if (image_filename) {
223
        /* Note: if no file, we put a dummy mtime */
224
        cow_header.mtime = cpu_to_be32(0);
225

  
226
        fd = open(image_filename, O_RDONLY | O_BINARY);
227
        if (fd < 0) {
228
            close(cow_fd);
229
            goto mtime_fail;
230
        }
231
        if (fstat(fd, &st) != 0) {
232
            close(fd);
233
            goto mtime_fail;
234
        }
235
        close(fd);
236
        cow_header.mtime = cpu_to_be32(st.st_mtime);
237
    mtime_fail:
238
        pstrcpy(cow_header.backing_file, sizeof(cow_header.backing_file),
239
                image_filename);
240
    }
241
    cow_header.sectorsize = cpu_to_be32(512);
242
    cow_header.size = cpu_to_be64(image_sectors * 512);
243
    write(cow_fd, &cow_header, sizeof(cow_header));
244
    /* resize to include at least all the bitmap */
245
    ftruncate(cow_fd, sizeof(cow_header) + ((image_sectors + 7) >> 3));
246
    close(cow_fd);
247
    return 0;
248
}
249

  
250
static void cow_flush(BlockDriverState *bs)
251
{
252
    BDRVCowState *s = bs->opaque;
253
    fsync(s->fd);
254
}
255

  
256
static BlockDriver bdrv_cow = {
257
    .format_name	= "cow",
258
    .instance_size	= sizeof(BDRVCowState),
259
    .bdrv_probe		= cow_probe,
260
    .bdrv_open		= cow_open,
261
    .bdrv_read		= cow_read,
262
    .bdrv_write		= cow_write,
263
    .bdrv_close		= cow_close,
264
    .bdrv_create	= cow_create,
265
    .bdrv_flush		= cow_flush,
266
    .bdrv_is_allocated	= cow_is_allocated,
267
};
268

  
269
static void bdrv_cow_init(void)
270
{
271
    bdrv_register(&bdrv_cow);
272
}
273

  
274
block_init(bdrv_cow_init);
275
#endif
/dev/null
1
/*
2
 * QEMU Block driver for DMG 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 "bswap.h"
27
#include "module.h"
28
#include <zlib.h>
29

  
30
typedef struct BDRVDMGState {
31
    int fd;
32

  
33
    /* each chunk contains a certain number of sectors,
34
     * offsets[i] is the offset in the .dmg file,
35
     * lengths[i] is the length of the compressed chunk,
36
     * sectors[i] is the sector beginning at offsets[i],
37
     * sectorcounts[i] is the number of sectors in that chunk,
38
     * the sectors array is ordered
39
     * 0<=i<n_chunks */
40

  
41
    uint32_t n_chunks;
42
    uint32_t* types;
43
    uint64_t* offsets;
44
    uint64_t* lengths;
45
    uint64_t* sectors;
46
    uint64_t* sectorcounts;
47
    uint32_t current_chunk;
48
    uint8_t *compressed_chunk;
49
    uint8_t *uncompressed_chunk;
50
    z_stream zstream;
51
} BDRVDMGState;
52

  
53
static int dmg_probe(const uint8_t *buf, int buf_size, const char *filename)
54
{
55
    int len=strlen(filename);
56
    if(len>4 && !strcmp(filename+len-4,".dmg"))
57
	return 2;
58
    return 0;
59
}
60

  
61
static off_t read_off(int fd)
62
{
63
	uint64_t buffer;
64
	if(read(fd,&buffer,8)<8)
65
		return 0;
66
	return be64_to_cpu(buffer);
67
}
68

  
69
static off_t read_uint32(int fd)
70
{
71
	uint32_t buffer;
72
	if(read(fd,&buffer,4)<4)
73
		return 0;
74
	return be32_to_cpu(buffer);
75
}
76

  
77
static int dmg_open(BlockDriverState *bs, const char *filename, int flags)
78
{
79
    BDRVDMGState *s = bs->opaque;
80
    off_t info_begin,info_end,last_in_offset,last_out_offset;
81
    uint32_t count;
82
    uint32_t max_compressed_size=1,max_sectors_per_chunk=1,i;
83

  
84
    s->fd = open(filename, O_RDONLY | O_BINARY);
85
    if (s->fd < 0)
86
        return -errno;
87
    bs->read_only = 1;
88
    s->n_chunks = 0;
89
    s->offsets = s->lengths = s->sectors = s->sectorcounts = NULL;
90

  
91
    /* read offset of info blocks */
92
    if(lseek(s->fd,-0x1d8,SEEK_END)<0) {
93
dmg_close:
94
	close(s->fd);
95
	/* open raw instead */
96
	bs->drv=bdrv_find_format("raw");
97
	return bs->drv->bdrv_open(bs, filename, flags);
98
    }
99
    info_begin=read_off(s->fd);
100
    if(info_begin==0)
101
	goto dmg_close;
102
    if(lseek(s->fd,info_begin,SEEK_SET)<0)
103
	goto dmg_close;
104
    if(read_uint32(s->fd)!=0x100)
105
	goto dmg_close;
106
    if((count = read_uint32(s->fd))==0)
107
	goto dmg_close;
108
    info_end = info_begin+count;
109
    if(lseek(s->fd,0xf8,SEEK_CUR)<0)
110
	goto dmg_close;
111

  
112
    /* read offsets */
113
    last_in_offset = last_out_offset = 0;
114
    while(lseek(s->fd,0,SEEK_CUR)<info_end) {
115
        uint32_t type;
116

  
117
	count = read_uint32(s->fd);
118
	if(count==0)
119
	    goto dmg_close;
120
	type = read_uint32(s->fd);
121
	if(type!=0x6d697368 || count<244)
122
	    lseek(s->fd,count-4,SEEK_CUR);
123
	else {
124
	    int new_size, chunk_count;
125
	    if(lseek(s->fd,200,SEEK_CUR)<0)
126
	        goto dmg_close;
127
	    chunk_count = (count-204)/40;
128
	    new_size = sizeof(uint64_t) * (s->n_chunks + chunk_count);
129
	    s->types = qemu_realloc(s->types, new_size/2);
130
	    s->offsets = qemu_realloc(s->offsets, new_size);
131
	    s->lengths = qemu_realloc(s->lengths, new_size);
132
	    s->sectors = qemu_realloc(s->sectors, new_size);
133
	    s->sectorcounts = qemu_realloc(s->sectorcounts, new_size);
134

  
135
	    for(i=s->n_chunks;i<s->n_chunks+chunk_count;i++) {
136
		s->types[i] = read_uint32(s->fd);
137
		if(s->types[i]!=0x80000005 && s->types[i]!=1 && s->types[i]!=2) {
138
		    if(s->types[i]==0xffffffff) {
139
			last_in_offset = s->offsets[i-1]+s->lengths[i-1];
140
			last_out_offset = s->sectors[i-1]+s->sectorcounts[i-1];
141
		    }
142
		    chunk_count--;
143
		    i--;
144
		    if(lseek(s->fd,36,SEEK_CUR)<0)
145
			goto dmg_close;
146
		    continue;
147
		}
148
		read_uint32(s->fd);
149
		s->sectors[i] = last_out_offset+read_off(s->fd);
150
		s->sectorcounts[i] = read_off(s->fd);
151
		s->offsets[i] = last_in_offset+read_off(s->fd);
152
		s->lengths[i] = read_off(s->fd);
153
		if(s->lengths[i]>max_compressed_size)
154
		    max_compressed_size = s->lengths[i];
155
		if(s->sectorcounts[i]>max_sectors_per_chunk)
156
		    max_sectors_per_chunk = s->sectorcounts[i];
157
	    }
158
	    s->n_chunks+=chunk_count;
159
	}
160
    }
161

  
162
    /* initialize zlib engine */
163
    s->compressed_chunk = qemu_malloc(max_compressed_size+1);
164
    s->uncompressed_chunk = qemu_malloc(512*max_sectors_per_chunk);
165
    if(inflateInit(&s->zstream) != Z_OK)
166
	goto dmg_close;
167

  
168
    s->current_chunk = s->n_chunks;
169

  
170
    return 0;
171
}
172

  
173
static inline int is_sector_in_chunk(BDRVDMGState* s,
174
		uint32_t chunk_num,int sector_num)
175
{
176
    if(chunk_num>=s->n_chunks || s->sectors[chunk_num]>sector_num ||
177
	    s->sectors[chunk_num]+s->sectorcounts[chunk_num]<=sector_num)
178
	return 0;
179
    else
180
	return -1;
181
}
182

  
183
static inline uint32_t search_chunk(BDRVDMGState* s,int sector_num)
184
{
185
    /* binary search */
186
    uint32_t chunk1=0,chunk2=s->n_chunks,chunk3;
187
    while(chunk1!=chunk2) {
188
	chunk3 = (chunk1+chunk2)/2;
189
	if(s->sectors[chunk3]>sector_num)
190
	    chunk2 = chunk3;
191
	else if(s->sectors[chunk3]+s->sectorcounts[chunk3]>sector_num)
192
	    return chunk3;
193
	else
194
	    chunk1 = chunk3;
195
    }
196
    return s->n_chunks; /* error */
197
}
198

  
199
static inline int dmg_read_chunk(BDRVDMGState *s,int sector_num)
200
{
201
    if(!is_sector_in_chunk(s,s->current_chunk,sector_num)) {
202
	int ret;
203
	uint32_t chunk = search_chunk(s,sector_num);
204

  
205
	if(chunk>=s->n_chunks)
206
	    return -1;
207

  
208
	s->current_chunk = s->n_chunks;
209
	switch(s->types[chunk]) {
210
	case 0x80000005: { /* zlib compressed */
211
	    int i;
212

  
213
	    ret = lseek(s->fd, s->offsets[chunk], SEEK_SET);
214
	    if(ret<0)
215
		return -1;
216

  
217
	    /* we need to buffer, because only the chunk as whole can be
218
	     * inflated. */
219
	    i=0;
220
	    do {
221
		ret = read(s->fd, s->compressed_chunk+i, s->lengths[chunk]-i);
222
		if(ret<0 && errno==EINTR)
223
		    ret=0;
224
		i+=ret;
225
	    } while(ret>=0 && ret+i<s->lengths[chunk]);
226

  
227
	    if (ret != s->lengths[chunk])
228
		return -1;
229

  
230
	    s->zstream.next_in = s->compressed_chunk;
231
	    s->zstream.avail_in = s->lengths[chunk];
232
	    s->zstream.next_out = s->uncompressed_chunk;
233
	    s->zstream.avail_out = 512*s->sectorcounts[chunk];
234
	    ret = inflateReset(&s->zstream);
235
	    if(ret != Z_OK)
236
		return -1;
237
	    ret = inflate(&s->zstream, Z_FINISH);
238
	    if(ret != Z_STREAM_END || s->zstream.total_out != 512*s->sectorcounts[chunk])
239
		return -1;
240
	    break; }
241
	case 1: /* copy */
242
	    ret = read(s->fd, s->uncompressed_chunk, s->lengths[chunk]);
243
	    if (ret != s->lengths[chunk])
244
		return -1;
245
	    break;
246
	case 2: /* zero */
247
	    memset(s->uncompressed_chunk, 0, 512*s->sectorcounts[chunk]);
248
	    break;
249
	}
250
	s->current_chunk = chunk;
251
    }
252
    return 0;
253
}
254

  
255
static int dmg_read(BlockDriverState *bs, int64_t sector_num,
256
                    uint8_t *buf, int nb_sectors)
257
{
258
    BDRVDMGState *s = bs->opaque;
259
    int i;
260

  
261
    for(i=0;i<nb_sectors;i++) {
262
	uint32_t sector_offset_in_chunk;
263
	if(dmg_read_chunk(s, sector_num+i) != 0)
264
	    return -1;
265
	sector_offset_in_chunk = sector_num+i-s->sectors[s->current_chunk];
266
	memcpy(buf+i*512,s->uncompressed_chunk+sector_offset_in_chunk*512,512);
267
    }
268
    return 0;
269
}
270

  
271
static void dmg_close(BlockDriverState *bs)
272
{
273
    BDRVDMGState *s = bs->opaque;
274
    close(s->fd);
275
    if(s->n_chunks>0) {
276
	free(s->types);
277
	free(s->offsets);
278
	free(s->lengths);
279
	free(s->sectors);
280
	free(s->sectorcounts);
281
    }
282
    free(s->compressed_chunk);
283
    free(s->uncompressed_chunk);
284
    inflateEnd(&s->zstream);
285
}
286

  
287
static BlockDriver bdrv_dmg = {
288
    .format_name	= "dmg",
289
    .instance_size	= sizeof(BDRVDMGState),
290
    .bdrv_probe		= dmg_probe,
291
    .bdrv_open		= dmg_open,
292
    .bdrv_read		= dmg_read,
293
    .bdrv_close		= dmg_close,
294
};
295

  
296
static void bdrv_dmg_init(void)
297
{
298
    bdrv_register(&bdrv_dmg);
299
}
300

  
301
block_init(bdrv_dmg_init);
/dev/null
1
/*
2
 * QEMU Block driver for  NBD
3
 *
4
 * Copyright (C) 2008 Bull S.A.S.
5
 *     Author: Laurent Vivier <Laurent.Vivier@bull.net>
6
 *
7
 * Some parts:
8
 *    Copyright (C) 2007 Anthony Liguori <anthony@codemonkey.ws>
9
 *
10
 * Permission is hereby granted, free of charge, to any person obtaining a copy
11
 * of this software and associated documentation files (the "Software"), to deal
12
 * in the Software without restriction, including without limitation the rights
13
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
 * copies of the Software, and to permit persons to whom the Software is
15
 * furnished to do so, subject to the following conditions:
16
 *
17
 * The above copyright notice and this permission notice shall be included in
18
 * all copies or substantial portions of the Software.
19
 *
20
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26
 * THE SOFTWARE.
27
 */
28

  
29
#include "qemu-common.h"
30
#include "nbd.h"
31
#include "module.h"
32

  
33
#include <sys/types.h>
34
#include <unistd.h>
35

  
36
typedef struct BDRVNBDState {
37
    int sock;
38
    off_t size;
39
    size_t blocksize;
40
} BDRVNBDState;
41

  
42
static int nbd_open(BlockDriverState *bs, const char* filename, int flags)
43
{
44
    BDRVNBDState *s = bs->opaque;
45
    const char *host;
46
    const char *unixpath;
47
    int sock;
48
    off_t size;
49
    size_t blocksize;
50
    int ret;
51

  
52
    if ((flags & BDRV_O_CREAT))
53
        return -EINVAL;
54

  
55
    if (!strstart(filename, "nbd:", &host))
56
        return -EINVAL;
57

  
58
    if (strstart(host, "unix:", &unixpath)) {
59

  
60
        if (unixpath[0] != '/')
61
            return -EINVAL;
62

  
63
        sock = unix_socket_outgoing(unixpath);
64

  
65
    } else {
66
        uint16_t port;
67
        char *p, *r;
68
        char hostname[128];
69

  
70
        pstrcpy(hostname, 128, host);
71

  
72
        p = strchr(hostname, ':');
73
        if (p == NULL)
74
            return -EINVAL;
75

  
76
        *p = '\0';
77
        p++;
78

  
79
        port = strtol(p, &r, 0);
80
        if (r == p)
81
            return -EINVAL;
82
        sock = tcp_socket_outgoing(hostname, port);
83
    }
84

  
85
    if (sock == -1)
86
        return -errno;
87

  
88
    ret = nbd_receive_negotiate(sock, &size, &blocksize);
89
    if (ret == -1)
90
        return -errno;
91

  
92
    s->sock = sock;
93
    s->size = size;
94
    s->blocksize = blocksize;
95

  
96
    return 0;
97
}
98

  
99
static int nbd_read(BlockDriverState *bs, int64_t sector_num,
100
                    uint8_t *buf, int nb_sectors)
101
{
102
    BDRVNBDState *s = bs->opaque;
103
    struct nbd_request request;
104
    struct nbd_reply reply;
105

  
106
    request.type = NBD_CMD_READ;
107
    request.handle = (uint64_t)(intptr_t)bs;
108
    request.from = sector_num * 512;;
109
    request.len = nb_sectors * 512;
110

  
111
    if (nbd_send_request(s->sock, &request) == -1)
112
        return -errno;
113

  
114
    if (nbd_receive_reply(s->sock, &reply) == -1)
115
        return -errno;
116

  
117
    if (reply.error !=0)
118
        return -reply.error;
119

  
120
    if (reply.handle != request.handle)
121
        return -EIO;
122

  
123
    if (nbd_wr_sync(s->sock, buf, request.len, 1) != request.len)
124
        return -EIO;
125

  
126
    return 0;
127
}
128

  
129
static int nbd_write(BlockDriverState *bs, int64_t sector_num,
130
                     const uint8_t *buf, int nb_sectors)
131
{
132
    BDRVNBDState *s = bs->opaque;
133
    struct nbd_request request;
134
    struct nbd_reply reply;
135

  
136
    request.type = NBD_CMD_WRITE;
137
    request.handle = (uint64_t)(intptr_t)bs;
138
    request.from = sector_num * 512;;
139
    request.len = nb_sectors * 512;
140

  
141
    if (nbd_send_request(s->sock, &request) == -1)
142
        return -errno;
143

  
144
    if (nbd_wr_sync(s->sock, (uint8_t*)buf, request.len, 0) != request.len)
145
        return -EIO;
146

  
147
    if (nbd_receive_reply(s->sock, &reply) == -1)
148
        return -errno;
149

  
150
    if (reply.error !=0)
151
        return -reply.error;
152

  
153
    if (reply.handle != request.handle)
154
        return -EIO;
155

  
156
    return 0;
157
}
158

  
159
static void nbd_close(BlockDriverState *bs)
160
{
161
    BDRVNBDState *s = bs->opaque;
162
    struct nbd_request request;
163

  
164
    request.type = NBD_CMD_DISC;
165
    request.handle = (uint64_t)(intptr_t)bs;
166
    request.from = 0;
167
    request.len = 0;
168
    nbd_send_request(s->sock, &request);
169

  
170
    close(s->sock);
171
}
172

  
173
static int64_t nbd_getlength(BlockDriverState *bs)
174
{
175
    BDRVNBDState *s = bs->opaque;
176

  
177
    return s->size;
178
}
179

  
180
static BlockDriver bdrv_nbd = {
181
    .format_name	= "nbd",
182
    .instance_size	= sizeof(BDRVNBDState),
183
    .bdrv_open		= nbd_open,
184
    .bdrv_read		= nbd_read,
185
    .bdrv_write		= nbd_write,
186
    .bdrv_close		= nbd_close,
187
    .bdrv_getlength	= nbd_getlength,
188
    .protocol_name	= "nbd",
189
};
190

  
191
static void bdrv_nbd_init(void)
192
{
193
    bdrv_register(&bdrv_nbd);
194
}
195

  
196
block_init(bdrv_nbd_init);
/dev/null
1
/*
2
 * Block driver for Parallels disk image format
3
 *
4
 * Copyright (c) 2007 Alex Beregszaszi
5
 *
6
 * This code is based on comparing different disk images created by Parallels.
7
 *
8
 * Permission is hereby granted, free of charge, to any person obtaining a copy
9
 * of this software and associated documentation files (the "Software"), to deal
10
 * in the Software without restriction, including without limitation the rights
11
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
 * copies of the Software, and to permit persons to whom the Software is
13
 * furnished to do so, subject to the following conditions:
14
 *
15
 * The above copyright notice and this permission notice shall be included in
16
 * all copies or substantial portions of the Software.
17
 *
18
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
 * THE SOFTWARE.
25
 */
26
#include "qemu-common.h"
27
#include "block_int.h"
28
#include "module.h"
29

  
30
/**************************************************************/
31

  
32
#define HEADER_MAGIC "WithoutFreeSpace"
33
#define HEADER_VERSION 2
34
#define HEADER_SIZE 64
35

  
36
// always little-endian
37
struct parallels_header {
38
    char magic[16]; // "WithoutFreeSpace"
39
    uint32_t version;
40
    uint32_t heads;
41
    uint32_t cylinders;
42
    uint32_t tracks;
43
    uint32_t catalog_entries;
44
    uint32_t nb_sectors;
45
    char padding[24];
46
} __attribute__((packed));
47

  
48
typedef struct BDRVParallelsState {
49
    int fd;
50

  
51
    uint32_t *catalog_bitmap;
52
    int catalog_size;
53

  
54
    int tracks;
55
} BDRVParallelsState;
56

  
57
static int parallels_probe(const uint8_t *buf, int buf_size, const char *filename)
58
{
59
    const struct parallels_header *ph = (const void *)buf;
60

  
61
    if (buf_size < HEADER_SIZE)
62
	return 0;
63

  
64
    if (!memcmp(ph->magic, HEADER_MAGIC, 16) &&
65
	(le32_to_cpu(ph->version) == HEADER_VERSION))
66
	return 100;
67

  
68
    return 0;
69
}
70

  
71
static int parallels_open(BlockDriverState *bs, const char *filename, int flags)
72
{
73
    BDRVParallelsState *s = bs->opaque;
74
    int fd, i;
75
    struct parallels_header ph;
76

  
77
    fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
78
    if (fd < 0) {
79
        fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
80
        if (fd < 0)
81
            return -1;
82
    }
83

  
84
    bs->read_only = 1; // no write support yet
85

  
86
    s->fd = fd;
87

  
88
    if (read(fd, &ph, sizeof(ph)) != sizeof(ph))
89
        goto fail;
90

  
91
    if (memcmp(ph.magic, HEADER_MAGIC, 16) ||
92
	(le32_to_cpu(ph.version) != HEADER_VERSION)) {
93
        goto fail;
94
    }
95

  
96
    bs->total_sectors = le32_to_cpu(ph.nb_sectors);
97

  
98
    if (lseek(s->fd, 64, SEEK_SET) != 64)
99
	goto fail;
100

  
101
    s->tracks = le32_to_cpu(ph.tracks);
102

  
103
    s->catalog_size = le32_to_cpu(ph.catalog_entries);
104
    s->catalog_bitmap = qemu_malloc(s->catalog_size * 4);
105
    if (read(s->fd, s->catalog_bitmap, s->catalog_size * 4) !=
106
	s->catalog_size * 4)
107
	goto fail;
108
    for (i = 0; i < s->catalog_size; i++)
109
	le32_to_cpus(&s->catalog_bitmap[i]);
110

  
111
    return 0;
112
fail:
113
    if (s->catalog_bitmap)
114
	qemu_free(s->catalog_bitmap);
115
    close(fd);
116
    return -1;
117
}
118

  
119
static inline int seek_to_sector(BlockDriverState *bs, int64_t sector_num)
120
{
121
    BDRVParallelsState *s = bs->opaque;
122
    uint32_t index, offset, position;
123

  
124
    index = sector_num / s->tracks;
125
    offset = sector_num % s->tracks;
126

  
127
    // not allocated
128
    if ((index > s->catalog_size) || (s->catalog_bitmap[index] == 0))
129
	return -1;
130

  
131
    position = (s->catalog_bitmap[index] + offset) * 512;
132

  
133
//    fprintf(stderr, "sector: %llx index=%x offset=%x pointer=%x position=%x\n",
134
//	sector_num, index, offset, s->catalog_bitmap[index], position);
135

  
136
    if (lseek(s->fd, position, SEEK_SET) != position)
137
	return -1;
138

  
139
    return 0;
140
}
141

  
142
static int parallels_read(BlockDriverState *bs, int64_t sector_num,
143
                    uint8_t *buf, int nb_sectors)
144
{
145
    BDRVParallelsState *s = bs->opaque;
146

  
147
    while (nb_sectors > 0) {
148
	if (!seek_to_sector(bs, sector_num)) {
149
	    if (read(s->fd, buf, 512) != 512)
150
		return -1;
151
	} else
152
            memset(buf, 0, 512);
153
        nb_sectors--;
154
        sector_num++;
155
        buf += 512;
156
    }
157
    return 0;
158
}
159

  
160
static void parallels_close(BlockDriverState *bs)
161
{
162
    BDRVParallelsState *s = bs->opaque;
163
    qemu_free(s->catalog_bitmap);
164
    close(s->fd);
165
}
166

  
167
static BlockDriver bdrv_parallels = {
168
    .format_name	= "parallels",
169
    .instance_size	= sizeof(BDRVParallelsState),
170
    .bdrv_probe		= parallels_probe,
171
    .bdrv_open		= parallels_open,
172
    .bdrv_read		= parallels_read,
173
    .bdrv_close		= parallels_close,
174
};
175

  
176
static void bdrv_parallels_init(void)
177
{
178
    bdrv_register(&bdrv_parallels);
179
}
180

  
181
block_init(bdrv_parallels_init);
/dev/null
1
/*
2
 * Block driver for the QCOW format
3
 *
4
 * Copyright (c) 2004-2006 Fabrice Bellard
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"
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff