From patchwork Thu Dec 10 14:39:51 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Programmingkid X-Patchwork-Id: 555166 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 1451C140216 for ; Fri, 11 Dec 2015 01:40:42 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b=dTff1/EN; dkim-atps=neutral Received: from localhost ([::1]:42313 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1a72Od-0000Fg-QK for incoming@patchwork.ozlabs.org; Thu, 10 Dec 2015 09:40:39 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38479) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1a72O5-0007wS-8F for qemu-devel@nongnu.org; Thu, 10 Dec 2015 09:40:09 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1a72O0-00011T-Lk for qemu-devel@nongnu.org; Thu, 10 Dec 2015 09:40:05 -0500 Received: from mail-qg0-x231.google.com ([2607:f8b0:400d:c04::231]:33814) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1a72Nu-0000zD-SX; Thu, 10 Dec 2015 09:39:54 -0500 Received: by qgeb1 with SMTP id b1so145379198qge.1; Thu, 10 Dec 2015 06:39:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:content-type:content-transfer-encoding:subject:date:message-id :cc:to:mime-version; bh=3CR00FiWFh3Pfa9xmL1d8VQrrnPmcXP4iceiTwfyhgI=; b=dTff1/ENhMYKGsStUS8XA4j0UXBn3oBb6Myvdg9o8gfoX14UR6pHDHWLoCCiFE5zGD Guuzp1Y8+JgAEjhV5QfwsieCobUWUmC1urYj67bdgZmMYLRhsiSpGo5CT+xVSLSVaGVI k2kUg5ndiL5yVXwXeYu+3g996iI3Cced8ekDqZuS5lbh1vLaTRPO8tPZsafdcqPsb+UA HK4f5+pEdA5aDdDhtynItm2JGRtjeZHRr1g5y2ViYwF4Ot4n4Q91MFMgrJjLYP8N7bgm YCnb5QD1tV/zfzItUFZ2L4kNF4t6TUzpE7Vyaa/4zwDt7j2bbhv1vBni/se1obcsdrf3 o1UQ== X-Received: by 10.140.239.87 with SMTP id k84mr7318696qhc.87.1449758393938; Thu, 10 Dec 2015 06:39:53 -0800 (PST) Received: from [192.168.0.3] (d199-74-164-53.col.wideopenwest.com. [74.199.53.164]) by smtp.gmail.com with ESMTPSA id f7sm6127316qkb.7.2015.12.10.06.39.52 (version=TLS1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 10 Dec 2015 06:39:52 -0800 (PST) From: Programmingkid Date: Thu, 10 Dec 2015 09:39:51 -0500 Message-Id: <69D59CD8-84A3-4C9E-93F4-D366C412F4C6@gmail.com> To: Kevin Wolf Mime-Version: 1.0 (Apple Message framework v1084) X-Mailer: Apple Mail (2.1084) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2607:f8b0:400d:c04::231 Cc: qemu-devel qemu-devel , Qemu-block Subject: [Qemu-devel] ping [PATCH v11] block/raw-posix.c: Make physical devices usable in QEMU under Mac OS X host X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org https://patchwork.ozlabs.org/patch/550295/ 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. Signed-off-by: John Arbuckle --- error_report()'s had their \n, '.', and "Error:" removed. Indentations are now at the left parenthesis rather than at the 80 character mark. Added spaces between the + sign. block/raw-posix.c | 135 +++++++++++++++++++++++++++++++++++++++-------------- 1 files changed, 99 insertions(+), 36 deletions(-) diff --git a/block/raw-posix.c b/block/raw-posix.c index ccfec1c..39e523b 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -43,6 +43,7 @@ #include #include //#include +#include #include #endif @@ -1975,32 +1976,46 @@ 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 kern_return_t FindEjectableOpticalMedia(io_iterator_t *mediaIterator, + char *mediaType) { kern_return_t kernResult; mach_port_t masterPort; CFMutableDictionaryRef classesToMatch; + const char *matching_array[] = {kIODVDMediaClass, kIOCDMediaClass}; 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); + } + /* If a match was found, leave the loop */ + if (*mediaIterator != 0) { + DPRINTF("Matching using %s\n", matching_array[index]); + snprintf(mediaType, strlen(matching_array[index]) + 1, "%s", + matching_array[index]); + break; + } + } return kernResult; } @@ -2033,7 +2048,35 @@ 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; +} +#endif /* defined(__APPLE__) && defined(__MACH__) */ static int hdev_probe_device(const char *filename) { @@ -2115,6 +2158,17 @@ static bool hdev_is_sg(BlockDriverState *bs) return false; } +/* 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); +} + static int hdev_open(BlockDriverState *bs, QDict *options, int flags, Error **errp) { @@ -2125,30 +2179,32 @@ static int hdev_open(BlockDriverState *bs, QDict *options, int flags, #if defined(__APPLE__) && defined(__MACH__) const char *filename = qdict_get_str(options, "filename"); - if (strstart(filename, "/dev/cdrom", NULL)) { - kern_return_t kernResult; + /* If using a real cdrom */ + if (strcmp(filename, "/dev/cdrom") == 0) { + char bsd_path[MAXPATHLEN]; + char mediaType[11]; /* IODVDMedia is the longest value */ 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)); + FindEjectableOpticalMedia(&mediaIterator, mediaType); + GetBSDPath(mediaIterator, bsd_path, sizeof(bsd_path), flags); + if (mediaIterator) { + IOObjectRelease(mediaIterator); } - if ( mediaIterator ) - IOObjectRelease( mediaIterator ); + /* If a real optical drive was not found */ + if (bsd_path[0] == '\0') { + error_setg(errp, "Failed to obtain bsd path for optical drive"); + return -1; + } + + /* If using a cdrom disc and finding a partition on the disc failed */ + if (strncmp(mediaType, "IOCDMedia", 9) == 0 && + setup_cdrom(bsd_path, errp) == false) { + print_unmounting_directions(bsd_path); + return -1; + } + + filename = bsd_path; + qdict_put(options, "filename", qstring_from_str(filename)); } #endif @@ -2159,9 +2215,16 @@ static int hdev_open(BlockDriverState *bs, QDict *options, int flags, if (local_err) { error_propagate(errp, local_err); } - return ret; } +#if defined(__APPLE__) && defined(__MACH__) + /* if a physical device experienced an error while being opened */ + if (strncmp(filename, "/dev/", 5) == 0 && ret != 0) { + print_unmounting_directions(filename); + return -1; + } +#endif /* defined(__APPLE__) && defined(__MACH__) */ + /* Since this does ioctl the device must be already opened */ bs->sg = hdev_is_sg(bs);