18typedef enum : uint32_t {
82 for (uint32_t i = 0U; i < length; ++i) {
84 for (uint8_t bit = 0U; bit < 8U; ++bit) {
85 const uint32_t mask = (uint32_t)(0U - (state & 1U));
101 out[0] = (uint8_t)(value >> 8U);
102 out[1] = (uint8_t)value;
115 out[1] = (uint8_t)(value >> 16U);
116 out[2] = (uint8_t)(value >> 8U);
117 out[3] = (uint8_t)value;
129 for (uint8_t i = 0U; i < 8U; ++i) {
143 return (uint16_t)(((uint16_t)in[0] << 8U) | (uint16_t)in[1]);
156 ((uint32_t)in[2] << 8U) | (uint32_t)in[3];
169 for (uint8_t i = 0U; i < 8U; ++i) {
170 value = (value << 8U) | (uint64_t)in[i];
208 const uint32_t actual =
216 (actual != expected)) {
235 uint32_t offset = 0U;
236 while (offset < length) {
266 uint64_t remaining = length;
267 uint32_t state = UINT32_MAX;
269 while (remaining > 0U) {
273 const uint32_t wanted = (remaining < (uint64_t)storage->
io_buffer_bytes)
274 ? (uint32_t)remaining
303 uint64_t file_bytes = 0U;
341 if ((storage ==
nullptr) || (storage->
fs ==
nullptr) || (path ==
nullptr)) {
352 const size_t length =
strlen(path);
356 memcpy(base, path, length + 1U);
357 memcpy(alternate, path, length + 1U);
396 const bool too_short = stat.
size_bytes <
sizeof(prefix);
401 if (legacy_magic && allow_legacy) {
404 }
else if (legacy_magic) {
451 *newest = base->
valid ? base : alternate;
463 *newest = base_newer ? base : alternate;
464 *older = base_newer ? alternate : base;
497 const uint16_t max_schema =
521 uint32_t offset = 0U;
522 while (offset < length) {
552 (writer->
payload_bytes > (UINT64_MAX - (uint64_t)(uint32_t)length))) {
577 const int length = snprintf(line,
sizeof(line),
"%c\t%s\n", type, value);
591 static const char types[] = {
'S',
'T',
'N',
'H',
'G',
'D',
'W',
'A',
'O',
'K',
'L'};
604 for (
size_t i = 0U; (i <
sizeof(types)) && (err ==
k_ra8_ok); ++i) {
609 const int length = snprintf(line,
sizeof(line),
"R\t%u\n", (
unsigned)st->
reading_direction);
629 uint64_t number_bits = 0U;
630 memcpy(&number_bits, &chapter->
number,
sizeof(number_bits));
631 const int length = snprintf(line,
633 "C\t%s\t%u\t%016" PRIx64
"\t%u\t%u\t%u\t%" PRId64
"\t%s\t%s\n",
662 const int length = snprintf(line,
664 "P\t%016" PRIx64
"\t%016" PRIx64
"\t%s\t%s\t%s\t%" PRId64
"\t%u\n",
688 const int length = snprintf(line,
690 "# mdl library state v%u\nV\t%u\n",
712 if ((ctx ==
nullptr) || (staged ==
nullptr)) {
739 if (!transaction->
active) {
743 return (aborted ==
k_ra8_ok) ? primary : aborted;
768 .crc_state = UINT32_MAX,
779 .payload_crc32 = ~writer.crc_state};
813 if (newest ==
nullptr) {
824 *target = (newest == base) ? alternate : base;
825 if ((older !=
nullptr) && (*target != older)) {
828 if (!(*target)->exists && ((*target)->error !=
k_ra8_ok)) {
829 return (*target)->error;
837 if (out_exists ==
nullptr) {
847 const char* paths[] = {base, alternate};
848 for (
size_t i = 0U; i < 2U; ++i) {
857 *out_exists = *out_exists || stat.
exists;
906 if (newest ==
nullptr) {
914 if ((err !=
k_ra8_ok) && (older !=
nullptr)) {
939 const char** out_target,
940 uint64_t* out_sequence)
961 *out_target = target->
path;
968 if (out_published ==
nullptr) {
971 *out_published =
false;
977 const char* target =
nullptr;
978 uint64_t sequence = 0U;
990 bool published =
false;
992 *out_published = published;
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_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_transaction_abort(fw_fs_transaction_t *transaction)
Close and remove an unpublished staging artifact.
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_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_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_seek(fw_fs_file_t *file, uint64_t absolute_offset)
Seek to an absolute byte offset from the beginning.
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_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.
@ 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_fw_fs_txn_create_new
Commit only when destination is absent.
bool priv_mdl_state_valid(const mdl_state_t *st)
Validate every bound and cross-field invariant before persistence.
Persistent per-series library state for the media downloader.
@ k_mdl_state_version
Timestamped cache schema written now.
@ k_mdl_state_version_v2
Legacy decimal schema accepted.
void mdl_state_init(mdl_state_t *st)
Reset a state object to an empty, current-version library.
ra8_err_t priv_mdl_state_parse_file(mdl_storage_t *storage, fw_fs_file_t *file, uint64_t offset, uint64_t length, uint16_t max_schema_version, mdl_state_t *st)
Parse one exact state payload from an open portable file.
Module-private validation shared by the state model and codec.
@ k_mdl_state_line_max
Serialized line cap.
static ra8_err_t internal_mdl_state_read_all(fw_fs_file_t *file, uint8_t *out, uint32_t length, uint32_t *calls)
Read an exact byte count while rejecting zero progress.
static uint16_t internal_mdl_state_get_be16(const uint8_t *in)
Decode one canonical big-endian uint16.
static void internal_mdl_state_put_be16(uint8_t *out, uint16_t value)
Encode one uint16 in canonical big-endian order.
static uint64_t internal_mdl_state_get_be64(const uint8_t *in)
Decode one canonical big-endian uint64.
static void internal_mdl_state_encode_header(const mdl_state_envelope_t *envelope, uint8_t *out)
Encode one self-checking canonical envelope.
static bool internal_mdl_state_decode_header(const uint8_t *bytes, mdl_state_envelope_t *out)
Decode and authenticate one canonical envelope.
static ra8_err_t internal_mdl_state_hash_payload(mdl_storage_t *storage, fw_fs_file_t *file, uint64_t length, uint32_t *out_crc)
Hash one exact payload extent and reject early EOF.
mdl_state_store_limit_t
Canonical journal-envelope and bounded-I/O constants.
@ k_state_be64_high_shift
High-byte shift for uint64.
@ k_state_header_crc_offset
Header-CRC byte offset.
@ k_state_magic_bytes
Journal magic width.
@ k_state_header_reserved_offset
Reserved field byte offset.
@ k_state_header_crc_span
Header bytes authenticated.
@ k_state_header_payload_size_offset
Payload-size byte offset.
@ k_state_header_payload_crc_offset
Payload-CRC byte offset.
@ k_state_be32_high_shift
High-byte shift for uint32.
@ k_state_header_bytes
Canonical envelope width.
@ k_state_crc32_polynomial
Reflected CRC-32 polynomial.
@ k_state_header_size_offset
Header-size byte offset.
@ k_state_io_call_max
Retry ceiling.
@ k_state_header_version_offset
Envelope-version byte offset.
@ k_state_envelope_v1
Envelope schema version.
@ k_state_header_sequence_offset
Sequence field byte offset.
@ k_state_alt_suffix
Bytes in .alt.
static ra8_err_t internal_mdl_state_emit_pages(mdl_state_writer_t *writer, const mdl_state_t *st)
Serialize every page identity and cache record.
static ra8_err_t internal_mdl_state_build_stage(mdl_storage_t *storage, const char *target, uint64_t sequence, const mdl_state_t *st, fw_fs_transaction_t *transaction, mdl_state_envelope_t *envelope)
Build and validate a private staged journal.
static ra8_err_t internal_mdl_state_abort(fw_fs_transaction_t *transaction, ra8_err_t primary)
Abort an unpublished transaction with cleanup-error precedence.
static ra8_err_t internal_mdl_state_validate_stage(void *ctx, fw_fs_file_t *staged)
Independently validate the staged journal before publication.
static uint32_t internal_mdl_state_crc32_update(uint32_t state, const uint8_t *bytes, uint32_t length)
Update an unfinalized reflected CRC-32 state.
static ra8_err_t internal_mdl_state_prepare_target(mdl_storage_t *storage, const char *path, char *base, char *alternate, const char **out_target, uint64_t *out_sequence)
Decide which generation slot the next save occupies, and clear it.
static void internal_mdl_state_put_be32(uint8_t *out, uint32_t value)
Encode one uint32 in canonical big-endian order.
static void internal_mdl_state_put_be64(uint8_t *out, uint64_t value)
Encode one uint64 in canonical big-endian order.
ra8_err_t mdl_state_save(mdl_storage_t *storage, const char *path, const mdl_state_t *st, bool *out_published)
Publish a checksummed successor without sacrificing the newest state.
static ra8_err_t internal_mdl_state_load_slot(mdl_storage_t *storage, const mdl_state_slot_t *slot, mdl_state_t *st)
Load and revalidate one previously scanned generation.
static ra8_err_t internal_mdl_state_paths(const mdl_storage_t *storage, const char *path, char *base, char *alternate)
Derive and validate both physical generation paths.
static ra8_err_t internal_mdl_state_load_mode(mdl_storage_t *storage, const char *path, mdl_state_t *st, bool allow_legacy)
Load the newest usable state with an explicit legacy policy.
static ra8_err_t internal_mdl_state_save_plan(const mdl_state_slot_t *base, const mdl_state_slot_t *alternate, const mdl_state_slot_t **target, uint64_t *sequence)
Select the preserved generation, rewrite target, and next sequence.
static ra8_err_t internal_mdl_state_emit(mdl_state_writer_t *writer, const char *line, int length)
Append one payload record and update its identity.
static uint32_t internal_mdl_state_get_be32(const uint8_t *in)
Decode one canonical big-endian uint32.
ra8_err_t mdl_state_load(mdl_storage_t *storage, const char *path, mdl_state_t *st)
Load a series' newest valid state through injected portable storage.
static ra8_err_t internal_mdl_state_emit_chapters(mdl_state_writer_t *writer, const mdl_state_t *st)
Serialize every chapter with exact v3 numeric identity.
static bool internal_mdl_state_same_generation(const mdl_state_slot_t *a, const mdl_state_slot_t *b)
Check whether two slots describe the same generation.
static const uint8_t s_state_magic[k_state_magic_bytes]
Canonical journal magic, encoded byte-for-byte.
static ra8_err_t internal_mdl_state_emit_kv(mdl_state_writer_t *writer, char type, const char *value)
Serialize one bounded key/value record.
ra8_err_t mdl_state_load_authenticated(mdl_storage_t *storage, const char *path, mdl_state_t *st)
Load only an authenticated checksummed state generation.
static ra8_err_t internal_mdl_state_order(const mdl_state_slot_t *base, const mdl_state_slot_t *alternate, const mdl_state_slot_t **newest, const mdl_state_slot_t **older)
Order valid generations newest first.
static ra8_err_t internal_mdl_state_serialize(mdl_state_writer_t *writer, const mdl_state_t *st)
Serialize one complete current-schema payload.
static ra8_err_t internal_mdl_state_validate_open(mdl_storage_t *storage, fw_fs_file_t *file, mdl_state_envelope_t *out)
Validate an open journal envelope, extent, and checksum.
static void internal_mdl_state_scan_slot(mdl_storage_t *storage, const char *path, bool allow_legacy, mdl_state_slot_t *out)
Scan one physical generation without parsing its payload.
static ra8_err_t internal_mdl_state_write_all(mdl_state_writer_t *writer, const uint8_t *bytes, uint32_t length)
Write all bytes to an active transaction with bounded retry.
static ra8_err_t internal_mdl_state_emit_metadata(mdl_state_writer_t *writer, const mdl_state_t *st)
Serialize every fixed series identity and metadata record.
ra8_err_t mdl_state_probe(mdl_storage_t *storage, const char *path, bool *out_exists)
Probe the complete two-generation state marker through portable storage.
Annotation-attribute framework macros for ra8-firmware.
#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_ok
Success – operation completed with all postconditions satisfied.
@ k_ra8_err_protocol_error
Protocol-level error (e.g.
@ 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_caps_t caps
Shared capabilities.
fw_fs_namespace_t names
Namespace operations.
fw_fs_transaction_port_t transactions
Staged publication.
Caller-owned transaction; fields are private to the facade.
bool active
Begin succeeded.
One chapter's coverage in library state.
char chapter_id[k_mdl_chapter_id_max]
Stable identifier (URL leaf).
double number
Parsed number; 0 may be valid.
int64_t fetched_at
Completion time (epoch s).
char source_url[k_mdl_url_max]
Chapter page URL.
uint16_t pages_done
Pages fetched and verified.
bool number_known
Whether number is known.
char title[k_mdl_title_max]
Display title, or empty.
uint16_t page_count
Total pages known (0 = ?).
bool complete
All pages present + verified.
One page's dedup/verify record in the series-wide pool.
char etag[k_mdl_etag_max]
Cached ETag for conditional GET.
char last_modified[k_mdl_last_mod_max]
Cached Last-Modified response value.
uint64_t content_hash
FNV-1a 64 of the fetched bytes.
char rel_path[k_mdl_relpath_max]
Path under the series directory.
uint64_t url_hash
FNV-1a 64 of the source URL.
uint16_t response_status
Most recent HTTP status; zero if legacy.
int64_t fetched_at
Most recent HTTP result time (epoch s).
Decoded canonical journal envelope.
uint64_t payload_bytes
Exact v1/v2 text payload size.
uint32_t payload_crc32
CRC-32 of payload bytes.
uint64_t sequence
Monotonic generation sequence.
One physical generation discovered under the logical path.
uint64_t file_bytes
Observed file extent.
bool legacy
Slot is legacy text.
bool valid
Slot is intact.
const char * path
Physical path.
ra8_err_t error
Scan status.
mdl_state_envelope_t envelope
Journal identity.
One series' complete persistent state (declare at file scope).
char summary[k_mdl_summary_max]
Series synopsis.
uint16_t chapter_count
Chapters recorded.
char cover_path[k_mdl_relpath_max]
Local cover path.
char series_title[k_mdl_title_max]
Series title.
mdl_chapter_rec_t chapters[k_mdl_max_chapters]
Per-chapter coverage.
char series_url[k_mdl_url_max]
Series page URL.
char site_name[k_mdl_name_max]
Descriptor name.
mdl_state_reading_direction_t reading_direction
Page progression.
char language[k_mdl_language_max]
BCP-47 language tag.
char artist[k_mdl_person_max]
Artist/illustrator.
uint32_t page_rec_count
Page records recorded.
mdl_page_rec_t pages[k_mdl_max_page_recs]
Per-page identities.
char site_host[k_mdl_host_max]
Site host.
char cover_url[k_mdl_url_max]
Remote cover URL.
char config_path[k_mdl_cfgpath_max]
Descriptor used.
char writer[k_mdl_person_max]
Writer/author.
Expected stage identity passed to the independent validator.
mdl_storage_t * storage
Validation scratch.
mdl_state_envelope_t envelope
Expected identity.
Streaming serialization state for one transaction.
uint32_t calls
Bounded write attempts.
fw_fs_transaction_t * transaction
Active private stage.
uint32_t crc_state
Unfinalized CRC-32.
uint64_t payload_bytes
Bytes after envelope.
One non-reentrant downloader filesystem dependency bundle.
uint32_t transaction_workspace_bytes
Transaction workspace extent.
uint32_t file_workspace_bytes
File workspace extent.
void * transaction_workspace
Transaction backend state.
uint8_t * io_buffer
Caller-owned stream scratch.
const fw_fs_t * fs
Injected portable filesystem.
void * file_workspace
Open-file backend state.
uint32_t io_buffer_bytes
Stream scratch extent.