2 * QEMU System Emulator block driver
4 * Copyright (c) 2003 Fabrice Bellard
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:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
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
25 #include "block_int.h"
28 #include <sys/types.h>
30 #include <sys/ioctl.h>
31 #include <sys/queue.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>
51 static BlockDriverState
*bdrv_first
;
52 static BlockDriver
*first_drv
;
55 static kern_return_t
FindEjectableCDMedia( io_iterator_t
*mediaIterator
);
56 static kern_return_t
GetBSDPath( io_iterator_t mediaIterator
, char *bsdPath
, CFIndex maxPathSize
);
58 kern_return_t
FindEjectableCDMedia( io_iterator_t
*mediaIterator
)
60 kern_return_t kernResult
;
61 mach_port_t masterPort
;
62 CFMutableDictionaryRef classesToMatch
;
64 kernResult
= IOMasterPort( MACH_PORT_NULL
, &masterPort
);
65 if ( KERN_SUCCESS
!= kernResult
) {
66 printf( "IOMasterPort returned %d\n", kernResult
);
69 classesToMatch
= IOServiceMatching( kIOCDMediaClass
);
70 if ( classesToMatch
== NULL
) {
71 printf( "IOServiceMatching returned a NULL dictionary.\n" );
73 CFDictionarySetValue( classesToMatch
, CFSTR( kIOMediaEjectableKey
), kCFBooleanTrue
);
75 kernResult
= IOServiceGetMatchingServices( masterPort
, classesToMatch
, mediaIterator
);
76 if ( KERN_SUCCESS
!= kernResult
)
78 printf( "IOServiceGetMatchingServices returned %d\n", kernResult
);
84 kern_return_t
GetBSDPath( io_iterator_t mediaIterator
, char *bsdPath
, CFIndex maxPathSize
)
86 io_object_t nextMedia
;
87 kern_return_t kernResult
= KERN_FAILURE
;
89 nextMedia
= IOIteratorNext( mediaIterator
);
92 CFTypeRef bsdPathAsCFString
;
93 bsdPathAsCFString
= IORegistryEntryCreateCFProperty( nextMedia
, CFSTR( kIOBSDNameKey
), kCFAllocatorDefault
, 0 );
94 if ( bsdPathAsCFString
) {
96 strcpy( bsdPath
, _PATH_DEV
);
97 strcat( bsdPath
, "r" );
98 devPathLength
= strlen( bsdPath
);
99 if ( CFStringGetCString( bsdPathAsCFString
, bsdPath
+ devPathLength
, maxPathSize
- devPathLength
, kCFStringEncodingASCII
) ) {
100 kernResult
= KERN_SUCCESS
;
102 CFRelease( bsdPathAsCFString
);
104 IOObjectRelease( nextMedia
);
112 void bdrv_register(BlockDriver
*bdrv
)
114 bdrv
->next
= first_drv
;
118 /* create a new block device (by default it is empty) */
119 BlockDriverState
*bdrv_new(const char *device_name
)
121 BlockDriverState
**pbs
, *bs
;
123 bs
= qemu_mallocz(sizeof(BlockDriverState
));
126 pstrcpy(bs
->device_name
, sizeof(bs
->device_name
), device_name
);
127 if (device_name
[0] != '\0') {
128 /* insert at the end */
137 BlockDriver
*bdrv_find_format(const char *format_name
)
140 for(drv1
= first_drv
; drv1
!= NULL
; drv1
= drv1
->next
) {
141 if (!strcmp(drv1
->format_name
, format_name
))
147 int bdrv_create(BlockDriver
*drv
,
148 const char *filename
, int64_t size_in_sectors
,
149 const char *backing_file
, int flags
)
151 if (!drv
->bdrv_create
)
153 return drv
->bdrv_create(filename
, size_in_sectors
, backing_file
, flags
);
157 void get_tmp_filename(char *filename
, int size
)
159 char* p
= strrchr(filename
, '/');
164 /* XXX: find a better function */
169 void get_tmp_filename(char *filename
, int size
)
172 /* XXX: race condition possible */
173 pstrcpy(filename
, size
, "/tmp/vl.XXXXXX");
174 fd
= mkstemp(filename
);
179 /* XXX: force raw format if block or character device ? It would
180 simplify the BSD case */
181 static BlockDriver
*find_image_format(const char *filename
)
183 int fd
, ret
, score
, score_max
;
184 BlockDriver
*drv1
, *drv
;
186 size_t bufsize
= 1024;
188 fd
= open(filename
, O_RDONLY
| O_BINARY
| O_LARGEFILE
);
193 #ifdef DIOCGSECTORSIZE
195 unsigned int sectorsize
= 512;
196 if (!ioctl(fd
, DIOCGSECTORSIZE
, §orsize
) &&
197 sectorsize
> bufsize
)
198 bufsize
= sectorsize
;
202 u_int32_t blockSize
= 512;
203 if ( !ioctl( fd
, DKIOCGETBLOCKSIZE
, &blockSize
) && blockSize
> bufsize
) {
207 buf
= qemu_malloc(bufsize
);
210 ret
= read(fd
, buf
, bufsize
);
221 for(drv1
= first_drv
; drv1
!= NULL
; drv1
= drv1
->next
) {
222 score
= drv1
->bdrv_probe(buf
, ret
, filename
);
223 if (score
> score_max
) {
232 int bdrv_open(BlockDriverState
*bs
, const char *filename
, int snapshot
)
235 if ( strncmp( filename
, "/dev/cdrom", 10 ) == 0 ) {
236 kern_return_t kernResult
;
237 io_iterator_t mediaIterator
;
238 char bsdPath
[ MAXPATHLEN
];
241 kernResult
= FindEjectableCDMedia( &mediaIterator
);
242 kernResult
= GetBSDPath( mediaIterator
, bsdPath
, sizeof( bsdPath
) );
244 if ( bsdPath
[ 0 ] != '\0' ) {
245 strcat(bsdPath
,"s0");
246 /* some CDs don't have a partition 0 */
247 fd
= open(bsdPath
, O_RDONLY
| O_BINARY
| O_LARGEFILE
);
249 bsdPath
[strlen(bsdPath
)-1] = '1';
257 IOObjectRelease( mediaIterator
);
260 return bdrv_open2(bs
, filename
, snapshot
, NULL
);
263 int bdrv_open2(BlockDriverState
*bs
, const char *filename
, int snapshot
,
267 char tmp_filename
[1024];
270 bs
->is_temporary
= 0;
274 BlockDriverState
*bs1
;
277 /* if snapshot, we create a temporary backing file and open it
278 instead of opening 'filename' directly */
280 /* if there is a backing file, use it */
285 if (bdrv_open(bs1
, filename
, 0) < 0) {
289 total_size
= bs1
->total_sectors
;
292 get_tmp_filename(tmp_filename
, sizeof(tmp_filename
));
293 /* XXX: use cow for linux as it is more efficient ? */
294 if (bdrv_create(&bdrv_qcow
, tmp_filename
,
295 total_size
, filename
, 0) < 0) {
298 filename
= tmp_filename
;
299 bs
->is_temporary
= 1;
302 pstrcpy(bs
->filename
, sizeof(bs
->filename
), filename
);
304 drv
= find_image_format(filename
);
309 bs
->opaque
= qemu_mallocz(drv
->instance_size
);
310 if (bs
->opaque
== NULL
&& drv
->instance_size
> 0)
313 ret
= drv
->bdrv_open(bs
, filename
);
315 qemu_free(bs
->opaque
);
319 if (bs
->is_temporary
) {
323 if (bs
->backing_file
[0] != '\0' && drv
->bdrv_is_allocated
) {
324 /* if there is a backing file, use it */
325 bs
->backing_hd
= bdrv_new("");
326 if (!bs
->backing_hd
) {
331 if (bdrv_open(bs
->backing_hd
, bs
->backing_file
, 0) < 0)
337 /* call the change callback */
339 bs
->change_cb(bs
->change_opaque
);
344 void bdrv_close(BlockDriverState
*bs
)
348 bdrv_delete(bs
->backing_hd
);
349 bs
->drv
->bdrv_close(bs
);
350 qemu_free(bs
->opaque
);
352 if (bs
->is_temporary
) {
353 unlink(bs
->filename
);
360 /* call the change callback */
362 bs
->change_cb(bs
->change_opaque
);
366 void bdrv_delete(BlockDriverState
*bs
)
368 /* XXX: remove the driver list */
373 /* commit COW file into the raw image */
374 int bdrv_commit(BlockDriverState
*bs
)
378 unsigned char sector
[512];
387 if (!bs
->backing_hd
) {
391 for (i
= 0; i
< bs
->total_sectors
;) {
392 if (bs
->drv
->bdrv_is_allocated(bs
, i
, 65536, &n
)) {
393 for(j
= 0; j
< n
; j
++) {
394 if (bdrv_read(bs
, i
, sector
, 1) != 0) {
398 if (bdrv_write(bs
->backing_hd
, i
, sector
, 1) != 0) {
408 if (bs
->drv
->bdrv_make_empty
)
409 return bs
->drv
->bdrv_make_empty(bs
);
414 /* return -1 if error */
415 int bdrv_read(BlockDriverState
*bs
, int64_t sector_num
,
416 uint8_t *buf
, int nb_sectors
)
419 BlockDriver
*drv
= bs
->drv
;
424 while (nb_sectors
> 0) {
425 if (sector_num
== 0 && bs
->boot_sector_enabled
) {
426 memcpy(buf
, bs
->boot_sector_data
, 512);
428 } else if (bs
->backing_hd
) {
429 if (drv
->bdrv_is_allocated(bs
, sector_num
, nb_sectors
, &n
)) {
430 ret
= drv
->bdrv_read(bs
, sector_num
, buf
, n
);
434 /* read from the base image */
435 ret
= bdrv_read(bs
->backing_hd
, sector_num
, buf
, n
);
440 ret
= drv
->bdrv_read(bs
, sector_num
, buf
, nb_sectors
);
443 /* no need to loop */
453 /* return -1 if error */
454 int bdrv_write(BlockDriverState
*bs
, int64_t sector_num
,
455 const uint8_t *buf
, int nb_sectors
)
461 if (sector_num
== 0 && bs
->boot_sector_enabled
&& nb_sectors
> 0) {
462 memcpy(bs
->boot_sector_data
, buf
, 512);
464 return bs
->drv
->bdrv_write(bs
, sector_num
, buf
, nb_sectors
);
467 void bdrv_get_geometry(BlockDriverState
*bs
, int64_t *nb_sectors_ptr
)
469 *nb_sectors_ptr
= bs
->total_sectors
;
472 /* force a given boot sector. */
473 void bdrv_set_boot_sector(BlockDriverState
*bs
, const uint8_t *data
, int size
)
475 bs
->boot_sector_enabled
= 1;
478 memcpy(bs
->boot_sector_data
, data
, size
);
479 memset(bs
->boot_sector_data
+ size
, 0, 512 - size
);
482 void bdrv_set_geometry_hint(BlockDriverState
*bs
,
483 int cyls
, int heads
, int secs
)
490 void bdrv_set_type_hint(BlockDriverState
*bs
, int type
)
493 bs
->removable
= ((type
== BDRV_TYPE_CDROM
||
494 type
== BDRV_TYPE_FLOPPY
));
497 void bdrv_set_translation_hint(BlockDriverState
*bs
, int translation
)
499 bs
->translation
= translation
;
502 void bdrv_get_geometry_hint(BlockDriverState
*bs
,
503 int *pcyls
, int *pheads
, int *psecs
)
510 int bdrv_get_type_hint(BlockDriverState
*bs
)
515 int bdrv_get_translation_hint(BlockDriverState
*bs
)
517 return bs
->translation
;
520 int bdrv_is_removable(BlockDriverState
*bs
)
522 return bs
->removable
;
525 int bdrv_is_read_only(BlockDriverState
*bs
)
527 return bs
->read_only
;
530 int bdrv_is_inserted(BlockDriverState
*bs
)
535 int bdrv_is_locked(BlockDriverState
*bs
)
540 void bdrv_set_locked(BlockDriverState
*bs
, int locked
)
545 void bdrv_set_change_cb(BlockDriverState
*bs
,
546 void (*change_cb
)(void *opaque
), void *opaque
)
548 bs
->change_cb
= change_cb
;
549 bs
->change_opaque
= opaque
;
552 int bdrv_is_encrypted(BlockDriverState
*bs
)
554 if (bs
->backing_hd
&& bs
->backing_hd
->encrypted
)
556 return bs
->encrypted
;
559 int bdrv_set_key(BlockDriverState
*bs
, const char *key
)
562 if (bs
->backing_hd
&& bs
->backing_hd
->encrypted
) {
563 ret
= bdrv_set_key(bs
->backing_hd
, key
);
569 if (!bs
->encrypted
|| !bs
->drv
|| !bs
->drv
->bdrv_set_key
)
571 return bs
->drv
->bdrv_set_key(bs
, key
);
574 void bdrv_get_format(BlockDriverState
*bs
, char *buf
, int buf_size
)
576 if (!bs
->inserted
|| !bs
->drv
) {
579 pstrcpy(buf
, buf_size
, bs
->drv
->format_name
);
583 void bdrv_iterate_format(void (*it
)(void *opaque
, const char *name
),
588 for (drv
= first_drv
; drv
!= NULL
; drv
= drv
->next
) {
589 it(opaque
, drv
->format_name
);
593 BlockDriverState
*bdrv_find(const char *name
)
595 BlockDriverState
*bs
;
597 for (bs
= bdrv_first
; bs
!= NULL
; bs
= bs
->next
) {
598 if (!strcmp(name
, bs
->device_name
))
604 void bdrv_iterate(void (*it
)(void *opaque
, const char *name
), void *opaque
)
606 BlockDriverState
*bs
;
608 for (bs
= bdrv_first
; bs
!= NULL
; bs
= bs
->next
) {
609 it(opaque
, bs
->device_name
);
613 const char *bdrv_get_device_name(BlockDriverState
*bs
)
615 return bs
->device_name
;
618 void bdrv_flush(BlockDriverState
*bs
)
620 if (bs
->drv
->bdrv_flush
)
621 bs
->drv
->bdrv_flush(bs
);
623 bdrv_flush(bs
->backing_hd
);
628 BlockDriverState
*bs
;
630 for (bs
= bdrv_first
; bs
!= NULL
; bs
= bs
->next
) {
631 term_printf("%s:", bs
->device_name
);
632 term_printf(" type=");
637 case BDRV_TYPE_CDROM
:
638 term_printf("cdrom");
640 case BDRV_TYPE_FLOPPY
:
641 term_printf("floppy");
644 term_printf(" removable=%d", bs
->removable
);
646 term_printf(" locked=%d", bs
->locked
);
649 term_printf(" file=%s", bs
->filename
);
650 if (bs
->backing_file
[0] != '\0')
651 term_printf(" backing_file=%s", bs
->backing_file
);
652 term_printf(" ro=%d", bs
->read_only
);
653 term_printf(" drv=%s", bs
->drv
->format_name
);
655 term_printf(" encrypted");
657 term_printf(" [not inserted]");
663 /**************************************************************/
664 /* RAW block driver */
666 typedef struct BDRVRawState
{
670 static int raw_probe(const uint8_t *buf
, int buf_size
, const char *filename
)
672 return 1; /* maybe */
675 static int raw_open(BlockDriverState
*bs
, const char *filename
)
677 BDRVRawState
*s
= bs
->opaque
;
684 struct dk_minfo minfo
;
688 fd
= open(filename
, O_RDWR
| O_BINARY
| O_LARGEFILE
);
690 fd
= open(filename
, O_RDONLY
| O_BINARY
| O_LARGEFILE
);
696 if (!fstat(fd
, &sb
) && (S_IFCHR
& sb
.st_mode
)) {
697 #ifdef DIOCGMEDIASIZE
698 if (ioctl(fd
, DIOCGMEDIASIZE
, (off_t
*)&size
))
701 size
= LONG_LONG_MAX
;
703 size
= lseek(fd
, 0LL, SEEK_END
);
709 * use the DKIOCGMEDIAINFO ioctl to read the size.
711 rv
= ioctl ( fd
, DKIOCGMEDIAINFO
, &minfo
);
713 size
= minfo
.dki_lbsize
* minfo
.dki_capacity
;
714 } else /* there are reports that lseek on some devices
715 fails, but irc discussion said that contingency
716 on contingency was overkill */
719 size
= lseek(fd
, 0, SEEK_END
);
722 /* On Windows hosts it can happen that we're unable to get file size
723 for CD-ROM raw device (it's inherent limitation of the CDFS driver). */
725 size
= LONG_LONG_MAX
;
727 bs
->total_sectors
= size
/ 512;
732 static int raw_read(BlockDriverState
*bs
, int64_t sector_num
,
733 uint8_t *buf
, int nb_sectors
)
735 BDRVRawState
*s
= bs
->opaque
;
738 lseek(s
->fd
, sector_num
* 512, SEEK_SET
);
739 ret
= read(s
->fd
, buf
, nb_sectors
* 512);
740 if (ret
!= nb_sectors
* 512)
745 static int raw_write(BlockDriverState
*bs
, int64_t sector_num
,
746 const uint8_t *buf
, int nb_sectors
)
748 BDRVRawState
*s
= bs
->opaque
;
751 lseek(s
->fd
, sector_num
* 512, SEEK_SET
);
752 ret
= write(s
->fd
, buf
, nb_sectors
* 512);
753 if (ret
!= nb_sectors
* 512)
758 static void raw_close(BlockDriverState
*bs
)
760 BDRVRawState
*s
= bs
->opaque
;
766 #include <winioctl.h>
768 int qemu_ftruncate64(int fd
, int64_t length
)
775 if ((GetVersion() & 0x80000000UL
) && (length
>> 32) != 0)
778 h
= (HANDLE
)_get_osfhandle(fd
);
780 /* get current position, ftruncate do not change position */
782 li
.LowPart
= SetFilePointer (h
, 0, &li
.HighPart
, FILE_CURRENT
);
783 if (li
.LowPart
== 0xffffffffUL
&& GetLastError() != NO_ERROR
)
787 if (!SetFilePointer(h
, (DWORD
) length
, &high
, FILE_BEGIN
))
789 res
= SetEndOfFile(h
);
791 /* back to old position */
792 SetFilePointer(h
, li
.LowPart
, &li
.HighPart
, FILE_BEGIN
);
796 static int set_sparse(int fd
)
799 return (int) DeviceIoControl((HANDLE
)_get_osfhandle(fd
), FSCTL_SET_SPARSE
,
800 NULL
, 0, NULL
, 0, &returned
, NULL
);
803 static inline int set_sparse(int fd
)
809 static int raw_create(const char *filename
, int64_t total_size
,
810 const char *backing_file
, int flags
)
814 if (flags
|| backing_file
)
817 fd
= open(filename
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_BINARY
| O_LARGEFILE
,
822 ftruncate(fd
, total_size
* 512);
827 static void raw_flush(BlockDriverState
*bs
)
829 BDRVRawState
*s
= bs
->opaque
;
833 BlockDriver bdrv_raw
= {
835 sizeof(BDRVRawState
),
847 bdrv_register(&bdrv_raw
);
849 bdrv_register(&bdrv_cow
);
851 bdrv_register(&bdrv_qcow
);
852 bdrv_register(&bdrv_vmdk
);
853 bdrv_register(&bdrv_cloop
);
854 bdrv_register(&bdrv_dmg
);
855 bdrv_register(&bdrv_bochs
);
856 bdrv_register(&bdrv_vpc
);
857 bdrv_register(&bdrv_vvfat
);