ext4_lwext4/blockdev/
file.rs1use crate::error::{Error, Result};
4use crate::blockdev::traits::BlockDevice;
5use std::fs::{File, OpenOptions};
6use std::io::{Read, Seek, SeekFrom, Write};
7use std::path::Path;
8use std::sync::Mutex;
9
10pub struct FileBlockDevice {
14 file: Mutex<File>,
15 block_size: u32,
16 block_count: u64,
17}
18
19impl FileBlockDevice {
20 pub fn create<P: AsRef<Path>>(path: P, size: u64) -> Result<Self> {
30 Self::create_with_block_size(path, size, 512)
31 }
32
33 pub fn create_with_block_size<P: AsRef<Path>>(
35 path: P,
36 size: u64,
37 block_size: u32,
38 ) -> Result<Self> {
39 let file = OpenOptions::new()
40 .read(true)
41 .write(true)
42 .create(true)
43 .truncate(true)
44 .open(path.as_ref())?;
45
46 file.set_len(size)?;
48
49 let block_count = size / block_size as u64;
50
51 Ok(Self {
52 file: Mutex::new(file),
53 block_size,
54 block_count,
55 })
56 }
57
58 pub fn open<P: AsRef<Path>>(path: P) -> Result<Self> {
66 Self::open_with_block_size(path, 512)
67 }
68
69 pub fn open_with_block_size<P: AsRef<Path>>(path: P, block_size: u32) -> Result<Self> {
71 let file = OpenOptions::new()
72 .read(true)
73 .write(true)
74 .open(path.as_ref())?;
75
76 let size = file.metadata()?.len();
77 let block_count = size / block_size as u64;
78
79 Ok(Self {
80 file: Mutex::new(file),
81 block_size,
82 block_count,
83 })
84 }
85
86 pub fn open_read_only<P: AsRef<Path>>(path: P) -> Result<Self> {
88 Self::open_read_only_with_block_size(path, 512)
89 }
90
91 pub fn open_read_only_with_block_size<P: AsRef<Path>>(
93 path: P,
94 block_size: u32,
95 ) -> Result<Self> {
96 let file = OpenOptions::new()
97 .read(true)
98 .open(path.as_ref())?;
99
100 let size = file.metadata()?.len();
101 let block_count = size / block_size as u64;
102
103 Ok(Self {
104 file: Mutex::new(file),
105 block_size,
106 block_count,
107 })
108 }
109}
110
111impl BlockDevice for FileBlockDevice {
112 fn read_blocks(&self, block_id: u64, buf: &mut [u8]) -> Result<u32> {
113 let offset = block_id * self.block_size as u64;
114 let block_count = buf.len() as u32 / self.block_size;
115
116 let mut file = self.file.lock().map_err(|_| {
117 Error::Io(std::io::Error::new(
118 std::io::ErrorKind::Other,
119 "lock poisoned",
120 ))
121 })?;
122
123 file.seek(SeekFrom::Start(offset))?;
124 file.read_exact(buf)?;
125
126 Ok(block_count)
127 }
128
129 fn write_blocks(&mut self, block_id: u64, buf: &[u8]) -> Result<u32> {
130 let offset = block_id * self.block_size as u64;
131 let block_count = buf.len() as u32 / self.block_size;
132
133 let mut file = self.file.lock().map_err(|_| {
134 Error::Io(std::io::Error::new(
135 std::io::ErrorKind::Other,
136 "lock poisoned",
137 ))
138 })?;
139
140 file.seek(SeekFrom::Start(offset))?;
141 file.write_all(buf)?;
142
143 Ok(block_count)
144 }
145
146 fn flush(&mut self) -> Result<()> {
147 let file = self.file.lock().map_err(|_| {
148 Error::Io(std::io::Error::new(
149 std::io::ErrorKind::Other,
150 "lock poisoned",
151 ))
152 })?;
153 file.sync_all()?;
154 Ok(())
155 }
156
157 fn block_size(&self) -> u32 {
158 self.block_size
159 }
160
161 fn block_count(&self) -> u64 {
162 self.block_count
163 }
164}