48 return text[0] ==
'.';
52 return text[1] ==
'.';
78 if (text ==
nullptr) {
81 if (out_len ==
nullptr) {
84 for (uint16_t i = 0U; i < cap; ++i) {
85 if (text[i] ==
'\0') {
119 if (path[i] ==
':') {
126 if (path[i] ==
'/') {
129 if (path[i] ==
'\\') {
132 if ((uint8_t)path[i] < 0x20U) {
159 if (path[colon + 1U] !=
'/') {
162 uint16_t start = (uint16_t)(colon + 2U);
163 uint16_t slash = (uint16_t)(colon + 1U);
164 for (uint16_t i = start; i <= len; ++i) {
165 const char c = path[i];
166 bool boundary = c ==
'/';
171 const uint16_t component_len = (uint16_t)(i - start);
172 if (component_len == 0U) {
180 start = (uint16_t)(i + 1U);
190 if ((uint8_t)c < 0x20U) {
259 if (*out_len == 0U) {
265 for (uint16_t i = 0U; i < *out_len; ++i) {
266 const char c = leaf[i];
276 if ((uint8_t)c < 0x20U) {
298 for (uint16_t i = 0U; i < len; ++i) {
322 if (destination_leaf[i] != stage_leaf[i]) {
325 if (destination_leaf[i] ==
'\0') {
352 const uint32_t prefix = (uint32_t)facts->
last_slash + 1U;
353 const uint32_t needed = prefix + (uint32_t)stage_len + 1U;
361 for (uint32_t i = 0U; i < prefix; ++i) {
364 for (uint16_t i = 0U; i < stage_len; ++i) {
390 const bool root_parent = ctx->
destination[last_slash - 1U] ==
':';
391 const uint16_t cut = root_parent ? (uint16_t)(last_slash + 1U) : last_slash;
488 if (ctx->
file ==
nullptr) {
499 return (sync_err ==
k_ra8_ok) ? close_err : sync_err;
521 uint16_t stage_len = 0U;
558 if (opaque ==
nullptr) {
561 if (destination ==
nullptr) {
610internal_write(
void* opaque,
const uint8_t* data, uint16_t len, uint16_t* written)
612 if (opaque ==
nullptr) {
615 if (written ==
nullptr) {
619 if (data ==
nullptr) {
626 if (ctx->
file ==
nullptr) {
701 if (opaque ==
nullptr) {
704 if (sha256 ==
nullptr) {
747 if (opaque ==
nullptr) {
790 return (first_err ==
k_ra8_ok) ? stat_err : first_err;
803 return (first_err ==
k_ra8_ok) ? unlink_err : first_err;
823 if (opaque ==
nullptr) {
841 if (storage ==
nullptr) {
844 if (config ==
nullptr) {
847 if (out_iface ==
nullptr) {
853 uint16_t stage_len = 0U;
867 out_iface->
ctx = storage;
static ra8_err_t internal_write(void *ctx, void *file_state, const uint8_t *src, uint32_t len, uint32_t *out_written)
static ra8_err_t internal_bounded_length(const char *text, uint16_t cap, uint16_t *out_len)
Measure one string without reading past a fixed capacity.
static ra8_err_t internal_write(void *opaque, const uint8_t *data, uint16_t len, uint16_t *written)
Coordinator callback: append one all-or-error bounded chunk.
static ra8_err_t internal_abort(void *opaque)
Coordinator callback: best-effort, retryable, idempotent cleanup.
static ra8_err_t internal_path_facts(const char *path, path_facts_t *out)
Prove a destination is a bounded canonical named-VFS file path.
static ra8_err_t internal_final_absent(const char *destination)
Refuse an existing final, distinguishing directories as bad paths.
static ra8_err_t internal_build_stage(mdl_storage_vfs_t *ctx, const path_facts_t *facts, uint16_t stage_len)
Build the caller-owned sibling staging path without truncation.
static ra8_err_t internal_stage_leaf_check(const char *leaf, uint16_t *out_len)
Validate the caller-reserved simple staging leaf.
static ra8_err_t internal_close_writer(mdl_storage_vfs_t *ctx)
Close the writer exactly once and retain staged cleanup state.
static ra8_err_t internal_abort_stage(mdl_storage_vfs_t *ctx, ra8_err_t first_err)
Finish cleanup after the writer, if any, has been closed.
static ra8_err_t internal_validate(void *opaque, uint64_t total_bytes, const uint8_t sha256[k_ra8_mdl_sha256_bytes])
Coordinator callback: close, size-check, and delegate validation.
static void internal_copy(char *dst, const char *src, uint16_t len)
Copy a bounded NUL-terminated byte string.
static ra8_err_t internal_remove_stale_stage(const char *staging_path)
Remove a stale owned regular stage, but never a directory.
static ra8_err_t internal_path_components(const char *path, uint16_t len, uint16_t colon, uint16_t *out_slash)
Validate canonical non-traversing components after mount:/.
static ra8_err_t internal_begin_prepare_stage(mdl_storage_vfs_t *ctx, const path_facts_t *facts)
Stage-preparation chain: leaf check, build, parent check, and cleanup.
static ra8_err_t internal_begin(void *opaque, const char *destination)
Coordinator callback: create the private sibling transaction file.
static ra8_err_t internal_commit(void *opaque)
Coordinator callback: one serialized no-replace same-mount publish.
static bool internal_leaf_equals(const char *destination_leaf, const char *stage_leaf)
Compare a destination leaf with the reserved staging leaf.
static ra8_err_t internal_staged_file_check(const mdl_storage_vfs_t *ctx, uint64_t expected)
Check the closed stage is still a regular file of the exact size.
static ra8_err_t internal_parent_check(mdl_storage_vfs_t *ctx, uint16_t last_slash)
Require the destination parent to exist and be a directory.
static bool internal_is_dot_component(const char *text, uint16_t len)
Return whether one component is exactly "." or "..".
ra8_err_t mdl_storage_vfs_init(mdl_storage_vfs_t *storage, const mdl_storage_vfs_config_t *config, ra8_mdl_storage_iface_t *out_iface)
Initialise one VFS storage adapter and bind its coordinator interface.
static ra8_err_t internal_mount_prefix(const char *path, uint16_t len, uint16_t *out_colon)
Validate the mount prefix and locate its colon.
No-heap VFS storage binding for the media-download coordinator.
@ k_mdl_storage_vfs_path_capacity
VFS path incl NUL.
@ k_mdl_storage_vfs_stage_leaf_capacity
Stage leaf incl NUL.
@ k_mdl_storage_vfs_ready
Validated and ready to rename.
@ k_mdl_storage_vfs_committed
Destination was published.
@ k_mdl_storage_vfs_idle
No owned private object.
@ k_mdl_storage_vfs_staged
Writer closed; not validated.
@ k_mdl_storage_vfs_writing
Private writer is open.
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
struct ra8_mdl_storage_iface ra8_mdl_storage_iface_t
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_invalid_arg
Invalid function argument.
@ k_ra8_err_exists
Item already exists – cannot create again.
@ k_ra8_err_invalid_state
Module in wrong state for requested operation.
@ 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_not_found
Requested item not found (lookup / search missed).
@ 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.
static void internal_abort(ra8_fmt_transaction_t *transaction)
Abort an active transaction after any pre-publication error.
@ k_ra8_fs_mode_write
Truncate (or create) for writing.
static ra8_err_t internal_validate(const ra8_io_blockdev_t *bd)
Reject a handle that is NULL or has no backend bound.
ra8_io virtual filesystem – mount many volumes, address them by name.
ra8_err_t ra8_io_vfs_file_close(ra8_io_vfs_file_t *file)
Close and always release one format-neutral stream facade.
@ k_ra8_io_vfs_name_max
Mount name length incl NUL.
ra8_err_t ra8_io_vfs_file_sync(ra8_io_vfs_file_t *file)
Explicitly sync a stream, or return not-supported when unavailable.
ra8_err_t ra8_io_vfs_unlink(const char *path)
Delete a file by "name:/path".
ra8_err_t ra8_io_vfs_file_open(const char *path, ra8_fs_mode_t mode, ra8_io_vfs_file_t **out_file)
Open a format-neutral stream through a mounted format's ops.
ra8_err_t ra8_io_vfs_stat(const char *path, ra8_io_vfs_stat_t *out)
Query metadata for "name:/path".
ra8_err_t ra8_io_vfs_rename(const char *old_path, const char *new_path)
Rename a file within one mount.
ra8_err_t ra8_io_vfs_file_write(ra8_io_vfs_file_t *file, const void *buf, uint32_t bytes)
Write bytes, or return not-supported when capability-gated.
@ k_ra8_mdl_sha256_bytes
SHA-256 digest size in bytes.
Immutable policy copied or retained by an adapter instance.
void * validate_ctx
Validator context.
mdl_storage_vfs_validate_fn validate
Optional artifact validator.
const char * stage_leaf
Reserved sibling staging leaf.
Caller-owned VFS transaction context.
uint64_t bytes_written
Successful appended bytes.
mdl_storage_vfs_validate_fn validate
Optional delegated check.
void * validate_ctx
Delegated check context.
char destination[k_mdl_storage_vfs_path_capacity]
Final path.
char staging_path[k_mdl_storage_vfs_path_capacity]
Private path.
mdl_storage_vfs_state_t state
Transaction lifecycle.
ra8_io_vfs_file_t * file
Open private writer.
char stage_leaf[k_mdl_storage_vfs_stage_leaf_capacity]
Owned leaf.
Module-local path facts proven before any filesystem mutation.
uint16_t last_slash
Final component separator.
uint16_t length
Bytes before NUL.
Opaque, statically-pooled format-neutral file stream.
Metadata returned by ra8_io_vfs_stat.
uint64_t size_bytes
File size in bytes (0 for directories).
bool is_directory
true => path names a directory.
bool exists
true => the path resolves to an entry.
ra8_err_t(* write)(void *ctx, const uint8_t *data, uint16_t len, uint16_t *written)
Append len bytes and report the exact number persisted.
ra8_err_t(* commit)(void *ctx)
Atomically publish the complete temporary object.
void * ctx
Backend context passed to every function.
ra8_err_t(* begin)(void *ctx, const char *destination)
Create private temporary state for destination.
ra8_err_t(* validate)(void *ctx, uint64_t total_bytes, const uint8_t sha256[k_ra8_mdl_sha256_bytes])
Validate artifact identity and structure before publication.
ra8_err_t(* abort)(void *ctx)
Destroy temporary state; valid after every successful begin.