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

exFAT directory scan and read-path open. 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_exfat_read.c:

Go to the source code of this file.

Functions

uint32_t priv_strlen (const char *s)
 Length of a NUL-terminated string.
char priv_ascii_upper (char c)
 Uppercase an ASCII character (others returned unchanged).
static uint8_t internal_exfat_is_volume (const uint8_t *buf)
 Detect an exFAT volume from its boot sector.
static ra8_err_t internal_exfat_parse (ra8_fs_mount_t *m, const uint8_t *buf)
 Parse an exFAT VBR into the mount's geometry fields.
void priv_exfat_upcase_verify (ra8_fs_mount_t *m)
 Decide whether this build's fold matches the mounted volume's table.
ra8_err_t priv_parse_volume (ra8_fs_mount_t *m)
 Parse the volume at the current base: exFAT first, then FAT BPB.
void priv_exfat_dir_root (const ra8_fs_mount_t *m, exfat_dir_t *out)
 Fill out with the volume root's directory location.
void priv_exfat_dir_from_set (const ra8_fs_mount_t *m, const uint8_t *strm, exfat_dir_t *out)
 Build a directory location from a Stream entry's allocation fields.
void priv_exfat_cursor_init (const exfat_dir_t *dir, exfat_cursor_t *out)
 Aim a fresh cursor at the start of dir.
ra8_err_t priv_exfat_step_cluster (const ra8_fs_mount_t *m, uint32_t cluster, uint32_t contig_end, uint32_t *out_next)
 Compute the cluster that follows cluster in a directory.
ra8_err_t priv_exfat_next_entry (const ra8_fs_mount_t *m, exfat_cursor_t *cur, uint8_t *out)
 Fetch the next 32-byte directory entry, following the cluster chain.
uint8_t priv_exfat_name_chunk_eq (const uint8_t *entry, const uint16_t *name, uint32_t pos, uint32_t nlen)
 Compare one file-name entry's 15 UTF-16 units against a needle.
ra8_err_t priv_exfat_name_to_units (const ra8_fs_mount_t *m, const char *path, uint16_t *out, uint32_t *out_units)
 Convert a caller's exFAT name to code units, refusing what will not fold.
ra8_err_t priv_exfat_needle_units (const ra8_fs_mount_t *m, const char *name, uint16_t *out, uint32_t *out_units, ra8_err_t too_long)
 Convert a leaf name to code units, mapping over-long to too_long.
static ra8_err_t internal_exfat_match_set (const ra8_fs_mount_t *m, exfat_cursor_t *cur, const uint16_t *name, uint32_t nlen, uint8_t *out_strm)
 Read a stream-ext + name set and test it against path.
ra8_err_t priv_exfat_find (const ra8_fs_mount_t *m, const exfat_dir_t *dir, const char *path, uint8_t *out_strm, uint8_t *out_attr)
 Find a name in ONE exFAT directory.
static void internal_exfat_seed_read (ra8_fs_file_t *file, ra8_fs_mount_t *handle, const uint8_t *strm)
 Populate a read handle from the file's Stream-extension entry.
ra8_err_t priv_exfat_open (ra8_fs_mount_t *handle, const char *path, ra8_fs_mode_t mode, ra8_fs_file_t **out_file)
 Open a file (read-only) on a mounted exFAT volume.

Detailed Description

exFAT directory scan and read-path open.

Linear cursor over 32-byte exFAT directory entries plus name matching and the read-side open path.

Since
0.1.0

Definition in file ra8_fs_fat_exfat_read.c.

Function Documentation

◆ internal_exfat_is_volume()

uint8_t internal_exfat_is_volume ( const uint8_t * buf)
static

Detect an exFAT volume from its boot sector.

exFAT stamps the ASCII string "EXFAT " (5 chars + 3 spaces) at offset 3 of the VBR, where a FAT BPB carries OEM text.

Parameters
[in]bufSector-0 (VBR) contents (>= 512 bytes).
Returns
1 if buf is an exFAT VBR, else 0.
Return values
1exFAT signature present.
0Not exFAT.
Precondition
buf is non-NULL.
buf holds at least one sector.
Postcondition
No state modified.
buf is unmodified.
Note
Pure function.
Since
0.1.0

Definition at line 66 of file ra8_fs_fat_exfat_read.c.

References k_exfat_fsname_len, and k_exfat_off_fsname.

Referenced by priv_parse_volume().

◆ internal_exfat_match_set()

ra8_err_t internal_exfat_match_set ( const ra8_fs_mount_t * m,
exfat_cursor_t * cur,
const uint16_t * name,
uint32_t nlen,
uint8_t * out_strm )
static

Read a stream-ext + name set and test it against path.

Called with cur positioned just after a 0x85 File entry. Reads the 0xC0 stream-extension entry and the following 0xC1 name entries; on a full match hands the WHOLE Stream entry back rather than a chosen few of its fields. That is the cheaper contract for everyone: the callers want different subsets of it – stat the length and cluster, an open also ValidDataLength and the flags – and a copy of 32 bytes they already had in hand costs less than another out-parameter each time one is needed.

Parameters
[in]mMounted exFAT volume.
[in,out]curCursor (advanced past the consumed entries).
[in]nameTarget name as UTF-16 code units.
[in]nlenNumber of units in name.
[out]out_strmReceives the matched 32-byte Stream-extension entry.
Returns
Error code.
Return values
k_ra8_okMatch; out_strm populated.
k_ra8_err_not_foundThis set is not name.
k_ra8_err_*Backend read failure.
Precondition
All pointers are non-NULL; cur follows a 0x85 entry.
name is a flat (root-level) name, already converted to units.
Postcondition
On match out_strm mirrors the on-disk Stream entry.
On non-match out_strm is untouched.
Note
Leftover name entries self-heal in priv_exfat_find.
Since
0.1.0

Definition at line 336 of file ra8_fs_fat_exfat_read.c.

References k_exfat_entry_bytes, k_exfat_entry_name, k_exfat_entry_stream, k_exfat_name_per_entry, k_exfat_strm_off_nlen, k_ra8_err_not_found, k_ra8_ok, priv_byte_copy(), priv_exfat_name_chunk_eq(), and priv_exfat_next_entry().

Referenced by priv_exfat_find().

◆ internal_exfat_parse()

ra8_err_t internal_exfat_parse ( ra8_fs_mount_t * m,
const uint8_t * buf )
static

Parse an exFAT VBR into the mount's geometry fields.

Maps exFAT's sector-relative region offsets + log2 geometry onto the shared FAT fields so priv_cluster_to_lba / priv_fat_get (FAT32 path) serve the data + FAT regions unchanged. BytesPerSectorShift values 9..12 (512..4096 bytes) are accepted, and the shift must agree with the DEVICE's block size seeded into m->bytes_per_sector at mount – a volume formatted for a different sector size than the medium presents is unmountable, not reinterpretable (#683).

Parameters
[in,out]mMount with backend bound, base LBA set, and bytes_per_sector seeded from the backend.
[in]bufVBR contents (sector 0 at the volume base).
Returns
Error code.
Return values
k_ra8_okexFAT geometry stored; m->type set.
k_ra8_err_not_supportedBytesPerSectorShift outside 9..12, or it disagrees with the device's block size.
Precondition
m and buf are non-NULL.
buf is a validated exFAT VBR (::priv_exfat_is_volume true).
Postcondition
On success m carries the exFAT region geometry.
On failure m is left unmounted.
Note
Not thread-safe; serialize mount operations.
The shift guard is one compound decision of three conditions; its vectors live with the tests that drive it, cited as libs/ra8_fs/src/ra8_fs_fat_exfat_read.c@priv_exfat_parse.
Since
0.1.0

Definition at line 106 of file ra8_fs_fat_exfat_read.c.

References ra8_fs_mount_t::bytes_per_sector, ra8_fs_mount_t::count_of_clusters, ra8_fs_mount_t::fat_size_sectors, ra8_fs_mount_t::first_data_lba, ra8_fs_mount_t::first_fat_lba, ra8_fs_mount_t::first_root_lba, k_exfat_bps_shift_max, k_exfat_bps_shift_min, k_exfat_foff_vol_len, k_exfat_off_bps_shift, k_exfat_off_clus_count, k_exfat_off_fat_lba, k_exfat_off_fat_len, k_exfat_off_heap_lba, k_exfat_off_num_fats, k_exfat_off_root_clus, k_exfat_off_spc_shift, k_ra8_err_not_supported, k_ra8_fs_type_exfat, k_ra8_ok, ra8_fs_mount_t::num_fats, priv_exfat_upcase_verify(), priv_rd32(), priv_rd64(), ra8_fs_mount_t::reserved_sectors, ra8_fs_mount_t::root_cluster, ra8_fs_mount_t::root_entries, ra8_fs_mount_t::sectors_per_cluster, ra8_fs_mount_t::total_sectors, and ra8_fs_mount_t::type.

Referenced by priv_parse_volume().

◆ internal_exfat_seed_read()

void internal_exfat_seed_read ( ra8_fs_file_t * file,
ra8_fs_mount_t * handle,
const uint8_t * strm )
static

Populate a read handle from the file's Stream-extension entry.

Everything a READ needs and nothing a write does: the chain head, the two lengths, and the contiguity flag. The streaming fields stay zeroed because a read handle never grows the file – but valid_bytes is not one of them, because the bytes past it must read as zero (exFAT spec sec 7.4.5) rather than as whatever the previous tenant of those clusters left.

Parameters
[out]fileFreshly claimed file slot.
[in]handleOwning mount.
[in]strmThe file's 32-byte Stream-extension entry.
Returns
Nothing.
Precondition
All pointers are non-NULL and strm came from priv_exfat_find.
The slot is not already in use.
Postcondition
file is in use, positioned at byte 0, in read mode.
The read accelerator is seeded at the chain head.
Note
Not thread-safe; callers serialise filesystem operations.
Since
0.1.0

Definition at line 448 of file ra8_fs_fat_exfat_read.c.

References k_exfat_off_strm_valid, k_exfat_secflag_no_fat, k_exfat_strm_off_clus, k_exfat_strm_off_dlen, k_exfat_strm_off_flags, k_ra8_fs_mode_read, priv_rd32(), and priv_rd64().

Referenced by priv_exfat_open().

◆ priv_ascii_upper()

char priv_ascii_upper ( char c)

Uppercase an ASCII character (others returned unchanged).

Maps a-z to A-Z; any other byte is returned unchanged.

Parameters
[in]cInput character.
Returns
Uppercased character.
Return values
cThe (possibly) uppercased value.
Precondition
None.
c is a byte value.
Postcondition
No state modified.
Result depends only on c.
Note
Avoids compound conditions (MC/DC).
Since
0.1.0

Definition at line 37 of file ra8_fs_fat_exfat_read.c.

Referenced by priv_exfat_upcase_unit().

◆ priv_exfat_cursor_init()

void priv_exfat_cursor_init ( const exfat_dir_t * dir,
exfat_cursor_t * out )

Aim a fresh cursor at the start of dir.

Copies the location's first cluster and run bound into the cursor and zeroes the position and scan counters, so every directory walk in the adapter starts the same way instead of open-coding the initialiser.

Parameters
[in]dirDirectory to walk.
[out]outReceives the initialised cursor.
Returns
Nothing.
Precondition
dir and out are non-NULL.
dir was produced by priv_exfat_dir_root or priv_exfat_dir_from_set.
Postcondition
The cursor addresses the directory's first entry.
The cursor's scan counter is 0.
Note
Pure initialisation; trivially thread-safe.
Since
0.1.0

Definition at line 196 of file ra8_fs_fat_exfat_read.c.

References exfat_cursor_t::cluster, exfat_dir_t::cluster, exfat_cursor_t::contig_end, exfat_dir_t::contig_end, exfat_cursor_t::entry_in_cluster, and exfat_cursor_t::scanned.

Referenced by internal_dir_open_locked(), internal_exchk_scan_dir(), internal_exfat_dir_is_empty(), internal_exfat_locate_label(), priv_exfat_find(), priv_exfat_find_bitmap(), priv_exfat_find_set(), and priv_exfat_listdir().

◆ priv_exfat_dir_from_set()

void priv_exfat_dir_from_set ( const ra8_fs_mount_t * m,
const uint8_t * strm,
exfat_dir_t * out )

Build a directory location from a Stream entry's allocation fields.

A FAT-chained directory (nofat == 0) keeps a run bound of 0 and is walked through the FAT. A contiguous one records the cluster one past its last, derived from DataLength – which for an exFAT directory is its ALLOCATION, not a byte count, so the division is exact for every directory this driver writes.

Parameters
[in]mMounted exFAT volume.
[in]strmThe entry set's 32-byte Stream-extension entry.
[out]outReceives the directory location.
Returns
Nothing.
Precondition
m, strm and out are non-NULL.
strm came from priv_exfat_find or priv_exfat_find_set.
Postcondition
out->cluster is the entry's FirstCluster.
out->contig_end is 0, or that cluster plus the run's cluster count.
Note
Pure computation; trivially thread-safe.
Since
0.1.0

Definition at line 183 of file ra8_fs_fat_exfat_read.c.

References exfat_dir_t::cluster, exfat_dir_t::contig_end, k_exfat_secflag_no_fat, k_exfat_strm_off_clus, k_exfat_strm_off_dlen, k_exfat_strm_off_flags, priv_cluster_bytes(), priv_rd32(), and priv_rd64().

Referenced by internal_exchk_set_clusters(), internal_exfat_enter(), and internal_exfat_rmdir_locate().

◆ priv_exfat_dir_root()

void priv_exfat_dir_root ( const ra8_fs_mount_t * m,
exfat_dir_t * out )

Fill out with the volume root's directory location.

The root's first cluster comes from the VBR and its contents are always reached through the FAT – exFAT has no other shape for it – so the run bound is left at 0.

Parameters
[in]mMounted exFAT volume.
[out]outReceives the root's location.
Returns
Nothing.
Precondition
m and out are non-NULL; m->type is exFAT.
The mount carries a parsed VBR.
Postcondition
out->cluster is m->root_cluster.
out->contig_end is 0 (FAT-chained).
Note
Pure accessor; trivially thread-safe.
Since
0.1.0

Definition at line 171 of file ra8_fs_fat_exfat_read.c.

References exfat_dir_t::cluster, exfat_dir_t::contig_end, ra8_fs_mount_t::root_cluster, exfat_dir_t::self_cluster, and exfat_dir_t::self_index.

Referenced by internal_exchk_tree(), internal_exfat_locate_label(), internal_setattr_exfat(), internal_utime_exfat(), priv_exfat_find_bitmap(), priv_exfat_resolve_dir(), and priv_exfat_resolve_parent().

◆ priv_exfat_find()

ra8_err_t priv_exfat_find ( const ra8_fs_mount_t * m,
const exfat_dir_t * dir,
const char * path,
uint8_t * out_strm,
uint8_t * out_attr )

Find a name in ONE exFAT directory.

Streams dir's entries, matching each File entry set against path; stops at end-of-directory, the end of the directory's run, or the scan bound. This is a single-directory lookup, not a path resolver – pass a leaf name and the directory it should be in, or use priv_exfat_lookup, which resolves a whole path and then calls this (#605).

Parameters
[in]mMounted exFAT volume.
[in]dirDirectory to search.
[in]pathTarget leaf name, UTF-8; leading slashes are skipped.
[out]out_strmReceives the matched 32-byte Stream-extension entry – first cluster, both lengths and the secondary flags, so a caller decodes the fields it needs rather than every caller paying for another out-parameter.
[out]out_attrLow byte of the File entry's FileAttributes, which is where k_exfat_attr_directory lives. Callers that act on the entry MUST consult it: a directory answers this lookup exactly like a file, and treating one as a file frees its cluster chain (#604).
Returns
Error code.
Return values
k_ra8_okEntry found; outputs populated.
k_ra8_err_not_foundNo matching entry in dir.
k_ra8_err_*Backend read failure.
Precondition
All pointers are non-NULL; m->type is exFAT.
dir locates an existing directory on this volume.
Postcondition
On success out_strm mirrors the on-disk Stream entry.
Scan is bounded by k_exfat_scan_limit entries.
Note
Not thread-safe; callers serialise.
Since
0.1.0

Definition at line 371 of file ra8_fs_fat_exfat_read.c.

References internal_exfat_match_set(), k_exfat_entry_bytes, k_exfat_entry_eod, k_exfat_entry_file, k_exfat_name_cap, k_exfat_off_file_attr, k_exfat_scan_limit, k_ra8_err_no_mem, k_ra8_err_not_found, k_ra8_ok, priv_exfat_cursor_init(), priv_exfat_name_to_units(), priv_exfat_next_entry(), and exfat_cursor_t::scanned.

Referenced by internal_exfat_mkdir_check(), priv_exfat_lookup(), and priv_exfat_rename().

◆ priv_exfat_name_chunk_eq()

uint8_t priv_exfat_name_chunk_eq ( const uint8_t * entry,
const uint16_t * name,
uint32_t pos,
uint32_t nlen )

Compare one file-name entry's 15 UTF-16 units against a needle.

Case-insensitive under the canonical up-case table (priv_exfat_upcase_unit), which is the fold the exFAT specification defines name matching against. Positions at/after nlen are treated as already matched (tail padding).

It used to compare the low byte of each unit with an ASCII fold and reject any unit whose high byte was set, so a name outside ASCII never matched at all (#606).

Parameters
[in]entry32-byte file-name (0xC1) entry.
[in]nameTarget name as UTF-16 code units.
[in]posIndex of the first name unit this entry covers.
[in]nlenTotal name length in UTF-16 units.
Returns
1 if this slice matches, else 0.
Return values
1Slice matches.
0At least one folded unit differs.
Precondition
entry and name are non-NULL.
name holds at least nlen units.
Postcondition
No state modified.
Inputs are unmodified.
Note
Pure function.
Since
0.1.0

Definition at line 258 of file ra8_fs_fat_exfat_read.c.

References k_exfat_name_off, k_exfat_name_per_entry, priv_exfat_upcase_unit(), and priv_rd16().

Referenced by internal_exfat_match_set(), and internal_exfat_take_set().

◆ priv_exfat_name_to_units()

ra8_err_t priv_exfat_name_to_units ( const ra8_fs_mount_t * m,
const char * path,
uint16_t * out,
uint32_t * out_units )

Convert a caller's exFAT name to code units, refusing what will not fold.

The one place an exFAT path becomes the units every on-disk structure counts in. Two refusals, both loud: a name that is not well-formed UTF-8, and a name outside ASCII on a volume whose up-case table this build cannot reproduce – because the NameHash it would store is one the host disagrees with (see priv_exfat_upcase_verify).

Parameters
[in]mMounted exFAT volume.
[in]pathCaller's name, NUL-terminated UTF-8, no leading slash.
[out]outReceives up to k_exfat_name_cap code units.
[out]out_unitsReceives the unit count.
Returns
Error code.
Return values
k_ra8_okConverted.
k_ra8_err_invalid_argpath is not well-formed UTF-8.
k_ra8_err_no_memOver k_exfat_name_cap units.
k_ra8_err_not_supportedNon-ASCII on a volume with a foreign table.
Precondition
All pointers are non-NULL; out holds k_exfat_name_cap units.
m is a mounted exFAT volume.
Postcondition
On failure *out_units is 0.
No volume state is modified.
Note
Pure apart from the outputs.
Since
0.1.0

Definition at line 274 of file ra8_fs_fat_exfat_read.c.

References ra8_fs_mount_t::exfat_upcase_ok, k_exfat_name_cap, k_ra8_err_not_supported, k_ra8_ok, priv_utf16_all_ascii(), and priv_utf8_to_utf16().

Referenced by internal_exfat_enter(), priv_exfat_find(), priv_exfat_mkdir(), priv_exfat_needle_units(), and priv_exfat_open_write().

◆ priv_exfat_needle_units()

ra8_err_t priv_exfat_needle_units ( const ra8_fs_mount_t * m,
const char * name,
uint16_t * out,
uint32_t * out_units,
ra8_err_t too_long )

Convert a leaf name to code units, mapping over-long to too_long.

The exact wrapper the mutate verbs share: priv_exfat_name_to_units plus the one line that turns its k_ra8_err_no_mem – a name past the cap – into whatever "absent" or "unsupported" code the caller reports. Factored out so find_set, rename and the create paths do not each restate it (#606).

Parameters
[in]mMounted exFAT volume.
[in]nameLeaf name, NUL-terminated UTF-8, no leading slash.
[out]outReceives up to k_exfat_name_cap code units.
[out]out_unitsReceives the unit count.
[in]too_longThe code returned when name exceeds the cap.
Returns
Error code.
Return values
k_ra8_okConverted.
too_longname is longer than k_exfat_name_cap.
k_ra8_err_invalid_argname is not well-formed UTF-8.
k_ra8_err_not_supportedNon-ASCII on a volume with a foreign table.
Precondition
All pointers are non-NULL; out holds k_exfat_name_cap units.
m is a mounted exFAT volume.
Postcondition
On failure the unit count is 0.
No volume state is modified.
Note
Pure apart from the outputs.
Since
0.1.0

Definition at line 298 of file ra8_fs_fat_exfat_read.c.

References k_ra8_err_no_mem, and priv_exfat_name_to_units().

Referenced by priv_exfat_find_set(), and priv_exfat_rename().

◆ priv_exfat_next_entry()

ra8_err_t priv_exfat_next_entry ( const ra8_fs_mount_t * m,
exfat_cursor_t * cur,
uint8_t * out )

Fetch the next 32-byte directory entry, following the cluster chain.

Advances across sectors and (via the FAT) clusters. Reports end-of-directory as k_ra8_err_not_found when the chain reaches EOC.

Parameters
[in]mMounted exFAT volume.
[in,out]curCursor; advanced by one entry on success.
[out]outReceives the 32-byte entry.
Returns
Error code.
Return values
k_ra8_okout holds the next entry.
k_ra8_err_not_foundThe directory chain ended (EOC).
k_ra8_err_*Backend or FAT read failure.
Precondition
m, cur, and out are non-NULL.
cur->cluster is a valid directory cluster.
Postcondition
On success cur points at the following entry.
On failure out is undefined.
Note
Re-reads the sector per entry (simple; dir scans are short).
Since
0.1.0

Definition at line 231 of file ra8_fs_fat_exfat_read.c.

References exfat_cursor_t::cluster, exfat_cursor_t::contig_end, exfat_cursor_t::entry_in_cluster, k_exfat_entry_bytes, k_ra8_ok, priv_bps(), priv_byte_copy(), priv_cluster_bytes(), priv_cluster_to_lba(), priv_exfat_step_cluster(), priv_read_sector(), priv_sec_io(), and exfat_cursor_t::scanned.

Referenced by internal_exchk_scan_dir(), internal_exchk_scan_dir_terminal(), internal_exchk_set(), internal_exfat_dir_is_empty(), internal_exfat_dir_relen(), internal_exfat_gather_name(), internal_exfat_gather_set(), internal_exfat_list_emit(), internal_exfat_locate_label(), internal_exfat_match_set(), internal_exfat_take_set(), internal_setattr_exfat(), internal_utime_exfat(), priv_exfat_dir_next(), priv_exfat_drop_set(), priv_exfat_find(), priv_exfat_find_bitmap(), priv_exfat_find_set(), and priv_exfat_upcase_verify().

◆ priv_exfat_open()

ra8_err_t priv_exfat_open ( ra8_fs_mount_t * handle,
const char * path,
ra8_fs_mode_t mode,
ra8_fs_file_t ** out_file )

Open a file (read-only) on a mounted exFAT volume.

Resolves path in the root directory and populates a read handle; write/append modes are rejected (exFAT is read-only here). A name that resolves to a directory is rejected rather than opened as the empty file its zero DataLength would otherwise describe (#604).

Parameters
[in]handleMounted exFAT volume.
[in]pathFlat root-level file name, UTF-8.
[in]modeOpen mode; only k_ra8_fs_mode_read is supported.
[out]out_fileReceives the open handle.
Returns
Error code.
Return values
k_ra8_okFile opened.
k_ra8_err_not_supportedWrite/append requested (exFAT is read-only).
k_ra8_err_invalid_argpath names a directory, not a file.
k_ra8_err_not_foundNo such file.
k_ra8_err_no_memFile table full.
Precondition
handle, path, out_file are non-NULL; mount is exFAT.
handle is in use.
Postcondition
On success *out_file is an in-use read handle.
On failure no file slot is consumed.
Note
Not thread-safe; callers serialize.
Since
0.1.0

Definition at line 474 of file ra8_fs_fat_exfat_read.c.

References internal_exfat_seed_read(), k_exfat_attr_directory, k_exfat_entry_bytes, k_ra8_err_invalid_arg, k_ra8_err_no_mem, k_ra8_fs_mode_read, k_ra8_ok, priv_alloc_file_slot(), priv_exfat_lookup(), and priv_exfat_open_write().

Referenced by priv_open_locked().

◆ priv_exfat_step_cluster()

ra8_err_t priv_exfat_step_cluster ( const ra8_fs_mount_t * m,
uint32_t cluster,
uint32_t contig_end,
uint32_t * out_next )

Compute the cluster that follows cluster in a directory.

Two shapes, one answer. A FAT-chained directory (the volume root, or a subdirectory some other implementation grew) follows priv_fat_get and stops at end-of-chain. A contiguous run – what this driver creates, with NoFatChain set – steps to the adjacent cluster and stops at contig_end. Following the FAT for a NoFatChain run is not merely redundant: the exFAT specification declares those FAT entries invalid, and the ones this driver leaves behind read as 0 (free), which priv_is_eoc does not call end-of-chain, so the walk would continue into cluster 0.

Parameters
[in]mMounted exFAT volume.
[in]clusterThe directory's current cluster.
[in]contig_endOne past the run's last cluster; 0 => follow the FAT.
[out]out_nextReceives the successor cluster.
Returns
Error code.
Return values
k_ra8_ok*out_next is the next cluster.
k_ra8_err_not_foundThe directory ends here.
k_ra8_err_*FAT read failure.
Precondition
m and out_next are non-NULL.
cluster belongs to the directory being walked.
Postcondition
On k_ra8_ok *out_next addresses a heap cluster.
No volume state is modified.
Note
Not thread-safe; callers serialise.
MC/DC:
Decision: contig_end != 0 (1 condition).
  • a subdirectory created here (NoFatChain) -> true -> step to cluster + 1.
  • the volume root (FAT-chained) -> false -> follow the FAT. Decision: adjacent >= contig_end (1 condition), reached only on the true arm above.
  • the last cluster of the run -> true -> the directory ends.
  • a run of two or more clusters -> false -> the adjacent cluster.
Since
0.1.0

Definition at line 205 of file ra8_fs_fat_exfat_read.c.

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

Referenced by internal_exchk_mark_dir_alloc(), internal_exfat_scan_dir_space(), and priv_exfat_next_entry().

◆ priv_exfat_upcase_verify()

void priv_exfat_upcase_verify ( ra8_fs_mount_t * m)

Decide whether this build's fold matches the mounted volume's table.

Walks the root directory for the up-case-table entry (0x82) and compares its TableChecksum against priv_exfat_upcase_checksum(). The answer lands in ra8_fs_mount_t::exfat_upcase_ok and decides one thing: whether a name containing anything outside ASCII may be created, renamed or looked up on this volume at all. An ASCII-only name folds identically under every conforming table, so it is never affected.

Refusing the operation is the point. Hashing a name with a fold the volume does not use stores a NameHash the host disagrees with, and a host that cannot match the hash cannot find a file it can see listed – a disagreement with the on-disk format rather than a limitation of this API (#606).

A missing entry or a read error is treated exactly like a mismatch, so a volume this function could not interrogate degrades to ASCII-only names rather than failing to mount.

Parameters
[in,out]mMount whose exFAT geometry is already populated.
Returns
Nothing.
Precondition
m is non-NULL and its exFAT region geometry is valid.
The backend is bound and partition_base_lba is final.
Postcondition
m->exfat_upcase_ok is 0 or 1 and is never left unwritten.
No volume state is modified.
Note
Not thread-safe; callers serialise mount operations.
Since
0.1.0

Definition at line 133 of file ra8_fs_fat_exfat_read.c.

References ra8_fs_mount_t::exfat_upcase_ok, k_exfat_entry_bytes, k_exfat_entry_eod, k_exfat_entry_upcase, k_exfat_scan_limit, k_exfat_upc_off_csum, k_ra8_ok, priv_exfat_next_entry(), priv_exfat_upcase_checksum(), priv_rd32(), ra8_fs_mount_t::root_cluster, and exfat_cursor_t::scanned.

Referenced by internal_exfat_parse().

◆ priv_parse_volume()

ra8_err_t priv_parse_volume ( ra8_fs_mount_t * m)

Parse the volume at the current base: exFAT first, then FAT BPB.

Dispatches to the exFAT parser when the VBR carries the exFAT signature, else to the FAT BPB parser.

Parameters
[in,out]mMount with sector 0 already read into g_fs_scratch.
Returns
Error code from the chosen parser.
Return values
k_ra8_okVolume parsed (FAT or exFAT).
k_ra8_err_*No recognizable volume at this base.
Precondition
m is non-NULL and g_fs_scratch holds the base sector 0.
m->backend is bound.
Postcondition
On success m holds the volume geometry + type.
On failure m is left unmounted.
Note
Not thread-safe.
Since
0.1.0

Definition at line 162 of file ra8_fs_fat_exfat_read.c.

References g_fs_scratch, internal_exfat_is_volume(), internal_exfat_parse(), and priv_parse_bpb_into_mount().

Referenced by internal_read_boot_sector().

◆ priv_strlen()

uint32_t priv_strlen ( const char * s)

Length of a NUL-terminated string.

Counts bytes up to the NUL terminator.

Parameters
[in]sNUL-terminated string.
Returns
Character count before the terminator.
Return values
0..UINT32_MAXString length.
Precondition
s is non-NULL.
s is NUL-terminated.
Postcondition
No state modified.
s is unmodified.
Note
Pure function.
Since
0.1.0

Definition at line 27 of file ra8_fs_fat_exfat_read.c.

Referenced by internal_exfat_rename_prepare(), internal_exfat_rmdir_locate(), internal_set_label_locked(), priv_exfat_lookup(), priv_exfat_resolve_dir(), and priv_exfat_unlink().