1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 use std::cmp::min;
18 use std::convert::TryFrom;
19 use std::io;
20 use std::sync::{Arc, Mutex};
21 
22 use super::{ChunkBuffer, RandomWrite, ReadByChunk};
23 use crate::common::CHUNK_SIZE;
24 
25 use authfs_aidl_interface::aidl::com::android::virt::fs::IVirtFdService;
26 use authfs_aidl_interface::binder::Strong;
27 
28 type VirtFdService = Strong<dyn IVirtFdService::IVirtFdService>;
29 
remote_read_chunk( service: &Arc<Mutex<VirtFdService>>, remote_fd: i32, chunk_index: u64, buf: &mut ChunkBuffer, ) -> io::Result<usize>30 fn remote_read_chunk(
31     service: &Arc<Mutex<VirtFdService>>,
32     remote_fd: i32,
33     chunk_index: u64,
34     buf: &mut ChunkBuffer,
35 ) -> io::Result<usize> {
36     let offset = i64::try_from(chunk_index * CHUNK_SIZE)
37         .map_err(|_| io::Error::from_raw_os_error(libc::EOVERFLOW))?;
38 
39     let chunk = service
40         .lock()
41         .unwrap()
42         .readFile(remote_fd, offset, buf.len() as i32)
43         .map_err(|e| io::Error::new(io::ErrorKind::Other, e.get_description()))?;
44     let size = min(buf.len(), chunk.len());
45     buf[..size].copy_from_slice(&chunk[..size]);
46     Ok(size)
47 }
48 
49 pub struct RemoteFileReader {
50     // This needs to have Sync trait to be used in fuse::worker::start_message_loop.
51     service: Arc<Mutex<VirtFdService>>,
52     file_fd: i32,
53 }
54 
55 impl RemoteFileReader {
new(service: Arc<Mutex<VirtFdService>>, file_fd: i32) -> Self56     pub fn new(service: Arc<Mutex<VirtFdService>>, file_fd: i32) -> Self {
57         RemoteFileReader { service, file_fd }
58     }
59 }
60 
61 impl ReadByChunk for RemoteFileReader {
read_chunk(&self, chunk_index: u64, buf: &mut ChunkBuffer) -> io::Result<usize>62     fn read_chunk(&self, chunk_index: u64, buf: &mut ChunkBuffer) -> io::Result<usize> {
63         remote_read_chunk(&self.service, self.file_fd, chunk_index, buf)
64     }
65 }
66 
67 pub struct RemoteMerkleTreeReader {
68     // This needs to be a Sync to be used in fuse::worker::start_message_loop.
69     // TODO(victorhsieh): change to Strong<> once binder supports it.
70     service: Arc<Mutex<VirtFdService>>,
71     file_fd: i32,
72 }
73 
74 impl RemoteMerkleTreeReader {
new(service: Arc<Mutex<VirtFdService>>, file_fd: i32) -> Self75     pub fn new(service: Arc<Mutex<VirtFdService>>, file_fd: i32) -> Self {
76         RemoteMerkleTreeReader { service, file_fd }
77     }
78 }
79 
80 impl ReadByChunk for RemoteMerkleTreeReader {
read_chunk(&self, chunk_index: u64, buf: &mut ChunkBuffer) -> io::Result<usize>81     fn read_chunk(&self, chunk_index: u64, buf: &mut ChunkBuffer) -> io::Result<usize> {
82         let offset = i64::try_from(chunk_index * CHUNK_SIZE)
83             .map_err(|_| io::Error::from_raw_os_error(libc::EOVERFLOW))?;
84 
85         let chunk = self
86             .service
87             .lock()
88             .unwrap()
89             .readFsverityMerkleTree(self.file_fd, offset, buf.len() as i32)
90             .map_err(|e| io::Error::new(io::ErrorKind::Other, e.get_description()))?;
91         let size = min(buf.len(), chunk.len());
92         buf[..size].copy_from_slice(&chunk[..size]);
93         Ok(size)
94     }
95 }
96 
97 pub struct RemoteFileEditor {
98     // This needs to have Sync trait to be used in fuse::worker::start_message_loop.
99     service: Arc<Mutex<VirtFdService>>,
100     file_fd: i32,
101 }
102 
103 impl RemoteFileEditor {
new(service: Arc<Mutex<VirtFdService>>, file_fd: i32) -> Self104     pub fn new(service: Arc<Mutex<VirtFdService>>, file_fd: i32) -> Self {
105         RemoteFileEditor { service, file_fd }
106     }
107 }
108 
109 impl RandomWrite for RemoteFileEditor {
write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize>110     fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
111         let offset =
112             i64::try_from(offset).map_err(|_| io::Error::from_raw_os_error(libc::EOVERFLOW))?;
113         let size = self
114             .service
115             .lock()
116             .unwrap()
117             .writeFile(self.file_fd, &buf, offset)
118             .map_err(|e| io::Error::new(io::ErrorKind::Other, e.get_description()))?;
119         Ok(size as usize) // within range because size is supposed to <= buf.len(), which is a usize
120     }
121 
resize(&self, size: u64) -> io::Result<()>122     fn resize(&self, size: u64) -> io::Result<()> {
123         let size =
124             i64::try_from(size).map_err(|_| io::Error::from_raw_os_error(libc::EOVERFLOW))?;
125         self.service
126             .lock()
127             .unwrap()
128             .resize(self.file_fd, size)
129             .map_err(|e| io::Error::new(io::ErrorKind::Other, e.get_description()))?;
130         Ok(())
131     }
132 }
133 
134 impl ReadByChunk for RemoteFileEditor {
read_chunk(&self, chunk_index: u64, buf: &mut ChunkBuffer) -> io::Result<usize>135     fn read_chunk(&self, chunk_index: u64, buf: &mut ChunkBuffer) -> io::Result<usize> {
136         remote_read_chunk(&self.service, self.file_fd, chunk_index, buf)
137     }
138 }
139