19typedef enum : uint32_t {
41 {
'M',
'D',
'L',
'C',
'A',
'C',
'H',
'1'};
58 static const char k_hex[] =
"0123456789abcdef";
59 for (uint8_t i = 0U; i < 16U; ++i) {
85 static const char k_prefix[] =
"host-";
86 const size_t required = (
sizeof(k_prefix) - 1U) + 16U + 1U;
87 if (capacity < required) {
90 memcpy(destination, k_prefix,
sizeof(k_prefix) - 1U);
92 destination[required - 1U] =
'\0';
117 uint64_t content_hash)
119 static const char k_prefix[] =
"body-";
120 static const char k_suffix[] =
".cache";
121 const size_t required = (
sizeof(k_prefix) - 1U) + 16U + 1U + 16U +
sizeof(k_suffix);
122 if (capacity < required) {
126 memcpy(&destination[cursor], k_prefix,
sizeof(k_prefix) - 1U);
127 cursor +=
sizeof(k_prefix) - 1U;
130 destination[cursor++] =
'-';
133 memcpy(&destination[cursor], k_suffix,
sizeof(k_suffix));
152 out[0] = (uint8_t)(value >> 8U);
153 out[1] = (uint8_t)value;
171 for (uint8_t i = 0U; i < 8U; ++i) {
192 return (uint16_t)(((uint16_t)in[0] << 8U) | (uint16_t)in[1]);
212 for (uint8_t i = 0U; i < 8U; ++i) {
213 value = (value << 8U) | (uint64_t)in[i];
241 uint32_t offset = 0U;
242 while (offset < length) {
246 uint32_t received = 0U;
247 const ra8_err_t error =
fw_fs_read(file, destination + offset, length - offset, &received);
252 if (received == 0U) {
321 if ((cache ==
nullptr) || (cache->
storage ==
nullptr) || (cache->
root ==
nullptr) ||
357 const bool fields = (record->
url[0] !=
'\0') && (record->
relative_path[0] !=
'\0') &&
358 (strpbrk(record->
url,
"\t\r\n") ==
nullptr) &&
360 (strpbrk(record->
etag,
"\r\n") ==
nullptr) &&
406 const size_t capacities[] = {
sizeof(record->
url),
408 sizeof(record->
etag),
419 for (
size_t i = 0U; i < 4U; ++i) {
420 if ((
size_t)lengths[i] >= capacities[i]) {
427 fields[i][lengths[i]] =
'\0';
470 const uint64_t expected_size =
476 (expected_size != size_bytes) ||
484 for (uint16_t i = 0U; (error ==
k_ra8_ok) && (i < count); ++i) {
496 return (error ==
k_ra8_ok) ? closed : error;
537 if ((cache ==
nullptr) || (cache->
storage ==
nullptr) || (cache->
index ==
nullptr) ||
538 (url ==
nullptr) || (paths ==
nullptr) || (rebuilt ==
nullptr)) {
594 for (
size_t i = 0U; i < 4U; ++i) {
595 const size_t length =
strlen(fields[i]);
596 if (length > UINT16_MAX) {
599 lengths[i] = (uint16_t)length;
643 bytes +=
sizeof(header);
644 const char* fields[] = {index->
records[i].
url,
648 for (
size_t field = 0U; field < 4U; ++field) {
650 bytes += lengths[field];
685 const char* fields[] = {index->
records[i].
url,
689 for (
size_t field = 0U; (error ==
k_ra8_ok) && (field < 4U); ++field) {
701 if ((cache ==
nullptr) || (cache->
storage ==
nullptr) || (cache->
index ==
nullptr) ||
712 uint64_t payload_bytes = 0U;
713 uint64_t payload_hash = 0U;
741 return (aborted ==
k_ra8_ok) ? error : aborted;
767 const char* body_path,
787 if ((error ==
k_ra8_ok) && (got != 0U)) {
804 if ((storage ==
nullptr) || (paths ==
nullptr) || (record ==
nullptr) || (buffer ==
nullptr) ||
805 (capacity == 0U) || (out_length ==
nullptr)) {
835 uint64_t content_hash,
839 size_t relative_capacity)
841 if ((storage ==
nullptr) || (paths ==
nullptr) || (buffer ==
nullptr) || (length == 0U) ||
842 (length > UINT32_MAX) || (relative_path ==
nullptr) || (relative_capacity == 0U)) {
859 return (aborted ==
k_ra8_ok) ? error : aborted;
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.
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_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_close(fw_fs_file_t *file)
Close and consume an open handle.
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_mkdir(const fw_fs_namespace_t *names, const char *path)
Create exactly one directory; parents must already exist.
@ k_fw_fs_node_directory
Directory.
@ k_fw_fs_node_file
Regular byte stream.
@ k_fw_fs_path_cap
Largest portable path including its NUL.
@ k_fw_fs_open_read
Existing file, read-only.
@ k_mdl_cache_schema_version
Current binary index schema.
@ k_mdl_cache_record_max
Records retained per host.
Private binary-index and body I/O seams for mdl_cache.
static ra8_err_t internal_cache_decode(mdl_cache_t *cache, const mdl_cache_paths_t *paths, uint64_t size_bytes)
Decode and authenticate one complete index file.
ra8_err_t priv_mdl_cache_load(mdl_cache_t *cache, const char *url, mdl_cache_paths_t *paths, bool *rebuilt)
Prepare a host directory and load or recover its index.
mdl_cache_binary_limit_t
Canonical binary layout and bounded I/O constants.
@ k_cache_record_path_len
Record path-length offset.
@ k_cache_header_host
Header host-hash offset.
@ k_cache_trailer_bytes
Payload-hash trailer width.
@ k_cache_nibble_mask
Low hexadecimal nibble mask.
@ k_cache_header_count
Header record-count offset.
@ k_cache_status_max
Largest retained HTTP code.
@ k_cache_record_url_len
Record URL-length offset.
@ k_cache_io_call_max
Short-I/O progress ceiling.
@ k_cache_record_bytes
Fixed record header width.
@ k_cache_record_etag_len
Record ETag-length offset.
@ k_cache_record_status
Record HTTP-status offset.
@ k_cache_record_reserved
Record reserved-field offset.
@ k_cache_status_min
Smallest retained HTTP code.
@ k_cache_hex_high_shift
Shift of the first hash nibble.
@ k_cache_header_bytes
Fixed index header width.
@ k_cache_record_time_len
Record modified-length offset.
@ k_cache_u64_high_shift
Shift of the first uint64 byte.
ra8_err_t priv_mdl_cache_publish_body(mdl_storage_t *storage, const mdl_cache_paths_t *paths, uint64_t url_hash, uint64_t content_hash, const char *buffer, size_t length, char *relative_path, size_t relative_capacity)
Publish one new body under its immutable content-derived leaf.
static ra8_err_t internal_cache_read_record(fw_fs_file_t *file, uint32_t *calls, uint64_t *hash, mdl_cache_record_t *record, const mdl_cache_paths_t *paths)
Decode one variable-length record and update its payload hash.
static ra8_err_t internal_cache_discard_index(mdl_cache_t *cache, const char *path)
Remove one corrupt regular index.
ra8_err_t priv_mdl_cache_read_body(mdl_storage_t *storage, const mdl_cache_paths_t *paths, const mdl_cache_record_t *record, char *buffer, size_t capacity, size_t *out_length)
Read and hash-check one retained body into caller storage.
static bool internal_cache_encode_record(const mdl_cache_record_t *record, uint8_t *header, uint16_t *lengths)
Encode one record header and compute exact string lengths.
static void internal_cache_put_u16(uint8_t *out, uint16_t value)
Encode one big-endian uint16.
static bool internal_cache_record_valid(const mdl_cache_record_t *record, const mdl_cache_paths_t *paths)
Validate one decoded persistent record.
static void internal_cache_hex16(char *destination, uint64_t value)
Encode exactly sixteen lowercase hexadecimal digits.
static bool internal_cache_body_leaf(char *destination, size_t capacity, uint64_t url_hash, uint64_t content_hash)
Format one immutable body leaf without stdio.
ra8_err_t priv_mdl_cache_save(mdl_cache_t *cache, const mdl_cache_paths_t *paths)
Transactionally publish the current host index.
static ra8_err_t internal_cache_read_all(fw_fs_file_t *file, uint8_t *destination, uint32_t length, uint32_t *calls)
Read exactly one bounded span from an open file.
static ra8_err_t internal_cache_write_records(mdl_storage_txn_t *writer, const mdl_cache_index_t *index)
Stream every encoded record into an active transaction.
static ra8_err_t internal_cache_ensure_directory(mdl_storage_t *storage, const char *path)
Ensure a cache namespace component is a real directory.
static uint64_t internal_cache_get_u64(const uint8_t *in)
Decode one big-endian uint64.
static const uint8_t s_cache_magic[k_cache_trailer_bytes]
Canonical cache index magic.
static uint16_t internal_cache_get_u16(const uint8_t *in)
Decode one big-endian uint16.
static ra8_err_t internal_cache_paths(mdl_cache_t *cache, const char *url, mdl_cache_paths_t *paths)
Derive and prepare one host-specific cache namespace.
static ra8_err_t internal_cache_read_body_exact(mdl_storage_t *storage, const char *body_path, char *buffer, uint64_t size_bytes)
Read a body file's exact declared extent and confirm no trailer.
static bool internal_cache_host_leaf(char *destination, size_t capacity, uint64_t host_hash)
Format one host-directory leaf without stdio.
static void internal_cache_put_u64(uint8_t *out, uint64_t value)
Encode one big-endian uint64.
static ra8_err_t internal_cache_payload_identity(const mdl_cache_index_t *index, uint64_t *out_bytes, uint64_t *out_hash)
Compute payload extent and hash for the current index.
Content-identity hashing (FNV-1a 64) for the media downloader's persistent library state.
uint64_t mdl_hash_bytes(const void *data, size_t len)
FNV-1a 64 hash of a byte range.
@ k_mdl_fnv_offset
FNV-1a 64 offset basis.
uint64_t mdl_hash_bytes_seed(const void *data, size_t len, uint64_t seed)
Continue an FNV-1a 64 fold over a byte range from a running state.
uint64_t mdl_hash_str(const char *s)
FNV-1a 64 hash of a NUL-terminated string (excluding the NUL).
@ k_mdl_gov_host_max
Host-key buffer bytes (matches config).
Neutralise untrusted names before they reach a filesystem or XML sink.
bool mdl_path_join(const char *parent, const char *seg, char *out, size_t cap)
Join one safe child segment under a parent directory path.
ra8_err_t mdl_storage_txn_write(mdl_storage_txn_t *writer, const uint8_t *bytes, uint32_t length)
Append one complete caller chunk, tolerating bounded short writes.
ra8_err_t mdl_storage_txn_abort(mdl_storage_txn_t *writer)
Abort and clear one streamed transaction.
ra8_err_t mdl_storage_txn_commit(mdl_storage_txn_t *writer)
Independently validate and publish a completed streamed transaction.
ra8_err_t mdl_storage_txn_begin(mdl_storage_txn_t *writer, mdl_storage_t *storage, const char *destination)
Begin one streamed create or truthful atomic replacement.
Pure URL / address safety predicates for the libcurl backend.
bool mdl_url_host(const char *url, char *out, size_t cap)
Extract the authority (host and optional port) from an http(s) URL.
#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).
@ k_ra8_err_invalid_arg
Invalid function argument.
@ 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_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.
void * memset(void *dst, int value, size_t n)
Fill memory with a constant byte value.
int memcmp(const void *a, const void *b, size_t n)
Compare bytes in two memory areas.
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.
Caller-owned open file; fields are private to the facade.
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.
fw_fs_stream_port_t streams
Byte-stream operations.
fw_fs_namespace_t names
Namespace operations.
Caller-owned workspace for one loaded host index.
uint64_t host_hash
Bound host identity.
uint16_t schema_version
Binary schema version.
mdl_cache_record_t records[k_mdl_cache_record_max]
Retained observations.
uint16_t record_count
Populated rows.
Complete paths and host identity derived for one request.
uint64_t host_hash
Stable host identity.
char host[k_mdl_gov_host_max]
Lowercase host and optional port.
char index_path[k_fw_fs_path_cap]
Versioned host index path.
char directory[k_fw_fs_path_cap]
Host-specific cache directory.
One exact URL-keyed cached document observation.
uint64_t content_hash
Exact persisted body identity.
char url[k_mdl_url_max]
Exact canonical request URL.
char etag[k_mdl_etag_max]
Last response ETag, or empty.
char last_modified[k_mdl_last_mod_max]
Last-Modified, or empty.
uint64_t url_hash
FNV identity accelerator.
uint16_t response_status
Last observed HTTP status.
int64_t fetched_at
Completion epoch seconds.
char relative_path[k_mdl_relpath_max]
Body leaf beneath the host dir.
One non-reentrant cache binding over caller storage.
const char * root
Canonical cache root.
mdl_storage_t * storage
Injected portable storage binding.
mdl_cache_index_t * index
Caller-owned index workspace.
One non-reentrant downloader filesystem dependency bundle.
uint32_t file_workspace_bytes
File workspace extent.
const fw_fs_t * fs
Injected portable filesystem.
void * file_workspace
Open-file backend state.
Caller-owned streaming publication transaction with running identity.