35 "ra8_fs directory cursor state exceeds public storage");
37 "ra8_fs directory cursor state alignment exceeds public storage");
110 uint32_t lnunits = 0U;
112 uint8_t have_long = 0U;
113 if (lunits !=
nullptr) {
119 cb((have_long != 0U) ? lname : short_name, ent[
k_dir_off_attr], size, ctx);
164 if (handle ==
nullptr || cb ==
nullptr || path ==
nullptr) {
167 if (handle->in_use == 0U) {
168 return k_ra8_err_invalid_state;
175 exfat_dir_t dir = {};
230 state->finished =
true;
256 const uint8_t* sector,
260 while (state->fat_walk.entry_idx <
priv_bps(state->mount)) {
261 const uint8_t* entry = §or[state->fat_walk.entry_idx];
262 state->fat_walk.entry_idx += (uint32_t)k_ra8_fs_dir_entry_bytes;
263 if (entry[k_dir_off_name] == k_dir_marker_free_perm) {
264 state->finished = true;
283 const uint16_t* name_units =
285 const char* name = short_name;
286 if (name_units !=
nullptr) {
323 while (!state->finished) {
324 if (state->fat_walk.entry_idx >= priv_bps(state->mount)) {
325 const ra8_err_t step = internal_fat_dir_advance_sector(state);
326 if (step != k_ra8_ok) {
329 if (state->finished) {
339 if (*out_entry || state->finished) {
368 if (handle->in_use == 0U) {
369 return k_ra8_err_invalid_state;
374 exfat_dir_t dir = {};
424 uint32_t* out_cluster)
426 const char* leaf =
nullptr;
487 if (handle ==
nullptr || path ==
nullptr) {
490 if (handle->in_use == 0U) {
491 return k_ra8_err_invalid_state;
494 return priv_exfat_unlink(handle, path);
497 uint32_t cluster = 0;
546 const char* old_path,
547 const char* new_path,
549 const char** out_old,
550 const char** out_new)
553 const char* ol =
nullptr;
559 const char* nl =
nullptr;
622 const char* ol =
nullptr;
623 const char* nl =
nullptr;
628 uint64_t dup_lba = 0U;
629 uint32_t dup_off = 0U;
656 uint64_t new_lba = 0U;
657 uint32_t new_off = 0U;
686 if (handle ==
nullptr) {
689 if (old_path ==
nullptr) {
692 if (new_path ==
nullptr) {
695 if (handle->in_use == 0U) {
696 return k_ra8_err_invalid_state;
699 return priv_exfat_rename(handle, old_path, new_path);
722 if (handle ==
nullptr) {
725 if (path ==
nullptr) {
728 if (directory ==
nullptr) {
731 if (directory->is_open) {
732 return k_ra8_err_busy;
734 void* state_memory = directory->state;
740 directory->is_open =
true;
742 (void)
memset(directory->state, 0,
sizeof(directory->state));
750 if (directory ==
nullptr) {
753 if (out ==
nullptr) {
756 if (out_entry ==
nullptr) {
759 if (!directory->is_open) {
760 return k_ra8_err_invalid_state;
764 void* state_memory = directory->state;
769 if (!state->finished) {
779 state->finished =
true;
788 if (directory ==
nullptr) {
Annotation-attribute framework macros for ra8-firmware.
#define RA8_OWNS_RESOURCE(kind)
RAII-style resource ownership contract.
#define RA8_EXPECTS_LOCK(name)
The function expects the named thread/IRQ lock to be held on entry.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
@ k_ra8_err_not_supported
Requested feature not compiled in, not wired, or not supported by this MCU variant.
@ k_ra8_err_invalid_arg
Invalid function argument.
@ k_ra8_err_exists
Item already exists – cannot create again.
@ k_ra8_err_invalid_state
Module in wrong state for requested operation.
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
@ k_ra8_err_null_ptr
Pointer was NULL where a valid pointer was required.
@ k_ra8_err_access_denied
Operation refused because the target is protected against it.
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
void * memset(void *dst, int value, size_t n)
Fill memory with a constant byte value.
size_t strlen(const char *s)
Calculate string length.
void * memcpy(void *dst, const void *src, size_t n)
Copy memory area between non-overlapping regions.
Minimal FAT12/FAT16/FAT32 filesystem adapter (read + write).
ra8_err_t ra8_fs_listdir(const ra8_fs_mount_t *handle, const char *path, ra8_fs_listdir_cb_t cb, void *ctx)
Enumerate directory entries; invoke cb once per visible entry.
ra8_err_t ra8_fs_dir_next(ra8_fs_dir_t *directory, ra8_fs_dirent_t *out, bool *out_entry)
Copy the next visible directory entry.
ra8_err_t ra8_fs_rename(const ra8_fs_mount_t *handle, const char *old_path, const char *new_path)
Rename a file within its own directory.
ra8_err_t ra8_fs_unlink(const ra8_fs_mount_t *handle, const char *path)
Delete a file: mark its dir entry deleted and free its clusters.
ra8_err_t ra8_fs_dir_open(ra8_fs_mount_t *handle, const char *path, ra8_fs_dir_t *directory)
Open a caller-owned directory cursor without holding the filesystem lock.
uint32_t priv_rd32(const uint8_t *p)
Decode a little-endian uint32_t from a byte buffer.
uint32_t priv_dir_eps(const ra8_fs_mount_t *m)
Directory entries per sector on one mounted volume.
ra8_err_t priv_read_sector(const ra8_fs_mount_t *m, uint64_t lba, uint8_t *buf)
Read a single sector into the module scratch buffer.
uint32_t priv_bps(const ra8_fs_mount_t *m)
One mounted volume's sector size in bytes.
uint8_t * priv_sec_walk(void)
The WALK-role sector buffer (directory scans and entry RMW).
static ra8_err_t internal_rename_prepare(const ra8_fs_mount_t *handle, const char *old_path, const char *new_path, dir_loc_t *out_parent, const char **out_old, const char **out_new)
Resolve a rename's old/new paths to a shared parent and two leaves.
static void internal_fat_dir_scan_sector(ra8_fs_dir_private_t *state, const uint8_t *sector, ra8_fs_dirent_t *out, bool *out_entry)
Scan one already-read sector's remaining entries for one visible entry.
static ra8_err_t internal_fat_dir_advance_sector(ra8_fs_dir_private_t *state)
Advance an independent FAT cursor to its next directory sector.
static ra8_err_t internal_unlink_locate(const ra8_fs_mount_t *handle, const char *path, dir_target_t *out, uint32_t *out_cluster)
Resolve a path to a deletable FILE's entry and first cluster.
static ra8_err_t internal_fat_dir_next(ra8_fs_dir_private_t *state, ra8_fs_dirent_t *out, bool *out_entry)
Copy one visible FAT entry from an independent cursor.
static ra8_err_t internal_dir_open_locked(ra8_fs_mount_t *handle, const char *path, ra8_fs_dir_private_t *state)
Resolve and initialize one private filesystem cursor.
static ra8_err_t internal_rename_locked(const ra8_fs_mount_t *handle, const char *old_path, const char *new_path)
Rename – the guarded body of ra8_fs_rename().
static uint8_t internal_listdir_visit_sector(const ra8_fs_mount_t *m, const uint8_t *buf, lfn_state_t *lfn, ra8_fs_listdir_cb_t cb, void *ctx)
Visit every visible entry in one already-loaded directory sector.
static ra8_err_t internal_listdir_locked(const ra8_fs_mount_t *handle, const char *path, ra8_fs_listdir_cb_t cb, void *ctx)
Enumerate a directory – the guarded body of ra8_fs_listdir().
static ra8_err_t internal_unlink_locked(const ra8_fs_mount_t *handle, const char *path)
Delete a file – the guarded body of ra8_fs_unlink().
static ra8_err_t internal_fat_rename(const ra8_fs_mount_t *handle, const char *old_path, const char *new_path)
Rename by writing the new entry first, then taking the old one away.
ra8_err_t ra8_fs_dir_close(ra8_fs_dir_t *directory)
Consume one open directory cursor.
ra8_err_t priv_exfat_resolve_dir(const ra8_fs_mount_t *m, const char *path, exfat_dir_t *out)
Resolve a whole path to the directory it names.
void priv_exfat_cursor_init(const exfat_dir_t *dir, exfat_cursor_t *out)
Aim a fresh cursor at the start of dir.
ra8_err_t priv_exfat_listdir(const ra8_fs_mount_t *m, const exfat_dir_t *dir, ra8_fs_listdir_cb_t cb, void *ctx)
Enumerate ONE directory of an exFAT volume.
ra8_err_t priv_exfat_dir_next(const ra8_fs_mount_t *m, exfat_cursor_t *cur, ra8_fs_dirent_t *out, bool *out_entry)
Copy the next visible exFAT directory entry from an existing cursor.
ra8_err_t priv_resolve_dir(const ra8_fs_mount_t *m, const char *path, dir_loc_t *out)
Resolve a whole path to the directory it names.
uint32_t priv_entry_first_cluster(const uint8_t *entry)
Read the first cluster from a 32-byte directory entry.
ra8_err_t priv_resolve_parent(const ra8_fs_mount_t *m, const char *path, dir_loc_t *out_parent, const char **out_leaf)
Resolve all-but-the-last path component to a parent directory.
Cross-TU shared declarations for the FAT/exFAT ra8_fs adapter.
ra8_err_t priv_free_chain(const ra8_fs_mount_t *m, uint32_t start)
Free an entire cluster chain starting at start.
void priv_lfn_add(lfn_state_t *s, const uint8_t *ent)
Fold one LFN directory entry's 13 UTF-16LE code units into the state.
const uint16_t * priv_lfn_units_for(const lfn_state_t *s, const uint8_t *name83, uint32_t *out_units)
Code units of the chain that precedes name83, or NULL if none.
void priv_lfn_reset(lfn_state_t *s)
Reset the LFN reassembly state so a fresh chain can start.
ra8_err_t priv_dir_reserve(const ra8_fs_mount_t *m, const dir_loc_t *loc, const char *leaf, dir_insert_t *out)
Decide how a name will be stored and set aside the slots for it.
ra8_err_t priv_dir_erase_chain(const ra8_fs_mount_t *m, const dir_loc_t *loc, uint64_t lba, uint32_t off, const uint8_t *name83)
Delete a directory entry together with its long-name chain.
ra8_err_t priv_dir_lookup_any(const ra8_fs_mount_t *m, const dir_loc_t *loc, const char *leaf, uint64_t *out_lba, uint32_t *out_off, uint8_t out_entry[k_ra8_fs_dir_entry_bytes])
Resolve one leaf name by 8.3 first and by long name second.
ra8_err_t priv_dir_commit(const ra8_fs_mount_t *m, const dir_insert_t *plan, const uint8_t *tmpl, uint64_t *out_lba, uint32_t *out_off)
Write a reserved run: the long-name chain, then the 8.3 entry.
void priv_lock_release(void)
Drop the library lock taken by priv_lock_acquire.
void priv_lock_acquire(void)
Take the library lock, if the caller installed one.
void priv_dir_walk_init_loc(const ra8_fs_mount_t *m, const dir_loc_t *loc, dir_walk_t *w)
Initialise a directory walker for an arbitrary directory location.
ra8_err_t priv_dir_walk_next_sector(const ra8_fs_mount_t *m, dir_walk_t *w, uint8_t *out_eod)
Advance the walker to the next sector.
void priv_83_to_str(const uint8_t *in11, uint8_t ntres, char *out13)
Unpack on-disk 11-byte 8.3 name into NUL-terminated "NAME.EXT".
void priv_fat_entry_stamp_access(uint8_t *entry)
Advance only a FAT directory entry's last-access date.
@ k_dir_off_attr
MS FAT spec sec 6 "DIR_Attr".
@ k_dir_off_ntres
MS FAT spec sec 6 "DIR_NTRes".
@ k_dir_off_file_size
MS FAT spec sec 6 "DIR_FileSize".
@ k_dir_off_name
MS FAT spec sec 6 "DIR_Name" (11 bytes).
@ k_dir_marker_free_used
Slot was used, deleted.
@ k_dir_marker_free_perm
End-of-directory.
@ k_cluster_first_data
Cluster numbers start at 2.
@ k_lfn_utf8_cap
A 247-unit name in UTF-8: 3 * 247, + NUL.
@ k_ra8_fs_type_exfat
exFAT (read + streaming write + format).
@ k_ra8_fs_attr_lfn
Long-file-name marker (we skip).
@ k_ra8_fs_attr_directory
MS FAT spec sec 6 "ATTR_DIRECTORY".
@ k_ra8_fs_attr_read_only
MS FAT spec sec 6 "ATTR_READ_ONLY".
@ k_ra8_fs_short_name_len
8.3 short name "AAAAAAAA.EXT" + NUL.
void(* ra8_fs_listdir_cb_t)(const char *name, uint8_t attr, uint64_t size, void *ctx)
Callback invoked once per directory entry by ra8_fs_listdir().
@ k_ra8_fs_dir_entry_bytes
MS FAT spec sec 6 "Directory Entry".
@ k_ra8_fs_dir_state_bytes
Opaque caller-owned cursor state.
ra8_err_t priv_utf16_to_utf8(const uint16_t *in, uint32_t units, char *out, uint32_t cap)
Convert UTF-16LE code units into a NUL-terminated UTF-8 name.
Everything decided about a new directory entry before anything is written.
Identifies the directory a lookup/scan should operate in.
uint8_t is_root
1 => the volume root; 0 => the subdirectory at cluster.
uint32_t cluster
First cluster of the subdirectory (ignored when root).
One resolved directory entry: where it is, and what is in it.
uint32_t off
Byte offset within that sector.
uint8_t entry[k_ra8_fs_dir_entry_bytes]
The entry as read from disk.
dir_loc_t parent
Directory the entry lives in.
uint64_t lba
Sector holding the entry.
Internal cursor used by the directory iterator.
uint64_t cur_lba
Currently loaded LBA.
Linear cursor over a directory's 32-byte entries.
In-progress reassembly of one LFN chain across the directory scan.
Private state stored inside one public opaque directory cursor.
bool finished
Clean end-of-directory was observed.
dir_walk_t fat_walk
FAT sector and cluster position.
ra8_fs_mount_t * mount
Mounted volume retained by open.
exfat_cursor_t exfat_cursor
exFAT entry-set position.
lfn_state_t fat_lfn
FAT long-name state across sectors.
Caller-owned opaque directory cursor.
bool is_open
Facade lifecycle guard.
Stable directory-entry value copied by ra8_fs_dir_next.
Cached parse of one mounted FAT volume.