X-Git-Url: http://vcs.maemo.org/git/?a=blobdiff_plain;f=block.c;h=b9081671862f580ec245cf202fbf8040565ead8e;hb=7ef4da1c3a753888e2678388150f1b846b025168;hp=cbe07a9d8f6035edd060f2c1d0d54284ae8b598c;hpb=7674e7bf08c0be8e6872f8602e2d875b3efb6903;p=qemu diff --git a/block.c b/block.c index cbe07a9..b908167 100644 --- a/block.c +++ b/block.c @@ -32,9 +32,83 @@ #include #endif +#ifdef CONFIG_COCOA +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#endif + +#ifdef __sun__ +#include +#endif + static BlockDriverState *bdrv_first; static BlockDriver *first_drv; +#ifdef CONFIG_COCOA +static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator ); +static kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize ); + +kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator ) +{ + kern_return_t kernResult; + mach_port_t masterPort; + CFMutableDictionaryRef classesToMatch; + + 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 ); + } + + return kernResult; +} + +kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize ) +{ + io_object_t nextMedia; + kern_return_t kernResult = KERN_FAILURE; + *bsdPath = '\0'; + nextMedia = IOIteratorNext( mediaIterator ); + if ( nextMedia ) + { + CFTypeRef bsdPathAsCFString; + bsdPathAsCFString = IORegistryEntryCreateCFProperty( nextMedia, CFSTR( kIOBSDNameKey ), kCFAllocatorDefault, 0 ); + if ( bsdPathAsCFString ) { + size_t devPathLength; + strcpy( bsdPath, _PATH_DEV ); + strcat( bsdPath, "r" ); + devPathLength = strlen( bsdPath ); + if ( CFStringGetCString( bsdPathAsCFString, bsdPath + devPathLength, maxPathSize - devPathLength, kCFStringEncodingASCII ) ) { + kernResult = KERN_SUCCESS; + } + CFRelease( bsdPathAsCFString ); + } + IOObjectRelease( nextMedia ); + } + + return kernResult; +} + +#endif + void bdrv_register(BlockDriver *bdrv) { bdrv->next = first_drv; @@ -80,13 +154,19 @@ int bdrv_create(BlockDriver *drv, } #ifdef _WIN32 -static void get_tmp_filename(char *filename, int size) +void get_tmp_filename(char *filename, int size) { + char* p = strrchr(filename, '/'); + + if (p == NULL) + return; + /* XXX: find a better function */ - tmpnam(filename); + tmpnam(p); + *p = '/'; } #else -static void get_tmp_filename(char *filename, int size) +void get_tmp_filename(char *filename, int size) { int fd; /* XXX: race condition possible */ @@ -106,26 +186,35 @@ static BlockDriver *find_image_format(const char *filename) size_t bufsize = 1024; fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE); - if (fd < 0) - return NULL; + if (fd < 0) { + buf = NULL; + ret = 0; + } else { #ifdef DIOCGSECTORSIZE - { - unsigned int sectorsize = 512; - if (!ioctl(fd, DIOCGSECTORSIZE, §orsize) && - sectorsize > bufsize) - bufsize = sectorsize; - } + { + unsigned int sectorsize = 512; + if (!ioctl(fd, DIOCGSECTORSIZE, §orsize) && + sectorsize > bufsize) + bufsize = sectorsize; + } #endif - buf = malloc(bufsize); - if (!buf) - return NULL; - ret = read(fd, buf, bufsize); - if (ret < 0) { +#ifdef CONFIG_COCOA + u_int32_t blockSize = 512; + if ( !ioctl( fd, DKIOCGETBLOCKSIZE, &blockSize ) && blockSize > bufsize) { + bufsize = blockSize; + } +#endif + buf = qemu_malloc(bufsize); + if (!buf) + return NULL; + ret = read(fd, buf, bufsize); + if (ret < 0) { + close(fd); + qemu_free(buf); + return NULL; + } close(fd); - free(buf); - return NULL; } - close(fd); drv = NULL; score_max = 0; @@ -136,12 +225,38 @@ static BlockDriver *find_image_format(const char *filename) drv = drv1; } } - free(buf); + qemu_free(buf); return drv; } int bdrv_open(BlockDriverState *bs, const char *filename, int snapshot) { +#ifdef CONFIG_COCOA + if ( strncmp( filename, "/dev/cdrom", 10 ) == 0 ) { + kern_return_t kernResult; + io_iterator_t mediaIterator; + char bsdPath[ MAXPATHLEN ]; + int fd; + + kernResult = FindEjectableCDMedia( &mediaIterator ); + kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof( bsdPath ) ); + + if ( bsdPath[ 0 ] != '\0' ) { + strcat(bsdPath,"s0"); + /* some CDs don't have a partition 0 */ + fd = open(bsdPath, O_RDONLY | O_BINARY | O_LARGEFILE); + if (fd < 0) { + bsdPath[strlen(bsdPath)-1] = '1'; + } else { + close(fd); + } + filename = bsdPath; + } + + if ( mediaIterator ) + IOObjectRelease( mediaIterator ); + } +#endif return bdrv_open2(bs, filename, snapshot, NULL); } @@ -154,7 +269,7 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int snapshot, bs->read_only = 0; bs->is_temporary = 0; bs->encrypted = 0; - + if (snapshot) { BlockDriverState *bs1; int64_t total_size; @@ -183,7 +298,7 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int snapshot, filename = tmp_filename; bs->is_temporary = 1; } - + pstrcpy(bs->filename, sizeof(bs->filename), filename); if (!drv) { drv = find_image_format(filename); @@ -289,6 +404,10 @@ int bdrv_commit(BlockDriverState *bs) i += n; } } + + if (bs->drv->bdrv_make_empty) + return bs->drv->bdrv_make_empty(bs); + return 0; } @@ -339,6 +458,9 @@ int bdrv_write(BlockDriverState *bs, int64_t sector_num, return -1; if (bs->read_only) return -1; + if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) { + memcpy(bs->boot_sector_data, buf, 512); + } return bs->drv->bdrv_write(bs, sector_num, buf, nb_sectors); } @@ -530,7 +652,6 @@ void bdrv_info(void) } } - /**************************************************************/ /* RAW block driver */ @@ -548,6 +669,13 @@ static int raw_open(BlockDriverState *bs, const char *filename) BDRVRawState *s = bs->opaque; int fd; int64_t size; +#ifdef _BSD + struct stat sb; +#endif +#ifdef __sun__ + struct dk_minfo minfo; + int rv; +#endif fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE); if (fd < 0) { @@ -557,15 +685,28 @@ static int raw_open(BlockDriverState *bs, const char *filename) bs->read_only = 1; } #ifdef _BSD - { - struct stat sb; - if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) { + if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) { #ifdef DIOCGMEDIASIZE - if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size)) + if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size)) +#endif +#ifdef CONFIG_COCOA + size = LONG_LONG_MAX; +#else + size = lseek(fd, 0LL, SEEK_END); #endif - size = lseek(fd, 0LL, SEEK_END); } else #endif +#ifdef __sun__ + /* + * use the DKIOCGMEDIAINFO ioctl to read the size. + */ + rv = ioctl ( fd, DKIOCGMEDIAINFO, &minfo ); + if ( rv != -1 ) { + size = minfo.dki_lbsize * minfo.dki_capacity; + } else /* there are reports that lseek on some devices + fails, but irc discussion said that contingency + on contingency was overkill */ +#endif { size = lseek(fd, 0, SEEK_END); } @@ -651,4 +792,6 @@ void bdrv_init(void) bdrv_register(&bdrv_cloop); bdrv_register(&bdrv_dmg); bdrv_register(&bdrv_bochs); + bdrv_register(&bdrv_vpc); + bdrv_register(&bdrv_vvfat); }