11#define _POSIX_C_SOURCE (200809L)
47extern int renameat(
int old_dir_fd,
const char* old_path,
int new_dir_fd,
const char* new_path);
50typedef enum : uint32_t {
80 if ((source ==
nullptr) || (got ==
nullptr) || ((bytes ==
nullptr) && (len != 0U))) {
84 if ((offset >= source->
source.
size) || (len == 0U)) {
87 uint64_t remain = source->
source.
size - offset;
88 if ((uint64_t)len > remain) {
92 const ssize_t rc = pread(source->
fd, &bytes[*got], len - *got, (off_t)(offset + *got));
97 }
else if (errno != EINTR) {
125 if ((sink ==
nullptr) || ((bytes ==
nullptr) && (len != 0U))) {
130 const ssize_t rc =
write(sink->
fd, &bytes[done], len - done);
133 }
else if ((rc < 0) && (errno == EINTR)) {
162 if ((len + 1U) > cap) {
165 (void)
memcpy(out, text, len);
192 const size_t len = (path ==
nullptr) ? 0U :
strlen(path);
196 const char* slash =
strrchr(path,
'/');
197 const char* name = (slash ==
nullptr) ? path : &slash[1];
198 const size_t name_len = len - (size_t)(name - path);
199 if ((name_len == 0U) || ((name_len == 1U) && (name[0] ==
'.')) ||
200 ((name_len == 2U) && (name[0] ==
'.') && (name[1] ==
'.'))) {
207 if (slash ==
nullptr) {
210 const size_t parent_len = (slash == path) ? 1U : (size_t)(slash - path);
239 }
while (value != 0U);
240 if ((*len + count + 1U) > cap) {
243 while (count != 0U) {
244 name[(*len)++] = reverse[--count];
268 static const char suffix[] =
".ra8tmp.";
272 if ((1U + leaf_len +
sizeof(suffix)) >
sizeof(state->
stage_name)) {
278 len +=
sizeof(suffix) - 1U;
308 struct stat status = {};
337 if ((state ==
nullptr) || !state->
active || ((bytes ==
nullptr) && (len != 0U))) {
363 if (state ==
nullptr) {
401 if ((state ==
nullptr) || !state->
active || (state->
stage_fd < 0)) {
404 const int stage_sync_rc = fsync(state->
stage_fd);
405 const int stage_close_rc = close(state->
stage_fd);
407 if ((stage_sync_rc != 0) || (stage_close_rc != 0)) {
416 const int sync_rc = fsync(state->
parent_fd);
439 const struct timespec modified = status->st_mtimespec;
440 const struct timespec changed = status->st_ctimespec;
442 const struct timespec modified = status->st_mtim;
443 const struct timespec changed = status->st_ctim;
446 .device = (uint64_t)status->st_dev,
447 .inode = (uint64_t)status->st_ino,
448 .size = (uint64_t)status->st_size,
449 .mtime_sec = (int64_t)modified.tv_sec,
450 .mtime_nsec = (int64_t)modified.tv_nsec,
451 .ctime_sec = (int64_t)changed.tv_sec,
452 .ctime_nsec = (int64_t)changed.tv_nsec,
501 if ((source ==
nullptr) || (source->
source.
size != expected_size)) {
517 if ((path ==
nullptr) || (out ==
nullptr)) {
525 struct stat status = {};
526 if ((fstat(fd, &status) != 0) || !S_ISREG(status.st_mode) || (status.st_size <= 0) ||
527 ((uint64_t)status.st_size > max_size)) {
543 if ((first ==
nullptr) || (second ==
nullptr) || (first == second) || (first->
fd < 0) ||
544 (second->
fd < 0) || (first->
fd == second->
fd)) {
552 if ((source ==
nullptr) || (source->
fd < 0)) {
555 struct stat status = {};
556 if (fstat(source->
fd, &status) != 0) {
559 if (!S_ISREG(status.st_mode)) {
570 if ((source !=
nullptr) && (source->
fd >= 0)) {
571 (void)close(source->
fd);
590 if ((path ==
nullptr) || (state ==
nullptr) || (out ==
nullptr)) {
static RA8_INTERNAL ssize_t internal_pread(int fd, void *buf, size_t count, off_t offset)
Call the default positioned input primitive.
#define O_DIRECTORY
No-op directory-open fallback for hosts lacking the flag.
#define O_NOFOLLOW
Zero fallback paired with explicit no-follow metadata validation.
#define AT_SYMLINK_NOFOLLOW
Zero fallback paired with explicit target-type rejection.
#define O_CLOEXEC
Zero fallback when the host lacks close-on-exec open flags.
Annotation-attribute framework macros for ra8-firmware.
#define RA8_PRIV
Module-private helper: shared across TUs but only inside one library.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
static ra8_err_t internal_source_validate(const ra8_camera_source_t *source)
Validate a source handle and its mandatory vtable rows.
@ k_ra8_fail
Generic unspecified failure.
@ 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_err_validation_failed
Validation rule failed (caller-supplied invariant not satisfied).
@ 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.
ra8_err_t priv_fmt_host_transaction_begin(const char *path, ra8_fmt_host_transaction_t *state, ra8_fmt_transaction_t *out)
Begin a sibling-temp durable replacement transaction.
static ra8_err_t internal_fd_write(void *ctx, const uint8_t *bytes, size_t len)
Append all requested bytes to one descriptor.
int renameat(int old_dir_fd, const char *old_path, int new_dir_fd, const char *new_path)
Rename one directory-relative path to another atomically.
static void internal_transaction_abort(void *ctx)
Discard transaction-owned staging resources.
static ra8_err_t internal_pread(void *ctx, uint64_t offset, uint8_t *bytes, size_t len, size_t *got)
Perform positioned reads with exact offset handling and legal short EOF.
static ra8_err_t internal_copy(char *out, size_t cap, const char *text, size_t len)
Copy a bounded string slice and append NUL.
bool priv_fmt_host_sources_same(const ra8_fmt_host_source_t *first, const ra8_fmt_host_source_t *second)
Confirm two opens captured the same unchanged regular-file object.
static ra8_err_t internal_transaction_commit(void *ctx)
Sync, install, and directory-sync one staged artifact.
ra8_err_t priv_fmt_host_source_open(const char *path, uint64_t max_size, ra8_fmt_host_source_t *out)
Open a bounded, regular, non-symlink input object.
void priv_fmt_host_log_byte(void *ctx, uint8_t byte)
Adapt a logging byte to an injected raw-fd sink.
static const ra8_fmt_transaction_ops_t s_transaction_ops
static ra8_err_t internal_stage_name(ra8_fmt_host_transaction_t *state, uint32_t attempt)
Build a bounded sibling staging name.
ra8_fmt_sink_t priv_fmt_host_fd_sink(ra8_fmt_host_fd_sink_t *state)
Obtain the exact-write portable sink for a raw descriptor.
static void internal_snapshot(const struct stat *status, ra8_fmt_host_snapshot_t *out)
Capture portable-width identity and mutation fields from host metadata.
static ra8_err_t internal_name_u64(char *name, size_t cap, size_t *len, uint64_t value)
Append one unsigned decimal to a bounded stage name.
static ra8_err_t internal_transaction_append(void *ctx, const uint8_t *bytes, size_t len)
Append transaction bytes exactly once.
static ra8_err_t internal_validate_destination(int parent_fd, const char *leaf)
Reject existing non-regular or symlink destinations.
static ra8_err_t internal_split_path(const char *path, char parent[k_ra8_fmt_host_path_cap], char leaf[k_ra8_fmt_host_name_cap])
Split a destination into a parent path and safe leaf name.
static ra8_err_t internal_source_validate(void *ctx, uint64_t expected_size)
Portable source-validation callback over host snapshot evidence.
host_const_t
Host adapter bounds.
@ k_host_create_attempts
Collision-bounded stage creation.
@ k_host_mode_private
Staging-file permissions.
@ k_host_decimal_radix
Decimal name digit radix.
void priv_fmt_host_source_close(ra8_fmt_host_source_t *source)
Close an open host source; safe after failed open.
static bool internal_snapshot_same(const ra8_fmt_host_snapshot_t *first, const ra8_fmt_host_snapshot_t *second)
Compare complete captured regular-file evidence.
ra8_err_t priv_fmt_host_source_unchanged(const ra8_fmt_host_source_t *source)
Revalidate one open descriptor against its captured snapshot.
Raw file-descriptor adapters for the portable format-tool contracts.
@ k_ra8_fmt_host_path_cap
Parent-path storage including NUL.
@ k_ra8_fmt_host_name_cap
One leaf name including NUL.
size_t strlen(const char *s)
Calculate string length.
void * memcpy(void *dst, const void *src, size_t n)
Copy memory area between non-overlapping regions.
char * strrchr(const char *s, int c)
Locate last occurrence of character in string.
Append sink backed by a caller-owned descriptor.
int fd
Borrowed writable descriptor.
Captured regular-file identity and mutation evidence.
int64_t ctime_nsec
Metadata-change timestamp nanoseconds.
int64_t ctime_sec
Metadata-change timestamp seconds.
uint64_t device
Filesystem device identifier.
int64_t mtime_sec
Modification timestamp seconds.
int64_t mtime_nsec
Modification timestamp nanoseconds.
uint64_t size
Captured regular-file extent.
uint64_t inode
File object identifier.
Open raw-fd source and its portable view.
ra8_fmt_source_t source
Portable positioned-read view.
int fd
Owned descriptor, or -1 when closed.
ra8_fmt_host_snapshot_t snapshot
Immutable-open evidence.
Caller-owned state for one sibling-file transaction.
char stage_name[k_ra8_fmt_host_name_cap]
Staging leaf name.
char final_name[k_ra8_fmt_host_name_cap]
Destination leaf name.
int parent_fd
Owned parent directory.
bool stage_exists
Stage still needs unlink.
int stage_fd
Owned staging descriptor.
bool active
Transaction is usable.
uint64_t position
Bytes appended so far.
Injected append-only sink.
uint64_t size
Exact object byte length.
void * ctx
Backend-owned context.
ra8_fmt_source_validate_fn validate
Optional stability callback.
jof_pread_fn read_at
Positioned-read callback.
Durable artifact-transaction operations.
One caller-owned artifact transaction.
void * ctx
Backend-owned state.
const ra8_fmt_transaction_ops_t * ops
Transaction implementation.