Allow client to pass a file descriptor for VM logs.
Bug: 180893082
Test: Ran vm tool on VIM3L
Test: atest VirtualizationTestCases
Change-Id: I6c7729eb01d953559e1ddb0b5eb84655a84159a8
diff --git a/vm/Android.bp b/vm/Android.bp
index 0de6cae..5089e39 100644
--- a/vm/Android.bp
+++ b/vm/Android.bp
@@ -12,6 +12,7 @@
"libanyhow",
"libbinder_rs",
"libenv_logger",
+ "liblibc",
"liblog_rust",
],
apex_available: [
diff --git a/vm/src/main.rs b/vm/src/main.rs
index df375e4..96ec649 100644
--- a/vm/src/main.rs
+++ b/vm/src/main.rs
@@ -17,12 +17,17 @@
mod sync;
use android_system_virtmanager::aidl::android::system::virtmanager::IVirtManager::IVirtManager;
-use android_system_virtmanager::binder::{get_interface, ProcessState, Strong};
+use android_system_virtmanager::binder::{
+ get_interface, ParcelFileDescriptor, ProcessState, Strong,
+};
use anyhow::{bail, Context, Error};
// TODO: Import these via android_system_virtmanager::binder once https://r.android.com/1619403 is
// submitted.
use binder::{DeathRecipient, IBinder};
use std::env;
+use std::fs::File;
+use std::io;
+use std::os::unix::io::{AsRawFd, FromRawFd};
use std::process::exit;
use sync::AtomicFlag;
@@ -54,7 +59,9 @@
/// Run a VM from the given configuration file.
fn command_run(virt_manager: Strong<dyn IVirtManager>, config_filename: &str) -> Result<(), Error> {
- let vm = virt_manager.startVm(config_filename).context("Failed to start VM")?;
+ let stdout_file = ParcelFileDescriptor::new(duplicate_stdout()?);
+ let vm =
+ virt_manager.startVm(config_filename, Some(&stdout_file)).context("Failed to start VM")?;
let cid = vm.getCid().context("Failed to get CID")?;
println!("Started VM from {} with CID {}.", config_filename, cid);
@@ -85,3 +92,18 @@
dead.wait();
Ok(())
}
+
+/// Safely duplicate the standard output file descriptor.
+fn duplicate_stdout() -> io::Result<File> {
+ let stdout_fd = io::stdout().as_raw_fd();
+ // Safe because this just duplicates a file descriptor which we know to be valid, and we check
+ // for an error.
+ let dup_fd = unsafe { libc::dup(stdout_fd) };
+ if dup_fd < 0 {
+ Err(io::Error::last_os_error())
+ } else {
+ // Safe because we have just duplicated the file descriptor so we own it, and `from_raw_fd`
+ // takes ownership of it.
+ Ok(unsafe { File::from_raw_fd(dup_fd) })
+ }
+}