|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
Minimal FAT12/FAT16/FAT32 filesystem adapter (read + write). More...
Go to the source code of this file.
Functions | |
| ra8_err_t | ra8_fs_format (const ra8_fs_backend_t *backend, const ra8_fs_format_opts_t *opts) |
| Format a block device as a fresh, empty FAT12/FAT16/FAT32/exFAT volume. | |
| 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_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_mount_partition (const ra8_fs_backend_t *backend, uint8_t index, ra8_fs_mount_t **out_handle) |
| Mount a FAT/exFAT volume from a specific partition of a block device. | |
| 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_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_close (ra8_fs_file_t *file) |
| Close an open file, stamping its final modification time. | |
| 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_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_write_file (ra8_fs_mount_t *handle, const char *path, const uint8_t *data, uint32_t len) |
| Create a whole file in one call (provisioning helper). | |
| 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_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_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_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_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_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_dir_close (ra8_fs_dir_t *directory) |
| Consume one open directory cursor. | |
| 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_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_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. | |
Minimal FAT12/FAT16/FAT32 filesystem adapter (read + write).
ra8_fs is a self-contained, pure-C FAT filesystem implementation that sits on top of an arbitrary block-device backend (ra8_fs_backend_t), with no RTOS and no vendor-SDK dependencies. It is the platform's only filesystem: the vendored FileX it once coexisted with was retired by #611.
Two backends are intended for production use:
Any object that supplies read_block(), write_block(), and get_capacity() works – including the in-memory mock used in tests/storage/src/test_ra8_fs.c.
Every name crossing this API is UTF-8; both on-disk formats store UTF-16LE, converted in one place so the three paths that did their own cannot disagree again (#606).
Limits (compile-time):
The 4Kn-sector and beyond-2-TiB paths are SIMULATION-VERIFIED ONLY (host tests over fake backends); no such medium has been on the bench. 512-byte sub-2-TiB media remain the hardware-proven configuration.
The library owns three pieces of shared mutable state – the file-handle table, the mount table and one static scratch sector – so every public entry point is serialised against every other one, not merely against itself. With no lock installed (the default) that serialisation is the caller's job and the library behaves exactly as it always has: bare metal pays nothing, not even a branch worth measuring.
An RTOS-world caller installs a lock instead of duplicating that discipline at every call site – see ra8_fs_lock_t and ra8_fs_set_lock(). The lock is taken at the public boundary and released on every return path, including error returns; no internal helper takes it, so there is no lock-ordering graph and no recursion. It serialises the library: it does not make one open ra8_fs_file_t safe to drive from two threads at once.
Definition in file ra8_fs.h.
|
nodiscard |
Close an open file, stamping its final modification time.
File contents are never buffered – ra8_fs_write() has already put every byte on the volume – so what closing does is metadata. A handle that was written through gets DIR_WrtTime / DIR_WrtDate set to the moment of the close (the time a host shows as "modified" and a sync tool compares), and the volume's FAT32 FSInfo free count is committed. A handle opened read-only, or write-opened and never written, touches nothing.
| [in,out] | file | Handle from ra8_fs_open(). |
| k_ra8_ok | Closed. |
| k_ra8_err_null_ptr | file is NULL. |
| k_ra8_err_* | The timestamp or FSInfo write failed. The handle is released anyway – a close that could be refused would leak the slot. |
Definition at line 578 of file ra8_fs_fat_file.c.
References priv_close_locked(), priv_lock_acquire(), priv_lock_release(), and ra8_fs_close().
Referenced by demo_read_test_file(), demo_read_verify(), eoh_provision_or_halt(), etoc_provision_one(), fileops_expect_absent(), fileops_read_back(), fs_fmt_create_and_verify(), fs_fmt_rename_and_verify(), imp_read_cache(), internal_close(), internal_compute_source_key(), internal_demo_read_once(), internal_file_exists(), internal_mkfontimg_verify(), internal_mkfontimg_write(), internal_native_close(), internal_pc_font_or_halt(), internal_pc_read_cache(), internal_ra8_io_roundtrip_read_verify(), internal_ra8_io_roundtrip_write_subdir(), internal_ra8_vfs_compress_load_blob(), internal_ra8_vfs_compress_store_blob(), internal_read_font(), internal_read_stamp(), internal_read_whole_file(), internal_stream_book(), internal_stream_open(), internal_swap_vfs_read_verify(), internal_swap_vfs_write(), internal_verify_book(), internal_verify_book_reopen(), ra8_fs_close(), ra8_io_roundtrip_read_verify(), ra8_io_roundtrip_subdir_file(), rabook_import_compile_adapter(), sd_demo_read_payload(), sd_demo_write_payload(), sdhi_demo_read_and_verify(), sdhi_demo_write_payload(), and sh_sd_book_close().
|
nodiscard |
Consume one open directory cursor.
| [in,out] | directory | Open caller-owned cursor. |
Definition at line 786 of file ra8_fs_fat_dir.c.
References ra8_fs_dir_t::is_open, k_ra8_err_invalid_state, k_ra8_err_null_ptr, and k_ra8_ok.
Referenced by internal_native_dir_close(), and internal_native_listdir().
|
nodiscard |
Copy the next visible directory entry.
| [in,out] | directory | Open caller-owned cursor. |
| [out] | out | Stable entry value owned by the caller. |
| [out] | out_entry | True when out is populated; false at clean EOF. |
out survives later cursor calls. Definition at line 748 of file ra8_fs_fat_dir.c.
References internal_fat_dir_next(), k_ra8_err_invalid_state, k_ra8_err_null_ptr, k_ra8_fs_type_exfat, k_ra8_ok, priv_exfat_dir_next(), priv_lock_acquire(), priv_lock_release(), and ra8_fs_dir_next().
Referenced by internal_native_dir_next(), internal_native_listdir(), and ra8_fs_dir_next().
|
nodiscard |
Open a caller-owned directory cursor without holding the filesystem lock.
Path resolution is locked only for this call. Each later next reacquires and releases the lock, so client metadata and stream operations are valid between entries. Two cursor objects advance independently. The enumerated directory and its ancestors must not be mutated until close; mutation elsewhere is permitted.
| [in,out] | handle | Mounted filesystem. |
| [in] | path | Directory path. |
| [out] | directory | Idle caller-owned cursor. |
| k_ra8_ok | Cursor opened. |
| k_ra8_err_busy | directory is already open. |
handle is mounted. Definition at line 720 of file ra8_fs_fat_dir.c.
References internal_dir_open_locked(), k_ra8_err_null_ptr, k_ra8_ok, memset(), priv_lock_acquire(), priv_lock_release(), and ra8_fs_dir_open().
Referenced by internal_native_dir_open(), internal_native_listdir(), and ra8_fs_dir_open().
|
nodiscard |
Format a block device as a fresh, empty FAT12/FAT16/FAT32/exFAT volume.
Lays down a complete volume so the very next ra8_fs_mount() on the same backend detects exactly opts->type. The FAT variants are written as a superfloppy (no MBR) at LBA 0; exFAT is written into an MBR partition (see below). For the FAT variants this is a classic BPB layout:
The cluster size is chosen (when opts->sectors_per_cluster == 0) so the resulting count_of_clusters lands in the band the requested type requires per Microsoft "FAT: General Overview of On-Disk Format" sec 3.5 (FAT12 < 4085, 4085 <= FAT16 < 65525, FAT32 >= 65525). If the backend's capacity cannot satisfy opts->type – too small for FAT16/FAT32, or too large for FAT12/FAT16 even at the maximum cluster size – the call fails without writing anything.
exFAT (k_ra8_fs_type_exfat) is written the way a PC writes it, so a card formatted here mounts on a desktop: a DOS/MBR partition table at LBA 0 with one type-0x07 partition aligned at 1 MiB, and the volume itself inside that partition rather than at LBA 0. ra8_fs_mount() follows the partition table back (ra8_fs_mount_t::partition_base_lba records where it landed), and also mounts a card partitioned by a desktop. Because the partition cannot start at sector 0, the device must be big enough for the 1 MiB alignment gap ON TOP OF the 32 MiB minimum volume – a 32 MiB card is no longer formattable.
Inside the partition exFAT lays down its own on-disk structures instead of a FAT BPB: the 12-sector boot region (Main + Backup) with the VBR checksum sector, the single FAT, the allocation-bitmap cluster(s), the canonical compressed up-case table (which may span several clusters), and a root-directory cluster carrying the volume-label, allocation-bitmap, and up-case-table system directory entries. The image is fsck.exfat-clean and round-trips through ra8_fs_mount() plus the whole exFAT file API: ra8_fs_open() in every mode, ra8_fs_read(), ra8_fs_write(), ra8_fs_write_file(), ra8_fs_rename(), and ra8_fs_unlink().
| [in] | backend | Block-device implementation (read/write/get_capacity all non-NULL). Its write_block is driven during the format. |
| [in] | opts | Format options. type selects the variant; label is an optional 0..11 char volume label; sectors_per_cluster pins the cluster size (0 = auto-select). |
| k_ra8_ok | Volume formatted; ready to mount. |
| k_ra8_err_null_ptr | backend or opts is NULL. |
| k_ra8_err_invalid_arg | Backend has NULL callbacks, the reported block size is not a power of two in 512..4096, or sectors_per_cluster is non-zero and not a power of two in 1..128. |
| k_ra8_err_not_supported | opts->type is unknown / not a writable filesystem, or the device is too small to hold a partitioned exFAT volume (the 1 MiB alignment gap plus the 32 MiB minimum). |
| k_ra8_err_invalid_size | Capacity cannot satisfy opts->type. |
| k_ra8_err_* | Backend read/write failure (volume may be partially written on a mid-format I/O error). |
Definition at line 744 of file ra8_fs_fat_mount.c.
References internal_format_locked(), priv_lock_acquire(), priv_lock_release(), and ra8_fs_format().
Referenced by demo_fs_format_mount(), demo_fs_format_or_panic(), eoh_mount_or_halt(), etoc_mount_or_halt(), fs_fmt_run_exfat(), fs_fmt_run_one_type(), internal_demo_mount(), internal_demo_mount(), internal_demo_probe_fat(), internal_format_mount(), internal_pc_mount_or_halt(), internal_ra8_io_roundtrip_format_mount(), internal_swap_run_one(), main(), ra8_fs_format(), ra8_io_roundtrip_mount(), and sdhi_demo_mount_via_io().
|
nodiscard |
Enumerate directory entries; invoke cb once per visible entry.
Every supported filesystem enumerates any directory by path ("/" for the root, "/books" for a subdirectory) – exFAT included since #605. FAT's synthetic "." and ".." entries are not reported; exFAT has none to report. A subdirectory appears in its parent's listing like any other entry, with the directory bit set in the attr argument.
| [in] | handle | Mount handle. |
| [in] | path | Directory path ("/" or a nested path). |
| [in] | cb | Callback (must be non-NULL). |
| [in] | ctx | Cookie forwarded to the callback. |
| k_ra8_ok | Enumeration complete. |
| k_ra8_err_null_ptr | handle/cb NULL. |
| k_ra8_err_not_found | A path component does not exist. |
| k_ra8_err_invalid_arg | A path component names a file. |
Definition at line 711 of file ra8_fs_fat_dir.c.
References internal_listdir_locked(), priv_lock_acquire(), priv_lock_release(), and ra8_fs_listdir().
Referenced by demo_file_ops(), fileops_step_listdir(), fs_fmt_assert_empty_root(), ra8_fs_listdir(), and sh_sd_scan().
|
nodiscard |
Create a directory at path.
Resolves all-but-the-last path component to an existing parent directory, then creates the final component as a new, empty subdirectory. Nested paths are supported ("/books/scifi"), provided each intermediate component already exists. A partial allocation is rolled back on failure, so the volume is never leaked.
On FAT the new directory is stamped with its "." and ".." links, and a leaf that is not 8.3-representable is stored as a long name, exactly as ra8_fs_open() stores one. On exFAT the new directory is one zeroed cluster – entry type 0x00 is end-of-directory, so that IS an empty directory – and there are no dot entries at all, because exFAT has none.
An existing name is REFUSED with k_ra8_err_exists, whether it is a file or a directory. mkdir is not a create-or-replace verb; ra8_fs_write_file() is the one that replaces.
| [in] | handle | Mount handle. |
| [in] | path | NUL-terminated directory path to create. |
| k_ra8_ok | Directory created. |
| k_ra8_err_null_ptr | handle or path was NULL. |
| k_ra8_err_invalid_state | Mount is not in use. |
| k_ra8_err_invalid_arg | The leaf is empty, longer than 247 characters, or holds a character no FAT name may carry. |
| k_ra8_err_exists | The name already exists in the parent. |
| k_ra8_err_not_found | An intermediate component does not exist. |
| k_ra8_err_no_mem | Parent directory or volume is full. |
path. Definition at line 536 of file ra8_fs_fat_dirmk.c.
References internal_mkdir_locked(), priv_lock_acquire(), priv_lock_release(), and ra8_fs_mkdir().
Referenced by internal_native_mkdir(), internal_populate(), and ra8_fs_mkdir().
|
nodiscard |
Mount a FAT volume from a block-device backend, auto-selecting the first partition.
Reads sector 0 and, if it is not itself a boot sector, follows the partition table to the first volume: MBR partition 0, or – on a GPT disk (protective MBR type 0xEE) – the first Microsoft Basic Data entry. It then validates the BPB signature and bytes-per-sector, computes the cluster count, dispatches to FAT12 / FAT16 / FAT32, and caches the layout in *out_handle. Exactly equivalent to ra8_fs_mount_partition() with k_ra8_fs_partition_auto; use that sibling to reach any other partition.
| [in] | backend | Block-device implementation. Must remain alive for the lifetime of the mount. |
| [out] | out_handle | Populated mount handle on success. |
| k_ra8_ok | Volume mounted successfully. |
| k_ra8_err_null_ptr | backend or out_handle is NULL. |
| k_ra8_err_invalid_arg | Backend has NULL function pointers. |
| k_ra8_err_no_mem | No free mount slot. |
| k_ra8_err_validation_failed | BPB signature invalid / unsupported. |
Definition at line 762 of file ra8_fs_fat_mount.c.
References internal_mount_locked(), k_ra8_fs_partition_auto, priv_lock_acquire(), priv_lock_release(), and ra8_fs_mount().
Referenced by demo_fs_format_mount(), demo_fs_format_or_panic(), eoh_mount_or_halt(), etoc_mount_or_halt(), fileops_mount_volume(), fs_fmt_run_exfat(), fs_fmt_run_one_type(), imp_mount_or_halt(), internal_demo_mount(), internal_demo_mount(), internal_format_mount(), internal_mount(), internal_mount_image(), internal_mount_sd(), internal_native_mount(), internal_pc_mount_or_halt(), internal_ra8_io_roundtrip_format_mount(), internal_swap_run_one(), main(), ra8_fs_mount(), ra8_io_roundtrip_mount(), sd_demo_mount_or_halt(), sdhi_demo_mount_via_io(), selftest_mount_volume(), selftest_mount_volume(), selftest_mount_volume(), selftest_mount_volume(), selftest_mount_volume(), and sh_sd_mount().
|
nodiscard |
Mount a FAT/exFAT volume from a specific partition of a block device.
Generalises ra8_fs_mount() with an explicit partition selector so a multi-partition card or disk exposes every volume, not just the first. Sector 0 decides the table type: a GPT disk (protective MBR type 0xEE) selects entry index of the GPT partition-entry array; any other 0xAA55 MBR selects primary entry index (0-3). The chosen partition's first LBA becomes out_handle->partition_base_lba and every subsequent access is partition-relative. Passing k_ra8_fs_partition_auto reproduces ra8_fs_mount() exactly, including transparent superfloppy (LBA 0) mounts; an explicit index requires a partition table, so a superfloppy with no table returns k_ra8_err_not_found.
| [in] | backend | Block-device implementation. Must remain alive for the lifetime of the mount. |
| [in] | index | Zero-based partition index, or k_ra8_fs_partition_auto. |
| [out] | out_handle | Populated mount handle on success. |
| k_ra8_ok | Volume mounted successfully. |
| k_ra8_err_null_ptr | backend or out_handle is NULL. |
| k_ra8_err_invalid_arg | Backend has NULL function pointers. |
| k_ra8_err_no_mem | No free mount slot. |
| k_ra8_err_out_of_range | index is past the partition table. |
| k_ra8_err_not_found | The selected entry is empty, or there is no partition table to index. |
| k_ra8_err_not_supported | GPT entry-array geometry this backend cannot address (non-128-byte entries, or a first LBA above 32 bits). |
| k_ra8_err_validation_failed | BPB signature invalid / unsupported. |
Definition at line 773 of file ra8_fs_fat_mount.c.
References internal_mount_locked(), priv_lock_acquire(), priv_lock_release(), and ra8_fs_mount_partition().
Referenced by ra8_fs_mount_partition().
|
nodiscard |
Open or create a file by path, 8.3 or long.
A path that resolves to a DIRECTORY is rejected in every mode. In write mode that rejection is load-bearing: the truncate step would free the cluster chain holding the directory's contents and leave every file inside it unreachable. In read mode it prevents handing back the zero-byte handle a directory's DIR_FileSize of 0 would otherwise describe.
All three modes work on every filesystem this adapter mounts, exFAT included (#602). An exFAT write grows the file one cluster at a time out of the allocation bitmap, so the size a caller can create is bounded by the volume's free space rather than by RAM, and a fragmented volume is written the way the format intends: the entry set keeps NoFatChain while the run stays contiguous and drops it – materialising a real FAT chain over the clusters already allocated – the first time the next cluster is not the successor of the last.
| [in] | handle | Mount handle. |
| [in] | path | Path from the volume root, e.g. "HELLO.TXT" or "/Reading List/Chapter One.txt". Any component may be a long name of up to 247 characters. |
| [in] | mode | k_ra8_fs_mode_read, _write, or _append. |
| [out] | out_file | Populated file handle on success. |
| k_ra8_ok | File opened. |
| k_ra8_err_null_ptr | Any pointer arg is NULL. |
| k_ra8_err_invalid_arg | path names a directory (any mode), or a new name is empty, holds a character no name may carry, or is longer than the volume allows – 247 characters on FAT, 64 on exFAT. |
| k_ra8_err_not_found | Read mode and path doesn't exist. |
| k_ra8_err_access_denied | A writing mode (_write / _append) on a file whose read-only attribute is set; a read open of the same file succeeds. |
| k_ra8_err_no_mem | No free file slot, no directory slot, or the volume has no free cluster. |
| k_ra8_err_no_data | Write mode failed to allocate cluster. |
| k_ra8_err_not_supported | An exFAT entry set larger than this adapter rewrites (a name over 64 chars written by another implementation). |
Definition at line 569 of file ra8_fs_fat_file.c.
References priv_lock_acquire(), priv_lock_release(), priv_open_locked(), and ra8_fs_open().
Referenced by demo_read_test_file(), demo_read_verify(), eoh_provision_or_halt(), etoc_provision_one(), fileops_expect_absent(), fileops_read_back(), fs_fmt_create_and_verify(), fs_fmt_rename_and_verify(), imp_read_cache(), internal_compute_source_key(), internal_file_exists(), internal_mkfontimg_verify(), internal_mkfontimg_write(), internal_native_open(), internal_open_or_provision(), internal_pc_font_or_halt(), internal_pc_read_cache(), internal_read_stamp(), internal_read_whole_file(), internal_stream_book(), internal_stream_open(), internal_verify_book_reopen(), ra8_fs_open(), sd_demo_read_payload(), sd_demo_write_payload(), and sh_sd_book_open().
|
nodiscard |
Identify a FAT/exFAT volume without claiming a mount slot.
Runs the same superfloppy/MBR/GPT discovery and BPB/VBR validation as ra8_fs_mount(), but parses into temporary caller-invisible state and returns only the detected type. This is the authoritative probe used by the pluggable format registry: partitioned exFAT is not mistaken for an unknown format merely because LBA 0 is an MBR.
| [in] | backend | Readable block backend. |
| [out] | out_type | Detected FAT12/16/32 or exFAT type. |
| k_ra8_ok | A supported volume was validated. |
| k_ra8_err_null_ptr | Either argument was NULL. |
| k_ra8_err_invalid_arg | Required backend operations/capacity are invalid. |
| k_ra8_err_validation_failed | No supported volume is present. |
| k_ra8_err_* | Backend or partition-parse failure. |
out_type is untouched. Definition at line 753 of file ra8_fs_fat_mount.c.
References internal_probe_locked(), priv_lock_acquire(), priv_lock_release(), and ra8_fs_probe().
Referenced by internal_exfat_probe(), internal_fat_probe(), and ra8_fs_probe().
|
nodiscard |
Read up to max_len bytes; advance the cluster chain on cluster crossings.
| [in] | file | Open file (any mode). |
| [out] | buf | Destination buffer. |
| [in] | max_len | Maximum bytes to copy. |
| [out] | got_len | Actual bytes read (0 at EOF). |
| k_ra8_ok | Read completed (got_len may be 0 = EOF). |
| k_ra8_err_null_ptr | Any pointer arg is NULL. |
| k_ra8_err_invalid_state | file->in_use == 0. |
Definition at line 758 of file ra8_fs_fat_fileio.c.
References internal_read_locked(), priv_lock_acquire(), priv_lock_release(), and ra8_fs_read().
Referenced by demo_read_test_file(), demo_read_verify(), fileops_read_back(), fs_fmt_create_and_verify(), fs_fmt_rename_and_verify(), imp_read_cache(), internal_compare(), internal_demo_read_once(), internal_import_fs_read(), internal_native_read(), internal_pc_font_or_halt(), internal_pc_read_cache(), internal_ra8_io_roundtrip_read_verify(), internal_ra8_vfs_compress_load_blob(), internal_read(), internal_read_font(), internal_read_stamp(), internal_read_whole_file(), internal_source_read(), internal_swap_vfs_read_verify(), internal_verify_book(), ra8_fs_read(), ra8_io_roundtrip_read_verify(), sd_demo_read_payload(), sdhi_demo_read_and_verify(), sh_sd_book_read(), and sh_sd_comic_read().
|
nodiscard |
Rename a file within its own directory.
FAT12/16/32: re-files the entry under the new name – writing the new entry (with its long-name chain, if the new name needs one) before taking the old one away, so a failure between the two leaves the file reachable under both names rather than under neither. The cluster, the size and the attributes are carried across unchanged. Legacy note: this used to rewrite the 11-byte packed 8.3 name in the existing directory entry. exFAT: patches the Stream entry's NameLength and NameHash, rebuilds the Name entry, and recomputes the SetChecksum – supported when both names fit one Name entry (<= 15 characters), which keeps the entry-set length unchanged. Data clusters never move.
The LAST-ACCESS stamp advances; the modification stamp deliberately does not. A rename changes the name, not the bytes, so moving the modification time would tell every rsync, backup and "pick the newest image" heuristic that the contents changed. Neither format has a metadata-change field, so the access stamp is the honest record that the entry was touched.
| [in] | handle | Mount handle. |
| [in] | old_path | Existing path. |
| [in] | new_path | Replacement path, in the same directory (must not already exist). |
| k_ra8_ok | File renamed. |
| k_ra8_err_null_ptr | Any pointer arg is NULL. |
| k_ra8_err_not_found | old_path does not exist. |
| k_ra8_err_access_denied | old_path's read-only attribute is set. |
| k_ra8_err_exists | new_path already resolves. |
| k_ra8_err_not_supported | exFAT name longer than 15 characters, or the two paths are in different directories. |
| k_ra8_err_invalid_arg | The new leaf holds a character no FAT name may carry, or is longer than 247 characters. |
| k_ra8_err_no_mem | The directory has no room for the new entry. |
new_path resolves to the same data. Definition at line 808 of file ra8_fs_fat_dir.c.
References internal_rename_locked(), priv_lock_acquire(), priv_lock_release(), and ra8_fs_rename().
Referenced by fileops_suite_mutate(), fs_fmt_rename_and_verify(), internal_atomic_replace(), internal_native_rename(), and ra8_fs_rename().
|
nodiscard |
Remove an empty directory at path.
The symmetric partner of ra8_fs_mkdir(): resolves all-but-the-last path component to an existing parent, requires the final component to be an existing directory, requires that directory to be empty, then frees its clusters and takes its entry away. Nested paths are supported ("/books/scifi").
The emptiness proof runs before anything is freed, so a refusal costs the volume nothing. Only remnants are discounted – FAT's deleted (0xE5) slots and orphaned long-name entries, exFAT's entries with the in-use bit clear – so a directory another implementation left remnants in is still removable, while anything live makes it k_ra8_err_not_empty. On FAT the directory's own "." and ".." links do not count either; exFAT has none to discount.
The volume root is not removable, and neither is a file: use ra8_fs_unlink() for those.
| [in] | handle | Mount handle. |
| [in] | path | NUL-terminated directory path to remove. |
| k_ra8_ok | Directory removed. |
| k_ra8_err_null_ptr | handle or path was NULL. |
| k_ra8_err_invalid_state | Mount is not in use. |
| k_ra8_err_invalid_arg | path is the root, or names a file rather than a directory. |
| k_ra8_err_not_found | No such entry, or a component is missing. |
| k_ra8_err_not_empty | The directory still holds entries. |
| k_ra8_err_protocol_error | Corrupt chain, or a directory entry that claims no data cluster. |
path. path no longer resolves and its cluster is free. path cannot be orphaned by this call: that file's directory entry still exists, so the emptiness check refuses the removal first. Definition at line 545 of file ra8_fs_fat_dirmk.c.
References internal_rmdir_locked(), priv_lock_acquire(), priv_lock_release(), and ra8_fs_rmdir().
Referenced by internal_native_rmdir(), and ra8_fs_rmdir().
|
nodiscard |
Move the file offset to offset_bytes (clamped to size).
64-bit so any position in a >4 GiB exFAT file is reachable (#676).
| k_ra8_ok | Seek committed. |
| k_ra8_err_null_ptr | file is NULL. |
Definition at line 786 of file ra8_fs_fat_fileio.c.
References internal_seek_locked(), priv_lock_acquire(), priv_lock_release(), and ra8_fs_seek().
Referenced by internal_native_seek(), internal_seek(), internal_source_read(), ra8_fs_seek(), sh_sd_book_read(), and sh_sd_comic_read().
|
nodiscard |
Report the file's size in bytes (64-bit on exFAT, #676).
Definition at line 804 of file ra8_fs_fat_fileio.c.
References internal_size_locked(), priv_lock_acquire(), priv_lock_release(), and ra8_fs_size().
Referenced by imp_read_cache(), internal_crc_stream(), internal_mkfontimg_verify(), internal_native_size(), internal_read_whole_file(), internal_size(), internal_stream_open(), internal_verify_book_reopen(), ra8_fs_size(), and sh_sd_book_open().
|
nodiscard |
Report what a path names – file or directory – without opening it.
Resolves path the same way ra8_fs_open() does (parent walk, 8.3 lookup, VFAT long-name fallback on FAT; root-directory entry-set scan on exFAT) but stops at the directory entry and reads the answer straight out of it. Nothing is opened, so no file-table slot is consumed and a directory is reported as a directory rather than as a zero-byte file – which is what opening one would have made it look like, DIR_FileSize being 0 by definition.
Creation, modification, and access timestamps are decoded from the same entry. FAT access time is date-only and FAT carries no UTC offset; exFAT reports its 10-ms increments and offset-valid bits. A malformed third-party stamp is returned with timestamp.valid == false rather than guessed.
A path naming the volume root ("", "/") is answered from the mount geometry: it always exists and is always a directory. Because the root has no directory entry of its own, its three timestamp results are invalid.
| [in] | handle | Mount handle. |
| [in] | path | NUL-terminated path. Nested paths resolve on every supported filesystem, FAT12/16/32 and exFAT alike. |
| [out] | out | Receives the entry's metadata on success. |
| k_ra8_ok | Entry found; out populated. |
| k_ra8_err_null_ptr | Any pointer argument was NULL. |
| k_ra8_err_invalid_state | Mount is not in use. |
| k_ra8_err_not_found | Nothing at path (or an intermediate component is missing). |
| k_ra8_err_invalid_arg | A path component is longer than 247 characters. |
| k_ra8_err_* | Backend read failure. |
Definition at line 565 of file ra8_fs_fat_stat.c.
References internal_stat_locked(), priv_lock_acquire(), priv_lock_release(), and ra8_fs_stat().
Referenced by demo_file_ops(), internal_native_stat(), and ra8_fs_stat().
|
nodiscard |
Report the current offset (64-bit; see ra8_fs_seek).
Definition at line 795 of file ra8_fs_fat_fileio.c.
References internal_tell_locked(), priv_lock_acquire(), priv_lock_release(), and ra8_fs_tell().
Referenced by internal_native_tell(), internal_tell(), and ra8_fs_tell().
|
nodiscard |
Delete a file: mark its dir entry deleted and free its clusters.
FAT12/16/32: 0xE5-marks the entry – together with the VFAT long-name chain in front of it, if it has one – and frees the FAT chain. exFAT: clears the in-use bit on the whole entry set and frees the clusters in the allocation bitmap (the bitmap is authoritative).
A DIRECTORY is refused on both filesystems. Deleting one this way would free the chain that holds its children while their own entries still claim their clusters, leaving them allocated and unreachable – lost clusters that only a reformat recovers. Use ra8_fs_rmdir().
| [in] | handle | Mount handle. |
| [in] | path | NUL-terminated path to the file. |
| k_ra8_ok | File unlinked. |
| k_ra8_err_null_ptr | handle/path NULL. |
| k_ra8_err_invalid_arg | path names a directory. |
| k_ra8_err_access_denied | path's read-only attribute is set. |
| k_ra8_err_not_found | File doesn't exist. |
Definition at line 799 of file ra8_fs_fat_dir.c.
References internal_unlink_locked(), priv_lock_acquire(), priv_lock_release(), and ra8_fs_unlink().
Referenced by demo_file_ops(), fileops_suite_create(), fileops_suite_mutate(), fs_fmt_write_cycle(), internal_atomic_replace(), internal_compile_and_cache(), internal_native_unlink(), internal_write_stamp(), and ra8_fs_unlink().
|
nodiscard |
Unmount a previously mounted volume and release its slot.
On a FAT32 volume carrying a valid FSInfo sector this is also where the free-cluster count and next-free hint are written back, so a card the firmware wrote reports the right free space on a desktop and fsck.fat stops calling the summary wrong. The slot is released even when that write fails – an unmount that could be refused would be worse than a stale free count.
| [in,out] | handle | Mount handle returned by ra8_fs_mount(). |
| k_ra8_ok | Slot released. |
| k_ra8_err_null_ptr | handle is NULL. |
| k_ra8_err_invalid_state | Slot was not in use. |
| k_ra8_err_* | FSInfo writeback failed; the slot is still released. |
Definition at line 782 of file ra8_fs_fat_mount.c.
References internal_unmount_locked(), priv_lock_acquire(), priv_lock_release(), and ra8_fs_unmount().
Referenced by demo_thread_entry(), fileops_run_ladder(), fs_fmt_run_exfat(), fs_fmt_run_one_type(), internal_finish_image(), internal_native_unmount(), internal_run_font(), internal_swap_run_one(), main(), priv_mkbookimg_build_image(), ra8_fs_unmount(), ra8_sdfont_load(), selftest_host_pass(), and selftest_host_pass().
|
nodiscard |
Write len bytes; allocate new clusters from FAT free-space scan as needed.
New clusters come from a scan that starts at the mount's next-free hint rather than at cluster 2, reading the FAT through a one-sector cache, so appending stays linear in the bytes written instead of quadratic. The directory entry's modification time advances with every call, and again when the handle is closed.
| k_ra8_ok | Wrote all bytes; size + dir entry updated. |
| k_ra8_err_null_ptr | file or buf NULL. |
| k_ra8_err_invalid_state | file not opened for writing. |
| k_ra8_err_invalid_size | FAT volume and the write would push the file past 4 GiB - 1 (DIR_FileSize is 32-bit); exFAT files have no such cap (#676). |
| k_ra8_err_no_mem | Volume out of free clusters. |
Definition at line 767 of file ra8_fs_fat_fileio.c.
References internal_write_locked(), priv_lock_acquire(), priv_lock_release(), and ra8_fs_write().
Referenced by internal_native_write(), internal_ra8_io_roundtrip_write_subdir(), internal_ra8_vfs_compress_store_blob(), internal_stream(), internal_stream_book(), internal_swap_vfs_write(), internal_write(), ra8_fs_write(), ra8_io_roundtrip_subdir_file(), and sdhi_demo_write_payload().
|
nodiscard |
Create a whole file in one call (provisioning helper).
Convenience wrapper, and nothing more: on EVERY filesystem it opens path in write mode, writes data, and closes. It carried a second, exFAT-only implementation until exFAT learned to stream (#602) – a whole-file creator that needed one contiguous run and the entire payload in RAM at once. Both limits are gone with it, and the one remaining path means the two filesystems can no longer disagree about what this call does.
An existing path is REPLACED on both filesystems: write mode truncates it, so its old contents are discarded and its clusters returned to the volume's free space. Calling this twice with the same name leaves exactly one file, of the second call's contents, with no space lost to the first.
| [in] | handle | Mounted volume. |
| [in] | path | File path, UTF-8; nested paths resolve on both filesystems, provided every intermediate directory exists. |
| [in] | data | File contents. |
| [in] | len | Byte count; 0 leaves an empty file. |
| k_ra8_ok | File created and written. |
| k_ra8_err_null_ptr | Any pointer argument was NULL. |
| k_ra8_err_invalid_arg | Empty/oversized name, or path names an existing directory. |
| k_ra8_err_access_denied | path exists and its read-only attribute is set (it would be replaced – refused). |
| k_ra8_err_no_mem | Out of free clusters or directory slots. |
| k_ra8_err_* | Backend error. |
path. path resolves to exactly one entry of len bytes. path short, not stale. Definition at line 777 of file ra8_fs_fat_fileio.c.
References internal_write_file_locked(), priv_lock_acquire(), priv_lock_release(), and ra8_fs_write_file().
Referenced by demo_file_ops(), demo_write_test_file(), eoh_provision_or_halt(), etoc_provision_one(), fileops_step_write(), fs_fmt_create_and_verify(), internal_demo_run(), internal_dispatch_and_cache(), internal_open_or_provision(), internal_pc_font_or_halt(), internal_pc_persist_and_verify_or_halt(), internal_populate(), internal_write_stamp(), ra8_fs_write_file(), ra8_io_roundtrip_root_file(), rabook_compile_from_epub(), and sd_demo_write_payload().