On 07/07/2015 19:33, Programmingkid wrote: > Make physical devices like a USB flash drive or a CDROM drive work in > QEMU. With > this patch I can use a USB flash drive like a hard drive. Before this > patch, > QEMU would just quit with a message like "resource busy". Now it handles > issues > like these for the user. This patch unmounts volumes of physical devices > before > using them in QEMU. When QEMU quits, the physical devices are mounted again > for the user. The user can find out which device files to use for their > physical > devices by running the mount command in the terminal. This patch makes > "qemu-system-ppc -cdrom /dev/cdrom" work again on Mac OS X. > > Signed-off-by: John Arbuckle <programmingk...@gmail.com > <mailto:programmingk...@gmail.com>>
Two comments: - you should not mix several fixes in one patch (raw block device management, partition seek, unmount/mount cdrom...) - according to Stefan answer, I think you should not unmount the CDROM but you should inform the user he must unmount it manually to be able to use it. Laurent > --- > block/raw-posix.c | 155 > ++++++++++++++++++++++++++++++++++++++++++++-------- > 1 files changed, 131 insertions(+), 24 deletions(-) > > diff --git a/block/raw-posix.c b/block/raw-posix.c > index cbe6574..af0981a 100644 > --- a/block/raw-posix.c > +++ b/block/raw-posix.c > @@ -42,9 +42,10 @@ > #include <IOKit/storage/IOMediaBSDClient.h> > #include <IOKit/storage/IOMedia.h> > #include <IOKit/storage/IOCDMedia.h> > -//#include <IOKit/storage/IOCDTypes.h> > #include <CoreFoundation/CoreFoundation.h> > -#endif > +#include <sys/syslimits.h> > +#include <fcntl.h> > +#endif /* (__APPLE__) && (__MACH__) */ > > > > #ifdef __sun__ > #define _POSIX_PTHREAD_SEMANTICS 1 > @@ -162,6 +163,25 @@ typedef struct BDRVRawState { > bool needs_alignment; > } BDRVRawState; > > > > +#ifdef __APPLE__ > + > +#define MAX_NUM_DEVICES 7 > + > +/* > + * Keeps track of devices that need to be mounted > + * when QEMU exists. > + */ > +typedef struct { > + int fd; > + char filePath[MAXPATHLEN]; > +} PhysicalDevice; > + > +PhysicalDevice deviceArray[MAX_NUM_DEVICES]; > +int numberOfDevices; > + > +#endif /* __APPLE__ */ > + > + > typedef struct BDRVRawReopenState { > int fd; > int open_flags; > @@ -1972,8 +1992,10 @@ 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 ); > +static kern_return_t FindEjectableCDMedia(io_iterator_t *mediaIterator); > +static kern_return_t GetBSDPath(io_iterator_t mediaIterator, char *bsdPath, > + CFIndex maxPathSize, int flags); > +void mountDevice(void); > > > > kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator ) > { > @@ -2001,7 +2023,8 @@ kern_return_t FindEjectableCDMedia( io_iterator_t > *mediaIterator ) > return kernResult; > } > > > > -kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, > CFIndex maxPathSize ) > +kern_return_t GetBSDPath(io_iterator_t mediaIterator, char *bsdPath, > + CFIndex maxPathSize, int flags) > { > io_object_t nextMedia; > kern_return_t kernResult = KERN_FAILURE; > @@ -2014,7 +2037,9 @@ kern_return_t GetBSDPath( io_iterator_t > mediaIterator, char *bsdPath, CFIndex ma > if ( bsdPathAsCFString ) { > size_t devPathLength; > strcpy( bsdPath, _PATH_DEV ); > - strcat( bsdPath, "r" ); > + if (flags & BDRV_O_NOCACHE) { > + strcat(bsdPath, "r"); > + } > devPathLength = strlen( bsdPath ); > if ( CFStringGetCString( bsdPathAsCFString, bsdPath + > devPathLength, maxPathSize - devPathLength, kCFStringEncodingASCII ) ) { > kernResult = KERN_SUCCESS; > @@ -2027,7 +2052,54 @@ kern_return_t GetBSDPath( io_iterator_t > mediaIterator, char *bsdPath, CFIndex ma > return kernResult; > } > > > > -#endif > +/* Mounts unmounted devices onto host computer's desktop */ > +void mountDevice(void) > +{ > + char commandBuffer[MAXPATHLEN]; > + int result, index; > + > + for (index = 0; index < numberOfDevices; index++) { > + qemu_close(deviceArray[index].fd); > + sprintf(commandBuffer, "diskutil mountDisk %s", > + > deviceArray[index].filePath); > + DPRINTF("Issuing command: %s\n", commandBuffer); > + result = system(commandBuffer); > + if (result != 0) { > + printf("Warning: problem detected while mounting %s\n", > + > deviceArray[index].filePath); > + } > + } > +} > + > +/* Sets up a real cdrom for use in QEMU */ > +static void setupCDROM(char *bsdPath) > +{ > + int index, numOfTestPartitions = 2, fd; > + char testPartition[MAXPATHLEN]; > + bool partitionFound = false; > + > + /* look for a working partition */ > + for (index = 0; index < numOfTestPartitions; index++) { > + strcpy(testPartition, bsdPath); > + sprintf(testPartition, "%ss%d", testPartition, index); > + fd = qemu_open(testPartition, O_RDONLY | O_BINARY | O_LARGEFILE); > + if (fd > 0) { > + partitionFound = true; > + qemu_close(fd); > + break; > + } > + } > + > + /* if a working partition on the device was found */ > + if (partitionFound == false) { > + printf("Error: Failed to find a working partition on CD!\n"); > + exit(EXIT_FAILURE); > + } > + > + strcpy(bsdPath, testPartition); > +} > + > +#endif /* defined(__APPLE__) && defined(__MACH__) */ > > > > static int hdev_probe_device(const char *filename) > { > @@ -2119,30 +2191,52 @@ 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; > + /* If using a physical device */ > + if (strstart(filename, "/dev/", NULL)) { > char bsdPath[ MAXPATHLEN ]; > - int fd; > > > > - kernResult = FindEjectableCDMedia( &mediaIterator ); > - kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof( > bsdPath ) ); > + /* If the physical device is a cdrom */ > + if (strcmp(filename, "/dev/cdrom") == 0) { > + io_iterator_t mediaIterator; > + FindEjectableCDMedia(&mediaIterator); > + GetBSDPath(mediaIterator, bsdPath, sizeof(bsdPath), flags); > + if (mediaIterator) { > + IOObjectRelease(mediaIterator); > + } > + } > > > > - 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); > + /* If the physical device is something else */ > + else { > + strcpy(bsdPath, filename); > + } > + > + /* if accessing a buffered device */ > + if ((flags & BDRV_O_NOCACHE) == 0) { > + /* > + * Unmount the device from the desktop before > + * using the buffered device. A resource busy error > + * would happen if we don't. > + */ > + char commandBuffer[MAXPATHLEN]; > + int result; > + sprintf(commandBuffer, "diskutil unmountDisk %s", bsdPath); > + DPRINTF("Issuing command: %s\n", commandBuffer); > + result = system(commandBuffer); > + if (result != 0) { > + printf("Warning: problem detected while unmounting %s\n", > + > bsdPath); > } > + } > + > + atexit(mountDevice); > + > + /* Setup a CDROM device if found */ > + if (bsdPath[0] != '\0' && (strcmp(filename, "/dev/cdrom") == 0)) { > + setupCDROM(bsdPath); > + DPRINTF("Using %s as CDROM\n", bsdPath); > filename = bsdPath; > qdict_put(options, "filename", qstring_from_str(filename)); > } > - > - if ( mediaIterator ) > - IOObjectRelease( mediaIterator ); > } > #endif > > > > @@ -2156,6 +2250,19 @@ static int hdev_open(BlockDriverState *bs, QDict > *options, int flags, > return ret; > } > > > > +#ifdef __APPLE__ > + > + /* Add the fd to the fd array for mounting at exit */ > + if (strncmp(filename, "/dev/", 5) == 0) { > + int mountFD = ((BDRVRawState *) bs->opaque)->fd; > + DPRINTF("Queuing %s (fd: %d) for mounting at exit\n", > + filename, > mountFD); > + deviceArray[numberOfDevices].fd = mountFD; > + strcpy(deviceArray[numberOfDevices++].filePath, filename); > + } > + > +#endif /* __APPLE__ */ > + > /* Since this does ioctl the device must be already opened */ > bs->sg = hdev_is_sg(bs); > > > > -- > 1.7.5.4 >