[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 07/48] block/raw-posix.c: Make physical devices usabl
From: |
Kevin Wolf |
Subject: |
[Qemu-devel] [PULL 07/48] block/raw-posix.c: Make physical devices usable in QEMU under Mac OS X host |
Date: |
Tue, 29 Mar 2016 17:08:07 +0200 |
From: Programmingkid <address@hidden>
Mac OS X can be picky when it comes to allowing the user
to use physical devices in QEMU. Most mounted volumes
appear to be off limits to QEMU. If an issue is detected,
a message is displayed showing the user how to unmount a
volume. Now QEMU uses both CD and DVD media.
Signed-off-by: John Arbuckle <address@hidden>
Signed-off-by: Kevin Wolf <address@hidden>
---
block/raw-posix.c | 165 +++++++++++++++++++++++++++++++++++++++++-------------
1 file changed, 126 insertions(+), 39 deletions(-)
diff --git a/block/raw-posix.c b/block/raw-posix.c
index 8866121..eb50c02 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -44,6 +44,7 @@
#include <IOKit/storage/IOMedia.h>
#include <IOKit/storage/IOCDMedia.h>
//#include <IOKit/storage/IOCDTypes.h>
+#include <IOKit/storage/IODVDMedia.h>
#include <CoreFoundation/CoreFoundation.h>
#endif
@@ -1965,33 +1966,47 @@ BlockDriver bdrv_file = {
/* host device */
#if defined(__APPLE__) && defined(__MACH__)
-static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator );
static kern_return_t GetBSDPath(io_iterator_t mediaIterator, char *bsdPath,
CFIndex maxPathSize, int flags);
-kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator )
+static char *FindEjectableOpticalMedia(io_iterator_t *mediaIterator)
{
- kern_return_t kernResult;
+ kern_return_t kernResult = KERN_FAILURE;
mach_port_t masterPort;
CFMutableDictionaryRef classesToMatch;
+ const char *matching_array[] = {kIODVDMediaClass, kIOCDMediaClass};
+ char *mediaType = NULL;
kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort );
if ( KERN_SUCCESS != kernResult ) {
printf( "IOMasterPort returned %d\n", kernResult );
}
- classesToMatch = IOServiceMatching( kIOCDMediaClass );
- if ( classesToMatch == NULL ) {
- printf( "IOServiceMatching returned a NULL dictionary.\n" );
- } else {
- CFDictionarySetValue( classesToMatch, CFSTR( kIOMediaEjectableKey ),
kCFBooleanTrue );
- }
- kernResult = IOServiceGetMatchingServices( masterPort, classesToMatch,
mediaIterator );
- if ( KERN_SUCCESS != kernResult )
- {
- printf( "IOServiceGetMatchingServices returned %d\n", kernResult );
- }
+ int index;
+ for (index = 0; index < ARRAY_SIZE(matching_array); index++) {
+ classesToMatch = IOServiceMatching(matching_array[index]);
+ if (classesToMatch == NULL) {
+ error_report("IOServiceMatching returned NULL for %s",
+ matching_array[index]);
+ continue;
+ }
+ CFDictionarySetValue(classesToMatch, CFSTR(kIOMediaEjectableKey),
+ kCFBooleanTrue);
+ kernResult = IOServiceGetMatchingServices(masterPort, classesToMatch,
+ mediaIterator);
+ if (kernResult != KERN_SUCCESS) {
+ error_report("Note: IOServiceGetMatchingServices returned %d",
+ kernResult);
+ continue;
+ }
- return kernResult;
+ /* If a match was found, leave the loop */
+ if (*mediaIterator != 0) {
+ DPRINTF("Matching using %s\n", matching_array[index]);
+ mediaType = g_strdup(matching_array[index]);
+ break;
+ }
+ }
+ return mediaType;
}
kern_return_t GetBSDPath(io_iterator_t mediaIterator, char *bsdPath,
@@ -2023,7 +2038,46 @@ kern_return_t GetBSDPath(io_iterator_t mediaIterator,
char *bsdPath,
return kernResult;
}
-#endif
+/* Sets up a real cdrom for use in QEMU */
+static bool setup_cdrom(char *bsd_path, Error **errp)
+{
+ int index, num_of_test_partitions = 2, fd;
+ char test_partition[MAXPATHLEN];
+ bool partition_found = false;
+
+ /* look for a working partition */
+ for (index = 0; index < num_of_test_partitions; index++) {
+ snprintf(test_partition, sizeof(test_partition), "%ss%d", bsd_path,
+ index);
+ fd = qemu_open(test_partition, O_RDONLY | O_BINARY | O_LARGEFILE);
+ if (fd >= 0) {
+ partition_found = true;
+ qemu_close(fd);
+ break;
+ }
+ }
+
+ /* if a working partition on the device was not found */
+ if (partition_found == false) {
+ error_setg(errp, "Failed to find a working partition on disc");
+ } else {
+ DPRINTF("Using %s as optical disc\n", test_partition);
+ pstrcpy(bsd_path, MAXPATHLEN, test_partition);
+ }
+ return partition_found;
+}
+
+/* Prints directions on mounting and unmounting a device */
+static void print_unmounting_directions(const char *file_name)
+{
+ error_report("If device %s is mounted on the desktop, unmount"
+ " it first before using it in QEMU", file_name);
+ error_report("Command to unmount device: diskutil unmountDisk %s",
+ file_name);
+ error_report("Command to mount device: diskutil mountDisk %s", file_name);
+}
+
+#endif /* defined(__APPLE__) && defined(__MACH__) */
static int hdev_probe_device(const char *filename)
{
@@ -2114,33 +2168,57 @@ static int hdev_open(BlockDriverState *bs, QDict
*options, int flags,
#if defined(__APPLE__) && defined(__MACH__)
const char *filename = qdict_get_str(options, "filename");
+ char bsd_path[MAXPATHLEN] = "";
+ bool error_occurred = false;
+
+ /* If using a real cdrom */
+ if (strcmp(filename, "/dev/cdrom") == 0) {
+ char *mediaType = NULL;
+ kern_return_t ret_val;
+ io_iterator_t mediaIterator = 0;
+
+ mediaType = FindEjectableOpticalMedia(&mediaIterator);
+ if (mediaType == NULL) {
+ error_setg(errp, "Please make sure your CD/DVD is in the optical"
+ " drive");
+ error_occurred = true;
+ goto hdev_open_Mac_error;
+ }
- if (strstart(filename, "/dev/cdrom", NULL)) {
- kern_return_t kernResult;
- io_iterator_t mediaIterator;
- char bsdPath[ MAXPATHLEN ];
- int fd;
-
- kernResult = FindEjectableCDMedia( &mediaIterator );
- kernResult = GetBSDPath(mediaIterator, bsdPath, sizeof(bsdPath),
- flags);
- if ( bsdPath[ 0 ] != '\0' ) {
- strcat(bsdPath,"s0");
- /* some CDs don't have a partition 0 */
- fd = qemu_open(bsdPath, O_RDONLY | O_BINARY | O_LARGEFILE);
- if (fd < 0) {
- bsdPath[strlen(bsdPath)-1] = '1';
- } else {
- qemu_close(fd);
- }
- filename = bsdPath;
- qdict_put(options, "filename", qstring_from_str(filename));
+ ret_val = GetBSDPath(mediaIterator, bsd_path, sizeof(bsd_path), flags);
+ if (ret_val != KERN_SUCCESS) {
+ error_setg(errp, "Could not get BSD path for optical drive");
+ error_occurred = true;
+ goto hdev_open_Mac_error;
+ }
+
+ /* If a real optical drive was not found */
+ if (bsd_path[0] == '\0') {
+ error_setg(errp, "Failed to obtain bsd path for optical drive");
+ error_occurred = true;
+ goto hdev_open_Mac_error;
+ }
+
+ /* If using a cdrom disc and finding a partition on the disc failed */
+ if (strncmp(mediaType, kIOCDMediaClass, 9) == 0 &&
+ setup_cdrom(bsd_path, errp) == false) {
+ print_unmounting_directions(bsd_path);
+ error_occurred = true;
+ goto hdev_open_Mac_error;
}
- if ( mediaIterator )
- IOObjectRelease( mediaIterator );
+ qdict_put(options, "filename", qstring_from_str(bsd_path));
+
+hdev_open_Mac_error:
+ g_free(mediaType);
+ if (mediaIterator) {
+ IOObjectRelease(mediaIterator);
+ }
+ if (error_occurred) {
+ return -ENOENT;
+ }
}
-#endif
+#endif /* defined(__APPLE__) && defined(__MACH__) */
s->type = FTYPE_FILE;
@@ -2149,6 +2227,15 @@ static int hdev_open(BlockDriverState *bs, QDict
*options, int flags,
if (local_err) {
error_propagate(errp, local_err);
}
+#if defined(__APPLE__) && defined(__MACH__)
+ if (*bsd_path) {
+ filename = bsd_path;
+ }
+ /* if a physical device experienced an error while being opened */
+ if (strncmp(filename, "/dev/", 5) == 0) {
+ print_unmounting_directions(filename);
+ }
+#endif /* defined(__APPLE__) && defined(__MACH__) */
return ret;
}
--
1.8.3.1
- [Qemu-devel] [PULL 00/48] Block layer patches, Kevin Wolf, 2016/03/29
- [Qemu-devel] [PULL 01/48] block: Remove bdrv_make_anon(), Kevin Wolf, 2016/03/29
- [Qemu-devel] [PULL 04/48] block: Remove cache.writeback from blockdev-add, Kevin Wolf, 2016/03/29
- [Qemu-devel] [PULL 02/48] block: Remove copy-on-read from bdrv_move_feature_fields(), Kevin Wolf, 2016/03/29
- [Qemu-devel] [PULL 03/48] block: Remove dirty bitmaps from bdrv_move_feature_fields(), Kevin Wolf, 2016/03/29
- [Qemu-devel] [PULL 05/48] block: Make backing files always writeback, Kevin Wolf, 2016/03/29
- [Qemu-devel] [PULL 09/48] block/qapi: make two printf() formats literal, Kevin Wolf, 2016/03/29
- [Qemu-devel] [PULL 11/48] block/qapi: Set s->device in bdrv_query_stats(), Kevin Wolf, 2016/03/29
- [Qemu-devel] [PULL 08/48] block: Remove blk_set_bs(), Kevin Wolf, 2016/03/29
- [Qemu-devel] [PULL 07/48] block/raw-posix.c: Make physical devices usable in QEMU under Mac OS X host,
Kevin Wolf <=
- [Qemu-devel] [PULL 06/48] block: Reject writethrough mode except at the root, Kevin Wolf, 2016/03/29
- [Qemu-devel] [PULL 10/48] block/qapi: fix unbounded stack for dump_qdict, Kevin Wolf, 2016/03/29
- [Qemu-devel] [PULL 14/48] qemu-img/qemu-io: don't prompt for passwords if not required, Kevin Wolf, 2016/03/29
- [Qemu-devel] [PULL 12/48] block/qapi: Pass bdrv_query_blk_stats() s->stats, Kevin Wolf, 2016/03/29
- [Qemu-devel] [PULL 13/48] block: add flag to indicate that no I/O will be performed, Kevin Wolf, 2016/03/29
- [Qemu-devel] [PULL 15/48] tests: redirect stderr to stdout for iotests, Kevin Wolf, 2016/03/29
- [Qemu-devel] [PULL 16/48] tests: refactor python I/O tests helper main method, Kevin Wolf, 2016/03/29
- [Qemu-devel] [PULL 17/48] tests: add output filter to python I/O tests helper, Kevin Wolf, 2016/03/29
- [Qemu-devel] [PULL 18/48] block: add generic full disk encryption driver, Kevin Wolf, 2016/03/29
- [Qemu-devel] [PULL 23/48] replay: fix error message, Kevin Wolf, 2016/03/29