From patchwork Mon Mar 21 15:41:28 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Programmingkid X-Patchwork-Id: 8633821 Return-Path: X-Original-To: patchwork-qemu-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id A386A9F372 for ; Mon, 21 Mar 2016 15:41:45 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 6997320320 for ; Mon, 21 Mar 2016 15:41:44 +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 2611620306 for ; Mon, 21 Mar 2016 15:41:43 +0000 (UTC) Received: from localhost ([::1]:58482 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ai1xe-0001OV-KW for patchwork-qemu-devel@patchwork.kernel.org; Mon, 21 Mar 2016 11:41:42 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:40510) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ai1xW-0001O6-81 for qemu-devel@nongnu.org; Mon, 21 Mar 2016 11:41:36 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ai1xT-0005i1-0l for qemu-devel@nongnu.org; Mon, 21 Mar 2016 11:41:34 -0400 Received: from mail-ig0-x244.google.com ([2607:f8b0:4001:c05::244]:36711) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ai1xS-0005hj-Q7; Mon, 21 Mar 2016 11:41:30 -0400 Received: by mail-ig0-x244.google.com with SMTP id kc10so10806310igb.3; Mon, 21 Mar 2016 08:41:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:content-transfer-encoding:subject:date:message-id:to :mime-version; bh=CnCjmr7kqH7EQ5dQ7vlX4uL6aKntv1eIttm1JXHtjkA=; b=dPmY004fXtektoCfHlqHgeB24ZTs22rWWkIIMpI+NDZWEMXjkPENNxiEixh2OkwMNc ub2c4/E0nwErcsXlt1TnhempXNKi9XAIBAWTLk3wpXWf/ozQLLpEJhp3YHRpFVGugt7L 7gaMJJ2TDg7yBMszNrW4Gl8UHzNHgokcIaqovRZSidhakchNFRBMHNuFo21JXjCIAyOT QwKPM5upAthmw9LIOqVd4A44NQzmu34vrfBBpTAwhIKLaKHmg7LuDRAEQnH2oH18kaca 65klxwOOVSp7RXqTMHCtd66sO/6alnfvyHid1XLeOLfKX7z5NdBpb5UA0LgHLnHeQDeT mU+A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:content-transfer-encoding:subject:date :message-id:to:mime-version; bh=CnCjmr7kqH7EQ5dQ7vlX4uL6aKntv1eIttm1JXHtjkA=; b=DXYtXJOLet++/pHk0ZPW90Dd2wAhGYz07xfNoiV21d2vVuvV7B5B7It7jUxhxXppZr qI4eu6rypdWFYszXjepeA/5jcWS3ZaL4urmCIt6mNlVWxMeLicH3inKFxwGidAPKBzXh wvWpIGpb+hPMf2K9sR7Ri7kiaQNmKaobKmzJ+SiAU7Uzoak/SSuTemcWhFMcqxgmoyeE tSY+m2svCTWfgdAZCF1G+tci9DSowbnjuPXkbwqYBm9pUHxeDMPrkaZn/OZkjYI+8ICt 3G5qf9qMeKq+eitqqMPEdAUpoNzp1iP0F2hvJgsC4jCfTRPs6wQ+cu2ihxdbUUvuvUKE nNfA== X-Gm-Message-State: AD7BkJJCw4L9eHu+MUY7E6lq9TQObi1YISVw8z9832DGsWaZ9Qefi1ZP57mfvEMuy5pLeg== X-Received: by 10.50.61.234 with SMTP id t10mr14135994igr.20.1458574889919; Mon, 21 Mar 2016 08:41:29 -0700 (PDT) Received: from [192.168.0.5] (d199-74-164-53.col.wideopenwest.com. [74.199.53.164]) by smtp.gmail.com with ESMTPSA id 12sm11542523iog.21.2016.03.21.08.41.29 (version=TLS1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 21 Mar 2016 08:41:29 -0700 (PDT) From: Programmingkid Date: Mon, 21 Mar 2016 11:41:28 -0400 Message-Id: To: Kevin Wolf , qemu-devel qemu-devel , Qemu-block 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:c05::244 Subject: [Qemu-devel] ping [PATCH v15] 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 http://patchwork.ozlabs.org/patch/591171/ 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 --- Replaced one "return -1" with "return -ENOENT". Replaced another "return -1" with "return ret". Removed trailing whitespace. 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 #include //#include +#include #include #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; }