84 return (bytes + cbytes - 1U) / cbytes;
118 uint32_t cur = start;
119 for (uint32_t i = 0U; i < idx; i++) {
174 const uint32_t sec_idx = off /
priv_bps(m);
175 const uint32_t sec_start = sec_idx *
priv_bps(m);
176 const uint32_t in_sector = off - sec_start;
177 uint32_t n =
priv_bps(m) - in_sector;
178 if (n > (hi - off)) {
186 for (uint32_t i = 0U; i < n; i++) {
187 sec[in_sector + i] = 0U;
234 if (new_nclus == 0U) {
241 file->first_cluster = 0U;
242 file->size_bytes = new_size;
245 uint32_t new_tail = 0U;
265 file->size_bytes = new_size;
311 file->first_cluster = cur;
318 while (have < new_nclus) {
369 const uint32_t old_size = (uint32_t)file->size_bytes;
373 if (old_nclus > 0U) {
378 const uint32_t base = (old_nclus - 1U) * cbytes;
379 const uint32_t cap = old_nclus * cbytes;
380 const uint32_t span_hi = (new_size < cap) ? new_size : cap;
390 file->size_bytes = new_size;
428 (uint32_t)file->size_bytes);
466 if (new_size < file->size_bytes) {
468 }
else if (new_size > file->size_bytes) {
474 file->cur_cluster = file->first_cluster;
475 file->walk_cache_idx = 0U;
476 file->walk_cache_cluster = file->first_cluster;
557 uint32_t new_tail = 0U;
575 file->tail_cluster = new_tail;
611 if (new_nclus < file->alloc_clusters) {
612 if (new_nclus == 0U) {
618 file->first_cluster = 0U;
619 file->no_fat_chain = 1U;
620 file->tail_cluster = 0U;
621 }
else if (file->no_fat_chain != 0U) {
622 const uint32_t first = file->first_cluster + new_nclus;
626 (uint64_t)(file->alloc_clusters - new_nclus) * cbytes,
631 file->tail_cluster = file->first_cluster + new_nclus - 1U;
638 file->alloc_clusters = new_nclus;
640 file->size_bytes = new_size;
641 if (file->valid_bytes > new_size) {
642 file->valid_bytes = new_size;
679 if (new_size < file->size_bytes) {
684 }
else if (new_size > file->size_bytes) {
689 if (want > (uint64_t)file->mount->count_of_clusters) {
696 file->size_bytes = new_size;
744 if (file ==
nullptr) {
748 return k_ra8_err_invalid_state;
752 e = internal_exfat_trunc(file, new_size);
763 if (file->offset > file->size_bytes) {
764 file->offset = file->size_bytes;
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_no_mem
Static buffer exhausted (no dynamic memory on this project).
@ 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_protocol_error
Protocol-level error (e.g.
@ k_ra8_err_invalid_size
Invalid size parameter (too large, too small, or misaligned).
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Minimal FAT12/FAT16/FAT32 filesystem adapter (read + write).
ra8_err_t priv_fat_get(const ra8_fs_mount_t *m, uint32_t cluster, uint32_t *out_value)
Fetch the FAT entry for cluster, returning the next-cluster value.
void priv_wr64(uint8_t *p, uint64_t v)
Encode a uint64_t into a byte buffer, little-endian.
ra8_err_t priv_fat_set(const ra8_fs_mount_t *m, uint32_t cluster, uint32_t value)
Write value into the FAT entry for cluster across every FAT copy.
uint64_t priv_cluster_to_lba(const ra8_fs_mount_t *m, uint32_t cluster)
Convert a cluster number into its first data-region LBA.
uint8_t priv_is_eoc(const ra8_fs_mount_t *m, uint32_t value)
Test whether value is an end-of-chain marker for this FAT type.
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.
uint32_t priv_eoc_write(const ra8_fs_mount_t *m)
End-of-chain value to write for this FAT type.
void priv_wr32(uint8_t *p, uint32_t v)
Encode a little-endian uint32_t into a byte buffer.
uint32_t priv_cluster_bytes(const ra8_fs_mount_t *m)
One mounted volume's cluster size in bytes.
ra8_err_t priv_write_sector(const ra8_fs_mount_t *m, uint64_t lba, const uint8_t *buf)
Write a single sector from a caller-provided buffer.
uint8_t * priv_sec_io(void)
The IO-role sector buffer (leaf data / bitmap sector transfers).
uint8_t * priv_sec_walk(void)
The WALK-role sector buffer (directory scans and entry RMW).
ra8_err_t priv_exfat_free_clusters(const ra8_fs_mount_t *m, const uint8_t *strm)
Implementation of priv_exfat_free_clusters() – run or chain, bitmap only.
ra8_err_t priv_exfat_ensure_clusters(ra8_fs_file_t *file, uint32_t need)
Grow a file's allocation until it owns at least need clusters.
ra8_err_t priv_exfat_flush_set(ra8_fs_file_t *file)
Rewrite a file's entry set from the handle, checksum last.
void priv_entry_set_cluster_size(uint8_t *entry, uint32_t cluster, uint32_t size)
Patch first-cluster + size back into a 32-byte directory entry.
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.
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_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_fat_entry_stamp_write(uint8_t *entry)
Advance a FAT directory entry's modification time and access date.
static ra8_err_t internal_fat_trunc_extend(ra8_fs_file_t *file, uint32_t tail, uint32_t have, uint32_t new_nclus, uint32_t cbytes)
Append zeroed clusters to a FAT file until it owns new_nclus.
static ra8_err_t internal_fat_trunc_grow(ra8_fs_file_t *file, uint32_t new_size, uint32_t cbytes)
Grow a FAT file to new_size, zero-filling [old_size, new_size).
static uint64_t internal_trunc_clusters(uint64_t bytes, uint32_t cbytes)
Clusters needed to hold bytes at cbytes bytes per cluster.
static ra8_err_t internal_trunc_zero_span(const ra8_fs_mount_t *m, uint32_t cluster, uint32_t lo, uint32_t hi)
Write real zeros over the byte range [lo, hi) inside one cluster.
static ra8_err_t internal_truncate_locked(ra8_fs_file_t *file, uint64_t new_size)
Truncate the file behind file – the guarded body of ra8_fs_truncate.
static ra8_err_t internal_fat_trunc_commit(ra8_fs_file_t *file)
Rewrite a FAT file's directory entry after its length changed.
static ra8_err_t internal_trunc_walk(const ra8_fs_mount_t *m, uint32_t start, uint32_t idx, uint32_t *out)
Walk idx clusters forward along a chain from start.
static ra8_err_t internal_exfat_free_run(const ra8_fs_mount_t *m, uint32_t first, uint64_t nbytes, uint8_t nofat)
Release a cluster run by describing it as a Stream-extension entry.
static ra8_err_t internal_exfat_shrink_chain_tail(ra8_fs_file_t *file, uint32_t new_nclus, uint32_t cbytes)
Trim a FAT-chained exFAT file to new_nclus clusters.
static ra8_err_t internal_fat_trunc(ra8_fs_file_t *file, uint32_t new_size)
Truncate a FAT file to new_size and commit its directory entry.
static ra8_err_t internal_exfat_trunc(ra8_fs_file_t *file, uint64_t new_size)
Truncate an exFAT file to new_size and flush its entry set.
static ra8_err_t internal_fat_trunc_shrink(ra8_fs_file_t *file, uint32_t new_size, uint32_t cbytes)
Free the cluster tail past new_size on a FAT file.
static ra8_err_t internal_exfat_trunc_shrink(ra8_fs_file_t *file, uint64_t new_size, uint32_t cbytes)
Free an exFAT file's cluster tail past new_size.
@ k_exfat_strm_off_dlen
Stream-ext DataLength (low 32 used).
@ k_exfat_strm_off_clus
Stream-ext FirstCluster.
@ k_exfat_strm_off_flags
Stream-ext GeneralSecondaryFlags.
@ k_exfat_entry_bytes
Directory entry size.
@ k_exfat_secflag_poss
GeneralSecondaryFlags: AllocationPossible.
@ k_exfat_secflag_alloc
AllocationPossible | NoFatChain.
@ k_cluster_first_data
Cluster numbers start at 2.
@ k_ra8_fs_fat_max_file_bytes
4 GiB - 1: max DIR_FileSize.
@ k_ra8_fs_type_exfat
exFAT (read + streaming write + format).
@ k_ra8_fs_mode_read
Read-only, must exist.
Cached parse of one mounted FAT volume.