42typedef enum : uint32_t {
76 if (field[i] != (uint8_t)
' ') {
83 while ((i < len) && (field[i] != 0U) && (field[i] != (uint8_t)
' ')) {
84 const uint8_t c = field[i];
85 if (c < (uint8_t)
'0') {
88 if (c > (uint8_t)
'7') {
91 const uint64_t d = (uint64_t)c - (uint64_t)(uint8_t)
'0';
134 for (
size_t i = 1U; i < len; ++i) {
135 const size_t remaining = len - i;
137 if (field[i] != 0U) {
165 if (block[i] != 0U) {
180 uint64_t stored = 0U;
185 return stored == (uint64_t)sum;
190 static const uint8_t magic[] = {
'u',
's',
't',
'a',
'r'};
191 for (
size_t i = 0U; i <
sizeof(magic); ++i) {
197 return (term == 0U) || (term == (uint8_t)
' ');
202 if (typeflag == (uint8_t)
'0') {
205 if (typeflag == 0U) {
208 if (typeflag == (uint8_t)
'5') {
211 if (typeflag == (uint8_t)
'x') {
214 if (typeflag == (uint8_t)
'g') {
217 if (typeflag == (uint8_t)
'K') {
220 if (typeflag == (uint8_t)
'L') {
252 const uint8_t c = data[i];
253 if (c == (uint8_t)
' ') {
256 if (c < (uint8_t)
'0') {
259 if (c > (uint8_t)
'9') {
305 for (
size_t i = 0U; i < len; ++i) {
306 const uint8_t c = val[i];
307 if (c < (uint8_t)
'0') {
310 if (c > (uint8_t)
'9') {
313 const uint64_t d = (uint64_t)c - (uint64_t)(uint8_t)
'0';
359 static const uint8_t key_path[] = {
'p',
'a',
't',
'h'};
360 static const uint8_t key_size[] = {
's',
'i',
'z',
'e'};
361 bool is_path = key_len ==
sizeof(key_path);
362 for (
size_t i = 0U; is_path && (i <
sizeof(key_path)); ++i) {
363 is_path = key[i] == key_path[i];
366 const size_t want = (val_len > (size_t)name_cap) ? (
size_t)name_cap : val_len;
368 (void)
memcpy(name_buf, val, want);
370 *name_len = (uint16_t)want;
374 bool is_size = key_len ==
sizeof(key_size);
375 for (
size_t i = 0U; is_size && (i <
sizeof(key_size)); ++i) {
376 is_size = key[i] == key_size[i];
413 if (reclen <= body) {
416 if (reclen > (len - off)) {
419 if (data[off + reclen - 1U] != (uint8_t)
'\n') {
422 const uint8_t* kv = &data[off + body];
423 const size_t kv_len = reclen - body - 1U;
425 while ((key_len < kv_len) && (kv[key_len] != (uint8_t)
'=')) {
428 if (key_len == kv_len) {
434 kv_len - key_len - 1U,
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).
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.
@ k_ra8_err_validation_failed
Validation rule failed (caller-supplied invariant not satisfied).
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
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.
@ k_unarch_tar_block
On-disk block / header size.
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.
static ra8_err_t internal_pax_reclen(const uint8_t *data, size_t len, size_t *reclen, size_t *body)
Decode one pax record's decimal length prefix.
bool priv_unarch_tar_block_zero(const uint8_t *block)
Whether a header block is all zero bytes (end-of-archive marker).
static ra8_err_t internal_octal(const uint8_t *field, size_t len, uint64_t *out)
Decode an octal ASCII field (leading spaces, NUL/space terminated).
static const char *const s_tag_tar_f
Log tag for tar field-parser diagnostics.
bool priv_unarch_tar_magic_ok(const uint8_t *block)
Whether a header block carries the ustar / GNU magic.
static ra8_err_t internal_pax_apply(const uint8_t *key, size_t key_len, const uint8_t *val, size_t val_len, char *name_buf, uint16_t name_cap, uint16_t *name_len, bool *have_path, uint64_t *size_ovr, bool *have_size)
Apply one parsed pax record's key/value to the override outputs.
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).
static ra8_err_t internal_base256(const uint8_t *field, size_t len, uint64_t *out)
Decode a GNU base-256 (big-endian binary) numeric field.
ra8_tar_type_t priv_unarch_tar_classify(uint8_t typeflag)
Classify a header block's typeflag byte.
static ra8_err_t internal_pax_size_value(const uint8_t *val, size_t len, uint64_t *out)
Decimal-decode a pax size record value with overflow checks.
tar_field_const_t
Grammar constants for the numeric and pax record parsers.
@ k_tar_octal_base
Octal radix.
@ k_tar_b256_flag
Base-256 marker bit in byte 0.
@ k_tar_pax_len_max
Max digits in a pax record length.
@ k_tar_shift_byte
Bits per base-256 byte.
@ k_tar_chksum_space
chksum bytes count as spaces.
@ k_tar_b256_payload
Payload mask of base-256 byte 0.
@ k_tar_b256_fit
Trailing bytes that fit in uint64.
@ k_tar_decimal_base
pax record-length / size radix.
@ k_tar_b256_negative
Sign bit of a base-256 value.
Module-private tar field/record parsers shared across the tar TUs.
@ k_ra8_tar_len_chksum
chksum field length.
@ k_ra8_tar_off_magic_term
Byte after "ustar" (NUL or ' ').
@ k_ra8_tar_off_chksum
chksum field offset.
@ k_ra8_tar_off_magic
magic field offset.
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').