Merge "Let fd_server return errno as service specific error"
diff --git a/authfs/aidl/com/android/virt/fs/IVirtFdService.aidl b/authfs/aidl/com/android/virt/fs/IVirtFdService.aidl
index a565a6f..d8f481a 100644
--- a/authfs/aidl/com/android/virt/fs/IVirtFdService.aidl
+++ b/authfs/aidl/com/android/virt/fs/IVirtFdService.aidl
@@ -16,21 +16,16 @@
 
 package com.android.virt.fs;
 
-/** {@hide} */
+/**
+ * A service that works like a file server, where the files and directories are identified by "FD"
+ * as the unique identifier.
+ *
+ * When a binder error is returned and it is a service specific error, the error code is an errno
+ * value which is an int.
+ *
+ * {@hide}
+ */
 interface IVirtFdService {
-    /** Error when the requesting FD is unknown. */
-    const int ERROR_UNKNOWN_FD = 1;
-
-    /**
-     * Error when I/O fails. This can happen when actual I/O error happens to the backing file,
-     * when the given offset or size are invalid, or any problems that can fail a read/write
-     * request.
-     */
-    const int ERROR_IO = 2;
-
-    /** Error when the file is too large to handle correctly. */
-    const int ERROR_FILE_TOO_LARGE = 3;
-
     /** Maximum content size that the service allows the client to request. */
     const int MAX_REQUESTING_DATA = 16384;
 
diff --git a/authfs/fd_server/src/aidl.rs b/authfs/fd_server/src/aidl.rs
index b235025..48547e7 100644
--- a/authfs/fd_server/src/aidl.rs
+++ b/authfs/fd_server/src/aidl.rs
@@ -16,6 +16,7 @@
 
 use anyhow::Result;
 use log::error;
+use nix::errno::Errno;
 use std::cmp::min;
 use std::collections::BTreeMap;
 use std::convert::TryInto;
@@ -26,30 +27,22 @@
 
 use crate::fsverity;
 use authfs_aidl_interface::aidl::com::android::virt::fs::IVirtFdService::{
-    BnVirtFdService, IVirtFdService, ERROR_FILE_TOO_LARGE, ERROR_IO, ERROR_UNKNOWN_FD,
-    MAX_REQUESTING_DATA,
+    BnVirtFdService, IVirtFdService, MAX_REQUESTING_DATA,
 };
 use authfs_aidl_interface::binder::{
-    BinderFeatures, ExceptionCode, Interface, Result as BinderResult, Status, StatusCode, Strong,
+    BinderFeatures, Interface, Result as BinderResult, Status, StatusCode, Strong,
 };
-use binder_common::new_binder_exception;
+use binder_common::new_binder_service_specific_error;
 
 fn validate_and_cast_offset(offset: i64) -> Result<u64, Status> {
-    offset.try_into().map_err(|_| {
-        new_binder_exception(ExceptionCode::ILLEGAL_ARGUMENT, format!("Invalid offset: {}", offset))
-    })
+    offset.try_into().map_err(|_| new_errno_error(Errno::EINVAL))
 }
 
 fn validate_and_cast_size(size: i32) -> Result<usize, Status> {
     if size > MAX_REQUESTING_DATA {
-        Err(new_binder_exception(
-            ExceptionCode::ILLEGAL_ARGUMENT,
-            format!("Unexpectedly large size: {}", size),
-        ))
+        Err(new_errno_error(Errno::EFBIG))
     } else {
-        size.try_into().map_err(|_| {
-            new_binder_exception(ExceptionCode::ILLEGAL_ARGUMENT, format!("Invalid size: {}", size))
-        })
+        size.try_into().map_err(|_| new_errno_error(Errno::EINVAL))
     }
 }
 
@@ -89,7 +82,7 @@
     where
         F: FnOnce(&FdConfig) -> BinderResult<R>,
     {
-        let fd_config = self.fd_pool.get(&id).ok_or_else(|| Status::from(ERROR_UNKNOWN_FD))?;
+        let fd_config = self.fd_pool.get(&id).ok_or_else(|| new_errno_error(Errno::EBADF))?;
         handler(fd_config)
     }
 }
@@ -105,7 +98,7 @@
             FdConfig::Readonly { file, .. } | FdConfig::ReadWrite(file) => {
                 read_into_buf(file, size, offset).map_err(|e| {
                     error!("readFile: read error: {}", e);
-                    Status::from(ERROR_IO)
+                    new_errno_error(Errno::EIO)
                 })
             }
         })
@@ -120,14 +113,14 @@
                 if let Some(tree_file) = &alt_merkle_tree {
                     read_into_buf(tree_file, size, offset).map_err(|e| {
                         error!("readFsverityMerkleTree: read error: {}", e);
-                        Status::from(ERROR_IO)
+                        new_errno_error(Errno::EIO)
                     })
                 } else {
                     let mut buf = vec![0; size];
                     let s = fsverity::read_merkle_tree(file.as_raw_fd(), offset, &mut buf)
                         .map_err(|e| {
                             error!("readFsverityMerkleTree: failed to retrieve merkle tree: {}", e);
-                            Status::from(e.raw_os_error().unwrap_or(ERROR_IO))
+                            new_errno_error(Errno::EIO)
                         })?;
                     debug_assert!(s <= buf.len(), "Shouldn't return more bytes than asked");
                     buf.truncate(s);
@@ -138,7 +131,7 @@
                 // For a writable file, Merkle tree is not expected to be served since Auth FS
                 // doesn't trust it anyway. Auth FS may keep the Merkle tree privately for its own
                 // use.
-                Err(new_binder_exception(ExceptionCode::UNSUPPORTED_OPERATION, "Unsupported"))
+                Err(new_errno_error(Errno::ENOSYS))
             }
         })
     }
@@ -152,13 +145,13 @@
                     let offset = 0;
                     read_into_buf(sig_file, size, offset).map_err(|e| {
                         error!("readFsveritySignature: read error: {}", e);
-                        Status::from(ERROR_IO)
+                        new_errno_error(Errno::EIO)
                     })
                 } else {
                     let mut buf = vec![0; MAX_REQUESTING_DATA as usize];
                     let s = fsverity::read_signature(file.as_raw_fd(), &mut buf).map_err(|e| {
                         error!("readFsverityMerkleTree: failed to retrieve merkle tree: {}", e);
-                        Status::from(e.raw_os_error().unwrap_or(ERROR_IO))
+                        new_errno_error(Errno::EIO)
                     })?;
                     debug_assert!(s <= buf.len(), "Shouldn't return more bytes than asked");
                     buf.truncate(s);
@@ -167,7 +160,7 @@
             }
             FdConfig::ReadWrite(_file) => {
                 // There is no signature for a writable file.
-                Err(new_binder_exception(ExceptionCode::UNSUPPORTED_OPERATION, "Unsupported"))
+                Err(new_errno_error(Errno::ENOSYS))
             }
         })
     }
@@ -176,19 +169,14 @@
         self.handle_fd(id, |config| match config {
             FdConfig::Readonly { .. } => Err(StatusCode::INVALID_OPERATION.into()),
             FdConfig::ReadWrite(file) => {
-                let offset: u64 = offset.try_into().map_err(|_| {
-                    new_binder_exception(ExceptionCode::ILLEGAL_ARGUMENT, "Invalid offset")
-                })?;
+                let offset: u64 = offset.try_into().map_err(|_| new_errno_error(Errno::EINVAL))?;
                 // Check buffer size just to make `as i32` safe below.
                 if buf.len() > i32::MAX as usize {
-                    return Err(new_binder_exception(
-                        ExceptionCode::ILLEGAL_ARGUMENT,
-                        "Buffer size is too big",
-                    ));
+                    return Err(new_errno_error(Errno::EOVERFLOW));
                 }
                 Ok(file.write_at(buf, offset).map_err(|e| {
                     error!("writeFile: write error: {}", e);
-                    Status::from(ERROR_IO)
+                    new_errno_error(Errno::EIO)
                 })? as i32)
             }
         })
@@ -199,14 +187,11 @@
             FdConfig::Readonly { .. } => Err(StatusCode::INVALID_OPERATION.into()),
             FdConfig::ReadWrite(file) => {
                 if size < 0 {
-                    return Err(new_binder_exception(
-                        ExceptionCode::ILLEGAL_ARGUMENT,
-                        "Invalid size to resize to",
-                    ));
+                    return Err(new_errno_error(Errno::EINVAL));
                 }
                 file.set_len(size as u64).map_err(|e| {
                     error!("resize: set_len error: {}", e);
-                    Status::from(ERROR_IO)
+                    new_errno_error(Errno::EIO)
                 })
             }
         })
@@ -219,19 +204,19 @@
                     .metadata()
                     .map_err(|e| {
                         error!("getFileSize error: {}", e);
-                        Status::from(ERROR_IO)
+                        new_errno_error(Errno::EIO)
                     })?
                     .len();
                 Ok(size.try_into().map_err(|e| {
                     error!("getFileSize: File too large: {}", e);
-                    Status::from(ERROR_FILE_TOO_LARGE)
+                    new_errno_error(Errno::EFBIG)
                 })?)
             }
             FdConfig::ReadWrite(_file) => {
                 // Content and metadata of a writable file needs to be tracked by authfs, since
                 // fd_server isn't considered trusted. So there is no point to support getFileSize
                 // for a writable file.
-                Err(new_binder_exception(ExceptionCode::UNSUPPORTED_OPERATION, "Unsupported"))
+                Err(new_errno_error(Errno::ENOSYS))
             }
         })
     }
@@ -244,3 +229,7 @@
     file.read_exact_at(&mut buf, offset)?;
     Ok(buf)
 }
+
+fn new_errno_error(errno: Errno) -> Status {
+    new_binder_service_specific_error(errno as i32, errno.desc())
+}