ext4_lwext4/blockdev/
mod.rs1mod file;
7mod memory;
8mod traits;
9
10pub use file::FileBlockDevice;
11pub use memory::MemoryBlockDevice;
12pub use traits::{BlockDevice, BlockDeviceExt};
13
14use crate::error::Error;
15use ext4_lwext4_sys::{ext4_blockdev, ext4_blockdev_iface};
16use std::ffi::c_void;
17use std::os::raw::c_int;
18use std::pin::Pin;
19use std::ptr;
20use std::cell::UnsafeCell;
21
22pub(crate) struct BlockDeviceWrapper {
27 device: UnsafeCell<Box<dyn BlockDevice>>,
29 buffer: Pin<Box<[u8]>>,
31 bdif: Pin<Box<ext4_blockdev_iface>>,
33 bdev: Pin<Box<ext4_blockdev>>,
35}
36
37unsafe impl Send for BlockDeviceWrapper {}
39unsafe impl Sync for BlockDeviceWrapper {}
40
41impl BlockDeviceWrapper {
42 pub fn new<B: BlockDevice + 'static>(device: B) -> Pin<Box<Self>> {
44 let block_size = device.block_size();
45 let block_count = device.block_count();
46
47 let buffer = vec![0u8; block_size as usize].into_boxed_slice();
49 let buffer = Pin::new(buffer);
50
51 let bdif = Box::new(ext4_blockdev_iface {
53 open: Some(blockdev_open),
54 bread: Some(blockdev_bread),
55 bwrite: Some(blockdev_bwrite),
56 close: Some(blockdev_close),
57 lock: Some(blockdev_lock),
58 unlock: Some(blockdev_unlock),
59 ph_bsize: block_size,
60 ph_bcnt: block_count,
61 ph_bbuf: ptr::null_mut(), ph_refctr: 0,
63 bread_ctr: 0,
64 bwrite_ctr: 0,
65 p_user: ptr::null_mut(), });
67 let bdif = Pin::new(bdif);
68
69 let bdev = Box::new(ext4_blockdev {
71 bdif: ptr::null_mut(), part_offset: 0,
73 part_size: block_count * block_size as u64,
74 bc: ptr::null_mut(),
75 lg_bsize: 0,
76 lg_bcnt: 0,
77 cache_write_back: 0,
78 fs: ptr::null_mut(),
79 journal: ptr::null_mut(),
80 });
81 let bdev = Pin::new(bdev);
82
83 let wrapper = Box::new(Self {
84 device: UnsafeCell::new(Box::new(device)),
85 buffer,
86 bdif,
87 bdev,
88 });
89
90 let wrapper = Pin::new(wrapper);
91
92 unsafe {
94 let wrapper_ptr = &*wrapper as *const Self as *mut Self;
95
96 let bdif_ptr = &*wrapper.bdif as *const ext4_blockdev_iface as *mut ext4_blockdev_iface;
98 (*bdif_ptr).ph_bbuf = wrapper.buffer.as_ptr() as *mut u8;
99 (*bdif_ptr).p_user = wrapper_ptr as *mut c_void;
100
101 let bdev_ptr = &*wrapper.bdev as *const ext4_blockdev as *mut ext4_blockdev;
103 (*bdev_ptr).bdif = bdif_ptr;
104 }
105
106 wrapper
107 }
108
109 pub fn as_bdev_ptr(&self) -> *mut ext4_blockdev {
111 &*self.bdev as *const ext4_blockdev as *mut ext4_blockdev
112 }
113
114 #[allow(dead_code)]
119 pub(crate) unsafe fn device_mut(&self) -> &mut dyn BlockDevice {
120 unsafe { (*self.device.get()).as_mut() }
121 }
122}
123
124unsafe fn get_wrapper(bdev: *mut ext4_blockdev) -> &'static BlockDeviceWrapper {
130 unsafe {
131 let bdif = (*bdev).bdif;
132 let wrapper_ptr = (*bdif).p_user as *const BlockDeviceWrapper;
133 &*wrapper_ptr
134 }
135}
136
137unsafe extern "C" fn blockdev_open(bdev: *mut ext4_blockdev) -> c_int {
139 unsafe {
140 let wrapper = get_wrapper(bdev);
141 let device = (*wrapper.device.get()).as_mut();
142
143 match device.open() {
144 Ok(()) => 0,
145 Err(e) => match e {
146 Error::Io(io) => io.raw_os_error().unwrap_or(libc::EIO),
147 _ => libc::EIO,
148 },
149 }
150 }
151}
152
153unsafe extern "C" fn blockdev_bread(
155 bdev: *mut ext4_blockdev,
156 buf: *mut c_void,
157 blk_id: u64,
158 blk_cnt: u32,
159) -> c_int {
160 unsafe {
161 let wrapper = get_wrapper(bdev);
162 let device = (*wrapper.device.get()).as_ref();
163 let block_size = device.block_size() as usize;
164 let total_size = block_size * blk_cnt as usize;
165
166 let slice = std::slice::from_raw_parts_mut(buf as *mut u8, total_size);
167
168 match device.read_blocks(blk_id, slice) {
169 Ok(_) => 0,
170 Err(e) => match e {
171 Error::Io(io) => io.raw_os_error().unwrap_or(libc::EIO),
172 _ => libc::EIO,
173 },
174 }
175 }
176}
177
178unsafe extern "C" fn blockdev_bwrite(
180 bdev: *mut ext4_blockdev,
181 buf: *const c_void,
182 blk_id: u64,
183 blk_cnt: u32,
184) -> c_int {
185 unsafe {
186 let wrapper = get_wrapper(bdev);
187 let device = (*wrapper.device.get()).as_mut();
188 let block_size = device.block_size() as usize;
189 let total_size = block_size * blk_cnt as usize;
190
191 let slice = std::slice::from_raw_parts(buf as *const u8, total_size);
192
193 match device.write_blocks(blk_id, slice) {
194 Ok(_) => 0,
195 Err(e) => match e {
196 Error::Io(io) => io.raw_os_error().unwrap_or(libc::EIO),
197 _ => libc::EIO,
198 },
199 }
200 }
201}
202
203unsafe extern "C" fn blockdev_close(bdev: *mut ext4_blockdev) -> c_int {
205 unsafe {
206 let wrapper = get_wrapper(bdev);
207 let device = (*wrapper.device.get()).as_mut();
208
209 match device.close() {
210 Ok(()) => 0,
211 Err(e) => match e {
212 Error::Io(io) => io.raw_os_error().unwrap_or(libc::EIO),
213 _ => libc::EIO,
214 },
215 }
216 }
217}
218
219unsafe extern "C" fn blockdev_lock(_bdev: *mut ext4_blockdev) -> c_int {
221 0
222}
223
224unsafe extern "C" fn blockdev_unlock(_bdev: *mut ext4_blockdev) -> c_int {
226 0
227}