// SafeC Standard Library — FAT32 Read-Only Driver
// Freestanding-safe. Uses a BlockDevice for sector reads.
#pragma once
#include <std/fs/block.h>
#include <std/fs/vfs.h>
// Maximum path components parsed
#define FAT_MAX_DEPTH 8
#define FAT_MAX_CLUSTER 4096 // largest supported cluster size in bytes (FatCtx::init rejects bigger)
namespace std {
struct FatBpb {
unsigned char oem_name[8];
unsigned short bytes_per_sector;
unsigned char sectors_per_cluster;
unsigned short reserved_sectors;
unsigned char num_fats;
unsigned short root_entry_count; // 0 for FAT32
unsigned short total_sectors_16;
unsigned char media;
unsigned short fat_size_16; // 0 for FAT32
unsigned short sectors_per_track;
unsigned short num_heads;
unsigned int hidden_sectors;
unsigned int total_sectors_32;
// FAT32 extended
unsigned int fat_size_32;
unsigned short ext_flags;
unsigned short fs_version;
unsigned int root_cluster;
unsigned short fs_info;
unsigned short backup_boot;
};
struct FatCtx {
struct BlockDevice dev;
unsigned long partition_lba; // LBA of FAT32 partition start
struct FatBpb bpb;
unsigned long fat_lba; // LBA of FAT region
unsigned long data_lba; // LBA of first data cluster
unsigned long root_cluster; // cluster of root directory
unsigned long bytes_per_cluster;
// Initialise this context in place from a block device partition
// starting at `lba` (the device is copied into `dev`).
// Returns 0 on success.
int init(&BlockDevice dev, unsigned long lba);
// Read a cluster into the first bytes_per_cluster bytes of `buf` (-1
// if it is shorter).
int read_cluster(unsigned long cluster, []unsigned char buf);
// Follow FAT chain to find cluster at position `idx` from `start_cluster`.
unsigned long follow_fat(unsigned long start_cluster, unsigned long idx);
// ── FsRead (vfs.h): mount with vfs.mount_ro(mountpoint, &ctx) ──────────
int open(const &char path, int flags, &VfsNode node_out);
unsigned long read(unsigned long inode, unsigned long offset, []unsigned char buf);
generic<T> int readdir(unsigned long inode, fn void(&VfsNode, ?&T) cb, ?&T user);
int readdir_raw_(unsigned long inode, fn void(&VfsNode, ?&Erased) cb, ?&Erased user);
};
generic<T>
int FatCtx::readdir(unsigned long inode, fn void(&VfsNode, ?&T) cb, ?&T user) {
unsafe { return self.readdir_raw_(inode, (fn void(&VfsNode, ?&Erased))cb, (?&Erased)user); }
}
} // namespace std