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

Secure hosted POSIX backend for the portable filesystem interface. More...

#include "fw_if_fs_posix.h"
#include <errno.h>
#include <fcntl.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <unistd.h>
#include "ra8_attributes.h"
#include "fw_if_fs.h"
#include "fw_if_fs_backend.h"
#include "fw_if_fs_posix_contracts_internal.h"
#include "fw_if_fs_posix_internal.h"
#include "ra8_err.h"
Include dependency graph for fw_if_fs_posix.c:

Go to the source code of this file.

Macros

#define _GNU_SOURCE
 Request GNU descriptor-relative syscall declarations on Linux.
#define O_CLOEXEC   (0)
 Zero fallback when the host lacks close-on-exec open flags.
#define O_NOFOLLOW   (0)
 Zero fallback paired with explicit no-follow metadata validation.
#define AT_SYMLINK_NOFOLLOW   (0)
 Zero fallback paired with explicit target-type rejection.
#define RENAME_NOREPLACE   (1U << 0U)
 Host flag value for atomic no-replace rename probing.

Enumerations

enum  posix_directory_budget_t : uint8_t { k_posix_directory_budget_overhead = 3U }
 Number of dot records plus the completion look-ahead record. More...

Functions

static ra8_err_t internal_component_copy (const char *start, uint16_t length, char *out)
static ra8_err_t internal_intermediate_check (int parent_fd, const char *component, posix_root_alias_t *out_alias)
ra8_err_t priv_fs_posix_component_open (int parent_fd, const char *component, int *out_fd)
 Open one validated directory component without following its pathname.
static ra8_err_t internal_next_component (const char **cursor, char *out_name, uint16_t *out_length)
static ra8_err_t internal_parent_open_step (int *current, const char *name)
ra8_err_t priv_fs_posix_parent_open (fw_fs_posix_state_t *state, const char *path, int *out_parent_fd, char *out_leaf)
 Resolve a canonical path's parent without following any symlink.
static fw_fs_node_type_t internal_node_type (mode_t mode)
static ra8_err_t internal_native_stat (fw_fs_posix_state_t *state, const char *path, struct stat *out, bool *out_exists)
static ra8_err_t internal_stat (void *ctx, const char *path, fw_fs_stat_t *out)
static ra8_err_t internal_directory_open (fw_fs_posix_state_t *state, const char *path, int *out_fd)
ra8_err_t priv_fs_posix_dir_open (void *ctx, const char *path, void *directory_state, uint32_t state_bytes)
 Open a confined raw-directory cursor in caller storage.
ra8_err_t priv_fs_posix_dir_next (void *ctx, void *directory_state, fw_fs_dirent_value_t *out, bool *out_entry)
 Copy the next visible raw-directory entry.
ra8_err_t priv_fs_posix_dir_close (void *ctx, void *directory_state)
 Close one owned raw-directory descriptor.
static ra8_err_t internal_mkdir (void *ctx, const char *path)
static ra8_err_t internal_unlink (void *ctx, const char *path)
static ra8_err_t internal_rmdir (void *ctx, const char *path)
static ra8_err_t internal_rename_noreplace (int old_fd, const char *old_leaf, int new_fd, const char *new_leaf)
static ra8_err_t internal_rename_opened (int old_fd, const char *old_leaf, int new_fd, const char *new_leaf, bool replace)
 Validate opened parents and perform the selected rename operation.
static ra8_err_t internal_rename_validate_endpoints (fw_fs_posix_state_t *state, const char *old_path, const char *new_path)
static ra8_err_t internal_rename (void *ctx, const char *old_path, const char *new_path, bool replace)
static ra8_err_t internal_space (void *ctx, fw_fs_space_t *out)
static ra8_err_t internal_stage_open (fw_fs_posix_state_t *state, posix_transaction_state_t *txn)
static ra8_err_t internal_txn_begin (void *ctx, void *transaction_state, uint32_t state_bytes, const char *destination, fw_fs_transaction_policy_t policy)
static ra8_err_t internal_txn_write (void *ctx, void *transaction_state, const uint8_t *src, uint32_t len, uint32_t *out_written)
static ra8_err_t internal_txn_seek (void *ctx, void *transaction_state, uint64_t offset)
static ra8_err_t internal_txn_validate (void *ctx, void *transaction_state, fw_fs_validate_fn_t validator, void *validator_ctx)
static ra8_err_t internal_parent_sync (fw_fs_posix_state_t *state, const char *path)
static ra8_err_t internal_txn_commit (void *ctx, void *transaction_state, bool *out_published)
static ra8_err_t internal_txn_abort (void *ctx, void *transaction_state)
ra8_err_t priv_fs_posix_bind_interfaces (fw_fs_t *out, fw_fs_posix_state_t *state, const fw_fs_caps_t *caps)
 Bind the immutable POSIX operation tables to initialized state.

Variables

static const fw_fs_namespace_iface_t s_namespace_iface
 Immutable POSIX namespace vtable.
static const fw_fs_transaction_iface_t s_transaction_iface
 Immutable POSIX transaction vtable.

Detailed Description

Secure hosted POSIX backend for the portable filesystem interface.

Tag
[Ring 4 / Host Port] {World: Host}

Implements portable filesystem operations relative to one opened root descriptor. Component-wise no-follow traversal rejects parent escapes and every symbolic link on Linux. Darwin accepts only its exact filesystem-root tmp and var aliases, opening them through canonical private components rather than the alias pathname. Caller-owned file and transaction workspaces provide bounded streaming, listing, metadata, and staged publication on hosted systems.

Definition in file fw_if_fs_posix.c.

Macro Definition Documentation

◆ _GNU_SOURCE

#define _GNU_SOURCE

Request GNU descriptor-relative syscall declarations on Linux.

Definition at line 28 of file fw_if_fs_posix.c.

◆ AT_SYMLINK_NOFOLLOW

#define AT_SYMLINK_NOFOLLOW   (0)

Zero fallback paired with explicit target-type rejection.

Definition at line 67 of file fw_if_fs_posix.c.

Referenced by internal_intermediate_check(), internal_native_stat(), internal_validate_destination(), and priv_fs_posix_dir_next().

◆ O_CLOEXEC

◆ O_NOFOLLOW

◆ RENAME_NOREPLACE

#define RENAME_NOREPLACE   (1U << 0U)

Host flag value for atomic no-replace rename probing.

Definition at line 72 of file fw_if_fs_posix.c.

Referenced by internal_atomic_noreplace_available(), and internal_rename_noreplace().

Enumeration Type Documentation

◆ posix_directory_budget_t

enum posix_directory_budget_t : uint8_t

Number of dot records plus the completion look-ahead record.

Enumerator
k_posix_directory_budget_overhead 

Dot entries plus EOF look-ahead.

Definition at line 76 of file fw_if_fs_posix.c.

Function Documentation

◆ internal_component_copy()

ra8_err_t internal_component_copy ( const char * start,
uint16_t length,
char * out )
static

◆ internal_directory_open()

◆ internal_intermediate_check()

ra8_err_t internal_intermediate_check ( int parent_fd,
const char * component,
posix_root_alias_t * out_alias )
static

◆ internal_mkdir()

ra8_err_t internal_mkdir ( void * ctx,
const char * path )
static

◆ internal_native_stat()

◆ internal_next_component()

ra8_err_t internal_next_component ( const char ** cursor,
char * out_name,
uint16_t * out_length )
static

◆ internal_node_type()

fw_fs_node_type_t internal_node_type ( mode_t mode)
static

◆ internal_parent_open_step()

ra8_err_t internal_parent_open_step ( int * current,
const char * name )
static

◆ internal_parent_sync()

ra8_err_t internal_parent_sync ( fw_fs_posix_state_t * state,
const char * path )
static

◆ internal_rename()

ra8_err_t internal_rename ( void * ctx,
const char * old_path,
const char * new_path,
bool replace )
static

◆ internal_rename_noreplace()

ra8_err_t internal_rename_noreplace ( int old_fd,
const char * old_leaf,
int new_fd,
const char * new_leaf )
static

◆ internal_rename_opened()

ra8_err_t internal_rename_opened ( int old_fd,
const char * old_leaf,
int new_fd,
const char * new_leaf,
bool replace )
static

Validate opened parents and perform the selected rename operation.

Proves both parents occupy one filesystem, then dispatches to atomic replacement or the host's atomic no-replace primitive.

Parameters
[in]old_fdOpen source-parent descriptor.
[in]old_leafSource leaf relative to old_fd.
[in]new_fdOpen destination-parent descriptor.
[in]new_leafDestination leaf relative to new_fd.
[in]replaceWhether an existing destination may be replaced.
Returns
Rename status or mapped host failure.
Return values
k_ra8_okThe entry was renamed atomically.
k_ra8_err_invalid_argParent descriptors name different filesystems.
k_ra8_err_*Metadata or rename failures are mapped unchanged.
Precondition
Both descriptors are live, owned by the caller, and name directories.
Both leaf strings are bounded validated path components.
Postcondition
Success moves exactly the source entry to the destination name.
Descriptor ownership remains with the caller on every result.
Note
No-replace mode never falls back to a racy check-then-rename sequence.
Since
0.1.0

Definition at line 512 of file fw_if_fs_posix.c.

References internal_rename_noreplace(), k_ra8_err_invalid_arg, k_ra8_ok, priv_fs_posix_errno(), RA8_INTERNAL, and renameat().

Referenced by internal_rename().

◆ internal_rename_validate_endpoints()

ra8_err_t internal_rename_validate_endpoints ( fw_fs_posix_state_t * state,
const char * old_path,
const char * new_path )
static

◆ internal_rmdir()

◆ internal_space()

◆ internal_stage_open()

◆ internal_stat()

◆ internal_txn_abort()

◆ internal_txn_begin()

◆ internal_txn_commit()

◆ internal_txn_seek()

ra8_err_t internal_txn_seek ( void * ctx,
void * transaction_state,
uint64_t offset )
static

◆ internal_txn_validate()

◆ internal_txn_write()

ra8_err_t internal_txn_write ( void * ctx,
void * transaction_state,
const uint8_t * src,
uint32_t len,
uint32_t * out_written )
static

◆ internal_unlink()

◆ priv_fs_posix_bind_interfaces()

ra8_err_t priv_fs_posix_bind_interfaces ( fw_fs_t * out,
fw_fs_posix_state_t * state,
const fw_fs_caps_t * caps )

Bind the immutable POSIX operation tables to initialized state.

Hands fw_fs_bind this port's namespace and transaction vtables, which are translation-unit-scoped, together with the shared table borrowed from priv_fs_posix_stream_iface and state as the single backend context. Routing the bind through one helper is what keeps those two private tables from needing a second copy in the initialization unit. Every consistency rule between the tables and caps is enforced inside the facade rather than here.

Parameters
[out]outFacade populated with the bound tables, context, and caps.
[in,out]stateInitialized adapter state published as backend context.
[in]capsTruthful capability and workspace-sizing descriptor.
Returns
Facade bind status.
Return values
k_ra8_okout is a complete facade over state.
k_ra8_err_null_ptrout, state, or caps is NULL.
k_ra8_err_invalid_argAn advertised capability, workspace alignment, or root-path rule is not satisfied by the bound tables.
Precondition
state is fully initialized with an open root descriptor, because a successful bind immediately publishes it as the backend context.
caps describes state truthfully, including every workspace size and power-of-two alignment the facade re-validates.
Postcondition
Success installs the namespace, stream, and transaction tables and the same state pointer into all three facade sections.
Failure writes nothing to out and releases nothing from state, so unwinding the adapter state stays the caller's responsibility.
Note
Thread-safe; the bound tables are immutable and statically initialized, and the call itself writes only out.
Since
Version 0.1.0

Definition at line 835 of file fw_if_fs_posix.c.

References fw_fs_bind(), priv_fs_posix_stream_iface(), RA8_PRIV, s_namespace_iface, and s_transaction_iface.

Referenced by fw_fs_posix_init().

◆ priv_fs_posix_component_open()

ra8_err_t priv_fs_posix_component_open ( int parent_fd,
const char * component,
int * out_fd )

Open one validated directory component without following its pathname.

Uses no-follow metadata and openat beneath parent_fd. Linux rejects every symbolic link. Darwin permits only an exact tmp or var alias whose parent descriptor identifies actual /, and opens that alias through canonical no-follow private components instead of its pathname.

Parameters
[in]parent_fdOpen descriptor for the selected parent directory.
[in]componentTerminated child component without slash bytes.
[out]out_fdReceives the owned directory descriptor.
Returns
Validated component-open status.
Return values
k_ra8_okout_fd owns the requested directory.
k_ra8_err_access_deniedA symbolic link is not an approved Darwin alias.
k_ra8_err_not_foundThe component is absent or is not a directory.
k_ra8_err_*Mapped metadata, open, or descriptor-close failure.
Precondition
parent_fd is open and component is a validated non-empty name.
out_fd is non-NULL and does not alias either input.
Postcondition
Success publishes exactly one owned descriptor.
Failure publishes no descriptor and retains parent_fd ownership.
Note
Thread-safe subject to host namespace race semantics.
Since
Version 0.1.0

Definition at line 117 of file fw_if_fs_posix.c.

References internal_intermediate_check(), k_posix_root_alias_none, k_ra8_ok, O_CLOEXEC, O_DIRECTORY, O_NOFOLLOW, priv_fs_posix_errno(), priv_fs_posix_root_alias_open(), and RA8_PRIV.

Referenced by internal_directory_open(), internal_parent_open_step(), and internal_root_open_step().

◆ priv_fs_posix_dir_close()

ra8_err_t priv_fs_posix_dir_close ( void * ctx,
void * directory_state )

Close one owned raw-directory descriptor.

Invalidates the stored descriptor before mapping the host close result, preventing a retry from closing a reused descriptor number.

Parameters
[in,out]ctxBound POSIX adapter context.
[in,out]directory_stateOpen caller-owned cursor workspace.
Returns
Mapped descriptor-close status.
Return values
k_ra8_okThe descriptor closed successfully.
k_ra8_err_*Mapped host close failure.
Precondition
directory_state is non-NULL and owns a directory descriptor.
ctx is the bound adapter context associated with the cursor.
Postcondition
The descriptor field is invalidated even when close reports an error.
Caller workspace ownership remains with the caller.
Note
The generic facade consumes its handle on every return.
Since
Version 0.1.0

Definition at line 373 of file fw_if_fs_posix.c.

References posix_directory_state_t::fd, priv_fs_posix_close_fd(), and RA8_PRIV.

Referenced by priv_fs_posix_listdir().

◆ priv_fs_posix_dir_next()

ra8_err_t priv_fs_posix_dir_next ( void * ctx,
void * directory_state,
fw_fs_dirent_value_t * out,
bool * out_entry )

Copy the next visible raw-directory entry.

Decodes bounded native records, skips dot entries, and performs a no-follow metadata lookup before publishing a stable copied value.

Parameters
[in,out]ctxBound POSIX adapter context.
[in,out]directory_stateOpen caller-owned cursor workspace.
[out]outStable copied portable entry value.
[out]out_entryTrue when out contains an entry; false at EOF.
Returns
Raw read, metadata, or validation status.
Return values
k_ra8_okOne entry was copied or native end was observed.
k_ra8_err_*Raw-read, record, metadata, or retry-bound failure.
Precondition
Output and cursor pointers are non-NULL and the cursor owns its descriptor.
ctx names the same bound root that opened the cursor.
Postcondition
No lock is retained and borrowed kernel-record bytes never escape.
Success with out_entry true fully initializes out.
Note
Namespace mutation may surface as the exact fstatat lookup error.
Since
Version 0.1.0

Definition at line 333 of file fw_if_fs_posix.c.

References AT_SYMLINK_NOFOLLOW, posix_directory_state_t::fd, internal_node_type(), k_posix_directory_budget_overhead, k_ra8_err_invalid_state, k_ra8_ok, memcpy(), fw_fs_dirent_value_t::name, posix_directory_record_t::name, fw_fs_dirent_value_t::name_bytes, posix_directory_record_t::name_bytes, priv_fs_posix_directory_next(), priv_fs_posix_errno(), RA8_PRIV, posix_directory_state_t::reader, fw_fs_dirent_value_t::size_bytes, strcmp(), and fw_fs_dirent_value_t::type.

Referenced by priv_fs_posix_listdir().

◆ priv_fs_posix_dir_open()

ra8_err_t priv_fs_posix_dir_open ( void * ctx,
const char * path,
void * directory_state,
uint32_t state_bytes )

Open a confined raw-directory cursor in caller storage.

Opens beneath the bound root without following the final leaf and initializes the fixed raw-record buffer in caller storage.

Parameters
[in,out]ctxBound POSIX adapter context.
[in]pathValidated canonical directory path.
[out]directory_stateCaller-owned cursor workspace.
[in]state_bytesAccessible workspace extent.
Returns
Confined open or workspace status.
Return values
k_ra8_okThe workspace owns one directory descriptor.
k_ra8_err_*Capacity, confinement, open, or platform failure.
Precondition
Required pointers are non-NULL and path passed facade validation.
state_bytes describes the writable extent at directory_state.
Postcondition
Success owns one directory descriptor in directory_state.
Failure closes every descriptor acquired by this operation.
Note
No allocator-backed C runtime directory object is used.
Since
Version 0.1.0

Definition at line 320 of file fw_if_fs_posix.c.

References posix_directory_state_t::fd, internal_directory_open(), k_ra8_err_no_mem, and RA8_PRIV.

Referenced by priv_fs_posix_listdir().

◆ priv_fs_posix_parent_open()

ra8_err_t priv_fs_posix_parent_open ( fw_fs_posix_state_t * state,
const char * path,
int * out_parent_fd,
char * out_leaf )

Resolve a canonical path's parent without following any symlink.

Duplicates the bound root and walks each intermediate component with no-follow stat/open calls, so normal paths remain confined beneath the owned descriptor as ownership moves. Darwin replaces a verified actual-root alias with its canonical no-follow descriptor; Linux rejects every alias and neither platform follows the alias pathname.

Parameters
[in]stateInitialized confined-root adapter state.
[in]pathValidated portable path below the bound root.
[out]out_parent_fdReceives the owned parent directory descriptor.
[out]out_leafReceives the terminated final component.
Returns
Resolution status.
Return values
k_ra8_okBoth parent descriptor and leaf were published.
k_ra8_err_access_deniedAn intermediate component is an unapproved symlink.
k_ra8_err_not_foundAn intermediate component is absent or not a directory.
k_ra8_err_invalid_sizeA component or iteration bound is invalid.
k_ra8_err_*Mapped descriptor operation failure.
Precondition
Pointer arguments are non-NULL and outputs have advertised capacity.
path passed portable lexical validation and is not root-only.
Postcondition
On success caller owns *out_parent_fd and out_leaf is populated.
On failure every descriptor opened by this resolver is closed.
Note
Thread-safe for independent state; host namespace changes can race resolution.
Since
Version 0.1.0

Definition at line 178 of file fw_if_fs_posix.c.

References internal_next_component(), internal_parent_open_step(), k_fw_fs_path_cap, k_posix_component_cap, k_ra8_err_invalid_size, k_ra8_ok, memcpy(), priv_fs_posix_close_fd_preserve(), priv_fs_posix_errno(), RA8_PRIV, and fw_fs_posix_state_t::root_fd.

Referenced by internal_directory_open(), internal_mkdir(), internal_native_stat(), internal_parent_sync(), internal_rename(), internal_rmdir(), internal_unlink(), and priv_fs_posix_open().

Variable Documentation

◆ s_namespace_iface

const fw_fs_namespace_iface_t s_namespace_iface
static
Initial value:
= {
.stat = internal_stat,
.mkdir = internal_mkdir,
.unlink = internal_unlink,
.rmdir = internal_rmdir,
.rename = internal_rename,
.space = internal_space,
}
ra8_err_t priv_fs_posix_dir_open(void *ctx, const char *path, void *directory_state, uint32_t state_bytes)
Open a confined raw-directory cursor in caller storage.
ra8_err_t priv_fs_posix_dir_next(void *ctx, void *directory_state, fw_fs_dirent_value_t *out, bool *out_entry)
Copy the next visible raw-directory entry.
ra8_err_t priv_fs_posix_dir_close(void *ctx, void *directory_state)
Close one owned raw-directory descriptor.
ra8_err_t priv_fs_posix_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 a POSIX directory through bounded raw records.
static ra8_err_t internal_rename(void *ctx, const char *old_path, const char *new_path, bool replace)
static ra8_err_t internal_space(void *ctx, fw_fs_space_t *out)
static ra8_err_t internal_mkdir(void *ctx, const char *path)
static ra8_err_t internal_rmdir(void *ctx, const char *path)
static ra8_err_t internal_unlink(void *ctx, const char *path)
static ra8_err_t internal_stat(void *ctx, const char *path, fw_fs_stat_t *out)

Immutable POSIX namespace vtable.

Definition at line 812 of file fw_if_fs_posix.c.

◆ s_transaction_iface

const fw_fs_transaction_iface_t s_transaction_iface
static
Initial value:
= {
.validate = internal_txn_validate,
}
static ra8_err_t internal_txn_commit(void *ctx, void *transaction_state, bool *out_published)
static ra8_err_t internal_txn_begin(void *ctx, void *transaction_state, uint32_t state_bytes, const char *destination, fw_fs_transaction_policy_t policy)
static ra8_err_t internal_txn_validate(void *ctx, void *transaction_state, fw_fs_validate_fn_t validator, void *validator_ctx)
static ra8_err_t internal_txn_abort(void *ctx, void *transaction_state)
static ra8_err_t internal_txn_seek(void *ctx, void *transaction_state, uint64_t offset)
static ra8_err_t internal_txn_write(void *ctx, void *transaction_state, const uint8_t *src, uint32_t len, uint32_t *out_written)

Immutable POSIX transaction vtable.

Definition at line 826 of file fw_if_fs_posix.c.