62 if (block ==
nullptr) {
82 if (read ==
nullptr) {
94 const size_t got = read(ctx, 0U, block,
sizeof(block));
95 if (got !=
sizeof(block)) {
129 if (off > (t->
size - need)) {
132 const size_t got = t->
read(t->
ctx, off, block, (
size_t)need);
133 if ((uint64_t)got != need) {
161 if (dsize > (UINT64_MAX - (blk - 1U))) {
164 const uint64_t blocks = (dsize + (blk - 1U)) / blk;
165 if (blocks > ((UINT64_MAX / blk) - 1U)) {
168 const uint64_t span = (blocks + 1U) * blk;
169 if (off > (UINT64_MAX - span)) {
211 uint8_t*
const data = s_tar_meta_scratch;
212 const size_t got = t->
read(t->
ctx, doff, data, (
size_t)dsize);
213 if ((uint64_t)got != dsize) {
227 size_t nlen = (size_t)dsize;
229 if (data[nlen - 1U] != 0U) {
234 const size_t want = (nlen > (size_t)meta->
name_cap) ? (
size_t)meta->
name_cap : nlen;
262 while ((length < (
size_t)capacity) && (block[offset + length] != 0U)) {
290 const size_t pw = (p_len > (size_t)meta->
name_cap) ? (
size_t)meta->
name_cap : p_len;
295 if (used < (
size_t)meta->
name_cap) {
300 const size_t room = (size_t)meta->
name_cap - used;
301 const size_t nw = (n_len > room) ? room : n_len;
305 meta->
name_len = (uint16_t)(used + nw);
379 const uint8_t* block,
386 uint64_t msize = dsize;
396 if (msize > (t->
size - doff)) {
434 tar_meta_t meta = {.name_buf = name_buf, .name_cap = name_cap};
441 if (cur >= t->
size) {
461 if (dsize > (t->
size - doff)) {
503 if ((uint64_t)cap < ent->size) {
512 if (ent->
size == 0U) {
516 if ((uint64_t)n != ent->
size) {
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Validation and Error-Checking Macros for ra8-firmware.
#define RA8_CHECK_NULL_PTR(ptr, tag, message)
Reject nullptr pointer, returning k_ra8_err_null_ptr.
ra8_err_t ra8_decomp_check_declared(const ra8_decomp_limits_t *limits, uint64_t comp_size, uint64_t out_size)
Header-level check of a member's declared sizes against a policy.
ra8_err_t ra8_decomp_budget_charge_entry(ra8_decomp_budget_t *b)
Charge one enumerated archive entry against the entry cap.
ra8_err_t ra8_decomp_budget_charge_iter(ra8_decomp_budget_t *b)
Charge one decode-loop turn against the iteration budget.
ra8_err_t ra8_decomp_budget_init(ra8_decomp_budget_t *b, const ra8_decomp_limits_t *limits)
Bind a budget to a policy (or the default policy) and zero it.
@ k_ra8_err_not_supported
Requested feature not compiled in, not wired, or not supported by this MCU variant.
@ k_ra8_err_no_mem
Static buffer exhausted (no dynamic memory on this project).
@ 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_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 * memcpy(void *dst, const void *src, size_t n)
Copy memory area between non-overlapping regions.
#define ra8_log_error(tag, message)
RA8 log error.
ra8_decomp_limits_t limits
Policy in force for this budget.
One decompression policy: the five resource bounds decoders enforce.
One decoded tar member: a file, a directory, or a skipped block.
uint64_t data_off
Absolute offset of the member's data area.
uint64_t size
Member data length in bytes (stored verbatim).
uint64_t next_off
Absolute offset of the next member's first block.
uint8_t is_file
1 if this member is a regular file.
uint16_t name_len
Name bytes copied into the caller buffer (clamped).
uint8_t is_dir
1 if this member is a directory.
One open tar archive: the backing plus the walk's running budget.
void * ctx
Context for read.
uint64_t size
Archive length in bytes.
bool live
Open succeeded and not superseded.
unarch_read_fn read
Byte reader over the archive.
ra8_decomp_budget_t budget
Entry / iteration budget for the walk.
size_t(* unarch_read_fn)(void *ctx, uint64_t offset, void *buf, size_t len)
Seek+read backing over an archive's bytes.
ra8_err_t unarch_tar_open(unarch_tar_t *t, unarch_read_fn read, void *ctx, uint64_t size, const ra8_decomp_limits_t *limits)
Bind a walker to an archive and validate its first header block.
ra8_err_t unarch_tar_next(unarch_tar_t *t, uint64_t off, char *name_buf, uint16_t name_cap, unarch_tar_entry_t *out)
Decode the member at off and advance to the next member.
static const char *const s_tag_tar
Log tag for tar-walker diagnostics.
static ra8_err_t internal_next_off(uint64_t off, uint64_t dsize, uint64_t *next)
Compute the offset of the block after a member, overflow-checked.
static void internal_ustar_name(const uint8_t *block, tar_meta_t *meta)
Assemble a ustar member name (prefix + '/' + name), clamped.
static ra8_err_t internal_read_block(const unarch_tar_t *t, uint64_t off, uint8_t *block)
Read one full header block at off, bounds-checked.
ra8_err_t unarch_tar_read(const unarch_tar_t *t, const unarch_tar_entry_t *ent, uint8_t *buf, size_t cap, size_t *got)
Copy a file member's data area into the caller buffer.
static size_t internal_field_length(const uint8_t *block, uint32_t offset, uint32_t capacity)
Measure one NUL-terminated-or-full ustar header field.
bool unarch_tar_probe(const uint8_t *block, size_t len)
Whether a leading header block looks like a tar archive.
static ra8_err_t internal_finish_member(unarch_tar_t *t, const uint8_t *block, uint64_t off, ra8_tar_type_t type, uint64_t dsize, tar_meta_t *meta, unarch_tar_entry_t *out)
Finish decoding the real member header into the caller entry.
static ra8_err_t internal_decode_header(const uint8_t *block, uint64_t off, ra8_tar_type_t *type, uint64_t *dsize, uint64_t *next)
Validate one header block and decode its size / type / next offset.
static ra8_err_t internal_meta_consume(const unarch_tar_t *t, ra8_tar_type_t type, uint64_t doff, uint64_t dsize, tar_meta_t *meta)
Consume one pax / GNU-longname meta block's data area.
Clean-room, read-only streaming tar walker (POSIX ustar + pax + GNU).
@ k_unarch_tar_pax_max
Max pax / longname data bytes.
@ k_unarch_tar_block
On-disk block / header size.
@ k_unarch_tar_meta_max
Max meta (x/g/L/K) blocks per member.
ra8_err_t priv_unarch_tar_pax_parse(const uint8_t *data, size_t len, char *name_buf, uint16_t name_cap, uint16_t *name_len, bool *have_path, uint64_t *size_ovr, bool *have_size)
Parse pax extended-header records, extracting path / size.
bool priv_unarch_tar_block_zero(const uint8_t *block)
Whether a header block is all zero bytes (end-of-archive marker).
bool priv_unarch_tar_magic_ok(const uint8_t *block)
Whether a header block carries the ustar / GNU magic.
bool priv_unarch_tar_checksum_ok(const uint8_t *block)
Verify a header block's checksum (unsigned byte sum).
ra8_err_t priv_unarch_tar_num(const uint8_t *field, size_t len, uint64_t *out)
Decode a tar numeric field (octal ASCII or GNU base-256).
ra8_tar_type_t priv_unarch_tar_classify(uint8_t typeflag)
Classify a header block's typeflag byte.
Module-private tar field/record parsers shared across the tar TUs.
@ k_ra8_tar_len_prefix
prefix field length.
@ k_ra8_tar_off_prefix
prefix field offset.
@ k_ra8_tar_len_size
size field length.
@ k_ra8_tar_off_size
size field offset.
@ k_ra8_tar_off_name
name field offset.
@ k_ra8_tar_off_type
typeflag byte offset.
@ k_ra8_tar_len_name
name field length.
ra8_tar_type_t
Normalised classification of a header block's typeflag.
@ k_ra8_tar_type_pax
pax extended header ('x').
@ k_ra8_tar_type_other
Any other member kind (skipped).
@ k_ra8_tar_type_dir
Directory ('5').
@ k_ra8_tar_type_meta
Skipped meta: 'g' global, 'K' longlink.
@ k_ra8_tar_type_file
Regular file ('0' or NUL).
@ k_ra8_tar_type_longname
GNU longname data ('L').