devices: Serial devices can be backed by FD via /proc/self/fd/N

Like disks, serial devices can be backed by file descriptors using the
/proc/self/fd/N syntax.

BUG=b:200914564
TEST:cargo test
Change-Id: Idd6f5763db24e61a80dc34732c9e2118d613cefc
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/3241083
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
Reviewed-by: Keiichi Watanabe <keiichiw@chromium.org>
Commit-Queue: Daniel Verkamp <dverkamp@chromium.org>
This commit is contained in:
Jiyong Park 2021-10-18 23:58:50 +09:00 committed by Commit Bot
parent d73e41276e
commit 5d5a128943
2 changed files with 25 additions and 8 deletions

View file

@ -12,7 +12,10 @@ use std::str::FromStr;
use std::thread;
use std::time::Duration;
use base::{error, info, read_raw_stdin, syslog, AsRawDescriptor, Event, RawDescriptor};
use base::{
error, info, read_raw_stdin, safe_descriptor_from_path, syslog, AsRawDescriptor, Event,
RawDescriptor,
};
use minijail::Minijail;
use remain::sorted;
use thiserror::Error as ThisError;
@ -220,7 +223,14 @@ impl SerialParameters {
let evt = evt.try_clone().map_err(Error::CloneEvent)?;
keep_rds.push(evt.as_raw_descriptor());
let input: Option<Box<dyn io::Read + Send>> = if let Some(input_path) = &self.input {
let input_file = File::open(input_path.as_path()).map_err(Error::FileError)?;
let input_path = input_path.as_path();
let input_file = if let Some(fd) =
safe_descriptor_from_path(input_path).map_err(|e| Error::FileError(e.into()))?
{
fd.into()
} else {
File::open(input_path).map_err(Error::FileError)?
};
keep_rds.push(input_file.as_raw_descriptor());
Some(Box::new(input_file))
} else if self.stdin {
@ -252,11 +262,18 @@ impl SerialParameters {
}
SerialType::File => match &self.path {
Some(path) => {
let file = OpenOptions::new()
.append(true)
.create(true)
.open(path.as_path())
.map_err(Error::FileError)?;
let path = path.as_path();
let file = if let Some(fd) =
safe_descriptor_from_path(path).map_err(|e| Error::FileError(e.into()))?
{
fd.into()
} else {
OpenOptions::new()
.append(true)
.create(true)
.open(path)
.map_err(Error::FileError)?
};
keep_rds.push(file.as_raw_descriptor());
Some(Box::new(file))
}

View file

@ -575,7 +575,7 @@ pub fn max_timeout() -> Duration {
}
/// If the given path is of the form /proc/self/fd/N for some N, returns `Ok(Some(N))`. Otherwise
/// returns `Ok(None`).
/// returns `Ok(None)`.
pub fn safe_descriptor_from_path<P: AsRef<Path>>(path: P) -> Result<Option<SafeDescriptor>> {
let path = path.as_ref();
if path.parent() == Some(Path::new("/proc/self/fd")) {