Annotation of qemu/block.c, revision 1.1.1.2

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       root       47: static BlockDriverState *bdrv_first;
                     48: static BlockDriver *first_drv;
                     49: 
1.1.1.2 ! root       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: 
1.1       root      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
1.1.1.2 ! root      153: void get_tmp_filename(char *filename, int size)
1.1       root      154: {
1.1.1.2 ! root      155:     char* p = strrchr(filename, '/');
        !           156: 
        !           157:     if (p == NULL)
        !           158:        return;
        !           159: 
1.1       root      160:     /* XXX: find a better function */
1.1.1.2 ! root      161:     tmpnam(p);
        !           162:     *p = '/';
1.1       root      163: }
                    164: #else
1.1.1.2 ! root      165: void get_tmp_filename(char *filename, int size)
1.1       root      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
1.1.1.2 ! root      197: #ifdef CONFIG_COCOA
        !           198:         u_int32_t   blockSize = 512;
        !           199:         if ( !ioctl( fd, DKIOCGETBLOCKSIZE, &blockSize ) && blockSize > bufsize) {
        !           200:             bufsize = blockSize;
        !           201:         }
        !           202: #endif
1.1       root      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: {
1.1.1.2 ! root      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
1.1       root      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:     }
1.1.1.2 ! root      403: 
        !           404:     if (bs->drv->bdrv_make_empty)
        !           405:        return bs->drv->bdrv_make_empty(bs);
        !           406: 
1.1       root      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;
1.1.1.2 ! root      457:     if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
        !           458:         memcpy(bs->boot_sector_data, buf, 512);   
        !           459:     }
1.1       root      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
1.1.1.2 ! root      685: #ifdef CONFIG_COCOA
        !           686:         size = LONG_LONG_MAX;
        !           687: #else
        !           688:         size = lseek(fd, 0LL, SEEK_END);
        !           689: #endif
1.1       root      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