1use super::*;
2
3impl<'fs, D: BlockDevice + 'static> FileWriter<'fs, D> {
4 pub fn write(&mut self, data: &[u8]) -> Result<usize> {
5 if self.stream.is_some() {
6 self.write_streaming(data)?;
7 return Ok(data.len());
8 }
9
10 let end = self.pos.checked_add(data.len()).ok_or(Error::NoSpace)?;
11 if end > self.fs.info().file_max as usize {
12 return Err(Error::FileTooLarge);
13 }
14 if end > self.fs.fs.inline_threshold() && self.pos == self.data.len() {
15 self.start_streaming_from_buffer()?;
16 self.write_streaming(data)?;
17 return Ok(data.len());
18 }
19 if end > self.data.len() {
20 self.data.resize(end, 0);
21 }
22 self.data[self.pos..end].copy_from_slice(data);
23 self.pos = end;
24 if self.data.len() > self.fs.fs.inline_threshold() && self.pos == self.data.len() {
25 self.start_streaming_from_buffer()?;
26 }
27 Ok(data.len())
28 }
29
30 pub fn write_all(&mut self, data: &[u8]) -> Result<()> {
31 self.write(data)?;
32 Ok(())
33 }
34
35 pub fn seek(&mut self, pos: usize) -> Result<()> {
36 if let Some(stream) = &self.stream {
37 if pos != stream.len {
38 return Err(Error::Unsupported);
39 }
40 }
41 self.pos = pos;
42 Ok(())
43 }
44
45 pub fn close(self) -> Result<()> {
46 match self.stream {
47 Some(stream) => self.fs.finish_streaming_create_file(self.path, stream),
48 None => self.fs.create_file(&self.path, &self.data),
49 }
50 }
51
52 fn start_streaming_from_buffer(&mut self) -> Result<()> {
53 let buffered = core::mem::take(&mut self.data);
54 self.stream = Some(StreamingWrite {
55 allocator: self.fs.allocator.clone(),
56 blocks: Vec::new(),
57 current: None,
58 len: 0,
59 target: StreamingTarget::Create,
60 });
61 self.pos = 0;
62 self.write_streaming(&buffered)
63 }
64
65 fn write_streaming(&mut self, mut data: &[u8]) -> Result<()> {
66 let stream = self.stream.as_mut().ok_or(Error::Corrupt)?;
67 if self.pos != stream.len {
68 return Err(Error::Unsupported);
69 }
70 if stream.len.checked_add(data.len()).ok_or(Error::NoSpace)?
71 > self.fs.info().file_max as usize
72 {
73 return Err(Error::FileTooLarge);
74 }
75
76 while !data.is_empty() {
77 if stream.current.is_none() {
78 let index = stream.blocks.len();
79 let block = stream.allocator.alloc_block()?;
80 let mut bytes = alloc::vec![0xff; self.fs.info().block_size as usize];
81 let data_start = ctz_data_start(index)?;
82 if index > 0 {
83 let skips = index.trailing_zeros() as usize + 1;
84 for skip in 0..skips {
85 let target_index =
86 index.checked_sub(1usize << skip).ok_or(Error::Corrupt)?;
87 let target = stream
88 .blocks
89 .get(target_index)
90 .copied()
91 .ok_or(Error::Corrupt)?;
92 program_nor_bytes(&mut bytes, skip * 4, &target.to_le_bytes())?;
93 }
94 }
95 stream.current = Some(StreamingBlock {
96 block,
97 bytes,
98 off: data_start,
99 mode: StreamingBlockMode::New,
100 });
101 }
102
103 let current = stream.current.as_mut().ok_or(Error::Corrupt)?;
104 let capacity = current.bytes.len().saturating_sub(current.off);
105 let n = core::cmp::min(capacity, data.len());
106 current.bytes[current.off..current.off + n].copy_from_slice(&data[..n]);
107 current.off += n;
108 stream.len = stream.len.checked_add(n).ok_or(Error::NoSpace)?;
109 self.pos = stream.len;
110 data = &data[n..];
111
112 if current.off == current.bytes.len() {
113 let current = stream.current.take().ok_or(Error::Corrupt)?;
114 self.fs.flush_streaming_block(stream, current)?;
115 }
116 }
117
118 Ok(())
119 }
120}
121
122impl FileOptions {
123 pub fn new() -> Self {
124 Self::default()
125 }
126
127 pub fn read(mut self, value: bool) -> Self {
128 self.read = value;
129 self
130 }
131
132 pub fn write(mut self, value: bool) -> Self {
133 self.write = value;
134 self
135 }
136
137 pub fn create(mut self, value: bool) -> Self {
138 self.create = value;
139 self
140 }
141
142 pub fn create_new(mut self, value: bool) -> Self {
143 self.create_new = value;
144 self
145 }
146
147 pub fn truncate(mut self, value: bool) -> Self {
148 self.truncate = value;
149 self
150 }
151
152 pub fn append(mut self, value: bool) -> Self {
153 self.append = value;
154 self
155 }
156}
157
158impl<'fs, D: BlockDevice + 'static> FileHandle<'fs, D> {
159 pub fn read(&mut self, out: &mut [u8]) -> Result<usize> {
160 if !self.readable {
161 return Err(Error::BadFileDescriptor);
162 }
163 if self.stream.is_some() {
164 return Err(Error::Unsupported);
165 }
166 if self.merge.is_some() {
167 return Err(Error::Unsupported);
168 }
169 if self.stream_read {
170 let source = self.stream_source.as_ref().ok_or(Error::Corrupt)?;
171 let n = self.fs.read_file_data_at(source, self.pos, out)?;
172 self.pos += n;
173 return Ok(n);
174 }
175 let available = self.data.len().saturating_sub(self.pos);
176 let n = core::cmp::min(out.len(), available);
177 out[..n].copy_from_slice(&self.data[self.pos..self.pos + n]);
178 self.pos += n;
179 Ok(n)
180 }
181
182 pub fn write(&mut self, data: &[u8]) -> Result<usize> {
183 if !self.writable {
184 return Err(Error::BadFileDescriptor);
185 }
186 if self.stream.is_some() {
187 self.write_streaming(data)?;
188 return Ok(data.len());
189 }
190 if self.merge.is_some() {
191 return self.write_merge_patch(data);
192 }
193 let end = self.pos.checked_add(data.len()).ok_or(Error::NoSpace)?;
194 if end > self.fs.info().file_max as usize {
195 return Err(Error::FileTooLarge);
196 }
197 if end > self.fs.fs.inline_threshold() && self.pos == self.data.len() {
198 self.start_streaming_from_buffer()?;
199 self.write_streaming(data)?;
200 return Ok(data.len());
201 }
202 if end > self.data.len() {
203 self.data.resize(end, 0);
204 }
205 self.data[self.pos..end].copy_from_slice(data);
206 self.pos = end;
207 self.len = self.data.len();
208 self.dirty = true;
209 if self.data.len() > self.fs.fs.inline_threshold() && self.pos == self.data.len() {
210 self.start_streaming_from_buffer()?;
211 }
212 Ok(data.len())
213 }
214
215 pub fn write_all(&mut self, data: &[u8]) -> Result<()> {
216 self.write(data)?;
217 Ok(())
218 }
219
220 pub fn seek(&mut self, pos: usize) -> Result<()> {
221 if let Some(stream) = &self.stream {
222 if pos != stream.len {
223 return Err(Error::Unsupported);
224 }
225 }
226 self.pos = pos;
227 Ok(())
228 }
229
230 pub fn truncate(&mut self, len: usize) -> Result<()> {
231 if !self.writable {
232 return Err(Error::BadFileDescriptor);
233 }
234 if len > self.fs.info().file_max as usize {
235 return Err(Error::Unsupported);
236 }
237 if self.stream.is_some() {
238 return Err(Error::Unsupported);
239 }
240 if self.merge.is_some() {
241 self.promote_merge_to_buffer()?;
242 }
243 self.data.resize(len, 0);
244 if self.pos > len {
245 self.pos = len;
246 }
247 self.len = len;
248 self.dirty = true;
249 Ok(())
250 }
251
252 pub fn flush(&mut self) -> Result<()> {
253 if !self.dirty {
254 return Ok(());
255 }
256 if let Some(merge) = self.merge.clone() {
260 self.flush_merge_patches(merge)?;
261 self.data = self.fs.read_file(&self.path)?;
262 self.len = self.data.len();
263 self.pos = self.len;
264 self.stream_target = StreamingTarget::Replace;
265 self.merge = None;
266 self.dirty = false;
267 return Ok(());
268 }
269 if let Some(stream) = self.stream.clone() {
270 let len = stream.len;
271 self.fs.finish_streaming_file(self.path.clone(), stream)?;
272 self.data.clear();
277 self.len = len;
278 self.pos = self.len;
279 self.stream_target = StreamingTarget::Replace;
280 self.stream = None;
281 self.dirty = false;
282 return Ok(());
283 }
284 self.fs.write_file(&self.path, &self.data)?;
285 self.len = self.data.len();
286 self.stream_target = StreamingTarget::Replace;
287 self.dirty = false;
288 Ok(())
289 }
290
291 pub fn sync(&mut self) -> Result<()> {
292 self.flush()?;
293 self.fs.sync()
294 }
295
296 pub fn close(mut self) -> Result<()> {
297 if !self.dirty {
298 return Ok(());
299 }
300 if let Some(merge) = self.merge.take() {
301 return self.flush_merge_patches(merge);
302 }
303 if let Some(stream) = self.stream.take() {
304 return self.fs.finish_streaming_file(self.path, stream);
305 }
306 self.fs.write_file(&self.path, &self.data)
307 }
308
309 fn start_streaming_from_buffer(&mut self) -> Result<()> {
310 let buffered = core::mem::take(&mut self.data);
311 self.stream = Some(StreamingWrite {
312 allocator: self.fs.allocator.clone(),
313 blocks: Vec::new(),
314 current: None,
315 len: 0,
316 target: self.stream_target,
317 });
318 self.pos = 0;
319 self.write_streaming(&buffered)
320 }
321
322 fn write_merge_patch(&mut self, data: &[u8]) -> Result<usize> {
323 let end = self.pos.checked_add(data.len()).ok_or(Error::NoSpace)?;
324 if end > self.fs.info().file_max as usize {
325 return Err(Error::FileTooLarge);
326 }
327 let original_len = self.merge.as_ref().ok_or(Error::Corrupt)?.original_len;
328 if end > original_len {
329 self.promote_merge_to_buffer()?;
333 return self.write(data);
334 }
335
336 let merge = self.merge.as_mut().ok_or(Error::Corrupt)?;
337 merge.patches.push(FilePatch {
338 off: self.pos,
339 data: data.to_vec(),
340 });
341 self.pos = end;
342 self.len = original_len;
343 self.dirty = true;
344 Ok(data.len())
345 }
346
347 fn promote_merge_to_buffer(&mut self) -> Result<()> {
348 let Some(merge) = self.merge.take() else {
349 return Ok(());
350 };
351 let mut data = self.fs.read_file(&self.path)?;
352 for patch in merge.patches {
353 let end = patch
354 .off
355 .checked_add(patch.data.len())
356 .ok_or(Error::NoSpace)?;
357 if end > data.len() {
358 data.resize(end, 0);
359 }
360 data[patch.off..end].copy_from_slice(&patch.data);
361 }
362 self.len = data.len();
363 self.data = data;
364 Ok(())
365 }
366
367 fn flush_merge_patches(&mut self, merge: MergeWrite) -> Result<()> {
368 let mut stream = StreamingWrite {
369 allocator: self.fs.allocator.clone(),
370 blocks: Vec::new(),
371 current: None,
372 len: 0,
373 target: StreamingTarget::Replace,
374 };
375
376 let mut off = 0usize;
377 let mut buf = alloc::vec![0; self.fs.info().block_size as usize];
378 while off < merge.original_len {
379 let n = core::cmp::min(buf.len(), merge.original_len - off);
380 let read = self.fs.read_file_at(&self.path, off, &mut buf[..n])?;
381 if read != n {
382 return Err(Error::Corrupt);
383 }
384 for patch in &merge.patches {
385 let patch_end = patch
386 .off
387 .checked_add(patch.data.len())
388 .ok_or(Error::NoSpace)?;
389 let start = core::cmp::max(off, patch.off);
390 let end = core::cmp::min(off + n, patch_end);
391 if start < end {
392 let dst = start - off;
393 let src = start - patch.off;
394 let len = end - start;
395 buf[dst..dst + len].copy_from_slice(&patch.data[src..src + len]);
396 }
397 }
398 self.write_streaming_into(&mut stream, &buf[..n])?;
399 off += n;
400 }
401
402 if let Some(current) = stream.current.take() {
403 self.fs.flush_streaming_block(&mut stream, current)?;
404 }
405 self.fs.finish_streaming_file(self.path.clone(), stream)
406 }
407
408 fn write_streaming_into(&mut self, stream: &mut StreamingWrite, mut data: &[u8]) -> Result<()> {
409 while !data.is_empty() {
410 if stream.current.is_none() {
411 let index = stream.blocks.len();
412 let block = stream.allocator.alloc_block()?;
413 let mut bytes = alloc::vec![0xff; self.fs.info().block_size as usize];
414 let data_start = ctz_data_start(index)?;
415 if index > 0 {
416 let skips = index.trailing_zeros() as usize + 1;
417 for skip in 0..skips {
418 let target_index =
419 index.checked_sub(1usize << skip).ok_or(Error::Corrupt)?;
420 let target = stream
421 .blocks
422 .get(target_index)
423 .copied()
424 .ok_or(Error::Corrupt)?;
425 program_nor_bytes(&mut bytes, skip * 4, &target.to_le_bytes())?;
426 }
427 }
428 stream.current = Some(StreamingBlock {
429 block,
430 bytes,
431 off: data_start,
432 mode: StreamingBlockMode::New,
433 });
434 }
435
436 let current = stream.current.as_mut().ok_or(Error::Corrupt)?;
437 let capacity = current.bytes.len().saturating_sub(current.off);
438 let n = core::cmp::min(capacity, data.len());
439 current.bytes[current.off..current.off + n].copy_from_slice(&data[..n]);
440 current.off += n;
441 stream.len = stream.len.checked_add(n).ok_or(Error::NoSpace)?;
442 data = &data[n..];
443
444 if current.off == current.bytes.len() {
445 let current = stream.current.take().ok_or(Error::Corrupt)?;
446 self.fs.flush_streaming_block(stream, current)?;
447 }
448 }
449 Ok(())
450 }
451
452 fn write_streaming(&mut self, mut data: &[u8]) -> Result<()> {
453 let stream = self.stream.as_mut().ok_or(Error::Corrupt)?;
454 if self.pos != stream.len {
455 return Err(Error::Unsupported);
456 }
457 if stream.len.checked_add(data.len()).ok_or(Error::NoSpace)?
458 > self.fs.info().file_max as usize
459 {
460 return Err(Error::FileTooLarge);
461 }
462
463 while !data.is_empty() {
464 if stream.current.is_none() {
465 let index = stream.blocks.len();
466 let block = stream.allocator.alloc_block()?;
467 let mut bytes = alloc::vec![0xff; self.fs.info().block_size as usize];
468 let data_start = ctz_data_start(index)?;
469 if index > 0 {
470 let skips = index.trailing_zeros() as usize + 1;
471 for skip in 0..skips {
472 let target_index =
473 index.checked_sub(1usize << skip).ok_or(Error::Corrupt)?;
474 let target = stream
475 .blocks
476 .get(target_index)
477 .copied()
478 .ok_or(Error::Corrupt)?;
479 program_nor_bytes(&mut bytes, skip * 4, &target.to_le_bytes())?;
480 }
481 }
482 stream.current = Some(StreamingBlock {
483 block,
484 bytes,
485 off: data_start,
486 mode: StreamingBlockMode::New,
487 });
488 }
489
490 let current = stream.current.as_mut().ok_or(Error::Corrupt)?;
491 let capacity = current.bytes.len().saturating_sub(current.off);
492 let n = core::cmp::min(capacity, data.len());
493 current.bytes[current.off..current.off + n].copy_from_slice(&data[..n]);
494 current.off += n;
495 stream.len = stream.len.checked_add(n).ok_or(Error::NoSpace)?;
496 self.pos = stream.len;
497 self.len = stream.len;
498 self.dirty = true;
499 data = &data[n..];
500
501 if current.off == current.bytes.len() {
502 let current = stream.current.take().ok_or(Error::Corrupt)?;
503 self.fs.flush_streaming_block(stream, current)?;
504 }
505 }
506
507 Ok(())
508 }
509}
510
511impl<'fs, 'a> DirHandle<'fs, 'a> {
512 pub fn read(&mut self) -> Result<Option<DirEntry>> {
513 let entry = self.fs.dir_entry_at(self.head, self.pos)?;
514 if entry.is_some() {
515 self.pos += 1;
516 }
517 Ok(entry)
518 }
519
520 pub fn seek(&mut self, pos: usize) -> Result<()> {
521 self.pos = pos;
522 Ok(())
523 }
524
525 pub fn rewind(&mut self) -> Result<()> {
526 self.pos = 0;
527 Ok(())
528 }
529
530 pub fn close(self) -> Result<()> {
531 Ok(())
532 }
533}