use anyhow::Context;
use argh::FromArgs;
use base::RawDescriptor;
use cros_async::Executor;
use hypervisor::ProtectionType;
use crate::virtio::base_features;
use crate::virtio::block::DiskOption;
use crate::virtio::vhost::user::device::BackendConnection;
use crate::virtio::BlockAsync;
#[derive(FromArgs)]
#[argh(subcommand, name = "block")]
pub struct Options {
#[argh(option, arg_name = "PATH", hidden_help)]
socket: Option<String>,
#[argh(option, arg_name = "PATH")]
socket_path: Option<String>,
#[argh(option, arg_name = "FD")]
fd: Option<RawDescriptor>,
#[argh(option, arg_name = "PATH<:read-only>")]
file: String,
}
pub fn start_device(opts: Options) -> anyhow::Result<()> {
let ex = Executor::new().context("failed to create executor")?;
let mut fileopts = opts.file.split(":").collect::<Vec<_>>();
let filename = fileopts.remove(0);
let disk = DiskOption {
path: filename.into(),
read_only: fileopts.contains(&"read-only"),
sparse: false,
..DiskOption::default()
};
let block = Box::new(BlockAsync::new(
base_features(ProtectionType::Unprotected),
disk.open()?,
&disk,
None,
None,
None,
)?);
let conn =
BackendConnection::from_opts(opts.socket.as_deref(), opts.socket_path.as_deref(), opts.fd)?;
conn.run_device(ex, block)
}