Read Merkle tree once per file

EagerChunkReader is added to read the wrapper Merkle tree reader. Also
add a function to calculate the tree size, in order to know how much
bytes to read.

Separately, add a check in fd_server to prevent crash when the read size
is 0.

Bug: 182827266
Test: atest AuthFsHostTest authfs_device_test_src_lib
Change-Id: Ibff8c9ac091f1449aec8f4a52cd148e6f41d7b33
diff --git a/authfs/src/fsverity/common.rs b/authfs/src/fsverity/common.rs
index 8889f5c..83e8ae4 100644
--- a/authfs/src/fsverity/common.rs
+++ b/authfs/src/fsverity/common.rs
@@ -52,6 +52,18 @@
     log128_ceil(hash_pages)
 }
 
+/// Returns the size of Merkle tree for `data_size` bytes amount of data.
+pub fn merkle_tree_size(mut data_size: u64) -> u64 {
+    let mut total = 0;
+    while data_size > CHUNK_SIZE {
+        let hash_size = divide_roundup(data_size, CHUNK_SIZE) * Sha256Hasher::HASH_SIZE as u64;
+        let hash_storage_size = divide_roundup(hash_size, CHUNK_SIZE) * CHUNK_SIZE;
+        total += hash_storage_size;
+        data_size = hash_storage_size;
+    }
+    total
+}
+
 pub fn build_fsverity_digest(
     root_hash: &Sha256Hash,
     file_size: u64,
@@ -75,3 +87,22 @@
         .update(&[0u8; 16])? // reserved
         .finalize()
 }
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test_merkle_tree_size() {
+        // To produce groundtruth:
+        //   dd if=/dev/zero of=zeros bs=1 count=524289 && \
+        //   fsverity digest --out-merkle-tree=tree zeros && \
+        //   du -b tree
+        assert_eq!(merkle_tree_size(0), 0);
+        assert_eq!(merkle_tree_size(1), 0);
+        assert_eq!(merkle_tree_size(4096), 0);
+        assert_eq!(merkle_tree_size(4097), 4096);
+        assert_eq!(merkle_tree_size(524288), 4096);
+        assert_eq!(merkle_tree_size(524289), 12288);
+    }
+}