Statistics
| Branch: | Revision:

root / block-raw-posix.c @ ea4b07f7

History | View | Annotate | Download (23.5 kB)

1
/*
2
 * Block driver for RAW files (posix)
3
 *
4
 * Copyright (c) 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
#ifndef QEMU_IMG
26
#include "qemu-timer.h"
27
#include "exec-all.h"
28
#endif
29
#include "block_int.h"
30
#include <assert.h>
31
#include <aio.h>
32

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

    
45
#ifdef __sun__
46
#define _POSIX_PTHREAD_SEMANTICS 1
47
#include <signal.h>
48
#include <sys/dkio.h>
49
#endif
50
#ifdef __linux__
51
#include <sys/ioctl.h>
52
#include <linux/cdrom.h>
53
#include <linux/fd.h>
54
#endif
55
#ifdef __FreeBSD__
56
#include <sys/disk.h>
57
#endif
58

    
59
//#define DEBUG_FLOPPY
60

    
61
//#define DEBUG_BLOCK
62
#if defined(DEBUG_BLOCK) && !defined(QEMU_IMG)
63
#define DEBUG_BLOCK_PRINT(formatCstr, args...) do { if (loglevel != 0)        \
64
    { fprintf(logfile, formatCstr, ##args); fflush(logfile); } } while (0)
65
#else
66
#define DEBUG_BLOCK_PRINT(formatCstr, args...)
67
#endif
68

    
69
#define FTYPE_FILE   0
70
#define FTYPE_CD     1
71
#define FTYPE_FD     2
72

    
73
/* if the FD is not accessed during that time (in ms), we try to
74
   reopen it to see if the disk has been changed */
75
#define FD_OPEN_TIMEOUT 1000
76

    
77
typedef struct BDRVRawState {
78
    int fd;
79
    int type;
80
    unsigned int lseek_err_cnt;
81
#if defined(__linux__)
82
    /* linux floppy specific */
83
    int fd_open_flags;
84
    int64_t fd_open_time;
85
    int64_t fd_error_time;
86
    int fd_got_error;
87
    int fd_media_changed;
88
#endif
89
} BDRVRawState;
90

    
91
static int fd_open(BlockDriverState *bs);
92

    
93
static int raw_open(BlockDriverState *bs, const char *filename, int flags)
94
{
95
    BDRVRawState *s = bs->opaque;
96
    int fd, open_flags, ret;
97

    
98
    s->lseek_err_cnt = 0;
99

    
100
    open_flags = O_BINARY;
101
    if ((flags & BDRV_O_ACCESS) == O_RDWR) {
102
        open_flags |= O_RDWR;
103
    } else {
104
        open_flags |= O_RDONLY;
105
        bs->read_only = 1;
106
    }
107
    if (flags & BDRV_O_CREAT)
108
        open_flags |= O_CREAT | O_TRUNC;
109
#ifdef O_DIRECT
110
    if (flags & BDRV_O_DIRECT)
111
        open_flags |= O_DIRECT;
112
#endif
113

    
114
    s->type = FTYPE_FILE;
115

    
116
    fd = open(filename, open_flags, 0644);
117
    if (fd < 0) {
118
        ret = -errno;
119
        if (ret == -EROFS)
120
            ret = -EACCES;
121
        return ret;
122
    }
123
    s->fd = fd;
124
    return 0;
125
}
126

    
127
/* XXX: use host sector size if necessary with:
128
#ifdef DIOCGSECTORSIZE
129
        {
130
            unsigned int sectorsize = 512;
131
            if (!ioctl(fd, DIOCGSECTORSIZE, &sectorsize) &&
132
                sectorsize > bufsize)
133
                bufsize = sectorsize;
134
        }
135
#endif
136
#ifdef CONFIG_COCOA
137
        u_int32_t   blockSize = 512;
138
        if ( !ioctl( fd, DKIOCGETBLOCKSIZE, &blockSize ) && blockSize > bufsize) {
139
            bufsize = blockSize;
140
        }
141
#endif
142
*/
143

    
144
static int raw_pread(BlockDriverState *bs, int64_t offset,
145
                     uint8_t *buf, int count)
146
{
147
    BDRVRawState *s = bs->opaque;
148
    int ret;
149

    
150
    ret = fd_open(bs);
151
    if (ret < 0)
152
        return ret;
153

    
154
    if (offset >= 0 && lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
155
        ++(s->lseek_err_cnt);
156
        if(s->lseek_err_cnt <= 10) {
157
            DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
158
                              "] lseek failed : %d = %s\n",
159
                              s->fd, bs->filename, offset, buf, count,
160
                              bs->total_sectors, errno, strerror(errno));
161
        }
162
        return -1;
163
    }
164
    s->lseek_err_cnt=0;
165

    
166
    ret = read(s->fd, buf, count);
167
    if (ret == count)
168
        goto label__raw_read__success;
169

    
170
    DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
171
                      "] read failed %d : %d = %s\n",
172
                      s->fd, bs->filename, offset, buf, count,
173
                      bs->total_sectors, ret, errno, strerror(errno));
174

    
175
    /* Try harder for CDrom. */
176
    if (bs->type == BDRV_TYPE_CDROM) {
177
        lseek(s->fd, offset, SEEK_SET);
178
        ret = read(s->fd, buf, count);
179
        if (ret == count)
180
            goto label__raw_read__success;
181
        lseek(s->fd, offset, SEEK_SET);
182
        ret = read(s->fd, buf, count);
183
        if (ret == count)
184
            goto label__raw_read__success;
185

    
186
        DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
187
                          "] retry read failed %d : %d = %s\n",
188
                          s->fd, bs->filename, offset, buf, count,
189
                          bs->total_sectors, ret, errno, strerror(errno));
190
    }
191

    
192
label__raw_read__success:
193

    
194
    return ret;
195
}
196

    
197
static int raw_pwrite(BlockDriverState *bs, int64_t offset,
198
                      const uint8_t *buf, int count)
199
{
200
    BDRVRawState *s = bs->opaque;
201
    int ret;
202

    
203
    ret = fd_open(bs);
204
    if (ret < 0)
205
        return ret;
206

    
207
    if (offset >= 0 && lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
208
        ++(s->lseek_err_cnt);
209
        if(s->lseek_err_cnt) {
210
            DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %" PRId64 ", %p, %d) [%"
211
                              PRId64 "] lseek failed : %d = %s\n",
212
                              s->fd, bs->filename, offset, buf, count,
213
                              bs->total_sectors, errno, strerror(errno));
214
        }
215
        return -1;
216
    }
217
    s->lseek_err_cnt = 0;
218

    
219
    ret = write(s->fd, buf, count);
220
    if (ret == count)
221
        goto label__raw_write__success;
222

    
223
    DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
224
                      "] write failed %d : %d = %s\n",
225
                      s->fd, bs->filename, offset, buf, count,
226
                      bs->total_sectors, ret, errno, strerror(errno));
227

    
228
label__raw_write__success:
229

    
230
    return ret;
231
}
232

    
233
/***********************************************************/
234
/* Unix AIO using POSIX AIO */
235

    
236
typedef struct RawAIOCB {
237
    BlockDriverAIOCB common;
238
    struct aiocb aiocb;
239
    struct RawAIOCB *next;
240
} RawAIOCB;
241

    
242
static int aio_sig_num = SIGUSR2;
243
static RawAIOCB *first_aio; /* AIO issued */
244
static int aio_initialized = 0;
245

    
246
static void aio_signal_handler(int signum)
247
{
248
#ifndef QEMU_IMG
249
    CPUState *env = cpu_single_env;
250
    if (env) {
251
        /* stop the currently executing cpu because a timer occured */
252
        cpu_interrupt(env, CPU_INTERRUPT_EXIT);
253
#ifdef USE_KQEMU
254
        if (env->kqemu_enabled) {
255
            kqemu_cpu_interrupt(env);
256
        }
257
#endif
258
    }
259
#endif
260
}
261

    
262
void qemu_aio_init(void)
263
{
264
    struct sigaction act;
265

    
266
    aio_initialized = 1;
267

    
268
    sigfillset(&act.sa_mask);
269
    act.sa_flags = 0; /* do not restart syscalls to interrupt select() */
270
    act.sa_handler = aio_signal_handler;
271
    sigaction(aio_sig_num, &act, NULL);
272

    
273
#if defined(__GLIBC__) && defined(__linux__)
274
    {
275
        /* XXX: aio thread exit seems to hang on RedHat 9 and this init
276
           seems to fix the problem. */
277
        struct aioinit ai;
278
        memset(&ai, 0, sizeof(ai));
279
        ai.aio_threads = 16;
280
        ai.aio_num = 16;
281
        ai.aio_idle_time = 365 * 100000;
282
        aio_init(&ai);
283
    }
284
#endif
285
}
286

    
287
void qemu_aio_poll(void)
288
{
289
    RawAIOCB *acb, **pacb;
290
    int ret;
291

    
292
    for(;;) {
293
        pacb = &first_aio;
294
        for(;;) {
295
            acb = *pacb;
296
            if (!acb)
297
                goto the_end;
298
            ret = aio_error(&acb->aiocb);
299
            if (ret == ECANCELED) {
300
                /* remove the request */
301
                *pacb = acb->next;
302
                qemu_aio_release(acb);
303
            } else if (ret != EINPROGRESS) {
304
                /* end of aio */
305
                if (ret == 0) {
306
                    ret = aio_return(&acb->aiocb);
307
                    if (ret == acb->aiocb.aio_nbytes)
308
                        ret = 0;
309
                    else
310
                        ret = -EINVAL;
311
                } else {
312
                    ret = -ret;
313
                }
314
                /* remove the request */
315
                *pacb = acb->next;
316
                /* call the callback */
317
                acb->common.cb(acb->common.opaque, ret);
318
                qemu_aio_release(acb);
319
                break;
320
            } else {
321
                pacb = &acb->next;
322
            }
323
        }
324
    }
325
 the_end: ;
326
}
327

    
328
/* Wait for all IO requests to complete.  */
329
void qemu_aio_flush(void)
330
{
331
    qemu_aio_wait_start();
332
    qemu_aio_poll();
333
    while (first_aio) {
334
        qemu_aio_wait();
335
    }
336
    qemu_aio_wait_end();
337
}
338

    
339
/* wait until at least one AIO was handled */
340
static sigset_t wait_oset;
341

    
342
void qemu_aio_wait_start(void)
343
{
344
    sigset_t set;
345

    
346
    if (!aio_initialized)
347
        qemu_aio_init();
348
    sigemptyset(&set);
349
    sigaddset(&set, aio_sig_num);
350
    sigprocmask(SIG_BLOCK, &set, &wait_oset);
351
}
352

    
353
void qemu_aio_wait(void)
354
{
355
    sigset_t set;
356
    int nb_sigs;
357

    
358
#ifndef QEMU_IMG
359
    if (qemu_bh_poll())
360
        return;
361
#endif
362
    sigemptyset(&set);
363
    sigaddset(&set, aio_sig_num);
364
    sigwait(&set, &nb_sigs);
365
    qemu_aio_poll();
366
}
367

    
368
void qemu_aio_wait_end(void)
369
{
370
    sigprocmask(SIG_SETMASK, &wait_oset, NULL);
371
}
372

    
373
static RawAIOCB *raw_aio_setup(BlockDriverState *bs,
374
        int64_t sector_num, uint8_t *buf, int nb_sectors,
375
        BlockDriverCompletionFunc *cb, void *opaque)
376
{
377
    BDRVRawState *s = bs->opaque;
378
    RawAIOCB *acb;
379

    
380
    if (fd_open(bs) < 0)
381
        return NULL;
382

    
383
    acb = qemu_aio_get(bs, cb, opaque);
384
    if (!acb)
385
        return NULL;
386
    acb->aiocb.aio_fildes = s->fd;
387
    acb->aiocb.aio_sigevent.sigev_signo = aio_sig_num;
388
    acb->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
389
    acb->aiocb.aio_buf = buf;
390
    if (nb_sectors < 0)
391
        acb->aiocb.aio_nbytes = -nb_sectors;
392
    else
393
        acb->aiocb.aio_nbytes = nb_sectors * 512;
394
    acb->aiocb.aio_offset = sector_num * 512;
395
    acb->next = first_aio;
396
    first_aio = acb;
397
    return acb;
398
}
399

    
400
static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs,
401
        int64_t sector_num, uint8_t *buf, int nb_sectors,
402
        BlockDriverCompletionFunc *cb, void *opaque)
403
{
404
    RawAIOCB *acb;
405

    
406
    acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
407
    if (!acb)
408
        return NULL;
409
    if (aio_read(&acb->aiocb) < 0) {
410
        qemu_aio_release(acb);
411
        return NULL;
412
    }
413
    return &acb->common;
414
}
415

    
416
static BlockDriverAIOCB *raw_aio_write(BlockDriverState *bs,
417
        int64_t sector_num, const uint8_t *buf, int nb_sectors,
418
        BlockDriverCompletionFunc *cb, void *opaque)
419
{
420
    RawAIOCB *acb;
421

    
422
    acb = raw_aio_setup(bs, sector_num, (uint8_t*)buf, nb_sectors, cb, opaque);
423
    if (!acb)
424
        return NULL;
425
    if (aio_write(&acb->aiocb) < 0) {
426
        qemu_aio_release(acb);
427
        return NULL;
428
    }
429
    return &acb->common;
430
}
431

    
432
static void raw_aio_cancel(BlockDriverAIOCB *blockacb)
433
{
434
    int ret;
435
    RawAIOCB *acb = (RawAIOCB *)blockacb;
436
    RawAIOCB **pacb;
437

    
438
    ret = aio_cancel(acb->aiocb.aio_fildes, &acb->aiocb);
439
    if (ret == AIO_NOTCANCELED) {
440
        /* fail safe: if the aio could not be canceled, we wait for
441
           it */
442
        while (aio_error(&acb->aiocb) == EINPROGRESS);
443
    }
444

    
445
    /* remove the callback from the queue */
446
    pacb = &first_aio;
447
    for(;;) {
448
        if (*pacb == NULL) {
449
            break;
450
        } else if (*pacb == acb) {
451
            *pacb = acb->next;
452
            qemu_aio_release(acb);
453
            break;
454
        }
455
        pacb = &acb->next;
456
    }
457
}
458

    
459
static void raw_close(BlockDriverState *bs)
460
{
461
    BDRVRawState *s = bs->opaque;
462
    if (s->fd >= 0) {
463
        close(s->fd);
464
        s->fd = -1;
465
    }
466
}
467

    
468
static int raw_truncate(BlockDriverState *bs, int64_t offset)
469
{
470
    BDRVRawState *s = bs->opaque;
471
    if (s->type != FTYPE_FILE)
472
        return -ENOTSUP;
473
    if (ftruncate(s->fd, offset) < 0)
474
        return -errno;
475
    return 0;
476
}
477

    
478
static int64_t  raw_getlength(BlockDriverState *bs)
479
{
480
    BDRVRawState *s = bs->opaque;
481
    int fd = s->fd;
482
    int64_t size;
483
#ifdef _BSD
484
    struct stat sb;
485
#endif
486
#ifdef __sun__
487
    struct dk_minfo minfo;
488
    int rv;
489
#endif
490
    int ret;
491

    
492
    ret = fd_open(bs);
493
    if (ret < 0)
494
        return ret;
495

    
496
#ifdef _BSD
497
    if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) {
498
#ifdef DIOCGMEDIASIZE
499
        if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size))
500
#endif
501
#ifdef CONFIG_COCOA
502
        size = LONG_LONG_MAX;
503
#else
504
        size = lseek(fd, 0LL, SEEK_END);
505
#endif
506
    } else
507
#endif
508
#ifdef __sun__
509
    /*
510
     * use the DKIOCGMEDIAINFO ioctl to read the size.
511
     */
512
    rv = ioctl ( fd, DKIOCGMEDIAINFO, &minfo );
513
    if ( rv != -1 ) {
514
        size = minfo.dki_lbsize * minfo.dki_capacity;
515
    } else /* there are reports that lseek on some devices
516
              fails, but irc discussion said that contingency
517
              on contingency was overkill */
518
#endif
519
    {
520
        size = lseek(fd, 0, SEEK_END);
521
    }
522
    return size;
523
}
524

    
525
static int raw_create(const char *filename, int64_t total_size,
526
                      const char *backing_file, int flags)
527
{
528
    int fd;
529

    
530
    if (flags || backing_file)
531
        return -ENOTSUP;
532

    
533
    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
534
              0644);
535
    if (fd < 0)
536
        return -EIO;
537
    ftruncate(fd, total_size * 512);
538
    close(fd);
539
    return 0;
540
}
541

    
542
static void raw_flush(BlockDriverState *bs)
543
{
544
    BDRVRawState *s = bs->opaque;
545
    fsync(s->fd);
546
}
547

    
548
BlockDriver bdrv_raw = {
549
    "raw",
550
    sizeof(BDRVRawState),
551
    NULL, /* no probe for protocols */
552
    raw_open,
553
    NULL,
554
    NULL,
555
    raw_close,
556
    raw_create,
557
    raw_flush,
558

    
559
    .bdrv_aio_read = raw_aio_read,
560
    .bdrv_aio_write = raw_aio_write,
561
    .bdrv_aio_cancel = raw_aio_cancel,
562
    .aiocb_size = sizeof(RawAIOCB),
563
    .protocol_name = "file",
564
    .bdrv_pread = raw_pread,
565
    .bdrv_pwrite = raw_pwrite,
566
    .bdrv_truncate = raw_truncate,
567
    .bdrv_getlength = raw_getlength,
568
};
569

    
570
/***********************************************/
571
/* host device */
572

    
573
#ifdef CONFIG_COCOA
574
static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator );
575
static kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize );
576

    
577
kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator )
578
{
579
    kern_return_t       kernResult;
580
    mach_port_t     masterPort;
581
    CFMutableDictionaryRef  classesToMatch;
582

    
583
    kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort );
584
    if ( KERN_SUCCESS != kernResult ) {
585
        printf( "IOMasterPort returned %d\n", kernResult );
586
    }
587

    
588
    classesToMatch = IOServiceMatching( kIOCDMediaClass );
589
    if ( classesToMatch == NULL ) {
590
        printf( "IOServiceMatching returned a NULL dictionary.\n" );
591
    } else {
592
    CFDictionarySetValue( classesToMatch, CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue );
593
    }
594
    kernResult = IOServiceGetMatchingServices( masterPort, classesToMatch, mediaIterator );
595
    if ( KERN_SUCCESS != kernResult )
596
    {
597
        printf( "IOServiceGetMatchingServices returned %d\n", kernResult );
598
    }
599

    
600
    return kernResult;
601
}
602

    
603
kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize )
604
{
605
    io_object_t     nextMedia;
606
    kern_return_t   kernResult = KERN_FAILURE;
607
    *bsdPath = '\0';
608
    nextMedia = IOIteratorNext( mediaIterator );
609
    if ( nextMedia )
610
    {
611
        CFTypeRef   bsdPathAsCFString;
612
    bsdPathAsCFString = IORegistryEntryCreateCFProperty( nextMedia, CFSTR( kIOBSDNameKey ), kCFAllocatorDefault, 0 );
613
        if ( bsdPathAsCFString ) {
614
            size_t devPathLength;
615
            strcpy( bsdPath, _PATH_DEV );
616
            strcat( bsdPath, "r" );
617
            devPathLength = strlen( bsdPath );
618
            if ( CFStringGetCString( bsdPathAsCFString, bsdPath + devPathLength, maxPathSize - devPathLength, kCFStringEncodingASCII ) ) {
619
                kernResult = KERN_SUCCESS;
620
            }
621
            CFRelease( bsdPathAsCFString );
622
        }
623
        IOObjectRelease( nextMedia );
624
    }
625

    
626
    return kernResult;
627
}
628

    
629
#endif
630

    
631
static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
632
{
633
    BDRVRawState *s = bs->opaque;
634
    int fd, open_flags, ret;
635

    
636
#ifdef CONFIG_COCOA
637
    if (strstart(filename, "/dev/cdrom", NULL)) {
638
        kern_return_t kernResult;
639
        io_iterator_t mediaIterator;
640
        char bsdPath[ MAXPATHLEN ];
641
        int fd;
642

    
643
        kernResult = FindEjectableCDMedia( &mediaIterator );
644
        kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof( bsdPath ) );
645

    
646
        if ( bsdPath[ 0 ] != '\0' ) {
647
            strcat(bsdPath,"s0");
648
            /* some CDs don't have a partition 0 */
649
            fd = open(bsdPath, O_RDONLY | O_BINARY | O_LARGEFILE);
650
            if (fd < 0) {
651
                bsdPath[strlen(bsdPath)-1] = '1';
652
            } else {
653
                close(fd);
654
            }
655
            filename = bsdPath;
656
        }
657

    
658
        if ( mediaIterator )
659
            IOObjectRelease( mediaIterator );
660
    }
661
#endif
662
    open_flags = O_BINARY;
663
    if ((flags & BDRV_O_ACCESS) == O_RDWR) {
664
        open_flags |= O_RDWR;
665
    } else {
666
        open_flags |= O_RDONLY;
667
        bs->read_only = 1;
668
    }
669
#ifdef O_DIRECT
670
    if (flags & BDRV_O_DIRECT)
671
        open_flags |= O_DIRECT;
672
#endif
673

    
674
    s->type = FTYPE_FILE;
675
#if defined(__linux__)
676
    if (strstart(filename, "/dev/cd", NULL)) {
677
        /* open will not fail even if no CD is inserted */
678
        open_flags |= O_NONBLOCK;
679
        s->type = FTYPE_CD;
680
    } else if (strstart(filename, "/dev/fd", NULL)) {
681
        s->type = FTYPE_FD;
682
        s->fd_open_flags = open_flags;
683
        /* open will not fail even if no floppy is inserted */
684
        open_flags |= O_NONBLOCK;
685
    } else if (strstart(filename, "/dev/sg", NULL)) {
686
        bs->sg = 1;
687
    }
688
#endif
689
    fd = open(filename, open_flags, 0644);
690
    if (fd < 0) {
691
        ret = -errno;
692
        if (ret == -EROFS)
693
            ret = -EACCES;
694
        return ret;
695
    }
696
    s->fd = fd;
697
#if defined(__linux__)
698
    /* close fd so that we can reopen it as needed */
699
    if (s->type == FTYPE_FD) {
700
        close(s->fd);
701
        s->fd = -1;
702
        s->fd_media_changed = 1;
703
    }
704
#endif
705
    return 0;
706
}
707

    
708
#if defined(__linux__) && !defined(QEMU_IMG)
709

    
710
/* Note: we do not have a reliable method to detect if the floppy is
711
   present. The current method is to try to open the floppy at every
712
   I/O and to keep it opened during a few hundreds of ms. */
713
static int fd_open(BlockDriverState *bs)
714
{
715
    BDRVRawState *s = bs->opaque;
716
    int last_media_present;
717

    
718
    if (s->type != FTYPE_FD)
719
        return 0;
720
    last_media_present = (s->fd >= 0);
721
    if (s->fd >= 0 &&
722
        (qemu_get_clock(rt_clock) - s->fd_open_time) >= FD_OPEN_TIMEOUT) {
723
        close(s->fd);
724
        s->fd = -1;
725
#ifdef DEBUG_FLOPPY
726
        printf("Floppy closed\n");
727
#endif
728
    }
729
    if (s->fd < 0) {
730
        if (s->fd_got_error &&
731
            (qemu_get_clock(rt_clock) - s->fd_error_time) < FD_OPEN_TIMEOUT) {
732
#ifdef DEBUG_FLOPPY
733
            printf("No floppy (open delayed)\n");
734
#endif
735
            return -EIO;
736
        }
737
        s->fd = open(bs->filename, s->fd_open_flags);
738
        if (s->fd < 0) {
739
            s->fd_error_time = qemu_get_clock(rt_clock);
740
            s->fd_got_error = 1;
741
            if (last_media_present)
742
                s->fd_media_changed = 1;
743
#ifdef DEBUG_FLOPPY
744
            printf("No floppy\n");
745
#endif
746
            return -EIO;
747
        }
748
#ifdef DEBUG_FLOPPY
749
        printf("Floppy opened\n");
750
#endif
751
    }
752
    if (!last_media_present)
753
        s->fd_media_changed = 1;
754
    s->fd_open_time = qemu_get_clock(rt_clock);
755
    s->fd_got_error = 0;
756
    return 0;
757
}
758
#else
759
static int fd_open(BlockDriverState *bs)
760
{
761
    return 0;
762
}
763
#endif
764

    
765
#if defined(__linux__)
766

    
767
static int raw_is_inserted(BlockDriverState *bs)
768
{
769
    BDRVRawState *s = bs->opaque;
770
    int ret;
771

    
772
    switch(s->type) {
773
    case FTYPE_CD:
774
        ret = ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
775
        if (ret == CDS_DISC_OK)
776
            return 1;
777
        else
778
            return 0;
779
        break;
780
    case FTYPE_FD:
781
        ret = fd_open(bs);
782
        return (ret >= 0);
783
    default:
784
        return 1;
785
    }
786
}
787

    
788
/* currently only used by fdc.c, but a CD version would be good too */
789
static int raw_media_changed(BlockDriverState *bs)
790
{
791
    BDRVRawState *s = bs->opaque;
792

    
793
    switch(s->type) {
794
    case FTYPE_FD:
795
        {
796
            int ret;
797
            /* XXX: we do not have a true media changed indication. It
798
               does not work if the floppy is changed without trying
799
               to read it */
800
            fd_open(bs);
801
            ret = s->fd_media_changed;
802
            s->fd_media_changed = 0;
803
#ifdef DEBUG_FLOPPY
804
            printf("Floppy changed=%d\n", ret);
805
#endif
806
            return ret;
807
        }
808
    default:
809
        return -ENOTSUP;
810
    }
811
}
812

    
813
static int raw_eject(BlockDriverState *bs, int eject_flag)
814
{
815
    BDRVRawState *s = bs->opaque;
816

    
817
    switch(s->type) {
818
    case FTYPE_CD:
819
        if (eject_flag) {
820
            if (ioctl (s->fd, CDROMEJECT, NULL) < 0)
821
                perror("CDROMEJECT");
822
        } else {
823
            if (ioctl (s->fd, CDROMCLOSETRAY, NULL) < 0)
824
                perror("CDROMEJECT");
825
        }
826
        break;
827
    case FTYPE_FD:
828
        {
829
            int fd;
830
            if (s->fd >= 0) {
831
                close(s->fd);
832
                s->fd = -1;
833
            }
834
            fd = open(bs->filename, s->fd_open_flags | O_NONBLOCK);
835
            if (fd >= 0) {
836
                if (ioctl(fd, FDEJECT, 0) < 0)
837
                    perror("FDEJECT");
838
                close(fd);
839
            }
840
        }
841
        break;
842
    default:
843
        return -ENOTSUP;
844
    }
845
    return 0;
846
}
847

    
848
static int raw_set_locked(BlockDriverState *bs, int locked)
849
{
850
    BDRVRawState *s = bs->opaque;
851

    
852
    switch(s->type) {
853
    case FTYPE_CD:
854
        if (ioctl (s->fd, CDROM_LOCKDOOR, locked) < 0) {
855
            /* Note: an error can happen if the distribution automatically
856
               mounts the CD-ROM */
857
            //        perror("CDROM_LOCKDOOR");
858
        }
859
        break;
860
    default:
861
        return -ENOTSUP;
862
    }
863
    return 0;
864
}
865

    
866
static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
867
{
868
    BDRVRawState *s = bs->opaque;
869

    
870
    return ioctl(s->fd, req, buf);
871
}
872
#else
873

    
874
static int raw_is_inserted(BlockDriverState *bs)
875
{
876
    return 1;
877
}
878

    
879
static int raw_media_changed(BlockDriverState *bs)
880
{
881
    return -ENOTSUP;
882
}
883

    
884
static int raw_eject(BlockDriverState *bs, int eject_flag)
885
{
886
    return -ENOTSUP;
887
}
888

    
889
static int raw_set_locked(BlockDriverState *bs, int locked)
890
{
891
    return -ENOTSUP;
892
}
893

    
894
static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
895
{
896
    return -ENOTSUP;
897
}
898
#endif /* !linux */
899

    
900
BlockDriver bdrv_host_device = {
901
    "host_device",
902
    sizeof(BDRVRawState),
903
    NULL, /* no probe for protocols */
904
    hdev_open,
905
    NULL,
906
    NULL,
907
    raw_close,
908
    NULL,
909
    raw_flush,
910

    
911
    .bdrv_aio_read = raw_aio_read,
912
    .bdrv_aio_write = raw_aio_write,
913
    .bdrv_aio_cancel = raw_aio_cancel,
914
    .aiocb_size = sizeof(RawAIOCB),
915
    .bdrv_pread = raw_pread,
916
    .bdrv_pwrite = raw_pwrite,
917
    .bdrv_getlength = raw_getlength,
918

    
919
    /* removable device support */
920
    .bdrv_is_inserted = raw_is_inserted,
921
    .bdrv_media_changed = raw_media_changed,
922
    .bdrv_eject = raw_eject,
923
    .bdrv_set_locked = raw_set_locked,
924
    /* generic scsi device */
925
    .bdrv_ioctl = raw_ioctl,
926
};