From patchwork Tue Feb 2 17:08:31 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Programmingkid X-Patchwork-Id: 8191941 Return-Path: X-Original-To: patchwork-qemu-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 36A14BEEE5 for ; Tue, 2 Feb 2016 17:09:31 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 077F2202F0 for ; Tue, 2 Feb 2016 17:09:30 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id B55FE202D1 for ; Tue, 2 Feb 2016 17:09:28 +0000 (UTC) Received: from localhost ([::1]:58321 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aQeSG-0005bY-0q for patchwork-qemu-devel@patchwork.kernel.org; Tue, 02 Feb 2016 12:09:28 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:40824) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aQeRY-0004dS-P4 for qemu-devel@nongnu.org; Tue, 02 Feb 2016 12:08:46 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1aQeRX-0001yx-1L for qemu-devel@nongnu.org; Tue, 02 Feb 2016 12:08:44 -0500 Received: from mail-io0-x241.google.com ([2607:f8b0:4001:c06::241]:34571) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aQeRO-0001vj-UU; Tue, 02 Feb 2016 12:08:35 -0500 Received: by mail-io0-x241.google.com with SMTP id k127so1144531iok.1; Tue, 02 Feb 2016 09:08:34 -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 :to:mime-version; bh=m42C2L11L3qgqTqJDuVdyn4NxK9Zt7/gn/EUvhcNeGo=; b=YuwiyEjnjJDEP5bMVXGRqIvU4+0aEa9SDsb7ZQKdP1kreuC63gPVPOf1A1A3nMG3FC iY/3CCS6VEIe0Fme92/x4ZNMNN272Y9FL8KqVYOXmTf1OpKRG5PJsOe7ONqgtyOzeXpP oZ84VlxRQQ+yD8vxnKwVJYq3+GCCMKyI777w1f2ywH4Evlw+2+WWNGqoNB6itMAbHu1c z+tkFJzSxJaFSRmRPbhgPdGVP0qtUdF4Wd5IVsfCs2C/+iRPujzi8JPm0GmsePOIa88m ZHXn8sOmlrHTlwBDwqheyEXEbGGEhPO6V1iNfM+RwUjb6yGbipT7/yF2cj+umdyYidUt NXSA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:content-type:content-transfer-encoding :subject:date:message-id:to:mime-version; bh=m42C2L11L3qgqTqJDuVdyn4NxK9Zt7/gn/EUvhcNeGo=; b=QlcflxtgBlWr7M42ol3OWV9FGbi1QO/Q0HdCYo1jTBuN9DRGYwAdEjIIhwghWE10hE 8FebM+sQG51fLz3vMLXvPfzs7M/wEftswwcpHuB6OonZwHi0Its+wdX3XNd0yKktrn6d 4S029hWPe1Kkty99O9FxR9zuA0j7swwAQZhOenTkwN9kFMNSlrRFTJdP6+4/0BxlpzcQ 1fAJ2KD0565UCMdl9FW0mRK4iClHLJ1DCdpu9nCJ8enl3ucxI7YJ4FiF+K0+3HuQF+dW RNPOXAxsXBin1DP/wicYfyTeuxsr/o7t385BQncKAszD9EmAhOzQ28MWmD6N/CM46hC0 hYLg== X-Gm-Message-State: AG10YORGPWpJ3/GYdkOEzH/WBigbLi75p1T9evoqZFXvYs1Aw/9MTnLCApK0zIusZWLJdw== X-Received: by 10.107.154.79 with SMTP id c76mr29047331ioe.53.1454432914173; Tue, 02 Feb 2016 09:08:34 -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 mu8sm6541045igb.16.2016.02.02.09.08.32 (version=TLS1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 02 Feb 2016 09:08:32 -0800 (PST) From: Programmingkid Date: Tue, 2 Feb 2016 12:08:31 -0500 Message-Id: <1CF37786-9AAA-4E5E-B571-DE20E7A463EB@gmail.com> To: Kevin Wolf , Qemu-block , qemu-devel qemu-devel 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:4001:c06::241 Subject: [Qemu-devel] ping: [PATCH v13] 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+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP https://patchwork.ozlabs.org/patch/570128/ 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 --- Added continue statement to the kernResult != KERN_SUCCESS if condition in FindEjectableCDMedia(). Moved print_unmounting_directions() to only compile under Mac OS X. Fixed indentation of "setup_cdrom(bsd_path, errp) == false) {". Replaced IOCDMedia with kIOCDMediaClass. Changed filename variable to a character array. Changed how filename was set to bsd_path's value by using snprintf(). Removed "goto continue_as_normal" code. Added error_occurred variable. Moved "if (strncmp(filename, "/dev/", 5) == 0 && ret != 0)" code to inside of "if (ret < 0)" block. block/raw-posix.c | 169 ++++++++++++++++++++++++++++++++++++++++------------- 1 files changed, 127 insertions(+), 42 deletions(-) diff --git a/block/raw-posix.c b/block/raw-posix.c index 076d070..67dc166 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -43,6 +43,7 @@ #include #include //#include +#include #include #endif @@ -1971,33 +1972,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, @@ -2029,7 +2044,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) { @@ -2119,34 +2173,59 @@ static int hdev_open(BlockDriverState *bs, QDict *options, int flags, int ret; #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)); + char filename[MAXPATHLEN]; + bool error_occurred = false; + snprintf(filename, MAXPATHLEN, "%s", qdict_get_str(options, "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"); + error_occurred = true; + 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"); + 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 ); + snprintf(filename, MAXPATHLEN, "%s", bsd_path); + qdict_put(options, "filename", qstring_from_str(filename)); + +hdev_open_Mac_error: + g_free(mediaType); + if (mediaIterator) { + IOObjectRelease(mediaIterator); + } + if (error_occurred) { + return -1; + } } -#endif +#endif /* defined(__APPLE__) && defined(__MACH__) */ s->type = FTYPE_FILE; @@ -2155,7 +2234,13 @@ 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) { + print_unmounting_directions(filename); + return -1; + } +#endif /* defined(__APPLE__) && defined(__MACH__) */ } /* Since this does ioctl the device must be already opened */