1#![allow(dead_code)]
15#![allow(static_mut_refs)]
16use crate::println;
17
18pub mod storage_policy;
19pub mod block;
20pub mod btree;
21pub mod checksum;
22
23extern crate alloc;
24use alloc::boxed::Box;
25use alloc::vec::Vec;
26
27use block::{MirroredBlockDevice, RAMDisk, DATA_SIZE_PER_SECTOR};
28use btree::CowBTree;
29use core::ptr::null_mut;
30
31pub fn fnv1a_128(data: &[u8]) -> [u8; 16] {
32 let mut hash: u128 = 0x6c62272e07bb014262b821756295c58d;
33 for &b in data {
34 hash ^= b as u128;
35 hash = hash.wrapping_mul(0x0000000001000000000000000000013B);
36 }
37 hash.to_le_bytes()
38}
39
40#[repr(C, packed)]
48#[derive(Clone, Copy, Default)]
49pub struct Extent {
50 pub start: u64,
52 pub count: u64,
54}
55
56const MAX_INLINE_EXTENTS: usize = 18;
59
60const EXTENTS_PER_OVERFLOW_SECTOR: usize = (DATA_SIZE_PER_SECTOR - 8) / 16;
63
64const SUPERBLOCK_SECTOR: usize = 0;
65const BITMAP_START_SECTOR: u32 = 1;
66const BITS_PER_BITMAP_SECTOR: u64 = (DATA_SIZE_PER_SECTOR as u64) * 8;
68
69fn bitmap_sectors_for(total_sectors: u64) -> u64 {
78 total_sectors.div_ceil(BITS_PER_BITMAP_SECTOR).max(1)
79}
80
81pub const SYLFS_MAGIC: &[u8; 8] = b"SYLFS\0\0\0";
82
83#[repr(C, packed)]
85#[derive(Clone, Copy)]
86pub struct Superblock {
87 pub magic: [u8; 8],
88 pub version: u32,
89 pub root_sector: u32, pub bitmap_start: u32,
91 pub bitmap_sectors: u32,
92}
93
94#[repr(C, packed)]
96#[derive(Clone, Copy)]
97pub struct FileMetadata {
98 pub filename: [u8; 128],
102 pub label_data: [u8; 64], pub size: u64,
105 pub extent_count: u32,
107 pub overflow_sector: u64,
110 pub extents: [Extent; MAX_INLINE_EXTENTS],
112}
113
114const _: () = assert!(
120 core::mem::size_of::<FileMetadata>() <= DATA_SIZE_PER_SECTOR,
121 "FileMetadata must fit within a single sector"
122);
123
124impl FileMetadata {
125 pub fn new(name: &str, labels: &str, size: u64) -> Self {
126 let mut fm = Self {
127 filename: [0; 128],
128 label_data: [0; 64],
129 size,
130 extent_count: 0,
131 overflow_sector: 0,
132 extents: [Extent::default(); MAX_INLINE_EXTENTS],
133 };
134
135 let mut name_valid_len = 0;
137 for (i, c) in name.char_indices() {
138 if i + c.len_utf8() > 127 {
139 break;
140 }
141 name_valid_len = i + c.len_utf8();
142 }
143 let name_bytes = name.as_bytes();
144 fm.filename[..name_valid_len].copy_from_slice(&name_bytes[..name_valid_len]);
145
146 let mut label_valid_len = 0;
147 for (i, c) in labels.char_indices() {
148 if i + c.len_utf8() > 63 {
149 break;
150 }
151 label_valid_len = i + c.len_utf8();
152 }
153 let label_bytes = labels.as_bytes();
154 fm.label_data[..label_valid_len].copy_from_slice(&label_bytes[..label_valid_len]);
155
156 fm
157 }
158
159 pub fn get_filename(&self) -> &str {
160 let len = self.filename.iter().position(|&x| x == 0).unwrap_or(128);
161 unsafe { core::str::from_utf8_unchecked(&self.filename[..len]) }
162 }
163
164 pub fn get_labels(&self) -> &str {
165 let len = self.label_data.iter().position(|&x| x == 0).unwrap_or(64);
166 unsafe { core::str::from_utf8_unchecked(&self.label_data[..len]) }
167 }
168}
169
170pub struct SylFS {
171 pub device: MirroredBlockDevice<block::BackendDevice>,
172 pub superblock: Superblock,
173 next_bitmap_hint: u32,
184}
185
186impl SylFS {
187 pub fn from_parts(
193 device: MirroredBlockDevice<block::BackendDevice>,
194 superblock: Superblock,
195 ) -> Self {
196 Self {
197 device,
198 superblock,
199 next_bitmap_hint: 0,
200 }
201 }
202}
203
204static mut FS_INSTANCE: *mut SylFS = null_mut();
205
206include!(concat!(env!("OUT_DIR"), "/app_assets.rs"));
208
209pub fn format_device(
218 device: &mut MirroredBlockDevice<block::BackendDevice>,
219) -> Result<Superblock, &'static str> {
220 let total = device.total_usable_sectors() as u64;
221 let bitmap_sectors = bitmap_sectors_for(total);
222
223 let superblock = Superblock {
224 magic: *SYLFS_MAGIC,
225 version: 1,
226 root_sector: 0, bitmap_start: BITMAP_START_SECTOR,
228 bitmap_sectors: bitmap_sectors as u32,
229 };
230
231 crate::info!(
232 "[FS] Formatting: total_sectors={} bitmap_sectors={} (capacity {} MiB)",
233 total,
234 bitmap_sectors,
235 total * DATA_SIZE_PER_SECTOR as u64 / (1024 * 1024)
236 );
237
238 let reserved = 1 + bitmap_sectors; let mut first = [0u8; DATA_SIZE_PER_SECTOR];
242 for s in 0..reserved.min(BITS_PER_BITMAP_SECTOR) {
243 let byte = (s / 8) as usize;
244 let bit = (s % 8) as u8;
245 first[byte] |= 1 << bit;
246 }
247
248 for i in 0..bitmap_sectors {
249 let sec = BITMAP_START_SECTOR as u64 + i;
250 let data_to_write = if i == 0 {
251 &first[..]
252 } else {
253 &[0u8; DATA_SIZE_PER_SECTOR][..]
254 };
255 if let Err(e) = device.write_sector(sec as usize, data_to_write) {
256 crate::error!("[FS] Format failed: bitmap sector {} not written: {}", sec, e);
257 return Err(e);
258 }
259 }
260
261 let mut sb_buf = [0u8; DATA_SIZE_PER_SECTOR];
263 unsafe {
264 core::ptr::copy_nonoverlapping(
265 &superblock as *const Superblock as *const u8,
266 sb_buf.as_mut_ptr(),
267 core::mem::size_of::<Superblock>(),
268 );
269 }
270 if let Err(e) = device.write_sector(SUPERBLOCK_SECTOR, &sb_buf) {
271 crate::error!("[FS] Format failed: superblock not written: {}", e);
272 return Err(e);
273 }
274
275 crate::info!("[FS] Format completed successfully!");
276 Ok(superblock)
277}
278
279pub fn mount() -> Result<(), &'static str> {
286 crate::info!("[FS] Mounting SylFS (COW Label-based File System)...");
287
288 let backend = match block::SDCard::new() {
290 Ok(sd_card) => {
291 crate::info!("[FS] microSD card backend successfully initialized.");
292 block::BackendDevice::SD(sd_card)
293 }
294 Err(e) => {
295 crate::warn!("[FS] Failed to initialize microSD card: {}. Falling back to RAMDisk...", e);
296 extern "C" {
329 static __cpu_stacks_end: u8;
330 }
331 let heap_start = core::ptr::addr_of!(__cpu_stacks_end) as usize;
332 let heap_size = crate::kernel::allocator::KERNEL_HEAP_SIZE;
334 let ramdisk_start = heap_start + heap_size;
335 let gpu_boundary = crate::kernel::mmu::DEVICE_REGION_START;
338 let ramdisk_size = if gpu_boundary > ramdisk_start {
339 gpu_boundary - ramdisk_start
340 } else {
341 64 * 1024 * 1024
342 };
343
344 let ram_disk = unsafe { block::RAMDisk::from_raw_memory(ramdisk_start, ramdisk_size) };
345 crate::warn!(
350 "[FS] Dedicated RAMDisk allocated from 0x{:08X} to 0x{:08X} ({} MB)",
351 ramdisk_start,
352 ramdisk_start + ramdisk_size,
353 ramdisk_size / (1024 * 1024)
354 );
355 block::BackendDevice::RAM(ram_disk)
356 }
357 };
358
359 let mut device = MirroredBlockDevice::new(backend);
360
361 let mut superblock = Superblock {
362 magic: [0; 8],
363 version: 0,
364 root_sector: 0,
365 bitmap_start: BITMAP_START_SECTOR,
366 bitmap_sectors: 4, };
368
369 let mut is_formatted = false;
370 let mut buf = [0u8; DATA_SIZE_PER_SECTOR];
371
372 crate::kernel::uart::set_silent(true);
374 let read_res = device.read_sector(SUPERBLOCK_SECTOR, &mut buf);
375 crate::kernel::uart::set_silent(false);
376
377 if read_res.is_ok() {
378 unsafe {
379 core::ptr::copy_nonoverlapping(
380 buf.as_ptr(),
381 &mut superblock as *mut Superblock as *mut u8,
382 core::mem::size_of::<Superblock>(),
383 );
384 }
385 if &superblock.magic == SYLFS_MAGIC {
386 is_formatted = true;
387 let root_sec = superblock.root_sector;
388 crate::info!(
389 "[FS] SylFS successfully mounted! Root B-Tree root at Sector {}",
390 root_sec
391 );
392 }
393 }
394
395 let mut status: Result<(), &'static str> = Ok(());
397
398 if !is_formatted {
399 crate::info!("[FS] SylFS not detected. Formatting disk...");
400 match format_device(&mut device) {
401 Ok(sb) => superblock = sb,
402 Err(e) => {
403 crate::error!("[FS] Format failed: {}", e);
406 status = Err(e);
407 }
408 }
409 }
410
411 let fs = Box::new(SylFS::from_parts(device, superblock));
412 unsafe {
413 FS_INSTANCE = Box::into_raw(fs);
414 }
415
416 let fs_ref = get_fs();
418
419 let mut asset_failures = 0usize;
420 for asset in APP_ASSETS.iter() {
421 if let Err(e) = fs_ref.save_file(asset.path, asset.data, "sys") {
422 crate::error!("[FS] Failed to install default app '{}': {}", asset.path, e);
425 asset_failures += 1;
426 }
427 }
428
429 if asset_failures > 0 {
430 crate::error!(
431 "[FS] {} of {} pre-installed apps could not be written.",
432 asset_failures,
433 APP_ASSETS.len()
434 );
435 if status.is_ok() {
436 status = Err("failed to install pre-installed apps");
437 }
438 } else {
439 crate::info!("[FS] Pre-installed default apps updated.");
440 }
441
442 status
443}
444
445pub fn read_file(path: &str) -> Option<alloc::vec::Vec<u8>> {
447 let fs = get_fs();
448 let (_meta, data) = fs.read_file(path)?;
449 Some(data)
450}
451
452pub fn is_mounted() -> bool {
454 unsafe { !FS_INSTANCE.is_null() }
455}
456
457pub static FS_LOCK: crate::kernel::reclock::RecoverableMutex<()> =
525 crate::kernel::reclock::RecoverableMutex::new(());
526
527pub fn force_release_locks(cid: i16) {
530 unsafe {
531 FS_LOCK.force_release_if_core(cid);
532 }
533}
534
535pub fn get_fs() -> &'static mut SylFS {
536 unsafe {
537 assert!(!FS_INSTANCE.is_null(), "SylFS not mounted!");
538 &mut *FS_INSTANCE
539 }
540}
541
542impl SylFS {
543 pub fn allocate_sector(&mut self) -> u32 {
545 let mut buf = [0u8; DATA_SIZE_PER_SECTOR];
546
547 let total = self.superblock.bitmap_sectors;
554 for step in 0..total {
555 let i = (self.next_bitmap_hint + step) % total.max(1);
556 let sec = self.superblock.bitmap_start + i;
557 if self.device.read_sector(sec as usize, &mut buf).is_err() {
558 println!("[SylFS] Failed to read bitmap sector {}", sec);
559 continue;
560 }
561
562 for byte_idx in 0..DATA_SIZE_PER_SECTOR {
563 let byte = buf[byte_idx];
564 if byte != 0xFF {
565 for bit in 0..8 {
567 if (byte & (1 << bit)) == 0 {
568 buf[byte_idx] |= 1 << bit;
570
571 if let Err(e) = self.device.write_sector(sec as usize, &buf) {
577 crate::error!(
578 "[SylFS] allocate_sector: bitmap write failed on sector {}: {}",
579 sec,
580 e
581 );
582 return 0;
583 }
584
585 self.next_bitmap_hint = i;
587 let allocated_sector = (i * DATA_SIZE_PER_SECTOR as u32 * 8)
588 + (byte_idx as u32 * 8)
589 + bit as u32;
590 if allocated_sector as usize >= self.device.total_usable_sectors() {
606 buf[byte_idx] &= !(1 << bit);
608 if let Err(e) = self.device.write_sector(sec as usize, &buf) {
613 crate::error!(
614 "[SylFS] allocate_sector: 余剰ビットの戻し書きに失敗 sector={} err={}(ビットが漏れる)",
615 sec,
616 e
617 );
618 }
619 crate::warn!(
620 "[SylFS] allocate_sector: ビットマップの余剰ビットに到達 (sector={} usable={})。満杯として扱う",
621 allocated_sector,
622 self.device.total_usable_sectors()
623 );
624 return 0;
625 }
626 return allocated_sector;
627 }
628 }
629 }
630 }
631 }
632 println!("[SylFS] allocate_sector failed (Disk Full)");
633 0 }
635
636 pub fn deallocate_sector(&mut self, sector: u32) {
638 let i = sector / (DATA_SIZE_PER_SECTOR as u32 * 8);
639 let rem = sector % (DATA_SIZE_PER_SECTOR as u32 * 8);
640 let byte_idx = (rem / 8) as usize;
641 let bit = rem % 8;
642
643 let sec = self.superblock.bitmap_start + i;
644 let mut buf = [0u8; DATA_SIZE_PER_SECTOR];
645 if self.device.read_sector(sec as usize, &mut buf).is_ok() {
646 buf[byte_idx] &= !(1 << bit); if let Err(e) = self.device.write_sector(sec as usize, &buf) {
651 crate::error!(
652 "[SylFS] deallocate_sector({}): bitmap write failed: {} (sector leaked)",
653 sector,
654 e
655 );
656 }
657 } else {
658 crate::error!(
659 "[SylFS] deallocate_sector({}): bitmap read failed (sector leaked)",
660 sector
661 );
662 }
663 }
664
665 pub fn save_file(
667 &mut self,
668 filename: &str,
669 content: &[u8],
670 labels: &str,
671 ) -> Result<(), &'static str> {
672 crate::debug!("[FS] Saving file '{}' with labels [{}]...", filename, labels);
673
674 let needed_sectors = content.len().div_ceil(DATA_SIZE_PER_SECTOR);
679
680 let mut extents: Vec<Extent> = Vec::new();
681 for i in 0..needed_sectors {
682 let sec = self.allocate_sector() as u64;
683 if sec == 0 {
684 return Err("save_file: no free data sector");
685 }
686
687 match extents.last_mut() {
688 Some(last) if last.start + last.count == sec => last.count += 1,
690 _ => extents.push(Extent {
691 start: sec,
692 count: 1,
693 }),
694 }
695
696 let offset = i * DATA_SIZE_PER_SECTOR;
697 let end = (offset + DATA_SIZE_PER_SECTOR).min(content.len());
698 if let Err(e) = self
702 .device
703 .write_sector(sec as usize, &content[offset..end])
704 {
705 crate::error!(
706 "[SylFS] save_file('{}'): data sector {} write failed: {}",
707 filename,
708 sec,
709 e
710 );
711 return Err("save_file: data sector write failed");
712 }
713 }
714
715 let inline_count = extents.len().min(MAX_INLINE_EXTENTS);
717 let mut inline_extents = [Extent::default(); MAX_INLINE_EXTENTS];
718 inline_extents[..inline_count].copy_from_slice(&extents[..inline_count]);
719 let overflow_sector = self.write_overflow_extents(&extents[inline_count..])?;
720
721 let meta_sector = self.allocate_sector();
723 if meta_sector == 0 {
724 return Err("save_file: no free metadata sector");
725 }
726 let mut meta = FileMetadata::new(filename, labels, content.len() as u64);
727 meta.extents = inline_extents;
728 meta.extent_count = extents.len() as u32;
729 meta.overflow_sector = overflow_sector;
730
731 let mut meta_buf = [0u8; DATA_SIZE_PER_SECTOR];
732 unsafe {
733 core::ptr::copy_nonoverlapping(
734 &meta as *const FileMetadata as *const u8,
735 meta_buf.as_mut_ptr(),
736 core::mem::size_of::<FileMetadata>(),
737 );
738 }
739 self.device.write_sector(meta_sector as usize, &meta_buf)?;
740
741 let mut btree = CowBTree::new(self.superblock.root_sector);
743
744 let self_ptr = self as *mut Self;
746 let mut alloc_fn = || unsafe { (*self_ptr).allocate_sector() };
747
748 let hash_key = fnv1a_128(filename.as_bytes());
750 let new_root = btree.insert(&mut self.device, &hash_key, meta_sector, &mut alloc_fn)?;
751 self.superblock.root_sector = new_root;
752
753 let mut sb_buf = [0u8; DATA_SIZE_PER_SECTOR];
755 unsafe {
756 core::ptr::copy_nonoverlapping(
757 &self.superblock as *const Superblock as *const u8,
758 sb_buf.as_mut_ptr(),
759 core::mem::size_of::<Superblock>(),
760 );
761 }
762 self.device.write_sector(SUPERBLOCK_SECTOR, &sb_buf)?;
763
764 crate::debug!(
765 " File '{}' successfully saved! Metadata stored at Sector {}",
766 filename,
767 meta_sector
768 );
769 Ok(())
770 }
771
772 pub fn read_file(&mut self, filename: &str) -> Option<(FileMetadata, Vec<u8>)> {
783 match self.read_file_checked(filename) {
784 Ok(v) => v,
785 Err(e) => {
786 crate::error!("[SylFS] read_file('{}') failed: {}", filename, e);
787 None
788 }
789 }
790 }
791
792 pub fn read_file_checked(
800 &mut self,
801 filename: &str,
802 ) -> Result<Option<(FileMetadata, Vec<u8>)>, &'static str> {
803 let btree = CowBTree::new(self.superblock.root_sector);
804
805 let hash_key = fnv1a_128(filename.as_bytes());
807 let meta_sector = match btree.search(&mut self.device, &hash_key) {
808 Some(sec) => sec,
809 None => {
810 for asset in APP_ASSETS.iter() {
813 if asset.path == filename {
814 let dummy_meta = FileMetadata::new(filename, "rom", asset.data.len() as u64);
815 return Ok(Some((dummy_meta, asset.data.to_vec())));
816 }
817 }
818 return Ok(None);
820 }
821 };
822
823 let mut buf = [0u8; DATA_SIZE_PER_SECTOR];
825 if let Err(e) = self.device.read_sector(meta_sector as usize, &mut buf) {
826 crate::error!(
827 "[SylFS] read '{}': metadata sector {} unreadable: {}",
828 filename,
829 meta_sector,
830 e
831 );
832 return Err("metadata sector unreadable");
833 }
834 let meta = unsafe { *(buf.as_ptr() as *const FileMetadata) };
835 if meta.get_filename() != filename {
836 crate::error!(
838 "[SylFS] read '{}': hash collision with '{}'",
839 filename,
840 meta.get_filename()
841 );
842 return Err("filename hash collision");
843 }
844
845 let mut content = Vec::new();
847 let mut total_read = 0;
848 let mut i = 0;
849
850 let extents = self
852 .collect_extents(&meta)
853 .ok_or("extent list unreadable")?;
854 let all_secs = Self::extents_to_sectors(&extents);
855
856 while total_read < meta.size && i < all_secs.len() {
857 let sec = all_secs[i];
858 let mut data_buf = [0u8; DATA_SIZE_PER_SECTOR];
859 if let Err(e) = self.device.read_sector(sec as usize, &mut data_buf) {
860 crate::error!(
861 "[SylFS] read '{}': data sector {} unreadable: {}",
862 filename,
863 sec,
864 e
865 );
866 return Err("data sector unreadable");
867 }
868
869 let remain = (meta.size - total_read) as usize;
870 let chunk_size = remain.min(DATA_SIZE_PER_SECTOR);
871 content.extend_from_slice(&data_buf[..chunk_size]);
872
873 total_read += chunk_size as u64;
874 i += 1;
875 }
876
877 let expected_size = meta.size;
881 if total_read < expected_size {
882 crate::error!(
883 "[SylFS] read '{}': truncated ({} of {} bytes)",
884 filename,
885 total_read,
886 expected_size
887 );
888 return Err("file data is truncated");
889 }
890
891 Ok(Some((meta, content)))
892 }
893
894 fn write_overflow_extents(&mut self, rest: &[Extent]) -> Result<u64, &'static str> {
898 if rest.is_empty() {
899 return Ok(0);
900 }
901 let mut next: u64 = 0;
903 let mut head: u64 = 0;
904 for chunk in rest.chunks(EXTENTS_PER_OVERFLOW_SECTOR).rev() {
905 let sec = self.allocate_sector() as u64;
906 if sec == 0 {
907 return Err("save_file: no free overflow sector");
908 }
909 let mut buf = [0u8; DATA_SIZE_PER_SECTOR];
910 buf[..8].copy_from_slice(&next.to_le_bytes());
911 for (i, e) in chunk.iter().enumerate() {
912 let off = 8 + i * 16;
913 buf[off..off + 8].copy_from_slice(&e.start.to_le_bytes());
914 buf[off + 8..off + 16].copy_from_slice(&e.count.to_le_bytes());
915 }
916 if let Err(e) = self.device.write_sector(sec as usize, &buf) {
920 crate::error!(
921 "[SylFS] write_overflow_extents: sector {} write failed: {}",
922 sec,
923 e
924 );
925 return Err("save_file: overflow extent write failed");
926 }
927 next = sec;
928 head = sec;
929 }
930 Ok(head)
931 }
932
933 fn collect_extents(&mut self, meta: &FileMetadata) -> Option<Vec<Extent>> {
935 let total = meta.extent_count as usize;
936 let mut out: Vec<Extent> = Vec::with_capacity(total);
937
938 let inline_n = total.min(MAX_INLINE_EXTENTS);
939 for e in meta.extents.iter().take(inline_n) {
940 out.push(*e);
941 }
942
943 let mut next = meta.overflow_sector;
944 while next != 0 && out.len() < total {
945 let mut buf = [0u8; DATA_SIZE_PER_SECTOR];
946 if self.device.read_sector(next as usize, &mut buf).is_err() {
947 return None;
948 }
949 let following = u64::from_le_bytes([
950 buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],
951 ]);
952 for i in 0..EXTENTS_PER_OVERFLOW_SECTOR {
953 if out.len() >= total {
954 break;
955 }
956 let off = 8 + i * 16;
957 let start = u64::from_le_bytes([
958 buf[off], buf[off + 1], buf[off + 2], buf[off + 3],
959 buf[off + 4], buf[off + 5], buf[off + 6], buf[off + 7],
960 ]);
961 let count = u64::from_le_bytes([
962 buf[off + 8], buf[off + 9], buf[off + 10], buf[off + 11],
963 buf[off + 12], buf[off + 13], buf[off + 14], buf[off + 15],
964 ]);
965 if count == 0 {
966 continue;
967 }
968 out.push(Extent { start, count });
969 }
970 next = following;
971 }
972 Some(out)
973 }
974
975 fn extents_to_sectors(extents: &[Extent]) -> Vec<u64> {
977 let mut secs = Vec::new();
978 for e in extents {
979 for k in 0..e.count {
980 secs.push(e.start + k);
981 }
982 }
983 secs
984 }
985
986 pub fn find_by_label(&mut self, label: &str) -> Vec<FileMetadata> {
988 let mut results = Vec::new();
989 let all_files = self.list_files();
990 for meta in all_files {
991 if meta.get_labels().split(',').any(|l| l.trim() == label) {
992 results.push(meta);
993 }
994 }
995 results
996 }
997
998 pub fn list_files(&mut self) -> Vec<FileMetadata> {
1000 let btree = CowBTree::new(self.superblock.root_sector);
1001 let mut entries = Vec::new();
1002 let mut results = Vec::new();
1003 let mut seen_meta_sectors = Vec::new();
1004
1005 btree.collect_leaf_entries(&mut self.device, &mut entries);
1006
1007 for (_, meta_sector) in entries {
1008 if seen_meta_sectors.contains(&meta_sector) {
1009 continue;
1010 }
1011 seen_meta_sectors.push(meta_sector);
1012
1013 let mut buf = [0u8; DATA_SIZE_PER_SECTOR];
1014 if self
1015 .device
1016 .read_sector(meta_sector as usize, &mut buf)
1017 .is_ok()
1018 {
1019 let meta = unsafe { *(buf.as_ptr() as *const FileMetadata) };
1020 if meta.filename[0] != 0 {
1022 results.push(meta);
1023 }
1024 }
1025 }
1026
1027 results
1028 }
1029
1030 pub fn delete_file(&mut self, filename: &str) -> Result<(), &'static str> {
1032 let btree = CowBTree::new(self.superblock.root_sector);
1033 let hash_key = fnv1a_128(filename.as_bytes());
1034
1035 if let Some(meta_sector) = btree.search(&mut self.device, &hash_key) {
1036 let mut buf = [0u8; DATA_SIZE_PER_SECTOR];
1037 if self
1038 .device
1039 .read_sector(meta_sector as usize, &mut buf)
1040 .is_ok()
1041 {
1042 let mut meta = unsafe { *(buf.as_ptr() as *const FileMetadata) };
1043
1044 meta.filename[0] = 0;
1046
1047 let mut meta_buf = [0u8; DATA_SIZE_PER_SECTOR];
1048 unsafe {
1049 core::ptr::copy_nonoverlapping(
1050 &meta as *const FileMetadata as *const u8,
1051 meta_buf.as_mut_ptr(),
1052 core::mem::size_of::<FileMetadata>(),
1053 );
1054 }
1055 self.device.write_sector(meta_sector as usize, &meta_buf)?;
1056
1057 if let Some(extents) = self.collect_extents(&meta) {
1059 for sec in Self::extents_to_sectors(&extents) {
1060 self.deallocate_sector(sec as u32);
1061 }
1062 }
1063
1064 let mut next = meta.overflow_sector;
1067 while next != 0 {
1068 let mut buf = [0u8; DATA_SIZE_PER_SECTOR];
1069 let following = if self.device.read_sector(next as usize, &mut buf).is_ok() {
1070 u64::from_le_bytes([
1071 buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],
1072 ])
1073 } else {
1074 0
1075 };
1076 self.deallocate_sector(next as u32);
1077 next = following;
1078 }
1079
1080 println!(
1084 " SylFS: File '{}' deallocated and deleted successfully.",
1085 filename
1086 );
1087 return Ok(());
1088 }
1089 }
1090 Err("delete_file: file not found")
1091 }
1092
1093 pub fn list_dir(&mut self, prefix: &str) -> Vec<FileMetadata> {
1095 let mut results = Vec::new();
1096 let all_files = self.list_files();
1097 for meta in all_files {
1098 if meta.get_filename().starts_with(prefix) {
1099 results.push(meta);
1100 }
1101 }
1102 results
1103 }
1104}
1105
1106pub fn selftest() -> (u32, u32) {
1111 let mut pass = 0u32;
1112 let mut total = 0u32;
1113
1114 {
1116 let mut dev = MirroredBlockDevice::new(RAMDisk::new(1024 * 1024));
1117 let mut next_sec: u32 = 10; let mut btree = CowBTree::new(0);
1119 const N: u32 = 40; let make_key = |i: u32| -> [u8; 16] {
1122 let mut k = [0u8; 16];
1123 k[..4].copy_from_slice(&i.to_be_bytes());
1124 k
1125 };
1126
1127 let mut ok = true;
1129 for i in 0..N {
1130 let key = make_key(i);
1131 let mut alloc = || {
1132 let s = next_sec;
1133 next_sec += 1;
1134 s
1135 };
1136 if btree.insert(&mut dev, &key, 2000 + i, &mut alloc).is_err() {
1137 ok = false;
1138 break;
1139 }
1140 }
1141 total += 1;
1142 if ok {
1143 pass += 1;
1144 }
1145
1146 let mut ok2 = true;
1148 for i in 0..N {
1149 let key = make_key(i);
1150 let mut alloc = || {
1151 let s = next_sec;
1152 next_sec += 1;
1153 s
1154 };
1155 if btree.insert(&mut dev, &key, 3000 + i, &mut alloc).is_err() {
1156 ok2 = false;
1157 break;
1158 }
1159 }
1160 total += 1;
1161 if ok2 {
1162 pass += 1;
1163 }
1164
1165 let mut all_ok = true;
1167 for i in 0..N {
1168 let key = make_key(i);
1169 if btree.search(&mut dev, &key) != Some(3000 + i) {
1170 all_ok = false;
1171 }
1172 }
1173 total += 1;
1174 if all_ok {
1175 pass += 1;
1176 }
1177 }
1178
1179 {
1181 let mut dev = MirroredBlockDevice::new(RAMDisk::new(64 * 1024));
1182 let sector = 5usize;
1183 let payload = b"SylFS dual-redundancy selftest payload";
1184 total += 1;
1187 if dev.write_sector(sector, payload).is_ok() {
1188 pass += 1;
1189 }
1190
1191 let _ = dev.force_corrupt_raw_sector(sector);
1193 let mut buf = [0u8; DATA_SIZE_PER_SECTOR];
1194 let healed = dev.read_sector(sector, &mut buf).is_ok() && &buf[..payload.len()] == payload;
1195 total += 1;
1196 if healed {
1197 pass += 1;
1198 }
1199
1200 let mut buf2 = [0u8; DATA_SIZE_PER_SECTOR];
1202 let reread =
1203 dev.read_sector(sector, &mut buf2).is_ok() && &buf2[..payload.len()] == payload;
1204 total += 1;
1205 if reread {
1206 pass += 1;
1207 }
1208
1209 let mirror = sector + dev.total_usable_sectors();
1211 let _ = dev.force_corrupt_raw_sector(sector);
1212 let _ = dev.force_corrupt_raw_sector(mirror);
1213 let mut buf3 = [0u8; DATA_SIZE_PER_SECTOR];
1214 total += 1;
1215 if dev.read_sector(sector, &mut buf3).is_err() {
1216 pass += 1;
1217 }
1218 }
1219
1220 (pass, total)
1221}