29typedef enum : uint8_t {
54 return (value & (value - 1U)) == 0U;
81 if (workspace ==
nullptr) {
90 if (((uintptr_t)workspace % (uintptr_t)align) != 0U) {
114 if (names ==
nullptr) {
117 if (names->
iface ==
nullptr) {
142 if (file ==
nullptr) {
145 if (!file->is_open) {
148 if (file->iface ==
nullptr) {
173 if (transaction ==
nullptr) {
176 if (!transaction->
active) {
179 if (transaction->
iface ==
nullptr) {
209 if (path[start] ==
'.') {
214 if (path[start] ==
'.') {
215 if (path[(uint16_t)(start + 1U)] ==
'.') {
250 uint16_t component_start = 1U;
251 uint16_t component_len = 0U;
253 const unsigned char value = (
unsigned char)path[i];
254 if (value == (
unsigned char)
'\0') {
257 if (value == (
unsigned char)
'/') {
262 component_start = (uint16_t)(i + 1U);
266 if (value == (
unsigned char)
':') {
269 if (value == (
unsigned char)
'\\') {
288 if (caps ==
nullptr) {
291 if (path ==
nullptr) {
303 if (path[0] !=
'/') {
306 if (path[1] ==
'\0') {
334 if (names->
stat ==
nullptr || names->
listdir ==
nullptr) {
340 if (names->
mkdir ==
nullptr || names->
unlink ==
nullptr) {
343 if (names->
rmdir ==
nullptr || names->
rename ==
nullptr) {
346 if (streams->
open ==
nullptr || streams->
read ==
nullptr) {
349 if (streams->
write ==
nullptr || streams->
close ==
nullptr) {
352 if (streams->
seek ==
nullptr || streams->
tell ==
nullptr || streams->
size ==
nullptr) {
355 if (transactions ==
nullptr) {
358 if (transactions->
begin ==
nullptr || transactions->
write ==
nullptr) {
361 if (transactions->
seek ==
nullptr || transactions->
validate ==
nullptr) {
396 if ((caps->
flags & required) != required) {
400 (namespace_iface->
space ==
nullptr)) {
411 (transaction_iface ==
nullptr)) {
434 if (out ==
nullptr || namespace_iface ==
nullptr || stream_iface ==
nullptr) {
437 if (ctx ==
nullptr || caps ==
nullptr) {
470 if (fs ==
nullptr || out ==
nullptr) {
486 if (out ==
nullptr) {
493 (void)
memset(out, 0,
sizeof(*out));
497 const bool missing_invalid =
501 if (type_invalid || missing_invalid || present_invalid || directory_invalid) {
502 (void)
memset(out, 0,
sizeof(*out));
511 uint32_t max_entries,
521 if (callback ==
nullptr || out_count ==
nullptr || out_complete ==
nullptr) {
524 if (max_entries == 0U) {
532 *out_complete =
false;
535 ->
listdir(names->
ctx, path, max_entries, callback, callback_ctx, out_count, out_complete);
536 if (*out_count > max_entries) {
538 *out_complete =
false;
547 ra8_err_t (*operation)(
void*,
const char*))
553 if (operation ==
nullptr) {
560 if (path[1] ==
'\0') {
563 return operation(names->
ctx, path);
594 const char* old_path,
595 const char* new_path,
617 if (old_path[1] ==
'\0' || new_path[1] ==
'\0') {
620 return names->
iface->
rename(names->
ctx, old_path, new_path, replace);
629 if (out ==
nullptr) {
638 (void)
memset(out, 0,
sizeof(*out));
642 (void)
memset(out, 0,
sizeof(*out));
653 uint32_t workspace_size)
655 if (streams ==
nullptr || file ==
nullptr) {
658 if (streams->
iface ==
nullptr) {
676 if (path[1] ==
'\0') {
687 streams->
iface->
open(streams->
ctx, path, mode, workspace, workspace_size);
691 file->iface = streams->
iface;
692 file->ctx = streams->
ctx;
693 file->state = workspace;
694 file->state_bytes = workspace_size;
695 file->is_open =
true;
705 if (dst ==
nullptr || out_read ==
nullptr) {
709 const ra8_err_t result = file->iface->read(file->ctx, file->state, dst, cap, out_read);
710 if (*out_read > cap) {
724 if (source ==
nullptr || out_written ==
nullptr) {
728 const ra8_err_t result = file->iface->write(file->ctx, file->state, source, length, out_written);
729 if (*out_written > length) {
742 return file->iface->seek(file->ctx, file->state, offset);
751 if (out_offset ==
nullptr) {
755 return file->iface->tell(file->ctx, file->state, out_offset);
764 if (out_size ==
nullptr) {
768 return file->iface->size(file->ctx, file->state, out_size);
777 if (file->iface->sync ==
nullptr) {
780 return file->iface->sync(file->ctx, file->state);
789 const ra8_err_t closed = file->iface->close(file->ctx, file->state);
790 file->iface =
nullptr;
792 file->state =
nullptr;
793 file->state_bytes = 0U;
794 file->is_open =
false;
826 if (port->
iface ==
nullptr) {
834 if (transaction->
active) {
851 const char* destination,
855 uint32_t workspace_size)
857 if (port ==
nullptr || transaction ==
nullptr) {
868 if (destination[1] ==
'\0') {
879 port->
iface->
begin(port->
ctx, workspace, workspace_size, destination, policy);
884 transaction->
ctx = port->
ctx;
885 transaction->
state = workspace;
887 transaction->
active =
true;
893 const uint8_t* source,
895 uint32_t* out_written)
901 if (source ==
nullptr || out_written ==
nullptr) {
909 transaction->
iface->
write(transaction->
ctx, transaction->
state, source, length, out_written);
910 if (*out_written > length) {
926 return transaction->
iface->
seek(transaction->
ctx, transaction->
state, absolute_offset);
937 if (validator ==
nullptr) {
957 if (out_published ==
nullptr) {
963 *out_published =
false;
966 if ((result ==
k_ra8_ok) && !*out_published) {
969 if (*out_published) {
970 transaction->
active =
false;
984 transaction->
active =
false;
static ra8_err_t internal_names(const fw_fs_namespace_t *names)
Validate a namespace facade before dispatch.
ra8_err_t fw_fs_bind(fw_fs_t *out, const fw_fs_namespace_iface_t *namespace_iface, const fw_fs_stream_iface_t *stream_iface, const fw_fs_transaction_iface_t *transaction_iface, void *ctx, const fw_fs_caps_t *caps)
Bind segregated vtables and one context into a complete facade.
fw_fs_ascii_byte_t
ASCII byte boundaries used by portable path validation.
@ k_fw_fs_ascii_delete
DEL control byte.
@ k_fw_fs_ascii_space
First non-control ASCII byte.
static bool internal_power_of_two(uint32_t value)
Test whether an unsigned value is a non-zero power of two.
ra8_err_t fw_fs_open(const fw_fs_stream_port_t *streams, const char *path, fw_fs_open_mode_t mode, fw_fs_file_t *file, void *workspace, uint32_t workspace_size)
Open a file into a caller-owned handle and backend workspace.
static ra8_err_t internal_component(const char *path, uint16_t start, uint16_t length)
Validate one completed portable path component.
ra8_err_t fw_fs_transaction_seek(fw_fs_transaction_t *transaction, uint64_t absolute_offset)
Seek the staging writer to an absolute byte offset for bounded backfill.
ra8_err_t fw_fs_listdir(const fw_fs_namespace_t *names, const char *path, uint32_t max_entries, fw_fs_list_fn_t callback, void *callback_ctx, uint32_t *out_count, bool *out_complete)
Enumerate at most max_entries callback entries.
ra8_err_t fw_fs_get_caps(const fw_fs_t *fs, fw_fs_caps_t *out)
Copy the immutable capability snapshot from a complete binding.
ra8_err_t fw_fs_tell(fw_fs_file_t *file, uint64_t *out_offset)
Report the current absolute offset.
ra8_err_t fw_fs_transaction_abort(fw_fs_transaction_t *transaction)
Close and remove an unpublished staging artifact.
ra8_err_t fw_fs_write(fw_fs_file_t *file, const uint8_t *source, uint32_t length, uint32_t *out_written)
Attempt to write all bytes, reporting any accepted prefix.
ra8_err_t fw_fs_stat(const fw_fs_namespace_t *names, const char *path, fw_fs_stat_t *out)
Query a path; a miss is success with out->exists == false.
ra8_err_t fw_fs_transaction_validate(fw_fs_transaction_t *transaction, fw_fs_validate_fn_t validator, void *validator_ctx)
Flush/reopen the stage and ask validator to inspect it read-only.
ra8_err_t fw_fs_seek(fw_fs_file_t *file, uint64_t offset)
Seek to an absolute byte offset from the beginning.
ra8_err_t fw_fs_rmdir(const fw_fs_namespace_t *names, const char *path)
Remove one empty directory; recursive deletion is deliberately absent.
static ra8_err_t internal_fw_fs_transaction_preamble(const fw_fs_transaction_port_t *port, const fw_fs_transaction_t *transaction, fw_fs_transaction_policy_t policy)
Validate a transaction port, in-flight state, and policy before begin.
static ra8_err_t internal_name_op(const fw_fs_namespace_t *names, const char *path, ra8_err_t(*operation)(void *, const char *))
Common one-path namespace dispatch.
static ra8_err_t internal_fw_fs_scan_components(const fw_fs_caps_t *caps, const char *path)
Walk a validated non-root path byte-by-byte, checking every component.
ra8_err_t fw_fs_read(fw_fs_file_t *file, uint8_t *dst, uint32_t cap, uint32_t *out_read)
Read up to cap bytes; zero bytes is EOF.
ra8_err_t fw_fs_sync(fw_fs_file_t *file)
Request file synchronization or return k_ra8_err_not_supported.
ra8_err_t fw_fs_transaction_begin(const fw_fs_transaction_port_t *port, const char *destination, fw_fs_transaction_policy_t policy, fw_fs_transaction_t *transaction, void *workspace, uint32_t workspace_size)
Create a hidden sibling staging file for one destination.
ra8_err_t fw_fs_transaction_write(fw_fs_transaction_t *transaction, const uint8_t *source, uint32_t length, uint32_t *out_written)
Append bytes to the private staging artifact.
ra8_err_t fw_fs_close(fw_fs_file_t *file)
Close and consume an open handle.
ra8_err_t fw_fs_rename(const fw_fs_namespace_t *names, const char *old_path, const char *new_path, bool replace)
Rename inside one bound root/volume with optional atomic replacement.
static ra8_err_t internal_file(const fw_fs_file_t *file)
Validate an open file facade before dispatch.
static ra8_err_t internal_transaction(const fw_fs_transaction_t *transaction)
Validate an active transaction facade before dispatch.
static ra8_err_t internal_fw_fs_caps_validate(const fw_fs_namespace_iface_t *namespace_iface, const fw_fs_stream_iface_t *stream_iface, const fw_fs_transaction_iface_t *transaction_iface, const fw_fs_caps_t *caps)
Validate capability flags and workspace alignments before a bind.
static ra8_err_t internal_interfaces(const fw_fs_namespace_iface_t *names, const fw_fs_stream_iface_t *streams, const fw_fs_transaction_iface_t *transactions)
Validate all mandatory backend operations before binding them.
ra8_err_t fw_fs_transaction_commit(fw_fs_transaction_t *transaction, bool *out_published)
Publish a validated stage.
ra8_err_t fw_fs_path_validate(const fw_fs_caps_t *caps, const char *path)
Validate a canonical portable path against a binding's limits.
ra8_err_t fw_fs_space(const fw_fs_namespace_t *names, fw_fs_space_t *out)
Report total/free/used bytes when space-query capability is present.
ra8_err_t fw_fs_unlink(const fw_fs_namespace_t *names, const char *path)
Remove one regular file; directories require fw_fs_rmdir.
ra8_err_t fw_fs_file_size(fw_fs_file_t *file, uint64_t *out_size)
Report the open file's current length.
ra8_err_t fw_fs_mkdir(const fw_fs_namespace_t *names, const char *path)
Create exactly one directory; parents must already exist.
static ra8_err_t internal_workspace(void *workspace, uint32_t bytes, uint32_t need, uint8_t align)
Validate a workspace against a backend byte/alignment contract.
Architecture-neutral filesystem namespace, stream, and transaction ports.
Backend-author interface for binding concrete filesystem ports.
Portable filesystem value types and caller-owned opaque handles.
@ k_fw_fs_node_none
No node exists at the path.
@ k_fw_fs_node_directory
Directory.
@ k_fw_fs_node_other
Backend-specific non-file node.
struct fw_fs_stream_iface fw_fs_stream_iface_t
struct fw_fs_transaction_iface fw_fs_transaction_iface_t
ra8_err_t(* fw_fs_validate_fn_t)(void *ctx, fw_fs_file_t *staged)
Validate staged bytes through a read-only generic file handle.
@ k_fw_fs_path_cap
Largest portable path including its NUL.
struct fw_fs_namespace_iface fw_fs_namespace_iface_t
fw_fs_open_mode_t
Open intent for fw_fs_open.
@ k_fw_fs_open_create_new
Create only when leaf is absent.
ra8_err_t(* fw_fs_list_fn_t)(void *ctx, const fw_fs_dirent_t *entry, bool *out_continue)
Bounded list callback.
fw_fs_transaction_policy_t
Destination policy for a staged transaction.
@ k_fw_fs_txn_replace_atomic
Atomically replace an existing file.
@ k_fw_fs_cap_durable_file_sync
Successful file sync reaches durable media.
@ k_fw_fs_cap_stream
Regular-file stream operations are available.
@ k_fw_fs_cap_namespace
Metadata and namespace operations are available.
@ k_fw_fs_cap_space_query
Volume capacity and available bytes can be queried.
@ k_fw_fs_cap_create_exclusive
Open can atomically require that its leaf be absent.
@ k_fw_fs_cap_file_sync
An explicit file-sync operation is available.
@ k_fw_fs_cap_atomic_noreplace
Rename can atomically reject an existing destination.
@ k_fw_fs_cap_transactions
Staged publication operations are available.
@ k_fw_fs_cap_atomic_replace
Rename can atomically replace an existing destination.
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Error Code Definitions for ra8-firmware.
@ k_ra8_err_not_supported
Requested feature not compiled in, not wired, or not supported by this MCU variant.
@ k_ra8_err_no_mem
Static buffer exhausted (no dynamic memory on this project).
@ k_ra8_err_busy
Resource busy – blocking operation cannot proceed.
@ k_ra8_err_invalid_arg
Invalid function argument.
@ k_ra8_err_invalid_state
Module in wrong state for requested operation.
@ k_ra8_err_not_initialized
Module not initialized – _init() not yet called successfully.
@ 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_access_denied
Operation refused because the target is protected against it.
@ 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.
void * memset(void *dst, int value, size_t n)
Fill memory with a constant byte value.
Static properties and workspace requirements of one bound port.
uint16_t name_max_bytes
Component bytes excluding NUL.
uint8_t directory_workspace_align
Required directory-state alignment.
uint16_t path_max_bytes
Path bytes including NUL.
uint32_t file_workspace_bytes
State bytes required by open.
uint8_t transaction_workspace_align
Required transaction alignment.
uint16_t max_open_directories
Concurrent directory cursors.
uint32_t directory_workspace_bytes
State bytes required by dir open.
uint8_t file_workspace_align
Required file-state alignment.
uint32_t flags
OR of fw_fs_capability_t.
uint32_t transaction_workspace_bytes
State bytes required by begin.
Caller-owned open file; fields are private to the facade.
ra8_err_t(* mkdir)(void *ctx, const char *path)
Create one directory leaf.
ra8_err_t(* listdir)(void *ctx, const char *path, uint32_t max_entries, fw_fs_list_fn_t callback, void *callback_ctx, uint32_t *out_count, bool *out_complete)
Enumerate at most the requested number of directory entries.
ra8_err_t(* rmdir)(void *ctx, const char *path)
Remove one empty directory leaf.
ra8_err_t(* rename)(void *ctx, const char *old_path, const char *new_path, bool replace)
Rename one leaf within the backend volume.
ra8_err_t(* dir_open)(void *ctx, const char *path, void *directory_state, uint32_t state_bytes)
Open a directory cursor in caller-supplied workspace.
ra8_err_t(* stat)(void *ctx, const char *path, fw_fs_stat_t *out)
Query one path without following a symbolic-link leaf.
ra8_err_t(* dir_next)(void *ctx, void *directory_state, fw_fs_dirent_value_t *out, bool *out_entry)
Copy the next visible entry or report clean end-of-directory.
ra8_err_t(* space)(void *ctx, fw_fs_space_t *out)
Query the volume capacity and available byte count.
ra8_err_t(* dir_close)(void *ctx, void *directory_state)
Close a directory cursor and consume its backend state.
ra8_err_t(* unlink)(void *ctx, const char *path)
Remove one regular-file leaf.
Independently injectable path/namespace facade.
fw_fs_caps_t caps
Immutable capabilities.
void * ctx
Backend context.
const fw_fs_namespace_iface_t * iface
Bound private vtable.
Portable volume usage snapshot.
uint64_t free_bytes
Bytes available to new data.
uint64_t total_bytes
Addressable data bytes.
uint64_t used_bytes
Allocated bytes.
Result of a portable metadata query.
uint64_t size_bytes
File length; zero for a directory.
bool exists
False means a clean lookup miss.
fw_fs_node_type_t type
Kind of node at the path.
ra8_err_t(* tell)(void *ctx, void *file_state, uint64_t *out_offset)
Report the current absolute stream position.
ra8_err_t(* close)(void *ctx, void *file_state)
Close the file and release its caller workspace.
ra8_err_t(* open)(void *ctx, const char *path, fw_fs_open_mode_t mode, void *file_state, uint32_t state_bytes)
Initialize caller workspace for one path and open mode.
ra8_err_t(* size)(void *ctx, void *file_state, uint64_t *out_size)
Report the current file length.
ra8_err_t(* read)(void *ctx, void *file_state, uint8_t *dst, uint32_t cap, uint32_t *out_read)
Read bytes at the current stream position.
ra8_err_t(* write)(void *ctx, void *file_state, const uint8_t *src, uint32_t len, uint32_t *out_written)
Write bytes at the current stream position.
ra8_err_t(* sync)(void *ctx, void *file_state)
Request backend file durability when supported.
ra8_err_t(* seek)(void *ctx, void *file_state, uint64_t absolute_offset)
Set the absolute stream position.
Independently injectable open-stream facade.
fw_fs_caps_t caps
Immutable capabilities.
void * ctx
Backend context.
const fw_fs_stream_iface_t * iface
Bound private vtable.
One complete composition-root filesystem binding.
fw_fs_stream_port_t streams
Byte-stream operations.
fw_fs_caps_t caps
Shared capabilities.
fw_fs_namespace_t names
Namespace operations.
fw_fs_transaction_port_t transactions
Staged publication.
ra8_err_t(* abort)(void *ctx, void *transaction_state)
Close and remove an unpublished private stage.
ra8_err_t(* validate)(void *ctx, void *transaction_state, fw_fs_validate_fn_t validator, void *validator_ctx)
Run a caller validator against the staged stream.
ra8_err_t(* begin)(void *ctx, void *transaction_state, uint32_t state_bytes, const char *destination, fw_fs_transaction_policy_t policy)
Create a private stage for the requested destination policy.
ra8_err_t(* write)(void *ctx, void *transaction_state, const uint8_t *src, uint32_t len, uint32_t *out_written)
Append or overwrite bytes in the private stage.
ra8_err_t(* seek)(void *ctx, void *transaction_state, uint64_t absolute_offset)
Set the absolute position within the staged stream.
ra8_err_t(* commit)(void *ctx, void *transaction_state, bool *out_published)
Publish the validated stage under the destination path.
Independently injectable staged-transaction facade.
fw_fs_caps_t caps
Immutable capabilities.
const fw_fs_transaction_iface_t * iface
Bound private vtable.
void * ctx
Backend context.
Caller-owned transaction; fields are private to the facade.
void * ctx
Adapter context.
const fw_fs_transaction_iface_t * iface
Bound vtable.
void * state
Caller workspace.
uint32_t state_bytes
Workspace extent.
bool validated
Stage was accepted.
bool active
Begin succeeded.