authfs: support remote output directory

This change contains 3 major groups:
 - authfs/{aidl, fd_server}: new AIDL API and the service implementation
 - authfs/src: implement FUSE APIs for creating directory and file, by
               interact with the new service API as a client
 - authfs/tests, tests/: test coverage

A few notable changes that might help reviewing:

 - Now that both AuthFs and FdService struct is no longer immutable (in
   order to allow writable directory), their BTreeMap are now guarded by
   Arc<Mutex<_>>.

   * AuthFs::insert_new_inode and FdService::insert_new_fd are designed
     specifically to allow querying then mutating the map, which isn't
     trivial.

 - File and directory modes from the user program / VFS are currently
   ignored (just not to grow the change size).

 - Some shuffling of test paths to make it easy to clean up in tearDown.

Bug: 203251769
Test: AuthFsHostTest
Change-Id: I50f3f1ba8a3ebd969cf0f25a8feab2ec8cb1a2dc
diff --git a/authfs/src/main.rs b/authfs/src/main.rs
index a6956e2..0add77f 100644
--- a/authfs/src/main.rs
+++ b/authfs/src/main.rs
@@ -42,7 +42,7 @@
 mod fusefs;
 
 use auth::FakeAuthenticator;
-use file::{RemoteFileEditor, RemoteFileReader, RemoteMerkleTreeReader};
+use file::{RemoteDirEditor, RemoteFileEditor, RemoteFileReader, RemoteMerkleTreeReader};
 use fsverity::{VerifiedFileEditor, VerifiedFileReader};
 use fusefs::{FileConfig, Inode};
 
@@ -81,6 +81,15 @@
     #[structopt(long, parse(try_from_str = parse_remote_new_rw_file_option))]
     remote_new_rw_file: Vec<OptionRemoteRwFile>,
 
+    /// A new directory that is assumed empty in the backing filesystem. New files created in this
+    /// directory are integrity-protected in the same way as --remote-new-verified-file. Can be
+    /// multiple.
+    ///
+    /// For example, `--remote-new-verified-dir 12:34` tells the filesystem to associate entry 12
+    /// with a remote dir FD 34.
+    #[structopt(long, parse(try_from_str = parse_remote_new_rw_dir_option))]
+    remote_new_rw_dir: Vec<OptionRemoteRwDir>,
+
     /// Enable debugging features.
     #[structopt(long)]
     debug: bool,
@@ -111,6 +120,13 @@
     remote_id: i32,
 }
 
+struct OptionRemoteRwDir {
+    ino: Inode,
+
+    /// ID to refer to the remote dir.
+    remote_id: i32,
+}
+
 fn parse_remote_ro_file_option(option: &str) -> Result<OptionRemoteRoFile> {
     let strs: Vec<&str> = option.split(':').collect();
     if strs.len() != 3 {
@@ -145,6 +161,17 @@
     })
 }
 
+fn parse_remote_new_rw_dir_option(option: &str) -> Result<OptionRemoteRwDir> {
+    let strs: Vec<&str> = option.split(':').collect();
+    if strs.len() != 2 {
+        bail!("Invalid option: {}", option);
+    }
+    Ok(OptionRemoteRwDir {
+        ino: strs[0].parse::<Inode>().unwrap(),
+        remote_id: strs[1].parse::<i32>().unwrap(),
+    })
+}
+
 fn new_config_remote_verified_file(
     service: file::VirtFdService,
     remote_id: i32,
@@ -182,6 +209,14 @@
     Ok(FileConfig::VerifiedNew { editor: VerifiedFileEditor::new(remote_file) })
 }
 
+fn new_config_remote_new_verified_dir(
+    service: file::VirtFdService,
+    remote_id: i32,
+) -> Result<FileConfig> {
+    let dir = RemoteDirEditor::new(service, remote_id);
+    Ok(FileConfig::VerifiedNewDirectory { dir })
+}
+
 fn prepare_file_pool(args: &Args) -> Result<BTreeMap<Inode, FileConfig>> {
     let mut file_pool = BTreeMap::new();
 
@@ -216,6 +251,13 @@
         );
     }
 
+    for config in &args.remote_new_rw_dir {
+        file_pool.insert(
+            config.ino,
+            new_config_remote_new_verified_dir(service.clone(), config.remote_id)?,
+        );
+    }
+
     Ok(file_pool)
 }