ext4_read_only/
readers.rs1use fuchsia_sync::Mutex;
6use std::io::{Read, Seek, SeekFrom};
7use std::sync::Arc;
8use thiserror::Error;
9
10#[cfg(target_os = "fuchsia")]
11pub use self::fuchsia::*;
12
13#[derive(Error, Debug, PartialEq)]
14pub enum ReaderError {
15 #[error("Read error at: 0x{:X}", _0)]
16 Read(u64),
17 #[error("Out of bound read 0x{:X} when size is 0x{:X}", _0, _1)]
18 OutOfBounds(u64, u64),
19}
20
21pub trait Reader: Send + Sync {
22 fn read(&self, offset: u64, data: &mut [u8]) -> Result<(), ReaderError>;
23}
24
25impl Reader for Box<dyn Reader> {
30 fn read(&self, offset: u64, data: &mut [u8]) -> Result<(), ReaderError> {
31 self.as_ref().read(offset, data)
32 }
33}
34
35impl Reader for Arc<dyn Reader> {
36 fn read(&self, offset: u64, data: &mut [u8]) -> Result<(), ReaderError> {
37 self.as_ref().read(offset, data)
38 }
39}
40
41pub struct IoAdapter<T>(Mutex<T>);
43
44impl<T> IoAdapter<T> {
45 pub fn new(inner: T) -> Self {
46 Self(Mutex::new(inner))
47 }
48}
49
50impl<T: Read + Seek + Send + Sync> Reader for IoAdapter<T> {
51 fn read(&self, offset: u64, data: &mut [u8]) -> Result<(), ReaderError> {
52 let mut reader = self.0.lock();
53 reader.seek(SeekFrom::Start(offset)).map_err(|_| ReaderError::Read(offset))?;
54 reader.read_exact(data).map_err(|_| ReaderError::Read(offset))
55 }
56}
57
58pub struct VecReader {
59 data: Vec<u8>,
60}
61
62impl Reader for VecReader {
63 fn read(&self, offset: u64, data: &mut [u8]) -> Result<(), ReaderError> {
64 let data_len = data.len() as u64;
65 let self_data_len = self.data.len() as u64;
66 let offset_max = offset + data_len;
67 if offset_max > self_data_len {
68 return Err(ReaderError::OutOfBounds(offset_max, self_data_len));
69 }
70
71 let offset_for_range: usize = offset.try_into().unwrap();
72
73 match self.data.get(offset_for_range..offset_for_range + data.len()) {
74 Some(slice) => {
75 data.clone_from_slice(slice);
76 Ok(())
77 }
78 None => Err(ReaderError::Read(offset)),
79 }
80 }
81}
82
83impl VecReader {
84 pub fn new(filesystem: Vec<u8>) -> Self {
85 VecReader { data: filesystem }
86 }
87}
88
89#[cfg(target_os = "fuchsia")]
90mod fuchsia {
91 use super::{Reader, ReaderError};
92 use anyhow::Error;
93 use block_client::{Cache, RemoteBlockClientSync};
94 use fidl::endpoints::ClientEnd;
95 use fidl_fuchsia_hardware_block::BlockMarker;
96 use fuchsia_sync::Mutex;
97 use log::error;
98 use std::sync::Arc;
99
100 pub struct VmoReader {
101 vmo: Arc<zx::Vmo>,
102 }
103
104 impl Reader for VmoReader {
105 fn read(&self, offset: u64, data: &mut [u8]) -> Result<(), ReaderError> {
106 match self.vmo.read(data, offset) {
107 Ok(_) => Ok(()),
108 Err(zx::Status::OUT_OF_RANGE) => {
109 let size = self.vmo.get_size().map_err(|_| ReaderError::Read(u64::MAX))?;
110 Err(ReaderError::OutOfBounds(offset, size))
111 }
112 Err(_) => Err(ReaderError::Read(offset)),
113 }
114 }
115 }
116
117 impl VmoReader {
118 pub fn new(vmo: Arc<zx::Vmo>) -> Self {
119 VmoReader { vmo }
120 }
121 }
122
123 pub struct BlockDeviceReader {
124 block_cache: Mutex<Cache>,
125 }
126
127 impl Reader for BlockDeviceReader {
128 fn read(&self, offset: u64, data: &mut [u8]) -> Result<(), ReaderError> {
129 self.block_cache.lock().read_at(data, offset).map_err(|e| {
130 error!("Encountered error while reading block device: {}", e);
131 ReaderError::Read(offset)
132 })
133 }
134 }
135
136 impl BlockDeviceReader {
137 pub fn from_client_end(client_end: ClientEnd<BlockMarker>) -> Result<Self, Error> {
138 Ok(Self {
139 block_cache: Mutex::new(Cache::new(RemoteBlockClientSync::new(client_end)?)?),
140 })
141 }
142 }
143}