Statistics
| Branch: | Revision:

root / block.c @ ecd78a0a

History | View | Annotate | Download (19.5 kB)

1
/*
2
 * QEMU System Emulator block driver
3
 * 
4
 * Copyright (c) 2003 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 "vl.h"
25
#include "block_int.h"
26

    
27
#ifdef _BSD
28
#include <sys/types.h>
29
#include <sys/stat.h>
30
#include <sys/ioctl.h>
31
#include <sys/queue.h>
32
#include <sys/disk.h>
33
#endif
34

    
35
#ifdef CONFIG_COCOA
36
#include <paths.h>
37
#include <sys/param.h>
38
#include <IOKit/IOKitLib.h>
39
#include <IOKit/IOBSD.h>
40
#include <IOKit/storage/IOMediaBSDClient.h>
41
#include <IOKit/storage/IOMedia.h>
42
#include <IOKit/storage/IOCDMedia.h>
43
//#include <IOKit/storage/IOCDTypes.h>
44
#include <CoreFoundation/CoreFoundation.h>
45
#endif
46

    
47
static BlockDriverState *bdrv_first;
48
static BlockDriver *first_drv;
49

    
50
#ifdef CONFIG_COCOA
51
static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator );
52
static kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize );
53

    
54
kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator )
55
{
56
    kern_return_t       kernResult; 
57
    mach_port_t     masterPort;
58
    CFMutableDictionaryRef  classesToMatch;
59

    
60
    kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort );
61
    if ( KERN_SUCCESS != kernResult ) {
62
        printf( "IOMasterPort returned %d\n", kernResult );
63
    }
64
    
65
    classesToMatch = IOServiceMatching( kIOCDMediaClass ); 
66
    if ( classesToMatch == NULL ) {
67
        printf( "IOServiceMatching returned a NULL dictionary.\n" );
68
    } else {
69
    CFDictionarySetValue( classesToMatch, CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue );
70
    }
71
    kernResult = IOServiceGetMatchingServices( masterPort, classesToMatch, mediaIterator );
72
    if ( KERN_SUCCESS != kernResult )
73
    {
74
        printf( "IOServiceGetMatchingServices returned %d\n", kernResult );
75
    }
76
    
77
    return kernResult;
78
}
79

    
80
kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize )
81
{
82
    io_object_t     nextMedia;
83
    kern_return_t   kernResult = KERN_FAILURE;
84
    *bsdPath = '\0';
85
    nextMedia = IOIteratorNext( mediaIterator );
86
    if ( nextMedia )
87
    {
88
        CFTypeRef   bsdPathAsCFString;
89
    bsdPathAsCFString = IORegistryEntryCreateCFProperty( nextMedia, CFSTR( kIOBSDNameKey ), kCFAllocatorDefault, 0 );
90
        if ( bsdPathAsCFString ) {
91
            size_t devPathLength;
92
            strcpy( bsdPath, _PATH_DEV );
93
            strcat( bsdPath, "r" );
94
            devPathLength = strlen( bsdPath );
95
            if ( CFStringGetCString( bsdPathAsCFString, bsdPath + devPathLength, maxPathSize - devPathLength, kCFStringEncodingASCII ) ) {
96
                kernResult = KERN_SUCCESS;
97
            }
98
            CFRelease( bsdPathAsCFString );
99
        }
100
        IOObjectRelease( nextMedia );
101
    }
102
    
103
    return kernResult;
104
}
105

    
106
#endif
107

    
108
void bdrv_register(BlockDriver *bdrv)
109
{
110
    bdrv->next = first_drv;
111
    first_drv = bdrv;
112
}
113

    
114
/* create a new block device (by default it is empty) */
115
BlockDriverState *bdrv_new(const char *device_name)
116
{
117
    BlockDriverState **pbs, *bs;
118

    
119
    bs = qemu_mallocz(sizeof(BlockDriverState));
120
    if(!bs)
121
        return NULL;
122
    pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
123
    if (device_name[0] != '\0') {
124
        /* insert at the end */
125
        pbs = &bdrv_first;
126
        while (*pbs != NULL)
127
            pbs = &(*pbs)->next;
128
        *pbs = bs;
129
    }
130
    return bs;
131
}
132

    
133
BlockDriver *bdrv_find_format(const char *format_name)
134
{
135
    BlockDriver *drv1;
136
    for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
137
        if (!strcmp(drv1->format_name, format_name))
138
            return drv1;
139
    }
140
    return NULL;
141
}
142

    
143
int bdrv_create(BlockDriver *drv, 
144
                const char *filename, int64_t size_in_sectors,
145
                const char *backing_file, int flags)
146
{
147
    if (!drv->bdrv_create)
148
        return -ENOTSUP;
149
    return drv->bdrv_create(filename, size_in_sectors, backing_file, flags);
150
}
151

    
152
#ifdef _WIN32
153
void get_tmp_filename(char *filename, int size)
154
{
155
    char* p = strrchr(filename, '/');
156

    
157
    if (p == NULL)
158
        return;
159

    
160
    /* XXX: find a better function */
161
    tmpnam(p);
162
    *p = '/';
163
}
164
#else
165
void get_tmp_filename(char *filename, int size)
166
{
167
    int fd;
168
    /* XXX: race condition possible */
169
    pstrcpy(filename, size, "/tmp/vl.XXXXXX");
170
    fd = mkstemp(filename);
171
    close(fd);
172
}
173
#endif
174

    
175
/* XXX: force raw format if block or character device ? It would
176
   simplify the BSD case */
177
static BlockDriver *find_image_format(const char *filename)
178
{
179
    int fd, ret, score, score_max;
180
    BlockDriver *drv1, *drv;
181
    uint8_t *buf;
182
    size_t bufsize = 1024;
183

    
184
    fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
185
    if (fd < 0) {
186
        buf = NULL;
187
        ret = 0;
188
    } else {
189
#ifdef DIOCGSECTORSIZE
190
        {
191
            unsigned int sectorsize = 512;
192
            if (!ioctl(fd, DIOCGSECTORSIZE, &sectorsize) &&
193
                sectorsize > bufsize)
194
                bufsize = sectorsize;
195
        }
196
#endif
197
#ifdef CONFIG_COCOA
198
        u_int32_t   blockSize = 512;
199
        if ( !ioctl( fd, DKIOCGETBLOCKSIZE, &blockSize ) && blockSize > bufsize) {
200
            bufsize = blockSize;
201
        }
202
#endif
203
        buf = qemu_malloc(bufsize);
204
        if (!buf)
205
            return NULL;
206
        ret = read(fd, buf, bufsize);
207
        if (ret < 0) {
208
            close(fd);
209
            qemu_free(buf);
210
            return NULL;
211
        }
212
        close(fd);
213
    }
214
    
215
    drv = NULL;
216
    score_max = 0;
217
    for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
218
        score = drv1->bdrv_probe(buf, ret, filename);
219
        if (score > score_max) {
220
            score_max = score;
221
            drv = drv1;
222
        }
223
    }
224
    qemu_free(buf);
225
    return drv;
226
}
227

    
228
int bdrv_open(BlockDriverState *bs, const char *filename, int snapshot)
229
{
230
#ifdef CONFIG_COCOA
231
    if ( strncmp( filename, "/dev/cdrom", 10 ) == 0 ) {
232
        kern_return_t kernResult;
233
        io_iterator_t mediaIterator;
234
        char bsdPath[ MAXPATHLEN ];
235
        int fd;
236
 
237
        kernResult = FindEjectableCDMedia( &mediaIterator );
238
        kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof( bsdPath ) );
239
    
240
        if ( bsdPath[ 0 ] != '\0' ) {
241
            strcat(bsdPath,"s0");
242
            /* some CDs don't have a partition 0 */
243
            fd = open(bsdPath, O_RDONLY | O_BINARY | O_LARGEFILE);
244
            if (fd < 0) {
245
                bsdPath[strlen(bsdPath)-1] = '1';
246
            } else {
247
                close(fd);
248
            }
249
            filename = bsdPath;
250
        }
251
        
252
        if ( mediaIterator )
253
            IOObjectRelease( mediaIterator );
254
    }
255
#endif
256
    return bdrv_open2(bs, filename, snapshot, NULL);
257
}
258

    
259
int bdrv_open2(BlockDriverState *bs, const char *filename, int snapshot,
260
               BlockDriver *drv)
261
{
262
    int ret;
263
    char tmp_filename[1024];
264
    
265
    bs->read_only = 0;
266
    bs->is_temporary = 0;
267
    bs->encrypted = 0;
268

    
269
    if (snapshot) {
270
        BlockDriverState *bs1;
271
        int64_t total_size;
272
        
273
        /* if snapshot, we create a temporary backing file and open it
274
           instead of opening 'filename' directly */
275

    
276
        /* if there is a backing file, use it */
277
        bs1 = bdrv_new("");
278
        if (!bs1) {
279
            return -1;
280
        }
281
        if (bdrv_open(bs1, filename, 0) < 0) {
282
            bdrv_delete(bs1);
283
            return -1;
284
        }
285
        total_size = bs1->total_sectors;
286
        bdrv_delete(bs1);
287
        
288
        get_tmp_filename(tmp_filename, sizeof(tmp_filename));
289
        /* XXX: use cow for linux as it is more efficient ? */
290
        if (bdrv_create(&bdrv_qcow, tmp_filename, 
291
                        total_size, filename, 0) < 0) {
292
            return -1;
293
        }
294
        filename = tmp_filename;
295
        bs->is_temporary = 1;
296
    }
297

    
298
    pstrcpy(bs->filename, sizeof(bs->filename), filename);
299
    if (!drv) {
300
        drv = find_image_format(filename);
301
        if (!drv)
302
            return -1;
303
    }
304
    bs->drv = drv;
305
    bs->opaque = qemu_mallocz(drv->instance_size);
306
    if (bs->opaque == NULL && drv->instance_size > 0)
307
        return -1;
308
    
309
    ret = drv->bdrv_open(bs, filename);
310
    if (ret < 0) {
311
        qemu_free(bs->opaque);
312
        return -1;
313
    }
314
#ifndef _WIN32
315
    if (bs->is_temporary) {
316
        unlink(filename);
317
    }
318
#endif
319
    if (bs->backing_file[0] != '\0' && drv->bdrv_is_allocated) {
320
        /* if there is a backing file, use it */
321
        bs->backing_hd = bdrv_new("");
322
        if (!bs->backing_hd) {
323
        fail:
324
            bdrv_close(bs);
325
            return -1;
326
        }
327
        if (bdrv_open(bs->backing_hd, bs->backing_file, 0) < 0)
328
            goto fail;
329
    }
330

    
331
    bs->inserted = 1;
332

    
333
    /* call the change callback */
334
    if (bs->change_cb)
335
        bs->change_cb(bs->change_opaque);
336

    
337
    return 0;
338
}
339

    
340
void bdrv_close(BlockDriverState *bs)
341
{
342
    if (bs->inserted) {
343
        if (bs->backing_hd)
344
            bdrv_delete(bs->backing_hd);
345
        bs->drv->bdrv_close(bs);
346
        qemu_free(bs->opaque);
347
#ifdef _WIN32
348
        if (bs->is_temporary) {
349
            unlink(bs->filename);
350
        }
351
#endif
352
        bs->opaque = NULL;
353
        bs->drv = NULL;
354
        bs->inserted = 0;
355

    
356
        /* call the change callback */
357
        if (bs->change_cb)
358
            bs->change_cb(bs->change_opaque);
359
    }
360
}
361

    
362
void bdrv_delete(BlockDriverState *bs)
363
{
364
    /* XXX: remove the driver list */
365
    bdrv_close(bs);
366
    qemu_free(bs);
367
}
368

    
369
/* commit COW file into the raw image */
370
int bdrv_commit(BlockDriverState *bs)
371
{
372
    int64_t i;
373
    int n, j;
374
    unsigned char sector[512];
375

    
376
    if (!bs->inserted)
377
        return -ENOENT;
378

    
379
    if (bs->read_only) {
380
        return -EACCES;
381
    }
382

    
383
    if (!bs->backing_hd) {
384
        return -ENOTSUP;
385
    }
386

    
387
    for (i = 0; i < bs->total_sectors;) {
388
        if (bs->drv->bdrv_is_allocated(bs, i, 65536, &n)) {
389
            for(j = 0; j < n; j++) {
390
                if (bdrv_read(bs, i, sector, 1) != 0) {
391
                    return -EIO;
392
                }
393

    
394
                if (bdrv_write(bs->backing_hd, i, sector, 1) != 0) {
395
                    return -EIO;
396
                }
397
                i++;
398
            }
399
        } else {
400
            i += n;
401
        }
402
    }
403

    
404
    if (bs->drv->bdrv_make_empty)
405
        return bs->drv->bdrv_make_empty(bs);
406

    
407
    return 0;
408
}
409

    
410
/* return -1 if error */
411
int bdrv_read(BlockDriverState *bs, int64_t sector_num, 
412
              uint8_t *buf, int nb_sectors)
413
{
414
    int ret, n;
415
    BlockDriver *drv = bs->drv;
416

    
417
    if (!bs->inserted)
418
        return -1;
419

    
420
    while (nb_sectors > 0) {
421
        if (sector_num == 0 && bs->boot_sector_enabled) {
422
            memcpy(buf, bs->boot_sector_data, 512);
423
            n = 1;
424
        } else if (bs->backing_hd) {
425
            if (drv->bdrv_is_allocated(bs, sector_num, nb_sectors, &n)) {
426
                ret = drv->bdrv_read(bs, sector_num, buf, n);
427
                if (ret < 0)
428
                    return -1;
429
            } else {
430
                /* read from the base image */
431
                ret = bdrv_read(bs->backing_hd, sector_num, buf, n);
432
                if (ret < 0)
433
                    return -1;
434
            }
435
        } else {
436
            ret = drv->bdrv_read(bs, sector_num, buf, nb_sectors);
437
            if (ret < 0)
438
                return -1;
439
            /* no need to loop */
440
            break;
441
        }
442
        nb_sectors -= n;
443
        sector_num += n;
444
        buf += n * 512;
445
    }
446
    return 0;
447
}
448

    
449
/* return -1 if error */
450
int bdrv_write(BlockDriverState *bs, int64_t sector_num, 
451
               const uint8_t *buf, int nb_sectors)
452
{
453
    if (!bs->inserted)
454
        return -1;
455
    if (bs->read_only)
456
        return -1;
457
    if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
458
        memcpy(bs->boot_sector_data, buf, 512);   
459
    }
460
    return bs->drv->bdrv_write(bs, sector_num, buf, nb_sectors);
461
}
462

    
463
void bdrv_get_geometry(BlockDriverState *bs, int64_t *nb_sectors_ptr)
464
{
465
    *nb_sectors_ptr = bs->total_sectors;
466
}
467

    
468
/* force a given boot sector. */
469
void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size)
470
{
471
    bs->boot_sector_enabled = 1;
472
    if (size > 512)
473
        size = 512;
474
    memcpy(bs->boot_sector_data, data, size);
475
    memset(bs->boot_sector_data + size, 0, 512 - size);
476
}
477

    
478
void bdrv_set_geometry_hint(BlockDriverState *bs, 
479
                            int cyls, int heads, int secs)
480
{
481
    bs->cyls = cyls;
482
    bs->heads = heads;
483
    bs->secs = secs;
484
}
485

    
486
void bdrv_set_type_hint(BlockDriverState *bs, int type)
487
{
488
    bs->type = type;
489
    bs->removable = ((type == BDRV_TYPE_CDROM ||
490
                      type == BDRV_TYPE_FLOPPY));
491
}
492

    
493
void bdrv_set_translation_hint(BlockDriverState *bs, int translation)
494
{
495
    bs->translation = translation;
496
}
497

    
498
void bdrv_get_geometry_hint(BlockDriverState *bs, 
499
                            int *pcyls, int *pheads, int *psecs)
500
{
501
    *pcyls = bs->cyls;
502
    *pheads = bs->heads;
503
    *psecs = bs->secs;
504
}
505

    
506
int bdrv_get_type_hint(BlockDriverState *bs)
507
{
508
    return bs->type;
509
}
510

    
511
int bdrv_get_translation_hint(BlockDriverState *bs)
512
{
513
    return bs->translation;
514
}
515

    
516
int bdrv_is_removable(BlockDriverState *bs)
517
{
518
    return bs->removable;
519
}
520

    
521
int bdrv_is_read_only(BlockDriverState *bs)
522
{
523
    return bs->read_only;
524
}
525

    
526
int bdrv_is_inserted(BlockDriverState *bs)
527
{
528
    return bs->inserted;
529
}
530

    
531
int bdrv_is_locked(BlockDriverState *bs)
532
{
533
    return bs->locked;
534
}
535

    
536
void bdrv_set_locked(BlockDriverState *bs, int locked)
537
{
538
    bs->locked = locked;
539
}
540

    
541
void bdrv_set_change_cb(BlockDriverState *bs, 
542
                        void (*change_cb)(void *opaque), void *opaque)
543
{
544
    bs->change_cb = change_cb;
545
    bs->change_opaque = opaque;
546
}
547

    
548
int bdrv_is_encrypted(BlockDriverState *bs)
549
{
550
    if (bs->backing_hd && bs->backing_hd->encrypted)
551
        return 1;
552
    return bs->encrypted;
553
}
554

    
555
int bdrv_set_key(BlockDriverState *bs, const char *key)
556
{
557
    int ret;
558
    if (bs->backing_hd && bs->backing_hd->encrypted) {
559
        ret = bdrv_set_key(bs->backing_hd, key);
560
        if (ret < 0)
561
            return ret;
562
        if (!bs->encrypted)
563
            return 0;
564
    }
565
    if (!bs->encrypted || !bs->drv || !bs->drv->bdrv_set_key)
566
        return -1;
567
    return bs->drv->bdrv_set_key(bs, key);
568
}
569

    
570
void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size)
571
{
572
    if (!bs->inserted || !bs->drv) {
573
        buf[0] = '\0';
574
    } else {
575
        pstrcpy(buf, buf_size, bs->drv->format_name);
576
    }
577
}
578

    
579
void bdrv_iterate_format(void (*it)(void *opaque, const char *name), 
580
                         void *opaque)
581
{
582
    BlockDriver *drv;
583

    
584
    for (drv = first_drv; drv != NULL; drv = drv->next) {
585
        it(opaque, drv->format_name);
586
    }
587
}
588

    
589
BlockDriverState *bdrv_find(const char *name)
590
{
591
    BlockDriverState *bs;
592

    
593
    for (bs = bdrv_first; bs != NULL; bs = bs->next) {
594
        if (!strcmp(name, bs->device_name))
595
            return bs;
596
    }
597
    return NULL;
598
}
599

    
600
void bdrv_iterate(void (*it)(void *opaque, const char *name), void *opaque)
601
{
602
    BlockDriverState *bs;
603

    
604
    for (bs = bdrv_first; bs != NULL; bs = bs->next) {
605
        it(opaque, bs->device_name);
606
    }
607
}
608

    
609
const char *bdrv_get_device_name(BlockDriverState *bs)
610
{
611
    return bs->device_name;
612
}
613

    
614
void bdrv_info(void)
615
{
616
    BlockDriverState *bs;
617

    
618
    for (bs = bdrv_first; bs != NULL; bs = bs->next) {
619
        term_printf("%s:", bs->device_name);
620
        term_printf(" type=");
621
        switch(bs->type) {
622
        case BDRV_TYPE_HD:
623
            term_printf("hd");
624
            break;
625
        case BDRV_TYPE_CDROM:
626
            term_printf("cdrom");
627
            break;
628
        case BDRV_TYPE_FLOPPY:
629
            term_printf("floppy");
630
            break;
631
        }
632
        term_printf(" removable=%d", bs->removable);
633
        if (bs->removable) {
634
            term_printf(" locked=%d", bs->locked);
635
        }
636
        if (bs->inserted) {
637
            term_printf(" file=%s", bs->filename);
638
            if (bs->backing_file[0] != '\0')
639
                term_printf(" backing_file=%s", bs->backing_file);
640
            term_printf(" ro=%d", bs->read_only);
641
            term_printf(" drv=%s", bs->drv->format_name);
642
            if (bs->encrypted)
643
                term_printf(" encrypted");
644
        } else {
645
            term_printf(" [not inserted]");
646
        }
647
        term_printf("\n");
648
    }
649
}
650

    
651

    
652
/**************************************************************/
653
/* RAW block driver */
654

    
655
typedef struct BDRVRawState {
656
    int fd;
657
} BDRVRawState;
658

    
659
static int raw_probe(const uint8_t *buf, int buf_size, const char *filename)
660
{
661
    return 1; /* maybe */
662
}
663

    
664
static int raw_open(BlockDriverState *bs, const char *filename)
665
{
666
    BDRVRawState *s = bs->opaque;
667
    int fd;
668
    int64_t size;
669
#ifdef _BSD
670
    struct stat sb;
671
#endif
672

    
673
    fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
674
    if (fd < 0) {
675
        fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
676
        if (fd < 0)
677
            return -1;
678
        bs->read_only = 1;
679
    }
680
#ifdef _BSD
681
    if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) {
682
#ifdef DIOCGMEDIASIZE
683
        if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size))
684
#endif
685
#ifdef CONFIG_COCOA
686
        size = LONG_LONG_MAX;
687
#else
688
        size = lseek(fd, 0LL, SEEK_END);
689
#endif
690
    } else
691
#endif
692
    {
693
        size = lseek(fd, 0, SEEK_END);
694
    }
695
#ifdef _WIN32
696
    /* On Windows hosts it can happen that we're unable to get file size
697
       for CD-ROM raw device (it's inherent limitation of the CDFS driver). */
698
    if (size == -1)
699
        size = LONG_LONG_MAX;
700
#endif
701
    bs->total_sectors = size / 512;
702
    s->fd = fd;
703
    return 0;
704
}
705

    
706
static int raw_read(BlockDriverState *bs, int64_t sector_num, 
707
                    uint8_t *buf, int nb_sectors)
708
{
709
    BDRVRawState *s = bs->opaque;
710
    int ret;
711
    
712
    lseek(s->fd, sector_num * 512, SEEK_SET);
713
    ret = read(s->fd, buf, nb_sectors * 512);
714
    if (ret != nb_sectors * 512) 
715
        return -1;
716
    return 0;
717
}
718

    
719
static int raw_write(BlockDriverState *bs, int64_t sector_num, 
720
                     const uint8_t *buf, int nb_sectors)
721
{
722
    BDRVRawState *s = bs->opaque;
723
    int ret;
724
    
725
    lseek(s->fd, sector_num * 512, SEEK_SET);
726
    ret = write(s->fd, buf, nb_sectors * 512);
727
    if (ret != nb_sectors * 512) 
728
        return -1;
729
    return 0;
730
}
731

    
732
static void raw_close(BlockDriverState *bs)
733
{
734
    BDRVRawState *s = bs->opaque;
735
    close(s->fd);
736
}
737

    
738
static int raw_create(const char *filename, int64_t total_size,
739
                      const char *backing_file, int flags)
740
{
741
    int fd;
742

    
743
    if (flags || backing_file)
744
        return -ENOTSUP;
745

    
746
    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, 
747
              0644);
748
    if (fd < 0)
749
        return -EIO;
750
    ftruncate(fd, total_size * 512);
751
    close(fd);
752
    return 0;
753
}
754

    
755
BlockDriver bdrv_raw = {
756
    "raw",
757
    sizeof(BDRVRawState),
758
    raw_probe,
759
    raw_open,
760
    raw_read,
761
    raw_write,
762
    raw_close,
763
    raw_create,
764
};
765

    
766
void bdrv_init(void)
767
{
768
    bdrv_register(&bdrv_raw);
769
#ifndef _WIN32
770
    bdrv_register(&bdrv_cow);
771
#endif
772
    bdrv_register(&bdrv_qcow);
773
    bdrv_register(&bdrv_vmdk);
774
    bdrv_register(&bdrv_cloop);
775
    bdrv_register(&bdrv_dmg);
776
    bdrv_register(&bdrv_bochs);
777
    bdrv_register(&bdrv_vpc);
778
    bdrv_register(&bdrv_vvfat);
779
}