File:  [Qemu by Fabrice Bellard] / qemu / block.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 16:38:32 2018 UTC (19 months, 2 weeks ago) by root
Branches: qemu, MAIN
CVS tags: qemu0080, HEAD
qemu 0.8.0

    1: /*
    2:  * QEMU System Emulator block driver
    3:  * 
    4:  * Copyright (c) 2003 Fabrice Bellard
    5:  * 
    6:  * Permission is hereby granted, free of charge, to any person obtaining a copy
    7:  * of this software and associated documentation files (the "Software"), to deal
    8:  * in the Software without restriction, including without limitation the rights
    9:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   10:  * copies of the Software, and to permit persons to whom the Software is
   11:  * furnished to do so, subject to the following conditions:
   12:  *
   13:  * The above copyright notice and this permission notice shall be included in
   14:  * all copies or substantial portions of the Software.
   15:  *
   16:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   17:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   18:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   19:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   20:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   21:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   22:  * THE SOFTWARE.
   23:  */
   24: #include "vl.h"
   25: #include "block_int.h"
   26: 
   27: #ifdef _BSD
   28: #include <sys/types.h>
   29: #include <sys/stat.h>
   30: #include <sys/ioctl.h>
   31: #include <sys/queue.h>
   32: #include <sys/disk.h>
   33: #endif
   34: 
   35: #ifdef CONFIG_COCOA
   36: #include <paths.h>
   37: #include <sys/param.h>
   38: #include <IOKit/IOKitLib.h>
   39: #include <IOKit/IOBSD.h>
   40: #include <IOKit/storage/IOMediaBSDClient.h>
   41: #include <IOKit/storage/IOMedia.h>
   42: #include <IOKit/storage/IOCDMedia.h>
   43: //#include <IOKit/storage/IOCDTypes.h>
   44: #include <CoreFoundation/CoreFoundation.h>
   45: #endif
   46: 
   47: static BlockDriverState *bdrv_first;
   48: static BlockDriver *first_drv;
   49: 
   50: #ifdef CONFIG_COCOA
   51: static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator );
   52: static kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize );
   53: 
   54: kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator )
   55: {
   56:     kern_return_t       kernResult; 
   57:     mach_port_t     masterPort;
   58:     CFMutableDictionaryRef  classesToMatch;
   59: 
   60:     kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort );
   61:     if ( KERN_SUCCESS != kernResult ) {
   62:         printf( "IOMasterPort returned %d\n", kernResult );
   63:     }
   64:     
   65:     classesToMatch = IOServiceMatching( kIOCDMediaClass ); 
   66:     if ( classesToMatch == NULL ) {
   67:         printf( "IOServiceMatching returned a NULL dictionary.\n" );
   68:     } else {
   69:     CFDictionarySetValue( classesToMatch, CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue );
   70:     }
   71:     kernResult = IOServiceGetMatchingServices( masterPort, classesToMatch, mediaIterator );
   72:     if ( KERN_SUCCESS != kernResult )
   73:     {
   74:         printf( "IOServiceGetMatchingServices returned %d\n", kernResult );
   75:     }
   76:     
   77:     return kernResult;
   78: }
   79: 
   80: kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize )
   81: {
   82:     io_object_t     nextMedia;
   83:     kern_return_t   kernResult = KERN_FAILURE;
   84:     *bsdPath = '\0';
   85:     nextMedia = IOIteratorNext( mediaIterator );
   86:     if ( nextMedia )
   87:     {
   88:         CFTypeRef   bsdPathAsCFString;
   89:     bsdPathAsCFString = IORegistryEntryCreateCFProperty( nextMedia, CFSTR( kIOBSDNameKey ), kCFAllocatorDefault, 0 );
   90:         if ( bsdPathAsCFString ) {
   91:             size_t devPathLength;
   92:             strcpy( bsdPath, _PATH_DEV );
   93:             strcat( bsdPath, "r" );
   94:             devPathLength = strlen( bsdPath );
   95:             if ( CFStringGetCString( bsdPathAsCFString, bsdPath + devPathLength, maxPathSize - devPathLength, kCFStringEncodingASCII ) ) {
   96:                 kernResult = KERN_SUCCESS;
   97:             }
   98:             CFRelease( bsdPathAsCFString );
   99:         }
  100:         IOObjectRelease( nextMedia );
  101:     }
  102:     
  103:     return kernResult;
  104: }
  105: 
  106: #endif
  107: 
  108: void bdrv_register(BlockDriver *bdrv)
  109: {
  110:     bdrv->next = first_drv;
  111:     first_drv = bdrv;
  112: }
  113: 
  114: /* create a new block device (by default it is empty) */
  115: BlockDriverState *bdrv_new(const char *device_name)
  116: {
  117:     BlockDriverState **pbs, *bs;
  118: 
  119:     bs = qemu_mallocz(sizeof(BlockDriverState));
  120:     if(!bs)
  121:         return NULL;
  122:     pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
  123:     if (device_name[0] != '\0') {
  124:         /* insert at the end */
  125:         pbs = &bdrv_first;
  126:         while (*pbs != NULL)
  127:             pbs = &(*pbs)->next;
  128:         *pbs = bs;
  129:     }
  130:     return bs;
  131: }
  132: 
  133: BlockDriver *bdrv_find_format(const char *format_name)
  134: {
  135:     BlockDriver *drv1;
  136:     for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
  137:         if (!strcmp(drv1->format_name, format_name))
  138:             return drv1;
  139:     }
  140:     return NULL;
  141: }
  142: 
  143: int bdrv_create(BlockDriver *drv, 
  144:                 const char *filename, int64_t size_in_sectors,
  145:                 const char *backing_file, int flags)
  146: {
  147:     if (!drv->bdrv_create)
  148:         return -ENOTSUP;
  149:     return drv->bdrv_create(filename, size_in_sectors, backing_file, flags);
  150: }
  151: 
  152: #ifdef _WIN32
  153: void get_tmp_filename(char *filename, int size)
  154: {
  155:     char* p = strrchr(filename, '/');
  156: 
  157:     if (p == NULL)
  158: 	return;
  159: 
  160:     /* XXX: find a better function */
  161:     tmpnam(p);
  162:     *p = '/';
  163: }
  164: #else
  165: void get_tmp_filename(char *filename, int size)
  166: {
  167:     int fd;
  168:     /* XXX: race condition possible */
  169:     pstrcpy(filename, size, "/tmp/vl.XXXXXX");
  170:     fd = mkstemp(filename);
  171:     close(fd);
  172: }
  173: #endif
  174: 
  175: /* XXX: force raw format if block or character device ? It would
  176:    simplify the BSD case */
  177: static BlockDriver *find_image_format(const char *filename)
  178: {
  179:     int fd, ret, score, score_max;
  180:     BlockDriver *drv1, *drv;
  181:     uint8_t *buf;
  182:     size_t bufsize = 1024;
  183: 
  184:     fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
  185:     if (fd < 0) {
  186:         buf = NULL;
  187:         ret = 0;
  188:     } else {
  189: #ifdef DIOCGSECTORSIZE
  190:         {
  191:             unsigned int sectorsize = 512;
  192:             if (!ioctl(fd, DIOCGSECTORSIZE, &sectorsize) &&
  193:                 sectorsize > bufsize)
  194:                 bufsize = sectorsize;
  195:         }
  196: #endif
  197: #ifdef CONFIG_COCOA
  198:         u_int32_t   blockSize = 512;
  199:         if ( !ioctl( fd, DKIOCGETBLOCKSIZE, &blockSize ) && blockSize > bufsize) {
  200:             bufsize = blockSize;
  201:         }
  202: #endif
  203:         buf = qemu_malloc(bufsize);
  204:         if (!buf)
  205:             return NULL;
  206:         ret = read(fd, buf, bufsize);
  207:         if (ret < 0) {
  208:             close(fd);
  209:             qemu_free(buf);
  210:             return NULL;
  211:         }
  212:         close(fd);
  213:     }
  214:     
  215:     drv = NULL;
  216:     score_max = 0;
  217:     for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
  218:         score = drv1->bdrv_probe(buf, ret, filename);
  219:         if (score > score_max) {
  220:             score_max = score;
  221:             drv = drv1;
  222:         }
  223:     }
  224:     qemu_free(buf);
  225:     return drv;
  226: }
  227: 
  228: int bdrv_open(BlockDriverState *bs, const char *filename, int snapshot)
  229: {
  230: #ifdef CONFIG_COCOA
  231:     if ( strncmp( filename, "/dev/cdrom", 10 ) == 0 ) {
  232:         kern_return_t kernResult;
  233:         io_iterator_t mediaIterator;
  234:         char bsdPath[ MAXPATHLEN ];
  235:         int fd;
  236:  
  237:         kernResult = FindEjectableCDMedia( &mediaIterator );
  238:         kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof( bsdPath ) );
  239:     
  240:         if ( bsdPath[ 0 ] != '\0' ) {
  241:             strcat(bsdPath,"s0");
  242:             /* some CDs don't have a partition 0 */
  243:             fd = open(bsdPath, O_RDONLY | O_BINARY | O_LARGEFILE);
  244:             if (fd < 0) {
  245:                 bsdPath[strlen(bsdPath)-1] = '1';
  246:             } else {
  247:                 close(fd);
  248:             }
  249:             filename = bsdPath;
  250:         }
  251:         
  252:         if ( mediaIterator )
  253:             IOObjectRelease( mediaIterator );
  254:     }
  255: #endif
  256:     return bdrv_open2(bs, filename, snapshot, NULL);
  257: }
  258: 
  259: int bdrv_open2(BlockDriverState *bs, const char *filename, int snapshot,
  260:                BlockDriver *drv)
  261: {
  262:     int ret;
  263:     char tmp_filename[1024];
  264:     
  265:     bs->read_only = 0;
  266:     bs->is_temporary = 0;
  267:     bs->encrypted = 0;
  268: 
  269:     if (snapshot) {
  270:         BlockDriverState *bs1;
  271:         int64_t total_size;
  272:         
  273:         /* if snapshot, we create a temporary backing file and open it
  274:            instead of opening 'filename' directly */
  275: 
  276:         /* if there is a backing file, use it */
  277:         bs1 = bdrv_new("");
  278:         if (!bs1) {
  279:             return -1;
  280:         }
  281:         if (bdrv_open(bs1, filename, 0) < 0) {
  282:             bdrv_delete(bs1);
  283:             return -1;
  284:         }
  285:         total_size = bs1->total_sectors;
  286:         bdrv_delete(bs1);
  287:         
  288:         get_tmp_filename(tmp_filename, sizeof(tmp_filename));
  289:         /* XXX: use cow for linux as it is more efficient ? */
  290:         if (bdrv_create(&bdrv_qcow, tmp_filename, 
  291:                         total_size, filename, 0) < 0) {
  292:             return -1;
  293:         }
  294:         filename = tmp_filename;
  295:         bs->is_temporary = 1;
  296:     }
  297: 
  298:     pstrcpy(bs->filename, sizeof(bs->filename), filename);
  299:     if (!drv) {
  300:         drv = find_image_format(filename);
  301:         if (!drv)
  302:             return -1;
  303:     }
  304:     bs->drv = drv;
  305:     bs->opaque = qemu_mallocz(drv->instance_size);
  306:     if (bs->opaque == NULL && drv->instance_size > 0)
  307:         return -1;
  308:     
  309:     ret = drv->bdrv_open(bs, filename);
  310:     if (ret < 0) {
  311:         qemu_free(bs->opaque);
  312:         return -1;
  313:     }
  314: #ifndef _WIN32
  315:     if (bs->is_temporary) {
  316:         unlink(filename);
  317:     }
  318: #endif
  319:     if (bs->backing_file[0] != '\0' && drv->bdrv_is_allocated) {
  320:         /* if there is a backing file, use it */
  321:         bs->backing_hd = bdrv_new("");
  322:         if (!bs->backing_hd) {
  323:         fail:
  324:             bdrv_close(bs);
  325:             return -1;
  326:         }
  327:         if (bdrv_open(bs->backing_hd, bs->backing_file, 0) < 0)
  328:             goto fail;
  329:     }
  330: 
  331:     bs->inserted = 1;
  332: 
  333:     /* call the change callback */
  334:     if (bs->change_cb)
  335:         bs->change_cb(bs->change_opaque);
  336: 
  337:     return 0;
  338: }
  339: 
  340: void bdrv_close(BlockDriverState *bs)
  341: {
  342:     if (bs->inserted) {
  343:         if (bs->backing_hd)
  344:             bdrv_delete(bs->backing_hd);
  345:         bs->drv->bdrv_close(bs);
  346:         qemu_free(bs->opaque);
  347: #ifdef _WIN32
  348:         if (bs->is_temporary) {
  349:             unlink(bs->filename);
  350:         }
  351: #endif
  352:         bs->opaque = NULL;
  353:         bs->drv = NULL;
  354:         bs->inserted = 0;
  355: 
  356:         /* call the change callback */
  357:         if (bs->change_cb)
  358:             bs->change_cb(bs->change_opaque);
  359:     }
  360: }
  361: 
  362: void bdrv_delete(BlockDriverState *bs)
  363: {
  364:     /* XXX: remove the driver list */
  365:     bdrv_close(bs);
  366:     qemu_free(bs);
  367: }
  368: 
  369: /* commit COW file into the raw image */
  370: int bdrv_commit(BlockDriverState *bs)
  371: {
  372:     int64_t i;
  373:     int n, j;
  374:     unsigned char sector[512];
  375: 
  376:     if (!bs->inserted)
  377:         return -ENOENT;
  378: 
  379:     if (bs->read_only) {
  380: 	return -EACCES;
  381:     }
  382: 
  383:     if (!bs->backing_hd) {
  384: 	return -ENOTSUP;
  385:     }
  386: 
  387:     for (i = 0; i < bs->total_sectors;) {
  388:         if (bs->drv->bdrv_is_allocated(bs, i, 65536, &n)) {
  389:             for(j = 0; j < n; j++) {
  390:                 if (bdrv_read(bs, i, sector, 1) != 0) {
  391:                     return -EIO;
  392:                 }
  393: 
  394:                 if (bdrv_write(bs->backing_hd, i, sector, 1) != 0) {
  395:                     return -EIO;
  396:                 }
  397:                 i++;
  398: 	    }
  399: 	} else {
  400:             i += n;
  401:         }
  402:     }
  403: 
  404:     if (bs->drv->bdrv_make_empty)
  405: 	return bs->drv->bdrv_make_empty(bs);
  406: 
  407:     return 0;
  408: }
  409: 
  410: /* return -1 if error */
  411: int bdrv_read(BlockDriverState *bs, int64_t sector_num, 
  412:               uint8_t *buf, int nb_sectors)
  413: {
  414:     int ret, n;
  415:     BlockDriver *drv = bs->drv;
  416: 
  417:     if (!bs->inserted)
  418:         return -1;
  419: 
  420:     while (nb_sectors > 0) {
  421:         if (sector_num == 0 && bs->boot_sector_enabled) {
  422:             memcpy(buf, bs->boot_sector_data, 512);
  423:             n = 1;
  424:         } else if (bs->backing_hd) {
  425:             if (drv->bdrv_is_allocated(bs, sector_num, nb_sectors, &n)) {
  426:                 ret = drv->bdrv_read(bs, sector_num, buf, n);
  427:                 if (ret < 0)
  428:                     return -1;
  429:             } else {
  430:                 /* read from the base image */
  431:                 ret = bdrv_read(bs->backing_hd, sector_num, buf, n);
  432:                 if (ret < 0)
  433:                     return -1;
  434:             }
  435:         } else {
  436:             ret = drv->bdrv_read(bs, sector_num, buf, nb_sectors);
  437:             if (ret < 0)
  438:                 return -1;
  439:             /* no need to loop */
  440:             break;
  441:         }
  442:         nb_sectors -= n;
  443:         sector_num += n;
  444:         buf += n * 512;
  445:     }
  446:     return 0;
  447: }
  448: 
  449: /* return -1 if error */
  450: int bdrv_write(BlockDriverState *bs, int64_t sector_num, 
  451:                const uint8_t *buf, int nb_sectors)
  452: {
  453:     if (!bs->inserted)
  454:         return -1;
  455:     if (bs->read_only)
  456:         return -1;
  457:     if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
  458:         memcpy(bs->boot_sector_data, buf, 512);   
  459:     }
  460:     return bs->drv->bdrv_write(bs, sector_num, buf, nb_sectors);
  461: }
  462: 
  463: void bdrv_get_geometry(BlockDriverState *bs, int64_t *nb_sectors_ptr)
  464: {
  465:     *nb_sectors_ptr = bs->total_sectors;
  466: }
  467: 
  468: /* force a given boot sector. */
  469: void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size)
  470: {
  471:     bs->boot_sector_enabled = 1;
  472:     if (size > 512)
  473:         size = 512;
  474:     memcpy(bs->boot_sector_data, data, size);
  475:     memset(bs->boot_sector_data + size, 0, 512 - size);
  476: }
  477: 
  478: void bdrv_set_geometry_hint(BlockDriverState *bs, 
  479:                             int cyls, int heads, int secs)
  480: {
  481:     bs->cyls = cyls;
  482:     bs->heads = heads;
  483:     bs->secs = secs;
  484: }
  485: 
  486: void bdrv_set_type_hint(BlockDriverState *bs, int type)
  487: {
  488:     bs->type = type;
  489:     bs->removable = ((type == BDRV_TYPE_CDROM ||
  490:                       type == BDRV_TYPE_FLOPPY));
  491: }
  492: 
  493: void bdrv_set_translation_hint(BlockDriverState *bs, int translation)
  494: {
  495:     bs->translation = translation;
  496: }
  497: 
  498: void bdrv_get_geometry_hint(BlockDriverState *bs, 
  499:                             int *pcyls, int *pheads, int *psecs)
  500: {
  501:     *pcyls = bs->cyls;
  502:     *pheads = bs->heads;
  503:     *psecs = bs->secs;
  504: }
  505: 
  506: int bdrv_get_type_hint(BlockDriverState *bs)
  507: {
  508:     return bs->type;
  509: }
  510: 
  511: int bdrv_get_translation_hint(BlockDriverState *bs)
  512: {
  513:     return bs->translation;
  514: }
  515: 
  516: int bdrv_is_removable(BlockDriverState *bs)
  517: {
  518:     return bs->removable;
  519: }
  520: 
  521: int bdrv_is_read_only(BlockDriverState *bs)
  522: {
  523:     return bs->read_only;
  524: }
  525: 
  526: int bdrv_is_inserted(BlockDriverState *bs)
  527: {
  528:     return bs->inserted;
  529: }
  530: 
  531: int bdrv_is_locked(BlockDriverState *bs)
  532: {
  533:     return bs->locked;
  534: }
  535: 
  536: void bdrv_set_locked(BlockDriverState *bs, int locked)
  537: {
  538:     bs->locked = locked;
  539: }
  540: 
  541: void bdrv_set_change_cb(BlockDriverState *bs, 
  542:                         void (*change_cb)(void *opaque), void *opaque)
  543: {
  544:     bs->change_cb = change_cb;
  545:     bs->change_opaque = opaque;
  546: }
  547: 
  548: int bdrv_is_encrypted(BlockDriverState *bs)
  549: {
  550:     if (bs->backing_hd && bs->backing_hd->encrypted)
  551:         return 1;
  552:     return bs->encrypted;
  553: }
  554: 
  555: int bdrv_set_key(BlockDriverState *bs, const char *key)
  556: {
  557:     int ret;
  558:     if (bs->backing_hd && bs->backing_hd->encrypted) {
  559:         ret = bdrv_set_key(bs->backing_hd, key);
  560:         if (ret < 0)
  561:             return ret;
  562:         if (!bs->encrypted)
  563:             return 0;
  564:     }
  565:     if (!bs->encrypted || !bs->drv || !bs->drv->bdrv_set_key)
  566:         return -1;
  567:     return bs->drv->bdrv_set_key(bs, key);
  568: }
  569: 
  570: void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size)
  571: {
  572:     if (!bs->inserted || !bs->drv) {
  573:         buf[0] = '\0';
  574:     } else {
  575:         pstrcpy(buf, buf_size, bs->drv->format_name);
  576:     }
  577: }
  578: 
  579: void bdrv_iterate_format(void (*it)(void *opaque, const char *name), 
  580:                          void *opaque)
  581: {
  582:     BlockDriver *drv;
  583: 
  584:     for (drv = first_drv; drv != NULL; drv = drv->next) {
  585:         it(opaque, drv->format_name);
  586:     }
  587: }
  588: 
  589: BlockDriverState *bdrv_find(const char *name)
  590: {
  591:     BlockDriverState *bs;
  592: 
  593:     for (bs = bdrv_first; bs != NULL; bs = bs->next) {
  594:         if (!strcmp(name, bs->device_name))
  595:             return bs;
  596:     }
  597:     return NULL;
  598: }
  599: 
  600: void bdrv_iterate(void (*it)(void *opaque, const char *name), void *opaque)
  601: {
  602:     BlockDriverState *bs;
  603: 
  604:     for (bs = bdrv_first; bs != NULL; bs = bs->next) {
  605:         it(opaque, bs->device_name);
  606:     }
  607: }
  608: 
  609: const char *bdrv_get_device_name(BlockDriverState *bs)
  610: {
  611:     return bs->device_name;
  612: }
  613: 
  614: void bdrv_info(void)
  615: {
  616:     BlockDriverState *bs;
  617: 
  618:     for (bs = bdrv_first; bs != NULL; bs = bs->next) {
  619:         term_printf("%s:", bs->device_name);
  620:         term_printf(" type=");
  621:         switch(bs->type) {
  622:         case BDRV_TYPE_HD:
  623:             term_printf("hd");
  624:             break;
  625:         case BDRV_TYPE_CDROM:
  626:             term_printf("cdrom");
  627:             break;
  628:         case BDRV_TYPE_FLOPPY:
  629:             term_printf("floppy");
  630:             break;
  631:         }
  632:         term_printf(" removable=%d", bs->removable);
  633:         if (bs->removable) {
  634:             term_printf(" locked=%d", bs->locked);
  635:         }
  636:         if (bs->inserted) {
  637:             term_printf(" file=%s", bs->filename);
  638:             if (bs->backing_file[0] != '\0')
  639:                 term_printf(" backing_file=%s", bs->backing_file);
  640:             term_printf(" ro=%d", bs->read_only);
  641:             term_printf(" drv=%s", bs->drv->format_name);
  642:             if (bs->encrypted)
  643:                 term_printf(" encrypted");
  644:         } else {
  645:             term_printf(" [not inserted]");
  646:         }
  647:         term_printf("\n");
  648:     }
  649: }
  650: 
  651: 
  652: /**************************************************************/
  653: /* RAW block driver */
  654: 
  655: typedef struct BDRVRawState {
  656:     int fd;
  657: } BDRVRawState;
  658: 
  659: static int raw_probe(const uint8_t *buf, int buf_size, const char *filename)
  660: {
  661:     return 1; /* maybe */
  662: }
  663: 
  664: static int raw_open(BlockDriverState *bs, const char *filename)
  665: {
  666:     BDRVRawState *s = bs->opaque;
  667:     int fd;
  668:     int64_t size;
  669: #ifdef _BSD
  670:     struct stat sb;
  671: #endif
  672: 
  673:     fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
  674:     if (fd < 0) {
  675:         fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
  676:         if (fd < 0)
  677:             return -1;
  678:         bs->read_only = 1;
  679:     }
  680: #ifdef _BSD
  681:     if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) {
  682: #ifdef DIOCGMEDIASIZE
  683: 	if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size))
  684: #endif
  685: #ifdef CONFIG_COCOA
  686:         size = LONG_LONG_MAX;
  687: #else
  688:         size = lseek(fd, 0LL, SEEK_END);
  689: #endif
  690:     } else
  691: #endif
  692:     {
  693:         size = lseek(fd, 0, SEEK_END);
  694:     }
  695: #ifdef _WIN32
  696:     /* On Windows hosts it can happen that we're unable to get file size
  697:        for CD-ROM raw device (it's inherent limitation of the CDFS driver). */
  698:     if (size == -1)
  699:         size = LONG_LONG_MAX;
  700: #endif
  701:     bs->total_sectors = size / 512;
  702:     s->fd = fd;
  703:     return 0;
  704: }
  705: 
  706: static int raw_read(BlockDriverState *bs, int64_t sector_num, 
  707:                     uint8_t *buf, int nb_sectors)
  708: {
  709:     BDRVRawState *s = bs->opaque;
  710:     int ret;
  711:     
  712:     lseek(s->fd, sector_num * 512, SEEK_SET);
  713:     ret = read(s->fd, buf, nb_sectors * 512);
  714:     if (ret != nb_sectors * 512) 
  715:         return -1;
  716:     return 0;
  717: }
  718: 
  719: static int raw_write(BlockDriverState *bs, int64_t sector_num, 
  720:                      const uint8_t *buf, int nb_sectors)
  721: {
  722:     BDRVRawState *s = bs->opaque;
  723:     int ret;
  724:     
  725:     lseek(s->fd, sector_num * 512, SEEK_SET);
  726:     ret = write(s->fd, buf, nb_sectors * 512);
  727:     if (ret != nb_sectors * 512) 
  728:         return -1;
  729:     return 0;
  730: }
  731: 
  732: static void raw_close(BlockDriverState *bs)
  733: {
  734:     BDRVRawState *s = bs->opaque;
  735:     close(s->fd);
  736: }
  737: 
  738: static int raw_create(const char *filename, int64_t total_size,
  739:                       const char *backing_file, int flags)
  740: {
  741:     int fd;
  742: 
  743:     if (flags || backing_file)
  744:         return -ENOTSUP;
  745: 
  746:     fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, 
  747:               0644);
  748:     if (fd < 0)
  749:         return -EIO;
  750:     ftruncate(fd, total_size * 512);
  751:     close(fd);
  752:     return 0;
  753: }
  754: 
  755: BlockDriver bdrv_raw = {
  756:     "raw",
  757:     sizeof(BDRVRawState),
  758:     raw_probe,
  759:     raw_open,
  760:     raw_read,
  761:     raw_write,
  762:     raw_close,
  763:     raw_create,
  764: };
  765: 
  766: void bdrv_init(void)
  767: {
  768:     bdrv_register(&bdrv_raw);
  769: #ifndef _WIN32
  770:     bdrv_register(&bdrv_cow);
  771: #endif
  772:     bdrv_register(&bdrv_qcow);
  773:     bdrv_register(&bdrv_vmdk);
  774:     bdrv_register(&bdrv_cloop);
  775:     bdrv_register(&bdrv_dmg);
  776:     bdrv_register(&bdrv_bochs);
  777:     bdrv_register(&bdrv_vpc);
  778:     bdrv_register(&bdrv_vvfat);
  779: }

unix.superglobalmegacorp.com