This adds format probing both to the BlockDriver trait and the bochs-rs block driver. With this, bochs-rs achieves feature parity with its C counterpart. Its probe function returns a higher priority so that it is preferred when both drivers are available.
Signed-off-by: Kevin Wolf <kw...@redhat.com> --- rust/block/src/bochs.rs | 20 ++++++++++++++++++++ rust/block/src/driver.rs | 26 +++++++++++++++++++++++++- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/rust/block/src/bochs.rs b/rust/block/src/bochs.rs index 9dd84446e1..b1247a6bd5 100644 --- a/rust/block/src/bochs.rs +++ b/rust/block/src/bochs.rs @@ -188,6 +188,26 @@ pub async fn new(file: BdrvChild) -> io::Result<Self> { impl BlockDriver for BochsImage { type Options = bindings::BlockdevOptionsGenericFormat; + fn probe(buf: &[u8], _filename: &str) -> u16 { + let header = match BochsHeader::from_byte_slice(buf) { + Some(header) => header, + None => return 0, + }; + + if header.magic != HEADER_MAGIC + || header.imgtype != HEADER_TYPE_REDOLOG + || header.subtype != HEADER_SUBTYPE_GROWING + { + return 0; + } + + // This driver is better than the C one which returns 100, give it priority + match header.version { + HEADER_VERSION | HEADER_V1 => 200, + _ => 0, + } + } + unsafe fn parse_options( v: &mut bindings::Visitor, opts: &mut *mut Self::Options, diff --git a/rust/block/src/driver.rs b/rust/block/src/driver.rs index baeaf47eda..1b132bc8de 100644 --- a/rust/block/src/driver.rs +++ b/rust/block/src/driver.rs @@ -7,7 +7,7 @@ use qemu_api::errno::Errno; use qemu_api::futures::qemu_co_run_future; use std::cmp::min; -use std::ffi::c_void; +use std::ffi::{c_void, CStr}; use std::io::{self, Error, ErrorKind}; use std::mem::MaybeUninit; use std::ptr; @@ -65,6 +65,16 @@ unsafe fn open( errp: *mut *mut bindings::Error, ) -> std::os::raw::c_int; + /// Returns the image format probing priority of this block driver for disk images starting + /// with the byte sequence in `buf`. Probing selects the driver that returns the highest + /// number. + /// + /// If the driver doesn't support images starting with `buf`, 0 is returned. + fn probe(buf: &[u8], filename: &str) -> u16 { + let _ = (buf, filename); + 0 + } + /// Returns the size of the image in bytes fn size(&self) -> u64; @@ -161,6 +171,19 @@ pub async fn read_uninit<T: SizedIoBuffer>( } } +#[doc(hidden)] +pub unsafe extern "C" fn bdrv_probe<D: BlockDriver>( + buf: *const u8, + buf_size: std::os::raw::c_int, + filename: *const std::os::raw::c_char, +) -> std::os::raw::c_int { + let buf = unsafe { std::slice::from_raw_parts(buf, buf_size as usize) }; + match unsafe { CStr::from_ptr(filename) }.to_str() { + Ok(filename) => D::probe(buf, filename).into(), + Err(_) => 0, + } +} + #[doc(hidden)] pub unsafe extern "C" fn bdrv_open<D: BlockDriver>( bs: *mut bindings::BlockDriverState, @@ -266,6 +289,7 @@ macro_rules! block_driver { ::qemu_api::bindings::BlockDriver { format_name: ::qemu_api::c_str!($fmtname).as_ptr(), instance_size: ::std::mem::size_of::<$typ>() as i32, + bdrv_probe: Some($crate::driver::bdrv_probe::<$typ>), bdrv_open: Some($crate::driver::bdrv_open::<$typ>), bdrv_close: Some($crate::driver::bdrv_close::<$typ>), bdrv_co_preadv_part: Some($crate::driver::bdrv_co_preadv_part::<$typ>), -- 2.48.1