From patchwork Mon Feb 29 15:17:58 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Programmingkid X-Patchwork-Id: 8455071 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 B7E989F52D for ; Mon, 29 Feb 2016 15:18:26 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 7F44820120 for ; Mon, 29 Feb 2016 15:18:25 +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 E1BB520254 for ; Mon, 29 Feb 2016 15:18:16 +0000 (UTC) Received: from localhost ([::1]:37194 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aaPaS-0000WT-4a for patchwork-qemu-devel@patchwork.kernel.org; Mon, 29 Feb 2016 10:18:16 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52211) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aaPaJ-0000WK-H3 for qemu-devel@nongnu.org; Mon, 29 Feb 2016 10:18:09 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1aaPaE-0000Af-F1 for qemu-devel@nongnu.org; Mon, 29 Feb 2016 10:18:07 -0500 Received: from mail-ig0-x243.google.com ([2607:f8b0:4001:c05::243]:35811) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aaPaE-0000AZ-7M; Mon, 29 Feb 2016 10:18:02 -0500 Received: by mail-ig0-x243.google.com with SMTP id ww10so9852583igb.2; Mon, 29 Feb 2016 07:18:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:content-transfer-encoding:date:subject:to:message-id :mime-version; bh=sMSRzpvnb/ArTJysjlWQJBSXM+3l4L+PO04zhdvVCUg=; b=MNMIkQbeJXT1LxrqQZbhfUlQtnVMKquhYUvua+dkbD83k8ots4QYSUYsU1ww3HGQZe L2iGYge8oq1hguqVsHk7ndfH50jL4CVErf+7F31fMu4IxJev+DklQr4SWPIutioNFoj3 s2cQL1RiDk//kykwd2pCdEdJENnbkRCuc4IlsR2KQiuJOUc+duC6vJwQHOrlV6Rw8T5j LMXO/KSW6YQfx7aCo+ToKh0oqh8gnB1uj7msyVg+uHCOmL1MeYLSqriwoli/rUmzlxbN FA9co5F07pYFzeoLhjt4WdTadyj6ANjXNibyUIiyqVEg7hzYjmfJunHm9lKvJOMaWNor Y04A== 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:date:subject:to :message-id:mime-version; bh=sMSRzpvnb/ArTJysjlWQJBSXM+3l4L+PO04zhdvVCUg=; b=AbgRdV+5oKsNBQsLuLh4pWyM8P+jgu25Yh//4VqsOnXT9Ix+fOyzkJJHh2vXjXucfQ +CyovXG0l+CT+GlGjOphUS+lBzNEJeD5dYSlgMkDi/PTwFg9tEnVS/fEXuZlooQEnnwR PHW8ttXjJnKjjiQCG27GkQ1vDm3lGZzd/OiEaBT6WHFJCfVsD+MBdnh/6g9cONo3UmJD JuZwv8zBT5cyUJUoR7e0PG9iqmln8eFfP17N3nVmDXOTg2CXt6dWc7SPkkS6A8OWHC3T gVv7iEOzRkcVHu9XNIEBx/C3IgsKw9DALB63nsniM+6Z+Id+K1qsnf89j3pTY9tl2zZF dyEg== X-Gm-Message-State: AD7BkJKgVJY8CQsmDs241BZNpcKKP+ufzsSsiqcNpr5GU4q61376Uc2QEeACqUXdoGJ6IA== X-Received: by 10.50.141.164 with SMTP id rp4mr10590320igb.89.1456759081497; Mon, 29 Feb 2016 07:18:01 -0800 (PST) Received: from [192.168.0.6] (d199-74-164-53.col.wideopenwest.com. [74.199.53.164]) by smtp.gmail.com with ESMTPSA id n5sm6947039iga.15.2016.02.29.07.18.00 (version=TLS1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 29 Feb 2016 07:18:00 -0800 (PST) From: Programmingkid Date: Mon, 29 Feb 2016 10:17:58 -0500 To: Kevin Wolf , qemu-devel qemu-devel , Qemu-block Message-Id: <3BAC5050-04A8-44DA-B65F-424CFE5615DA@gmail.com> 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::243 Subject: [Qemu-devel] ping [PATCH v14] 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 I do think this patch is ready to be added to QEMU. I have listened to what you said and implemented your changes. https://patchwork.ozlabs.org/patch/579325/ 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 --- Changed filename variable to const char * type. Removed snprintf call for filename variable. filename is set to bsd_path if using a physical device that isn't a DVD or CD. block/raw-posix.c | 167 ++++++++++++++++++++++++++++++++++++++++------------- 1 files changed, 127 insertions(+), 40 deletions(-) diff --git a/block/raw-posix.c b/block/raw-posix.c index 6df3067..48dc5a8 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -44,6 +44,7 @@ #include #include //#include +#include #include #endif @@ -1963,33 +1964,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, @@ -2021,7 +2036,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) { @@ -2112,33 +2166,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 ( mediaIterator ) - IOObjectRelease( mediaIterator ); + /* 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; + } + + qdict_put(options, "filename", qstring_from_str(bsd_path)); + +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; @@ -2147,7 +2225,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 (*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); + return -1; + } +#endif /* defined(__APPLE__) && defined(__MACH__) */ } /* Since this does ioctl the device must be already opened */