diff --git a/block.c b/block.c index 2e2059333c..c7e0dcbc5c 100644 --- a/block.c +++ b/block.c @@ -209,7 +209,7 @@ static int is_windows_drive_prefix(const char *filename) filename[1] == ':'); } -static int is_windows_drive(const char *filename) +int is_windows_drive(const char *filename) { if (is_windows_drive_prefix(filename) && filename[2] == '\0') @@ -253,43 +253,23 @@ static BlockDriver *find_protocol(const char *filename) * Detect host devices. By convention, /dev/cdrom[N] is always * recognized as a host CDROM. */ -#ifdef _WIN32 static BlockDriver *find_hdev_driver(const char *filename) { - if (strstart(filename, "/dev/cdrom", NULL)) - return bdrv_find_format("host_device"); - if (is_windows_drive(filename)) - return bdrv_find_format("host_device"); - return NULL; -} -#else -static BlockDriver *find_hdev_driver(const char *filename) -{ - struct stat st; + int score_max = 0, score; + BlockDriver *drv = NULL, *d; -#ifdef __linux__ - if (strstart(filename, "/dev/fd", NULL)) - return bdrv_find_format("host_floppy"); - if (strstart(filename, "/dev/cd", NULL)) - return bdrv_find_format("host_cdrom"); -#elif defined(__FreeBSD__) - if (strstart(filename, "/dev/cd", NULL) || - strstart(filename, "/dev/acd", NULL)) { - return bdrv_find_format("host_cdrom"); - } -#else - if (strstart(filename, "/dev/cdrom", NULL)) - return bdrv_find_format("host_device"); -#endif - - if (stat(filename, &st) >= 0 && - (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))) { - return bdrv_find_format("host_device"); + for (d = first_drv; d; d = d->next) { + if (d->bdrv_probe_device) { + score = d->bdrv_probe_device(filename); + if (score > score_max) { + score_max = score; + drv = d; + } + } } - return NULL; + return drv; } -#endif static BlockDriver *find_image_format(const char *filename) { diff --git a/block/raw-posix.c b/block/raw-posix.c index d7f9b4843e..5e65da00a7 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -953,6 +953,22 @@ kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex ma #endif +static int hdev_probe_device(const char *filename) +{ + struct stat st; + + /* allow a dedicated CD-ROM driver to match with a higher priority */ + if (strstart(filename, "/dev/cdrom", NULL)) + return 50; + + if (stat(filename, &st) >= 0 && + (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))) { + return 100; + } + + return 0; +} + static int hdev_open(BlockDriverState *bs, const char *filename, int flags) { BDRVRawState *s = bs->opaque; @@ -1152,6 +1168,7 @@ static int hdev_create(const char *filename, QEMUOptionParameter *options) static BlockDriver bdrv_host_device = { .format_name = "host_device", .instance_size = sizeof(BDRVRawState), + .bdrv_probe_device = hdev_probe_device, .bdrv_open = hdev_open, .bdrv_close = raw_close, .bdrv_create = hdev_create, @@ -1197,6 +1214,14 @@ static int floppy_open(BlockDriverState *bs, const char *filename, int flags) return 0; } +static int floppy_probe_device(const char *filename) +{ + if (strstart(filename, "/dev/fd", NULL)) + return 100; + return 0; +} + + static int floppy_is_inserted(BlockDriverState *bs) { return fd_open(bs) >= 0; @@ -1242,6 +1267,7 @@ static int floppy_eject(BlockDriverState *bs, int eject_flag) static BlockDriver bdrv_host_floppy = { .format_name = "host_floppy", .instance_size = sizeof(BDRVRawState), + .bdrv_probe_device = floppy_probe_device, .bdrv_open = floppy_open, .bdrv_close = raw_close, .bdrv_create = hdev_create, @@ -1279,6 +1305,13 @@ static int cdrom_open(BlockDriverState *bs, const char *filename, int flags) return raw_open_common(bs, filename, flags); } +static int cdrom_probe_device(const char *filename) +{ + if (strstart(filename, "/dev/cd", NULL)) + return 100; + return 0; +} + static int cdrom_is_inserted(BlockDriverState *bs) { BDRVRawState *s = bs->opaque; @@ -1323,6 +1356,7 @@ static int cdrom_set_locked(BlockDriverState *bs, int locked) static BlockDriver bdrv_host_cdrom = { .format_name = "host_cdrom", .instance_size = sizeof(BDRVRawState), + .bdrv_probe_device = cdrom_probe_device, .bdrv_open = cdrom_open, .bdrv_close = raw_close, .bdrv_create = hdev_create, @@ -1367,6 +1401,14 @@ static int cdrom_open(BlockDriverState *bs, const char *filename, int flags) return 0; } +static int cdrom_probe_device(const char *filename) +{ + if (strstart(filename, "/dev/cd", NULL) || + strstart(filename, "/dev/acd", NULL)) + return 100; + return 0; +} + static int cdrom_reopen(BlockDriverState *bs) { BDRVRawState *s = bs->opaque; @@ -1437,6 +1479,7 @@ static int cdrom_set_locked(BlockDriverState *bs, int locked) static BlockDriver bdrv_host_cdrom = { .format_name = "host_cdrom", .instance_size = sizeof(BDRVRawState), + .bdrv_probe_device = cdrom_probe_device, .bdrv_open = cdrom_open, .bdrv_close = raw_close, .bdrv_create = hdev_create, @@ -1466,6 +1509,10 @@ static BlockDriver bdrv_host_cdrom = { static void bdrv_raw_init(void) { + /* + * Register all the drivers. Note that order is important, the driver + * registered last will get probed first. + */ bdrv_register(&bdrv_raw); bdrv_register(&bdrv_host_device); #ifdef __linux__ diff --git a/block/raw-win32.c b/block/raw-win32.c index 1e95153d56..72acad58f9 100644 --- a/block/raw-win32.c +++ b/block/raw-win32.c @@ -306,6 +306,15 @@ static int find_device_type(BlockDriverState *bs, const char *filename) } } +static int hdev_probe_device(const char *filename) +{ + if (strstart(filename, "/dev/cdrom", NULL)) + return 100; + if (is_windows_drive(filename)) + return 100; + return 0; +} + static int hdev_open(BlockDriverState *bs, const char *filename, int flags) { BDRVRawState *s = bs->opaque; @@ -391,6 +400,7 @@ static int raw_set_locked(BlockDriverState *bs, int locked) static BlockDriver bdrv_host_device = { .format_name = "host_device", .instance_size = sizeof(BDRVRawState), + .bdrv_probe_device = hdev_probe_device, .bdrv_open = hdev_open, .bdrv_close = raw_close, .bdrv_flush = raw_flush, diff --git a/block_int.h b/block_int.h index 8d0da7cfd7..830b7e9c9d 100644 --- a/block_int.h +++ b/block_int.h @@ -48,6 +48,7 @@ struct BlockDriver { const char *format_name; int instance_size; int (*bdrv_probe)(const uint8_t *buf, int buf_size, const char *filename); + int (*bdrv_probe_device)(const char *filename); int (*bdrv_open)(BlockDriverState *bs, const char *filename, int flags); int (*bdrv_read)(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, int nb_sectors); @@ -177,4 +178,8 @@ void *qemu_blockalign(BlockDriverState *bs, size_t size); extern BlockDriverState *bdrv_first; +#ifdef _WIN32 +int is_windows_drive(const char *filename); +#endif + #endif /* BLOCK_INT_H */