virtual_file_system/
synchronous_file.rs1use core::{fmt::Debug, mem::forget};
2
3use crate::{Error, ItemStatic, Result, VirtualFileSystem};
4use alloc::{vec, vec::Vec};
5use exported_file_system::StateFlags;
6use exported_file_system::{ControlCommand, Permissions};
7use file_system::{
8 AccessFlags, AttributeFlags, Attributes, Context, Flags, Path, Position, Size, Statistics,
9};
10use shared::AnyByLayout;
11use task::TaskIdentifier;
12use task::block_on;
13use users::{GroupIdentifier, UserIdentifier};
14
15pub struct SynchronousFile {
16 pub(crate) item: ItemStatic,
17 pub(crate) position: Size,
18 pub(crate) flags: Flags,
19 pub(crate) context: Context,
20}
21
22impl Debug for SynchronousFile {
23 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
24 f.debug_struct("SynchronousFile")
25 .field("item", &self.item)
26 .field("position", &self.position)
27 .field("flags", &self.flags)
28 .finish()
29 }
30}
31
32impl SynchronousFile {
33 pub(crate) const fn new(
34 item: ItemStatic,
35 position: Size,
36 flags: Flags,
37 context: Context,
38 ) -> Self {
39 Self {
40 item,
41 position,
42 flags,
43 context,
44 }
45 }
46
47 pub fn open(
48 virtual_file_system: &VirtualFileSystem,
49 task: TaskIdentifier,
50 path: impl AsRef<Path>,
51 flags: Flags,
52 ) -> Result<Self> {
53 let file_identifier = block_on(virtual_file_system.open(&path, flags, task))?;
54
55 Ok(file_identifier.into_synchronous_file())
56 }
57
58 pub fn set_position(&mut self, position: &Position) -> Result<Size> {
59 self.position = self
60 .item
61 .as_base_operations()
62 .ok_or(Error::UnsupportedOperation)?
63 .set_position(&mut self.context, self.position, position)?;
64
65 Ok(self.position)
66 }
67
68 pub fn write(&mut self, buffer: &[u8]) -> Result<usize> {
71 if !self.flags.get_access().contains(AccessFlags::Write) {
72 return Err(Error::InvalidMode);
73 }
74
75 let size = self
76 .item
77 .as_base_operations()
78 .ok_or(Error::UnsupportedOperation)?
79 .write(&mut self.context, buffer, self.position)?;
80
81 self.position += size as Size;
82
83 Ok(size)
84 }
85
86 pub fn write_vectored(&mut self, buffers: &[&[u8]]) -> Result<usize> {
87 if !self.flags.get_access().contains(AccessFlags::Write) {
88 return Err(Error::InvalidMode);
89 }
90
91 let size = self
92 .item
93 .as_base_operations()
94 .ok_or(Error::UnsupportedOperation)?
95 .write_vectored(&mut self.context, buffers, self.position)?;
96
97 self.position += size as Size;
98
99 Ok(size)
100 }
101
102 pub fn write_line(&mut self, buffer: &[u8]) -> Result<usize> {
103 let size = self.write(buffer)? + self.write(b"\n")?;
104
105 Ok(size)
106 }
107
108 pub fn read(&mut self, buffer: &mut [u8]) -> Result<usize> {
109 let size = self
110 .item
111 .as_base_operations()
112 .ok_or(Error::UnsupportedOperation)?
113 .read(&mut self.context, buffer, self.position)?;
114
115 self.position += size as Size;
116
117 Ok(size)
118 }
119
120 pub fn read_until(&mut self, buffer: &mut [u8], delimiter: &[u8]) -> Result<usize> {
121 let size = self
122 .item
123 .as_base_operations()
124 .ok_or(Error::UnsupportedOperation)?
125 .read_until(&mut self.context, buffer, self.position, delimiter)?;
126
127 self.position += size as Size;
128
129 Ok(size)
130 }
131
132 pub fn read_to_end(&mut self, buffer: &mut Vec<u8>, chunk_size: usize) -> Result<usize> {
133 let mut total_read_size = 0;
134
135 let mut chunk = vec![0u8; chunk_size];
136 loop {
137 let read_size = self
138 .item
139 .as_base_operations()
140 .ok_or(Error::UnsupportedOperation)?
141 .read(&mut self.context, &mut chunk, self.position)?;
142
143 if read_size == 0 {
144 break;
145 }
146
147 self.position += read_size as Size;
148
149 total_read_size += read_size;
150
151 buffer.extend_from_slice(&chunk[..read_size]);
152
153 }
156
157 Ok(total_read_size)
158 }
159
160 pub fn flush(&mut self) -> Result<()> {
161 self.item
162 .as_base_operations()
163 .ok_or(Error::UnsupportedOperation)?
164 .flush(&mut self.context)?;
165
166 Ok(())
167 }
168
169 pub fn duplicate(&self) -> Result<Self> {
170 let context = self
171 .item
172 .as_base_operations()
173 .ok_or(Error::UnsupportedOperation)?
174 .clone_context(&self.context)?;
175
176 Ok(Self {
177 item: self.item.clone(),
178 position: self.position,
179 flags: self.flags,
180 context,
181 })
182 }
183
184 pub fn get_statistics(&mut self) -> Result<Statistics> {
185 let mut attributes = Attributes::new().set_mask(AttributeFlags::All);
186
187 self.item
188 .as_attributes_operations()
189 .ok_or(Error::UnsupportedOperation)?
190 .get_attributes(&mut self.context, &mut attributes)?;
191
192 Statistics::from_attributes(&attributes).ok_or(Error::MissingAttribute)
193 }
194
195 pub fn set_owner(
196 &mut self,
197 user: Option<UserIdentifier>,
198 group: Option<GroupIdentifier>,
199 ) -> Result<()> {
200 let mut attributes = Attributes::new();
201
202 if let Some(user) = user {
203 attributes = attributes.set_user(user);
204 }
205
206 if let Some(group) = group {
207 attributes = attributes.set_group(group);
208 }
209
210 self.item
211 .as_attributes_operations()
212 .ok_or(Error::UnsupportedOperation)?
213 .set_attributes(&mut self.context, &attributes)?;
214
215 Ok(())
216 }
217
218 pub fn set_permissions(&mut self, permissions: Permissions) -> Result<()> {
219 let attributes = Attributes::new().set_permissions(permissions);
220
221 self.item
222 .as_attributes_operations()
223 .ok_or(Error::UnsupportedOperation)?
224 .set_attributes(&mut self.context, &attributes)?;
225
226 Ok(())
227 }
228
229 pub fn control<C>(&mut self, _command: C, argument: &C::Input) -> Result<C::Output>
230 where
231 C: ControlCommand,
232 C::Output: Default,
233 {
234 let mut output = C::Output::default();
235
236 self.item
237 .as_base_operations()
238 .ok_or(Error::UnsupportedOperation)?
239 .control(
240 &mut self.context,
241 C::IDENTIFIER,
242 AnyByLayout::from(argument),
243 AnyByLayout::from_mutable(&mut output),
244 )?;
245
246 Ok(output)
247 }
248
249 pub fn get_access(&self) -> Result<AccessFlags> {
250 Ok(self.flags.get_access())
251 }
252
253 pub fn get_state(&self) -> Result<StateFlags> {
254 Ok(self.flags.get_state())
255 }
256
257 pub fn close_internal(&mut self, virtual_file_system: &VirtualFileSystem) -> crate::Result<()> {
258 block_on(virtual_file_system.close(&self.item, &mut self.context))
259 }
260
261 pub fn close(mut self, virtual_file_system: &VirtualFileSystem) -> crate::Result<()> {
262 let result = self.close_internal(virtual_file_system);
263 forget(self);
264
265 result
266 }
267}
268
269impl Drop for SynchronousFile {
270 fn drop(&mut self) {
271 let _ = self.close_internal(crate::get_instance()).map_err(|e| {
273 log::warning!("Failed to close SynchronousFile in Drop: {e}");
274 });
275 }
276}