mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
better support of host drives
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2124 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
+582
-100
File diff suppressed because it is too large
Load Diff
@@ -181,24 +181,37 @@ void get_tmp_filename(char *filename, int size)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
static int is_windows_drive(const char *filename)
|
||||
{
|
||||
if (((filename[0] >= 'a' && filename[0] <= 'z') ||
|
||||
(filename[0] >= 'A' && filename[0] <= 'Z')) &&
|
||||
filename[1] == ':' && filename[2] == '\0')
|
||||
return 1;
|
||||
if (strstart(filename, "\\\\.\\", NULL) ||
|
||||
strstart(filename, "//./", NULL))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static BlockDriver *find_protocol(const char *filename)
|
||||
{
|
||||
BlockDriver *drv1;
|
||||
char protocol[128];
|
||||
int len;
|
||||
const char *p;
|
||||
|
||||
#ifdef _WIN32
|
||||
if (is_windows_drive(filename))
|
||||
return &bdrv_raw;
|
||||
#endif
|
||||
p = strchr(filename, ':');
|
||||
if (!p)
|
||||
return &bdrv_raw;
|
||||
len = p - filename;
|
||||
if (len > sizeof(protocol) - 1)
|
||||
len = sizeof(protocol) - 1;
|
||||
#ifdef _WIN32
|
||||
if (len == 1) {
|
||||
/* specific win32 case for driver letters */
|
||||
return &bdrv_raw;
|
||||
}
|
||||
#endif
|
||||
memcpy(protocol, filename, len);
|
||||
protocol[len] = '\0';
|
||||
for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
|
||||
@@ -218,14 +231,28 @@ static BlockDriver *find_image_format(const char *filename)
|
||||
uint8_t buf[2048];
|
||||
BlockDriverState *bs;
|
||||
|
||||
/* detect host devices. By convention, /dev/cdrom[N] is always
|
||||
recognized as a host CDROM */
|
||||
if (strstart(filename, "/dev/cdrom", NULL))
|
||||
return &bdrv_host_device;
|
||||
#ifdef _WIN32
|
||||
if (is_windows_drive(filename))
|
||||
return &bdrv_host_device;
|
||||
#else
|
||||
{
|
||||
struct stat st;
|
||||
if (stat(filename, &st) >= 0 &&
|
||||
(S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))) {
|
||||
return &bdrv_host_device;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
drv = find_protocol(filename);
|
||||
/* no need to test disk image formats for vvfat or host specific
|
||||
devices */
|
||||
/* no need to test disk image formats for vvfat */
|
||||
if (drv == &bdrv_vvfat)
|
||||
return drv;
|
||||
if (strstart(filename, "/dev/", NULL))
|
||||
return &bdrv_raw;
|
||||
|
||||
|
||||
ret = bdrv_file_open(&bs, filename, BDRV_O_RDONLY);
|
||||
if (ret < 0)
|
||||
return NULL;
|
||||
@@ -362,9 +389,8 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
bs->inserted = 1;
|
||||
|
||||
/* call the change callback */
|
||||
bs->media_changed = 1;
|
||||
if (bs->change_cb)
|
||||
bs->change_cb(bs->change_opaque);
|
||||
|
||||
@@ -373,7 +399,7 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
|
||||
|
||||
void bdrv_close(BlockDriverState *bs)
|
||||
{
|
||||
if (bs->inserted) {
|
||||
if (bs->drv) {
|
||||
if (bs->backing_hd)
|
||||
bdrv_delete(bs->backing_hd);
|
||||
bs->drv->bdrv_close(bs);
|
||||
@@ -385,9 +411,9 @@ void bdrv_close(BlockDriverState *bs)
|
||||
#endif
|
||||
bs->opaque = NULL;
|
||||
bs->drv = NULL;
|
||||
bs->inserted = 0;
|
||||
|
||||
/* call the change callback */
|
||||
bs->media_changed = 1;
|
||||
if (bs->change_cb)
|
||||
bs->change_cb(bs->change_opaque);
|
||||
}
|
||||
@@ -403,12 +429,13 @@ void bdrv_delete(BlockDriverState *bs)
|
||||
/* commit COW file into the raw image */
|
||||
int bdrv_commit(BlockDriverState *bs)
|
||||
{
|
||||
BlockDriver *drv = bs->drv;
|
||||
int64_t i, total_sectors;
|
||||
int n, j;
|
||||
unsigned char sector[512];
|
||||
|
||||
if (!bs->inserted)
|
||||
return -ENOENT;
|
||||
if (!drv)
|
||||
return -ENOMEDIUM;
|
||||
|
||||
if (bs->read_only) {
|
||||
return -EACCES;
|
||||
@@ -420,7 +447,7 @@ int bdrv_commit(BlockDriverState *bs)
|
||||
|
||||
total_sectors = bdrv_getlength(bs) >> SECTOR_BITS;
|
||||
for (i = 0; i < total_sectors;) {
|
||||
if (bs->drv->bdrv_is_allocated(bs, i, 65536, &n)) {
|
||||
if (drv->bdrv_is_allocated(bs, i, 65536, &n)) {
|
||||
for(j = 0; j < n; j++) {
|
||||
if (bdrv_read(bs, i, sector, 1) != 0) {
|
||||
return -EIO;
|
||||
@@ -436,20 +463,20 @@ int bdrv_commit(BlockDriverState *bs)
|
||||
}
|
||||
}
|
||||
|
||||
if (bs->drv->bdrv_make_empty)
|
||||
return bs->drv->bdrv_make_empty(bs);
|
||||
if (drv->bdrv_make_empty)
|
||||
return drv->bdrv_make_empty(bs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* return < 0 if error */
|
||||
/* return < 0 if error. See bdrv_write() for the return codes */
|
||||
int bdrv_read(BlockDriverState *bs, int64_t sector_num,
|
||||
uint8_t *buf, int nb_sectors)
|
||||
{
|
||||
BlockDriver *drv = bs->drv;
|
||||
|
||||
if (!bs->inserted)
|
||||
return -1;
|
||||
if (!drv)
|
||||
return -ENOMEDIUM;
|
||||
|
||||
if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
|
||||
memcpy(buf, bs->boot_sector_data, 512);
|
||||
@@ -466,7 +493,7 @@ int bdrv_read(BlockDriverState *bs, int64_t sector_num,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
else if (ret != len)
|
||||
return -EIO;
|
||||
return -EINVAL;
|
||||
else
|
||||
return 0;
|
||||
} else {
|
||||
@@ -474,15 +501,20 @@ int bdrv_read(BlockDriverState *bs, int64_t sector_num,
|
||||
}
|
||||
}
|
||||
|
||||
/* return < 0 if error */
|
||||
/* Return < 0 if error. Important errors are:
|
||||
-EIO generic I/O error (may happen for all errors)
|
||||
-ENOMEDIUM No media inserted.
|
||||
-EINVAL Invalid sector number or nb_sectors
|
||||
-EACCES Trying to write a read-only device
|
||||
*/
|
||||
int bdrv_write(BlockDriverState *bs, int64_t sector_num,
|
||||
const uint8_t *buf, int nb_sectors)
|
||||
{
|
||||
BlockDriver *drv = bs->drv;
|
||||
if (!bs->inserted)
|
||||
return -1;
|
||||
if (!bs->drv)
|
||||
return -ENOMEDIUM;
|
||||
if (bs->read_only)
|
||||
return -1;
|
||||
return -EACCES;
|
||||
if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
|
||||
memcpy(bs->boot_sector_data, buf, 512);
|
||||
}
|
||||
@@ -501,7 +533,6 @@ int bdrv_write(BlockDriverState *bs, int64_t sector_num,
|
||||
}
|
||||
}
|
||||
|
||||
/* not necessary now */
|
||||
static int bdrv_pread_em(BlockDriverState *bs, int64_t offset,
|
||||
uint8_t *buf, int count1)
|
||||
{
|
||||
@@ -603,7 +634,7 @@ int bdrv_pread(BlockDriverState *bs, int64_t offset,
|
||||
BlockDriver *drv = bs->drv;
|
||||
|
||||
if (!drv)
|
||||
return -ENOENT;
|
||||
return -ENOMEDIUM;
|
||||
if (!drv->bdrv_pread)
|
||||
return bdrv_pread_em(bs, offset, buf1, count1);
|
||||
return drv->bdrv_pread(bs, offset, buf1, count1);
|
||||
@@ -618,7 +649,7 @@ int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
|
||||
BlockDriver *drv = bs->drv;
|
||||
|
||||
if (!drv)
|
||||
return -ENOENT;
|
||||
return -ENOMEDIUM;
|
||||
if (!drv->bdrv_pwrite)
|
||||
return bdrv_pwrite_em(bs, offset, buf1, count1);
|
||||
return drv->bdrv_pwrite(bs, offset, buf1, count1);
|
||||
@@ -631,7 +662,7 @@ int bdrv_truncate(BlockDriverState *bs, int64_t offset)
|
||||
{
|
||||
BlockDriver *drv = bs->drv;
|
||||
if (!drv)
|
||||
return -ENOENT;
|
||||
return -ENOMEDIUM;
|
||||
if (!drv->bdrv_truncate)
|
||||
return -ENOTSUP;
|
||||
return drv->bdrv_truncate(bs, offset);
|
||||
@@ -644,7 +675,7 @@ int64_t bdrv_getlength(BlockDriverState *bs)
|
||||
{
|
||||
BlockDriver *drv = bs->drv;
|
||||
if (!drv)
|
||||
return -ENOENT;
|
||||
return -ENOMEDIUM;
|
||||
if (!drv->bdrv_getlength) {
|
||||
/* legacy mode */
|
||||
return bs->total_sectors * SECTOR_SIZE;
|
||||
@@ -652,9 +683,16 @@ int64_t bdrv_getlength(BlockDriverState *bs)
|
||||
return drv->bdrv_getlength(bs);
|
||||
}
|
||||
|
||||
/* return 0 as number of sectors if no device present or error */
|
||||
void bdrv_get_geometry(BlockDriverState *bs, int64_t *nb_sectors_ptr)
|
||||
{
|
||||
*nb_sectors_ptr = bs->total_sectors;
|
||||
int64_t length;
|
||||
length = bdrv_getlength(bs);
|
||||
if (length < 0)
|
||||
length = 0;
|
||||
else
|
||||
length = length >> SECTOR_BITS;
|
||||
*nb_sectors_ptr = length;
|
||||
}
|
||||
|
||||
/* force a given boot sector. */
|
||||
@@ -715,21 +753,7 @@ int bdrv_is_read_only(BlockDriverState *bs)
|
||||
return bs->read_only;
|
||||
}
|
||||
|
||||
int bdrv_is_inserted(BlockDriverState *bs)
|
||||
{
|
||||
return bs->inserted;
|
||||
}
|
||||
|
||||
int bdrv_is_locked(BlockDriverState *bs)
|
||||
{
|
||||
return bs->locked;
|
||||
}
|
||||
|
||||
void bdrv_set_locked(BlockDriverState *bs, int locked)
|
||||
{
|
||||
bs->locked = locked;
|
||||
}
|
||||
|
||||
/* XXX: no longer used */
|
||||
void bdrv_set_change_cb(BlockDriverState *bs,
|
||||
void (*change_cb)(void *opaque), void *opaque)
|
||||
{
|
||||
@@ -761,7 +785,7 @@ int bdrv_set_key(BlockDriverState *bs, const char *key)
|
||||
|
||||
void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size)
|
||||
{
|
||||
if (!bs->inserted || !bs->drv) {
|
||||
if (!bs->drv) {
|
||||
buf[0] = '\0';
|
||||
} else {
|
||||
pstrcpy(buf, buf_size, bs->drv->format_name);
|
||||
@@ -833,7 +857,7 @@ void bdrv_info(void)
|
||||
if (bs->removable) {
|
||||
term_printf(" locked=%d", bs->locked);
|
||||
}
|
||||
if (bs->inserted) {
|
||||
if (bs->drv) {
|
||||
term_printf(" file=%s", bs->filename);
|
||||
if (bs->backing_file[0] != '\0')
|
||||
term_printf(" backing_file=%s", bs->backing_file);
|
||||
@@ -863,7 +887,7 @@ int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num,
|
||||
{
|
||||
BlockDriver *drv = bs->drv;
|
||||
if (!drv)
|
||||
return -ENOENT;
|
||||
return -ENOMEDIUM;
|
||||
if (!drv->bdrv_write_compressed)
|
||||
return -ENOTSUP;
|
||||
return drv->bdrv_write_compressed(bs, sector_num, buf, nb_sectors);
|
||||
@@ -873,7 +897,7 @@ int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
|
||||
{
|
||||
BlockDriver *drv = bs->drv;
|
||||
if (!drv)
|
||||
return -ENOENT;
|
||||
return -ENOMEDIUM;
|
||||
if (!drv->bdrv_get_info)
|
||||
return -ENOTSUP;
|
||||
memset(bdi, 0, sizeof(*bdi));
|
||||
@@ -888,7 +912,7 @@ int bdrv_snapshot_create(BlockDriverState *bs,
|
||||
{
|
||||
BlockDriver *drv = bs->drv;
|
||||
if (!drv)
|
||||
return -ENOENT;
|
||||
return -ENOMEDIUM;
|
||||
if (!drv->bdrv_snapshot_create)
|
||||
return -ENOTSUP;
|
||||
return drv->bdrv_snapshot_create(bs, sn_info);
|
||||
@@ -899,7 +923,7 @@ int bdrv_snapshot_goto(BlockDriverState *bs,
|
||||
{
|
||||
BlockDriver *drv = bs->drv;
|
||||
if (!drv)
|
||||
return -ENOENT;
|
||||
return -ENOMEDIUM;
|
||||
if (!drv->bdrv_snapshot_goto)
|
||||
return -ENOTSUP;
|
||||
return drv->bdrv_snapshot_goto(bs, snapshot_id);
|
||||
@@ -909,7 +933,7 @@ int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id)
|
||||
{
|
||||
BlockDriver *drv = bs->drv;
|
||||
if (!drv)
|
||||
return -ENOENT;
|
||||
return -ENOMEDIUM;
|
||||
if (!drv->bdrv_snapshot_delete)
|
||||
return -ENOTSUP;
|
||||
return drv->bdrv_snapshot_delete(bs, snapshot_id);
|
||||
@@ -920,7 +944,7 @@ int bdrv_snapshot_list(BlockDriverState *bs,
|
||||
{
|
||||
BlockDriver *drv = bs->drv;
|
||||
if (!drv)
|
||||
return -ENOENT;
|
||||
return -ENOMEDIUM;
|
||||
if (!drv->bdrv_snapshot_list)
|
||||
return -ENOTSUP;
|
||||
return drv->bdrv_snapshot_list(bs, psn_info);
|
||||
@@ -1001,7 +1025,7 @@ BlockDriverAIOCB *bdrv_aio_read(BlockDriverState *bs, int64_t sector_num,
|
||||
{
|
||||
BlockDriver *drv = bs->drv;
|
||||
|
||||
if (!bs->inserted)
|
||||
if (!drv)
|
||||
return NULL;
|
||||
|
||||
/* XXX: we assume that nb_sectors == 0 is suppored by the async read */
|
||||
@@ -1021,7 +1045,7 @@ BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, int64_t sector_num,
|
||||
{
|
||||
BlockDriver *drv = bs->drv;
|
||||
|
||||
if (!bs->inserted)
|
||||
if (!drv)
|
||||
return NULL;
|
||||
if (bs->read_only)
|
||||
return NULL;
|
||||
@@ -1170,6 +1194,7 @@ static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
|
||||
void bdrv_init(void)
|
||||
{
|
||||
bdrv_register(&bdrv_raw);
|
||||
bdrv_register(&bdrv_host_device);
|
||||
#ifndef _WIN32
|
||||
bdrv_register(&bdrv_cow);
|
||||
#endif
|
||||
@@ -1211,3 +1236,78 @@ void qemu_aio_release(void *p)
|
||||
acb->next = drv->free_aiocb;
|
||||
drv->free_aiocb = acb;
|
||||
}
|
||||
|
||||
/**************************************************************/
|
||||
/* removable device support */
|
||||
|
||||
/**
|
||||
* Return TRUE if the media is present
|
||||
*/
|
||||
int bdrv_is_inserted(BlockDriverState *bs)
|
||||
{
|
||||
BlockDriver *drv = bs->drv;
|
||||
int ret;
|
||||
if (!drv)
|
||||
return 0;
|
||||
if (!drv->bdrv_is_inserted)
|
||||
return 1;
|
||||
ret = drv->bdrv_is_inserted(bs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return TRUE if the media changed since the last call to this
|
||||
* function. It is currently only used for floppy disks
|
||||
*/
|
||||
int bdrv_media_changed(BlockDriverState *bs)
|
||||
{
|
||||
BlockDriver *drv = bs->drv;
|
||||
int ret;
|
||||
|
||||
if (!drv || !drv->bdrv_media_changed)
|
||||
ret = -ENOTSUP;
|
||||
else
|
||||
ret = drv->bdrv_media_changed(bs);
|
||||
if (ret == -ENOTSUP)
|
||||
ret = bs->media_changed;
|
||||
bs->media_changed = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* If eject_flag is TRUE, eject the media. Otherwise, close the tray
|
||||
*/
|
||||
void bdrv_eject(BlockDriverState *bs, int eject_flag)
|
||||
{
|
||||
BlockDriver *drv = bs->drv;
|
||||
int ret;
|
||||
|
||||
if (!drv || !drv->bdrv_eject) {
|
||||
ret = -ENOTSUP;
|
||||
} else {
|
||||
ret = drv->bdrv_eject(bs, eject_flag);
|
||||
}
|
||||
if (ret == -ENOTSUP) {
|
||||
if (eject_flag)
|
||||
bdrv_close(bs);
|
||||
}
|
||||
}
|
||||
|
||||
int bdrv_is_locked(BlockDriverState *bs)
|
||||
{
|
||||
return bs->locked;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lock or unlock the media (if it is locked, the user won't be able
|
||||
* to eject it manually).
|
||||
*/
|
||||
void bdrv_set_locked(BlockDriverState *bs, int locked)
|
||||
{
|
||||
BlockDriver *drv = bs->drv;
|
||||
|
||||
bs->locked = locked;
|
||||
if (drv && drv->bdrv_set_locked) {
|
||||
drv->bdrv_set_locked(bs, locked);
|
||||
}
|
||||
}
|
||||
|
||||
+9
-3
@@ -70,6 +70,12 @@ struct BlockDriver {
|
||||
QEMUSnapshotInfo **psn_info);
|
||||
int (*bdrv_get_info)(BlockDriverState *bs, BlockDriverInfo *bdi);
|
||||
|
||||
/* removable device specific */
|
||||
int (*bdrv_is_inserted)(BlockDriverState *bs);
|
||||
int (*bdrv_media_changed)(BlockDriverState *bs);
|
||||
int (*bdrv_eject)(BlockDriverState *bs, int eject_flag);
|
||||
int (*bdrv_set_locked)(BlockDriverState *bs, int locked);
|
||||
|
||||
BlockDriverAIOCB *free_aiocb;
|
||||
struct BlockDriver *next;
|
||||
};
|
||||
@@ -78,7 +84,6 @@ struct BlockDriverState {
|
||||
int64_t total_sectors; /* if we are reading a disk image, give its
|
||||
size in sectors */
|
||||
int read_only; /* if true, the media is read only */
|
||||
int inserted; /* if true, the media is present */
|
||||
int removable; /* if true, the media can be removed */
|
||||
int locked; /* if true, the media cannot temporarily be ejected */
|
||||
int encrypted; /* if true, the media is encrypted */
|
||||
@@ -86,7 +91,7 @@ struct BlockDriverState {
|
||||
void (*change_cb)(void *opaque);
|
||||
void *change_opaque;
|
||||
|
||||
BlockDriver *drv;
|
||||
BlockDriver *drv; /* NULL means no media */
|
||||
void *opaque;
|
||||
|
||||
int boot_sector_enabled;
|
||||
@@ -96,7 +101,8 @@ struct BlockDriverState {
|
||||
char backing_file[1024]; /* if non zero, the image is a diff of
|
||||
this file image */
|
||||
int is_temporary;
|
||||
|
||||
int media_changed;
|
||||
|
||||
BlockDriverState *backing_hd;
|
||||
/* async read/write emulation */
|
||||
|
||||
|
||||
+54
-2
@@ -206,7 +206,7 @@ Select the emulated machine (@code{-M ?} for list)
|
||||
@item -fda file
|
||||
@item -fdb file
|
||||
Use @var{file} as floppy disk 0/1 image (@pxref{disk_images}). You can
|
||||
use the host floppy by using @file{/dev/fd0} as filename.
|
||||
use the host floppy by using @file{/dev/fd0} as filename (@pxref{host_drives}).
|
||||
|
||||
@item -hda file
|
||||
@item -hdb file
|
||||
@@ -217,7 +217,7 @@ Use @var{file} as hard disk 0, 1, 2 or 3 image (@pxref{disk_images}).
|
||||
@item -cdrom file
|
||||
Use @var{file} as CD-ROM image (you cannot use @option{-hdc} and and
|
||||
@option{-cdrom} at the same time). You can use the host CD-ROM by
|
||||
using @file{/dev/cdrom} as filename.
|
||||
using @file{/dev/cdrom} as filename (@pxref{host_drives}).
|
||||
|
||||
@item -boot [a|c|d]
|
||||
Boot on floppy (a), hard disk (c) or CD-ROM (d). Hard disk boot is
|
||||
@@ -916,6 +916,7 @@ snapshots.
|
||||
* disk_images_snapshot_mode:: Snapshot mode
|
||||
* vm_snapshots:: VM snapshots
|
||||
* qemu_img_invocation:: qemu-img Invocation
|
||||
* host_drives:: Using host drives
|
||||
* disk_images_fat_images:: Virtual FAT disk images
|
||||
@end menu
|
||||
|
||||
@@ -997,6 +998,57 @@ state is not saved or restored properly (in particular USB).
|
||||
|
||||
@include qemu-img.texi
|
||||
|
||||
@node host_drives
|
||||
@subsection Using host drives
|
||||
|
||||
In addition to disk image files, QEMU can directly access host
|
||||
devices. We describe here the usage for QEMU version >= 0.8.3.
|
||||
|
||||
@subsubsection Linux
|
||||
|
||||
On Linux, you can directly use the host device filename instead of a
|
||||
disk image filename provided you have enough proviledge to access
|
||||
it. For example, use @file{/dev/cdrom} to access to the CDROM or
|
||||
@file{/dev/fd0} for the floppy.
|
||||
|
||||
@table
|
||||
@item CD
|
||||
You can specify a CDROM device even if no CDROM is loaded. QEMU has
|
||||
specific code to detect CDROM insertion or removal. CDROM ejection by
|
||||
the guest OS is supported. Currently only data CDs are supported.
|
||||
@item Floppy
|
||||
You can specify a floppy device even if no floppy is loaded. Floppy
|
||||
removal is currently not detected accurately (if you change floppy
|
||||
without doing floppy access while the floppy is not loaded, the guest
|
||||
OS will think that the same floppy is loaded).
|
||||
@item Hard disks
|
||||
Hard disks can be used. Normally you must specify the whole disk
|
||||
(@file{/dev/hdb} instead of @file{/dev/hdb1}) so that the guest OS can
|
||||
see it as a partitioned disk. WARNING: unless you know what you do, it
|
||||
is better to only make READ-ONLY accesses to the hard disk otherwise
|
||||
you may corrupt your host data (use the @option{-snapshot} command
|
||||
line option or modify the device permissions accordingly).
|
||||
@end table
|
||||
|
||||
@subsubsection Windows
|
||||
|
||||
On Windows you can use any host drives as QEMU drive. The prefered
|
||||
syntax is the driver letter (e.g. @file{d:}). The alternate syntax
|
||||
@file{\\.\d:} is supported. @file{/dev/cdrom} is supported as an alias
|
||||
to the first CDROM drive.
|
||||
|
||||
Currently there is no specific code to handle removable medias, so it
|
||||
is better to use the @code{change} or @code{eject} monitor commands to
|
||||
change or eject media.
|
||||
|
||||
@subsubsection Mac OS X
|
||||
|
||||
@file{/dev/cdrom} is an alias to the first CDROM.
|
||||
|
||||
Currently there is no specific code to handle removable medias, so it
|
||||
is better to use the @code{change} or @code{eject} monitor commands to
|
||||
change or eject media.
|
||||
|
||||
@node disk_images_fat_images
|
||||
@subsection Virtual FAT disk images
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
#define fsync _commit
|
||||
#define lseek _lseeki64
|
||||
#define ENOTSUP 4096
|
||||
#define ENOMEDIUM 4097
|
||||
extern int qemu_ftruncate64(int, int64_t);
|
||||
#define ftruncate qemu_ftruncate64
|
||||
|
||||
@@ -502,6 +503,7 @@ typedef struct BlockDriverState BlockDriverState;
|
||||
typedef struct BlockDriver BlockDriver;
|
||||
|
||||
extern BlockDriver bdrv_raw;
|
||||
extern BlockDriver bdrv_host_device;
|
||||
extern BlockDriver bdrv_cow;
|
||||
extern BlockDriver bdrv_qcow;
|
||||
extern BlockDriver bdrv_vmdk;
|
||||
@@ -604,8 +606,10 @@ int bdrv_get_translation_hint(BlockDriverState *bs);
|
||||
int bdrv_is_removable(BlockDriverState *bs);
|
||||
int bdrv_is_read_only(BlockDriverState *bs);
|
||||
int bdrv_is_inserted(BlockDriverState *bs);
|
||||
int bdrv_media_changed(BlockDriverState *bs);
|
||||
int bdrv_is_locked(BlockDriverState *bs);
|
||||
void bdrv_set_locked(BlockDriverState *bs, int locked);
|
||||
void bdrv_eject(BlockDriverState *bs, int eject_flag);
|
||||
void bdrv_set_change_cb(BlockDriverState *bs,
|
||||
void (*change_cb)(void *opaque), void *opaque);
|
||||
void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size);
|
||||
|
||||
Reference in New Issue
Block a user