From patchwork Sat Dec 12 03:27:35 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Programmingkid X-Patchwork-Id: 555945 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 D9EBE1402A9 for ; Sat, 12 Dec 2015 14:28:03 +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=rHuC9e6N; dkim-atps=neutral Received: from localhost ([::1]:50373 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1a7aqn-0003VY-Pk for incoming@patchwork.ozlabs.org; Fri, 11 Dec 2015 22:28:01 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52106) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1a7aqU-000371-LX for qemu-devel@nongnu.org; Fri, 11 Dec 2015 22:27:44 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1a7aqR-000205-E7 for qemu-devel@nongnu.org; Fri, 11 Dec 2015 22:27:42 -0500 Received: from mail-qg0-x233.google.com ([2607:f8b0:400d:c04::233]:34226) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1a7aqR-000201-8J; Fri, 11 Dec 2015 22:27:39 -0500 Received: by qgz52 with SMTP id 52so25036152qgz.1; Fri, 11 Dec 2015 19:27:38 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=subject:mime-version:content-type:from:in-reply-to:date:cc :content-transfer-encoding:message-id:references:to; bh=rqnZvWn4Y1yFzGuAgNZqKy/MGRnlMAsSPCa7S+XKz2g=; b=rHuC9e6NEQ2QIPUOOyfzzYKg/mnC+FOxOoUkyYdsy0Zjkp/9Sltxemg9E0KDKPTdSI 5uA31YePGIu6Nlw+ErrQDx2XOm0SC8EUJAWzpLONcWcxUNrtccJYzVvtErSNvsFBjiDN uxe4FmasroajE2z/j/ClGl/9CeiLH+F6CjGPeSz66/2V9J04jpFIzcsr2jAy4gNptxMa 66rZOKn5yNbCQlqFEV9ofiuuepcVNoJu+gHly9rF4gkuqpl9tQ/AWpAfpddG5p7zvbUB 6FHHwNKJ0k34rEvIH/VKg0pTOHGFfe16W6tlC5VJVFT8AGMfUziroZDkGRDOEEQhAQCn fvVg== X-Received: by 10.140.104.167 with SMTP id a36mr26518310qgf.19.1449890858875; Fri, 11 Dec 2015 19:27:38 -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 129sm7960283qho.28.2015.12.11.19.27.37 (version=TLS1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 11 Dec 2015 19:27:37 -0800 (PST) Mime-Version: 1.0 (Apple Message framework v1084) From: Programmingkid In-Reply-To: <20151211220053.GA30085@localhost.localdomain> Date: Fri, 11 Dec 2015 22:27:35 -0500 Message-Id: <56307511-53E2-4B28-BCF5-423DCDABD0FC@gmail.com> References: <69D59CD8-84A3-4C9E-93F4-D366C412F4C6@gmail.com> <20151211220053.GA30085@localhost.localdomain> To: Jeff Cody 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::233 Cc: Kevin Wolf , qemu-devel qemu-devel , Qemu-block Subject: [Qemu-devel] [PATCH v12] 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 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 --- Removed mediaType parameter from FindEjectableOpticalMedia(). Added goto statements to hdev_open. Replaced snprintf() with g_strdup() in FindEjectableOpticalMedia(). Put back return statement in hdev_open for Linux compatibility. block/raw-posix.c | 163 ++++++++++++++++++++++++++++++++++++++++------------- 1 files changed, 124 insertions(+), 39 deletions(-) diff --git a/block/raw-posix.c b/block/raw-posix.c index d9162fd..82e8e62 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -43,6 +43,7 @@ #include #include //#include +#include #include #endif @@ -1975,33 +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 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); + } - 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, @@ -2033,7 +2047,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 +2157,16 @@ 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,32 +2177,55 @@ 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; - 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)); + /* If using a real cdrom */ + if (strcmp(filename, "/dev/cdrom") == 0) { + char bsd_path[MAXPATHLEN]; + 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"); + goto hdev_open_Mac_error; + } + + 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"); + 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"); + goto hdev_open_Mac_error; + } + + /* 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); + goto hdev_open_Mac_error; } - if ( mediaIterator ) - IOObjectRelease( mediaIterator ); + g_free(mediaType); + filename = bsd_path; + qdict_put(options, "filename", qstring_from_str(filename)); + goto continue_as_normal; /* skip over error handling code */ + + /* If an error occurred above */ + hdev_open_Mac_error: + if (mediaIterator) { + IOObjectRelease(mediaIterator); + } + g_free(mediaType); + return -1; + + continue_as_normal: ; } -#endif +#endif /* defined(__APPLE__) && defined(__MACH__) */ s->type = FTYPE_FILE; @@ -2159,8 +2234,18 @@ static int hdev_open(BlockDriverState *bs, QDict *options, int flags, if (local_err) { error_propagate(errp, local_err); } + #if !defined(__APPLE__) && !defined(__MACH__) return ret; + #endif /* !defined(__APPLE__) && !defined(__MACH__) */ + } + +#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);