]> Git Repo - qemu.git/blame - block-raw.c
typo
[qemu.git] / block-raw.c
CommitLineData
83f64091
FB
1/*
2 * Block driver for RAW files
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 "vl.h"
25#include "block_int.h"
26#include <assert.h>
27#ifndef _WIN32
28#include <aio.h>
29
30#ifndef QEMU_TOOL
31#include "exec-all.h"
32#endif
33
34#ifdef CONFIG_COCOA
35#include <paths.h>
36#include <sys/param.h>
37#include <IOKit/IOKitLib.h>
38#include <IOKit/IOBSD.h>
39#include <IOKit/storage/IOMediaBSDClient.h>
40#include <IOKit/storage/IOMedia.h>
41#include <IOKit/storage/IOCDMedia.h>
42//#include <IOKit/storage/IOCDTypes.h>
43#include <CoreFoundation/CoreFoundation.h>
44#endif
45
46#ifdef __sun__
47#include <sys/dkio.h>
48#endif
19cb3738
FB
49#ifdef __linux__
50#include <sys/ioctl.h>
51#include <linux/cdrom.h>
52#include <linux/fd.h>
53#endif
83f64091 54
19cb3738 55//#define DEBUG_FLOPPY
83f64091 56
19cb3738
FB
57#define FTYPE_FILE 0
58#define FTYPE_CD 1
59#define FTYPE_FD 2
83f64091 60
19cb3738
FB
61/* if the FD is not accessed during that time (in ms), we try to
62 reopen it to see if the disk has been changed */
63#define FD_OPEN_TIMEOUT 1000
83f64091 64
19cb3738
FB
65typedef struct BDRVRawState {
66 int fd;
67 int type;
68#if defined(__linux__)
69 /* linux floppy specific */
70 int fd_open_flags;
71 int64_t fd_open_time;
72 int64_t fd_error_time;
73 int fd_got_error;
74 int fd_media_changed;
83f64091 75#endif
19cb3738
FB
76} BDRVRawState;
77
78static int fd_open(BlockDriverState *bs);
83f64091
FB
79
80static int raw_open(BlockDriverState *bs, const char *filename, int flags)
81{
82 BDRVRawState *s = bs->opaque;
19cb3738 83 int fd, open_flags, ret;
83f64091 84
83f64091
FB
85 open_flags = O_BINARY;
86 if ((flags & BDRV_O_ACCESS) == O_RDWR) {
87 open_flags |= O_RDWR;
88 } else {
89 open_flags |= O_RDONLY;
90 bs->read_only = 1;
91 }
92 if (flags & BDRV_O_CREAT)
93 open_flags |= O_CREAT | O_TRUNC;
94
19cb3738
FB
95 s->type = FTYPE_FILE;
96
83f64091 97 fd = open(filename, open_flags, 0644);
19cb3738
FB
98 if (fd < 0) {
99 ret = -errno;
100 if (ret == -EROFS)
101 ret = -EACCES;
102 return ret;
103 }
83f64091
FB
104 s->fd = fd;
105 return 0;
106}
107
108/* XXX: use host sector size if necessary with:
109#ifdef DIOCGSECTORSIZE
110 {
111 unsigned int sectorsize = 512;
112 if (!ioctl(fd, DIOCGSECTORSIZE, &sectorsize) &&
113 sectorsize > bufsize)
114 bufsize = sectorsize;
115 }
116#endif
117#ifdef CONFIG_COCOA
118 u_int32_t blockSize = 512;
119 if ( !ioctl( fd, DKIOCGETBLOCKSIZE, &blockSize ) && blockSize > bufsize) {
120 bufsize = blockSize;
121 }
122#endif
123*/
124
125static int raw_pread(BlockDriverState *bs, int64_t offset,
126 uint8_t *buf, int count)
127{
128 BDRVRawState *s = bs->opaque;
129 int ret;
130
19cb3738
FB
131 ret = fd_open(bs);
132 if (ret < 0)
133 return ret;
134
83f64091
FB
135 lseek(s->fd, offset, SEEK_SET);
136 ret = read(s->fd, buf, count);
137 return ret;
138}
139
140static int raw_pwrite(BlockDriverState *bs, int64_t offset,
141 const uint8_t *buf, int count)
142{
143 BDRVRawState *s = bs->opaque;
144 int ret;
145
19cb3738
FB
146 ret = fd_open(bs);
147 if (ret < 0)
148 return ret;
149
83f64091
FB
150 lseek(s->fd, offset, SEEK_SET);
151 ret = write(s->fd, buf, count);
152 return ret;
153}
154
155/***********************************************************/
19cb3738 156/* Unix AIO using POSIX AIO */
83f64091
FB
157
158typedef struct RawAIOCB {
ce1a14dc 159 BlockDriverAIOCB common;
83f64091 160 struct aiocb aiocb;
ce1a14dc 161 struct RawAIOCB *next;
83f64091
FB
162} RawAIOCB;
163
164static int aio_sig_num = SIGUSR2;
ce1a14dc 165static RawAIOCB *first_aio; /* AIO issued */
979b67ad 166static int aio_initialized = 0;
83f64091 167
83f64091
FB
168static void aio_signal_handler(int signum)
169{
979b67ad 170#ifndef QEMU_TOOL
83f64091
FB
171 CPUState *env = cpu_single_env;
172 if (env) {
173 /* stop the currently executing cpu because a timer occured */
174 cpu_interrupt(env, CPU_INTERRUPT_EXIT);
175#ifdef USE_KQEMU
176 if (env->kqemu_enabled) {
177 kqemu_cpu_interrupt(env);
178 }
179#endif
180 }
979b67ad 181#endif
83f64091
FB
182}
183
184void qemu_aio_init(void)
185{
186 struct sigaction act;
979b67ad
FB
187
188 aio_initialized = 1;
83f64091
FB
189
190 sigfillset(&act.sa_mask);
191 act.sa_flags = 0; /* do not restart syscalls to interrupt select() */
192 act.sa_handler = aio_signal_handler;
193 sigaction(aio_sig_num, &act, NULL);
194
19cb3738 195#if defined(__GLIBC__) && defined(__linux__)
83f64091 196 {
19cb3738
FB
197 /* XXX: aio thread exit seems to hang on RedHat 9 and this init
198 seems to fix the problem. */
83f64091
FB
199 struct aioinit ai;
200 memset(&ai, 0, sizeof(ai));
19cb3738 201 ai.aio_threads = 1;
83f64091
FB
202 ai.aio_num = 1;
203 ai.aio_idle_time = 365 * 100000;
204 aio_init(&ai);
205 }
19cb3738 206#endif
83f64091 207}
83f64091
FB
208
209void qemu_aio_poll(void)
210{
ce1a14dc 211 RawAIOCB *acb, **pacb;
83f64091
FB
212 int ret;
213
214 for(;;) {
215 pacb = &first_aio;
216 for(;;) {
217 acb = *pacb;
218 if (!acb)
219 goto the_end;
ce1a14dc 220 ret = aio_error(&acb->aiocb);
83f64091
FB
221 if (ret == ECANCELED) {
222 /* remove the request */
ce1a14dc
PB
223 *pacb = acb->next;
224 qemu_aio_release(acb);
83f64091
FB
225 } else if (ret != EINPROGRESS) {
226 /* end of aio */
227 if (ret == 0) {
ce1a14dc
PB
228 ret = aio_return(&acb->aiocb);
229 if (ret == acb->aiocb.aio_nbytes)
83f64091
FB
230 ret = 0;
231 else
19cb3738 232 ret = -EINVAL;
83f64091
FB
233 } else {
234 ret = -ret;
235 }
236 /* remove the request */
ce1a14dc 237 *pacb = acb->next;
83f64091 238 /* call the callback */
ce1a14dc
PB
239 acb->common.cb(acb->common.opaque, ret);
240 qemu_aio_release(acb);
83f64091
FB
241 break;
242 } else {
ce1a14dc 243 pacb = &acb->next;
83f64091
FB
244 }
245 }
246 }
247 the_end: ;
248}
249
6192bc37
PB
250/* Wait for all IO requests to complete. */
251void qemu_aio_flush(void)
252{
253 qemu_aio_wait_start();
254 qemu_aio_poll();
255 while (first_aio) {
256 qemu_aio_wait();
257 }
258 qemu_aio_wait_end();
259}
260
83f64091
FB
261/* wait until at least one AIO was handled */
262static sigset_t wait_oset;
263
264void qemu_aio_wait_start(void)
265{
266 sigset_t set;
979b67ad
FB
267
268 if (!aio_initialized)
269 qemu_aio_init();
83f64091
FB
270 sigemptyset(&set);
271 sigaddset(&set, aio_sig_num);
272 sigprocmask(SIG_BLOCK, &set, &wait_oset);
273}
274
275void qemu_aio_wait(void)
276{
277 sigset_t set;
278 int nb_sigs;
6eb5733a
FB
279
280#ifndef QEMU_TOOL
281 if (qemu_bh_poll())
282 return;
283#endif
83f64091
FB
284 sigemptyset(&set);
285 sigaddset(&set, aio_sig_num);
286 sigwait(&set, &nb_sigs);
287 qemu_aio_poll();
288}
289
290void qemu_aio_wait_end(void)
291{
292 sigprocmask(SIG_SETMASK, &wait_oset, NULL);
293}
294
ce1a14dc
PB
295static RawAIOCB *raw_aio_setup(BlockDriverState *bs,
296 int64_t sector_num, uint8_t *buf, int nb_sectors,
297 BlockDriverCompletionFunc *cb, void *opaque)
83f64091 298{
ce1a14dc
PB
299 BDRVRawState *s = bs->opaque;
300 RawAIOCB *acb;
301
19cb3738
FB
302 if (fd_open(bs) < 0)
303 return NULL;
304
ce1a14dc
PB
305 acb = qemu_aio_get(bs, cb, opaque);
306 if (!acb)
307 return NULL;
308 acb->aiocb.aio_fildes = s->fd;
309 acb->aiocb.aio_sigevent.sigev_signo = aio_sig_num;
310 acb->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
311 acb->aiocb.aio_buf = buf;
312 acb->aiocb.aio_nbytes = nb_sectors * 512;
313 acb->aiocb.aio_offset = sector_num * 512;
314 acb->next = first_aio;
315 first_aio = acb;
316 return acb;
83f64091
FB
317}
318
ce1a14dc
PB
319static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs,
320 int64_t sector_num, uint8_t *buf, int nb_sectors,
321 BlockDriverCompletionFunc *cb, void *opaque)
83f64091 322{
ce1a14dc 323 RawAIOCB *acb;
83f64091 324
ce1a14dc
PB
325 acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
326 if (!acb)
327 return NULL;
328 if (aio_read(&acb->aiocb) < 0) {
329 qemu_aio_release(acb);
330 return NULL;
83f64091 331 }
ce1a14dc 332 return &acb->common;
83f64091
FB
333}
334
ce1a14dc
PB
335static BlockDriverAIOCB *raw_aio_write(BlockDriverState *bs,
336 int64_t sector_num, const uint8_t *buf, int nb_sectors,
337 BlockDriverCompletionFunc *cb, void *opaque)
83f64091 338{
ce1a14dc 339 RawAIOCB *acb;
83f64091 340
ce1a14dc
PB
341 acb = raw_aio_setup(bs, sector_num, (uint8_t*)buf, nb_sectors, cb, opaque);
342 if (!acb)
343 return NULL;
344 if (aio_write(&acb->aiocb) < 0) {
345 qemu_aio_release(acb);
346 return NULL;
83f64091 347 }
ce1a14dc 348 return &acb->common;
83f64091
FB
349}
350
ce1a14dc 351static void raw_aio_cancel(BlockDriverAIOCB *blockacb)
83f64091 352{
83f64091 353 int ret;
ce1a14dc
PB
354 RawAIOCB *acb = (RawAIOCB *)blockacb;
355 RawAIOCB **pacb;
83f64091 356
ce1a14dc 357 ret = aio_cancel(acb->aiocb.aio_fildes, &acb->aiocb);
83f64091
FB
358 if (ret == AIO_NOTCANCELED) {
359 /* fail safe: if the aio could not be canceled, we wait for
360 it */
ce1a14dc 361 while (aio_error(&acb->aiocb) == EINPROGRESS);
83f64091
FB
362 }
363
364 /* remove the callback from the queue */
365 pacb = &first_aio;
366 for(;;) {
367 if (*pacb == NULL) {
368 break;
369 } else if (*pacb == acb) {
ce1a14dc
PB
370 *pacb = acb->next;
371 qemu_aio_release(acb);
83f64091
FB
372 break;
373 }
ce1a14dc 374 pacb = &acb->next;
83f64091
FB
375 }
376}
377
83f64091
FB
378static void raw_close(BlockDriverState *bs)
379{
380 BDRVRawState *s = bs->opaque;
19cb3738
FB
381 if (s->fd >= 0) {
382 close(s->fd);
383 s->fd = -1;
384 }
83f64091
FB
385}
386
387static int raw_truncate(BlockDriverState *bs, int64_t offset)
388{
389 BDRVRawState *s = bs->opaque;
19cb3738
FB
390 if (s->type != FTYPE_FILE)
391 return -ENOTSUP;
83f64091
FB
392 if (ftruncate(s->fd, offset) < 0)
393 return -errno;
394 return 0;
395}
396
397static int64_t raw_getlength(BlockDriverState *bs)
398{
399 BDRVRawState *s = bs->opaque;
400 int fd = s->fd;
401 int64_t size;
402#ifdef _BSD
403 struct stat sb;
404#endif
405#ifdef __sun__
406 struct dk_minfo minfo;
407 int rv;
408#endif
19cb3738
FB
409 int ret;
410
411 ret = fd_open(bs);
412 if (ret < 0)
413 return ret;
83f64091
FB
414
415#ifdef _BSD
416 if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) {
417#ifdef DIOCGMEDIASIZE
418 if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size))
419#endif
420#ifdef CONFIG_COCOA
421 size = LONG_LONG_MAX;
422#else
423 size = lseek(fd, 0LL, SEEK_END);
424#endif
425 } else
426#endif
427#ifdef __sun__
428 /*
429 * use the DKIOCGMEDIAINFO ioctl to read the size.
430 */
431 rv = ioctl ( fd, DKIOCGMEDIAINFO, &minfo );
432 if ( rv != -1 ) {
433 size = minfo.dki_lbsize * minfo.dki_capacity;
434 } else /* there are reports that lseek on some devices
435 fails, but irc discussion said that contingency
436 on contingency was overkill */
437#endif
438 {
439 size = lseek(fd, 0, SEEK_END);
440 }
83f64091
FB
441 return size;
442}
443
444static int raw_create(const char *filename, int64_t total_size,
445 const char *backing_file, int flags)
446{
447 int fd;
448
449 if (flags || backing_file)
450 return -ENOTSUP;
451
9ab8a34a 452 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
83f64091
FB
453 0644);
454 if (fd < 0)
455 return -EIO;
456 ftruncate(fd, total_size * 512);
457 close(fd);
458 return 0;
459}
460
461static void raw_flush(BlockDriverState *bs)
462{
463 BDRVRawState *s = bs->opaque;
464 fsync(s->fd);
465}
466
467BlockDriver bdrv_raw = {
468 "raw",
469 sizeof(BDRVRawState),
470 NULL, /* no probe for protocols */
471 raw_open,
472 NULL,
473 NULL,
474 raw_close,
475 raw_create,
476 raw_flush,
477
83f64091
FB
478 .bdrv_aio_read = raw_aio_read,
479 .bdrv_aio_write = raw_aio_write,
480 .bdrv_aio_cancel = raw_aio_cancel,
ce1a14dc 481 .aiocb_size = sizeof(RawAIOCB),
83f64091
FB
482 .protocol_name = "file",
483 .bdrv_pread = raw_pread,
484 .bdrv_pwrite = raw_pwrite,
485 .bdrv_truncate = raw_truncate,
486 .bdrv_getlength = raw_getlength,
487};
488
19cb3738
FB
489/***********************************************/
490/* host device */
491
492#ifdef CONFIG_COCOA
493static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator );
494static kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize );
495
496kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator )
497{
498 kern_return_t kernResult;
499 mach_port_t masterPort;
500 CFMutableDictionaryRef classesToMatch;
501
502 kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort );
503 if ( KERN_SUCCESS != kernResult ) {
504 printf( "IOMasterPort returned %d\n", kernResult );
505 }
506
507 classesToMatch = IOServiceMatching( kIOCDMediaClass );
508 if ( classesToMatch == NULL ) {
509 printf( "IOServiceMatching returned a NULL dictionary.\n" );
510 } else {
511 CFDictionarySetValue( classesToMatch, CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue );
512 }
513 kernResult = IOServiceGetMatchingServices( masterPort, classesToMatch, mediaIterator );
514 if ( KERN_SUCCESS != kernResult )
515 {
516 printf( "IOServiceGetMatchingServices returned %d\n", kernResult );
517 }
518
519 return kernResult;
520}
521
522kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize )
523{
524 io_object_t nextMedia;
525 kern_return_t kernResult = KERN_FAILURE;
526 *bsdPath = '\0';
527 nextMedia = IOIteratorNext( mediaIterator );
528 if ( nextMedia )
529 {
530 CFTypeRef bsdPathAsCFString;
531 bsdPathAsCFString = IORegistryEntryCreateCFProperty( nextMedia, CFSTR( kIOBSDNameKey ), kCFAllocatorDefault, 0 );
532 if ( bsdPathAsCFString ) {
533 size_t devPathLength;
534 strcpy( bsdPath, _PATH_DEV );
535 strcat( bsdPath, "r" );
536 devPathLength = strlen( bsdPath );
537 if ( CFStringGetCString( bsdPathAsCFString, bsdPath + devPathLength, maxPathSize - devPathLength, kCFStringEncodingASCII ) ) {
538 kernResult = KERN_SUCCESS;
539 }
540 CFRelease( bsdPathAsCFString );
541 }
542 IOObjectRelease( nextMedia );
543 }
544
545 return kernResult;
546}
547
548#endif
549
550static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
551{
552 BDRVRawState *s = bs->opaque;
553 int fd, open_flags, ret;
554
555#ifdef CONFIG_COCOA
556 if (strstart(filename, "/dev/cdrom", NULL)) {
557 kern_return_t kernResult;
558 io_iterator_t mediaIterator;
559 char bsdPath[ MAXPATHLEN ];
560 int fd;
561
562 kernResult = FindEjectableCDMedia( &mediaIterator );
563 kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof( bsdPath ) );
564
565 if ( bsdPath[ 0 ] != '\0' ) {
566 strcat(bsdPath,"s0");
567 /* some CDs don't have a partition 0 */
568 fd = open(bsdPath, O_RDONLY | O_BINARY | O_LARGEFILE);
569 if (fd < 0) {
570 bsdPath[strlen(bsdPath)-1] = '1';
571 } else {
572 close(fd);
573 }
574 filename = bsdPath;
575 }
576
577 if ( mediaIterator )
578 IOObjectRelease( mediaIterator );
579 }
580#endif
581 open_flags = O_BINARY;
582 if ((flags & BDRV_O_ACCESS) == O_RDWR) {
583 open_flags |= O_RDWR;
584 } else {
585 open_flags |= O_RDONLY;
586 bs->read_only = 1;
587 }
588
589 s->type = FTYPE_FILE;
590#if defined(__linux__)
591 if (strstart(filename, "/dev/cd", NULL)) {
592 /* open will not fail even if no CD is inserted */
593 open_flags |= O_NONBLOCK;
594 s->type = FTYPE_CD;
595 } else if (strstart(filename, "/dev/fd", NULL)) {
596 s->type = FTYPE_FD;
597 s->fd_open_flags = open_flags;
598 /* open will not fail even if no floppy is inserted */
599 open_flags |= O_NONBLOCK;
600 }
601#endif
602 fd = open(filename, open_flags, 0644);
603 if (fd < 0) {
604 ret = -errno;
605 if (ret == -EROFS)
606 ret = -EACCES;
607 return ret;
608 }
609 s->fd = fd;
610#if defined(__linux__)
611 /* close fd so that we can reopen it as needed */
612 if (s->type == FTYPE_FD) {
613 close(s->fd);
614 s->fd = -1;
615 s->fd_media_changed = 1;
616 }
617#endif
618 return 0;
619}
620
621#if defined(__linux__) && !defined(QEMU_TOOL)
622
623/* Note: we do not have a reliable method to detect if the floppy is
624 present. The current method is to try to open the floppy at every
625 I/O and to keep it opened during a few hundreds of ms. */
626static int fd_open(BlockDriverState *bs)
627{
628 BDRVRawState *s = bs->opaque;
629 int last_media_present;
630
631 if (s->type != FTYPE_FD)
632 return 0;
633 last_media_present = (s->fd >= 0);
634 if (s->fd >= 0 &&
635 (qemu_get_clock(rt_clock) - s->fd_open_time) >= FD_OPEN_TIMEOUT) {
636 close(s->fd);
637 s->fd = -1;
638#ifdef DEBUG_FLOPPY
639 printf("Floppy closed\n");
640#endif
641 }
642 if (s->fd < 0) {
643 if (s->fd_got_error &&
644 (qemu_get_clock(rt_clock) - s->fd_error_time) < FD_OPEN_TIMEOUT) {
645#ifdef DEBUG_FLOPPY
646 printf("No floppy (open delayed)\n");
647#endif
648 return -EIO;
649 }
650 s->fd = open(bs->filename, s->fd_open_flags);
651 if (s->fd < 0) {
652 s->fd_error_time = qemu_get_clock(rt_clock);
653 s->fd_got_error = 1;
654 if (last_media_present)
655 s->fd_media_changed = 1;
656#ifdef DEBUG_FLOPPY
657 printf("No floppy\n");
658#endif
659 return -EIO;
660 }
661#ifdef DEBUG_FLOPPY
662 printf("Floppy opened\n");
663#endif
664 }
665 if (!last_media_present)
666 s->fd_media_changed = 1;
667 s->fd_open_time = qemu_get_clock(rt_clock);
668 s->fd_got_error = 0;
669 return 0;
670}
671#else
672static int fd_open(BlockDriverState *bs)
673{
674 return 0;
675}
676#endif
677
678#if defined(__linux__)
679
680static int raw_is_inserted(BlockDriverState *bs)
681{
682 BDRVRawState *s = bs->opaque;
683 int ret;
684
685 switch(s->type) {
686 case FTYPE_CD:
687 ret = ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
688 if (ret == CDS_DISC_OK)
689 return 1;
690 else
691 return 0;
692 break;
693 case FTYPE_FD:
694 ret = fd_open(bs);
695 return (ret >= 0);
696 default:
697 return 1;
698 }
699}
700
701/* currently only used by fdc.c, but a CD version would be good too */
702static int raw_media_changed(BlockDriverState *bs)
703{
704 BDRVRawState *s = bs->opaque;
705
706 switch(s->type) {
707 case FTYPE_FD:
708 {
709 int ret;
710 /* XXX: we do not have a true media changed indication. It
711 does not work if the floppy is changed without trying
712 to read it */
713 fd_open(bs);
714 ret = s->fd_media_changed;
715 s->fd_media_changed = 0;
716#ifdef DEBUG_FLOPPY
717 printf("Floppy changed=%d\n", ret);
718#endif
719 return ret;
720 }
721 default:
722 return -ENOTSUP;
723 }
724}
725
726static int raw_eject(BlockDriverState *bs, int eject_flag)
727{
728 BDRVRawState *s = bs->opaque;
729
730 switch(s->type) {
731 case FTYPE_CD:
732 if (eject_flag) {
733 if (ioctl (s->fd, CDROMEJECT, NULL) < 0)
734 perror("CDROMEJECT");
735 } else {
736 if (ioctl (s->fd, CDROMCLOSETRAY, NULL) < 0)
737 perror("CDROMEJECT");
738 }
739 break;
740 case FTYPE_FD:
741 {
742 int fd;
743 if (s->fd >= 0) {
744 close(s->fd);
745 s->fd = -1;
746 }
747 fd = open(bs->filename, s->fd_open_flags | O_NONBLOCK);
748 if (fd >= 0) {
749 if (ioctl(fd, FDEJECT, 0) < 0)
750 perror("FDEJECT");
751 close(fd);
752 }
753 }
754 break;
755 default:
756 return -ENOTSUP;
757 }
758 return 0;
759}
760
761static int raw_set_locked(BlockDriverState *bs, int locked)
762{
763 BDRVRawState *s = bs->opaque;
764
765 switch(s->type) {
766 case FTYPE_CD:
767 if (ioctl (s->fd, CDROM_LOCKDOOR, locked) < 0) {
768 /* Note: an error can happen if the distribution automatically
769 mounts the CD-ROM */
770 // perror("CDROM_LOCKDOOR");
771 }
772 break;
773 default:
774 return -ENOTSUP;
775 }
776 return 0;
777}
778
779#else
780
781static int raw_is_inserted(BlockDriverState *bs)
782{
783 return 1;
784}
785
786static int raw_media_changed(BlockDriverState *bs)
787{
788 return -ENOTSUP;
789}
790
791static int raw_eject(BlockDriverState *bs, int eject_flag)
792{
793 return -ENOTSUP;
794}
795
796static int raw_set_locked(BlockDriverState *bs, int locked)
797{
798 return -ENOTSUP;
799}
800
801#endif /* !linux */
802
803BlockDriver bdrv_host_device = {
804 "host_device",
805 sizeof(BDRVRawState),
806 NULL, /* no probe for protocols */
807 hdev_open,
808 NULL,
809 NULL,
810 raw_close,
811 NULL,
812 raw_flush,
813
814 .bdrv_aio_read = raw_aio_read,
815 .bdrv_aio_write = raw_aio_write,
816 .bdrv_aio_cancel = raw_aio_cancel,
817 .aiocb_size = sizeof(RawAIOCB),
818 .bdrv_pread = raw_pread,
819 .bdrv_pwrite = raw_pwrite,
820 .bdrv_getlength = raw_getlength,
821
822 /* removable device support */
823 .bdrv_is_inserted = raw_is_inserted,
824 .bdrv_media_changed = raw_media_changed,
825 .bdrv_eject = raw_eject,
826 .bdrv_set_locked = raw_set_locked,
827};
828
83f64091
FB
829#else /* _WIN32 */
830
831/* XXX: use another file ? */
83f64091
FB
832#include <winioctl.h>
833
19cb3738
FB
834#define FTYPE_FILE 0
835#define FTYPE_CD 1
836
83f64091
FB
837typedef struct BDRVRawState {
838 HANDLE hfile;
19cb3738 839 int type;
f45512fe 840 char drive_path[16]; /* format: "d:\" */
83f64091
FB
841} BDRVRawState;
842
843typedef struct RawAIOCB {
ce1a14dc 844 BlockDriverAIOCB common;
83f64091
FB
845 HANDLE hEvent;
846 OVERLAPPED ov;
847 int count;
848} RawAIOCB;
849
850int qemu_ftruncate64(int fd, int64_t length)
851{
852 LARGE_INTEGER li;
853 LONG high;
854 HANDLE h;
855 BOOL res;
856
857 if ((GetVersion() & 0x80000000UL) && (length >> 32) != 0)
858 return -1;
859
860 h = (HANDLE)_get_osfhandle(fd);
861
862 /* get current position, ftruncate do not change position */
863 li.HighPart = 0;
864 li.LowPart = SetFilePointer (h, 0, &li.HighPart, FILE_CURRENT);
865 if (li.LowPart == 0xffffffffUL && GetLastError() != NO_ERROR)
866 return -1;
867
868 high = length >> 32;
869 if (!SetFilePointer(h, (DWORD) length, &high, FILE_BEGIN))
870 return -1;
871 res = SetEndOfFile(h);
872
873 /* back to old position */
874 SetFilePointer(h, li.LowPart, &li.HighPart, FILE_BEGIN);
875 return res ? 0 : -1;
876}
877
878static int set_sparse(int fd)
879{
880 DWORD returned;
881 return (int) DeviceIoControl((HANDLE)_get_osfhandle(fd), FSCTL_SET_SPARSE,
882 NULL, 0, NULL, 0, &returned, NULL);
883}
884
885static int raw_open(BlockDriverState *bs, const char *filename, int flags)
886{
887 BDRVRawState *s = bs->opaque;
888 int access_flags, create_flags;
ce1a14dc 889 DWORD overlapped;
19cb3738 890
f45512fe 891 s->type = FTYPE_FILE;
83f64091
FB
892
893 if ((flags & BDRV_O_ACCESS) == O_RDWR) {
894 access_flags = GENERIC_READ | GENERIC_WRITE;
895 } else {
896 access_flags = GENERIC_READ;
897 }
979b67ad 898 if (flags & BDRV_O_CREAT) {
83f64091
FB
899 create_flags = CREATE_ALWAYS;
900 } else {
901 create_flags = OPEN_EXISTING;
902 }
ce1a14dc
PB
903#ifdef QEMU_TOOL
904 overlapped = 0;
905#else
906 overlapped = FILE_FLAG_OVERLAPPED;
907#endif
83f64091
FB
908 s->hfile = CreateFile(filename, access_flags,
909 FILE_SHARE_READ, NULL,
ce1a14dc 910 create_flags, overlapped, 0);
83f64091
FB
911 if (s->hfile == INVALID_HANDLE_VALUE)
912 return -1;
913 return 0;
914}
915
916static int raw_pread(BlockDriverState *bs, int64_t offset,
917 uint8_t *buf, int count)
918{
919 BDRVRawState *s = bs->opaque;
920 OVERLAPPED ov;
921 DWORD ret_count;
922 int ret;
923
924 memset(&ov, 0, sizeof(ov));
925 ov.Offset = offset;
926 ov.OffsetHigh = offset >> 32;
436e15b8
FB
927 ret = ReadFile(s->hfile, buf, count, &ret_count, &ov);
928 if (!ret) {
929 ret = GetOverlappedResult(s->hfile, &ov, &ret_count, TRUE);
930 if (!ret)
931 return -EIO;
932 else
933 return ret_count;
934 }
83f64091
FB
935 return ret_count;
936}
937
938static int raw_pwrite(BlockDriverState *bs, int64_t offset,
939 const uint8_t *buf, int count)
940{
941 BDRVRawState *s = bs->opaque;
942 OVERLAPPED ov;
943 DWORD ret_count;
944 int ret;
945
946 memset(&ov, 0, sizeof(ov));
947 ov.Offset = offset;
948 ov.OffsetHigh = offset >> 32;
436e15b8
FB
949 ret = WriteFile(s->hfile, buf, count, &ret_count, &ov);
950 if (!ret) {
951 ret = GetOverlappedResult(s->hfile, &ov, &ret_count, TRUE);
952 if (!ret)
953 return -EIO;
954 else
955 return ret_count;
956 }
83f64091
FB
957 return ret_count;
958}
959
436e15b8 960#ifndef QEMU_TOOL
83f64091
FB
961static void raw_aio_cb(void *opaque)
962{
ce1a14dc
PB
963 RawAIOCB *acb = opaque;
964 BlockDriverState *bs = acb->common.bs;
979b67ad 965 BDRVRawState *s = bs->opaque;
83f64091
FB
966 DWORD ret_count;
967 int ret;
968
ce1a14dc
PB
969 ret = GetOverlappedResult(s->hfile, &acb->ov, &ret_count, TRUE);
970 if (!ret || ret_count != acb->count) {
971 acb->common.cb(acb->common.opaque, -EIO);
83f64091 972 } else {
ce1a14dc 973 acb->common.cb(acb->common.opaque, 0);
83f64091
FB
974 }
975}
436e15b8 976#endif
ce1a14dc
PB
977
978static RawAIOCB *raw_aio_setup(BlockDriverState *bs,
979 int64_t sector_num, uint8_t *buf, int nb_sectors,
980 BlockDriverCompletionFunc *cb, void *opaque)
83f64091 981{
ce1a14dc 982 RawAIOCB *acb;
83f64091
FB
983 int64_t offset;
984
ce1a14dc
PB
985 acb = qemu_aio_get(bs, cb, opaque);
986 if (acb->hEvent) {
987 acb->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
988 if (!acb->hEvent) {
989 qemu_aio_release(acb);
990 return NULL;
991 }
992 }
993 memset(&acb->ov, 0, sizeof(acb->ov));
83f64091 994 offset = sector_num * 512;
ce1a14dc
PB
995 acb->ov.Offset = offset;
996 acb->ov.OffsetHigh = offset >> 32;
997 acb->ov.hEvent = acb->hEvent;
998 acb->count = nb_sectors * 512;
436e15b8 999#ifndef QEMU_TOOL
ce1a14dc 1000 qemu_add_wait_object(acb->ov.hEvent, raw_aio_cb, acb);
436e15b8 1001#endif
ce1a14dc 1002 return acb;
83f64091
FB
1003}
1004
ce1a14dc
PB
1005static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs,
1006 int64_t sector_num, uint8_t *buf, int nb_sectors,
1007 BlockDriverCompletionFunc *cb, void *opaque)
83f64091 1008{
83f64091 1009 BDRVRawState *s = bs->opaque;
ce1a14dc 1010 RawAIOCB *acb;
83f64091 1011 int ret;
83f64091 1012
ce1a14dc
PB
1013 acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
1014 if (!acb)
1015 return NULL;
1016 ret = ReadFile(s->hfile, buf, acb->count, NULL, &acb->ov);
1017 if (!ret) {
1018 qemu_aio_release(acb);
1019 return NULL;
1020 }
1021#ifdef QEMU_TOOL
1022 qemu_aio_release(acb);
436e15b8 1023#endif
ce1a14dc 1024 return (BlockDriverAIOCB *)acb;
83f64091
FB
1025}
1026
ce1a14dc
PB
1027static BlockDriverAIOCB *raw_aio_write(BlockDriverState *bs,
1028 int64_t sector_num, uint8_t *buf, int nb_sectors,
1029 BlockDriverCompletionFunc *cb, void *opaque)
83f64091 1030{
83f64091 1031 BDRVRawState *s = bs->opaque;
ce1a14dc
PB
1032 RawAIOCB *acb;
1033 int ret;
83f64091 1034
ce1a14dc
PB
1035 acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
1036 if (!acb)
1037 return NULL;
1038 ret = WriteFile(s->hfile, buf, acb->count, NULL, &acb->ov);
1039 if (!ret) {
1040 qemu_aio_release(acb);
1041 return NULL;
1042 }
1043#ifdef QEMU_TOOL
1044 qemu_aio_release(acb);
436e15b8 1045#endif
ce1a14dc 1046 return (BlockDriverAIOCB *)acb;
83f64091
FB
1047}
1048
ce1a14dc 1049static void raw_aio_cancel(BlockDriverAIOCB *blockacb)
83f64091 1050{
ce1a14dc
PB
1051#ifndef QEMU_TOOL
1052 RawAIOCB *acb = (RawAIOCB *)blockacb;
1053 BlockDriverState *bs = acb->common.bs;
1054 BDRVRawState *s = bs->opaque;
1055
1056 qemu_del_wait_object(acb->ov.hEvent, raw_aio_cb, acb);
1057 /* XXX: if more than one async I/O it is not correct */
1058 CancelIo(s->hfile);
1059 qemu_aio_release(acb);
1060#endif
83f64091
FB
1061}
1062
1063static void raw_flush(BlockDriverState *bs)
1064{
1065 /* XXX: add it */
1066}
1067
1068static void raw_close(BlockDriverState *bs)
1069{
1070 BDRVRawState *s = bs->opaque;
1071 CloseHandle(s->hfile);
1072}
1073
1074static int raw_truncate(BlockDriverState *bs, int64_t offset)
1075{
1076 BDRVRawState *s = bs->opaque;
1077 DWORD low, high;
1078
979b67ad
FB
1079 low = offset;
1080 high = offset >> 32;
83f64091
FB
1081 if (!SetFilePointer(s->hfile, low, &high, FILE_BEGIN))
1082 return -EIO;
1083 if (!SetEndOfFile(s->hfile))
1084 return -EIO;
1085 return 0;
1086}
1087
f45512fe 1088static int64_t raw_getlength(BlockDriverState *bs)
83f64091
FB
1089{
1090 BDRVRawState *s = bs->opaque;
1091 LARGE_INTEGER l;
19cb3738 1092 ULARGE_INTEGER available, total, total_free;
436e15b8 1093
f45512fe 1094 switch(s->type) {
19cb3738
FB
1095 case FTYPE_FILE:
1096 l.LowPart = GetFileSize(s->hfile, &l.HighPart);
1097 if (l.LowPart == 0xffffffffUL && GetLastError() != NO_ERROR)
1098 return -EIO;
1099 break;
1100 case FTYPE_CD:
f45512fe 1101 if (!GetDiskFreeSpaceEx(s->drive_path, &available, &total, &total_free))
19cb3738 1102 return -EIO;
f45512fe 1103 l.QuadPart = total.QuadPart;
19cb3738
FB
1104 break;
1105 default:
1106 return -EIO;
1107 }
83f64091
FB
1108 return l.QuadPart;
1109}
1110
1111static int raw_create(const char *filename, int64_t total_size,
1112 const char *backing_file, int flags)
1113{
1114 int fd;
1115
1116 if (flags || backing_file)
1117 return -ENOTSUP;
1118
1119 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
1120 0644);
1121 if (fd < 0)
1122 return -EIO;
1123 set_sparse(fd);
1124 ftruncate(fd, total_size * 512);
1125 close(fd);
1126 return 0;
1127}
1128
1129void qemu_aio_init(void)
1130{
1131}
1132
1133void qemu_aio_poll(void)
1134{
1135}
1136
1137void qemu_aio_wait_start(void)
1138{
1139}
1140
1141void qemu_aio_wait(void)
1142{
fd44d818
FB
1143#ifndef QEMU_TOOL
1144 qemu_bh_poll();
1145#endif
83f64091
FB
1146}
1147
1148void qemu_aio_wait_end(void)
1149{
1150}
1151
1152BlockDriver bdrv_raw = {
1153 "raw",
1154 sizeof(BDRVRawState),
1155 NULL, /* no probe for protocols */
1156 raw_open,
1157 NULL,
1158 NULL,
1159 raw_close,
1160 raw_create,
1161 raw_flush,
1162
1163#if 0
83f64091
FB
1164 .bdrv_aio_read = raw_aio_read,
1165 .bdrv_aio_write = raw_aio_write,
1166 .bdrv_aio_cancel = raw_aio_cancel,
ce1a14dc 1167 .aiocb_size = sizeof(RawAIOCB);
83f64091
FB
1168#endif
1169 .protocol_name = "file",
1170 .bdrv_pread = raw_pread,
1171 .bdrv_pwrite = raw_pwrite,
1172 .bdrv_truncate = raw_truncate,
1173 .bdrv_getlength = raw_getlength,
1174};
19cb3738
FB
1175
1176/***********************************************/
1177/* host device */
1178
1179static int find_cdrom(char *cdrom_name, int cdrom_name_size)
1180{
1181 char drives[256], *pdrv = drives;
1182 UINT type;
1183
f45512fe 1184 memset(drives, 0, sizeof(drives));
19cb3738
FB
1185 GetLogicalDriveStrings(sizeof(drives), drives);
1186 while(pdrv[0] != '\0') {
1187 type = GetDriveType(pdrv);
1188 switch(type) {
1189 case DRIVE_CDROM:
1190 snprintf(cdrom_name, cdrom_name_size, "\\\\.\\%c:", pdrv[0]);
1191 return 0;
1192 break;
1193 }
1194 pdrv += lstrlen(pdrv) + 1;
1195 }
1196 return -1;
1197}
1198
f45512fe 1199static int find_device_type(BlockDriverState *bs, const char *filename)
19cb3738 1200{
f45512fe 1201 BDRVRawState *s = bs->opaque;
19cb3738
FB
1202 UINT type;
1203 const char *p;
1204
1205 if (strstart(filename, "\\\\.\\", &p) ||
1206 strstart(filename, "//./", &p)) {
f45512fe
FB
1207 snprintf(s->drive_path, sizeof(s->drive_path), "%c:\\", p[0]);
1208 type = GetDriveType(s->drive_path);
19cb3738
FB
1209 if (type == DRIVE_CDROM)
1210 return FTYPE_CD;
1211 else
1212 return FTYPE_FILE;
1213 } else {
1214 return FTYPE_FILE;
1215 }
1216}
1217
1218static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
1219{
1220 BDRVRawState *s = bs->opaque;
1221 int access_flags, create_flags;
1222 DWORD overlapped;
1223 char device_name[64];
19cb3738
FB
1224
1225 if (strstart(filename, "/dev/cdrom", NULL)) {
1226 if (find_cdrom(device_name, sizeof(device_name)) < 0)
1227 return -ENOENT;
1228 filename = device_name;
1229 } else {
1230 /* transform drive letters into device name */
1231 if (((filename[0] >= 'a' && filename[0] <= 'z') ||
1232 (filename[0] >= 'A' && filename[0] <= 'Z')) &&
1233 filename[1] == ':' && filename[2] == '\0') {
1234 snprintf(device_name, sizeof(device_name), "\\\\.\\%c:", filename[0]);
1235 filename = device_name;
1236 }
1237 }
f45512fe 1238 s->type = find_device_type(bs, filename);
19cb3738
FB
1239
1240 if ((flags & BDRV_O_ACCESS) == O_RDWR) {
1241 access_flags = GENERIC_READ | GENERIC_WRITE;
1242 } else {
1243 access_flags = GENERIC_READ;
1244 }
1245 create_flags = OPEN_EXISTING;
1246
1247#ifdef QEMU_TOOL
1248 overlapped = 0;
1249#else
1250 overlapped = FILE_FLAG_OVERLAPPED;
1251#endif
1252 s->hfile = CreateFile(filename, access_flags,
1253 FILE_SHARE_READ, NULL,
1254 create_flags, overlapped, 0);
1255 if (s->hfile == INVALID_HANDLE_VALUE)
1256 return -1;
1257 return 0;
1258}
1259
1260#if 0
1261/***********************************************/
1262/* removable device additionnal commands */
1263
1264static int raw_is_inserted(BlockDriverState *bs)
1265{
1266 return 1;
1267}
1268
1269static int raw_media_changed(BlockDriverState *bs)
1270{
1271 return -ENOTSUP;
1272}
1273
1274static int raw_eject(BlockDriverState *bs, int eject_flag)
1275{
1276 DWORD ret_count;
1277
1278 if (s->type == FTYPE_FILE)
1279 return -ENOTSUP;
1280 if (eject_flag) {
1281 DeviceIoControl(s->hfile, IOCTL_STORAGE_EJECT_MEDIA,
1282 NULL, 0, NULL, 0, &lpBytesReturned, NULL);
1283 } else {
1284 DeviceIoControl(s->hfile, IOCTL_STORAGE_LOAD_MEDIA,
1285 NULL, 0, NULL, 0, &lpBytesReturned, NULL);
1286 }
1287}
1288
1289static int raw_set_locked(BlockDriverState *bs, int locked)
1290{
1291 return -ENOTSUP;
1292}
1293#endif
1294
1295BlockDriver bdrv_host_device = {
1296 "host_device",
1297 sizeof(BDRVRawState),
1298 NULL, /* no probe for protocols */
1299 hdev_open,
1300 NULL,
1301 NULL,
1302 raw_close,
1303 NULL,
1304 raw_flush,
1305
1306#if 0
1307 .bdrv_aio_read = raw_aio_read,
1308 .bdrv_aio_write = raw_aio_write,
1309 .bdrv_aio_cancel = raw_aio_cancel,
1310 .aiocb_size = sizeof(RawAIOCB);
1311#endif
1312 .bdrv_pread = raw_pread,
1313 .bdrv_pwrite = raw_pwrite,
1314 .bdrv_getlength = raw_getlength,
1315};
83f64091 1316#endif /* _WIN32 */
This page took 0.169908 seconds and 4 git commands to generate.