ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_io_fsfmt.c
Go to the documentation of this file.
1
18
19#include "ra8_io_fsfmt.h"
20
21#include <stddef.h>
22#include <stdint.h>
23
24#include "ra8_attributes.h"
25#include "ra8_check.h"
26#include "ra8_err.h"
27#include "ra8_fs.h"
28
30static const char* const s_tag = "ra8_io_fsfmt";
31
33static const ra8_io_fsfmt_t* s_reg[(uint32_t)k_ra8_io_fsfmt_max];
35static uint32_t s_count;
36
54 void** out_mount)
55{
56 ra8_fs_mount_t* mount = nullptr;
57 const ra8_err_t e = ra8_fs_mount(backend, &mount);
58 if (e != k_ra8_ok) {
59 return e;
60 }
61 *out_mount = mount;
62 return k_ra8_ok;
63}
64
81{
82 return ra8_fs_unmount((ra8_fs_mount_t*)mount_ctx);
83}
84
104internal_native_open(void* mount_ctx, const char* path, ra8_fs_mode_t mode, void** out_file)
105{
106 ra8_fs_file_t* file = nullptr;
107 const ra8_err_t e = ra8_fs_open((ra8_fs_mount_t*)mount_ctx, path, mode, &file);
108 if (e != k_ra8_ok) {
109 return e;
110 }
111 *out_file = file;
112 return k_ra8_ok;
113}
114
131{
132 return ra8_fs_close((ra8_fs_file_t*)file_ctx);
133}
134
154internal_native_read(void* file_ctx, void* buf, uint32_t bytes, uint32_t* out_read)
155{
156 return ra8_fs_read((ra8_fs_file_t*)file_ctx, (uint8_t*)buf, bytes, out_read);
157}
158
176RA8_INTERNAL static ra8_err_t internal_native_write(void* file_ctx, const void* buf, uint32_t bytes)
177{
178 return ra8_fs_write((ra8_fs_file_t*)file_ctx, (const uint8_t*)buf, bytes);
179}
180
197RA8_INTERNAL static ra8_err_t internal_native_seek(void* file_ctx, uint64_t offset_bytes)
198{
199 return ra8_fs_seek((ra8_fs_file_t*)file_ctx, offset_bytes);
200}
201
218RA8_INTERNAL static ra8_err_t internal_native_tell(const void* file_ctx, uint64_t* out_offset)
219{
220 return ra8_fs_tell((const ra8_fs_file_t*)file_ctx, out_offset);
221}
222
239RA8_INTERNAL static ra8_err_t internal_native_size(const void* file_ctx, uint64_t* out_bytes)
240{
241 return ra8_fs_size((const ra8_fs_file_t*)file_ctx, out_bytes);
242}
243
262internal_native_stat(void* mount_ctx, const char* path, ra8_fs_stat_t* out)
263{
264 return ra8_fs_stat((ra8_fs_mount_t*)mount_ctx, path, out);
265}
266
286internal_native_listdir(void* mount_ctx, const char* path, ra8_fs_listdir_cb_t cb, void* cb_ctx)
287{
288 ra8_fs_dir_t directory = {};
289 ra8_err_t err = ra8_fs_dir_open((ra8_fs_mount_t*)mount_ctx, path, &directory);
290 while (err == k_ra8_ok) {
291 ra8_fs_dirent_t entry = {};
292 bool present = false;
293 err = ra8_fs_dir_next(&directory, &entry, &present);
294 if (err != k_ra8_ok) {
295 break;
296 }
297 if (!present) {
298 break;
299 }
300 cb(entry.name, entry.attr, entry.size_bytes, cb_ctx);
301 }
302 if (directory.is_open) {
303 const ra8_err_t closed = ra8_fs_dir_close(&directory);
304 if (err == k_ra8_ok) {
305 err = closed;
306 }
307 }
308 return err;
309}
310
332 const char* path,
333 void* directory_state,
334 uint32_t state_bytes)
335{
336 if (state_bytes < (uint32_t)sizeof(ra8_fs_dir_t)) {
337 return k_ra8_err_no_mem;
338 }
339 ra8_fs_dir_t* directory = (ra8_fs_dir_t*)directory_state;
340 *directory = (ra8_fs_dir_t){};
341 return ra8_fs_dir_open((ra8_fs_mount_t*)mount_ctx, path, directory);
342}
343
362internal_native_dir_next(void* directory_state, ra8_fs_dirent_t* out, bool* out_entry)
363{
364 return ra8_fs_dir_next((ra8_fs_dir_t*)directory_state, out, out_entry);
365}
366
383{
384 return ra8_fs_dir_close((ra8_fs_dir_t*)directory_state);
385}
386
403RA8_INTERNAL static ra8_err_t internal_native_unlink(void* mount_ctx, const char* path)
404{
405 return ra8_fs_unlink((ra8_fs_mount_t*)mount_ctx, path);
406}
407
426internal_native_rename(void* mount_ctx, const char* old_path, const char* new_path)
427{
428 return ra8_fs_rename((ra8_fs_mount_t*)mount_ctx, old_path, new_path);
429}
430
447RA8_INTERNAL static ra8_err_t internal_native_mkdir(void* mount_ctx, const char* path)
448{
449 return ra8_fs_mkdir((ra8_fs_mount_t*)mount_ctx, path);
450}
451
468RA8_INTERNAL static ra8_err_t internal_native_rmdir(void* mount_ctx, const char* path)
469{
470 return ra8_fs_rmdir((ra8_fs_mount_t*)mount_ctx, path);
471}
472
490{
491 return ra8_fs_free_space((ra8_fs_mount_t*)mount_ctx, out);
492}
493
510{
512 if (ra8_fs_probe(backend, &type) != k_ra8_ok) {
513 return false;
514 }
515 return type == k_ra8_fs_type_exfat;
516}
517
534{
536 if (ra8_fs_probe(backend, &type) != k_ra8_ok) {
537 return false;
538 }
539 if (type == k_ra8_fs_type_fat12) {
540 return true;
541 }
542 if (type == k_ra8_fs_type_fat16) {
543 return true;
544 }
545 return type == k_ra8_fs_type_fat32;
546}
547
550 .probe = internal_fat_probe,
551 .mount = internal_native_mount,
552 .unmount = internal_native_unmount,
553 .open = internal_native_open,
554 .close = internal_native_close,
555 .read = internal_native_read,
556 .write = internal_native_write,
557 .seek = internal_native_seek,
558 .tell = internal_native_tell,
559 .size = internal_native_size,
560 .sync = nullptr,
561 .stat = internal_native_stat,
562 .listdir = internal_native_listdir,
563 .dir_open = internal_native_dir_open,
564 .dir_next = internal_native_dir_next,
565 .dir_close = internal_native_dir_close,
566 .unlink = internal_native_unlink,
567 .rename = internal_native_rename,
568 .mkdir = internal_native_mkdir,
569 .rmdir = internal_native_rmdir,
570 .free_space = internal_native_free_space,
571};
572
574static const ra8_io_fsfmt_t s_fmt_fat = {
575 .name = "fat",
576 .caps =
577 {
578 .directory_workspace_bytes = sizeof(ra8_fs_dir_t),
579 .max_name_len = (uint16_t)k_ra8_io_fsfmt_fat_max_name_utf8,
580 .max_open_directories = UINT16_MAX,
581 .directory_workspace_align = (uint8_t)_Alignof(ra8_fs_dir_t),
582 .read_only = false,
583 .supports_mkdir = true,
584 .supports_rmdir = true,
585 .supports_streaming_write = true,
586 .supports_timestamps = true,
587 .supports_free_space = true,
588 .supports_dir_cursor = true,
589 .supports_sync = false,
590 .atomic_rename = false,
591 .durable_sync = false,
592 .unicode_names = true,
593 .case_sensitive = false,
594 },
595 .ops = &s_native_ops,
596};
597
600 .probe = internal_exfat_probe,
601 .mount = internal_native_mount,
602 .unmount = internal_native_unmount,
603 .open = internal_native_open,
604 .close = internal_native_close,
605 .read = internal_native_read,
606 .write = internal_native_write,
607 .seek = internal_native_seek,
608 .tell = internal_native_tell,
609 .size = internal_native_size,
610 .sync = nullptr,
611 .stat = internal_native_stat,
612 .listdir = internal_native_listdir,
613 .dir_open = internal_native_dir_open,
614 .dir_next = internal_native_dir_next,
615 .dir_close = internal_native_dir_close,
616 .unlink = internal_native_unlink,
617 .rename = internal_native_rename,
618 .mkdir = internal_native_mkdir,
619 .rmdir = internal_native_rmdir,
620 .free_space = internal_native_free_space,
621};
622
625 .name = "exfat",
626 .caps =
627 {
628 .directory_workspace_bytes = sizeof(ra8_fs_dir_t),
629 .max_name_len = (uint16_t)k_ra8_io_fsfmt_exfat_max_name_utf8,
630 .max_open_directories = UINT16_MAX,
631 .directory_workspace_align = (uint8_t)_Alignof(ra8_fs_dir_t),
632 .read_only = false,
633 .supports_mkdir = true,
634 .supports_rmdir = true,
635 .supports_streaming_write = true,
636 .supports_timestamps = true,
637 .supports_free_space = true,
638 .supports_dir_cursor = true,
639 .supports_sync = false,
640 .atomic_rename = false,
641 .durable_sync = false,
642 .unicode_names = true,
643 .case_sensitive = false,
644 },
645 .ops = &s_exfat_ops,
646};
647
668{
669 const uint8_t align = fmt->caps.directory_workspace_align;
670 if ((fmt->ops->dir_open == nullptr) || (fmt->ops->dir_next == nullptr) ||
671 (fmt->ops->dir_close == nullptr) || (fmt->caps.directory_workspace_bytes == 0U) ||
672 (fmt->caps.max_open_directories == 0U) || (align == 0U) ||
673 (((uint32_t)align & ((uint32_t)align - 1U)) != 0U)) {
675 }
676 return k_ra8_ok;
677}
678
709{
710 if (fmt->caps.supports_streaming_write) {
711 if (fmt->ops->write == nullptr) {
713 }
714 }
715 if (fmt->caps.supports_mkdir) {
716 if (fmt->ops->mkdir == nullptr) {
718 }
719 }
720 if (fmt->caps.supports_rmdir) {
721 if (fmt->ops->rmdir == nullptr) {
723 }
724 }
725 if (fmt->caps.supports_free_space) {
726 if (fmt->ops->free_space == nullptr) {
728 }
729 }
730 if (fmt->caps.supports_sync) {
731 if (fmt->ops->sync == nullptr) {
733 }
734 }
735 if (fmt->caps.atomic_rename) {
736 if (fmt->ops->rename == nullptr) {
738 }
739 }
740 return k_ra8_ok;
741}
742
763{
764 if (fmt->caps.supports_dir_cursor) {
766 s_tag,
767 "dir-cursor capability mismatch");
768 }
769 RA8_RETURN_ON_ERROR(internal_validate_single_op_caps(fmt), s_tag, "capability mismatch");
770 if (fmt->caps.durable_sync) {
771 if (!fmt->caps.supports_sync) {
773 }
774 }
775 return k_ra8_ok;
776}
777
785
805{
806 RA8_CHECK_NULL_PTR(fmt->ops->probe, s_tag, "probe must not be nullptr");
807 RA8_CHECK_NULL_PTR(fmt->ops->mount, s_tag, "mount must not be nullptr");
808 RA8_CHECK_NULL_PTR(fmt->ops->unmount, s_tag, "unmount must not be nullptr");
809 RA8_CHECK_NULL_PTR(fmt->ops->open, s_tag, "open must not be nullptr");
810 RA8_CHECK_NULL_PTR(fmt->ops->close, s_tag, "close must not be nullptr");
811 RA8_CHECK_NULL_PTR(fmt->ops->read, s_tag, "read must not be nullptr");
812 return k_ra8_ok;
813}
814
834{
835 RA8_CHECK_NULL_PTR(fmt->ops->seek, s_tag, "seek must not be nullptr");
836 RA8_CHECK_NULL_PTR(fmt->ops->tell, s_tag, "tell must not be nullptr");
837 RA8_CHECK_NULL_PTR(fmt->ops->size, s_tag, "size must not be nullptr");
838 RA8_CHECK_NULL_PTR(fmt->ops->stat, s_tag, "stat must not be nullptr");
839 RA8_CHECK_NULL_PTR(fmt->ops->listdir, s_tag, "listdir must not be nullptr");
840 return k_ra8_ok;
841}
842
860{
862 s_tag,
863 "missing mandatory operation");
865}
866
868{
869 RA8_CHECK_NULL_PTR(fmt, s_tag, "fmt must not be nullptr");
870 RA8_CHECK_NULL_PTR(fmt->name, s_tag, "fmt->name must not be nullptr");
871 RA8_CHECK_NULL_PTR(fmt->ops, s_tag, "fmt->ops must not be nullptr");
872 RA8_RETURN_ON_ERROR(internal_validate_required_ops(fmt), s_tag, "missing mandatory operation");
873 RA8_RETURN_ON_ERROR(internal_validate_caps(fmt), s_tag, "capability mismatch");
874 if (s_count >= (uint32_t)k_ra8_io_fsfmt_max) {
875 return k_ra8_err_no_mem;
876 }
877 s_reg[s_count] = fmt;
878 s_count++;
879 return k_ra8_ok;
880}
881
883{
884 RA8_CHECK_NULL_PTR(out, s_tag, "out must not be nullptr");
885 if (type == k_ra8_fs_type_exfat) {
886 *out = &s_fmt_exfat;
887 return k_ra8_ok;
888 }
889 if (type == k_ra8_fs_type_fat12) {
890 *out = &s_fmt_fat;
891 return k_ra8_ok;
892 }
893 if (type == k_ra8_fs_type_fat16) {
894 *out = &s_fmt_fat;
895 return k_ra8_ok;
896 }
897 if (type == k_ra8_fs_type_fat32) {
898 *out = &s_fmt_fat;
899 return k_ra8_ok;
900 }
902}
903
905{
906 RA8_CHECK_NULL_PTR(backend, s_tag, "backend must not be nullptr");
907 RA8_CHECK_NULL_PTR(out, s_tag, "out must not be nullptr");
908 for (uint32_t i = 0U; i < s_count; ++i) {
909 if (s_reg[i]->ops->probe(backend)) {
910 *out = s_reg[i];
911 return k_ra8_ok;
912 }
913 }
914 return k_ra8_err_not_found;
915}
static const char * s_tag
Logging / check tag.
Definition ra8_app.c:17
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Validation and Error-Checking Macros for ra8-firmware.
#define RA8_RETURN_ON_ERROR(err, tag, message)
Early return on error, propagating the code upward.
Definition ra8_check.h:184
#define RA8_CHECK_NULL_PTR(ptr, tag, message)
Reject nullptr pointer, returning k_ra8_err_null_ptr.
Definition ra8_check.h:243
Error Code Definitions for ra8-firmware.
@ k_ra8_err_no_mem
Static buffer exhausted (no dynamic memory on this project).
Definition ra8_err.h:142
@ k_ra8_err_invalid_arg
Invalid function argument.
Definition ra8_err.h:152
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
@ k_ra8_err_not_found
Requested item not found (lookup / search missed).
Definition ra8_err.h:173
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
Minimal FAT12/FAT16/FAT32 filesystem adapter (read + write).
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_write(ra8_fs_file_t *file, const uint8_t *buf, uint32_t len)
Write len bytes; allocate new clusters from FAT free-space scan as needed.
ra8_err_t ra8_fs_mount(const ra8_fs_backend_t *backend, ra8_fs_mount_t **out_handle)
Mount a FAT volume from a block-device backend, auto-selecting the first partition.
ra8_err_t ra8_fs_size(const ra8_fs_file_t *file, uint64_t *out_bytes)
Report the file's size in bytes (64-bit on exFAT, #676).
ra8_err_t ra8_fs_read(ra8_fs_file_t *file, uint8_t *buf, uint32_t max_len, uint32_t *got_len)
Read up to max_len bytes; advance the cluster chain on cluster crossings.
ra8_err_t ra8_fs_stat(const ra8_fs_mount_t *handle, const char *path, ra8_fs_stat_t *out)
Report what a path names – file or directory – without opening it.
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_open(ra8_fs_mount_t *handle, const char *path, ra8_fs_mode_t mode, ra8_fs_file_t **out_file)
Open or create a file by path, 8.3 or long.
ra8_err_t ra8_fs_unmount(ra8_fs_mount_t *handle)
Unmount a previously mounted volume and release its slot.
ra8_err_t ra8_fs_mkdir(const ra8_fs_mount_t *handle, const char *path)
Create a directory at path.
ra8_err_t ra8_fs_rmdir(const ra8_fs_mount_t *handle, const char *path)
Remove an empty directory at path.
ra8_err_t ra8_fs_probe(const ra8_fs_backend_t *backend, ra8_fs_type_t *out_type)
Identify a FAT/exFAT volume without claiming a mount slot.
ra8_err_t ra8_fs_close(ra8_fs_file_t *file)
Close an open file, stamping its final modification time.
ra8_err_t ra8_fs_seek(ra8_fs_file_t *file, uint64_t offset_bytes)
Move the file offset to offset_bytes (clamped to size).
ra8_err_t ra8_fs_tell(const ra8_fs_file_t *file, uint64_t *out_offset)
Report the current offset (64-bit; see ra8_fs_seek).
ra8_err_t ra8_fs_dir_close(ra8_fs_dir_t *directory)
Consume one open directory cursor.
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.
ra8_err_t ra8_fs_free_space(const ra8_fs_mount_t *handle, ra8_fs_space_t *out)
Report a mounted volume's total, free, and used space.
ra8_fs_type_t
FAT variant detected from the BPB cluster-count rule.
@ k_ra8_fs_type_fat12
count_of_clusters < 4085.
@ k_ra8_fs_type_fat32
count_of_clusters >= 65525.
@ k_ra8_fs_type_exfat
exFAT (read + streaming write + format).
@ k_ra8_fs_type_fat16
4085 <= count_of_clusters < 65525.
@ k_ra8_fs_type_unknown
Not yet detected / mount failed.
ra8_fs_mode_t
File-open modes accepted by ra8_fs_open().
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().
static bool internal_exfat_probe(const ra8_fs_backend_t *backend)
Test whether the authoritative native parser identifies exFAT.
static ra8_err_t internal_native_mkdir(void *mount_ctx, const char *path)
Create a native ra8_fs directory.
static ra8_err_t internal_native_rename(void *mount_ctx, const char *old_path, const char *new_path)
Rename inside one native ra8_fs mount.
static ra8_err_t internal_native_write(void *file_ctx, const void *buf, uint32_t bytes)
Write a native ra8_fs stream.
static const ra8_io_fsfmt_t s_fmt_exfat
Native exFAT descriptor.
static ra8_err_t internal_native_free_space(void *mount_ctx, ra8_fs_space_t *out)
Query native ra8_fs free space.
static ra8_err_t internal_native_dir_next(void *directory_state, ra8_fs_dirent_t *out, bool *out_entry)
Copy one native directory-cursor entry without retaining a lock.
static const ra8_io_fsfmt_ops_t s_exfat_ops
Native exFAT descriptor; shares byte-identical ra8_fs dispatch.
static ra8_err_t internal_native_rmdir(void *mount_ctx, const char *path)
Remove a native ra8_fs directory.
static ra8_err_t internal_validate_required_ops_group2(const ra8_io_fsfmt_t *fmt)
Validate that the remaining five mandatory format operations are present.
static ra8_err_t internal_validate_caps(const ra8_io_fsfmt_t *fmt)
Validate every optional capability flag against its backing operation.
ra8_err_t ra8_io_fsfmt_init(void)
Reset the registry and register the built-in FAT + exFAT formats.
static const ra8_io_fsfmt_t s_fmt_fat
Native FAT12/16/32 descriptor.
ra8_err_t ra8_io_fsfmt_probe(const ra8_fs_backend_t *backend, const ra8_io_fsfmt_t **out)
Detect the format of a volume by probing registered formats in order.
static ra8_err_t internal_native_read(void *file_ctx, void *buf, uint32_t bytes, uint32_t *out_read)
Read a native ra8_fs stream.
static const ra8_io_fsfmt_ops_t s_native_ops
Complete native operation table; no explicit durable-sync seam exists.
static const ra8_io_fsfmt_t * s_reg[(uint32_t) k_ra8_io_fsfmt_max]
Registered formats, in probe priority order.
static ra8_err_t internal_validate_required_ops_group1(const ra8_io_fsfmt_t *fmt)
Validate that the first six mandatory format operations are present.
static ra8_err_t internal_native_close(void *file_ctx)
Close a native ra8_fs stream.
static ra8_err_t internal_native_size(const void *file_ctx, uint64_t *out_bytes)
Report a native ra8_fs stream size.
ra8_err_t ra8_io_fsfmt_register(const ra8_io_fsfmt_t *fmt)
Register a filesystem format (the foreign-format seam).
static uint32_t s_count
Occupied entries in s_reg.
static ra8_err_t internal_native_mount(const ra8_fs_backend_t *backend, void **out_mount)
Mount the native ra8_fs implementation without pointer aliasing.
static ra8_err_t internal_native_open(void *mount_ctx, const char *path, ra8_fs_mode_t mode, void **out_file)
Open a native ra8_fs stream without pointer aliasing.
static ra8_err_t internal_native_dir_open(void *mount_ctx, const char *path, void *directory_state, uint32_t state_bytes)
Open one native incremental directory cursor.
ra8_err_t ra8_io_fsfmt_get_builtin(ra8_fs_type_t type, const ra8_io_fsfmt_t **out)
Return the built-in descriptor serving one native ra8_fs type.
static ra8_err_t internal_native_stat(void *mount_ctx, const char *path, ra8_fs_stat_t *out)
Query native ra8_fs metadata.
static ra8_err_t internal_native_tell(const void *file_ctx, uint64_t *out_offset)
Report a native ra8_fs stream offset.
static bool internal_fat_probe(const ra8_fs_backend_t *backend)
Test whether the authoritative native parser identifies a FAT variant.
static ra8_err_t internal_native_unlink(void *mount_ctx, const char *path)
Unlink a native ra8_fs file.
static ra8_err_t internal_validate_single_op_caps(const ra8_io_fsfmt_t *fmt)
Validate that every claimed optional capability has an operation.
static ra8_err_t internal_validate_required_ops(const ra8_io_fsfmt_t *fmt)
Validate that every mandatory format operation pointer is present.
static ra8_err_t internal_native_listdir(void *mount_ctx, const char *path, ra8_fs_listdir_cb_t cb, void *cb_ctx)
Enumerate a native ra8_fs directory.
static ra8_err_t internal_native_unmount(void *mount_ctx)
Release a native ra8_fs mount.
static ra8_err_t internal_native_seek(void *file_ctx, uint64_t offset_bytes)
Seek a native ra8_fs stream.
static ra8_err_t internal_native_dir_close(void *directory_state)
Close and consume one native directory cursor.
static ra8_err_t internal_validate_dir_cursor_caps(const ra8_io_fsfmt_t *fmt)
Validate that a claimed directory-cursor capability is complete.
ra8_io pluggable filesystem-format registry (probe + capabilities).
@ k_ra8_io_fsfmt_exfat_max_name_utf8
64 UTF-16 units, worst case.
@ k_ra8_io_fsfmt_fat_max_name_utf8
247 UTF-16 units, worst case.
@ k_ra8_io_fsfmt_max
Max registered formats (built-ins + foreign).
Block-device interface that ra8_fs runs on top of.
Caller-owned opaque directory cursor.
bool is_open
Facade lifecycle guard.
Stable directory-entry value copied by ra8_fs_dir_next.
char name[k_ra8_fs_dir_name_cap]
NUL-terminated visible leaf.
uint8_t attr
On-disk FAT attributes.
uint64_t size_bytes
File bytes; zero for dirs.
Open-file state.
Cached parse of one mounted FAT volume.
A mounted volume's capacity, free space, and cluster geometry.
Definition ra8_fs_meta.h:84
What ra8_fs_stat() read out of a directory entry.
Complete filesystem-format dispatch surface used by the VFS.
One registered filesystem format.