open_then_run: Hold fd with OwnedFd instead of File/Dir

Stop using Dir from the nix crate. As we're now holding the FD by
OwnedFd, Dir doesn't allow us to transfer out the FD ownership.

Test: TH
Bug: 243500154
Change-Id: Ic5f2ead12f71c4cd2d8b34be8bd9dd548f49a87b
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);