Add file path mapping for FileTransfer

Match by longest prefix to get host paths from guest ones
This commit is contained in:
Val Packett 2026-02-12 22:15:40 -03:00
parent 2626130659
commit 95bc64076d
2 changed files with 88 additions and 14 deletions

View file

@ -4,6 +4,7 @@ mod vsock;
use bus::SharedHostedBus;
use clap::Parser;
use eyre::OptionExt;
use futures::{TryFutureExt, stream::FuturesUnordered};
use std::{path::PathBuf, sync::Arc, time::Duration};
use tokio::{net::UnixListener, process::Command, sync::Mutex};
@ -36,6 +37,10 @@ struct BrokerCli {
#[clap(long, default_value = "/run/vm-doc-portal")]
guest_mountpoint: PathBuf,
/// Mappings from guest paths to host paths for passthrough file systems (for file transfer), in guest=host format
#[clap(long)]
path_mapping: Vec<String>,
/// Vsock port number to listen on for the VM bus
#[clap(long)]
vsock_port: Option<u32>,
@ -65,11 +70,31 @@ async fn new_hosted_bus() -> eyre::Result<(
Ok((Arc::new(Mutex::new(bus)), guid, owner_stream))
}
fn parse_path_mapping(s: &str) -> eyre::Result<(PathBuf, PathBuf)> {
let mut split = s.split('=');
let guest_path = PathBuf::from(split.next().ok_or_eyre("failed to split mapping")?);
let host_path = PathBuf::from(split.next().ok_or_eyre("failed to split mapping")?);
Ok((guest_path, host_path))
}
#[tokio::main]
async fn main() -> eyre::Result<()> {
tracing_subscriber::fmt::init();
let cli = BrokerCli::parse();
let mut path_prefix_to_host: Vec<(PathBuf, PathBuf)> = cli
.path_mapping
.iter()
.flat_map(|arg| match parse_path_mapping(arg) {
Ok(mapping) => Some(mapping),
Err(err) => {
error!(?err, %arg, "could not parse path mapping");
None
}
})
.collect();
path_prefix_to_host.sort_unstable_by_key(|(prefix, _)| -(prefix.as_os_str().len() as isize));
debug!(?path_prefix_to_host, "parsed path mappings");
let (priv_bus, _, mut priv_lst) = new_hosted_bus().await?;
@ -153,6 +178,7 @@ async fn main() -> eyre::Result<()> {
&host_session_conn,
&priv_bus_conn,
cli.guest_mountpoint,
path_prefix_to_host,
)
.await?;
let notification_imp = portal::notification::Notification::new(&host_session_conn).await?;