Merge "Use common prefix for benchmark names"
diff --git a/authfs/fd_server/src/aidl.rs b/authfs/fd_server/src/aidl.rs
index 0859a7a..01b8209 100644
--- a/authfs/fd_server/src/aidl.rs
+++ b/authfs/fd_server/src/aidl.rs
@@ -27,7 +27,7 @@
 use std::fs::File;
 use std::io;
 use std::os::unix::fs::FileExt;
-use std::os::unix::io::{AsRawFd, FromRawFd, OwnedFd, RawFd};
+use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, OwnedFd};
 use std::path::{Component, Path, PathBuf, MAIN_SEPARATOR};
 use std::sync::{Arc, RwLock};
 
@@ -266,10 +266,10 @@
 
         self.insert_new_fd(dir_fd, |config| match config {
             FdConfig::InputDir(dir) => {
-                let file = open_readonly_at(dir.as_raw_fd(), &path_buf).map_err(new_errno_error)?;
+                let file = open_readonly_at(dir.as_fd(), &path_buf).map_err(new_errno_error)?;
 
                 let metadata_path_buf = get_fsverity_metadata_path(&path_buf);
-                let metadata = open_readonly_at(dir.as_raw_fd(), &metadata_path_buf)
+                let metadata = open_readonly_at(dir.as_fd(), &metadata_path_buf)
                     .ok()
                     .and_then(|f| parse_fsverity_metadata(f).ok());
 
@@ -399,8 +399,8 @@
     Status::new_service_specific_error_str(errno as i32, Some(errno.desc()))
 }
 
-fn open_readonly_at(dir_fd: RawFd, path: &Path) -> nix::Result<File> {
-    let new_fd = openat(dir_fd, path, OFlag::O_RDONLY, Mode::empty())?;
+fn open_readonly_at(dir_fd: BorrowedFd, path: &Path) -> nix::Result<File> {
+    let new_fd = openat(dir_fd.as_raw_fd(), path, OFlag::O_RDONLY, Mode::empty())?;
     // SAFETY: new_fd is just created successfully and not owned.
     let new_file = unsafe { File::from_raw_fd(new_fd) };
     Ok(new_file)
diff --git a/authfs/tests/Android.bp b/authfs/tests/Android.bp
index ebc6dd4..990daf3 100644
--- a/authfs/tests/Android.bp
+++ b/authfs/tests/Android.bp
@@ -33,8 +33,8 @@
         "libanyhow",
         "libclap",
         "libcommand_fds",
+        "liblibc",
         "liblog_rust",
-        "libnix",
     ],
     test_suites: ["general-tests"],
     test_harness: false,
diff --git a/authfs/tests/open_then_run.rs b/authfs/tests/open_then_run.rs
index a540f9d..110d838 100644
--- a/authfs/tests/open_then_run.rs
+++ b/authfs/tests/open_then_run.rs
@@ -22,9 +22,9 @@
 use clap::{App, Arg, Values};
 use command_fds::{CommandFdExt, FdMapping};
 use log::{debug, error};
-use nix::{dir::Dir, fcntl::OFlag, sys::stat::Mode};
-use std::fs::{File, OpenOptions};
-use std::os::unix::io::{AsRawFd, RawFd};
+use std::fs::OpenOptions;
+use std::os::unix::fs::OpenOptionsExt;
+use std::os::unix::io::{AsRawFd, OwnedFd, RawFd};
 use std::process::Command;
 
 // `PseudoRawFd` is just an integer and not necessarily backed by a real FD. It is used to denote
@@ -32,31 +32,30 @@
 // with this alias is to improve readability by distinguishing from actual RawFd.
 type PseudoRawFd = RawFd;
 
-struct FileMapping<T: AsRawFd> {
-    file: T,
+struct OwnedFdMapping {
+    owned_fd: OwnedFd,
     target_fd: PseudoRawFd,
 }
 
-impl<T: AsRawFd> FileMapping<T> {
+impl OwnedFdMapping {
     fn as_fd_mapping(&self) -> FdMapping {
-        FdMapping { parent_fd: self.file.as_raw_fd(), child_fd: self.target_fd }
+        FdMapping { parent_fd: self.owned_fd.as_raw_fd(), child_fd: self.target_fd }
     }
 }
 
 struct Args {
-    ro_files: Vec<FileMapping<File>>,
-    rw_files: Vec<FileMapping<File>>,
-    dir_files: Vec<FileMapping<Dir>>,
+    ro_file_fds: Vec<OwnedFdMapping>,
+    rw_file_fds: Vec<OwnedFdMapping>,
+    dir_fds: Vec<OwnedFdMapping>,
     cmdline_args: Vec<String>,
 }
 
-fn parse_and_create_file_mapping<F, T>(
+fn parse_and_create_file_mapping<F>(
     values: Option<Values<'_>>,
     opener: F,
-) -> Result<Vec<FileMapping<T>>>
+) -> Result<Vec<OwnedFdMapping>>
 where
-    F: Fn(&str) -> Result<T>,
-    T: AsRawFd,
+    F: Fn(&str) -> Result<OwnedFd>,
 {
     if let Some(options) = values {
         options
@@ -68,7 +67,7 @@
                 }
                 let fd = strs[0].parse::<PseudoRawFd>().context("Invalid FD format")?;
                 let path = strs[1];
-                Ok(FileMapping { target_fd: fd, file: opener(path)? })
+                Ok(OwnedFdMapping { target_fd: fd, owned_fd: opener(path)? })
             })
             .collect::<Result<_>>()
     } else {
@@ -104,27 +103,39 @@
              .multiple(true))
         .get_matches();
 
-    let ro_files = parse_and_create_file_mapping(matches.values_of("open-ro"), |path| {
-        OpenOptions::new().read(true).open(path).with_context(|| format!("Open {} read-only", path))
+    let ro_file_fds = parse_and_create_file_mapping(matches.values_of("open-ro"), |path| {
+        Ok(OwnedFd::from(
+            OpenOptions::new()
+                .read(true)
+                .open(path)
+                .with_context(|| format!("Open {} read-only", path))?,
+        ))
     })?;
 
-    let rw_files = parse_and_create_file_mapping(matches.values_of("open-rw"), |path| {
-        OpenOptions::new()
-            .read(true)
-            .write(true)
-            .create(true)
-            .open(path)
-            .with_context(|| format!("Open {} read-write", path))
+    let rw_file_fds = parse_and_create_file_mapping(matches.values_of("open-rw"), |path| {
+        Ok(OwnedFd::from(
+            OpenOptions::new()
+                .read(true)
+                .write(true)
+                .create(true)
+                .open(path)
+                .with_context(|| format!("Open {} read-write", path))?,
+        ))
     })?;
 
-    let dir_files = parse_and_create_file_mapping(matches.values_of("open-dir"), |path| {
-        Dir::open(path, OFlag::O_DIRECTORY | OFlag::O_RDONLY, Mode::S_IRWXU)
-            .with_context(|| format!("Open {} directory", path))
+    let dir_fds = parse_and_create_file_mapping(matches.values_of("open-dir"), |path| {
+        Ok(OwnedFd::from(
+            OpenOptions::new()
+                .custom_flags(libc::O_DIRECTORY)
+                .read(true) // O_DIRECTORY can only be opened with read
+                .open(path)
+                .with_context(|| format!("Open {} directory", path))?,
+        ))
     })?;
 
     let cmdline_args: Vec<_> = matches.values_of("args").unwrap().map(|s| s.to_string()).collect();
 
-    Ok(Args { ro_files, rw_files, dir_files, cmdline_args })
+    Ok(Args { ro_file_fds, rw_file_fds, dir_fds, cmdline_args })
 }
 
 fn try_main() -> Result<()> {
@@ -135,9 +146,9 @@
 
     // Set up FD mappings in the child process.
     let mut fd_mappings = Vec::new();
-    fd_mappings.extend(args.ro_files.iter().map(FileMapping::as_fd_mapping));
-    fd_mappings.extend(args.rw_files.iter().map(FileMapping::as_fd_mapping));
-    fd_mappings.extend(args.dir_files.iter().map(FileMapping::as_fd_mapping));
+    fd_mappings.extend(args.ro_file_fds.iter().map(OwnedFdMapping::as_fd_mapping));
+    fd_mappings.extend(args.rw_file_fds.iter().map(OwnedFdMapping::as_fd_mapping));
+    fd_mappings.extend(args.dir_fds.iter().map(OwnedFdMapping::as_fd_mapping));
     command.fd_mappings(fd_mappings)?;
 
     debug!("Spawning {:?}", command);
diff --git a/compos/composd/src/fd_server_helper.rs b/compos/composd/src/fd_server_helper.rs
index 24dc9e7..777ec27 100644
--- a/compos/composd/src/fd_server_helper.rs
+++ b/compos/composd/src/fd_server_helper.rs
@@ -23,7 +23,7 @@
 use nix::unistd::pipe2;
 use std::fs::File;
 use std::io::Read;
-use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
+use std::os::unix::io::{AsRawFd, FromRawFd, OwnedFd};
 use std::path::Path;
 
 const FD_SERVER_BIN: &str = "/apex/com.android.virt/bin/fd_server";
@@ -32,13 +32,13 @@
 #[derive(Default)]
 pub struct FdServerConfig {
     /// List of file FDs exposed for read-only operations.
-    pub ro_file_fds: Vec<RawFd>,
+    pub ro_file_fds: Vec<OwnedFd>,
     /// List of file FDs exposed for read-write operations.
-    pub rw_file_fds: Vec<RawFd>,
+    pub rw_file_fds: Vec<OwnedFd>,
     /// List of directory FDs exposed for read-only operations.
-    pub ro_dir_fds: Vec<RawFd>,
+    pub ro_dir_fds: Vec<OwnedFd>,
     /// List of directory FDs exposed for read-write operations.
-    pub rw_dir_fds: Vec<RawFd>,
+    pub rw_dir_fds: Vec<OwnedFd>,
 }
 
 impl FdServerConfig {
@@ -53,25 +53,29 @@
     fn do_spawn_fd_server(self, ready_file: File) -> Result<Minijail> {
         let mut inheritable_fds = Vec::new();
         let mut args = vec![FD_SERVER_BIN.to_string()];
-        for fd in self.ro_file_fds {
+        for fd in &self.ro_file_fds {
+            let raw_fd = fd.as_raw_fd();
             args.push("--ro-fds".to_string());
-            args.push(fd.to_string());
-            inheritable_fds.push(fd);
+            args.push(raw_fd.to_string());
+            inheritable_fds.push(raw_fd);
         }
-        for fd in self.rw_file_fds {
+        for fd in &self.rw_file_fds {
+            let raw_fd = fd.as_raw_fd();
             args.push("--rw-fds".to_string());
-            args.push(fd.to_string());
-            inheritable_fds.push(fd);
+            args.push(raw_fd.to_string());
+            inheritable_fds.push(raw_fd);
         }
-        for fd in self.ro_dir_fds {
+        for fd in &self.ro_dir_fds {
+            let raw_fd = fd.as_raw_fd();
             args.push("--ro-dirs".to_string());
-            args.push(fd.to_string());
-            inheritable_fds.push(fd);
+            args.push(raw_fd.to_string());
+            inheritable_fds.push(raw_fd);
         }
-        for fd in self.rw_dir_fds {
+        for fd in &self.rw_dir_fds {
+            let raw_fd = fd.as_raw_fd();
             args.push("--rw-dirs".to_string());
-            args.push(fd.to_string());
-            inheritable_fds.push(fd);
+            args.push(raw_fd.to_string());
+            inheritable_fds.push(raw_fd);
         }
         let ready_fd = ready_file.as_raw_fd();
         args.push("--ready-fd".to_string());
diff --git a/compos/composd/src/odrefresh_task.rs b/compos/composd/src/odrefresh_task.rs
index 100fc50..5c926b1 100644
--- a/compos/composd/src/odrefresh_task.rs
+++ b/compos/composd/src/odrefresh_task.rs
@@ -32,9 +32,9 @@
 };
 use log::{error, info, warn};
 use rustutils::system_properties;
-use std::fs::{remove_dir_all, File, OpenOptions};
+use std::fs::{remove_dir_all, OpenOptions};
 use std::os::unix::fs::OpenOptionsExt;
-use std::os::unix::io::AsRawFd;
+use std::os::unix::io::{AsRawFd, OwnedFd};
 use std::path::Path;
 use std::sync::{Arc, Mutex};
 use std::thread;
@@ -152,14 +152,19 @@
             .with_context(|| format!("Failed to delete {}", target_path.display()))?;
     }
 
-    let staging_dir = open_dir(composd_native::palette_create_odrefresh_staging_directory()?)?;
-    let system_dir = open_dir(Path::new("/system"))?;
-    let output_dir = open_dir(output_root)?;
+    let staging_dir_fd = open_dir(composd_native::palette_create_odrefresh_staging_directory()?)?;
+    let system_dir_fd = open_dir(Path::new("/system"))?;
+    let output_dir_fd = open_dir(output_root)?;
+
+    // Get the raw FD before passing the ownership, since borrowing will violate the borrow check.
+    let system_dir_raw_fd = system_dir_fd.as_raw_fd();
+    let output_dir_raw_fd = output_dir_fd.as_raw_fd();
+    let staging_dir_raw_fd = staging_dir_fd.as_raw_fd();
 
     // Spawn a fd_server to serve the FDs.
     let fd_server_config = FdServerConfig {
-        ro_dir_fds: vec![system_dir.as_raw_fd()],
-        rw_dir_fds: vec![staging_dir.as_raw_fd(), output_dir.as_raw_fd()],
+        ro_dir_fds: vec![system_dir_fd],
+        rw_dir_fds: vec![staging_dir_fd, output_dir_fd],
         ..Default::default()
     };
     let fd_server_raii = fd_server_config.into_fd_server()?;
@@ -169,9 +174,9 @@
         system_properties::read("dalvik.vm.systemservercompilerfilter")?.unwrap_or_default();
     let exit_code = service.odrefresh(
         compilation_mode,
-        system_dir.as_raw_fd(),
-        output_dir.as_raw_fd(),
-        staging_dir.as_raw_fd(),
+        system_dir_raw_fd,
+        output_dir_raw_fd,
+        staging_dir_raw_fd,
         target_dir_name,
         &zygote_arch,
         &system_server_compiler_filter,
@@ -181,12 +186,13 @@
     ExitCode::from_i32(exit_code.into())
 }
 
-/// Returns an owned FD of the directory. It currently returns a `File` as a FD owner, but
-/// it's better to use `std::os::unix::io::OwnedFd` once/if it becomes standard.
-fn open_dir(path: &Path) -> Result<File> {
-    OpenOptions::new()
-        .custom_flags(libc::O_DIRECTORY)
-        .read(true) // O_DIRECTORY can only be opened with read
-        .open(path)
-        .with_context(|| format!("Failed to open {:?} directory as path fd", path))
+/// Returns an `OwnedFD` of the directory.
+fn open_dir(path: &Path) -> Result<OwnedFd> {
+    Ok(OwnedFd::from(
+        OpenOptions::new()
+            .custom_flags(libc::O_DIRECTORY)
+            .read(true) // O_DIRECTORY can only be opened with read
+            .open(path)
+            .with_context(|| format!("Failed to open {:?} directory as path fd", path))?,
+    ))
 }
diff --git a/compos/src/artifact_signer.rs b/compos/src/artifact_signer.rs
index a15df28..e51b8dd 100644
--- a/compos/src/artifact_signer.rs
+++ b/compos/src/artifact_signer.rs
@@ -24,7 +24,7 @@
 use protobuf::Message;
 use std::fs::File;
 use std::io::Write;
-use std::os::unix::io::AsRawFd;
+use std::os::unix::io::AsFd;
 use std::path::Path;
 
 const TARGET_DIRECTORY: &str = "/data/misc/apexdata/com.android.art/dalvik-cache";
@@ -52,7 +52,7 @@
         let target_path = target_path.to_str().ok_or_else(|| anyhow!("Invalid path"))?;
 
         let file = File::open(path).with_context(|| format!("Opening {}", path.display()))?;
-        let digest = fsverity::measure(file.as_raw_fd())?;
+        let digest = fsverity::measure(file.as_fd())?;
         let digest = to_hex_string(&digest);
 
         self.file_digests.push((target_path.to_owned(), digest));
diff --git a/compos/src/fsverity.rs b/compos/src/fsverity.rs
index f5df5f7..4f0ed34 100644
--- a/compos/src/fsverity.rs
+++ b/compos/src/fsverity.rs
@@ -18,7 +18,7 @@
 use libc::getxattr;
 use std::ffi::CString;
 use std::io;
-use std::os::unix::io::RawFd;
+use std::os::unix::io::{AsRawFd, BorrowedFd};
 
 const SHA256_HASH_SIZE: usize = 32;
 
@@ -26,10 +26,10 @@
 pub type Sha256Digest = [u8; SHA256_HASH_SIZE];
 
 /// Returns the fs-verity measurement/digest. Currently only SHA256 is supported.
-pub fn measure(fd: RawFd) -> Result<Sha256Digest> {
+pub fn measure(fd: BorrowedFd) -> Result<Sha256Digest> {
     // TODO(b/196635431): Unfortunately, the FUSE API doesn't allow authfs to implement the standard
     // fs-verity ioctls. Until the kernel allows, use the alternative xattr that authfs provides.
-    let path = CString::new(format!("/proc/self/fd/{}", fd).as_str()).unwrap();
+    let path = CString::new(format!("/proc/self/fd/{}", fd.as_raw_fd()).as_str()).unwrap();
     let name = CString::new("authfs.fsverity.digest").unwrap();
     let mut buf = [0u8; SHA256_HASH_SIZE];
     // SAFETY: getxattr should not write beyond the given buffer size.