ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_fs_fat_fileio.c File Reference

FAT read / write / seek / tell / size I/O. More...

#include <stddef.h>
#include <stdint.h>
#include "ra8_attributes.h"
#include "ra8_fs.h"
#include "ra8_fs_fat_internal.h"
Include dependency graph for ra8_fs_fat_fileio.c:

Go to the source code of this file.

Data Structures

struct  write_walk_t
 Forward waypoint carried across one write's grow-walks. More...

Functions

static ra8_err_t internal_skip_clusters (const ra8_fs_mount_t *m, uint32_t start, uint32_t n, uint32_t *out)
 Walk n clusters forward from start along the FAT chain.
static ra8_err_t internal_read_one_chunk (ra8_fs_file_t *file, uint8_t *buf, uint32_t remaining, uint32_t *out_take)
 Read up to one sector's worth of bytes at the file's current offset.
static ra8_err_t internal_read_span (ra8_fs_file_t *file, uint8_t *buf, uint32_t remaining, uint32_t *out_take)
 Read one span, serving zeros past exFAT's ValidDataLength.
static ra8_err_t internal_read_locked (ra8_fs_file_t *file, uint8_t *buf, uint32_t max_len, uint32_t *got_len)
 Read bytes – the guarded body of ra8_fs_read().
ra8_err_t priv_alloc_eoc_cluster (const ra8_fs_mount_t *m, uint32_t *out_c)
 Allocate a fresh cluster, mark it EOC, and return its number.
static ra8_err_t internal_walk_grow (const ra8_fs_mount_t *m, uint32_t start, uint32_t idx, uint32_t *out_cluster)
 Walk to cluster index idx from start, growing the chain as needed.
ra8_err_t priv_write_into_sector (const ra8_fs_mount_t *m, uint64_t lba, uint32_t off_in_sector, const uint8_t *src, uint32_t put)
 Implementation of priv_write_into_sector() – one read-modify-write.
static ra8_err_t internal_write_position (ra8_fs_file_t *file, write_walk_t *way, uint32_t idx, uint32_t *out_cluster)
 Position the write cursor at chain index idx, growing as needed.
static ra8_err_t internal_write_stream (ra8_fs_file_t *file, const uint8_t *buf, uint32_t len)
 Inner write loop: stream len bytes from buf into the file's chain.
static ra8_err_t internal_write_locked (ra8_fs_file_t *file, const uint8_t *buf, uint32_t len)
 Write bytes – the guarded body of ra8_fs_write().
static ra8_err_t internal_write_file_locked (ra8_fs_mount_t *handle, const char *path, const uint8_t *data, uint32_t len)
 Create a whole file – the guarded body of ra8_fs_write_file().
static ra8_err_t internal_seek_locked (ra8_fs_file_t *file, uint64_t offset_bytes)
 Move the cursor – the guarded body of ra8_fs_seek().
static ra8_err_t internal_tell_locked (const ra8_fs_file_t *file, uint64_t *out_offset)
 Report the cursor – the guarded body of ra8_fs_tell().
static ra8_err_t internal_size_locked (const ra8_fs_file_t *file, uint64_t *out_bytes)
 Report the size – the guarded body of ra8_fs_size().
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).

Detailed Description

FAT read / write / seek / tell / size I/O.

Cluster-chain skip/grow, sector-granular read and write streaming, and the public read/write/seek/tell/size entry points.

Since
0.1.0

Definition in file ra8_fs_fat_fileio.c.

Function Documentation

◆ internal_read_locked()

ra8_err_t internal_read_locked ( ra8_fs_file_t * file,
uint8_t * buf,
uint32_t max_len,
uint32_t * got_len )
static

Read bytes – the guarded body of ra8_fs_read().

Loops on priv_read_one_chunk, advancing file->offset after each chunk. Stops at EOF or when max_len met.

Parameters
[in,out]fileOpen file handle.
[out]bufDestination buffer.
[in]max_lenMaximum bytes to read.
[out]got_lenBytes actually read.
Returns
Error code.
Return values
k_ra8_okRead completed (possibly short at EOF).
k_ra8_err_null_ptrAny pointer was NULL.
k_ra8_err_invalid_stateFile is not open.
k_ra8_err_*Backend error.
Precondition
The library lock is held (or none is installed).
file, buf, and got_len are non-NULL.
File is in use.
Postcondition
On success, *got_len bytes were placed in buf and the file offset advanced by the same amount.
On failure, *got_len is 0.
Note
Not thread-safe per file; callers serialise.
Since
0.1.0

Definition at line 245 of file ra8_fs_fat_fileio.c.

References internal_read_locked(), internal_read_span(), k_ra8_err_null_ptr, and k_ra8_ok.

Referenced by internal_read_locked(), and ra8_fs_read().

◆ internal_read_one_chunk()

ra8_err_t internal_read_one_chunk ( ra8_fs_file_t * file,
uint8_t * buf,
uint32_t remaining,
uint32_t * out_take )
static

Read up to one sector's worth of bytes at the file's current offset.

Resolves the cluster covering file->offset, reads the containing sector, and copies the relevant slice into buf.

Parameters
[in,out]fileFile handle providing offset and chain root.
[out]bufDestination of the byte slice.
[in]remainingMaximum bytes the caller can accept.
[out]out_takeNumber of bytes actually copied.
Returns
Error code.
Return values
k_ra8_okSlice copied.
k_ra8_err_*Backend or FAT error.
Precondition
All pointers are non-NULL; file is in use.
file->offset < file->size_bytes.
Postcondition
On success, *out_take > 0 and buf[0..*out_take] populated.
file->offset is NOT advanced – caller does that.
Note
Thread-safety inherited from the backend.
Since
0.1.0

Definition at line 98 of file ra8_fs_fat_fileio.c.

References internal_skip_clusters(), k_cluster_first_data, k_ra8_ok, priv_bps(), priv_byte_copy(), priv_cluster_bytes(), priv_cluster_to_lba(), priv_read_sector(), and priv_sec_io().

Referenced by internal_read_span().

◆ internal_read_span()

ra8_err_t internal_read_span ( ra8_fs_file_t * file,
uint8_t * buf,
uint32_t remaining,
uint32_t * out_take )
static

Read one span, serving zeros past exFAT's ValidDataLength.

exFAT spec sec 7.4.5 splits a file in two: the prefix below ValidDataLength was written, and everything from there to DataLength was never initialised. Those bytes must read as zero, and the clusters behind them still hold whatever the previous tenant left, so serving them raw would hand a caller another file's data. A FAT handle has no such split – DIR_FileSize IS the written length – so it takes the same path with the two bounds equal and never reaches the hole arm.

Parameters
[in,out]fileOpen file handle.
[out]bufDestination of the span.
[in]remainingMaximum bytes the caller can accept.
[out]out_takeNumber of bytes actually produced.
Returns
Error code.
Return values
k_ra8_okSpan produced; *out_take > 0.
k_ra8_err_*Backend or FAT error.
Precondition
All pointers are non-NULL; the file is in use.
file->offset < file->size_bytes and remaining > 0.
Postcondition
On success *out_take <= remaining.
file->offset is NOT advanced – the caller does that.
Note
Thread-safety inherited from the backend.
Two single-condition decisions, nested rather than joined. The first sends an exFAT handle positioned past the written prefix to the zero arm; every other read falls through. The second clips a read that would cross OUT of the prefix, so the next span is served zeros instead of the raw cluster tail.
Since
0.1.0

Definition at line 195 of file ra8_fs_fat_fileio.c.

References internal_read_one_chunk(), k_ra8_fs_type_exfat, and k_ra8_ok.

Referenced by internal_read_locked().

◆ internal_seek_locked()

ra8_err_t internal_seek_locked ( ra8_fs_file_t * file,
uint64_t offset_bytes )
static

Move the cursor – the guarded body of ra8_fs_seek().

Clamps the requested offset to the current file size; the driver does not implement sparse files.

Parameters
[in,out]fileOpen file handle.
[in]offset_bytesDesired cursor position.
Returns
Error code.
Return values
k_ra8_okCursor moved (possibly clamped).
k_ra8_err_null_ptrfile was NULL.
k_ra8_err_invalid_stateFile not open.
Precondition
The library lock is held (or none is installed).
File is in use.
Postcondition
file->offset == min(offset_bytes, file->size_bytes).
No on-disk state modified.
Note
Not thread-safe per file; callers serialise.
Since
0.1.0

Definition at line 662 of file ra8_fs_fat_fileio.c.

References internal_seek_locked(), k_ra8_err_null_ptr, and k_ra8_ok.

Referenced by internal_seek_locked(), and ra8_fs_seek().

◆ internal_size_locked()

ra8_err_t internal_size_locked ( const ra8_fs_file_t * file,
uint64_t * out_bytes )
static

Report the size – the guarded body of ra8_fs_size().

Reads file->size_bytes.

Parameters
[in]fileOpen file handle.
[out]out_bytesReceives the file size in bytes.
Returns
Error code.
Return values
k_ra8_okSize returned.
k_ra8_err_null_ptrAny pointer was NULL.
k_ra8_err_invalid_stateFile not open.
Precondition
The library lock is held (or none is installed).
file and out_bytes are non-NULL.
File is in use.
Postcondition
*out_bytes == file->size_bytes.
No state modified.
Note
Thread-safety: single-word read; safe vs other readers.
Since
0.1.0

Definition at line 740 of file ra8_fs_fat_fileio.c.

References internal_size_locked(), k_ra8_err_null_ptr, and k_ra8_ok.

Referenced by internal_size_locked(), and ra8_fs_size().

◆ internal_skip_clusters()

ra8_err_t internal_skip_clusters ( const ra8_fs_mount_t * m,
uint32_t start,
uint32_t n,
uint32_t * out )
static

Walk n clusters forward from start along the FAT chain.

Used by the read path to position to the cluster covering file->offset. Stops early on EOC.

Parameters
[in]mMount providing FAT access.
[in]startFirst cluster of the chain.
[in]nNumber of clusters to walk.
[out]outReceives the cluster reached (or last before EOC).
Returns
Error code.
Return values
k_ra8_okWalked exactly n clusters.
k_ra8_err_invalid_stateHit EOC before walking n clusters.
k_ra8_err_*Backend error.
Precondition
m and out are non-NULL.
start is a valid cluster number.
Postcondition
On success, *out is the destination cluster.
On EOC failure, *out is the last valid cluster reached.
Note
Thread-safety inherited from the backend.
Since
0.1.0

Definition at line 53 of file ra8_fs_fat_fileio.c.

References k_ra8_err_invalid_state, k_ra8_ok, priv_fat_get(), and priv_is_eoc().

Referenced by internal_read_one_chunk().

◆ internal_tell_locked()

ra8_err_t internal_tell_locked ( const ra8_fs_file_t * file,
uint64_t * out_offset )
static

Report the cursor – the guarded body of ra8_fs_tell().

Reads file->offset.

Parameters
[in]fileOpen file handle.
[out]out_offsetReceives the current offset in bytes.
Returns
Error code.
Return values
k_ra8_okPosition returned.
k_ra8_err_null_ptrAny pointer was NULL.
k_ra8_err_invalid_stateFile not open.
Precondition
The library lock is held (or none is installed).
file and out_offset are non-NULL.
File is in use.
Postcondition
*out_offset == file->offset.
No state modified.
Note
Thread-safety: single-word read; safe vs other readers.
Since
0.1.0

Definition at line 703 of file ra8_fs_fat_fileio.c.

References internal_tell_locked(), k_ra8_err_null_ptr, and k_ra8_ok.

Referenced by internal_tell_locked(), and ra8_fs_tell().

◆ internal_walk_grow()

ra8_err_t internal_walk_grow ( const ra8_fs_mount_t * m,
uint32_t start,
uint32_t idx,
uint32_t * out_cluster )
static

Walk to cluster index idx from start, growing the chain as needed.

Like priv_skip_clusters but extends the chain (with new EOC clusters) when EOC is encountered before reaching idx.

Parameters
[in]mMount providing FAT access.
[in]startFirst cluster of the chain.
[in]idxIndex to walk to.
[out]out_clusterReceives the cluster at index idx.
Returns
Error code.
Return values
k_ra8_okReached / created cluster at idx.
k_ra8_err_*Backend, FAT, or no-mem error.
Precondition
m and out_cluster are non-NULL.
start is a valid cluster.
Postcondition
On success, *out_cluster is the cluster at offset idx.
On failure, FAT may have been partially extended.
Note
Thread-safety inherited from the backend.
Since
0.1.0

Definition at line 313 of file ra8_fs_fat_fileio.c.

References k_ra8_ok, priv_alloc_eoc_cluster(), priv_fat_get(), priv_fat_set(), and priv_is_eoc().

Referenced by internal_write_position().

◆ internal_write_file_locked()

ra8_err_t internal_write_file_locked ( ra8_fs_mount_t * handle,
const char * path,
const uint8_t * data,
uint32_t len )
static

Create a whole file – the guarded body of ra8_fs_write_file().

Drives the unlocked open / write / close bodies – taking the library lock again here would deadlock a non-recursive mutex. The public ra8_fs_write_file() is the wrapper that holds the lock across all three, so the whole creation is one atomic operation rather than three.

There is no longer a second, exFAT-only path here: exFAT streams through the same three calls now that ra8_fs_open accepts a writing mode on it (#602), which is the point – two implementations of one verb are two places for it to mean different things.

Parameters
[in,out]handleMounted volume.
[in]pathRoot-level file name, UTF-8.
[in]dataFile contents.
[in]lenByte count.
Returns
Error code.
Return values
k_ra8_okFile created and written.
k_ra8_err_null_ptrAny pointer argument was NULL.
k_ra8_err_invalid_stateMount is not in use.
k_ra8_err_*As documented for ra8_fs_write_file().
Precondition
The library lock is held (or none is installed).
handle, path and data are non-NULL.
Postcondition
On success path resolves to len bytes of data.
No file slot stays in use on any return path.
Note
Never call this from outside ra8_fs; it is the unlocked half.
Since
0.1.0

Definition at line 607 of file ra8_fs_fat_fileio.c.

References internal_write_file_locked(), internal_write_locked(), k_ra8_err_null_ptr, k_ra8_fs_mode_write, k_ra8_ok, priv_close_locked(), and priv_open_locked().

Referenced by internal_write_file_locked(), and ra8_fs_write_file().

◆ internal_write_locked()

ra8_err_t internal_write_locked ( ra8_fs_file_t * file,
const uint8_t * buf,
uint32_t len )
static

Write bytes – the guarded body of ra8_fs_write().

Forwards to priv_write_stream, then patches the on-disk dir entry with the updated first-cluster and file size.

Parameters
[in,out]fileFile handle.
[in]bufSource buffer.
[in]lenBytes to write.
Returns
Error code.
Return values
k_ra8_okAll bytes written.
k_ra8_err_null_ptrfile or buf was NULL.
k_ra8_err_invalid_stateFile not open or opened read-only.
k_ra8_err_*Backend, FAT, or no-mem error.
Precondition
The library lock is held (or none is installed).
file and buf are non-NULL.
file->mode != k_ra8_fs_mode_read.
Postcondition
On success, the file's dir entry on disk reflects new size.
On failure, partial bytes may already be on disk.
Note
Not thread-safe per file; callers serialise.
Since
0.1.0

Definition at line 519 of file ra8_fs_fat_fileio.c.

References internal_write_locked(), k_ra8_err_null_ptr, k_ra8_fs_mode_read, k_ra8_fs_type_exfat, k_ra8_ok, and priv_exfat_flush_set().

Referenced by internal_write_file_locked(), internal_write_locked(), and ra8_fs_write().

◆ internal_write_position()

ra8_err_t internal_write_position ( ra8_fs_file_t * file,
write_walk_t * way,
uint32_t idx,
uint32_t * out_cluster )
static

Position the write cursor at chain index idx, growing as needed.

Allocates the file's first cluster when it has none, then walks forward from the waypoint – not from the chain head – extending the chain if the walk runs off the end. The waypoint is advanced to wherever the walk landed.

Parameters
[in,out]fileFile handle whose chain is being extended.
[in,out]wayForward waypoint, advanced on success.
[in]idxChain index the write needs.
[out]out_clusterReceives the cluster at idx.
Returns
Error code.
Return values
k_ra8_okCursor positioned; *out_cluster is valid.
k_ra8_err_no_memThe volume has no free cluster to grow into.
k_ra8_err_*Backend or FAT error.
Precondition
file, way and out_cluster are non-NULL.
way->index <= idx (a write only moves forward).
Postcondition
On success the waypoint sits at idx.
On failure the chain may have been partially extended.
Note
Thread-safety inherited from the backend.
Since
0.1.0

Definition at line 404 of file ra8_fs_fat_fileio.c.

References write_walk_t::cluster, write_walk_t::index, internal_walk_grow(), k_cluster_first_data, k_ra8_ok, and priv_alloc_eoc_cluster().

Referenced by internal_write_stream().

◆ internal_write_stream()

ra8_err_t internal_write_stream ( ra8_fs_file_t * file,
const uint8_t * buf,
uint32_t len )
static

Inner write loop: stream len bytes from buf into the file's chain.

Allocates the first cluster on demand, then walks/grows the chain as needed and forwards each sector slice through priv_write_into_sector.

Parameters
[in,out]fileFile handle providing chain root and offset.
[in]bufSource buffer.
[in]lenNumber of bytes to write.
Returns
Error code.
Return values
k_ra8_okAll len bytes written.
k_ra8_err_*Backend, FAT, or no-mem error.
Precondition
All pointers are non-NULL; file is open for writing.
len > 0.
Postcondition
On success, file->offset advanced by len; size grew if needed.
On failure, partial bytes may already be on disk.
Note
Thread-safety inherited from the backend.
Since
0.1.0

Definition at line 454 of file ra8_fs_fat_fileio.c.

References internal_write_position(), k_ra8_ok, priv_bps(), priv_cluster_bytes(), priv_cluster_to_lba(), and priv_write_into_sector().

◆ priv_alloc_eoc_cluster()

ra8_err_t priv_alloc_eoc_cluster ( const ra8_fs_mount_t * m,
uint32_t * out_c )

Allocate a fresh cluster, mark it EOC, and return its number.

Combines priv_alloc_cluster with a priv_fat_set to the canonical EOC value. Used by the write path when the file chain needs to grow.

Parameters
[in]mMount providing FAT access.
[out]out_cReceives the allocated cluster.
Returns
Error code.
Return values
k_ra8_okCluster allocated and marked EOC.
k_ra8_err_*Backend or FAT error.
Precondition
m and out_c are non-NULL.
Volume has free clusters.
Postcondition
On success, *out_c is in range and FAT entry = EOC.
On failure, FAT may have been partially updated.
Note
Thread-safety inherited from the backend.
Since
0.1.0

Definition at line 278 of file ra8_fs_fat_fileio.c.

References k_ra8_ok, priv_alloc_cluster(), priv_eoc_write(), and priv_fat_set().

Referenced by internal_dir_grow(), internal_fat_mkdir(), internal_fat_trunc_extend(), internal_walk_grow(), and internal_write_position().

◆ priv_write_into_sector()

ra8_err_t priv_write_into_sector ( const ra8_fs_mount_t * m,
uint64_t lba,
uint32_t off_in_sector,
const uint8_t * src,
uint32_t put )

Implementation of priv_write_into_sector() – one read-modify-write.

Merge put bytes into one sector at lba, at off_in_sector.

Definition at line 341 of file ra8_fs_fat_fileio.c.

References k_ra8_ok, priv_byte_copy(), priv_read_sector(), priv_sec_io(), and priv_write_sector().

Referenced by internal_exfat_close_gap(), internal_write_stream(), and priv_exfat_write_stream().

◆ ra8_fs_read()

ra8_err_t ra8_fs_read ( ra8_fs_file_t * file,
uint8_t * buf,
uint32_t max_len,
uint32_t * got_len )
nodiscard

◆ ra8_fs_seek()

ra8_err_t ra8_fs_seek ( ra8_fs_file_t * file,
uint64_t offset_bytes )
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).

Return values
k_ra8_okSeek committed.
k_ra8_err_null_ptrfile is NULL.
Since
0.1.0

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().

◆ ra8_fs_size()

ra8_err_t ra8_fs_size ( const ra8_fs_file_t * file,
uint64_t * out_bytes )
nodiscard

◆ ra8_fs_tell()

ra8_err_t ra8_fs_tell ( const ra8_fs_file_t * file,
uint64_t * out_offset )
nodiscard

Report the current offset (64-bit; see ra8_fs_seek).

Since
0.1.0

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().

◆ ra8_fs_write()

ra8_err_t ra8_fs_write ( ra8_fs_file_t * file,
const uint8_t * buf,
uint32_t len )
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.

Return values
k_ra8_okWrote all bytes; size + dir entry updated.
k_ra8_err_null_ptrfile or buf NULL.
k_ra8_err_invalid_statefile not opened for writing.
k_ra8_err_invalid_sizeFAT 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_memVolume out of free clusters.
Postcondition
On success the entry's DIR_WrtTime / DIR_WrtDate name this write.
Since
0.1.0

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().

◆ ra8_fs_write_file()

ra8_err_t ra8_fs_write_file ( ra8_fs_mount_t * handle,
const char * path,
const uint8_t * data,
uint32_t len )
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.

Parameters
[in]handleMounted volume.
[in]pathFile path, UTF-8; nested paths resolve on both filesystems, provided every intermediate directory exists.
[in]dataFile contents.
[in]lenByte count; 0 leaves an empty file.
Return values
k_ra8_okFile created and written.
k_ra8_err_null_ptrAny pointer argument was NULL.
k_ra8_err_invalid_argEmpty/oversized name, or path names an existing directory.
k_ra8_err_access_deniedpath exists and its read-only attribute is set (it would be replaced – refused).
k_ra8_err_no_memOut of free clusters or directory slots.
k_ra8_err_*Backend error.
Precondition
No handle is open on path.
Postcondition
On success path resolves to exactly one entry of len bytes.
On success a replaced predecessor's clusters read as free.
Note
Not atomic: the truncate lands before the new content does, so a failure mid-write leaves path short, not stale.
Since
0.1.0

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().