qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [Qemu-block] ping [PATCH v11] block/raw-posix.c: Make p


From: Jeff Cody
Subject: Re: [Qemu-devel] [Qemu-block] ping [PATCH v11] block/raw-posix.c: Make physical devices usable in QEMU under Mac OS X host
Date: Fri, 11 Dec 2015 17:00:53 -0500
User-agent: Mutt/1.5.21 (2010-09-15)

On Thu, Dec 10, 2015 at 09:39:51AM -0500, Programmingkid wrote:
> 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.
>

This commit message doesn't seem to really match the patch; it is more
than just a message displayed to the user.  For instance, before it
looked for just kIOCDMediaClass - now, it searches for kIOCDMediaClass
and kIODVDMediaClass.

> Signed-off-by: John Arbuckle <address@hidden>
> 
> ---
> 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.
>

Also, this patch seems garbled.  When saved via Mutt, or when I view
it "raw", there are '=20" and '=3D' all around, a sure sign that it is
(or once was) not plaintext.

I recommend using git format-patch [1] and git send-email [1] to
create and send patches - it'll do the Right Thing.

>  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 <IOKit/storage/IOMedia.h>
>  #include <IOKit/storage/IOCDMedia.h>
>  //#include <IOKit/storage/IOCDTypes.h>
> +#include <IOKit/storage/IODVDMedia.h>
>  #include <CoreFoundation/CoreFoundation.h>
>  #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) {

Since mediaIterator was not ever initialized in hdev_open, we can't
assume the value of mediaIterator as being 0 after kernResult !=
KERN_SUCCESS, can we?  A quick google search [3] shows it ambiguous, so
best initialize mediaIterator down below...


> +            DPRINTF("Matching using %s\n", matching_array[index]);
> +            snprintf(mediaType, strlen(matching_array[index]) + 1, "%s",
> +                     matching_array[index]);

Just use g_strdup().

We use snprintf here, with a size limit of the string referenced in
the array, which references a string defined in an OS X system header...

> +            break;
> +        }
> +    }
>      return kernResult;

You may return garbage here, because kernResult is never initialized,
and your for() loop short circuits on a NULL return from
IOServiceMatching().  Does this compile with our flags?  I don't have
OS X so I can't try it, but I thought at least with gcc and -werror, a
possible uninitialized usage would be flagged.

>  }
>  
> @@ -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;

What is the magic of 2 test partitions?

> +    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);

In OS X, is MAXPATHLEN including the terminating NULL?

> +    }
> +    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 */

... yet here we just hard code the array size to 11, which is prone to
an error later on by either a change in the system header (not very
likely, but possible), or by expanding the media types we support in
the future.

Just bypass that fragility, and use g_strdup() (and later g_free()),
so we are impervious to the exact string size.  You'll likely want a
common exit for the g_free() call.

>          io_iterator_t mediaIterator;

...Given your usage of mediaIterator, I think you need to initialize it
to 0 here.

> -        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);

Return value ignored here, don't ignore it.

> +        GetBSDPath(mediaIterator, bsd_path, sizeof(bsd_path), flags);

Return value ignored here, don't ignore it.

> +        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;

Spurious line delete?

>      }
>  
> +#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);
>  
> -- 
> 1.7.5.4
> 
> 
>

[1] https://git-scm.com/docs/git-format-patch
[2] https://git-scm.com/docs/git-send-email
[3] 
https://developer.apple.com/library/mac/documentation/IOKit/Reference/IOKitLib_header_reference/index.html#//apple_ref/doc/c_ref/IOServiceGetMatchingServices



reply via email to

[Prev in Thread] Current Thread [Next in Thread]