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

    1: /*
    2:  * QEMU System Emulator block driver
    3:  * 
    4:  * Copyright (c) 2003 Fabrice Bellard
    5:  * 
    6:  * Permission is hereby granted, free of charge, to any person obtaining a copy
    7:  * of this software and associated documentation files (the "Software"), to deal
    8:  * in the Software without restriction, including without limitation the rights
    9:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   10:  * copies of the Software, and to permit persons to whom the Software is
   11:  * furnished to do so, subject to the following conditions:
   12:  *
   13:  * The above copyright notice and this permission notice shall be included in
   14:  * all copies or substantial portions of the Software.
   15:  *
   16:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   17:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   18:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   19:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   20:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   21:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   22:  * THE SOFTWARE.
   23:  */
   24: #include "vl.h"
   25: #include "block_int.h"
   26: 
   27: #ifdef _BSD
   28: #include <sys/types.h>
   29: #include <sys/stat.h>
   30: #include <sys/ioctl.h>
   31: #include <sys/queue.h>
   32: #include <sys/disk.h>
   33: #endif
   34: 
   35: #define SECTOR_BITS 9
   36: #define SECTOR_SIZE (1 << SECTOR_BITS)
   37: 
   38: typedef struct BlockDriverAIOCBSync {
   39:     BlockDriverAIOCB common;
   40:     QEMUBH *bh;
   41:     int ret;
   42: } BlockDriverAIOCBSync;
   43: 
   44: static BlockDriverAIOCB *bdrv_aio_read_em(BlockDriverState *bs,
   45:         int64_t sector_num, uint8_t *buf, int nb_sectors,
   46:         BlockDriverCompletionFunc *cb, void *opaque);
   47: static BlockDriverAIOCB *bdrv_aio_write_em(BlockDriverState *bs,
   48:         int64_t sector_num, const uint8_t *buf, int nb_sectors,
   49:         BlockDriverCompletionFunc *cb, void *opaque);
   50: static void bdrv_aio_cancel_em(BlockDriverAIOCB *acb);
   51: static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num, 
   52:                         uint8_t *buf, int nb_sectors);
   53: static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
   54:                          const uint8_t *buf, int nb_sectors);
   55: 
   56: static BlockDriverState *bdrv_first;
   57: static BlockDriver *first_drv;
   58: 
   59: int path_is_absolute(const char *path)
   60: {
   61:     const char *p;
   62: #ifdef _WIN32
   63:     /* specific case for names like: "\\.\d:" */
   64:     if (*path == '/' || *path == '\\')
   65:         return 1;
   66: #endif
   67:     p = strchr(path, ':');
   68:     if (p)
   69:         p++;
   70:     else
   71:         p = path;
   72: #ifdef _WIN32
   73:     return (*p == '/' || *p == '\\');
   74: #else
   75:     return (*p == '/');
   76: #endif
   77: }
   78: 
   79: /* if filename is absolute, just copy it to dest. Otherwise, build a
   80:    path to it by considering it is relative to base_path. URL are
   81:    supported. */
   82: void path_combine(char *dest, int dest_size,
   83:                   const char *base_path,
   84:                   const char *filename)
   85: {
   86:     const char *p, *p1;
   87:     int len;
   88: 
   89:     if (dest_size <= 0)
   90:         return;
   91:     if (path_is_absolute(filename)) {
   92:         pstrcpy(dest, dest_size, filename);
   93:     } else {
   94:         p = strchr(base_path, ':');
   95:         if (p)
   96:             p++;
   97:         else
   98:             p = base_path;
   99:         p1 = strrchr(base_path, '/');
  100: #ifdef _WIN32
  101:         {
  102:             const char *p2;
  103:             p2 = strrchr(base_path, '\\');
  104:             if (!p1 || p2 > p1)
  105:                 p1 = p2;
  106:         }
  107: #endif
  108:         if (p1)
  109:             p1++;
  110:         else
  111:             p1 = base_path;
  112:         if (p1 > p)
  113:             p = p1;
  114:         len = p - base_path;
  115:         if (len > dest_size - 1)
  116:             len = dest_size - 1;
  117:         memcpy(dest, base_path, len);
  118:         dest[len] = '\0';
  119:         pstrcat(dest, dest_size, filename);
  120:     }
  121: }
  122: 
  123: 
  124: void bdrv_register(BlockDriver *bdrv)
  125: {
  126:     if (!bdrv->bdrv_aio_read) {
  127:         /* add AIO emulation layer */
  128:         bdrv->bdrv_aio_read = bdrv_aio_read_em;
  129:         bdrv->bdrv_aio_write = bdrv_aio_write_em;
  130:         bdrv->bdrv_aio_cancel = bdrv_aio_cancel_em;
  131:         bdrv->aiocb_size = sizeof(BlockDriverAIOCBSync);
  132:     } else if (!bdrv->bdrv_read && !bdrv->bdrv_pread) {
  133:         /* add synchronous IO emulation layer */
  134:         bdrv->bdrv_read = bdrv_read_em;
  135:         bdrv->bdrv_write = bdrv_write_em;
  136:     }
  137:     bdrv->next = first_drv;
  138:     first_drv = bdrv;
  139: }
  140: 
  141: /* create a new block device (by default it is empty) */
  142: BlockDriverState *bdrv_new(const char *device_name)
  143: {
  144:     BlockDriverState **pbs, *bs;
  145: 
  146:     bs = qemu_mallocz(sizeof(BlockDriverState));
  147:     if(!bs)
  148:         return NULL;
  149:     pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
  150:     if (device_name[0] != '\0') {
  151:         /* insert at the end */
  152:         pbs = &bdrv_first;
  153:         while (*pbs != NULL)
  154:             pbs = &(*pbs)->next;
  155:         *pbs = bs;
  156:     }
  157:     return bs;
  158: }
  159: 
  160: BlockDriver *bdrv_find_format(const char *format_name)
  161: {
  162:     BlockDriver *drv1;
  163:     for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
  164:         if (!strcmp(drv1->format_name, format_name))
  165:             return drv1;
  166:     }
  167:     return NULL;
  168: }
  169: 
  170: int bdrv_create(BlockDriver *drv, 
  171:                 const char *filename, int64_t size_in_sectors,
  172:                 const char *backing_file, int flags)
  173: {
  174:     if (!drv->bdrv_create)
  175:         return -ENOTSUP;
  176:     return drv->bdrv_create(filename, size_in_sectors, backing_file, flags);
  177: }
  178: 
  179: #ifdef _WIN32
  180: void get_tmp_filename(char *filename, int size)
  181: {
  182:     char temp_dir[MAX_PATH];
  183:     
  184:     GetTempPath(MAX_PATH, temp_dir);
  185:     GetTempFileName(temp_dir, "qem", 0, filename);
  186: }
  187: #else
  188: void get_tmp_filename(char *filename, int size)
  189: {
  190:     int fd;
  191:     /* XXX: race condition possible */
  192:     pstrcpy(filename, size, "/tmp/vl.XXXXXX");
  193:     fd = mkstemp(filename);
  194:     close(fd);
  195: }
  196: #endif
  197: 
  198: #ifdef _WIN32
  199: static int is_windows_drive_prefix(const char *filename)
  200: {
  201:     return (((filename[0] >= 'a' && filename[0] <= 'z') ||
  202:              (filename[0] >= 'A' && filename[0] <= 'Z')) &&
  203:             filename[1] == ':');
  204: }
  205:     
  206: static int is_windows_drive(const char *filename)
  207: {
  208:     if (is_windows_drive_prefix(filename) && 
  209:         filename[2] == '\0')
  210:         return 1;
  211:     if (strstart(filename, "\\\\.\\", NULL) ||
  212:         strstart(filename, "//./", NULL))
  213:         return 1;
  214:     return 0;
  215: }
  216: #endif
  217: 
  218: static BlockDriver *find_protocol(const char *filename)
  219: {
  220:     BlockDriver *drv1;
  221:     char protocol[128];
  222:     int len;
  223:     const char *p;
  224: 
  225: #ifdef _WIN32
  226:     if (is_windows_drive(filename) ||
  227:         is_windows_drive_prefix(filename))
  228:         return &bdrv_raw;
  229: #endif
  230:     p = strchr(filename, ':');
  231:     if (!p)
  232:         return &bdrv_raw;
  233:     len = p - filename;
  234:     if (len > sizeof(protocol) - 1)
  235:         len = sizeof(protocol) - 1;
  236:     memcpy(protocol, filename, len);
  237:     protocol[len] = '\0';
  238:     for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
  239:         if (drv1->protocol_name && 
  240:             !strcmp(drv1->protocol_name, protocol))
  241:             return drv1;
  242:     }
  243:     return NULL;
  244: }
  245: 
  246: /* XXX: force raw format if block or character device ? It would
  247:    simplify the BSD case */
  248: static BlockDriver *find_image_format(const char *filename)
  249: {
  250:     int ret, score, score_max;
  251:     BlockDriver *drv1, *drv;
  252:     uint8_t buf[2048];
  253:     BlockDriverState *bs;
  254:     
  255:     /* detect host devices. By convention, /dev/cdrom[N] is always
  256:        recognized as a host CDROM */
  257:     if (strstart(filename, "/dev/cdrom", NULL))
  258:         return &bdrv_host_device;
  259: #ifdef _WIN32
  260:     if (is_windows_drive(filename))
  261:         return &bdrv_host_device;
  262: #else
  263:     {
  264:         struct stat st;
  265:         if (stat(filename, &st) >= 0 && 
  266:             (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))) {
  267:             return &bdrv_host_device;
  268:         }
  269:     }
  270: #endif
  271:     
  272:     drv = find_protocol(filename);
  273:     /* no need to test disk image formats for vvfat */
  274:     if (drv == &bdrv_vvfat)
  275:         return drv;
  276: 
  277:     ret = bdrv_file_open(&bs, filename, BDRV_O_RDONLY);
  278:     if (ret < 0)
  279:         return NULL;
  280:     ret = bdrv_pread(bs, 0, buf, sizeof(buf));
  281:     bdrv_delete(bs);
  282:     if (ret < 0) {
  283:         return NULL;
  284:     }
  285: 
  286:     score_max = 0;
  287:     for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
  288:         if (drv1->bdrv_probe) {
  289:             score = drv1->bdrv_probe(buf, ret, filename);
  290:             if (score > score_max) {
  291:                 score_max = score;
  292:                 drv = drv1;
  293:             }
  294:         }
  295:     }
  296:     return drv;
  297: }
  298: 
  299: int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags)
  300: {
  301:     BlockDriverState *bs;
  302:     int ret;
  303: 
  304:     bs = bdrv_new("");
  305:     if (!bs)
  306:         return -ENOMEM;
  307:     ret = bdrv_open2(bs, filename, flags | BDRV_O_FILE, NULL);
  308:     if (ret < 0) {
  309:         bdrv_delete(bs);
  310:         return ret;
  311:     }
  312:     *pbs = bs;
  313:     return 0;
  314: }
  315: 
  316: int bdrv_open(BlockDriverState *bs, const char *filename, int flags)
  317: {
  318:     return bdrv_open2(bs, filename, flags, NULL);
  319: }
  320: 
  321: int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
  322:                BlockDriver *drv)
  323: {
  324:     int ret, open_flags;
  325:     char tmp_filename[1024];
  326:     char backing_filename[1024];
  327:     
  328:     bs->read_only = 0;
  329:     bs->is_temporary = 0;
  330:     bs->encrypted = 0;
  331: 
  332:     if (flags & BDRV_O_SNAPSHOT) {
  333:         BlockDriverState *bs1;
  334:         int64_t total_size;
  335:         
  336:         /* if snapshot, we create a temporary backing file and open it
  337:            instead of opening 'filename' directly */
  338: 
  339:         /* if there is a backing file, use it */
  340:         bs1 = bdrv_new("");
  341:         if (!bs1) {
  342:             return -ENOMEM;
  343:         }
  344:         if (bdrv_open(bs1, filename, 0) < 0) {
  345:             bdrv_delete(bs1);
  346:             return -1;
  347:         }
  348:         total_size = bdrv_getlength(bs1) >> SECTOR_BITS;
  349:         bdrv_delete(bs1);
  350:         
  351:         get_tmp_filename(tmp_filename, sizeof(tmp_filename));
  352:         realpath(filename, backing_filename);
  353:         if (bdrv_create(&bdrv_qcow2, tmp_filename, 
  354:                         total_size, backing_filename, 0) < 0) {
  355:             return -1;
  356:         }
  357:         filename = tmp_filename;
  358:         bs->is_temporary = 1;
  359:     }
  360: 
  361:     pstrcpy(bs->filename, sizeof(bs->filename), filename);
  362:     if (flags & BDRV_O_FILE) {
  363:         drv = find_protocol(filename);
  364:         if (!drv)
  365:             return -ENOENT;
  366:     } else {
  367:         if (!drv) {
  368:             drv = find_image_format(filename);
  369:             if (!drv)
  370:                 return -1;
  371:         }
  372:     }
  373:     bs->drv = drv;
  374:     bs->opaque = qemu_mallocz(drv->instance_size);
  375:     if (bs->opaque == NULL && drv->instance_size > 0)
  376:         return -1;
  377:     /* Note: for compatibility, we open disk image files as RDWR, and
  378:        RDONLY as fallback */
  379:     if (!(flags & BDRV_O_FILE))
  380:         open_flags = BDRV_O_RDWR;
  381:     else
  382:         open_flags = flags & ~(BDRV_O_FILE | BDRV_O_SNAPSHOT);
  383:     ret = drv->bdrv_open(bs, filename, open_flags);
  384:     if (ret == -EACCES && !(flags & BDRV_O_FILE)) {
  385:         ret = drv->bdrv_open(bs, filename, BDRV_O_RDONLY);
  386:         bs->read_only = 1;
  387:     }
  388:     if (ret < 0) {
  389:         qemu_free(bs->opaque);
  390:         bs->opaque = NULL;
  391:         bs->drv = NULL;
  392:         return ret;
  393:     }
  394:     if (drv->bdrv_getlength) {
  395:         bs->total_sectors = bdrv_getlength(bs) >> SECTOR_BITS;
  396:     }
  397: #ifndef _WIN32
  398:     if (bs->is_temporary) {
  399:         unlink(filename);
  400:     }
  401: #endif
  402:     if (bs->backing_file[0] != '\0') {
  403:         /* if there is a backing file, use it */
  404:         bs->backing_hd = bdrv_new("");
  405:         if (!bs->backing_hd) {
  406:         fail:
  407:             bdrv_close(bs);
  408:             return -ENOMEM;
  409:         }
  410:         path_combine(backing_filename, sizeof(backing_filename),
  411:                      filename, bs->backing_file);
  412:         if (bdrv_open(bs->backing_hd, backing_filename, 0) < 0)
  413:             goto fail;
  414:     }
  415: 
  416:     /* call the change callback */
  417:     bs->media_changed = 1;
  418:     if (bs->change_cb)
  419:         bs->change_cb(bs->change_opaque);
  420: 
  421:     return 0;
  422: }
  423: 
  424: void bdrv_close(BlockDriverState *bs)
  425: {
  426:     if (bs->drv) {
  427:         if (bs->backing_hd)
  428:             bdrv_delete(bs->backing_hd);
  429:         bs->drv->bdrv_close(bs);
  430:         qemu_free(bs->opaque);
  431: #ifdef _WIN32
  432:         if (bs->is_temporary) {
  433:             unlink(bs->filename);
  434:         }
  435: #endif
  436:         bs->opaque = NULL;
  437:         bs->drv = NULL;
  438: 
  439:         /* call the change callback */
  440:         bs->media_changed = 1;
  441:         if (bs->change_cb)
  442:             bs->change_cb(bs->change_opaque);
  443:     }
  444: }
  445: 
  446: void bdrv_delete(BlockDriverState *bs)
  447: {
  448:     /* XXX: remove the driver list */
  449:     bdrv_close(bs);
  450:     qemu_free(bs);
  451: }
  452: 
  453: /* commit COW file into the raw image */
  454: int bdrv_commit(BlockDriverState *bs)
  455: {
  456:     BlockDriver *drv = bs->drv;
  457:     int64_t i, total_sectors;
  458:     int n, j;
  459:     unsigned char sector[512];
  460: 
  461:     if (!drv)
  462:         return -ENOMEDIUM;
  463: 
  464:     if (bs->read_only) {
  465: 	return -EACCES;
  466:     }
  467: 
  468:     if (!bs->backing_hd) {
  469: 	return -ENOTSUP;
  470:     }
  471: 
  472:     total_sectors = bdrv_getlength(bs) >> SECTOR_BITS;
  473:     for (i = 0; i < total_sectors;) {
  474:         if (drv->bdrv_is_allocated(bs, i, 65536, &n)) {
  475:             for(j = 0; j < n; j++) {
  476:                 if (bdrv_read(bs, i, sector, 1) != 0) {
  477:                     return -EIO;
  478:                 }
  479: 
  480:                 if (bdrv_write(bs->backing_hd, i, sector, 1) != 0) {
  481:                     return -EIO;
  482:                 }
  483:                 i++;
  484: 	    }
  485: 	} else {
  486:             i += n;
  487:         }
  488:     }
  489: 
  490:     if (drv->bdrv_make_empty)
  491: 	return drv->bdrv_make_empty(bs);
  492: 
  493:     return 0;
  494: }
  495: 
  496: /* return < 0 if error. See bdrv_write() for the return codes */
  497: int bdrv_read(BlockDriverState *bs, int64_t sector_num, 
  498:               uint8_t *buf, int nb_sectors)
  499: {
  500:     BlockDriver *drv = bs->drv;
  501: 
  502:     if (!drv)
  503:         return -ENOMEDIUM;
  504: 
  505:     if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
  506:             memcpy(buf, bs->boot_sector_data, 512);
  507:         sector_num++;
  508:         nb_sectors--;
  509:         buf += 512;
  510:         if (nb_sectors == 0)
  511:             return 0;
  512:     }
  513:     if (drv->bdrv_pread) {
  514:         int ret, len;
  515:         len = nb_sectors * 512;
  516:         ret = drv->bdrv_pread(bs, sector_num * 512, buf, len);
  517:         if (ret < 0)
  518:             return ret;
  519:         else if (ret != len)
  520:             return -EINVAL;
  521:         else
  522:             return 0;
  523:     } else {
  524:         return drv->bdrv_read(bs, sector_num, buf, nb_sectors);
  525:     }
  526: }
  527: 
  528: /* Return < 0 if error. Important errors are: 
  529:   -EIO         generic I/O error (may happen for all errors)
  530:   -ENOMEDIUM   No media inserted.
  531:   -EINVAL      Invalid sector number or nb_sectors
  532:   -EACCES      Trying to write a read-only device
  533: */
  534: int bdrv_write(BlockDriverState *bs, int64_t sector_num, 
  535:                const uint8_t *buf, int nb_sectors)
  536: {
  537:     BlockDriver *drv = bs->drv;
  538:     if (!bs->drv)
  539:         return -ENOMEDIUM;
  540:     if (bs->read_only)
  541:         return -EACCES;
  542:     if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
  543:         memcpy(bs->boot_sector_data, buf, 512);   
  544:     }
  545:     if (drv->bdrv_pwrite) {
  546:         int ret, len;
  547:         len = nb_sectors * 512;
  548:         ret = drv->bdrv_pwrite(bs, sector_num * 512, buf, len);
  549:         if (ret < 0)
  550:             return ret;
  551:         else if (ret != len)
  552:             return -EIO;
  553:         else
  554:             return 0;
  555:     } else {
  556:         return drv->bdrv_write(bs, sector_num, buf, nb_sectors);
  557:     }
  558: }
  559: 
  560: static int bdrv_pread_em(BlockDriverState *bs, int64_t offset, 
  561:                          uint8_t *buf, int count1)
  562: {
  563:     uint8_t tmp_buf[SECTOR_SIZE];
  564:     int len, nb_sectors, count;
  565:     int64_t sector_num;
  566: 
  567:     count = count1;
  568:     /* first read to align to sector start */
  569:     len = (SECTOR_SIZE - offset) & (SECTOR_SIZE - 1);
  570:     if (len > count)
  571:         len = count;
  572:     sector_num = offset >> SECTOR_BITS;
  573:     if (len > 0) {
  574:         if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
  575:             return -EIO;
  576:         memcpy(buf, tmp_buf + (offset & (SECTOR_SIZE - 1)), len);
  577:         count -= len;
  578:         if (count == 0)
  579:             return count1;
  580:         sector_num++;
  581:         buf += len;
  582:     }
  583: 
  584:     /* read the sectors "in place" */
  585:     nb_sectors = count >> SECTOR_BITS;
  586:     if (nb_sectors > 0) {
  587:         if (bdrv_read(bs, sector_num, buf, nb_sectors) < 0)
  588:             return -EIO;
  589:         sector_num += nb_sectors;
  590:         len = nb_sectors << SECTOR_BITS;
  591:         buf += len;
  592:         count -= len;
  593:     }
  594: 
  595:     /* add data from the last sector */
  596:     if (count > 0) {
  597:         if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
  598:             return -EIO;
  599:         memcpy(buf, tmp_buf, count);
  600:     }
  601:     return count1;
  602: }
  603: 
  604: static int bdrv_pwrite_em(BlockDriverState *bs, int64_t offset, 
  605:                           const uint8_t *buf, int count1)
  606: {
  607:     uint8_t tmp_buf[SECTOR_SIZE];
  608:     int len, nb_sectors, count;
  609:     int64_t sector_num;
  610: 
  611:     count = count1;
  612:     /* first write to align to sector start */
  613:     len = (SECTOR_SIZE - offset) & (SECTOR_SIZE - 1);
  614:     if (len > count)
  615:         len = count;
  616:     sector_num = offset >> SECTOR_BITS;
  617:     if (len > 0) {
  618:         if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
  619:             return -EIO;
  620:         memcpy(tmp_buf + (offset & (SECTOR_SIZE - 1)), buf, len);
  621:         if (bdrv_write(bs, sector_num, tmp_buf, 1) < 0)
  622:             return -EIO;
  623:         count -= len;
  624:         if (count == 0)
  625:             return count1;
  626:         sector_num++;
  627:         buf += len;
  628:     }
  629: 
  630:     /* write the sectors "in place" */
  631:     nb_sectors = count >> SECTOR_BITS;
  632:     if (nb_sectors > 0) {
  633:         if (bdrv_write(bs, sector_num, buf, nb_sectors) < 0)
  634:             return -EIO;
  635:         sector_num += nb_sectors;
  636:         len = nb_sectors << SECTOR_BITS;
  637:         buf += len;
  638:         count -= len;
  639:     }
  640: 
  641:     /* add data from the last sector */
  642:     if (count > 0) {
  643:         if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
  644:             return -EIO;
  645:         memcpy(tmp_buf, buf, count);
  646:         if (bdrv_write(bs, sector_num, tmp_buf, 1) < 0)
  647:             return -EIO;
  648:     }
  649:     return count1;
  650: }
  651: 
  652: /**
  653:  * Read with byte offsets (needed only for file protocols) 
  654:  */
  655: int bdrv_pread(BlockDriverState *bs, int64_t offset, 
  656:                void *buf1, int count1)
  657: {
  658:     BlockDriver *drv = bs->drv;
  659: 
  660:     if (!drv)
  661:         return -ENOMEDIUM;
  662:     if (!drv->bdrv_pread)
  663:         return bdrv_pread_em(bs, offset, buf1, count1);
  664:     return drv->bdrv_pread(bs, offset, buf1, count1);
  665: }
  666: 
  667: /** 
  668:  * Write with byte offsets (needed only for file protocols) 
  669:  */
  670: int bdrv_pwrite(BlockDriverState *bs, int64_t offset, 
  671:                 const void *buf1, int count1)
  672: {
  673:     BlockDriver *drv = bs->drv;
  674: 
  675:     if (!drv)
  676:         return -ENOMEDIUM;
  677:     if (!drv->bdrv_pwrite)
  678:         return bdrv_pwrite_em(bs, offset, buf1, count1);
  679:     return drv->bdrv_pwrite(bs, offset, buf1, count1);
  680: }
  681: 
  682: /**
  683:  * Truncate file to 'offset' bytes (needed only for file protocols)
  684:  */
  685: int bdrv_truncate(BlockDriverState *bs, int64_t offset)
  686: {
  687:     BlockDriver *drv = bs->drv;
  688:     if (!drv)
  689:         return -ENOMEDIUM;
  690:     if (!drv->bdrv_truncate)
  691:         return -ENOTSUP;
  692:     return drv->bdrv_truncate(bs, offset);
  693: }
  694: 
  695: /**
  696:  * Length of a file in bytes. Return < 0 if error or unknown.
  697:  */
  698: int64_t bdrv_getlength(BlockDriverState *bs)
  699: {
  700:     BlockDriver *drv = bs->drv;
  701:     if (!drv)
  702:         return -ENOMEDIUM;
  703:     if (!drv->bdrv_getlength) {
  704:         /* legacy mode */
  705:         return bs->total_sectors * SECTOR_SIZE;
  706:     }
  707:     return drv->bdrv_getlength(bs);
  708: }
  709: 
  710: /* return 0 as number of sectors if no device present or error */
  711: void bdrv_get_geometry(BlockDriverState *bs, int64_t *nb_sectors_ptr)
  712: {
  713:     int64_t length;
  714:     length = bdrv_getlength(bs);
  715:     if (length < 0)
  716:         length = 0;
  717:     else
  718:         length = length >> SECTOR_BITS;
  719:     *nb_sectors_ptr = length;
  720: }
  721: 
  722: /* force a given boot sector. */
  723: void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size)
  724: {
  725:     bs->boot_sector_enabled = 1;
  726:     if (size > 512)
  727:         size = 512;
  728:     memcpy(bs->boot_sector_data, data, size);
  729:     memset(bs->boot_sector_data + size, 0, 512 - size);
  730: }
  731: 
  732: void bdrv_set_geometry_hint(BlockDriverState *bs, 
  733:                             int cyls, int heads, int secs)
  734: {
  735:     bs->cyls = cyls;
  736:     bs->heads = heads;
  737:     bs->secs = secs;
  738: }
  739: 
  740: void bdrv_set_type_hint(BlockDriverState *bs, int type)
  741: {
  742:     bs->type = type;
  743:     bs->removable = ((type == BDRV_TYPE_CDROM ||
  744:                       type == BDRV_TYPE_FLOPPY));
  745: }
  746: 
  747: void bdrv_set_translation_hint(BlockDriverState *bs, int translation)
  748: {
  749:     bs->translation = translation;
  750: }
  751: 
  752: void bdrv_get_geometry_hint(BlockDriverState *bs, 
  753:                             int *pcyls, int *pheads, int *psecs)
  754: {
  755:     *pcyls = bs->cyls;
  756:     *pheads = bs->heads;
  757:     *psecs = bs->secs;
  758: }
  759: 
  760: int bdrv_get_type_hint(BlockDriverState *bs)
  761: {
  762:     return bs->type;
  763: }
  764: 
  765: int bdrv_get_translation_hint(BlockDriverState *bs)
  766: {
  767:     return bs->translation;
  768: }
  769: 
  770: int bdrv_is_removable(BlockDriverState *bs)
  771: {
  772:     return bs->removable;
  773: }
  774: 
  775: int bdrv_is_read_only(BlockDriverState *bs)
  776: {
  777:     return bs->read_only;
  778: }
  779: 
  780: /* XXX: no longer used */
  781: void bdrv_set_change_cb(BlockDriverState *bs, 
  782:                         void (*change_cb)(void *opaque), void *opaque)
  783: {
  784:     bs->change_cb = change_cb;
  785:     bs->change_opaque = opaque;
  786: }
  787: 
  788: int bdrv_is_encrypted(BlockDriverState *bs)
  789: {
  790:     if (bs->backing_hd && bs->backing_hd->encrypted)
  791:         return 1;
  792:     return bs->encrypted;
  793: }
  794: 
  795: int bdrv_set_key(BlockDriverState *bs, const char *key)
  796: {
  797:     int ret;
  798:     if (bs->backing_hd && bs->backing_hd->encrypted) {
  799:         ret = bdrv_set_key(bs->backing_hd, key);
  800:         if (ret < 0)
  801:             return ret;
  802:         if (!bs->encrypted)
  803:             return 0;
  804:     }
  805:     if (!bs->encrypted || !bs->drv || !bs->drv->bdrv_set_key)
  806:         return -1;
  807:     return bs->drv->bdrv_set_key(bs, key);
  808: }
  809: 
  810: void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size)
  811: {
  812:     if (!bs->drv) {
  813:         buf[0] = '\0';
  814:     } else {
  815:         pstrcpy(buf, buf_size, bs->drv->format_name);
  816:     }
  817: }
  818: 
  819: void bdrv_iterate_format(void (*it)(void *opaque, const char *name), 
  820:                          void *opaque)
  821: {
  822:     BlockDriver *drv;
  823: 
  824:     for (drv = first_drv; drv != NULL; drv = drv->next) {
  825:         it(opaque, drv->format_name);
  826:     }
  827: }
  828: 
  829: BlockDriverState *bdrv_find(const char *name)
  830: {
  831:     BlockDriverState *bs;
  832: 
  833:     for (bs = bdrv_first; bs != NULL; bs = bs->next) {
  834:         if (!strcmp(name, bs->device_name))
  835:             return bs;
  836:     }
  837:     return NULL;
  838: }
  839: 
  840: void bdrv_iterate(void (*it)(void *opaque, const char *name), void *opaque)
  841: {
  842:     BlockDriverState *bs;
  843: 
  844:     for (bs = bdrv_first; bs != NULL; bs = bs->next) {
  845:         it(opaque, bs->device_name);
  846:     }
  847: }
  848: 
  849: const char *bdrv_get_device_name(BlockDriverState *bs)
  850: {
  851:     return bs->device_name;
  852: }
  853: 
  854: void bdrv_flush(BlockDriverState *bs)
  855: {
  856:     if (bs->drv->bdrv_flush)
  857:         bs->drv->bdrv_flush(bs);
  858:     if (bs->backing_hd)
  859:         bdrv_flush(bs->backing_hd);
  860: }
  861: 
  862: void bdrv_info(void)
  863: {
  864:     BlockDriverState *bs;
  865: 
  866:     for (bs = bdrv_first; bs != NULL; bs = bs->next) {
  867:         term_printf("%s:", bs->device_name);
  868:         term_printf(" type=");
  869:         switch(bs->type) {
  870:         case BDRV_TYPE_HD:
  871:             term_printf("hd");
  872:             break;
  873:         case BDRV_TYPE_CDROM:
  874:             term_printf("cdrom");
  875:             break;
  876:         case BDRV_TYPE_FLOPPY:
  877:             term_printf("floppy");
  878:             break;
  879:         }
  880:         term_printf(" removable=%d", bs->removable);
  881:         if (bs->removable) {
  882:             term_printf(" locked=%d", bs->locked);
  883:         }
  884:         if (bs->drv) {
  885:             term_printf(" file=");
  886: 	    term_print_filename(bs->filename);
  887:             if (bs->backing_file[0] != '\0') {
  888:                 term_printf(" backing_file=");
  889: 		term_print_filename(bs->backing_file);
  890: 	    }
  891:             term_printf(" ro=%d", bs->read_only);
  892:             term_printf(" drv=%s", bs->drv->format_name);
  893:             if (bs->encrypted)
  894:                 term_printf(" encrypted");
  895:         } else {
  896:             term_printf(" [not inserted]");
  897:         }
  898:         term_printf("\n");
  899:     }
  900: }
  901: 
  902: void bdrv_get_backing_filename(BlockDriverState *bs, 
  903:                                char *filename, int filename_size)
  904: {
  905:     if (!bs->backing_hd) {
  906:         pstrcpy(filename, filename_size, "");
  907:     } else {
  908:         pstrcpy(filename, filename_size, bs->backing_file);
  909:     }
  910: }
  911: 
  912: int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num, 
  913:                           const uint8_t *buf, int nb_sectors)
  914: {
  915:     BlockDriver *drv = bs->drv;
  916:     if (!drv)
  917:         return -ENOMEDIUM;
  918:     if (!drv->bdrv_write_compressed)
  919:         return -ENOTSUP;
  920:     return drv->bdrv_write_compressed(bs, sector_num, buf, nb_sectors);
  921: }
  922:     
  923: int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
  924: {
  925:     BlockDriver *drv = bs->drv;
  926:     if (!drv)
  927:         return -ENOMEDIUM;
  928:     if (!drv->bdrv_get_info)
  929:         return -ENOTSUP;
  930:     memset(bdi, 0, sizeof(*bdi));
  931:     return drv->bdrv_get_info(bs, bdi);
  932: }
  933: 
  934: /**************************************************************/
  935: /* handling of snapshots */
  936: 
  937: int bdrv_snapshot_create(BlockDriverState *bs, 
  938:                          QEMUSnapshotInfo *sn_info)
  939: {
  940:     BlockDriver *drv = bs->drv;
  941:     if (!drv)
  942:         return -ENOMEDIUM;
  943:     if (!drv->bdrv_snapshot_create)
  944:         return -ENOTSUP;
  945:     return drv->bdrv_snapshot_create(bs, sn_info);
  946: }
  947: 
  948: int bdrv_snapshot_goto(BlockDriverState *bs, 
  949:                        const char *snapshot_id)
  950: {
  951:     BlockDriver *drv = bs->drv;
  952:     if (!drv)
  953:         return -ENOMEDIUM;
  954:     if (!drv->bdrv_snapshot_goto)
  955:         return -ENOTSUP;
  956:     return drv->bdrv_snapshot_goto(bs, snapshot_id);
  957: }
  958: 
  959: int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id)
  960: {
  961:     BlockDriver *drv = bs->drv;
  962:     if (!drv)
  963:         return -ENOMEDIUM;
  964:     if (!drv->bdrv_snapshot_delete)
  965:         return -ENOTSUP;
  966:     return drv->bdrv_snapshot_delete(bs, snapshot_id);
  967: }
  968: 
  969: int bdrv_snapshot_list(BlockDriverState *bs, 
  970:                        QEMUSnapshotInfo **psn_info)
  971: {
  972:     BlockDriver *drv = bs->drv;
  973:     if (!drv)
  974:         return -ENOMEDIUM;
  975:     if (!drv->bdrv_snapshot_list)
  976:         return -ENOTSUP;
  977:     return drv->bdrv_snapshot_list(bs, psn_info);
  978: }
  979: 
  980: #define NB_SUFFIXES 4
  981: 
  982: char *get_human_readable_size(char *buf, int buf_size, int64_t size)
  983: {
  984:     static const char suffixes[NB_SUFFIXES] = "KMGT";
  985:     int64_t base;
  986:     int i;
  987: 
  988:     if (size <= 999) {
  989:         snprintf(buf, buf_size, "%" PRId64, size);
  990:     } else {
  991:         base = 1024;
  992:         for(i = 0; i < NB_SUFFIXES; i++) {
  993:             if (size < (10 * base)) {
  994:                 snprintf(buf, buf_size, "%0.1f%c", 
  995:                          (double)size / base,
  996:                          suffixes[i]);
  997:                 break;
  998:             } else if (size < (1000 * base) || i == (NB_SUFFIXES - 1)) {
  999:                 snprintf(buf, buf_size, "%" PRId64 "%c", 
 1000:                          ((size + (base >> 1)) / base),
 1001:                          suffixes[i]);
 1002:                 break;
 1003:             }
 1004:             base = base * 1024;
 1005:         }
 1006:     }
 1007:     return buf;
 1008: }
 1009: 
 1010: char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn)
 1011: {
 1012:     char buf1[128], date_buf[128], clock_buf[128];
 1013: #ifdef _WIN32
 1014:     struct tm *ptm;
 1015: #else
 1016:     struct tm tm;
 1017: #endif
 1018:     time_t ti;
 1019:     int64_t secs;
 1020: 
 1021:     if (!sn) {
 1022:         snprintf(buf, buf_size, 
 1023:                  "%-10s%-20s%7s%20s%15s", 
 1024:                  "ID", "TAG", "VM SIZE", "DATE", "VM CLOCK");
 1025:     } else {
 1026:         ti = sn->date_sec;
 1027: #ifdef _WIN32
 1028:         ptm = localtime(&ti);
 1029:         strftime(date_buf, sizeof(date_buf),
 1030:                  "%Y-%m-%d %H:%M:%S", ptm);
 1031: #else
 1032:         localtime_r(&ti, &tm);
 1033:         strftime(date_buf, sizeof(date_buf),
 1034:                  "%Y-%m-%d %H:%M:%S", &tm);
 1035: #endif
 1036:         secs = sn->vm_clock_nsec / 1000000000;
 1037:         snprintf(clock_buf, sizeof(clock_buf),
 1038:                  "%02d:%02d:%02d.%03d",
 1039:                  (int)(secs / 3600),
 1040:                  (int)((secs / 60) % 60),
 1041:                  (int)(secs % 60), 
 1042:                  (int)((sn->vm_clock_nsec / 1000000) % 1000));
 1043:         snprintf(buf, buf_size,
 1044:                  "%-10s%-20s%7s%20s%15s", 
 1045:                  sn->id_str, sn->name,
 1046:                  get_human_readable_size(buf1, sizeof(buf1), sn->vm_state_size),
 1047:                  date_buf,
 1048:                  clock_buf);
 1049:     }
 1050:     return buf;
 1051: }
 1052: 
 1053: 
 1054: /**************************************************************/
 1055: /* async I/Os */
 1056: 
 1057: BlockDriverAIOCB *bdrv_aio_read(BlockDriverState *bs, int64_t sector_num,
 1058:                                 uint8_t *buf, int nb_sectors,
 1059:                                 BlockDriverCompletionFunc *cb, void *opaque)
 1060: {
 1061:     BlockDriver *drv = bs->drv;
 1062: 
 1063:     if (!drv)
 1064:         return NULL;
 1065:     
 1066:     /* XXX: we assume that nb_sectors == 0 is suppored by the async read */
 1067:     if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
 1068:         memcpy(buf, bs->boot_sector_data, 512);
 1069:         sector_num++;
 1070:         nb_sectors--;
 1071:         buf += 512;
 1072:     }
 1073: 
 1074:     return drv->bdrv_aio_read(bs, sector_num, buf, nb_sectors, cb, opaque);
 1075: }
 1076: 
 1077: BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, int64_t sector_num,
 1078:                                  const uint8_t *buf, int nb_sectors,
 1079:                                  BlockDriverCompletionFunc *cb, void *opaque)
 1080: {
 1081:     BlockDriver *drv = bs->drv;
 1082: 
 1083:     if (!drv)
 1084:         return NULL;
 1085:     if (bs->read_only)
 1086:         return NULL;
 1087:     if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
 1088:         memcpy(bs->boot_sector_data, buf, 512);   
 1089:     }
 1090: 
 1091:     return drv->bdrv_aio_write(bs, sector_num, buf, nb_sectors, cb, opaque);
 1092: }
 1093: 
 1094: void bdrv_aio_cancel(BlockDriverAIOCB *acb)
 1095: {
 1096:     BlockDriver *drv = acb->bs->drv;
 1097: 
 1098:     drv->bdrv_aio_cancel(acb);
 1099: }
 1100: 
 1101: 
 1102: /**************************************************************/
 1103: /* async block device emulation */
 1104: 
 1105: #ifdef QEMU_TOOL
 1106: static BlockDriverAIOCB *bdrv_aio_read_em(BlockDriverState *bs,
 1107:         int64_t sector_num, uint8_t *buf, int nb_sectors,
 1108:         BlockDriverCompletionFunc *cb, void *opaque)
 1109: {
 1110:     int ret;
 1111:     ret = bdrv_read(bs, sector_num, buf, nb_sectors);
 1112:     cb(opaque, ret);
 1113:     return NULL;
 1114: }
 1115: 
 1116: static BlockDriverAIOCB *bdrv_aio_write_em(BlockDriverState *bs,
 1117:         int64_t sector_num, const uint8_t *buf, int nb_sectors,
 1118:         BlockDriverCompletionFunc *cb, void *opaque)
 1119: {
 1120:     int ret;
 1121:     ret = bdrv_write(bs, sector_num, buf, nb_sectors);
 1122:     cb(opaque, ret);
 1123:     return NULL;
 1124: }
 1125: 
 1126: static void bdrv_aio_cancel_em(BlockDriverAIOCB *acb)
 1127: {
 1128: }
 1129: #else
 1130: static void bdrv_aio_bh_cb(void *opaque)
 1131: {
 1132:     BlockDriverAIOCBSync *acb = opaque;
 1133:     acb->common.cb(acb->common.opaque, acb->ret);
 1134:     qemu_aio_release(acb);
 1135: }
 1136: 
 1137: static BlockDriverAIOCB *bdrv_aio_read_em(BlockDriverState *bs,
 1138:         int64_t sector_num, uint8_t *buf, int nb_sectors,
 1139:         BlockDriverCompletionFunc *cb, void *opaque)
 1140: {
 1141:     BlockDriverAIOCBSync *acb;
 1142:     int ret;
 1143: 
 1144:     acb = qemu_aio_get(bs, cb, opaque);
 1145:     if (!acb->bh)
 1146:         acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
 1147:     ret = bdrv_read(bs, sector_num, buf, nb_sectors);
 1148:     acb->ret = ret;
 1149:     qemu_bh_schedule(acb->bh);
 1150:     return &acb->common;
 1151: }
 1152: 
 1153: static BlockDriverAIOCB *bdrv_aio_write_em(BlockDriverState *bs,
 1154:         int64_t sector_num, const uint8_t *buf, int nb_sectors,
 1155:         BlockDriverCompletionFunc *cb, void *opaque)
 1156: {
 1157:     BlockDriverAIOCBSync *acb;
 1158:     int ret;
 1159: 
 1160:     acb = qemu_aio_get(bs, cb, opaque);
 1161:     if (!acb->bh)
 1162:         acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
 1163:     ret = bdrv_write(bs, sector_num, buf, nb_sectors);
 1164:     acb->ret = ret;
 1165:     qemu_bh_schedule(acb->bh);
 1166:     return &acb->common;
 1167: }
 1168: 
 1169: static void bdrv_aio_cancel_em(BlockDriverAIOCB *blockacb)
 1170: {
 1171:     BlockDriverAIOCBSync *acb = (BlockDriverAIOCBSync *)blockacb;
 1172:     qemu_bh_cancel(acb->bh);
 1173:     qemu_aio_release(acb);
 1174: }
 1175: #endif /* !QEMU_TOOL */
 1176: 
 1177: /**************************************************************/
 1178: /* sync block device emulation */
 1179: 
 1180: static void bdrv_rw_em_cb(void *opaque, int ret)
 1181: {
 1182:     *(int *)opaque = ret;
 1183: }
 1184: 
 1185: #define NOT_DONE 0x7fffffff
 1186: 
 1187: static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num, 
 1188:                         uint8_t *buf, int nb_sectors)
 1189: {
 1190:     int async_ret;
 1191:     BlockDriverAIOCB *acb;
 1192: 
 1193:     async_ret = NOT_DONE;
 1194:     qemu_aio_wait_start();
 1195:     acb = bdrv_aio_read(bs, sector_num, buf, nb_sectors, 
 1196:                         bdrv_rw_em_cb, &async_ret);
 1197:     if (acb == NULL) {
 1198:         qemu_aio_wait_end();
 1199:         return -1;
 1200:     }
 1201:     while (async_ret == NOT_DONE) {
 1202:         qemu_aio_wait();
 1203:     }
 1204:     qemu_aio_wait_end();
 1205:     return async_ret;
 1206: }
 1207: 
 1208: static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
 1209:                          const uint8_t *buf, int nb_sectors)
 1210: {
 1211:     int async_ret;
 1212:     BlockDriverAIOCB *acb;
 1213: 
 1214:     async_ret = NOT_DONE;
 1215:     qemu_aio_wait_start();
 1216:     acb = bdrv_aio_write(bs, sector_num, buf, nb_sectors, 
 1217:                          bdrv_rw_em_cb, &async_ret);
 1218:     if (acb == NULL) {
 1219:         qemu_aio_wait_end();
 1220:         return -1;
 1221:     }
 1222:     while (async_ret == NOT_DONE) {
 1223:         qemu_aio_wait();
 1224:     }
 1225:     qemu_aio_wait_end();
 1226:     return async_ret;
 1227: }
 1228: 
 1229: void bdrv_init(void)
 1230: {
 1231:     bdrv_register(&bdrv_raw);
 1232:     bdrv_register(&bdrv_host_device);
 1233: #ifndef _WIN32
 1234:     bdrv_register(&bdrv_cow);
 1235: #endif
 1236:     bdrv_register(&bdrv_qcow);
 1237:     bdrv_register(&bdrv_vmdk);
 1238:     bdrv_register(&bdrv_cloop);
 1239:     bdrv_register(&bdrv_dmg);
 1240:     bdrv_register(&bdrv_bochs);
 1241:     bdrv_register(&bdrv_vpc);
 1242:     bdrv_register(&bdrv_vvfat);
 1243:     bdrv_register(&bdrv_qcow2);
 1244: }
 1245: 
 1246: void *qemu_aio_get(BlockDriverState *bs, BlockDriverCompletionFunc *cb,
 1247:                    void *opaque)
 1248: {
 1249:     BlockDriver *drv;
 1250:     BlockDriverAIOCB *acb;
 1251: 
 1252:     drv = bs->drv;
 1253:     if (drv->free_aiocb) {
 1254:         acb = drv->free_aiocb;
 1255:         drv->free_aiocb = acb->next;
 1256:     } else {
 1257:         acb = qemu_mallocz(drv->aiocb_size);
 1258:         if (!acb)
 1259:             return NULL;
 1260:     }
 1261:     acb->bs = bs;
 1262:     acb->cb = cb;
 1263:     acb->opaque = opaque;
 1264:     return acb;
 1265: }
 1266: 
 1267: void qemu_aio_release(void *p)
 1268: {
 1269:     BlockDriverAIOCB *acb = p;
 1270:     BlockDriver *drv = acb->bs->drv;
 1271:     acb->next = drv->free_aiocb;
 1272:     drv->free_aiocb = acb;
 1273: }
 1274: 
 1275: /**************************************************************/
 1276: /* removable device support */
 1277: 
 1278: /**
 1279:  * Return TRUE if the media is present
 1280:  */
 1281: int bdrv_is_inserted(BlockDriverState *bs)
 1282: {
 1283:     BlockDriver *drv = bs->drv;
 1284:     int ret;
 1285:     if (!drv)
 1286:         return 0;
 1287:     if (!drv->bdrv_is_inserted)
 1288:         return 1;
 1289:     ret = drv->bdrv_is_inserted(bs);
 1290:     return ret;
 1291: }
 1292: 
 1293: /**
 1294:  * Return TRUE if the media changed since the last call to this
 1295:  * function. It is currently only used for floppy disks 
 1296:  */
 1297: int bdrv_media_changed(BlockDriverState *bs)
 1298: {
 1299:     BlockDriver *drv = bs->drv;
 1300:     int ret;
 1301: 
 1302:     if (!drv || !drv->bdrv_media_changed)
 1303:         ret = -ENOTSUP;
 1304:     else
 1305:         ret = drv->bdrv_media_changed(bs);
 1306:     if (ret == -ENOTSUP)
 1307:         ret = bs->media_changed;
 1308:     bs->media_changed = 0;
 1309:     return ret;
 1310: }
 1311: 
 1312: /**
 1313:  * If eject_flag is TRUE, eject the media. Otherwise, close the tray
 1314:  */
 1315: void bdrv_eject(BlockDriverState *bs, int eject_flag)
 1316: {
 1317:     BlockDriver *drv = bs->drv;
 1318:     int ret;
 1319: 
 1320:     if (!drv || !drv->bdrv_eject) {
 1321:         ret = -ENOTSUP;
 1322:     } else {
 1323:         ret = drv->bdrv_eject(bs, eject_flag);
 1324:     }
 1325:     if (ret == -ENOTSUP) {
 1326:         if (eject_flag)
 1327:             bdrv_close(bs);
 1328:     }
 1329: }
 1330: 
 1331: int bdrv_is_locked(BlockDriverState *bs)
 1332: {
 1333:     return bs->locked;
 1334: }
 1335: 
 1336: /**
 1337:  * Lock or unlock the media (if it is locked, the user won't be able
 1338:  * to eject it manually).
 1339:  */
 1340: void bdrv_set_locked(BlockDriverState *bs, int locked)
 1341: {
 1342:     BlockDriver *drv = bs->drv;
 1343: 
 1344:     bs->locked = locked;
 1345:     if (drv && drv->bdrv_set_locked) {
 1346:         drv->bdrv_set_locked(bs, locked);
 1347:     }
 1348: }

unix.superglobalmegacorp.com