kernel/fs/vfs_v2/drivers/fat32/mod.rs
1//! FAT32 Filesystem Implementation
2//!
3//! This module implements a FAT32 filesystem driver for the VFS v2 architecture.
4//! It provides support for reading and writing FAT32 filesystems on block devices,
5//! particularly designed to work with virtio-blk devices.
6//!
7//! ## Features
8//!
9//! - Full FAT32 filesystem support
10//! - Read and write operations
11//! - Directory navigation
12//! - File creation, deletion, and modification
13//! - Integration with VFS v2 architecture
14//! - Block device compatibility
15//!
16//! ## Architecture
17//!
18//! The FAT32 implementation consists of:
19//! - `Fat32FileSystem`: Main filesystem implementation
20//! - `Fat32Node`: VFS node implementation for files and directories
21//! - `Fat32Driver`: Filesystem driver for registration
22//! - Data structures for FAT32 format (boot sector, directory entries, etc.)
23
24use alloc::{
25 boxed::Box,
26 collections::BTreeMap,
27 format,
28 string::{String, ToString},
29 sync::Arc,
30 vec,
31 vec::Vec,
32};
33use core::{any::Any, fmt::Debug, mem};
34use spin::{Mutex, rwlock::RwLock};
35
36use crate::{
37 device::block::BlockDevice,
38 driver_initcall,
39 fs::{FileObject, FileSystemError, FileSystemErrorKind, FileType, get_fs_driver_manager},
40};
41
42use super::super::core::{DirectoryEntryInternal, FileSystemId, FileSystemOperations, VfsNode};
43
44pub mod driver;
45pub mod node;
46pub mod structures;
47
48#[cfg(test)]
49pub mod tests;
50
51pub use driver::Fat32Driver;
52pub use node::{Fat32DirectoryObject, Fat32FileObject, Fat32Node};
53pub use structures::*;
54
55/// FAT32 Filesystem implementation
56///
57/// This struct implements a FAT32 filesystem that can be mounted on block devices.
58/// It maintains the block device reference and provides filesystem operations
59/// through the VFS v2 interface.
60pub struct Fat32FileSystem {
61 /// Unique filesystem identifier
62 fs_id: FileSystemId,
63 /// Reference to the underlying block device
64 block_device: Arc<dyn BlockDevice>,
65 /// Boot sector information
66 boot_sector: Fat32BootSector,
67 /// Root directory cluster
68 root_cluster: u32,
69 /// Sectors per cluster
70 sectors_per_cluster: u32,
71 /// Bytes per sector
72 bytes_per_sector: u32,
73 /// Root directory node
74 root: RwLock<Arc<Fat32Node>>,
75 /// Filesystem name
76 name: String,
77 /// Next file ID generator
78 next_file_id: Mutex<u64>,
79 /// Cached FAT table entries
80 fat_cache: Mutex<BTreeMap<u32, u32>>,
81}
82
83impl Debug for Fat32FileSystem {
84 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
85 f.debug_struct("Fat32FileSystem")
86 .field("name", &self.name)
87 .field("root_cluster", &self.root_cluster)
88 .field("sectors_per_cluster", &self.sectors_per_cluster)
89 .field("bytes_per_sector", &self.bytes_per_sector)
90 .finish()
91 }
92}
93
94impl Fat32FileSystem {
95 /// Create a new FAT32 filesystem from a block device
96 pub fn new(block_device: Arc<dyn BlockDevice>) -> Result<Arc<Self>, FileSystemError> {
97 // Read boot sector
98 let boot_sector = Self::read_boot_sector(&*block_device)?;
99
100 // Validate FAT32 filesystem
101 Self::validate_fat32(&boot_sector)?;
102
103 // Calculate filesystem parameters
104 let sectors_per_cluster = boot_sector.sectors_per_cluster as u32;
105 let bytes_per_sector = boot_sector.bytes_per_sector as u32;
106 let root_cluster = boot_sector.root_cluster;
107
108 // Create root directory node
109 let root = Arc::new(Fat32Node::new_directory("/".to_string(), 1, root_cluster));
110
111 let fs = Arc::new(Self {
112 fs_id: FileSystemId::new(),
113 block_device,
114 boot_sector,
115 root_cluster,
116 sectors_per_cluster,
117 bytes_per_sector,
118 root: RwLock::new(Arc::clone(&root)),
119 name: "fat32".to_string(),
120 next_file_id: Mutex::new(2), // Start from 2, root is 1
121 fat_cache: Mutex::new(BTreeMap::new()),
122 });
123
124 // Set filesystem reference in root node
125 let fs_weak = Arc::downgrade(&(fs.clone() as Arc<dyn FileSystemOperations>));
126 root.set_filesystem(fs_weak);
127
128 Ok(fs)
129 }
130
131 /// Read boot sector from block device
132 fn read_boot_sector(
133 block_device: &dyn BlockDevice,
134 ) -> Result<Fat32BootSector, FileSystemError> {
135 // Create read request for sector 0 (boot sector)
136 let request = Box::new(crate::device::block::request::BlockIORequest {
137 request_type: crate::device::block::request::BlockIORequestType::Read,
138 sector: 0,
139 sector_count: 1,
140 head: 0,
141 cylinder: 0,
142 buffer: vec![0u8; 512], // Boot sector is always 512 bytes
143 });
144
145 block_device.enqueue_request(request);
146 let results = block_device.process_requests();
147
148 if let Some(result) = results.first() {
149 match &result.result {
150 Ok(_) => {
151 // Parse boot sector
152 if result.request.buffer.len() < mem::size_of::<Fat32BootSector>() {
153 return Err(FileSystemError::new(
154 FileSystemErrorKind::IoError,
155 "Boot sector read incomplete",
156 ));
157 }
158
159 // Convert bytes to boot sector structure
160 let boot_sector = unsafe {
161 core::ptr::read(result.request.buffer.as_ptr() as *const Fat32BootSector)
162 };
163
164 Ok(boot_sector)
165 }
166 Err(e) => Err(FileSystemError::new(
167 FileSystemErrorKind::IoError,
168 format!("Failed to read boot sector: {}", e),
169 )),
170 }
171 } else {
172 Err(FileSystemError::new(
173 FileSystemErrorKind::IoError,
174 "No result from block device",
175 ))
176 }
177 }
178
179 /// Validate that this is a FAT32 filesystem
180 fn validate_fat32(boot_sector: &Fat32BootSector) -> Result<(), FileSystemError> {
181 // Check signature
182 if boot_sector.signature != 0xAA55 {
183 return Err(FileSystemError::new(
184 FileSystemErrorKind::InvalidData,
185 "Invalid boot sector signature",
186 ));
187 }
188
189 // Check bytes per sector (must be 512, 1024, 2048, or 4096)
190 match boot_sector.bytes_per_sector {
191 512 | 1024 | 2048 | 4096 => {}
192 _ => {
193 return Err(FileSystemError::new(
194 FileSystemErrorKind::InvalidData,
195 "Invalid bytes per sector",
196 ));
197 }
198 }
199
200 // Check sectors per cluster (must be power of 2)
201 if boot_sector.sectors_per_cluster == 0
202 || (boot_sector.sectors_per_cluster & (boot_sector.sectors_per_cluster - 1)) != 0
203 {
204 return Err(FileSystemError::new(
205 FileSystemErrorKind::InvalidData,
206 "Invalid sectors per cluster",
207 ));
208 }
209
210 Ok(())
211 }
212
213 /// Lookup a specific file in a directory cluster
214 fn lookup_file_in_directory(
215 &self,
216 cluster: u32,
217 target_name: &str,
218 ) -> Result<Fat32DirectoryEntryInternal, FileSystemError> {
219 let mut current_cluster = cluster;
220
221 loop {
222 // Read the current cluster
223 let cluster_data = self.read_cluster_data(current_cluster)?;
224
225 // Parse directory entries in this cluster
226 let entries_per_cluster = (self.sectors_per_cluster * self.bytes_per_sector) / 32;
227 let mut lfn_parts: Vec<String> = Vec::new(); // Collect LFN parts in order
228
229 for i in 0..entries_per_cluster {
230 let offset = (i * 32) as usize;
231 if offset + 32 > cluster_data.len() {
232 break;
233 }
234
235 let entry_bytes = &cluster_data[offset..offset + 32];
236
237 // Safety: We know the slice is exactly 32 bytes (size of Fat32DirectoryEntry)
238 let dir_entry = unsafe {
239 core::ptr::read(entry_bytes.as_ptr() as *const structures::Fat32DirectoryEntry)
240 };
241
242 // Skip free entries
243 if dir_entry.is_free() {
244 lfn_parts.clear(); // Reset LFN accumulation
245 continue;
246 }
247
248 // Handle LFN entries
249 if dir_entry.is_long_filename() {
250 // Cast to LFN entry
251 let lfn_entry =
252 unsafe { &*(entry_bytes.as_ptr() as *const structures::Fat32LFNEntry) };
253
254 // Extract characters from this LFN entry
255 let chars = lfn_entry.extract_chars();
256
257 // Convert UTF-16 to UTF-8
258 let mut part = String::new();
259 for &ch in &chars {
260 if ch == 0 || ch == 0xFFFF {
261 break; // End of string or padding
262 }
263 if let Some(c) = char::from_u32(ch as u32) {
264 part.push(c);
265 }
266 }
267
268 // LFN entries are stored with highest sequence number first
269 if lfn_entry.is_last_lfn() {
270 lfn_parts.clear(); // Start fresh for new LFN sequence
271 lfn_parts.push(part); // Add this part to the end
272 } else {
273 // Add at the end, we'll reverse the entire collection later
274 lfn_parts.push(part);
275 }
276 continue;
277 }
278
279 // Skip dot entries
280 if dir_entry.name[0] == b'.' {
281 lfn_parts.clear();
282 continue;
283 }
284
285 // Create internal entry
286 let mut internal_entry = Fat32DirectoryEntryInternal::from_raw(dir_entry);
287
288 // Assemble complete LFN if available
289 if !lfn_parts.is_empty() {
290 // Reverse the parts since LFN entries are stored in reverse order
291 lfn_parts.reverse();
292 let long_filename = lfn_parts.join("");
293 internal_entry.set_long_filename(long_filename);
294 }
295
296 let filename = internal_entry.name();
297
298 // FAT32 is case-insensitive, so compare in uppercase
299 if filename.to_uppercase() == target_name.to_uppercase() {
300 return Ok(internal_entry);
301 }
302
303 // Clear LFN for next entry
304 lfn_parts.clear();
305 }
306
307 // Get next cluster in the chain
308 let next_cluster = self.read_fat_entry(current_cluster)?;
309 if next_cluster >= 0x0FFFFFF8 {
310 // End of cluster chain
311 break;
312 }
313 current_cluster = next_cluster;
314 }
315
316 Err(FileSystemError::new(
317 FileSystemErrorKind::NotFound,
318 &format!("File '{}' not found", target_name),
319 ))
320 }
321
322 /// Read complete cluster data
323 fn read_cluster_data(&self, cluster: u32) -> Result<Vec<u8>, FileSystemError> {
324 let cluster_size = (self.sectors_per_cluster * self.bytes_per_sector) as usize;
325 let cluster_sector = self.cluster_to_sector(cluster);
326
327 // Batch read all sectors in the cluster
328 let mut requests = Vec::new();
329 for i in 0..self.sectors_per_cluster {
330 let request = Box::new(crate::device::block::request::BlockIORequest {
331 request_type: crate::device::block::request::BlockIORequestType::Read,
332 sector: (cluster_sector + i) as usize,
333 sector_count: 1,
334 head: 0,
335 cylinder: 0,
336 buffer: vec![0u8; self.bytes_per_sector as usize],
337 });
338
339 self.block_device.enqueue_request(request);
340 requests.push(());
341 }
342
343 // Process all requests in batch
344 let results = self.block_device.process_requests();
345
346 if results.len() != requests.len() {
347 return Err(FileSystemError::new(
348 FileSystemErrorKind::IoError,
349 format!("Expected {} results, got {}", requests.len(), results.len()),
350 ));
351 }
352
353 // Assemble cluster data from results
354 let mut cluster_data = vec![0u8; cluster_size];
355 for (i, result) in results.iter().enumerate() {
356 match &result.result {
357 Ok(_) => {
358 let start_offset = i * self.bytes_per_sector as usize;
359 let end_offset = start_offset + self.bytes_per_sector as usize;
360 cluster_data[start_offset..end_offset].copy_from_slice(&result.request.buffer);
361 }
362 Err(e) => {
363 return Err(FileSystemError::new(
364 FileSystemErrorKind::IoError,
365 format!("Failed to read cluster sector {}: {}", i, e),
366 ));
367 }
368 }
369 }
370
371 Ok(cluster_data)
372 }
373
374 /// Generate next unique file ID
375 fn generate_file_id(&self) -> u64 {
376 let mut next_id = self.next_file_id.lock();
377 let id = *next_id;
378 *next_id += 1;
379 id
380 }
381
382 /// Read cluster data from the block device
383 fn read_cluster(&self, cluster: u32) -> Result<Vec<u8>, FileSystemError> {
384 if cluster < 2 {
385 return Err(FileSystemError::new(
386 FileSystemErrorKind::InvalidData,
387 "Invalid cluster number",
388 ));
389 }
390
391 // Calculate sector number for this cluster
392 let first_data_sector = self.boot_sector.reserved_sectors as u32
393 + (self.boot_sector.fat_count as u32 * self.boot_sector.sectors_per_fat);
394 let cluster_sector = first_data_sector + (cluster - 2) * self.sectors_per_cluster;
395
396 // Read cluster data
397 let cluster_size = (self.sectors_per_cluster * self.bytes_per_sector) as usize;
398 let mut buffer = vec![0u8; cluster_size];
399
400 // Read all sectors of the cluster
401 for i in 0..self.sectors_per_cluster {
402 let sector_buffer = vec![0u8; self.bytes_per_sector as usize];
403 let request = Box::new(crate::device::block::request::BlockIORequest {
404 request_type: crate::device::block::request::BlockIORequestType::Read,
405 sector: (cluster_sector + i) as usize,
406 sector_count: 1,
407 head: 0,
408 cylinder: 0,
409 buffer: sector_buffer,
410 });
411
412 self.block_device.enqueue_request(request);
413 let results = self.block_device.process_requests();
414
415 if let Some(result) = results.first() {
416 match &result.result {
417 Ok(_) => {
418 let start_offset = (i * self.bytes_per_sector) as usize;
419 let end_offset = start_offset + self.bytes_per_sector as usize;
420 if end_offset <= buffer.len()
421 && result.request.buffer.len() >= self.bytes_per_sector as usize
422 {
423 buffer[start_offset..end_offset].copy_from_slice(
424 &result.request.buffer[..self.bytes_per_sector as usize],
425 );
426 }
427 }
428 Err(e) => {
429 return Err(FileSystemError::new(
430 FileSystemErrorKind::IoError,
431 format!(
432 "Failed to read cluster {} sector {}: {}",
433 cluster,
434 cluster_sector + i,
435 e
436 ),
437 ));
438 }
439 }
440 } else {
441 return Err(FileSystemError::new(
442 FileSystemErrorKind::IoError,
443 format!(
444 "No result from block device for cluster {} sector {}",
445 cluster,
446 cluster_sector + i
447 ),
448 ));
449 }
450 }
451
452 Ok(buffer)
453 }
454
455 /// Read FAT entry for a given cluster
456 fn read_fat_entry(&self, cluster: u32) -> Result<u32, FileSystemError> {
457 // Check for cached entry first
458 {
459 let cache = self.fat_cache.lock();
460 if let Some(&entry) = cache.get(&cluster) {
461 return Ok(entry);
462 }
463 }
464
465 // Calculate FAT offset and sector
466 let fat_offset = cluster * 4; // FAT32 uses 4 bytes per entry
467 let fat_sector =
468 self.boot_sector.reserved_sectors as u32 + (fat_offset / self.bytes_per_sector);
469 let sector_offset = (fat_offset % self.bytes_per_sector) as usize;
470
471 // Read FAT sector
472 let request = Box::new(crate::device::block::request::BlockIORequest {
473 request_type: crate::device::block::request::BlockIORequestType::Read,
474 sector: fat_sector as usize,
475 sector_count: 1,
476 head: 0,
477 cylinder: 0,
478 buffer: vec![0u8; self.bytes_per_sector as usize],
479 });
480
481 self.block_device.enqueue_request(request);
482 let results = self.block_device.process_requests();
483
484 if let Some(result) = results.first() {
485 match &result.result {
486 Ok(_) => {
487 // Extract 32-bit FAT entry (only lower 28 bits are used in FAT32)
488 if sector_offset + 4 > result.request.buffer.len() {
489 return Err(FileSystemError::new(
490 FileSystemErrorKind::IoError,
491 "FAT entry spans sector boundary",
492 ));
493 }
494
495 let fat_entry = u32::from_le_bytes([
496 result.request.buffer[sector_offset],
497 result.request.buffer[sector_offset + 1],
498 result.request.buffer[sector_offset + 2],
499 result.request.buffer[sector_offset + 3],
500 ]) & 0x0FFFFFFF; // Mask to 28 bits for FAT32
501
502 // Cache the entry
503 {
504 let mut cache = self.fat_cache.lock();
505 cache.insert(cluster, fat_entry);
506 }
507
508 Ok(fat_entry)
509 }
510 Err(e) => Err(FileSystemError::new(
511 FileSystemErrorKind::IoError,
512 format!("Failed to read FAT sector: {}", e),
513 )),
514 }
515 } else {
516 Err(FileSystemError::new(
517 FileSystemErrorKind::IoError,
518 "No result from block device",
519 ))
520 }
521 }
522
523 /// Write FAT entry for a given cluster
524 fn write_fat_entry(&self, cluster: u32, value: u32) -> Result<(), FileSystemError> {
525 // Calculate FAT offset and sector
526 let fat_offset = cluster * 4; // FAT32 uses 4 bytes per entry
527 let fat_sector =
528 self.boot_sector.reserved_sectors as u32 + (fat_offset / self.bytes_per_sector);
529 let sector_offset = (fat_offset % self.bytes_per_sector) as usize;
530
531 // FAT32 has two copies of the FAT table, update both
532 for fat_copy in 0..self.boot_sector.fat_count {
533 let current_fat_sector =
534 fat_sector + (fat_copy as u32 * self.boot_sector.sectors_per_fat);
535
536 // Read current FAT sector
537 let request = Box::new(crate::device::block::request::BlockIORequest {
538 request_type: crate::device::block::request::BlockIORequestType::Read,
539 sector: current_fat_sector as usize,
540 sector_count: 1,
541 head: 0,
542 cylinder: 0,
543 buffer: vec![0u8; self.bytes_per_sector as usize],
544 });
545
546 self.block_device.enqueue_request(request);
547 let results = self.block_device.process_requests();
548
549 let mut sector_buffer = if let Some(result) = results.first() {
550 match &result.result {
551 Ok(_) => result.request.buffer.clone(),
552 Err(e) => {
553 return Err(FileSystemError::new(
554 FileSystemErrorKind::IoError,
555 format!("Failed to read FAT sector: {}", e),
556 ));
557 }
558 }
559 } else {
560 return Err(FileSystemError::new(
561 FileSystemErrorKind::IoError,
562 "No result from block device",
563 ));
564 };
565
566 // Update FAT entry (preserve upper 4 bits, update lower 28 bits)
567 if sector_offset + 4 > sector_buffer.len() {
568 return Err(FileSystemError::new(
569 FileSystemErrorKind::IoError,
570 "FAT entry spans sector boundary",
571 ));
572 }
573
574 let current_entry = u32::from_le_bytes([
575 sector_buffer[sector_offset],
576 sector_buffer[sector_offset + 1],
577 sector_buffer[sector_offset + 2],
578 sector_buffer[sector_offset + 3],
579 ]);
580
581 let new_entry = (current_entry & 0xF0000000) | (value & 0x0FFFFFFF);
582 let new_bytes = new_entry.to_le_bytes();
583
584 sector_buffer[sector_offset..sector_offset + 4].copy_from_slice(&new_bytes);
585
586 // Write updated sector back
587 let write_request = Box::new(crate::device::block::request::BlockIORequest {
588 request_type: crate::device::block::request::BlockIORequestType::Write,
589 sector: current_fat_sector as usize,
590 sector_count: 1,
591 head: 0,
592 cylinder: 0,
593 buffer: sector_buffer,
594 });
595
596 self.block_device.enqueue_request(write_request);
597 let write_results = self.block_device.process_requests();
598
599 if let Some(result) = write_results.first() {
600 match &result.result {
601 Ok(_) => {
602 // Successfully wrote this FAT copy
603 }
604 Err(e) => {
605 return Err(FileSystemError::new(
606 FileSystemErrorKind::IoError,
607 format!("Failed to write FAT sector: {}", e),
608 ));
609 }
610 }
611 } else {
612 return Err(FileSystemError::new(
613 FileSystemErrorKind::IoError,
614 "No result from block device for write",
615 ));
616 }
617 }
618
619 // Update cache after successfully writing all FAT copies
620 {
621 let mut cache = self.fat_cache.lock();
622 cache.insert(cluster, value);
623 }
624
625 Ok(())
626 }
627
628 /// Read file content by following cluster chain
629 pub fn read_file_content(
630 &self,
631 start_cluster: u32,
632 size: usize,
633 ) -> Result<Vec<u8>, FileSystemError> {
634 #[cfg(test)]
635 {
636 // use crate::early_println;
637 // early_println!("[FAT32] read_file_content: start_cluster={}, size={}", start_cluster, size);
638 }
639
640 if start_cluster < 2 {
641 return Ok(Vec::new()); // Empty file
642 }
643
644 let mut content = Vec::new();
645 let mut current_cluster = start_cluster;
646 let cluster_size = (self.sectors_per_cluster * self.bytes_per_sector) as usize;
647
648 loop {
649 // #[cfg(test)]
650 // {
651 // use crate::early_println;
652 // early_println!("[FAT32] reading cluster {}", current_cluster);
653 // }
654
655 // Read current cluster
656 let cluster_data = self.read_cluster(current_cluster)?;
657
658 // #[cfg(test)]
659 // {
660 // use crate::early_println;
661 // early_println!("[FAT32] read cluster {} data: {} bytes, first 8 bytes: {:?}",
662 // current_cluster, cluster_data.len(),
663 // &cluster_data[..core::cmp::min(8, cluster_data.len())]);
664 // }
665
666 // Add data to content (up to requested size)
667 let remaining_size = size.saturating_sub(content.len());
668 if remaining_size == 0 {
669 break;
670 }
671
672 let bytes_to_copy = core::cmp::min(cluster_data.len(), remaining_size);
673 content.extend_from_slice(&cluster_data[..bytes_to_copy]);
674
675 // Check if we've read enough
676 if content.len() >= size {
677 break;
678 }
679
680 // Get next cluster from FAT
681 let fat_entry = self.read_fat_entry(current_cluster)?;
682
683 // Check for end of chain
684 if fat_entry >= 0x0FFFFFF8 {
685 break; // End of file
686 }
687
688 current_cluster = fat_entry;
689 }
690
691 // Truncate to exact size if needed
692 content.truncate(size);
693 Ok(content)
694 }
695
696 /// Read a single page (4096 bytes) of file content into physical memory.
697 ///
698 /// This is used by the page cache manager for demand paging.
699 pub fn read_page_content(
700 &self,
701 start_cluster: u32,
702 page_index: u64,
703 paddr: usize,
704 ) -> Result<(), FileSystemError> {
705 use crate::environment::PAGE_SIZE;
706
707 if start_cluster < 2 {
708 unsafe {
709 core::ptr::write_bytes(paddr as *mut u8, 0, PAGE_SIZE);
710 }
711 return Ok(());
712 }
713
714 let cluster_size = (self.sectors_per_cluster * self.bytes_per_sector) as usize;
715 let page_offset = page_index as usize * PAGE_SIZE;
716
717 let start_cluster_index = page_offset / cluster_size;
718 let offset_in_cluster = page_offset % cluster_size;
719
720 unsafe {
721 core::ptr::write_bytes(paddr as *mut u8, 0, PAGE_SIZE);
722 }
723
724 let mut current_cluster = start_cluster;
725 for _ in 0..start_cluster_index {
726 let fat_entry = self.read_fat_entry(current_cluster)?;
727 if fat_entry >= 0x0FFFFFF8 {
728 return Ok(());
729 }
730 current_cluster = fat_entry;
731 }
732
733 let mut page_ptr = paddr as *mut u8;
734 let mut bytes_written = 0usize;
735 let mut cluster_offset = offset_in_cluster;
736
737 while bytes_written < PAGE_SIZE {
738 let cluster_data = self.read_cluster(current_cluster)?;
739
740 let bytes_to_copy = core::cmp::min(
741 cluster_data.len() - cluster_offset,
742 PAGE_SIZE - bytes_written,
743 );
744
745 unsafe {
746 core::ptr::copy_nonoverlapping(
747 cluster_data.as_ptr().add(cluster_offset),
748 page_ptr,
749 bytes_to_copy,
750 );
751 page_ptr = page_ptr.add(bytes_to_copy);
752 }
753
754 bytes_written += bytes_to_copy;
755 cluster_offset = 0;
756
757 if bytes_written >= PAGE_SIZE {
758 break;
759 }
760
761 let fat_entry = self.read_fat_entry(current_cluster)?;
762 if fat_entry >= 0x0FFFFFF8 {
763 break;
764 }
765 current_cluster = fat_entry;
766 }
767
768 Ok(())
769 }
770
771 /// Write file content to disk and return the starting cluster
772 pub fn write_file_content(
773 &self,
774 current_cluster: u32,
775 content: &[u8],
776 ) -> Result<u32, FileSystemError> {
777 // Debug output for large file operations
778 // #[cfg(test)]
779 // {
780 // use crate::early_println;
781 // early_println!("[FAT32] write_file_content: cluster={}, content_len={}", current_cluster, content.len());
782 // }
783
784 // If content is empty, free the cluster chain
785 if content.is_empty() {
786 if current_cluster != 0 {
787 self.free_cluster_chain(current_cluster)?;
788 }
789 return Ok(0);
790 }
791
792 let cluster_size = (self.sectors_per_cluster * self.bytes_per_sector) as usize;
793 let clusters_needed = (content.len() + cluster_size - 1) / cluster_size;
794
795 // Debug output for allocation
796 // #[cfg(test)]
797 // {
798 // use crate::early_println;
799 // early_println!("[FAT32] clusters_needed={}, cluster_size={}", clusters_needed, cluster_size);
800 // }
801
802 // Free existing chain if we're overwriting
803 if current_cluster != 0 {
804 // #[cfg(test)]
805 // {
806 // use crate::early_println;
807 // early_println!("[FAT32] freeing existing cluster chain starting from cluster {}", current_cluster);
808 // }
809 self.free_cluster_chain(current_cluster)?;
810 // #[cfg(test)]
811 // {
812 // use crate::early_println;
813 // early_println!("[FAT32] finished freeing cluster chain");
814 // }
815 }
816
817 // Allocate new cluster chain
818 let mut clusters = Vec::new();
819 for cluster_index in 0..clusters_needed {
820 // #[cfg(test)]
821 // {
822 // use crate::early_println;
823 // early_println!("[FAT32] allocating cluster {} of {}", cluster_index + 1, clusters_needed);
824 // }
825 match self.allocate_cluster() {
826 Ok(new_cluster) => {
827 // #[cfg(test)]
828 // {
829 // use crate::early_println;
830 // // early_println!("[FAT32] allocated cluster: {}", new_cluster);
831 // }
832 clusters.push(new_cluster);
833 }
834 Err(e) => {
835 #[cfg(test)]
836 {
837 use crate::early_println;
838 early_println!(
839 "[FAT32] failed to allocate cluster {} of {}: {:?}",
840 cluster_index + 1,
841 clusters_needed,
842 e
843 );
844 }
845 return Err(e);
846 }
847 }
848 }
849
850 // Chain the clusters together in FAT
851 // #[cfg(test)]
852 // {
853 // use crate::early_println;
854 // early_println!("[FAT32] setting up FAT chain for {} clusters", clusters.len());
855 // }
856 for i in 0..clusters.len() - 1 {
857 // #[cfg(test)]
858 // {
859 // use crate::early_println;
860 // early_println!("[FAT32] setting FAT entry: cluster {} -> {}", clusters[i], clusters[i + 1]);
861 // }
862 self.write_fat_entry(clusters[i], clusters[i + 1])?;
863 }
864 // Mark the last cluster as end of chain
865 if !clusters.is_empty() {
866 // #[cfg(test)]
867 // {
868 // use crate::early_println;
869 // early_println!("[FAT32] marking last cluster {} as end of chain", clusters[clusters.len() - 1]);
870 // }
871 self.write_fat_entry(clusters[clusters.len() - 1], 0x0FFFFFFF)?; // End of chain marker
872 }
873
874 // Write content to clusters
875 // #[cfg(test)]
876 // {
877 // use crate::early_println;
878 // early_println!("[FAT32] writing content to {} clusters", clusters.len());
879 // }
880 for (i, &cluster) in clusters.iter().enumerate() {
881 let start_offset = i * cluster_size;
882 let end_offset = core::cmp::min(start_offset + cluster_size, content.len());
883
884 if start_offset < content.len() {
885 let chunk = &content[start_offset..end_offset];
886
887 // #[cfg(test)]
888 // {
889 // use crate::early_println;
890 // early_println!("[FAT32] writing cluster {}: {} bytes (offset {}..{})", cluster, chunk.len(), start_offset, end_offset);
891 // }
892
893 self.write_cluster_data(cluster, chunk)?;
894 }
895 }
896
897 // #[cfg(test)]
898 // {
899 // use crate::early_println;
900 // early_println!("[FAT32] write_file_content completed, start_cluster={}", clusters.first().copied().unwrap_or(0));
901 // }
902
903 Ok(clusters.first().copied().unwrap_or(0))
904 }
905
906 /// Read FAT entry directly from disk without caching
907 fn read_fat_entry_direct(&self, cluster: u32) -> Result<u32, FileSystemError> {
908 // #[cfg(test)]
909 // {
910 // use crate::early_println;
911 // early_println!("[FAT32] reading FAT entry for cluster {} directly from disk", cluster);
912 // }
913
914 // Calculate FAT sector and offset
915 let fat_offset = cluster * 4; // 4 bytes per FAT32 entry
916 let fat_sector =
917 self.boot_sector.reserved_sectors as u32 + (fat_offset / self.bytes_per_sector);
918 let entry_offset = (fat_offset % self.bytes_per_sector) as usize;
919
920 // #[cfg(test)]
921 // {
922 // use crate::early_println;
923 // early_println!("[FAT32] fat_sector={}, entry_offset={}", fat_sector, entry_offset);
924 // }
925
926 // Read FAT sector
927 let buffer = vec![0u8; self.bytes_per_sector as usize];
928 let request = Box::new(crate::device::block::request::BlockIORequest {
929 request_type: crate::device::block::request::BlockIORequestType::Read,
930 sector: fat_sector as usize,
931 sector_count: 1,
932 head: 0,
933 cylinder: 0,
934 buffer,
935 });
936
937 // #[cfg(test)]
938 // {
939 // use crate::early_println;
940 // early_println!("[FAT32] enqueuing FAT read request for sector {}", fat_sector);
941 // }
942
943 self.block_device.enqueue_request(request);
944 let results = self.block_device.process_requests();
945
946 // #[cfg(test)]
947 // {
948 // use crate::early_println;
949 // early_println!("[FAT32] FAT read request completed, results.len()={}", results.len());
950 // }
951
952 if results.is_empty() || results[0].result.is_err() {
953 return Err(FileSystemError::new(
954 FileSystemErrorKind::IoError,
955 "Failed to read FAT sector",
956 ));
957 }
958
959 // Get the buffer back from the result
960 let buffer = &results[0].request.buffer;
961
962 // Extract FAT entry (little-endian, mask off top 4 bits for FAT32)
963 let entry = u32::from_le_bytes([
964 buffer[entry_offset],
965 buffer[entry_offset + 1],
966 buffer[entry_offset + 2],
967 buffer[entry_offset + 3],
968 ]) & 0x0FFFFFFF;
969
970 // #[cfg(test)]
971 // {
972 // use crate::early_println;
973 // early_println!("[FAT32] read FAT entry for cluster {}: {:#x}", cluster, entry);
974 // }
975
976 Ok(entry)
977 }
978
979 /// Allocate a free cluster from the FAT and mark it as allocated
980 fn allocate_cluster(&self) -> Result<u32, FileSystemError> {
981 // #[cfg(test)]
982 // {
983 // use crate::early_println;
984 // early_println!("[FAT32] searching for free cluster...");
985 // }
986
987 // Simple allocation: find first free cluster starting from cluster 2
988 for cluster in 2..100 {
989 // Reduced search range for faster debugging
990 // #[cfg(test)]
991 // {
992 // use crate::early_println;
993 // if cluster <= 10 {
994 // early_println!("[FAT32] checking cluster {}", cluster);
995 // }
996 // }
997
998 // Read FAT entry directly without caching to avoid stale cache issues
999 let fat_entry = self.read_fat_entry_direct(cluster)?;
1000
1001 // #[cfg(test)]
1002 // {
1003 // use crate::early_println;
1004 // if cluster <= 20 || fat_entry == 0 {
1005 // early_println!("[FAT32] cluster {} has FAT entry: {:#x}", cluster, fat_entry);
1006 // }
1007 // }
1008
1009 if fat_entry == 0 {
1010 // #[cfg(test)]
1011 // {
1012 // use crate::early_println;
1013 // early_println!("[FAT32] ✓ found free cluster: {}", cluster);
1014 // }
1015 // Mark as allocated immediately to prevent duplicate allocation
1016 self.write_fat_entry(cluster, 0x0FFFFFFF)?; // End of chain marker (will be updated later if part of chain)
1017
1018 // Update FS Info sector
1019 self.update_fs_info_allocated_cluster(cluster)?;
1020
1021 // #[cfg(test)]
1022 // {
1023 // use crate::early_println;
1024 // early_println!("[FAT32] ✓ allocated cluster: {}", cluster);
1025 // }
1026 return Ok(cluster);
1027 }
1028 }
1029
1030 Err(FileSystemError::new(
1031 FileSystemErrorKind::NoSpace,
1032 "No free clusters available",
1033 ))
1034 }
1035
1036 /// Initialize a new directory cluster with . and .. entries
1037 fn initialize_directory(
1038 &self,
1039 dir_cluster: u32,
1040 parent_cluster: u32,
1041 ) -> Result<(), FileSystemError> {
1042 use crate::fs::vfs_v2::drivers::fat32::structures::Fat32DirectoryEntry;
1043
1044 // Calculate LBA for the directory cluster
1045 let first_data_sector = self.boot_sector.reserved_sectors as u32
1046 + (self.boot_sector.fat_count as u32 * self.boot_sector.sectors_per_fat);
1047 let lba = first_data_sector + (dir_cluster - 2) * self.sectors_per_cluster;
1048
1049 // Clear the directory cluster first
1050 let cluster_size = (self.sectors_per_cluster * self.bytes_per_sector) as usize;
1051 let zero_data = vec![0u8; cluster_size];
1052
1053 for sector_offset in 0..self.sectors_per_cluster {
1054 let sector_lba = lba + sector_offset as u32;
1055 let sector_data = &zero_data[(sector_offset as usize * self.bytes_per_sector as usize)
1056 ..((sector_offset as usize + 1) * self.bytes_per_sector as usize)];
1057
1058 let request = Box::new(crate::device::block::request::BlockIORequest {
1059 request_type: crate::device::block::request::BlockIORequestType::Write,
1060 sector: sector_lba as usize,
1061 sector_count: 1,
1062 head: 0,
1063 cylinder: 0,
1064 buffer: sector_data.to_vec(),
1065 });
1066
1067 self.block_device.enqueue_request(request);
1068 }
1069 self.block_device.process_requests();
1070
1071 // Create . (current directory) entry
1072 let dot_entry = Fat32DirectoryEntry {
1073 name: [
1074 b'.', b' ', b' ', b' ', b' ', b' ', b' ', b' ', b' ', b' ', b' ',
1075 ],
1076 attributes: 0x10, // Directory attribute
1077 nt_reserved: 0,
1078 creation_time_tenths: 0,
1079 creation_time: 0,
1080 creation_date: 0,
1081 last_access_date: 0,
1082 cluster_high: ((dir_cluster >> 16) & 0xFFFF) as u16,
1083 modification_time: 0,
1084 modification_date: 0,
1085 cluster_low: (dir_cluster & 0xFFFF) as u16,
1086 file_size: 0,
1087 };
1088
1089 // Create .. (parent directory) entry
1090 // For FAT32 root directory children, '..' should point to cluster 0
1091 let actual_parent = if parent_cluster == self.root_cluster {
1092 0
1093 } else {
1094 parent_cluster
1095 };
1096 let dotdot_entry = Fat32DirectoryEntry {
1097 name: [
1098 b'.', b'.', b' ', b' ', b' ', b' ', b' ', b' ', b' ', b' ', b' ',
1099 ],
1100 attributes: 0x10, // Directory attribute
1101 nt_reserved: 0,
1102 creation_time_tenths: 0,
1103 creation_time: 0,
1104 creation_date: 0,
1105 last_access_date: 0,
1106 cluster_high: ((actual_parent >> 16) & 0xFFFF) as u16,
1107 modification_time: 0,
1108 modification_date: 0,
1109 cluster_low: (actual_parent & 0xFFFF) as u16,
1110 file_size: 0,
1111 };
1112
1113 // Write both entries to the beginning of the directory cluster
1114 let mut entry_data = Vec::new();
1115
1116 // Serialize . entry (32 bytes)
1117 entry_data.extend_from_slice(&dot_entry.name);
1118 entry_data.push(dot_entry.attributes);
1119 entry_data.push(dot_entry.nt_reserved);
1120 entry_data.push(dot_entry.creation_time_tenths);
1121 entry_data.extend_from_slice(&dot_entry.creation_time.to_le_bytes());
1122 entry_data.extend_from_slice(&dot_entry.creation_date.to_le_bytes());
1123 entry_data.extend_from_slice(&dot_entry.last_access_date.to_le_bytes());
1124 entry_data.extend_from_slice(&dot_entry.cluster_high.to_le_bytes());
1125 entry_data.extend_from_slice(&dot_entry.modification_time.to_le_bytes());
1126 entry_data.extend_from_slice(&dot_entry.modification_date.to_le_bytes());
1127 entry_data.extend_from_slice(&dot_entry.cluster_low.to_le_bytes());
1128 entry_data.extend_from_slice(&dot_entry.file_size.to_le_bytes());
1129
1130 // Serialize .. entry (32 bytes)
1131 entry_data.extend_from_slice(&dotdot_entry.name);
1132 entry_data.push(dotdot_entry.attributes);
1133 entry_data.push(dotdot_entry.nt_reserved);
1134 entry_data.push(dotdot_entry.creation_time_tenths);
1135 entry_data.extend_from_slice(&dotdot_entry.creation_time.to_le_bytes());
1136 entry_data.extend_from_slice(&dotdot_entry.creation_date.to_le_bytes());
1137 entry_data.extend_from_slice(&dotdot_entry.last_access_date.to_le_bytes());
1138 entry_data.extend_from_slice(&dotdot_entry.cluster_high.to_le_bytes());
1139 entry_data.extend_from_slice(&dotdot_entry.modification_time.to_le_bytes());
1140 entry_data.extend_from_slice(&dotdot_entry.modification_date.to_le_bytes());
1141 entry_data.extend_from_slice(&dotdot_entry.cluster_low.to_le_bytes());
1142 entry_data.extend_from_slice(&dotdot_entry.file_size.to_le_bytes());
1143
1144 // Pad to sector boundary if needed
1145 while entry_data.len() < self.bytes_per_sector as usize {
1146 entry_data.push(0);
1147 }
1148
1149 // Write the first sector with . and .. entries
1150 let request = Box::new(crate::device::block::request::BlockIORequest {
1151 request_type: crate::device::block::request::BlockIORequestType::Write,
1152 sector: lba as usize,
1153 sector_count: 1,
1154 head: 0,
1155 cylinder: 0,
1156 buffer: entry_data,
1157 });
1158
1159 self.block_device.enqueue_request(request);
1160 self.block_device.process_requests();
1161
1162 Ok(())
1163 }
1164
1165 /// Update FS Info sector when a cluster is allocated
1166 fn update_fs_info_allocated_cluster(
1167 &self,
1168 _allocated_cluster: u32,
1169 ) -> Result<(), FileSystemError> {
1170 // FS Info sector is usually at sector 1
1171 let fs_info_sector = 1;
1172 let fs_info_lba = fs_info_sector;
1173
1174 // Read the current FS Info sector
1175 let request = Box::new(crate::device::block::request::BlockIORequest {
1176 request_type: crate::device::block::request::BlockIORequestType::Read,
1177 sector: fs_info_lba as usize,
1178 sector_count: 1,
1179 head: 0,
1180 cylinder: 0,
1181 buffer: vec![0u8; self.bytes_per_sector as usize],
1182 });
1183
1184 self.block_device.enqueue_request(request);
1185 let results = self.block_device.process_requests();
1186
1187 if let Some(result) = results.get(0) {
1188 if result.result.is_ok() {
1189 let mut fs_info_data = result.request.buffer.clone();
1190
1191 // Check FS Info signature at offset 0x1e4
1192 if &fs_info_data[0x1e4..0x1e8] == b"rrAa" {
1193 // Get current free cluster count (offset 0x1e8, little-endian)
1194 let current_free = u32::from_le_bytes([
1195 fs_info_data[0x1e8],
1196 fs_info_data[0x1e9],
1197 fs_info_data[0x1ea],
1198 fs_info_data[0x1eb],
1199 ]);
1200
1201 // Decrease free cluster count by 1
1202 let new_free = current_free.saturating_sub(1);
1203 let new_free_bytes = new_free.to_le_bytes();
1204 fs_info_data[0x1e8] = new_free_bytes[0];
1205 fs_info_data[0x1e9] = new_free_bytes[1];
1206 fs_info_data[0x1ea] = new_free_bytes[2];
1207 fs_info_data[0x1eb] = new_free_bytes[3];
1208
1209 // Update next free cluster hint (offset 0x1ec)
1210 // Set it to one cluster after the allocated one
1211 let next_free_hint = _allocated_cluster + 1;
1212 let hint_bytes = next_free_hint.to_le_bytes();
1213 fs_info_data[0x1ec] = hint_bytes[0];
1214 fs_info_data[0x1ed] = hint_bytes[1];
1215 fs_info_data[0x1ee] = hint_bytes[2];
1216 fs_info_data[0x1ef] = hint_bytes[3];
1217
1218 // Write back the updated FS Info sector
1219 let write_request = Box::new(crate::device::block::request::BlockIORequest {
1220 request_type: crate::device::block::request::BlockIORequestType::Write,
1221 sector: fs_info_lba as usize,
1222 sector_count: 1,
1223 head: 0,
1224 cylinder: 0,
1225 buffer: fs_info_data,
1226 });
1227
1228 self.block_device.enqueue_request(write_request);
1229 self.block_device.process_requests();
1230 }
1231 }
1232 }
1233
1234 Ok(())
1235 }
1236
1237 /// Update FS Info sector to increment free cluster count
1238 fn update_fs_info_freed_cluster(&self, freed_count: u32) -> Result<(), FileSystemError> {
1239 let fs_info_sector = self.boot_sector.fs_info_sector;
1240 if fs_info_sector != 0 && fs_info_sector != 0xFFFF {
1241 let fs_info_lba = fs_info_sector as usize;
1242
1243 // Read current FS Info sector
1244 let request = Box::new(crate::device::block::request::BlockIORequest {
1245 request_type: crate::device::block::request::BlockIORequestType::Read,
1246 sector: fs_info_lba,
1247 sector_count: 1,
1248 head: 0,
1249 cylinder: 0,
1250 buffer: vec![0u8; 512],
1251 });
1252
1253 self.block_device.enqueue_request(request);
1254 let results = self.block_device.process_requests();
1255
1256 if let Some(result) = results.first() {
1257 match &result.result {
1258 Ok(_) => {
1259 let mut buffer = result.request.buffer.clone();
1260
1261 // Check FS Info signature
1262 if &buffer[0..4] == b"RRaA" && &buffer[484..488] == b"rrAa" {
1263 // Read current free cluster count
1264 let current_free = u32::from_le_bytes([
1265 buffer[488],
1266 buffer[489],
1267 buffer[490],
1268 buffer[491],
1269 ]);
1270
1271 // Update free cluster count (add freed clusters)
1272 let new_free = current_free.saturating_add(freed_count);
1273 let new_free_bytes = new_free.to_le_bytes();
1274 buffer[488] = new_free_bytes[0];
1275 buffer[489] = new_free_bytes[1];
1276 buffer[490] = new_free_bytes[2];
1277 buffer[491] = new_free_bytes[3];
1278
1279 // Write back to disk
1280 let write_request =
1281 Box::new(crate::device::block::request::BlockIORequest {
1282 request_type:
1283 crate::device::block::request::BlockIORequestType::Write,
1284 sector: fs_info_lba,
1285 sector_count: 1,
1286 head: 0,
1287 cylinder: 0,
1288 buffer,
1289 });
1290
1291 self.block_device.enqueue_request(write_request);
1292 self.block_device.process_requests();
1293 }
1294 }
1295 Err(_) => {
1296 return Err(FileSystemError::new(
1297 FileSystemErrorKind::IoError,
1298 "Failed to read FS Info sector for free cluster update",
1299 ));
1300 }
1301 }
1302 } else {
1303 return Err(FileSystemError::new(
1304 FileSystemErrorKind::IoError,
1305 "No result from FS Info sector read",
1306 ));
1307 }
1308 }
1309 Ok(())
1310 }
1311
1312 /// Free a cluster chain starting from the given cluster
1313 fn free_cluster_chain(&self, start_cluster: u32) -> Result<(), FileSystemError> {
1314 // #[cfg(test)]
1315 // {
1316 // use crate::early_println;
1317 // early_println!("[FAT32] free_cluster_chain: starting from cluster {}", start_cluster);
1318 // }
1319
1320 let mut current = start_cluster;
1321 let mut freed_count = 0;
1322
1323 // Only process valid cluster numbers (>= 2)
1324 while current >= 2 && current < 0x0FFFFFF0 {
1325 // #[cfg(test)]
1326 // {
1327 // use crate::early_println;
1328 // early_println!("[FAT32] freeing cluster {}, reading next cluster...", current);
1329 // }
1330
1331 let next = self.read_fat_entry(current)?;
1332
1333 // #[cfg(test)]
1334 // {
1335 // use crate::early_println;
1336 // early_println!("[FAT32] cluster {} next = {:#x}, marking as free", current, next);
1337 // }
1338
1339 self.write_fat_entry(current, 0)?; // Mark as free
1340 freed_count += 1;
1341
1342 // Check if we've reached the end of chain or invalid cluster
1343 if next >= 0x0FFFFFF8 || next == 0 || next == 1 {
1344 // #[cfg(test)]
1345 // {
1346 // use crate::early_println;
1347 // early_println!("[FAT32] reached end of chain at cluster {} (next={:#x})", current, next);
1348 // }
1349 break; // End of chain or invalid next cluster
1350 }
1351 current = next;
1352 }
1353
1354 // #[cfg(test)]
1355 // {
1356 // use crate::early_println;
1357 // early_println!("[FAT32] free_cluster_chain completed");
1358 // }
1359
1360 // Update FS Info sector with number of freed clusters
1361 self.update_fs_info_freed_cluster(freed_count)?;
1362
1363 Ok(())
1364 }
1365
1366 /// Read data to a cluster
1367 fn write_cluster_data(&self, cluster: u32, data: &[u8]) -> Result<(), FileSystemError> {
1368 #[cfg(test)]
1369 {
1370 use crate::early_println;
1371 early_println!(
1372 "[FAT32] write_cluster_data: cluster={}, data_len={}, first 8 bytes: {:?}",
1373 cluster,
1374 data.len(),
1375 &data[..core::cmp::min(8, data.len())]
1376 );
1377 }
1378
1379 if cluster < 2 {
1380 return Err(FileSystemError::new(
1381 FileSystemErrorKind::InvalidData,
1382 "Invalid cluster number",
1383 ));
1384 }
1385
1386 let first_data_sector = self.boot_sector.reserved_sectors as u32
1387 + (self.boot_sector.fat_count as u32 * self.boot_sector.sectors_per_fat);
1388 let first_sector_of_cluster = first_data_sector + (cluster - 2) * self.sectors_per_cluster;
1389
1390 // #[cfg(test)]
1391 // {
1392 // use crate::early_println;
1393 // early_println!("[FAT32] writing cluster {} at sector {}", cluster, first_sector_of_cluster);
1394 // }
1395
1396 let cluster_size = (self.sectors_per_cluster * self.bytes_per_sector) as usize;
1397 let mut buffer = vec![0u8; cluster_size];
1398
1399 // Copy data to buffer, pad with zeros if necessary
1400 let copy_len = core::cmp::min(data.len(), cluster_size);
1401 buffer[..copy_len].copy_from_slice(&data[..copy_len]);
1402
1403 // Write cluster data in batch
1404 let mut requests = Vec::new();
1405 for sector_offset in 0..self.sectors_per_cluster {
1406 let sector = first_sector_of_cluster + sector_offset;
1407 let buffer_offset = (sector_offset * self.bytes_per_sector) as usize;
1408 let sector_data =
1409 buffer[buffer_offset..buffer_offset + self.bytes_per_sector as usize].to_vec();
1410
1411 let request = Box::new(crate::device::block::request::BlockIORequest {
1412 request_type: crate::device::block::request::BlockIORequestType::Write,
1413 sector: sector as usize,
1414 sector_count: 1,
1415 head: 0,
1416 cylinder: 0,
1417 buffer: sector_data,
1418 });
1419
1420 self.block_device.enqueue_request(request);
1421 requests.push(());
1422 }
1423
1424 // Process all requests in batch
1425 let results = self.block_device.process_requests();
1426
1427 if results.len() != requests.len() {
1428 return Err(FileSystemError::new(
1429 FileSystemErrorKind::IoError,
1430 format!("Expected {} results, got {}", requests.len(), results.len()),
1431 ));
1432 }
1433
1434 // Check all results
1435 for (i, result) in results.iter().enumerate() {
1436 if result.result.is_err() {
1437 return Err(FileSystemError::new(
1438 FileSystemErrorKind::IoError,
1439 format!(
1440 "Failed to write cluster {} sector {}",
1441 cluster,
1442 first_sector_of_cluster + i as u32
1443 ),
1444 ));
1445 }
1446 }
1447
1448 Ok(())
1449 }
1450
1451 /// Convert cluster number to first sector number
1452 fn cluster_to_sector(&self, cluster: u32) -> u32 {
1453 let first_data_sector = self.boot_sector.reserved_sectors as u32
1454 + (self.boot_sector.fat_count as u32 * self.boot_sector.sectors_per_fat);
1455 first_data_sector + (cluster - 2) * self.sectors_per_cluster
1456 }
1457
1458 /// Read directory entries from a cluster
1459 fn read_directory_entries(
1460 &self,
1461 cluster: u32,
1462 entries: &mut Vec<Fat32DirectoryEntryInternal>,
1463 ) -> Result<(), FileSystemError> {
1464 let data = self.read_cluster_data(cluster)?;
1465 let entry_size = 32; // Each directory entry is 32 bytes
1466 let mut lfn_parts: Vec<String> = Vec::new(); // Collect LFN parts in order
1467
1468 for chunk in data.chunks(entry_size) {
1469 if chunk.len() < entry_size {
1470 break;
1471 }
1472
1473 // Check if entry is valid (not deleted and not empty)
1474 if chunk[0] == 0x00 {
1475 break; // End of directory
1476 }
1477 if chunk[0] == 0xE5 {
1478 lfn_parts.clear(); // Clear LFN parts on deleted entry
1479 continue; // Deleted entry
1480 }
1481
1482 // Parse directory entry
1483 let attributes = chunk[11];
1484
1485 // Handle LFN entries
1486 if attributes & 0x0F == 0x0F {
1487 // This is a LFN entry
1488 let lfn_entry = unsafe { &*(chunk.as_ptr() as *const structures::Fat32LFNEntry) };
1489
1490 // Extract characters from this LFN entry
1491 let chars = lfn_entry.extract_chars();
1492
1493 // Convert UTF-16 to UTF-8
1494 let mut part = String::new();
1495 for &ch in &chars {
1496 if ch == 0 || ch == 0xFFFF {
1497 break; // End of string or padding
1498 }
1499 if let Some(c) = char::from_u32(ch as u32) {
1500 part.push(c);
1501 }
1502 }
1503
1504 // LFN entries are stored with highest sequence number first
1505 // We need to collect them and reverse the order when assembling
1506 if lfn_entry.is_last_lfn() {
1507 lfn_parts.clear(); // Start fresh for new LFN sequence
1508 lfn_parts.push(part); // Add this part to the end
1509 } else {
1510 // Add at the end, we'll reverse the entire collection later
1511 lfn_parts.push(part);
1512 }
1513 continue;
1514 }
1515
1516 // Skip volume labels
1517 if attributes & 0x08 != 0 {
1518 lfn_parts.clear();
1519 continue;
1520 }
1521
1522 // This is a regular SFN directory entry
1523 let mut name_bytes = [0u8; 11];
1524 name_bytes.copy_from_slice(&chunk[0..11]);
1525
1526 let cluster = ((chunk[21] as u32) << 24)
1527 | ((chunk[20] as u32) << 16)
1528 | ((chunk[27] as u32) << 8)
1529 | (chunk[26] as u32);
1530 let size = u32::from_le_bytes([chunk[28], chunk[29], chunk[30], chunk[31]]);
1531
1532 // Create Fat32DirectoryEntry structure first
1533 let raw_entry = structures::Fat32DirectoryEntry {
1534 name: name_bytes,
1535 attributes,
1536 nt_reserved: 0,
1537 creation_time_tenths: 0,
1538 creation_time: 0,
1539 creation_date: 0,
1540 last_access_date: 0,
1541 cluster_high: ((cluster >> 16) & 0xFFFF) as u16,
1542 modification_time: 0,
1543 modification_date: 0,
1544 cluster_low: (cluster & 0xFFFF) as u16,
1545 file_size: size,
1546 };
1547
1548 // Create internal entry from raw entry
1549 let mut internal_entry = Fat32DirectoryEntryInternal::from_raw(raw_entry);
1550
1551 // Assemble complete LFN if available
1552 if !lfn_parts.is_empty() {
1553 // Reverse the parts since LFN entries are stored in reverse order
1554 lfn_parts.reverse();
1555 let long_filename = lfn_parts.join("");
1556 internal_entry.set_long_filename(long_filename);
1557 }
1558
1559 entries.push(internal_entry);
1560
1561 // Clear LFN for next entry
1562 lfn_parts.clear();
1563 }
1564
1565 Ok(())
1566 }
1567
1568 /// Write a new directory entry with LFN support to the specified directory cluster
1569 fn write_directory_entry_with_name(
1570 &self,
1571 dir_cluster: u32,
1572 filename: &str,
1573 cluster: u32,
1574 size: u32,
1575 is_directory: bool,
1576 ) -> Result<(), FileSystemError> {
1577 // #[cfg(test)]
1578 // {
1579 // use crate::early_println;
1580 // early_println!("[FAT32] write_directory_entry_with_name: dir_cluster={}, filename='{}', cluster={}, is_directory={}",
1581 // dir_cluster, filename, cluster, is_directory);
1582 // }
1583
1584 // Generate a unique SFN for this filename
1585 let unique_sfn = self.generate_unique_sfn(dir_cluster, filename)?;
1586
1587 #[cfg(test)]
1588 {
1589 use crate::early_println;
1590 let sfn_str = core::str::from_utf8(&unique_sfn).unwrap_or("<invalid>");
1591 early_println!(
1592 "[FAT32] generated unique SFN for '{}': '{}'",
1593 filename,
1594 sfn_str
1595 );
1596 }
1597
1598 // Create the SFN entry with the generated SFN
1599 let entry = if is_directory {
1600 structures::Fat32DirectoryEntry {
1601 name: unique_sfn,
1602 attributes: 0x10, // Directory
1603 nt_reserved: 0,
1604 creation_time_tenths: 0,
1605 creation_time: 0,
1606 creation_date: 0,
1607 last_access_date: 0,
1608 cluster_high: (cluster >> 16) as u16,
1609 modification_time: 0,
1610 modification_date: 0,
1611 cluster_low: (cluster & 0xFFFF) as u16,
1612 file_size: 0,
1613 }
1614 } else {
1615 structures::Fat32DirectoryEntry {
1616 name: unique_sfn,
1617 attributes: 0x00, // Regular file
1618 nt_reserved: 0,
1619 creation_time_tenths: 0,
1620 creation_time: 0,
1621 creation_date: 0,
1622 last_access_date: 0,
1623 cluster_high: (cluster >> 16) as u16,
1624 modification_time: 0,
1625 modification_date: 0,
1626 cluster_low: (cluster & 0xFFFF) as u16,
1627 file_size: size,
1628 }
1629 };
1630
1631 // Check if LFN is required
1632 let needs_lfn = Self::requires_lfn(filename);
1633 // #[cfg(test)]
1634 // {
1635 // use crate::early_println;
1636 // early_println!("[FAT32] filename='{}', needs_lfn={}", filename, needs_lfn);
1637 // }
1638
1639 let mut entries_to_write = Vec::new();
1640
1641 if needs_lfn {
1642 // Generate LFN entries
1643 let sfn_checksum = Self::calculate_sfn_checksum(&entry.name);
1644 let lfn_entries = Self::generate_lfn_entries(&filename, sfn_checksum);
1645 // #[cfg(test)]
1646 // {
1647 // use crate::early_println;
1648 // early_println!("[FAT32] generated {} LFN entries", lfn_entries.len());
1649 // }
1650
1651 // Add LFN entries first (they come before the SFN entry)
1652 for lfn_entry in lfn_entries {
1653 entries_to_write.push(EntryToWrite::LFN(lfn_entry));
1654 }
1655 }
1656
1657 // Add the SFN entry
1658 entries_to_write.push(EntryToWrite::SFN(entry));
1659
1660 let total_entries_needed = entries_to_write.len();
1661 // #[cfg(test)]
1662 // {
1663 // use crate::early_println;
1664 // early_println!("[FAT32] total entries needed: {}", total_entries_needed);
1665 // }
1666
1667 // Find space for all entries
1668 let mut current_cluster = dir_cluster;
1669
1670 // #[cfg(test)]
1671 // {
1672 // use crate::early_println;
1673 // early_println!("[FAT32] searching for space in cluster {} for {} entries", current_cluster, total_entries_needed);
1674 // }
1675
1676 loop {
1677 // Read the current cluster
1678 let mut cluster_data = self.read_cluster_data(current_cluster)?;
1679 // #[cfg(test)]
1680 // {
1681 // use crate::early_println;
1682 // early_println!("[FAT32] read directory cluster {} data: {} bytes", current_cluster, cluster_data.len());
1683 // }
1684
1685 // Look for consecutive empty slots
1686 let entries_per_cluster = (self.sectors_per_cluster * self.bytes_per_sector) / 32;
1687 // #[cfg(test)]
1688 // {
1689 // use crate::early_println;
1690 // early_println!("[FAT32] scanning {} directory entries for {} consecutive free slots",
1691 // entries_per_cluster, total_entries_needed);
1692 // }
1693
1694 for start_i in 0..entries_per_cluster {
1695 let start_offset = (start_i * 32) as usize;
1696 if start_offset + (total_entries_needed * 32) > cluster_data.len() {
1697 break;
1698 }
1699
1700 // Check if we have enough consecutive free slots
1701 let mut all_free = true;
1702 for j in 0..total_entries_needed {
1703 let offset = start_offset + (j * 32);
1704 if cluster_data[offset] != 0x00 && cluster_data[offset] != 0xE5 {
1705 all_free = false;
1706 break;
1707 }
1708 }
1709
1710 if all_free {
1711 // #[cfg(test)]
1712 // {
1713 // use crate::early_println;
1714 // early_println!("[FAT32] found {} consecutive free slots starting at entry {}, offset {}",
1715 // total_entries_needed, start_i, start_offset);
1716 // }
1717
1718 // Write all entries
1719 for (j, entry_to_write) in entries_to_write.iter().enumerate() {
1720 let offset = start_offset + (j * 32);
1721
1722 match entry_to_write {
1723 EntryToWrite::LFN(lfn_entry) => {
1724 let entry_bytes = unsafe {
1725 core::slice::from_raw_parts(
1726 lfn_entry as *const _ as *const u8,
1727 32,
1728 )
1729 };
1730 cluster_data[offset..offset + 32].copy_from_slice(entry_bytes);
1731
1732 // #[cfg(test)]
1733 // {
1734 // use crate::early_println;
1735 // early_println!("[FAT32] wrote LFN entry at offset {} in cluster {}", offset, current_cluster);
1736 // }
1737 }
1738 EntryToWrite::SFN(sfn_entry) => {
1739 let entry_bytes = unsafe {
1740 core::slice::from_raw_parts(
1741 sfn_entry as *const _ as *const u8,
1742 32,
1743 )
1744 };
1745 cluster_data[offset..offset + 32].copy_from_slice(entry_bytes);
1746
1747 // #[cfg(test)]
1748 // {
1749 // use crate::early_println;
1750 // early_println!("[FAT32] wrote SFN entry at offset {}, first 8 bytes: {:02x?}",
1751 // offset, &entry_bytes[0..8]);
1752 // }
1753 }
1754 }
1755 }
1756
1757 // Write the modified cluster back to disk
1758
1759 // #[cfg(test)]
1760 // {
1761 // use crate::early_println;
1762 // early_println!("[FAT32] writing modified directory cluster back to disk");
1763 // }
1764
1765 self.write_cluster_data(current_cluster, &cluster_data)?;
1766
1767 // #[cfg(test)]
1768 // {
1769 // use crate::early_println;
1770 // early_println!("[FAT32] write_directory_entry completed successfully");
1771 // }
1772
1773 return Ok(());
1774 }
1775 }
1776
1777 // #[cfg(test)]
1778 // {
1779 // use crate::early_println;
1780 // early_println!("[FAT32] no space found in cluster {}, checking next cluster", current_cluster);
1781 // }
1782
1783 // No space found in this cluster, check next cluster in chain
1784 let next_cluster = self.read_fat_entry(current_cluster)?;
1785 if next_cluster >= 0x0FFFFFF8 {
1786 // End of cluster chain, need to allocate new cluster
1787 // #[cfg(test)]
1788 // {
1789 // use crate::early_println;
1790 // early_println!("[FAT32] extending directory: allocating new cluster for cluster {}", current_cluster);
1791 // }
1792
1793 // Find a free cluster
1794 let new_cluster = self.allocate_cluster()?;
1795 // #[cfg(test)]
1796 // {
1797 // use crate::early_println;
1798 // early_println!("[FAT32] allocated new cluster {} for directory extension", new_cluster);
1799 // }
1800 // Link the new cluster to the directory chain
1801 self.write_fat_entry(current_cluster, new_cluster)?;
1802 // #[cfg(test)]
1803 // {
1804 // use crate::early_println;
1805 // early_println!("[FAT32] linked cluster {} -> {}", current_cluster, new_cluster);
1806 // }
1807
1808 // Mark the new cluster as end of chain
1809 self.write_fat_entry(new_cluster, 0x0FFFFFFF)?;
1810 // #[cfg(test)]
1811 // {
1812 // use crate::early_println;
1813 // early_println!("[FAT32] marked cluster {} as end of chain", new_cluster);
1814 // }
1815
1816 // Clear the new cluster (fill with zeros)
1817 let cluster_size = (self.sectors_per_cluster * self.bytes_per_sector) as usize;
1818 let mut empty_cluster = vec![0u8; cluster_size];
1819
1820 // Write all entries to the new cluster
1821 for (j, entry_to_write) in entries_to_write.iter().enumerate() {
1822 let offset = j * 32;
1823
1824 match entry_to_write {
1825 EntryToWrite::LFN(lfn_entry) => {
1826 let entry_bytes = unsafe {
1827 core::slice::from_raw_parts(lfn_entry as *const _ as *const u8, 32)
1828 };
1829 empty_cluster[offset..offset + 32].copy_from_slice(entry_bytes);
1830
1831 // #[cfg(test)]
1832 // {
1833 // use crate::early_println;
1834 // early_println!("[FAT32] wrote LFN entry at offset {} in new cluster", offset);
1835 // }
1836 }
1837 EntryToWrite::SFN(sfn_entry) => {
1838 let entry_bytes = unsafe {
1839 core::slice::from_raw_parts(sfn_entry as *const _ as *const u8, 32)
1840 };
1841 empty_cluster[offset..offset + 32].copy_from_slice(entry_bytes);
1842
1843 // #[cfg(test)]
1844 // {
1845 // use crate::early_println;
1846 // early_println!("[FAT32] wrote SFN entry at offset {} in new cluster, first 8 bytes: {:02x?}",
1847 // offset, &entry_bytes[0..8]);
1848 // }
1849 }
1850 }
1851 }
1852
1853 // Write the entries to the new cluster
1854 self.write_cluster_data(new_cluster, &empty_cluster)?;
1855 // early_println!("[FAT32] wrote directory entries to new cluster {}", new_cluster);
1856
1857 return Ok(());
1858 }
1859 current_cluster = next_cluster;
1860 }
1861 }
1862
1863 /// Update an existing directory entry in the specified directory cluster
1864 /// Supports both LFN and SFN matching
1865 pub fn update_directory_entry(
1866 &self,
1867 dir_cluster: u32,
1868 filename: &str,
1869 entry: &structures::Fat32DirectoryEntry,
1870 ) -> Result<(), FileSystemError> {
1871 // early_println!("[FAT32] update_directory_entry: searching for '{}' in cluster {}", filename, dir_cluster);
1872
1873 let mut current_cluster = dir_cluster;
1874
1875 loop {
1876 // Read the current cluster
1877 let mut cluster_data = self.read_cluster_data(current_cluster)?;
1878
1879 // Parse directory entries in this cluster
1880 let entries_per_cluster = (self.sectors_per_cluster * self.bytes_per_sector) / 32;
1881 let mut lfn_parts: Vec<String> = Vec::new();
1882 let mut found_entry_offset: Option<usize> = None;
1883 let mut lfn_start_offset: Option<usize> = None;
1884
1885 for i in 0..entries_per_cluster {
1886 let offset = (i * 32) as usize;
1887 if offset + 32 > cluster_data.len() {
1888 break;
1889 }
1890
1891 let entry_bytes = &cluster_data[offset..offset + 32];
1892
1893 // Safety: We know the slice is exactly 32 bytes (size of Fat32DirectoryEntry)
1894 let existing_entry = unsafe {
1895 core::ptr::read(entry_bytes.as_ptr() as *const structures::Fat32DirectoryEntry)
1896 };
1897
1898 // Skip free entries
1899 if existing_entry.is_free() {
1900 lfn_parts.clear();
1901 lfn_start_offset = None;
1902 continue;
1903 }
1904
1905 // Handle LFN entries
1906 if existing_entry.is_long_filename() {
1907 let lfn_entry =
1908 unsafe { &*(entry_bytes.as_ptr() as *const structures::Fat32LFNEntry) };
1909
1910 // Extract characters from this LFN entry
1911 let chars = lfn_entry.extract_chars();
1912
1913 // Convert UTF-16 to UTF-8
1914 let mut part = String::new();
1915 for &ch in &chars {
1916 if ch == 0 || ch == 0xFFFF {
1917 break;
1918 }
1919 if let Some(c) = char::from_u32(ch as u32) {
1920 part.push(c);
1921 }
1922 }
1923
1924 // LFN entries are stored with highest sequence number first
1925 if lfn_entry.is_last_lfn() {
1926 // This is the first LFN entry we encounter (which contains the last part)
1927 lfn_parts.clear();
1928 lfn_parts.push(part);
1929 lfn_start_offset = Some(offset);
1930 } else {
1931 // This is a subsequent LFN entry (which contains earlier parts)
1932 lfn_parts.push(part);
1933 if lfn_start_offset.is_none() {
1934 lfn_start_offset = Some(offset);
1935 }
1936 }
1937 continue;
1938 }
1939
1940 // Skip dot entries
1941 if existing_entry.name[0] == b'.' {
1942 lfn_parts.clear();
1943 lfn_start_offset = None;
1944 continue;
1945 }
1946
1947 // This is a regular directory entry (SFN)
1948 let sfn_filename = existing_entry.filename();
1949 let full_filename = if !lfn_parts.is_empty() {
1950 // Reverse the parts since LFN entries are stored in reverse order
1951 lfn_parts.reverse();
1952 lfn_parts.join("")
1953 } else {
1954 sfn_filename.clone()
1955 };
1956
1957 // #[cfg(test)]
1958 // {
1959 // use crate::early_println;
1960 // early_println!("[FAT32] checking entry: sfn='{}', lfn='{}', looking_for='{}'",
1961 // sfn_filename, full_filename, filename);
1962 // }
1963
1964 // Check if this matches the filename we're looking for
1965 let matches = full_filename == filename
1966 || sfn_filename == filename
1967 || full_filename.to_lowercase() == filename.to_lowercase()
1968 || sfn_filename.to_lowercase() == filename.to_lowercase();
1969
1970 if matches {
1971 // early_println!("[FAT32] found matching entry at offset {}, updating cluster and size", offset);
1972
1973 // Parse the existing entry to preserve its SFN and other metadata
1974 let mut existing_entry = existing_entry; // Use the already parsed entry
1975
1976 // Update only the cluster and file size fields
1977 existing_entry.update_cluster_and_size(entry.cluster(), entry.file_size);
1978
1979 // Write the updated entry back
1980 let updated_entry_bytes = unsafe {
1981 core::slice::from_raw_parts(&existing_entry as *const _ as *const u8, 32)
1982 };
1983 cluster_data[offset..offset + 32].copy_from_slice(updated_entry_bytes);
1984 found_entry_offset = Some(offset);
1985 break;
1986 }
1987
1988 // Clear LFN accumulation for next entry
1989 lfn_parts.clear();
1990 lfn_start_offset = None;
1991 }
1992
1993 if found_entry_offset.is_some() {
1994 // Write the modified cluster back to disk
1995 self.write_cluster_data(current_cluster, &cluster_data)?;
1996 // early_println!("[FAT32] directory entry updated successfully");
1997 return Ok(());
1998 }
1999
2000 // Get next cluster in the chain
2001 let next_cluster = self.read_fat_entry(current_cluster)?;
2002 if next_cluster >= 0x0FFFFFF8 {
2003 // End of cluster chain
2004 break;
2005 }
2006 current_cluster = next_cluster;
2007 }
2008
2009 // early_println!("[FAT32] directory entry for '{}' not found for update", filename);
2010 Err(FileSystemError::new(
2011 FileSystemErrorKind::NotFound,
2012 &format!("Directory entry for '{}' not found for update", filename),
2013 ))
2014 }
2015
2016 /// Check if a filename requires LFN (Long File Name) entries
2017 fn requires_lfn(filename: &str) -> bool {
2018 // LFN is required if:
2019 // 1. Filename is longer than 8.3 format
2020 // 2. Filename contains invalid SFN characters
2021 // 3. Extension is longer than 3 characters
2022 // 4. Filename contains spaces or other special characters not allowed in SFN
2023
2024 // #[cfg(test)]
2025 // {
2026 // use crate::early_println;
2027 // early_println!("[FAT32] checking requires_lfn for '{}'", filename);
2028 // }
2029
2030 // Quick check for obvious LFN cases
2031 if filename.contains(' ') || filename.contains('+') || filename.contains(',') {
2032 // #[cfg(test)]
2033 // {
2034 // use crate::early_println;
2035 // early_println!("[FAT32] requires_lfn('{}') = true (contains special chars)", filename);
2036 // }
2037 return true;
2038 }
2039
2040 if let Some(dot_pos) = filename.rfind('.') {
2041 let name_part = &filename[..dot_pos];
2042 let ext_part = &filename[dot_pos + 1..];
2043
2044 // Check name part and extension length
2045 if name_part.len() > 8 || ext_part.len() > 3 {
2046 // #[cfg(test)]
2047 // {
2048 // use crate::early_println;
2049 // early_println!("[FAT32] requires_lfn('{}') = true (length: name={}, ext={})", filename, name_part.len(), ext_part.len());
2050 // }
2051 return true;
2052 }
2053
2054 // Check for invalid SFN characters (valid: A-Z, a-z, 0-9, ! # $ % & ' ( ) - @ ^ _ ` { } ~)
2055 if name_part.chars().any(|c| !Self::is_valid_sfn_char(c))
2056 || ext_part.chars().any(|c| !Self::is_valid_sfn_char(c))
2057 {
2058 // #[cfg(test)]
2059 // {
2060 // use crate::early_println;
2061 // early_println!("[FAT32] requires_lfn('{}') = true (invalid SFN chars)", filename);
2062 // }
2063 return true;
2064 }
2065 } else {
2066 // No extension - just check name length and characters
2067 if filename.len() > 8 {
2068 // #[cfg(test)]
2069 // {
2070 // use crate::early_println;
2071 // early_println!("[FAT32] requires_lfn('{}') = true (no ext, length={})", filename, filename.len());
2072 // }
2073 return true;
2074 }
2075
2076 // Check for invalid SFN characters (valid: A-Z, a-z, 0-9, ! # $ % & ' ( ) - @ ^ _ ` { } ~)
2077 if filename.chars().any(|c| !Self::is_valid_sfn_char(c)) {
2078 // #[cfg(test)]
2079 // {
2080 // use crate::early_println;
2081 // early_println!("[FAT32] requires_lfn('{}') = true (invalid SFN chars)", filename);
2082 // }
2083 return true;
2084 }
2085 }
2086
2087 // #[cfg(test)]
2088 // {
2089 // use crate::early_println;
2090 // early_println!("[FAT32] requires_lfn('{}') = false (valid 8.3 format)", filename);
2091 // }
2092
2093 false
2094 }
2095
2096 /// Generate LFN entries for a given filename
2097 fn generate_lfn_entries(filename: &str, sfn_checksum: u8) -> Vec<structures::Fat32LFNEntry> {
2098 let mut entries = Vec::new();
2099 let chars: Vec<u16> = filename.encode_utf16().collect();
2100
2101 // Each LFN entry can hold 13 characters
2102 let entries_needed = (chars.len() + 12) / 13; // Round up division
2103
2104 for entry_num in 0..entries_needed {
2105 let start_idx = entry_num * 13;
2106
2107 let mut lfn_entry = structures::Fat32LFNEntry {
2108 sequence: (entry_num + 1) as u8,
2109 name1: [0xFFFF; 5],
2110 attributes: 0x0F, // LFN attribute
2111 entry_type: 0,
2112 checksum: sfn_checksum,
2113 name2: [0xFFFF; 6],
2114 cluster: 0,
2115 name3: [0xFFFF; 2],
2116 };
2117
2118 // Mark last entry
2119 if entry_num == entries_needed - 1 {
2120 lfn_entry.sequence |= 0x40; // Last LFN entry flag
2121 }
2122
2123 // Fill in characters
2124 let mut char_idx = start_idx;
2125
2126 // Fill name1 (5 characters)
2127 for i in 0..5 {
2128 if char_idx < chars.len() {
2129 lfn_entry.name1[i] = chars[char_idx];
2130 char_idx += 1;
2131 } else if char_idx == chars.len() {
2132 lfn_entry.name1[i] = 0x0000; // Null terminator
2133 char_idx += 1;
2134 } else {
2135 lfn_entry.name1[i] = 0xFFFF; // Padding
2136 }
2137 }
2138
2139 // Fill name2 (6 characters)
2140 for i in 0..6 {
2141 if char_idx < chars.len() {
2142 lfn_entry.name2[i] = chars[char_idx];
2143 char_idx += 1;
2144 } else if char_idx == chars.len() {
2145 lfn_entry.name2[i] = 0x0000; // Null terminator
2146 char_idx += 1;
2147 } else {
2148 lfn_entry.name2[i] = 0xFFFF; // Padding
2149 }
2150 }
2151
2152 // Fill name3 (2 characters)
2153 for i in 0..2 {
2154 if char_idx < chars.len() {
2155 lfn_entry.name3[i] = chars[char_idx];
2156 char_idx += 1;
2157 } else if char_idx == chars.len() {
2158 lfn_entry.name3[i] = 0x0000; // Null terminator
2159 char_idx += 1;
2160 } else {
2161 lfn_entry.name3[i] = 0xFFFF; // Padding
2162 }
2163 }
2164
2165 entries.push(lfn_entry);
2166 }
2167
2168 // LFN entries need to be in reverse order (last entry first)
2169 entries.reverse();
2170 entries
2171 }
2172
2173 /// Calculate checksum for SFN (used in LFN entries)
2174 fn calculate_sfn_checksum(sfn: &[u8; 11]) -> u8 {
2175 let mut checksum = 0u8;
2176 for &byte in sfn {
2177 checksum = ((checksum & 1) << 7)
2178 .wrapping_add(checksum >> 1)
2179 .wrapping_add(byte);
2180 }
2181 checksum
2182 }
2183
2184 /// Remove a directory entry from the specified directory cluster
2185 fn remove_directory_entry(
2186 &self,
2187 dir_cluster: u32,
2188 filename: &str,
2189 ) -> Result<(), FileSystemError> {
2190 let entries_per_cluster = (self.sectors_per_cluster * self.bytes_per_sector) / 32;
2191 let mut current_cluster = dir_cluster;
2192
2193 // #[cfg(test)]
2194 // {
2195 // use crate::early_println;
2196 // early_println!("[FAT32] remove_directory_entry: searching for '{}' in cluster {}", filename, dir_cluster);
2197 // }
2198
2199 loop {
2200 let mut cluster_data = self.read_cluster_data(current_cluster)?;
2201 let mut entries_to_remove = Vec::new();
2202 let mut i = 0;
2203
2204 while i < entries_per_cluster {
2205 let entry_offset = (i * 32) as usize;
2206 if entry_offset + 32 > cluster_data.len() {
2207 break;
2208 }
2209
2210 let entry_bytes = &cluster_data[entry_offset..entry_offset + 32];
2211
2212 // Check if this is the end of directory
2213 if entry_bytes[0] == 0x00 {
2214 break;
2215 }
2216
2217 // Skip free entries
2218 if entry_bytes[0] == 0xE5 {
2219 i += 1;
2220 continue;
2221 }
2222
2223 // Check if this is an LFN entry
2224 if entry_bytes[11] == 0x0F {
2225 // This is an LFN entry - we'll need to handle LFN chains later
2226 i += 1;
2227 continue;
2228 }
2229
2230 // This is a regular SFN entry
2231 let dir_entry = unsafe {
2232 core::ptr::read_unaligned(
2233 entry_bytes.as_ptr() as *const structures::Fat32DirectoryEntry
2234 )
2235 };
2236
2237 let entry_filename = dir_entry.filename().to_lowercase();
2238
2239 // Also check if this entry has LFN entries and read the long filename
2240 let mut full_filename = entry_filename.clone();
2241
2242 // Look backwards for LFN entries that belong to this SFN
2243 let mut lfn_start = i;
2244 let mut lfn_name = String::new();
2245
2246 // Find the start of LFN entries
2247 for j in (0..i).rev() {
2248 let lfn_offset = (j * 32) as usize;
2249 let lfn_bytes = &cluster_data[lfn_offset..lfn_offset + 32];
2250
2251 // Check if this is an LFN entry
2252 if lfn_bytes[11] == 0x0F {
2253 lfn_start = j;
2254 } else {
2255 break;
2256 }
2257 }
2258
2259 // If we found LFN entries, reconstruct the full filename
2260 if lfn_start < i {
2261 let mut lfn_entries = Vec::new();
2262
2263 // Collect all LFN entries
2264 for j in lfn_start..i {
2265 let lfn_offset = (j * 32) as usize;
2266 let lfn_bytes = &cluster_data[lfn_offset..lfn_offset + 32];
2267
2268 if lfn_bytes[11] == 0x0F {
2269 let lfn_entry = unsafe {
2270 core::ptr::read_unaligned(
2271 lfn_bytes.as_ptr() as *const structures::Fat32LFNEntry
2272 )
2273 };
2274 lfn_entries.push(lfn_entry);
2275 }
2276 }
2277
2278 // Sort LFN entries by their sequence number (ascending order)
2279 lfn_entries.sort_by(|a, b| {
2280 let seq_a = a.sequence & 0x1F; // Remove last entry flag
2281 let seq_b = b.sequence & 0x1F;
2282 seq_a.cmp(&seq_b) // Ascending order (lowest sequence first)
2283 });
2284
2285 // Reconstruct the filename from sorted LFN entries
2286 for lfn_entry in lfn_entries {
2287 // Extract characters from name1, name2, name3
2288 for k in 0..5 {
2289 let ch = lfn_entry.name1[k];
2290 if ch != 0x0000 && ch != 0xFFFF {
2291 if let Some(c) = char::from_u32(ch as u32) {
2292 lfn_name.push(c);
2293 }
2294 } else {
2295 break;
2296 }
2297 }
2298 for k in 0..6 {
2299 let ch = lfn_entry.name2[k];
2300 if ch != 0x0000 && ch != 0xFFFF {
2301 if let Some(c) = char::from_u32(ch as u32) {
2302 lfn_name.push(c);
2303 }
2304 } else {
2305 break;
2306 }
2307 }
2308 for k in 0..2 {
2309 let ch = lfn_entry.name3[k];
2310 if ch != 0x0000 && ch != 0xFFFF {
2311 if let Some(c) = char::from_u32(ch as u32) {
2312 lfn_name.push(c);
2313 }
2314 } else {
2315 break;
2316 }
2317 }
2318 }
2319
2320 if !lfn_name.is_empty() {
2321 full_filename = lfn_name;
2322 }
2323 }
2324
2325 #[cfg(test)]
2326 {
2327 use crate::early_println;
2328 early_println!(
2329 "[FAT32] checking entry: sfn='{}', lfn='{}', looking_for='{}'",
2330 entry_filename,
2331 full_filename,
2332 filename
2333 );
2334 }
2335
2336 // Check both SFN and LFN
2337 if entry_filename == filename.to_lowercase() || full_filename == filename {
2338 // #[cfg(test)]
2339 // {
2340 // use crate::early_println;
2341 // early_println!("[FAT32] found matching entry at offset {}", entry_offset);
2342 // }
2343
2344 // Mark all entries (LFN + SFN) for removal
2345 for remove_i in lfn_start..=i {
2346 entries_to_remove.push(remove_i);
2347 }
2348
2349 break;
2350 }
2351
2352 i += 1;
2353 }
2354
2355 // Remove the entries by marking them as deleted (0xE5)
2356 if !entries_to_remove.is_empty() {
2357 for &remove_i in &entries_to_remove {
2358 let entry_offset = (remove_i * 32) as usize;
2359 cluster_data[entry_offset] = 0xE5; // Mark as deleted
2360
2361 // #[cfg(test)]
2362 // {
2363 // use crate::early_println;
2364 // early_println!("[FAT32] marked entry {} as deleted at offset {}", remove_i, entry_offset);
2365 // }
2366 }
2367
2368 // Write the modified cluster back to disk
2369 self.write_cluster_data(current_cluster, &cluster_data)?;
2370
2371 // #[cfg(test)]
2372 // {
2373 // use crate::early_println;
2374 // early_println!("[FAT32] remove_directory_entry completed successfully");
2375 // }
2376
2377 return Ok(());
2378 }
2379
2380 // Move to next cluster in chain
2381 let next_cluster = self.read_fat_entry(current_cluster)?;
2382 if next_cluster >= 0x0FFFFFF8 || next_cluster == 0 {
2383 break;
2384 }
2385 current_cluster = next_cluster;
2386 }
2387
2388 // File not found
2389 Err(FileSystemError::new(
2390 FileSystemErrorKind::NotFound,
2391 format!("Directory entry '{}' not found", filename),
2392 ))
2393 }
2394
2395 /// Generate a FAT32-compliant SFN (Short File Name) from a long filename
2396 /// This implementation follows the Microsoft FAT32 specification
2397 fn generate_sfn(filename: &str, numeric_tail: Option<u32>) -> [u8; 11] {
2398 let mut sfn = [b' '; 11];
2399
2400 // Convert to uppercase and filter invalid characters
2401 let clean_filename = filename.to_uppercase();
2402
2403 // Split into name and extension
2404 let (name_part, ext_part) = if let Some(dot_pos) = clean_filename.rfind('.') {
2405 (
2406 &clean_filename[..dot_pos],
2407 Some(&clean_filename[dot_pos + 1..]),
2408 )
2409 } else {
2410 (clean_filename.as_str(), None)
2411 };
2412
2413 // Generate the name part (first 8 characters)
2414 let mut name_chars = Vec::new();
2415 for ch in name_part.chars() {
2416 if Self::is_valid_sfn_char(ch) {
2417 name_chars.push(ch as u8);
2418 } else if ch == ' ' {
2419 // Skip spaces
2420 continue;
2421 } else {
2422 // Replace invalid characters with underscore
2423 name_chars.push(b'_');
2424 }
2425 }
2426
2427 // Handle numeric tail for duplicate names (~1, ~2, etc.)
2428 let base_name_len = if let Some(tail) = numeric_tail {
2429 let tail_str = format!("~{}", tail);
2430 let max_base_len = 8 - tail_str.len();
2431 core::cmp::min(name_chars.len(), max_base_len)
2432 } else {
2433 core::cmp::min(name_chars.len(), 8)
2434 };
2435
2436 // Copy base name
2437 for i in 0..base_name_len {
2438 sfn[i] = name_chars[i];
2439 }
2440
2441 // Add numeric tail if present
2442 if let Some(tail) = numeric_tail {
2443 let tail_str = format!("~{}", tail);
2444 let tail_bytes = tail_str.as_bytes();
2445 for (i, &byte) in tail_bytes.iter().enumerate() {
2446 if base_name_len + i < 8 {
2447 sfn[base_name_len + i] = byte;
2448 }
2449 }
2450 }
2451
2452 // Handle extension part
2453 if let Some(ext) = ext_part {
2454 let mut ext_chars = Vec::new();
2455 for ch in ext.chars().take(3) {
2456 // Max 3 characters for extension
2457 if Self::is_valid_sfn_char(ch) {
2458 ext_chars.push(ch as u8);
2459 } else if ch != ' ' {
2460 ext_chars.push(b'_');
2461 }
2462 }
2463
2464 // Copy extension
2465 for (i, &byte) in ext_chars.iter().enumerate() {
2466 if i < 3 {
2467 sfn[8 + i] = byte;
2468 }
2469 }
2470 }
2471
2472 sfn
2473 }
2474
2475 /// Check if a character is valid for SFN according to FAT32 specification
2476 fn is_valid_sfn_char(ch: char) -> bool {
2477 match ch {
2478 'A'..='Z' | 'a'..='z' | '0'..='9' => true,
2479 '!' | '#' | '$' | '%' | '&' | '\'' | '(' | ')' | '-' | '@' | '^' | '_' | '`' | '{'
2480 | '}' | '~' => true,
2481 _ => false,
2482 }
2483 }
2484
2485 /// Check if filename needs numeric tail (Linux-style behavior)
2486 /// Returns true ONLY for filenames that cannot fit in 8.3 format or contain invalid characters
2487 fn filename_needs_numeric_tail(&self, filename: &str) -> bool {
2488 // Find the last dot to separate name and extension
2489 if let Some(dot_pos) = filename.rfind('.') {
2490 let main_name = &filename[..dot_pos];
2491 let extension = &filename[dot_pos + 1..];
2492
2493 // #[cfg(test)]
2494 // {
2495 // use crate::early_println;
2496 // early_println!("[FAT32] analyzing filename: '{}' -> name='{}' ({} chars), ext='{}' ({} chars)",
2497 // filename, main_name, main_name.len(), extension, extension.len());
2498 // }
2499
2500 // Check if main name is longer than 8 chars or extension longer than 3 chars
2501 if main_name.len() > 8 || extension.len() > 3 {
2502 // #[cfg(test)]
2503 // {
2504 // use crate::early_println;
2505 // early_println!("[FAT32] filename_needs_numeric_tail: '{}' -> true (length exceeded)", filename);
2506 // }
2507 return true;
2508 }
2509
2510 // Check main name for invalid characters
2511 for ch in main_name.chars() {
2512 if ch == ' '
2513 || ch == '+'
2514 || ch == '='
2515 || ch == '['
2516 || ch == ']'
2517 || ch == ','
2518 || ch == ';'
2519 {
2520 #[cfg(test)]
2521 {
2522 use crate::early_println;
2523 early_println!(
2524 "[FAT32] filename_needs_numeric_tail: '{}' -> true (invalid char in name: '{}')",
2525 filename,
2526 ch
2527 );
2528 }
2529 return true;
2530 }
2531 }
2532
2533 // Check extension for invalid characters
2534 for ch in extension.chars() {
2535 if ch == ' '
2536 || ch == '+'
2537 || ch == '='
2538 || ch == '['
2539 || ch == ']'
2540 || ch == ','
2541 || ch == ';'
2542 {
2543 #[cfg(test)]
2544 {
2545 use crate::early_println;
2546 early_println!(
2547 "[FAT32] filename_needs_numeric_tail: '{}' -> true (invalid char in ext: '{}')",
2548 filename,
2549 ch
2550 );
2551 }
2552 return true;
2553 }
2554 }
2555 } else {
2556 // No extension - check if name is longer than 8 chars
2557 if filename.len() > 8 {
2558 // #[cfg(test)]
2559 // {
2560 // use crate::early_println;
2561 // early_println!("[FAT32] filename_needs_numeric_tail: '{}' -> true (no ext, length={})", filename, filename.len());
2562 // }
2563 return true;
2564 }
2565
2566 // Check for invalid characters
2567 for ch in filename.chars() {
2568 if ch == ' '
2569 || ch == '+'
2570 || ch == '='
2571 || ch == '['
2572 || ch == ']'
2573 || ch == ','
2574 || ch == ';'
2575 {
2576 #[cfg(test)]
2577 {
2578 use crate::early_println;
2579 early_println!(
2580 "[FAT32] filename_needs_numeric_tail: '{}' -> true (invalid char: '{}')",
2581 filename,
2582 ch
2583 );
2584 }
2585 return true;
2586 }
2587 }
2588 }
2589
2590 #[cfg(test)]
2591 {
2592 use crate::early_println;
2593 early_println!(
2594 "[FAT32] filename_needs_numeric_tail: '{}' -> false (fits in 8.3)",
2595 filename
2596 );
2597 }
2598 false
2599 }
2600
2601 /// Generate a unique SFN by checking for duplicates in the directory
2602 fn generate_unique_sfn(
2603 &self,
2604 dir_cluster: u32,
2605 desired_filename: &str,
2606 ) -> Result<[u8; 11], FileSystemError> {
2607 // Check if the filename needs numeric tail (Linux-style: long names get ~1 from start)
2608 let needs_tail = self.filename_needs_numeric_tail(desired_filename);
2609
2610 if !needs_tail {
2611 // Short filename that fits in 8.3 - try without tail first
2612 let base_sfn = Self::generate_sfn(desired_filename, None);
2613 if !self.sfn_exists_in_directory(dir_cluster, &base_sfn)? {
2614 return Ok(base_sfn);
2615 }
2616 }
2617
2618 // Try with numeric tails ~1, ~2, ..., ~999999 (Linux-style)
2619 for tail in 1..=999999 {
2620 let sfn_with_tail = Self::generate_sfn(desired_filename, Some(tail));
2621
2622 if !self.sfn_exists_in_directory(dir_cluster, &sfn_with_tail)? {
2623 return Ok(sfn_with_tail);
2624 }
2625 }
2626
2627 Err(FileSystemError::new(
2628 FileSystemErrorKind::NoSpace,
2629 "Cannot generate unique SFN: too many similar filenames",
2630 ))
2631 }
2632
2633 /// Check if an SFN already exists in the specified directory
2634 fn sfn_exists_in_directory(
2635 &self,
2636 dir_cluster: u32,
2637 sfn: &[u8; 11],
2638 ) -> Result<bool, FileSystemError> {
2639 let mut current_cluster = dir_cluster;
2640 let entries_per_cluster = (self.sectors_per_cluster * self.bytes_per_sector / 32) as usize;
2641
2642 loop {
2643 let cluster_data = self.read_cluster_data(current_cluster)?;
2644
2645 for i in 0..entries_per_cluster {
2646 let entry_offset = i * 32;
2647 if entry_offset + 32 > cluster_data.len() {
2648 break;
2649 }
2650
2651 let entry_bytes = &cluster_data[entry_offset..entry_offset + 32];
2652
2653 // End of directory
2654 if entry_bytes[0] == 0x00 {
2655 return Ok(false);
2656 }
2657
2658 // Skip free entries and LFN entries
2659 if entry_bytes[0] == 0xE5 || entry_bytes[11] == 0x0F {
2660 continue;
2661 }
2662
2663 // Compare SFN
2664 let existing_sfn = &entry_bytes[0..11];
2665 if existing_sfn == sfn {
2666 return Ok(true);
2667 }
2668 }
2669
2670 // Move to next cluster in chain
2671 let next_cluster = self.read_fat_entry(current_cluster)?;
2672 if next_cluster >= 0x0FFFFFF8 {
2673 break;
2674 }
2675 current_cluster = next_cluster;
2676 }
2677
2678 Ok(false)
2679 }
2680}
2681
2682impl FileSystemOperations for Fat32FileSystem {
2683 fn fs_id(&self) -> FileSystemId {
2684 self.fs_id
2685 }
2686
2687 fn lookup(
2688 &self,
2689 parent: &Arc<dyn VfsNode>,
2690 name: &String,
2691 ) -> Result<Arc<dyn VfsNode>, FileSystemError> {
2692 let fat32_parent = parent.as_any().downcast_ref::<Fat32Node>().ok_or_else(|| {
2693 FileSystemError::new(
2694 FileSystemErrorKind::NotSupported,
2695 "Invalid node type for FAT32",
2696 )
2697 })?;
2698
2699 // Check if it's a directory
2700 match fat32_parent.file_type() {
2701 Ok(FileType::Directory) => {}
2702 Ok(_) => {
2703 return Err(FileSystemError::new(
2704 FileSystemErrorKind::NotADirectory,
2705 "Parent is not a directory",
2706 ));
2707 }
2708 Err(e) => return Err(e),
2709 }
2710
2711 // Get the starting cluster for the directory
2712 let parent_cluster = *fat32_parent.cluster.read();
2713 let starting_cluster = if parent_cluster == 0 {
2714 self.boot_sector.root_cluster
2715 } else {
2716 parent_cluster
2717 };
2718
2719 // Search for the file in the directory
2720 let found_entry = self.lookup_file_in_directory(starting_cluster, name)?;
2721 // Create a new Fat32Node for the found entry
2722 let node = if found_entry.is_directory() {
2723 let dir_node = Fat32Node::new_directory(
2724 found_entry.name(),
2725 found_entry.cluster() as u64,
2726 found_entry.cluster(),
2727 );
2728 // Set filesystem reference from parent
2729 if let Some(fs_ref) = fat32_parent.filesystem() {
2730 dir_node.set_filesystem(fs_ref);
2731 }
2732 dir_node
2733 } else {
2734 let file_node = Fat32Node::new_file(
2735 found_entry.name(),
2736 found_entry.cluster() as u64,
2737 found_entry.cluster(),
2738 );
2739 // Update file size
2740 {
2741 let mut metadata = file_node.metadata.write();
2742 metadata.size = found_entry.size() as usize;
2743 }
2744 // Set filesystem reference from parent
2745 if let Some(fs_ref) = fat32_parent.filesystem() {
2746 file_node.set_filesystem(fs_ref);
2747 }
2748 file_node
2749 };
2750
2751 Ok(Arc::new(node))
2752 }
2753
2754 fn open(
2755 &self,
2756 node: &Arc<dyn VfsNode>,
2757 _flags: u32,
2758 ) -> Result<Arc<dyn FileObject>, FileSystemError> {
2759 let fat32_node = node.as_any().downcast_ref::<Fat32Node>().ok_or_else(|| {
2760 FileSystemError::new(
2761 FileSystemErrorKind::NotSupported,
2762 "Invalid node type for FAT32",
2763 )
2764 })?;
2765
2766 match fat32_node.file_type() {
2767 Ok(FileType::RegularFile) => {
2768 // Get parent from parent node
2769 let parent_cluster = if let Some(parent_ref) = fat32_node.parent.read().as_ref() {
2770 if let Some(parent_node) = parent_ref.upgrade() {
2771 *parent_node.cluster.read()
2772 } else {
2773 0 // Default to 0 if parent is not available
2774 }
2775 } else {
2776 0 // Default to 0 if no parent reference
2777 };
2778
2779 Ok(Arc::new(Fat32FileObject::new(
2780 Arc::new(fat32_node.clone()),
2781 parent_cluster,
2782 )))
2783 }
2784 Ok(FileType::Directory) => Ok(Arc::new(Fat32DirectoryObject::new(Arc::new(
2785 fat32_node.clone(),
2786 )))),
2787 Ok(_) => Err(FileSystemError::new(
2788 FileSystemErrorKind::NotSupported,
2789 "Unsupported file type",
2790 )),
2791 Err(e) => Err(e),
2792 }
2793 }
2794
2795 fn create(
2796 &self,
2797 parent: &Arc<dyn VfsNode>,
2798 name: &String,
2799 file_type: FileType,
2800 _mode: u32,
2801 ) -> Result<Arc<dyn VfsNode>, FileSystemError> {
2802 let fat32_parent = parent.as_any().downcast_ref::<Fat32Node>().ok_or_else(|| {
2803 FileSystemError::new(
2804 FileSystemErrorKind::NotSupported,
2805 "Invalid node type for FAT32",
2806 )
2807 })?;
2808
2809 // Check if it's a directory
2810 match fat32_parent.file_type() {
2811 Ok(FileType::Directory) => {}
2812 Ok(_) => {
2813 return Err(FileSystemError::new(
2814 FileSystemErrorKind::NotADirectory,
2815 "Parent is not a directory",
2816 ));
2817 }
2818 Err(e) => return Err(e),
2819 }
2820
2821 // Check if file already exists (FAT32 is case-insensitive)
2822 let parent_cluster = *fat32_parent.cluster.read();
2823 let actual_parent_cluster = if parent_cluster == 0 {
2824 self.root_cluster // Use root cluster for root directory
2825 } else {
2826 parent_cluster
2827 };
2828
2829 // Check on disk for case-insensitive duplicates
2830 if let Ok(_existing_entry) = self.lookup_file_in_directory(actual_parent_cluster, name) {
2831 return Err(FileSystemError::new(
2832 FileSystemErrorKind::AlreadyExists,
2833 format!("File '{}' already exists (case-insensitive)", name),
2834 ));
2835 }
2836
2837 // Create new node
2838 let file_id = self.generate_file_id();
2839 let new_node = match file_type {
2840 FileType::RegularFile => {
2841 Arc::new(Fat32Node::new_file(name.clone(), file_id, 0)) // No cluster allocated yet
2842 }
2843 FileType::Directory => {
2844 // Allocate cluster for directory
2845 let dir_cluster = self.allocate_cluster().map_err(|e| {
2846 FileSystemError::new(
2847 FileSystemErrorKind::NoSpace,
2848 format!("Failed to allocate cluster for directory: {:?}", e),
2849 )
2850 })?;
2851
2852 // Initialize directory with . and .. entries
2853 self.initialize_directory(dir_cluster, actual_parent_cluster)?;
2854
2855 Arc::new(Fat32Node::new_directory(name.clone(), file_id, dir_cluster))
2856 }
2857 _ => {
2858 return Err(FileSystemError::new(
2859 FileSystemErrorKind::NotSupported,
2860 "Unsupported file type for FAT32",
2861 ));
2862 }
2863 };
2864
2865 // Set filesystem reference using the parent's filesystem
2866 if let Some(fs) = fat32_parent.filesystem() {
2867 if let Some(fs_strong) = fs.upgrade() {
2868 let fs_weak = Arc::downgrade(&fs_strong);
2869 new_node.set_filesystem(fs_weak);
2870 }
2871 }
2872
2873 // Set parent reference
2874 {
2875 let parent_arc: Arc<Fat32Node> = Arc::new(fat32_parent.clone());
2876 let parent_weak = Arc::downgrade(&parent_arc);
2877 *new_node.parent.write() = Some(parent_weak);
2878 }
2879
2880 // Write directory entry to the parent directory's cluster
2881 let parent_cluster = *fat32_parent.cluster.read();
2882 let actual_parent_cluster = if parent_cluster == 0 {
2883 self.root_cluster // Use root cluster for root directory
2884 } else {
2885 parent_cluster
2886 };
2887
2888 // #[cfg(test)]
2889 // {
2890 // use crate::early_println;
2891 // early_println!("[FAT32] Creating file '{}' in parent cluster {} (original: {})",
2892 // name, actual_parent_cluster, parent_cluster);
2893 // }
2894
2895 // Write directory entry to disk
2896 let node_cluster = match file_type {
2897 FileType::Directory => {
2898 // Get the cluster number from the created directory node
2899 *new_node
2900 .as_any()
2901 .downcast_ref::<Fat32Node>()
2902 .unwrap()
2903 .cluster
2904 .read()
2905 }
2906 FileType::RegularFile => 0, // Files get clusters when written to
2907 _ => 0,
2908 };
2909
2910 self.write_directory_entry_with_name(
2911 actual_parent_cluster,
2912 name,
2913 node_cluster,
2914 0,
2915 file_type == FileType::Directory,
2916 )?;
2917
2918 // Add to parent directory (in-memory)
2919 {
2920 let mut children = fat32_parent.children.write();
2921 children.insert(name.clone(), Arc::clone(&new_node) as Arc<dyn VfsNode>);
2922 }
2923
2924 Ok(new_node as Arc<dyn VfsNode>)
2925 }
2926
2927 fn remove(&self, parent: &Arc<dyn VfsNode>, name: &String) -> Result<(), FileSystemError> {
2928 let fat32_parent = parent.as_any().downcast_ref::<Fat32Node>().ok_or_else(|| {
2929 FileSystemError::new(
2930 FileSystemErrorKind::NotSupported,
2931 "Invalid node type for FAT32",
2932 )
2933 })?;
2934
2935 // Check if it's a directory
2936 match fat32_parent.file_type() {
2937 Ok(FileType::Directory) => {}
2938 Ok(_) => {
2939 return Err(FileSystemError::new(
2940 FileSystemErrorKind::NotADirectory,
2941 "Parent is not a directory",
2942 ));
2943 }
2944 Err(e) => return Err(e),
2945 }
2946
2947 // Get the file node to retrieve cluster information
2948 let file_node = {
2949 let children = fat32_parent.children.read();
2950 match children.get(name) {
2951 Some(node) => {
2952 // Downcast to Fat32Node to get cluster information
2953 node.as_any()
2954 .downcast_ref::<Fat32Node>()
2955 .ok_or_else(|| {
2956 FileSystemError::new(
2957 FileSystemErrorKind::NotSupported,
2958 "Invalid node type for FAT32",
2959 )
2960 })?
2961 .clone()
2962 }
2963 None => {
2964 return Err(FileSystemError::new(
2965 FileSystemErrorKind::NotFound,
2966 format!("File '{}' not found", name),
2967 ));
2968 }
2969 }
2970 };
2971
2972 // Get the starting cluster and deallocate the cluster chain
2973 let start_cluster = file_node.cluster();
2974 if start_cluster != 0 {
2975 self.free_cluster_chain(start_cluster)?;
2976 }
2977
2978 // Remove the directory entry from disk
2979 let parent_cluster = *fat32_parent.cluster.read();
2980 let actual_parent_cluster = if parent_cluster == 0 {
2981 self.root_cluster // Use root cluster for root directory
2982 } else {
2983 parent_cluster
2984 };
2985
2986 // #[cfg(test)]
2987 // {
2988 // use crate::early_println;
2989 // early_println!("[FAT32] Removing file '{}' from parent cluster {} (original: {})",
2990 // name, actual_parent_cluster, parent_cluster);
2991 // }
2992
2993 self.remove_directory_entry(actual_parent_cluster, name)?;
2994
2995 // Remove from parent directory (in-memory)
2996 {
2997 let mut children = fat32_parent.children.write();
2998 children.remove(name);
2999 }
3000
3001 // Invalidate page cache entries for this file to avoid stale data after delete/recreate
3002 {
3003 use crate::fs::vfs_v2::cache::CacheId;
3004 use crate::mem::page_cache::PageCacheManager;
3005 let fs_id = self.fs_id().get();
3006 let node_file_id = file_node.metadata.read().file_id;
3007 if node_file_id != 0 {
3008 let cid = CacheId::new((fs_id << 32) | node_file_id);
3009 PageCacheManager::global().invalidate(cid);
3010 }
3011 if start_cluster != 0 {
3012 let cid = CacheId::new((fs_id << 32) | (start_cluster as u64));
3013 PageCacheManager::global().invalidate(cid);
3014 }
3015 }
3016
3017 Ok(())
3018 }
3019
3020 fn readdir(
3021 &self,
3022 node: &Arc<dyn VfsNode>,
3023 ) -> Result<Vec<DirectoryEntryInternal>, FileSystemError> {
3024 let fat32_node = node.as_any().downcast_ref::<Fat32Node>().ok_or_else(|| {
3025 FileSystemError::new(
3026 FileSystemErrorKind::NotSupported,
3027 "Invalid node type for FAT32",
3028 )
3029 })?;
3030
3031 // Check if it's a directory
3032 match fat32_node.file_type() {
3033 Ok(FileType::Directory) => {}
3034 Ok(_) => {
3035 return Err(FileSystemError::new(
3036 FileSystemErrorKind::NotADirectory,
3037 "Not a directory",
3038 ));
3039 }
3040 Err(e) => return Err(e),
3041 }
3042
3043 // Load directory entries from disk if not already loaded
3044 let mut fat32_entries = Vec::new();
3045 let cluster = *fat32_node.cluster.read();
3046
3047 // #[cfg(test)]
3048 // {
3049 // use crate::early_println;
3050 // early_println!("[FAT32] Reading directory entries from cluster {}", cluster);
3051 // }
3052
3053 if cluster == 0 {
3054 // This is likely the root directory - handle FAT32 root directory differently
3055 // #[cfg(test)]
3056 // {
3057 // use crate::early_println;
3058 // early_println!("[FAT32] Reading FAT32 root directory (cluster 0, using root_cluster {})", self.root_cluster);
3059 // }
3060 self.read_directory_entries(self.root_cluster, &mut fat32_entries)?;
3061 } else {
3062 self.read_directory_entries(cluster, &mut fat32_entries)?;
3063 }
3064
3065 // Convert Fat32DirectoryEntryInternal to DirectoryEntryInternal
3066 let mut entries = Vec::new();
3067 for fat32_entry in fat32_entries {
3068 let file_type = if fat32_entry.is_directory() {
3069 FileType::Directory
3070 } else {
3071 FileType::RegularFile
3072 };
3073
3074 let entry = DirectoryEntryInternal {
3075 name: fat32_entry.name(),
3076 file_type,
3077 file_id: fat32_entry.cluster() as u64, // Use cluster as file_id
3078 };
3079 entries.push(entry);
3080 }
3081
3082 // #[cfg(test)]
3083 // {
3084 // use crate::early_println;
3085 // early_println!("[FAT32] Found {} directory entries", entries.len());
3086 // }
3087
3088 Ok(entries)
3089 }
3090
3091 fn root_node(&self) -> Arc<dyn VfsNode> {
3092 Arc::clone(&*self.root.read()) as Arc<dyn VfsNode>
3093 }
3094
3095 fn name(&self) -> &str {
3096 &self.name
3097 }
3098
3099 fn as_any(&self) -> &dyn Any {
3100 self
3101 }
3102}
3103
3104/// Register the FAT32 driver with the filesystem driver manager
3105fn register_driver() {
3106 let fs_driver_manager = get_fs_driver_manager();
3107 fs_driver_manager.register_driver(Box::new(Fat32Driver));
3108}
3109
3110driver_initcall!(register_driver);
3111
3112/// Helper enum for writing directory entries with LFN support
3113#[derive(Debug, Clone)]
3114enum EntryToWrite {
3115 LFN(structures::Fat32LFNEntry),
3116 SFN(structures::Fat32DirectoryEntry),
3117}