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::path::Path;
21
22 use super::{ChunkBuffer, RandomWrite, ReadByChunk, VirtFdService};
23 use crate::common::CHUNK_SIZE;
24
remote_read_chunk( service: &VirtFdService, remote_fd: i32, chunk_index: u64, buf: &mut ChunkBuffer, ) -> io::Result<usize>25 fn remote_read_chunk(
26 service: &VirtFdService,
27 remote_fd: i32,
28 chunk_index: u64,
29 buf: &mut ChunkBuffer,
30 ) -> io::Result<usize> {
31 let offset = i64::try_from(chunk_index * CHUNK_SIZE)
32 .map_err(|_| io::Error::from_raw_os_error(libc::EOVERFLOW))?;
33
34 let chunk = service
35 .readFile(remote_fd, offset, buf.len() as i32)
36 .map_err(|e| io::Error::new(io::ErrorKind::Other, e.get_description()))?;
37 let size = min(buf.len(), chunk.len());
38 buf[..size].copy_from_slice(&chunk[..size]);
39 Ok(size)
40 }
41
42 pub struct RemoteFileReader {
43 service: VirtFdService,
44 file_fd: i32,
45 }
46
47 impl RemoteFileReader {
new(service: VirtFdService, file_fd: i32) -> Self48 pub fn new(service: VirtFdService, file_fd: i32) -> Self {
49 RemoteFileReader { service, file_fd }
50 }
51
new_by_path( service: VirtFdService, dir_fd: i32, related_path: &Path, ) -> io::Result<Self>52 pub fn new_by_path(
53 service: VirtFdService,
54 dir_fd: i32,
55 related_path: &Path,
56 ) -> io::Result<Self> {
57 let file_fd =
58 service.openFileInDirectory(dir_fd, related_path.to_str().unwrap()).map_err(|e| {
59 io::Error::new(
60 io::ErrorKind::Other,
61 format!(
62 "Failed to create a remote file reader by path {}: {}",
63 related_path.display(),
64 e.get_description()
65 ),
66 )
67 })?;
68 Ok(RemoteFileReader { service, file_fd })
69 }
70
get_remote_fd(&self) -> i3271 pub fn get_remote_fd(&self) -> i32 {
72 self.file_fd
73 }
74 }
75
76 impl ReadByChunk for RemoteFileReader {
read_chunk(&self, chunk_index: u64, buf: &mut ChunkBuffer) -> io::Result<usize>77 fn read_chunk(&self, chunk_index: u64, buf: &mut ChunkBuffer) -> io::Result<usize> {
78 remote_read_chunk(&self.service, self.file_fd, chunk_index, buf)
79 }
80 }
81
82 pub struct RemoteMerkleTreeReader {
83 service: VirtFdService,
84 file_fd: i32,
85 }
86
87 impl RemoteMerkleTreeReader {
new(service: VirtFdService, file_fd: i32) -> Self88 pub fn new(service: VirtFdService, file_fd: i32) -> Self {
89 RemoteMerkleTreeReader { service, file_fd }
90 }
91 }
92
93 impl ReadByChunk for RemoteMerkleTreeReader {
read_chunk(&self, chunk_index: u64, buf: &mut ChunkBuffer) -> io::Result<usize>94 fn read_chunk(&self, chunk_index: u64, buf: &mut ChunkBuffer) -> io::Result<usize> {
95 let offset = i64::try_from(chunk_index * CHUNK_SIZE)
96 .map_err(|_| io::Error::from_raw_os_error(libc::EOVERFLOW))?;
97
98 let chunk = self
99 .service
100 .readFsverityMerkleTree(self.file_fd, offset, buf.len() as i32)
101 .map_err(|e| io::Error::new(io::ErrorKind::Other, e.get_description()))?;
102 let size = min(buf.len(), chunk.len());
103 buf[..size].copy_from_slice(&chunk[..size]);
104 Ok(size)
105 }
106 }
107
108 pub struct RemoteFileEditor {
109 service: VirtFdService,
110 file_fd: i32,
111 }
112
113 impl RemoteFileEditor {
new(service: VirtFdService, file_fd: i32) -> Self114 pub fn new(service: VirtFdService, file_fd: i32) -> Self {
115 RemoteFileEditor { service, file_fd }
116 }
117 }
118
119 impl RandomWrite for RemoteFileEditor {
write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize>120 fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
121 let offset =
122 i64::try_from(offset).map_err(|_| io::Error::from_raw_os_error(libc::EOVERFLOW))?;
123 let size = self
124 .service
125 .writeFile(self.file_fd, buf, offset)
126 .map_err(|e| io::Error::new(io::ErrorKind::Other, e.get_description()))?;
127 Ok(size as usize) // within range because size is supposed to <= buf.len(), which is a usize
128 }
129
resize(&self, size: u64) -> io::Result<()>130 fn resize(&self, size: u64) -> io::Result<()> {
131 let size =
132 i64::try_from(size).map_err(|_| io::Error::from_raw_os_error(libc::EOVERFLOW))?;
133 self.service
134 .resize(self.file_fd, size)
135 .map_err(|e| io::Error::new(io::ErrorKind::Other, e.get_description()))?;
136 Ok(())
137 }
138 }
139
140 impl ReadByChunk for RemoteFileEditor {
read_chunk(&self, chunk_index: u64, buf: &mut ChunkBuffer) -> io::Result<usize>141 fn read_chunk(&self, chunk_index: u64, buf: &mut ChunkBuffer) -> io::Result<usize> {
142 remote_read_chunk(&self.service, self.file_fd, chunk_index, buf)
143 }
144 }
145