Annotation of qemu/block.c, revision 1.1.1.3

1.1       root        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: 
1.1.1.2   root       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: 
1.1.1.3 ! root       47: #ifdef __sun__
        !            48: #include <sys/dkio.h>
        !            49: #endif
        !            50: 
1.1       root       51: static BlockDriverState *bdrv_first;
                     52: static BlockDriver *first_drv;
                     53: 
1.1.1.2   root       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: 
1.1       root      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
1.1.1.2   root      157: void get_tmp_filename(char *filename, int size)
1.1       root      158: {
1.1.1.2   root      159:     char* p = strrchr(filename, '/');
                    160: 
                    161:     if (p == NULL)
                    162:        return;
                    163: 
1.1       root      164:     /* XXX: find a better function */
1.1.1.2   root      165:     tmpnam(p);
                    166:     *p = '/';
1.1       root      167: }
                    168: #else
1.1.1.2   root      169: void get_tmp_filename(char *filename, int size)
1.1       root      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
1.1.1.2   root      201: #ifdef CONFIG_COCOA
                    202:         u_int32_t   blockSize = 512;
                    203:         if ( !ioctl( fd, DKIOCGETBLOCKSIZE, &blockSize ) && blockSize > bufsize) {
                    204:             bufsize = blockSize;
                    205:         }
                    206: #endif
1.1       root      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: {
1.1.1.2   root      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
1.1       root      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:     }
1.1.1.2   root      407: 
                    408:     if (bs->drv->bdrv_make_empty)
                    409:        return bs->drv->bdrv_make_empty(bs);
                    410: 
1.1       root      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;
1.1.1.2   root      461:     if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
                    462:         memcpy(bs->boot_sector_data, buf, 512);   
                    463:     }
1.1       root      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_info(void)
                    619: {
                    620:     BlockDriverState *bs;
                    621: 
                    622:     for (bs = bdrv_first; bs != NULL; bs = bs->next) {
                    623:         term_printf("%s:", bs->device_name);
                    624:         term_printf(" type=");
                    625:         switch(bs->type) {
                    626:         case BDRV_TYPE_HD:
                    627:             term_printf("hd");
                    628:             break;
                    629:         case BDRV_TYPE_CDROM:
                    630:             term_printf("cdrom");
                    631:             break;
                    632:         case BDRV_TYPE_FLOPPY:
                    633:             term_printf("floppy");
                    634:             break;
                    635:         }
                    636:         term_printf(" removable=%d", bs->removable);
                    637:         if (bs->removable) {
                    638:             term_printf(" locked=%d", bs->locked);
                    639:         }
                    640:         if (bs->inserted) {
                    641:             term_printf(" file=%s", bs->filename);
                    642:             if (bs->backing_file[0] != '\0')
                    643:                 term_printf(" backing_file=%s", bs->backing_file);
                    644:             term_printf(" ro=%d", bs->read_only);
                    645:             term_printf(" drv=%s", bs->drv->format_name);
                    646:             if (bs->encrypted)
                    647:                 term_printf(" encrypted");
                    648:         } else {
                    649:             term_printf(" [not inserted]");
                    650:         }
                    651:         term_printf("\n");
                    652:     }
                    653: }
                    654: 
                    655: /**************************************************************/
                    656: /* RAW block driver */
                    657: 
                    658: typedef struct BDRVRawState {
                    659:     int fd;
                    660: } BDRVRawState;
                    661: 
                    662: static int raw_probe(const uint8_t *buf, int buf_size, const char *filename)
                    663: {
                    664:     return 1; /* maybe */
                    665: }
                    666: 
                    667: static int raw_open(BlockDriverState *bs, const char *filename)
                    668: {
                    669:     BDRVRawState *s = bs->opaque;
                    670:     int fd;
                    671:     int64_t size;
                    672: #ifdef _BSD
                    673:     struct stat sb;
                    674: #endif
1.1.1.3 ! root      675: #ifdef __sun__
        !           676:     struct dk_minfo minfo;
        !           677:     int rv;
        !           678: #endif
1.1       root      679: 
                    680:     fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
                    681:     if (fd < 0) {
                    682:         fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
                    683:         if (fd < 0)
                    684:             return -1;
                    685:         bs->read_only = 1;
                    686:     }
                    687: #ifdef _BSD
                    688:     if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) {
                    689: #ifdef DIOCGMEDIASIZE
                    690:        if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size))
                    691: #endif
1.1.1.2   root      692: #ifdef CONFIG_COCOA
                    693:         size = LONG_LONG_MAX;
                    694: #else
                    695:         size = lseek(fd, 0LL, SEEK_END);
                    696: #endif
1.1       root      697:     } else
                    698: #endif
1.1.1.3 ! root      699: #ifdef __sun__
        !           700:     /*
        !           701:      * use the DKIOCGMEDIAINFO ioctl to read the size.
        !           702:      */
        !           703:     rv = ioctl ( fd, DKIOCGMEDIAINFO, &minfo );
        !           704:     if ( rv != -1 ) {
        !           705:         size = minfo.dki_lbsize * minfo.dki_capacity;
        !           706:     } else /* there are reports that lseek on some devices
        !           707:               fails, but irc discussion said that contingency
        !           708:               on contingency was overkill */
        !           709: #endif
1.1       root      710:     {
                    711:         size = lseek(fd, 0, SEEK_END);
                    712:     }
                    713: #ifdef _WIN32
                    714:     /* On Windows hosts it can happen that we're unable to get file size
                    715:        for CD-ROM raw device (it's inherent limitation of the CDFS driver). */
                    716:     if (size == -1)
                    717:         size = LONG_LONG_MAX;
                    718: #endif
                    719:     bs->total_sectors = size / 512;
                    720:     s->fd = fd;
                    721:     return 0;
                    722: }
                    723: 
                    724: static int raw_read(BlockDriverState *bs, int64_t sector_num, 
                    725:                     uint8_t *buf, int nb_sectors)
                    726: {
                    727:     BDRVRawState *s = bs->opaque;
                    728:     int ret;
                    729:     
                    730:     lseek(s->fd, sector_num * 512, SEEK_SET);
                    731:     ret = read(s->fd, buf, nb_sectors * 512);
                    732:     if (ret != nb_sectors * 512) 
                    733:         return -1;
                    734:     return 0;
                    735: }
                    736: 
                    737: static int raw_write(BlockDriverState *bs, int64_t sector_num, 
                    738:                      const uint8_t *buf, int nb_sectors)
                    739: {
                    740:     BDRVRawState *s = bs->opaque;
                    741:     int ret;
                    742:     
                    743:     lseek(s->fd, sector_num * 512, SEEK_SET);
                    744:     ret = write(s->fd, buf, nb_sectors * 512);
                    745:     if (ret != nb_sectors * 512) 
                    746:         return -1;
                    747:     return 0;
                    748: }
                    749: 
                    750: static void raw_close(BlockDriverState *bs)
                    751: {
                    752:     BDRVRawState *s = bs->opaque;
                    753:     close(s->fd);
                    754: }
                    755: 
                    756: static int raw_create(const char *filename, int64_t total_size,
                    757:                       const char *backing_file, int flags)
                    758: {
                    759:     int fd;
                    760: 
                    761:     if (flags || backing_file)
                    762:         return -ENOTSUP;
                    763: 
                    764:     fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, 
                    765:               0644);
                    766:     if (fd < 0)
                    767:         return -EIO;
                    768:     ftruncate(fd, total_size * 512);
                    769:     close(fd);
                    770:     return 0;
                    771: }
                    772: 
                    773: BlockDriver bdrv_raw = {
                    774:     "raw",
                    775:     sizeof(BDRVRawState),
                    776:     raw_probe,
                    777:     raw_open,
                    778:     raw_read,
                    779:     raw_write,
                    780:     raw_close,
                    781:     raw_create,
                    782: };
                    783: 
                    784: void bdrv_init(void)
                    785: {
                    786:     bdrv_register(&bdrv_raw);
                    787: #ifndef _WIN32
                    788:     bdrv_register(&bdrv_cow);
                    789: #endif
                    790:     bdrv_register(&bdrv_qcow);
                    791:     bdrv_register(&bdrv_vmdk);
                    792:     bdrv_register(&bdrv_cloop);
                    793:     bdrv_register(&bdrv_dmg);
                    794:     bdrv_register(&bdrv_bochs);
                    795:     bdrv_register(&bdrv_vpc);
                    796:     bdrv_register(&bdrv_vvfat);
                    797: }

unix.superglobalmegacorp.com