File:  [Qemu by Fabrice Bellard] / qemu / block.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 16:42:44 2018 UTC (2 years, 5 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu0082, HEAD
qemu 0.8.2

    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: #ifdef __sun__
   48: #include <sys/dkio.h>
   49: #endif
   50: 
   51: static BlockDriverState *bdrv_first;
   52: static BlockDriver *first_drv;
   53: 
   54: #ifdef CONFIG_COCOA
   55: static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator );
   56: static kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize );
   57: 
   58: kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator )
   59: {
   60:     kern_return_t       kernResult; 
   61:     mach_port_t     masterPort;
   62:     CFMutableDictionaryRef  classesToMatch;
   63: 
   64:     kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort );
   65:     if ( KERN_SUCCESS != kernResult ) {
   66:         printf( "IOMasterPort returned %d\n", kernResult );
   67:     }
   68:     
   69:     classesToMatch = IOServiceMatching( kIOCDMediaClass ); 
   70:     if ( classesToMatch == NULL ) {
   71:         printf( "IOServiceMatching returned a NULL dictionary.\n" );
   72:     } else {
   73:     CFDictionarySetValue( classesToMatch, CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue );
   74:     }
   75:     kernResult = IOServiceGetMatchingServices( masterPort, classesToMatch, mediaIterator );
   76:     if ( KERN_SUCCESS != kernResult )
   77:     {
   78:         printf( "IOServiceGetMatchingServices returned %d\n", kernResult );
   79:     }
   80:     
   81:     return kernResult;
   82: }
   83: 
   84: kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize )
   85: {
   86:     io_object_t     nextMedia;
   87:     kern_return_t   kernResult = KERN_FAILURE;
   88:     *bsdPath = '\0';
   89:     nextMedia = IOIteratorNext( mediaIterator );
   90:     if ( nextMedia )
   91:     {
   92:         CFTypeRef   bsdPathAsCFString;
   93:     bsdPathAsCFString = IORegistryEntryCreateCFProperty( nextMedia, CFSTR( kIOBSDNameKey ), kCFAllocatorDefault, 0 );
   94:         if ( bsdPathAsCFString ) {
   95:             size_t devPathLength;
   96:             strcpy( bsdPath, _PATH_DEV );
   97:             strcat( bsdPath, "r" );
   98:             devPathLength = strlen( bsdPath );
   99:             if ( CFStringGetCString( bsdPathAsCFString, bsdPath + devPathLength, maxPathSize - devPathLength, kCFStringEncodingASCII ) ) {
  100:                 kernResult = KERN_SUCCESS;
  101:             }
  102:             CFRelease( bsdPathAsCFString );
  103:         }
  104:         IOObjectRelease( nextMedia );
  105:     }
  106:     
  107:     return kernResult;
  108: }
  109: 
  110: #endif
  111: 
  112: void bdrv_register(BlockDriver *bdrv)
  113: {
  114:     bdrv->next = first_drv;
  115:     first_drv = bdrv;
  116: }
  117: 
  118: /* create a new block device (by default it is empty) */
  119: BlockDriverState *bdrv_new(const char *device_name)
  120: {
  121:     BlockDriverState **pbs, *bs;
  122: 
  123:     bs = qemu_mallocz(sizeof(BlockDriverState));
  124:     if(!bs)
  125:         return NULL;
  126:     pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
  127:     if (device_name[0] != '\0') {
  128:         /* insert at the end */
  129:         pbs = &bdrv_first;
  130:         while (*pbs != NULL)
  131:             pbs = &(*pbs)->next;
  132:         *pbs = bs;
  133:     }
  134:     return bs;
  135: }
  136: 
  137: BlockDriver *bdrv_find_format(const char *format_name)
  138: {
  139:     BlockDriver *drv1;
  140:     for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
  141:         if (!strcmp(drv1->format_name, format_name))
  142:             return drv1;
  143:     }
  144:     return NULL;
  145: }
  146: 
  147: int bdrv_create(BlockDriver *drv, 
  148:                 const char *filename, int64_t size_in_sectors,
  149:                 const char *backing_file, int flags)
  150: {
  151:     if (!drv->bdrv_create)
  152:         return -ENOTSUP;
  153:     return drv->bdrv_create(filename, size_in_sectors, backing_file, flags);
  154: }
  155: 
  156: #ifdef _WIN32
  157: void get_tmp_filename(char *filename, int size)
  158: {
  159:     char* p = strrchr(filename, '/');
  160: 
  161:     if (p == NULL)
  162: 	return;
  163: 
  164:     /* XXX: find a better function */
  165:     tmpnam(p);
  166:     *p = '/';
  167: }
  168: #else
  169: void get_tmp_filename(char *filename, int size)
  170: {
  171:     int fd;
  172:     /* XXX: race condition possible */
  173:     pstrcpy(filename, size, "/tmp/vl.XXXXXX");
  174:     fd = mkstemp(filename);
  175:     close(fd);
  176: }
  177: #endif
  178: 
  179: /* XXX: force raw format if block or character device ? It would
  180:    simplify the BSD case */
  181: static BlockDriver *find_image_format(const char *filename)
  182: {
  183:     int fd, ret, score, score_max;
  184:     BlockDriver *drv1, *drv;
  185:     uint8_t *buf;
  186:     size_t bufsize = 1024;
  187: 
  188:     fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
  189:     if (fd < 0) {
  190:         buf = NULL;
  191:         ret = 0;
  192:     } else {
  193: #ifdef DIOCGSECTORSIZE
  194:         {
  195:             unsigned int sectorsize = 512;
  196:             if (!ioctl(fd, DIOCGSECTORSIZE, &sectorsize) &&
  197:                 sectorsize > bufsize)
  198:                 bufsize = sectorsize;
  199:         }
  200: #endif
  201: #ifdef CONFIG_COCOA
  202:         u_int32_t   blockSize = 512;
  203:         if ( !ioctl( fd, DKIOCGETBLOCKSIZE, &blockSize ) && blockSize > bufsize) {
  204:             bufsize = blockSize;
  205:         }
  206: #endif
  207:         buf = qemu_malloc(bufsize);
  208:         if (!buf)
  209:             return NULL;
  210:         ret = read(fd, buf, bufsize);
  211:         if (ret < 0) {
  212:             close(fd);
  213:             qemu_free(buf);
  214:             return NULL;
  215:         }
  216:         close(fd);
  217:     }
  218:     
  219:     drv = NULL;
  220:     score_max = 0;
  221:     for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
  222:         score = drv1->bdrv_probe(buf, ret, filename);
  223:         if (score > score_max) {
  224:             score_max = score;
  225:             drv = drv1;
  226:         }
  227:     }
  228:     qemu_free(buf);
  229:     return drv;
  230: }
  231: 
  232: int bdrv_open(BlockDriverState *bs, const char *filename, int snapshot)
  233: {
  234: #ifdef CONFIG_COCOA
  235:     if ( strncmp( filename, "/dev/cdrom", 10 ) == 0 ) {
  236:         kern_return_t kernResult;
  237:         io_iterator_t mediaIterator;
  238:         char bsdPath[ MAXPATHLEN ];
  239:         int fd;
  240:  
  241:         kernResult = FindEjectableCDMedia( &mediaIterator );
  242:         kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof( bsdPath ) );
  243:     
  244:         if ( bsdPath[ 0 ] != '\0' ) {
  245:             strcat(bsdPath,"s0");
  246:             /* some CDs don't have a partition 0 */
  247:             fd = open(bsdPath, O_RDONLY | O_BINARY | O_LARGEFILE);
  248:             if (fd < 0) {
  249:                 bsdPath[strlen(bsdPath)-1] = '1';
  250:             } else {
  251:                 close(fd);
  252:             }
  253:             filename = bsdPath;
  254:         }
  255:         
  256:         if ( mediaIterator )
  257:             IOObjectRelease( mediaIterator );
  258:     }
  259: #endif
  260:     return bdrv_open2(bs, filename, snapshot, NULL);
  261: }
  262: 
  263: int bdrv_open2(BlockDriverState *bs, const char *filename, int snapshot,
  264:                BlockDriver *drv)
  265: {
  266:     int ret;
  267:     char tmp_filename[1024];
  268:     
  269:     bs->read_only = 0;
  270:     bs->is_temporary = 0;
  271:     bs->encrypted = 0;
  272: 
  273:     if (snapshot) {
  274:         BlockDriverState *bs1;
  275:         int64_t total_size;
  276:         
  277:         /* if snapshot, we create a temporary backing file and open it
  278:            instead of opening 'filename' directly */
  279: 
  280:         /* if there is a backing file, use it */
  281:         bs1 = bdrv_new("");
  282:         if (!bs1) {
  283:             return -1;
  284:         }
  285:         if (bdrv_open(bs1, filename, 0) < 0) {
  286:             bdrv_delete(bs1);
  287:             return -1;
  288:         }
  289:         total_size = bs1->total_sectors;
  290:         bdrv_delete(bs1);
  291:         
  292:         get_tmp_filename(tmp_filename, sizeof(tmp_filename));
  293:         /* XXX: use cow for linux as it is more efficient ? */
  294:         if (bdrv_create(&bdrv_qcow, tmp_filename, 
  295:                         total_size, filename, 0) < 0) {
  296:             return -1;
  297:         }
  298:         filename = tmp_filename;
  299:         bs->is_temporary = 1;
  300:     }
  301: 
  302:     pstrcpy(bs->filename, sizeof(bs->filename), filename);
  303:     if (!drv) {
  304:         drv = find_image_format(filename);
  305:         if (!drv)
  306:             return -1;
  307:     }
  308:     bs->drv = drv;
  309:     bs->opaque = qemu_mallocz(drv->instance_size);
  310:     if (bs->opaque == NULL && drv->instance_size > 0)
  311:         return -1;
  312:     
  313:     ret = drv->bdrv_open(bs, filename);
  314:     if (ret < 0) {
  315:         qemu_free(bs->opaque);
  316:         return -1;
  317:     }
  318: #ifndef _WIN32
  319:     if (bs->is_temporary) {
  320:         unlink(filename);
  321:     }
  322: #endif
  323:     if (bs->backing_file[0] != '\0' && drv->bdrv_is_allocated) {
  324:         /* if there is a backing file, use it */
  325:         bs->backing_hd = bdrv_new("");
  326:         if (!bs->backing_hd) {
  327:         fail:
  328:             bdrv_close(bs);
  329:             return -1;
  330:         }
  331:         if (bdrv_open(bs->backing_hd, bs->backing_file, 0) < 0)
  332:             goto fail;
  333:     }
  334: 
  335:     bs->inserted = 1;
  336: 
  337:     /* call the change callback */
  338:     if (bs->change_cb)
  339:         bs->change_cb(bs->change_opaque);
  340: 
  341:     return 0;
  342: }
  343: 
  344: void bdrv_close(BlockDriverState *bs)
  345: {
  346:     if (bs->inserted) {
  347:         if (bs->backing_hd)
  348:             bdrv_delete(bs->backing_hd);
  349:         bs->drv->bdrv_close(bs);
  350:         qemu_free(bs->opaque);
  351: #ifdef _WIN32
  352:         if (bs->is_temporary) {
  353:             unlink(bs->filename);
  354:         }
  355: #endif
  356:         bs->opaque = NULL;
  357:         bs->drv = NULL;
  358:         bs->inserted = 0;
  359: 
  360:         /* call the change callback */
  361:         if (bs->change_cb)
  362:             bs->change_cb(bs->change_opaque);
  363:     }
  364: }
  365: 
  366: void bdrv_delete(BlockDriverState *bs)
  367: {
  368:     /* XXX: remove the driver list */
  369:     bdrv_close(bs);
  370:     qemu_free(bs);
  371: }
  372: 
  373: /* commit COW file into the raw image */
  374: int bdrv_commit(BlockDriverState *bs)
  375: {
  376:     int64_t i;
  377:     int n, j;
  378:     unsigned char sector[512];
  379: 
  380:     if (!bs->inserted)
  381:         return -ENOENT;
  382: 
  383:     if (bs->read_only) {
  384: 	return -EACCES;
  385:     }
  386: 
  387:     if (!bs->backing_hd) {
  388: 	return -ENOTSUP;
  389:     }
  390: 
  391:     for (i = 0; i < bs->total_sectors;) {
  392:         if (bs->drv->bdrv_is_allocated(bs, i, 65536, &n)) {
  393:             for(j = 0; j < n; j++) {
  394:                 if (bdrv_read(bs, i, sector, 1) != 0) {
  395:                     return -EIO;
  396:                 }
  397: 
  398:                 if (bdrv_write(bs->backing_hd, i, sector, 1) != 0) {
  399:                     return -EIO;
  400:                 }
  401:                 i++;
  402: 	    }
  403: 	} else {
  404:             i += n;
  405:         }
  406:     }
  407: 
  408:     if (bs->drv->bdrv_make_empty)
  409: 	return bs->drv->bdrv_make_empty(bs);
  410: 
  411:     return 0;
  412: }
  413: 
  414: /* return -1 if error */
  415: int bdrv_read(BlockDriverState *bs, int64_t sector_num, 
  416:               uint8_t *buf, int nb_sectors)
  417: {
  418:     int ret, n;
  419:     BlockDriver *drv = bs->drv;
  420: 
  421:     if (!bs->inserted)
  422:         return -1;
  423: 
  424:     while (nb_sectors > 0) {
  425:         if (sector_num == 0 && bs->boot_sector_enabled) {
  426:             memcpy(buf, bs->boot_sector_data, 512);
  427:             n = 1;
  428:         } else if (bs->backing_hd) {
  429:             if (drv->bdrv_is_allocated(bs, sector_num, nb_sectors, &n)) {
  430:                 ret = drv->bdrv_read(bs, sector_num, buf, n);
  431:                 if (ret < 0)
  432:                     return -1;
  433:             } else {
  434:                 /* read from the base image */
  435:                 ret = bdrv_read(bs->backing_hd, sector_num, buf, n);
  436:                 if (ret < 0)
  437:                     return -1;
  438:             }
  439:         } else {
  440:             ret = drv->bdrv_read(bs, sector_num, buf, nb_sectors);
  441:             if (ret < 0)
  442:                 return -1;
  443:             /* no need to loop */
  444:             break;
  445:         }
  446:         nb_sectors -= n;
  447:         sector_num += n;
  448:         buf += n * 512;
  449:     }
  450:     return 0;
  451: }
  452: 
  453: /* return -1 if error */
  454: int bdrv_write(BlockDriverState *bs, int64_t sector_num, 
  455:                const uint8_t *buf, int nb_sectors)
  456: {
  457:     if (!bs->inserted)
  458:         return -1;
  459:     if (bs->read_only)
  460:         return -1;
  461:     if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
  462:         memcpy(bs->boot_sector_data, buf, 512);   
  463:     }
  464:     return bs->drv->bdrv_write(bs, sector_num, buf, nb_sectors);
  465: }
  466: 
  467: void bdrv_get_geometry(BlockDriverState *bs, int64_t *nb_sectors_ptr)
  468: {
  469:     *nb_sectors_ptr = bs->total_sectors;
  470: }
  471: 
  472: /* force a given boot sector. */
  473: void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size)
  474: {
  475:     bs->boot_sector_enabled = 1;
  476:     if (size > 512)
  477:         size = 512;
  478:     memcpy(bs->boot_sector_data, data, size);
  479:     memset(bs->boot_sector_data + size, 0, 512 - size);
  480: }
  481: 
  482: void bdrv_set_geometry_hint(BlockDriverState *bs, 
  483:                             int cyls, int heads, int secs)
  484: {
  485:     bs->cyls = cyls;
  486:     bs->heads = heads;
  487:     bs->secs = secs;
  488: }
  489: 
  490: void bdrv_set_type_hint(BlockDriverState *bs, int type)
  491: {
  492:     bs->type = type;
  493:     bs->removable = ((type == BDRV_TYPE_CDROM ||
  494:                       type == BDRV_TYPE_FLOPPY));
  495: }
  496: 
  497: void bdrv_set_translation_hint(BlockDriverState *bs, int translation)
  498: {
  499:     bs->translation = translation;
  500: }
  501: 
  502: void bdrv_get_geometry_hint(BlockDriverState *bs, 
  503:                             int *pcyls, int *pheads, int *psecs)
  504: {
  505:     *pcyls = bs->cyls;
  506:     *pheads = bs->heads;
  507:     *psecs = bs->secs;
  508: }
  509: 
  510: int bdrv_get_type_hint(BlockDriverState *bs)
  511: {
  512:     return bs->type;
  513: }
  514: 
  515: int bdrv_get_translation_hint(BlockDriverState *bs)
  516: {
  517:     return bs->translation;
  518: }
  519: 
  520: int bdrv_is_removable(BlockDriverState *bs)
  521: {
  522:     return bs->removable;
  523: }
  524: 
  525: int bdrv_is_read_only(BlockDriverState *bs)
  526: {
  527:     return bs->read_only;
  528: }
  529: 
  530: int bdrv_is_inserted(BlockDriverState *bs)
  531: {
  532:     return bs->inserted;
  533: }
  534: 
  535: int bdrv_is_locked(BlockDriverState *bs)
  536: {
  537:     return bs->locked;
  538: }
  539: 
  540: void bdrv_set_locked(BlockDriverState *bs, int locked)
  541: {
  542:     bs->locked = locked;
  543: }
  544: 
  545: void bdrv_set_change_cb(BlockDriverState *bs, 
  546:                         void (*change_cb)(void *opaque), void *opaque)
  547: {
  548:     bs->change_cb = change_cb;
  549:     bs->change_opaque = opaque;
  550: }
  551: 
  552: int bdrv_is_encrypted(BlockDriverState *bs)
  553: {
  554:     if (bs->backing_hd && bs->backing_hd->encrypted)
  555:         return 1;
  556:     return bs->encrypted;
  557: }
  558: 
  559: int bdrv_set_key(BlockDriverState *bs, const char *key)
  560: {
  561:     int ret;
  562:     if (bs->backing_hd && bs->backing_hd->encrypted) {
  563:         ret = bdrv_set_key(bs->backing_hd, key);
  564:         if (ret < 0)
  565:             return ret;
  566:         if (!bs->encrypted)
  567:             return 0;
  568:     }
  569:     if (!bs->encrypted || !bs->drv || !bs->drv->bdrv_set_key)
  570:         return -1;
  571:     return bs->drv->bdrv_set_key(bs, key);
  572: }
  573: 
  574: void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size)
  575: {
  576:     if (!bs->inserted || !bs->drv) {
  577:         buf[0] = '\0';
  578:     } else {
  579:         pstrcpy(buf, buf_size, bs->drv->format_name);
  580:     }
  581: }
  582: 
  583: void bdrv_iterate_format(void (*it)(void *opaque, const char *name), 
  584:                          void *opaque)
  585: {
  586:     BlockDriver *drv;
  587: 
  588:     for (drv = first_drv; drv != NULL; drv = drv->next) {
  589:         it(opaque, drv->format_name);
  590:     }
  591: }
  592: 
  593: BlockDriverState *bdrv_find(const char *name)
  594: {
  595:     BlockDriverState *bs;
  596: 
  597:     for (bs = bdrv_first; bs != NULL; bs = bs->next) {
  598:         if (!strcmp(name, bs->device_name))
  599:             return bs;
  600:     }
  601:     return NULL;
  602: }
  603: 
  604: void bdrv_iterate(void (*it)(void *opaque, const char *name), void *opaque)
  605: {
  606:     BlockDriverState *bs;
  607: 
  608:     for (bs = bdrv_first; bs != NULL; bs = bs->next) {
  609:         it(opaque, bs->device_name);
  610:     }
  611: }
  612: 
  613: const char *bdrv_get_device_name(BlockDriverState *bs)
  614: {
  615:     return bs->device_name;
  616: }
  617: 
  618: void bdrv_flush(BlockDriverState *bs)
  619: {
  620:     if (bs->drv->bdrv_flush)
  621:         bs->drv->bdrv_flush(bs);
  622:     if (bs->backing_hd)
  623:         bdrv_flush(bs->backing_hd);
  624: }
  625: 
  626: void bdrv_info(void)
  627: {
  628:     BlockDriverState *bs;
  629: 
  630:     for (bs = bdrv_first; bs != NULL; bs = bs->next) {
  631:         term_printf("%s:", bs->device_name);
  632:         term_printf(" type=");
  633:         switch(bs->type) {
  634:         case BDRV_TYPE_HD:
  635:             term_printf("hd");
  636:             break;
  637:         case BDRV_TYPE_CDROM:
  638:             term_printf("cdrom");
  639:             break;
  640:         case BDRV_TYPE_FLOPPY:
  641:             term_printf("floppy");
  642:             break;
  643:         }
  644:         term_printf(" removable=%d", bs->removable);
  645:         if (bs->removable) {
  646:             term_printf(" locked=%d", bs->locked);
  647:         }
  648:         if (bs->inserted) {
  649:             term_printf(" file=%s", bs->filename);
  650:             if (bs->backing_file[0] != '\0')
  651:                 term_printf(" backing_file=%s", bs->backing_file);
  652:             term_printf(" ro=%d", bs->read_only);
  653:             term_printf(" drv=%s", bs->drv->format_name);
  654:             if (bs->encrypted)
  655:                 term_printf(" encrypted");
  656:         } else {
  657:             term_printf(" [not inserted]");
  658:         }
  659:         term_printf("\n");
  660:     }
  661: }
  662: 
  663: /**************************************************************/
  664: /* RAW block driver */
  665: 
  666: typedef struct BDRVRawState {
  667:     int fd;
  668: } BDRVRawState;
  669: 
  670: static int raw_probe(const uint8_t *buf, int buf_size, const char *filename)
  671: {
  672:     return 1; /* maybe */
  673: }
  674: 
  675: static int raw_open(BlockDriverState *bs, const char *filename)
  676: {
  677:     BDRVRawState *s = bs->opaque;
  678:     int fd;
  679:     int64_t size;
  680: #ifdef _BSD
  681:     struct stat sb;
  682: #endif
  683: #ifdef __sun__
  684:     struct dk_minfo minfo;
  685:     int rv;
  686: #endif
  687: 
  688:     fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
  689:     if (fd < 0) {
  690:         fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
  691:         if (fd < 0)
  692:             return -1;
  693:         bs->read_only = 1;
  694:     }
  695: #ifdef _BSD
  696:     if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) {
  697: #ifdef DIOCGMEDIASIZE
  698: 	if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size))
  699: #endif
  700: #ifdef CONFIG_COCOA
  701:         size = LONG_LONG_MAX;
  702: #else
  703:         size = lseek(fd, 0LL, SEEK_END);
  704: #endif
  705:     } else
  706: #endif
  707: #ifdef __sun__
  708:     /*
  709:      * use the DKIOCGMEDIAINFO ioctl to read the size.
  710:      */
  711:     rv = ioctl ( fd, DKIOCGMEDIAINFO, &minfo );
  712:     if ( rv != -1 ) {
  713:         size = minfo.dki_lbsize * minfo.dki_capacity;
  714:     } else /* there are reports that lseek on some devices
  715:               fails, but irc discussion said that contingency
  716:               on contingency was overkill */
  717: #endif
  718:     {
  719:         size = lseek(fd, 0, SEEK_END);
  720:     }
  721: #ifdef _WIN32
  722:     /* On Windows hosts it can happen that we're unable to get file size
  723:        for CD-ROM raw device (it's inherent limitation of the CDFS driver). */
  724:     if (size == -1)
  725:         size = LONG_LONG_MAX;
  726: #endif
  727:     bs->total_sectors = size / 512;
  728:     s->fd = fd;
  729:     return 0;
  730: }
  731: 
  732: static int raw_read(BlockDriverState *bs, int64_t sector_num, 
  733:                     uint8_t *buf, int nb_sectors)
  734: {
  735:     BDRVRawState *s = bs->opaque;
  736:     int ret;
  737:     
  738:     lseek(s->fd, sector_num * 512, SEEK_SET);
  739:     ret = read(s->fd, buf, nb_sectors * 512);
  740:     if (ret != nb_sectors * 512) 
  741:         return -1;
  742:     return 0;
  743: }
  744: 
  745: static int raw_write(BlockDriverState *bs, int64_t sector_num, 
  746:                      const uint8_t *buf, int nb_sectors)
  747: {
  748:     BDRVRawState *s = bs->opaque;
  749:     int ret;
  750:     
  751:     lseek(s->fd, sector_num * 512, SEEK_SET);
  752:     ret = write(s->fd, buf, nb_sectors * 512);
  753:     if (ret != nb_sectors * 512) 
  754:         return -1;
  755:     return 0;
  756: }
  757: 
  758: static void raw_close(BlockDriverState *bs)
  759: {
  760:     BDRVRawState *s = bs->opaque;
  761:     close(s->fd);
  762: }
  763: 
  764: #ifdef _WIN32
  765: #include <windows.h>
  766: #include <winioctl.h>
  767: 
  768: int qemu_ftruncate64(int fd, int64_t length)
  769: {
  770:     LARGE_INTEGER li;
  771:     LONG high;
  772:     HANDLE h;
  773:     BOOL res;
  774: 
  775:     if ((GetVersion() & 0x80000000UL) && (length >> 32) != 0)
  776: 	return -1;
  777: 
  778:     h = (HANDLE)_get_osfhandle(fd);
  779: 
  780:     /* get current position, ftruncate do not change position */
  781:     li.HighPart = 0;
  782:     li.LowPart = SetFilePointer (h, 0, &li.HighPart, FILE_CURRENT);
  783:     if (li.LowPart == 0xffffffffUL && GetLastError() != NO_ERROR)
  784: 	return -1;
  785: 
  786:     high = length >> 32;
  787:     if (!SetFilePointer(h, (DWORD) length, &high, FILE_BEGIN))
  788: 	return -1;
  789:     res = SetEndOfFile(h);
  790: 
  791:     /* back to old position */
  792:     SetFilePointer(h, li.LowPart, &li.HighPart, FILE_BEGIN);
  793:     return res ? 0 : -1;
  794: }
  795: 
  796: static int set_sparse(int fd)
  797: {
  798:     DWORD returned;
  799:     return (int) DeviceIoControl((HANDLE)_get_osfhandle(fd), FSCTL_SET_SPARSE,
  800: 				 NULL, 0, NULL, 0, &returned, NULL);
  801: }
  802: #else
  803: static inline int set_sparse(int fd)
  804: {
  805:     return 1;
  806: }
  807: #endif
  808: 
  809: static int raw_create(const char *filename, int64_t total_size,
  810:                       const char *backing_file, int flags)
  811: {
  812:     int fd;
  813: 
  814:     if (flags || backing_file)
  815:         return -ENOTSUP;
  816: 
  817:     fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, 
  818:               0644);
  819:     if (fd < 0)
  820:         return -EIO;
  821:     set_sparse(fd);
  822:     ftruncate(fd, total_size * 512);
  823:     close(fd);
  824:     return 0;
  825: }
  826: 
  827: static void raw_flush(BlockDriverState *bs)
  828: {
  829:     BDRVRawState *s = bs->opaque;
  830:     fsync(s->fd);
  831: }
  832: 
  833: BlockDriver bdrv_raw = {
  834:     "raw",
  835:     sizeof(BDRVRawState),
  836:     raw_probe,
  837:     raw_open,
  838:     raw_read,
  839:     raw_write,
  840:     raw_close,
  841:     raw_create,
  842:     raw_flush,
  843: };
  844: 
  845: void bdrv_init(void)
  846: {
  847:     bdrv_register(&bdrv_raw);
  848: #ifndef _WIN32
  849:     bdrv_register(&bdrv_cow);
  850: #endif
  851:     bdrv_register(&bdrv_qcow);
  852:     bdrv_register(&bdrv_vmdk);
  853:     bdrv_register(&bdrv_cloop);
  854:     bdrv_register(&bdrv_dmg);
  855:     bdrv_register(&bdrv_bochs);
  856:     bdrv_register(&bdrv_vpc);
  857:     bdrv_register(&bdrv_vvfat);
  858: }

unix.superglobalmegacorp.com