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

exFAT unlink / rename / listdir mutation helpers. More...

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

Go to the source code of this file.

Functions

ra8_err_t priv_exfat_bitmap_clear (const ra8_fs_mount_t *m, uint64_t bmp_lba, uint32_t clus, uint32_t count)
 Clear a contiguous cluster run in the allocation bitmap.
static ra8_err_t internal_exfat_take_set (const ra8_fs_mount_t *m, exfat_cursor_t *cur, const uint16_t *name, uint32_t nlen, uint32_t sc, exfat_setpos_t *pos, uint8_t *strm_copy, uint8_t *out_match)
 Consume a set's secondary entries, recording positions + matching.
static ra8_err_t internal_exfat_try_set (const ra8_fs_mount_t *m, exfat_cursor_t *cur, exfat_setpos_t at, const uint8_t *e, const uint16_t *need, uint32_t nlen, exfat_setpos_t *pos, uint32_t max_pos, uint32_t *out_count, uint8_t *file_copy, uint8_t *strm_copy)
 Test one File entry set against a needle, recording its positions.
ra8_err_t priv_exfat_find_set (const ra8_fs_mount_t *m, const exfat_dir_t *dir, const char *path, exfat_setpos_t *pos, uint32_t max_pos, uint32_t *out_count, uint8_t *file_copy, uint8_t *strm_copy)
 Implementation of priv_exfat_find_set() – one aligned walk of a directory.
static ra8_err_t internal_exfat_put_entry (const ra8_fs_mount_t *m, const exfat_setpos_t *where, const uint8_t *entry)
 Rewrite one 32-byte directory entry at a recorded position.
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_drop_set (const ra8_fs_mount_t *m, const exfat_setpos_t *pos, uint32_t count)
 Retire an entry set by clearing the in-use bit on every entry.
ra8_err_t priv_exfat_unlink_at (const ra8_fs_mount_t *m, const exfat_dir_t *dir, const char *name)
 Delete a FILE named name from dir.
ra8_err_t priv_exfat_unlink (const ra8_fs_mount_t *m, const char *path)
 Delete a file on an exFAT volume, at any depth.
static uint32_t internal_exfat_build_rename_set (uint8_t *set, const uint8_t *file_e, const uint8_t *strm_e, const uint16_t *new_name, uint32_t new_len)
 Assemble a file's directory set under a new name, keeping its data.
static ra8_err_t internal_exfat_rename_prepare (const ra8_fs_mount_t *m, const char *old_path, const char *new_path, exfat_dir_t *out_parent, const char **out_old, const char **out_new)
 Resolve a rename's two paths to one shared parent plus two leaves.
static ra8_err_t internal_exfat_place_rename (const ra8_fs_mount_t *m, const exfat_dir_t *parent, const exfat_setpos_t *pos, uint32_t old_count, const uint8_t *set, uint32_t bytes)
 Write a rebuilt rename set, in place when it fits, else by relocation.
ra8_err_t priv_exfat_rename (const ra8_fs_mount_t *m, const char *old_path, const char *new_path)
 Rename a root-level file on an exFAT volume, at any storable length.
static ra8_err_t internal_exfat_gather_name (const ra8_fs_mount_t *m, exfat_cursor_t *cur, uint32_t sc, uint32_t nlen, char *name, uint32_t cap)
 Consume a set's Name entries and assemble the name as UTF-8.
static ra8_err_t internal_exfat_list_emit (const ra8_fs_mount_t *m, exfat_cursor_t *cur, const uint8_t *e, ra8_fs_dirent_t *out, bool *out_entry)
 Copy one File entry set into a stable directory value.
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_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.

Detailed Description

exFAT unlink / rename / listdir mutation helpers.

Locates a directory-entry set, frees its clusters and bitmap bits, and renames it – rewriting the whole set under the new name, in place when the entry count is unchanged and by relocation when the name needs more or fewer Name entries – plus the exFAT directory listing.

Since
0.1.0

Definition in file ra8_fs_fat_exfat_mutate.c.

Function Documentation

◆ internal_exfat_build_rename_set()

uint32_t internal_exfat_build_rename_set ( uint8_t * set,
const uint8_t * file_e,
const uint8_t * strm_e,
const uint16_t * new_name,
uint32_t new_len )
static

Assemble a file's directory set under a new name, keeping its data.

Starts from the file's current File + Stream entries, so every field that is NOT the name rides across untouched: the create / modify timestamps, the attributes, FirstCluster, DataLength, ValidDataLength and the secondary flags. It then overwrites exactly what a rename changes – the File entry's SecondaryCount, the Stream entry's NameLength + NameHash, and a run of Name entries carrying fifteen UTF-16 units apiece. The access stamp is refreshed just before the SetChecksum is recomputed over the whole set.

A name of 16+ units needs more than one Name entry, so the built set can be longer OR shorter than the one on the volume. That is precisely why the old in-place patch could not do this and ::priv_exfat_place_rename has to decide where the result lands (#603).

Parameters
[out]setBuffer of at least k_exfat_max_set_bytes.
[in]file_eThe file's current 32-byte File entry.
[in]strm_eThe file's current 32-byte Stream-extension entry.
[in]new_nameReplacement name as UTF-16 code units.
[in]new_lenNumber of units in new_name (1..k_exfat_name_cap).
Returns
The total byte length of the built set.
Return values
>0Number of bytes written into set.
Precondition
set, file_e, strm_e and new_name are non-NULL.
new_len is at least 1 and at most k_exfat_name_cap.
Postcondition
set holds a complete entry set with a valid SetChecksum.
No volume state is modified.
Note
Access stamp only; the create + modify stamps ride along in file_e.
Since
0.1.0

Definition at line 428 of file ra8_fs_fat_exfat_mutate.c.

References k_exfat_entry_bytes, k_exfat_entry_name, k_exfat_name_off, k_exfat_name_per_entry, k_exfat_off_file_csum, k_exfat_off_file_secnt, k_exfat_off_strm_hash, k_exfat_strm_off_nlen, priv_byte_copy(), priv_exfat_file_stamp_access(), priv_exfat_name_hash(), priv_exfat_set_checksum(), and priv_wr16().

Referenced by priv_exfat_rename().

◆ internal_exfat_gather_name()

ra8_err_t internal_exfat_gather_name ( const ra8_fs_mount_t * m,
exfat_cursor_t * cur,
uint32_t sc,
uint32_t nlen,
char * name,
uint32_t cap )
static

Consume a set's Name entries and assemble the name as UTF-8.

Reads the sc - 1 secondaries that follow the Stream entry, collecting whole UTF-16 code units, then converts the lot to UTF-8 in one step. Non-Name secondaries are consumed and skipped so the caller's cursor stays aligned.

Collecting units and converting once is what makes the conversion possible at all. The old loop copied the LOW BYTE of each unit straight into the output, so U+00E9 came back as the single byte 0xE9 – not valid UTF-8 – and U+4F60 came back as a backtick (#606). A variable-width encoding cannot be produced one fixed-width unit at a time into a byte-indexed buffer.

A set whose units cannot be expressed in UTF-8 at all – an unpaired surrogate, which no conforming writer produces – yields an empty name, and priv_exfat_listdir reports nothing for that entry rather than a name that would not re-open the file.

Parameters
[in]mMounted exFAT volume.
[in,out]curDirectory cursor (just past the Stream entry).
[in]scSecondaryCount from the File entry.
[in]nlenNameLength from the Stream entry, in UTF-16 units.
[out]nameReceives the NUL-terminated UTF-8 name.
[in]capCapacity of name in bytes.
Returns
Error code.
Return values
k_ra8_okAll secondaries consumed; name terminated.
k_ra8_err_*Backend read failure mid-set.
Precondition
cur sits immediately after the set's Stream entry.
cap is at least 1.
Postcondition
cur sits immediately after the set's last secondary, whatever the name turned out to be – an unconvertible one must not desynchronise the walk.
name is NUL-terminated, and empty when the units were not UTF-8.
Note
Helper of priv_exfat_listdir (complexity split).
Since
0.1.0

Definition at line 685 of file ra8_fs_fat_exfat_mutate.c.

References k_exfat_entry_bytes, k_exfat_entry_name, k_exfat_name_cap, k_exfat_name_off, k_exfat_name_per_entry, k_ra8_ok, priv_exfat_next_entry(), priv_rd16(), and priv_utf16_to_utf8().

Referenced by internal_exfat_list_emit().

◆ internal_exfat_list_emit()

ra8_err_t internal_exfat_list_emit ( const ra8_fs_mount_t * m,
exfat_cursor_t * cur,
const uint8_t * e,
ra8_fs_dirent_t * out,
bool * out_entry )
static

Copy one File entry set into a stable directory value.

The per-set body of priv_exfat_listdir, extracted so the walk stays under the statement-count gate. Reads the Stream entry, decides the size a directory reports (0, not its allocation), gathers the name as UTF-8 and fills out – unless the name is one no UTF-8 string encodes, which is reported as absent rather than as mojibake (#606).

Parameters
[in]mMounted exFAT volume.
[in,out]curCursor positioned just after the File entry.
[in]eThe 32-byte File entry.
[out]outStable caller-owned entry value.
[out]out_entryTrue when a valid name was copied.
Returns
Error code.
Return values
k_ra8_okThe set was consumed (and emitted, unless nameless).
k_ra8_err_*Backend read failure mid-set.
Precondition
All pointers are non-NULL; cur follows e.
e[0] is k_exfat_entry_file.
Postcondition
cur sits past the set's last secondary.
out_entry is true exactly when out contains a visible entry.
Note
Helper of priv_exfat_dir_next (complexity split).
Since
0.1.0

Definition at line 746 of file ra8_fs_fat_exfat_mutate.c.

References ra8_fs_dirent_t::attr, internal_exfat_gather_name(), k_exfat_attr_directory, k_exfat_entry_bytes, k_exfat_entry_stream, k_exfat_name_u8_cap, k_exfat_off_file_attr, k_exfat_off_file_secnt, k_exfat_strm_off_dlen, k_exfat_strm_off_nlen, k_ra8_ok, memcpy(), ra8_fs_dirent_t::name, priv_exfat_next_entry(), priv_rd64(), ra8_fs_dirent_t::size_bytes, and strlen().

Referenced by priv_exfat_dir_next().

◆ internal_exfat_place_rename()

ra8_err_t internal_exfat_place_rename ( const ra8_fs_mount_t * m,
const exfat_dir_t * parent,
const exfat_setpos_t * pos,
uint32_t old_count,
const uint8_t * set,
uint32_t bytes )
static

Write a rebuilt rename set, in place when it fits, else by relocation.

When the new set has the SAME entry count as the old one, every slot is rewritten where it already sits – the cheap path a same-length rename keeps, and the only path a checksum-and-name edit ever needed. Otherwise the set changed length: a fresh run of new_count free slots is located (growing the directory if it must), the whole set is written there, and only THEN is the old set retired by clearing bit 7 of each of its type bytes.

That order is the crash-safe one. The new set names the same clusters as the old, so a failure after the write but before the drop leaves two names for one file – a transient the next scan resolves – whereas dropping first would orphan the clusters if the write never completed (#603).

Parameters
[in]mMounted exFAT volume.
[in]parentDirectory that holds the set.
[in]posPositions of the OLD set's entries.
[in]old_countNumber of entries in the old set.
[in]setThe rebuilt set bytes (File + Stream + Name entries).
[in]bytesLength of set; bytes / 32 is the new entry count.
Returns
Error code.
Return values
k_ra8_okThe set was placed and any old set retired.
k_ra8_err_no_memThe directory has no room for a longer set.
k_ra8_err_*Backend read / write failure.
Precondition
pos came from priv_exfat_find_set for old_count entries.
bytes is a positive multiple of k_exfat_entry_bytes.
Postcondition
On k_ra8_ok exactly one entry set answers to the new name.
On relocation the old set's slots read as deleted.
Note
Helper of priv_exfat_rename (statement-count split).
Since
0.1.0

Definition at line 561 of file ra8_fs_fat_exfat_mutate.c.

References internal_exfat_put_entry(), k_exfat_entry_bytes, k_ra8_ok, priv_exfat_drop_set(), priv_exfat_find_dir_space(), and priv_exfat_write_dir_set().

Referenced by priv_exfat_rename().

◆ internal_exfat_put_entry()

ra8_err_t internal_exfat_put_entry ( const ra8_fs_mount_t * m,
const exfat_setpos_t * where,
const uint8_t * entry )
static

Rewrite one 32-byte directory entry at a recorded position.

Thin wrapper over priv_exfat_write_dir_set for a single entry.

Parameters
[in]mMounted exFAT volume.
[in]whereEntry position from priv_exfat_find_set.
[in]entryThe 32 bytes to write.
Returns
Error code.
Return values
k_ra8_okEntry rewritten.
k_ra8_err_*Backend read/write failure.
Precondition
m and entry are non-NULL.
where came from priv_exfat_find_set.
Postcondition
The on-disk entry equals entry.
No other directory bytes change.
Note
Read-modify-write of one sector.
Since
0.1.0

Definition at line 269 of file ra8_fs_fat_exfat_mutate.c.

References exfat_setpos_t::cluster, exfat_setpos_t::index, k_exfat_entry_bytes, and priv_exfat_write_dir_set().

Referenced by internal_exfat_place_rename(), and priv_exfat_drop_set().

◆ internal_exfat_rename_prepare()

ra8_err_t internal_exfat_rename_prepare ( const ra8_fs_mount_t * m,
const char * old_path,
const char * new_path,
exfat_dir_t * out_parent,
const char ** out_old,
const char ** out_new )
static

Resolve a rename's two paths to one shared parent plus two leaves.

Resolves both parents and requires them to be the same directory: this rename rewrites an entry set where it lies, so it cannot move one between directories. Both leaves must be real names – the volume root is neither renameable nor a legal destination. Extracted from priv_exfat_rename so that function stays inside the size gate, and the exFAT mirror of ::priv_rename_prepare.

Parameters
[in]mMounted exFAT volume.
[in]old_pathExisting path.
[in]new_pathReplacement path (same directory).
[out]out_parentReceives the shared parent directory.
[out]out_oldReceives a pointer to the old leaf name.
[out]out_newReceives a pointer to the new leaf name.
Returns
Error code.
Return values
k_ra8_okResolved; outputs populated.
k_ra8_err_invalid_argA path names the volume root.
k_ra8_err_not_supportedThe two paths are in different directories.
k_ra8_err_*Resolution / backend failure.
Precondition
Every pointer argument is non-NULL; the mount is exFAT.
Neither path is currently held open.
Postcondition
On success both leaves point into their caller's path strings.
No volume state is modified.
Note
Not thread-safe; callers serialise.
Since
0.1.0

Definition at line 494 of file ra8_fs_fat_exfat_mutate.c.

References exfat_dir_t::cluster, k_ra8_err_invalid_arg, k_ra8_err_not_supported, k_ra8_ok, priv_exfat_resolve_parent(), and priv_strlen().

Referenced by priv_exfat_rename().

◆ internal_exfat_take_set()

ra8_err_t internal_exfat_take_set ( const ra8_fs_mount_t * m,
exfat_cursor_t * cur,
const uint16_t * name,
uint32_t nlen,
uint32_t sc,
exfat_setpos_t * pos,
uint8_t * strm_copy,
uint8_t * out_match )
static

Consume a set's secondary entries, recording positions + matching.

Reads the sc secondaries following a File entry, snapshots each entry's (cluster, index) into pos starting at slot 1, and checks the set against path: the first secondary must be a Stream entry with the right NameLength, the rest must be Name entries whose UTF-16 chunks equal the path. The cursor always consumes all sc entries so the caller's walk stays aligned.

Parameters
[in]mMounted exFAT volume.
[in,out]curDirectory cursor (just past the File entry).
[in]nameTarget name as UTF-16 code units.
[in]nlenNumber of units in name.
[in]scSecondaryCount from the File entry.
[out]posPosition array (slot 0 already holds the File).
[out]strm_copyReceives the 32-byte Stream entry when matched.
[out]out_matchReceives 1 when the whole set matches name.
Returns
Error code.
Return values
k_ra8_okAll sc secondaries were consumed.
k_ra8_err_*Backend read failure mid-set.
Precondition
cur sits immediately after the set's File entry.
pos has at least 1 + sc slots.
Postcondition
cur sits immediately after the set's last secondary.
On k_ra8_ok out_match is 0 or 1.
Note
Helper of priv_exfat_find_set (complexity split).
Since
0.1.0

Definition at line 78 of file ra8_fs_fat_exfat_mutate.c.

References exfat_cursor_t::cluster, exfat_cursor_t::entry_in_cluster, k_exfat_entry_bytes, k_exfat_entry_name, k_exfat_entry_stream, k_exfat_name_per_entry, k_exfat_strm_off_nlen, k_ra8_ok, priv_byte_copy(), priv_exfat_name_chunk_eq(), and priv_exfat_next_entry().

Referenced by internal_exfat_try_set().

◆ internal_exfat_try_set()

ra8_err_t internal_exfat_try_set ( const ra8_fs_mount_t * m,
exfat_cursor_t * cur,
exfat_setpos_t at,
const uint8_t * e,
const uint16_t * need,
uint32_t nlen,
exfat_setpos_t * pos,
uint32_t max_pos,
uint32_t * out_count,
uint8_t * file_copy,
uint8_t * strm_copy )
static

Test one File entry set against a needle, recording its positions.

The per-File-entry body of priv_exfat_find_set, extracted so the walk stays under the statement-count gate. On a match it fills pos and out_count; otherwise it reports k_ra8_err_not_found so the caller keeps scanning.

Parameters
[in]mMounted exFAT volume.
[in,out]curCursor positioned just after the File entry e.
[in]atPosition of e itself.
[in]eThe 32-byte File entry.
[in]needNeedle name as UTF-16 units.
[in]nlenNumber of units in need.
[out]posReceives the set's positions (File entry first).
[in]max_posCapacity of pos.
[out]out_countReceives the entry count on a match.
[out]file_copyReceives the 32-byte File entry.
[out]strm_copyReceives the 32-byte Stream-extension entry.
Returns
Error code.
Return values
k_ra8_okThis set matches; outputs populated.
k_ra8_err_not_foundThis set is not need; keep scanning.
k_ra8_err_no_memThe set has more entries than max_pos.
k_ra8_err_*Backend read failure mid-set.
Precondition
All pointers are non-NULL; e[0] is k_exfat_entry_file.
cur sits immediately after e.
Postcondition
cur sits past the set's last secondary.
On a match out_count is 1 + SecondaryCount.
Note
Helper of priv_exfat_find_set (statement-count split).
Since
0.1.0

Definition at line 162 of file ra8_fs_fat_exfat_mutate.c.

References internal_exfat_take_set(), k_exfat_entry_bytes, k_exfat_off_file_secnt, k_ra8_err_no_mem, k_ra8_err_not_found, k_ra8_ok, and priv_byte_copy().

Referenced by priv_exfat_find_set().

◆ priv_exfat_bitmap_clear()

ra8_err_t priv_exfat_bitmap_clear ( const ra8_fs_mount_t * m,
uint64_t bmp_lba,
uint32_t clus,
uint32_t count )

Clear a contiguous cluster run in the allocation bitmap.

Mirror of priv_exfat_bitmap_mark: clears one bit per cluster, batching read-modify-write per bitmap sector, and pulls the mount's next-free hint back to the space just released.

Parameters
[in]mMounted exFAT volume.
[in]bmp_lbaFirst LBA (volume-relative) of the bitmap.
[in]clusFirst cluster of the run.
[in]countNumber of clusters to mark free.
Returns
Error code.
Return values
k_ra8_okAll bits cleared and written.
k_ra8_err_*Backend read/write failure.
Precondition
m is non-NULL; the run is within the bitmap.
The entries referencing the run are already retired.
Postcondition
The count bits for the run read as 0.
Only the affected bitmap sectors are rewritten.
Note
Not thread-safe; callers serialise.
Since
0.1.0

Definition at line 28 of file ra8_fs_fat_exfat_mutate.c.

References k_cluster_first_data, k_exfat_bit_mask, k_exfat_bit_shift, k_ra8_ok, priv_alloc_hint_lower(), priv_bps(), priv_exfat_bmp_switch(), priv_sec_io(), and priv_write_sector().

Referenced by priv_exfat_free_clusters(), and priv_exfat_mkdir().

◆ priv_exfat_dir_next()

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.

Advances the cursor and copies one stable name, attribute mask, and size.

Parameters
[in]mMounted exFAT volume.
[in,out]curIndependent caller-owned directory cursor state.
[out]outStable copied entry value.
[out]out_entryTrue for one copied entry; false at clean end.
Returns
Media, corruption, bound, or clean-end status.
Return values
k_ra8_okOne entry was copied or clean end was reached.
k_ra8_err_*Media, entry-set, name, or cursor-bound failure.
Precondition
Required pointers are non-NULL and cur was initialized for m.
The caller holds the filesystem serialization required by m.
Postcondition
The cursor advances monotonically and no callback is invoked.
Clean end leaves out_entry false without exposing sector scratch.
Note
The caller owns filesystem serialization around this operation.
Since
0.1.0

Definition at line 786 of file ra8_fs_fat_exfat_mutate.c.

References internal_exfat_list_emit(), k_exfat_entry_bytes, k_exfat_entry_eod, k_exfat_entry_file, k_exfat_scan_limit, k_ra8_err_invalid_size, k_ra8_err_not_found, k_ra8_ok, priv_exfat_next_entry(), and exfat_cursor_t::scanned.

Referenced by priv_exfat_listdir(), and ra8_fs_dir_next().

◆ priv_exfat_drop_set()

ra8_err_t priv_exfat_drop_set ( const ra8_fs_mount_t * m,
const exfat_setpos_t * pos,
uint32_t count )

Retire an entry set by clearing the in-use bit on every entry.

exFAT's delete marker is bit 7 of the type byte, so an entry keeps its type and its contents and simply stops being live. Shared by priv_exfat_unlink_at and priv_exfat_rmdir, which differ in what they prove BEFORE reaching this point, not in how they retire a set.

Parameters
[in]mMounted exFAT volume.
[in]posPositions from priv_exfat_find_set.
[in]countNumber of positions.
Returns
Error code.
Return values
k_ra8_okEvery entry rewritten with its in-use bit clear.
k_ra8_err_*Backend read/write failure.
Precondition
m and pos are non-NULL; count is the set's entry count.
pos came from priv_exfat_find_set on this volume.
Postcondition
The name no longer resolves.
No cluster is freed here.
Note
Not thread-safe; callers serialise.
Since
0.1.0

Definition at line 323 of file ra8_fs_fat_exfat_mutate.c.

References exfat_setpos_t::cluster, exfat_setpos_t::index, internal_exfat_put_entry(), k_exfat_entry_bytes, k_exfat_inuse_bit, k_ra8_ok, and priv_exfat_next_entry().

Referenced by internal_exfat_place_rename(), priv_exfat_rmdir(), and priv_exfat_unlink_at().

◆ priv_exfat_find_set()

◆ priv_exfat_free_clusters()

◆ priv_exfat_listdir()

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.

Walks dir's entry stream; every in-use File entry set yields one callback with the ASCII name (truncated to the local buffer, NUL-terminated), the low attribute byte, and the size. Deleted entries and non-file sets (bitmap, up-case table, label) are skipped. Subdirectories are reported like any other entry set, with k_exfat_attr_directory set in the attribute byte.

Parameters
[in]mMounted exFAT volume.
[in]dirDirectory to enumerate (priv_exfat_dir_root for the root).
[in]cbCallback invoked once per visible entry set.
[in]ctxCookie forwarded to the callback.
Returns
Error code.
Return values
k_ra8_okEnumeration completed (EOD or end of run reached).
k_ra8_err_*Backend read failure.
Precondition
m, dir and cb are non-NULL; mount is exFAT.
dir locates an existing directory on this volume.
Postcondition
cb ran once per in-use entry set.
No volume state modified.
Note
Names longer than the buffer are truncated (still NUL-terminated).
Since
0.1.0

Definition at line 819 of file ra8_fs_fat_exfat_mutate.c.

References ra8_fs_dirent_t::attr, k_ra8_ok, ra8_fs_dirent_t::name, priv_exfat_cursor_init(), priv_exfat_dir_next(), and ra8_fs_dirent_t::size_bytes.

Referenced by internal_listdir_locked().

◆ priv_exfat_rename()

ra8_err_t priv_exfat_rename ( const ra8_fs_mount_t * m,
const char * old_path,
const char * new_path )

Rename a root-level file on an exFAT volume, at any storable length.

Rewrites the whole entry set under the new name: the Stream entry's NameLength + NameHash, a run of one Name entry per fifteen UTF-16 units, the File entry's SecondaryCount, and the recomputed SetChecksum. When the new name keeps the entry count the set is rewritten in place; when it needs more or fewer Name entries the set is relocated to a fresh run of slots (growing the directory if needed) and the old set is then retired, so names up to k_exfat_name_cap units – the same range ra8_fs_write_file() writes – all rename. The data itself never moves: FirstCluster, DataLength and the timestamps ride across untouched.

Parameters
[in]mMounted exFAT volume.
[in]old_pathExisting root-level name.
[in]new_pathReplacement name (must not exist).
Returns
Error code.
Return values
k_ra8_okFile renamed.
k_ra8_err_not_foundold_path does not exist.
k_ra8_err_existsnew_path already resolves.
k_ra8_err_invalid_argnew_path is empty, over the name cap, or not well-formed UTF-8.
k_ra8_err_not_supportedThe paths cross directories, or a non-ASCII name on a volume with a foreign up-case table.
k_ra8_err_no_memThe directory cannot grow to hold a longer set.
Precondition
m and both paths are non-NULL; mount is exFAT.
The file is not open.
Postcondition
new_path resolves to the same data; old_path is gone.
File attributes, size, and clusters are unchanged.
Note
Root-directory namespace only.
Since
0.1.0

Definition at line 593 of file ra8_fs_fat_exfat_mutate.c.

References internal_exfat_build_rename_set(), internal_exfat_place_rename(), internal_exfat_rename_prepare(), k_exfat_attr_read_only, k_exfat_entry_bytes, k_exfat_max_set_bytes, k_exfat_name_cap, k_exfat_off_file_attr, k_exfat_set_max_entries, k_ra8_err_access_denied, k_ra8_err_exists, k_ra8_err_invalid_arg, k_ra8_ok, priv_exfat_find(), priv_exfat_find_set(), and priv_exfat_needle_units().

◆ priv_exfat_unlink()

ra8_err_t priv_exfat_unlink ( const ra8_fs_mount_t * m,
const char * path )

Delete a file on an exFAT volume, at any depth.

Resolves the path's parent, then hands the leaf to priv_exfat_unlink_at: the entry set is located, every entry's in-use bit (bit 7 of the entry type) is cleared, and the clusters are freed in the allocation bitmap. A set carrying k_exfat_attr_directory is refused: freeing a directory's run would strand every entry inside it (#604).

Parameters
[in]mMounted exFAT volume.
[in]pathFile path, UTF-8, nested or root-level.
Returns
Error code.
Return values
k_ra8_okFile unlinked.
k_ra8_err_invalid_argpath names a directory or the volume root.
k_ra8_err_not_foundNo such file, or a component is missing.
k_ra8_err_*Directory or bitmap write failure.
Precondition
m and path are non-NULL; mount is exFAT.
The file is not open.
Postcondition
The name no longer resolves; its clusters are free.
Other directory entries are untouched.
Note
Not thread-safe; callers serialise.
Since
0.1.0

Definition at line 383 of file ra8_fs_fat_exfat_mutate.c.

References k_ra8_err_invalid_arg, k_ra8_ok, priv_exfat_resolve_parent(), priv_exfat_unlink_at(), and priv_strlen().

◆ priv_exfat_unlink_at()

ra8_err_t priv_exfat_unlink_at ( const ra8_fs_mount_t * m,
const exfat_dir_t * dir,
const char * name )

Delete a FILE named name from dir.

The directory-scoped half of priv_exfat_unlink: locates the entry set, refuses one carrying k_exfat_attr_directory, retires it and frees its clusters. ::priv_exfat_create calls it directly, having already resolved the parent, so a create-over-an-existing-name replaces rather than duplicates (#603).

Parameters
[in]mMounted exFAT volume.
[in]dirDirectory holding the name.
[in]nameLeaf name (ASCII).
Returns
Error code.
Return values
k_ra8_okFile deleted.
k_ra8_err_invalid_argname is a DIRECTORY; rmdir is the verb.
k_ra8_err_not_foundNo such name in dir.
k_ra8_err_*Bitmap or backend failure.
Precondition
m, dir and name are non-NULL; m->type is exFAT.
No open file handle refers to the name.
Postcondition
On success the name no longer resolves and its clusters are free.
On k_ra8_err_invalid_arg the volume is unchanged.
Note
Not thread-safe; callers serialise.
Since
0.1.0

Definition at line 347 of file ra8_fs_fat_exfat_mutate.c.

References k_exfat_attr_directory, k_exfat_attr_read_only, k_exfat_entry_bytes, k_exfat_off_file_attr, k_exfat_set_max_entries, k_ra8_err_access_denied, k_ra8_err_invalid_arg, k_ra8_ok, priv_exfat_drop_set(), priv_exfat_find_set(), and priv_exfat_free_clusters().

Referenced by priv_exfat_unlink().