ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_rar.c
Go to the documentation of this file.
1
31#include "ra8_rar.h"
32
33#include <string.h>
34
35#include "ra8_attributes.h"
36#include "ra8_check.h"
37#include "ra8_rar5.h"
38
40static const char* const s_tag_rar = "ra8_rar";
41
55RA8_INTERNAL static void internal_copy_object(void* dst, const void* src, size_t len)
56{
57 (void)memcpy(dst, src, len);
58}
59
76RA8_INTERNAL static bool internal_bytes_equal(const void* lhs, const void* rhs, size_t len)
77{
78 return memcmp(lhs, rhs, len) == 0;
79}
80
87typedef enum : uint8_t {
92
113
120typedef enum : uint16_t {
127
146
152typedef enum : uint8_t {
156} rar_word_t;
157
173static uint16_t internal_le16(const uint8_t* p)
174{
175 uint16_t v = 0U;
176 internal_copy_object(&v, p, sizeof(v));
177 return v;
178}
179
195static uint32_t internal_le32(const uint8_t* p)
196{
197 uint32_t v = 0U;
198 internal_copy_object(&v, p, sizeof(v));
199 return v;
200}
201
226static bool internal_vint(const uint8_t* buf, size_t len, size_t* pos, uint64_t* val)
227{
228 uint32_t words[2] = {0U, 0U}; /* [0] = low 32 bits, [1] = high 32 bits */
229 uint32_t shift = 0U;
230 const uint32_t hi_bit = (uint32_t)k_rar_hi_sh; /* 32 */
231 const uint32_t straddle = (uint32_t)k_rar_hi_sh - (uint32_t)k_rar_vint_bits; /* 25 */
232 for (uint16_t i = 0U; i < (uint16_t)k_ra8_rar_vint_max; ++i) { /* <=10 bytes */
233 if (*pos >= len) {
234 return false;
235 }
236 const uint8_t b = buf[*pos];
237 *pos += 1U;
238 const uint32_t d = (uint32_t)b & (uint32_t)k_rar_vint_data;
239 if (shift < hi_bit) {
240 words[0] |= (uint32_t)(d << shift);
241 if (shift > straddle) { /* this 7-bit group straddles the 32-bit boundary */
242 words[1] |= (uint32_t)(d >> (hi_bit - shift));
243 }
244 } else {
245 words[1] |= (uint32_t)(d << (shift - hi_bit));
246 }
247 if ((b & (uint8_t)k_rar_vint_cont) == 0U) {
248 internal_copy_object(val, words, sizeof(*val)); /* LE host + target: word[0] low */
249 return true;
250 }
251 shift += (uint32_t)k_rar_vint_bits;
252 }
253 return false;
254}
255
279static uint16_t internal_copy_name(const ra8_rar_t* rar,
280 uint64_t name_abs,
281 const uint8_t* scratch,
282 size_t n,
283 size_t in_pos,
284 uint64_t name_len,
285 char* name_buf,
286 uint16_t name_cap)
287{
288 if (name_buf == nullptr) {
289 return 0U;
290 }
291 if (name_cap == 0U) {
292 return 0U;
293 }
294 const uint16_t want = (name_len > (uint64_t)name_cap) ? name_cap : (uint16_t)name_len;
295 if ((in_pos + (size_t)want) <= n) {
296 (void)memcpy(name_buf, &scratch[in_pos], (size_t)want);
297 return want;
298 }
299 const size_t got = rar->read(rar->ctx, name_abs, name_buf, (size_t)want);
300 return (uint16_t)got;
301}
302
329static bool internal_rar4_file(const ra8_rar_t* rar,
330 uint64_t off,
331 const uint8_t* scratch,
332 size_t n,
333 uint16_t flags,
334 uint16_t hsize,
335 char* nbuf,
336 uint16_t ncap,
337 ra8_rar_entry_t* out)
338{
339 const bool large = (flags & (uint16_t)k_rar4_flag_large) != 0U;
340 const size_t needfix = large ? (size_t)k_rar4_off_name_large : (size_t)k_rar4_off_name;
341 if (n < needfix) {
342 return false;
343 }
344 uint64_t pack = (uint64_t)internal_le32(&scratch[k_rar4_off_add]);
345 uint64_t unp = (uint64_t)internal_le32(&scratch[k_rar4_off_unp]);
346 const uint8_t method = scratch[k_rar4_off_method];
347 const uint16_t namesz = internal_le16(&scratch[k_rar4_off_namesz]);
348 size_t pos = (size_t)k_rar4_off_name;
349 if (large) {
350 pack |= (uint64_t)internal_le32(&scratch[k_rar4_off_name]) << (uint32_t)k_rar_hi_sh;
351 unp |= (uint64_t)internal_le32(&scratch[(size_t)k_rar4_off_name + (size_t)k_rar_w32])
352 << (uint32_t)k_rar_hi_sh;
353 pos = (size_t)k_rar4_off_name_large;
354 }
355 out->is_file = 1U;
356 out->is_dir = ((flags & (uint16_t)k_rar4_flag_dirmsk) == (uint16_t)k_rar4_flag_dirmsk) ? 1U : 0U;
357 out->method = (method == (uint8_t)k_rar4_method_stor) ? (uint8_t)k_ra8_rar_method_store
359 out->pack_size = pack;
360 out->unp_size = unp;
361 out->data_off = off + (uint64_t)hsize;
362 out->next_off = off + (uint64_t)hsize + pack;
363 out->name_len =
364 internal_copy_name(rar, off + (uint64_t)pos, scratch, n, pos, (uint64_t)namesz, nbuf, ncap);
365 return true;
366}
367
391 uint64_t off,
392 char* nbuf,
393 uint16_t ncap,
394 ra8_rar_entry_t* out)
395{
396 uint8_t scratch[k_ra8_rar_hdr_scratch] = {};
397 const size_t n = rar->read(rar->ctx, off, scratch, sizeof(scratch));
398 if (n < (size_t)k_rar4_base_len) {
400 }
401 const uint8_t type = scratch[k_rar4_off_type];
402 const uint16_t flags = internal_le16(&scratch[k_rar4_off_flags]);
403 const uint16_t hsize = internal_le16(&scratch[k_rar4_off_size]);
404 if (hsize < (uint16_t)k_rar4_base_len) {
406 }
407 const bool islong = (flags & (uint16_t)k_rar4_flag_long) != 0U;
408 uint64_t add = 0U;
409 if (islong) {
410 if (n >= ((size_t)k_rar4_off_add + (size_t)k_rar_w32)) {
411 add = (uint64_t)internal_le32(&scratch[k_rar4_off_add]);
412 }
413 }
414 if (type == (uint8_t)k_rar4_type_file) {
415 if (!internal_rar4_file(rar, off, scratch, n, flags, hsize, nbuf, ncap, out)) {
417 }
418 } else {
419 out->next_off = off + (uint64_t)hsize + add;
420 }
421 if (out->next_off <= off) {
423 }
424 return k_ra8_ok;
425}
426
452static bool internal_rar5_file_vints(const uint8_t* scratch,
453 size_t n,
454 size_t* pos,
455 uint64_t* fflags,
456 uint64_t* unp,
457 uint64_t* cinfo,
458 uint64_t* namesz)
459{
460 uint64_t attr = 0U;
461 uint64_t hostos = 0U;
462 if (!internal_vint(scratch, n, pos, fflags)) {
463 return false;
464 }
465 if (!internal_vint(scratch, n, pos, unp)) {
466 return false;
467 }
468 if (!internal_vint(scratch, n, pos, &attr)) {
469 return false;
470 }
471 if ((*fflags & (uint64_t)k_rar5_fflag_mtime) != 0U) {
472 *pos += (size_t)k_rar5_fixed_field;
473 }
474 if ((*fflags & (uint64_t)k_rar5_fflag_crc) != 0U) {
475 *pos += (size_t)k_rar5_fixed_field;
476 }
477 if (!internal_vint(scratch, n, pos, cinfo)) {
478 return false;
479 }
480 if (!internal_vint(scratch, n, pos, &hostos)) {
481 return false;
482 }
483 if (!internal_vint(scratch, n, pos, namesz)) {
484 return false;
485 }
486 (void)attr; /* decoded to advance the vint stream; value unused here */
487 (void)hostos; /* decoded to advance the vint stream; value unused here */
488 return true;
489}
490
519static bool internal_rar5_file(const ra8_rar_t* rar,
520 uint64_t off,
521 const uint8_t* scratch,
522 size_t n,
523 size_t pos,
524 uint64_t data_off,
525 uint64_t dsize,
526 char* nbuf,
527 uint16_t ncap,
528 ra8_rar_entry_t* out)
529{
530 uint64_t fflags = 0U;
531 uint64_t unp = 0U;
532 uint64_t cinfo = 0U;
533 uint64_t namesz = 0U;
534 if (!internal_rar5_file_vints(scratch, n, &pos, &fflags, &unp, &cinfo, &namesz)) {
535 return false;
536 }
537 const uint8_t method =
538 (uint8_t)((cinfo >> (uint64_t)k_rar5_method_shift) & (uint64_t)k_rar5_method_mask);
539 out->is_file = 1U;
540 out->is_dir = ((fflags & (uint64_t)k_rar5_fflag_dir) != 0U) ? 1U : 0U;
541 out->method =
542 (method == 0U) ? (uint8_t)k_ra8_rar_method_store : (uint8_t)k_ra8_rar_method_compressed;
543 out->unp_size = unp;
544 out->pack_size = dsize;
545 out->data_off = data_off;
546 out->name_len = internal_copy_name(rar, off + (uint64_t)pos, scratch, n, pos, namesz, nbuf, ncap);
547 return true;
548}
549
573 uint64_t off,
574 char* nbuf,
575 uint16_t ncap,
576 ra8_rar_entry_t* out)
577{
578 uint8_t scratch[k_ra8_rar_hdr_scratch] = {};
579 const size_t n = rar->read(rar->ctx, off, scratch, sizeof(scratch));
580 size_t pos = (size_t)k_rar_w32; /* skip the 4-byte header CRC32 */
581 uint64_t hsize = 0U;
582 if (!internal_vint(scratch, n, &pos, &hsize)) {
584 }
585 const uint64_t data_off = off + (uint64_t)pos + hsize; /* header data ends here */
586 uint64_t htype = 0U;
587 uint64_t hflags = 0U;
588 if (!internal_vint(scratch, n, &pos, &htype)) {
590 }
591 if (!internal_vint(scratch, n, &pos, &hflags)) {
593 }
594 uint64_t extra = 0U;
595 if ((hflags & (uint64_t)k_rar5_hflag_extra) != 0U) {
596 if (!internal_vint(scratch, n, &pos, &extra)) {
598 }
599 }
600 (void)extra; /* extra-area length is skipped via the header-size vint */
601 uint64_t dsize = 0U;
602 if ((hflags & (uint64_t)k_rar5_hflag_data) != 0U) {
603 if (!internal_vint(scratch, n, &pos, &dsize)) {
605 }
606 }
607 out->next_off = data_off + dsize;
608 if (htype == (uint64_t)k_rar5_type_file) {
609 if (!internal_rar5_file(rar, off, scratch, n, pos, data_off, dsize, nbuf, ncap, out)) {
611 }
612 }
613 if (out->next_off <= off) {
615 }
616 return k_ra8_ok;
617}
618
640static void internal_rar_match_signature(const uint8_t* hdr, size_t got, ra8_rar_t* rar)
641{
642 static const char k_sig5[] = "Rar!\x1A\x07\x01"; /* + implicit NUL = 8-byte RAR5 sig */
643 static const char k_sig4[] = "Rar!\x1A\x07"; /* + implicit NUL = 7-byte RAR4 marker */
644 static_assert(sizeof(k_sig5) == (size_t)k_ra8_rar_sig5_len, "RAR5 signature length");
645 static_assert(sizeof(k_sig4) == (size_t)k_ra8_rar_sig4_len, "RAR4 marker length");
646 if (got >= (size_t)k_ra8_rar_sig5_len) {
647 if (internal_bytes_equal(hdr, k_sig5, (size_t)k_ra8_rar_sig5_len)) {
649 rar->first_off = (uint64_t)k_ra8_rar_sig5_len;
650 return;
651 }
652 }
653 if (internal_bytes_equal(hdr, k_sig4, (size_t)k_ra8_rar_sig4_len)) {
655 rar->first_off = (uint64_t)k_ra8_rar_sig4_len;
656 }
657}
658
659ra8_err_t ra8_rar_open(ra8_rar_t* rar, ra8_rar_read_fn read, void* ctx, uint64_t size)
660{
661 RA8_CHECK_NULL_PTR(rar, s_tag_rar, "open: null rar");
662 RA8_CHECK_NULL_PTR(read, s_tag_rar, "open: null read");
663 *rar = (ra8_rar_t){};
664 if (size < (uint64_t)k_ra8_rar_sig4_len) {
666 }
667 uint8_t hdr[k_ra8_rar_sig5_len] = {};
668 const size_t got = read(ctx, 0U, hdr, sizeof(hdr));
669 if (got < (size_t)k_ra8_rar_sig4_len) {
671 }
672 internal_rar_match_signature(hdr, got, rar);
673 if (rar->version == k_ra8_rar_ver_none) {
675 }
676 rar->read = read;
677 rar->ctx = ctx;
678 rar->size = size;
679 return k_ra8_ok;
680}
681
683 uint64_t off,
684 char* name_buf,
685 uint16_t name_cap,
686 ra8_rar_entry_t* out)
687{
688 RA8_CHECK_NULL_PTR(rar, s_tag_rar, "next: null rar");
689 RA8_CHECK_NULL_PTR(out, s_tag_rar, "next: null out");
690 *out = (ra8_rar_entry_t){};
691 if (rar->version == k_ra8_rar_ver_none) {
693 }
694 if (off >= rar->size) {
696 }
697 if (rar->version == k_ra8_rar_ver_5) {
698 return internal_rar5_block(rar, off, name_buf, name_cap, out);
699 }
700 return internal_rar4_block(rar, off, name_buf, name_cap, out);
701}
702
726static ra8_err_t
727internal_rar_check_stored(const ra8_rar_t* rar, const ra8_rar_entry_t* ent, size_t cap)
728{
729 if (rar->version == k_ra8_rar_ver_none) {
731 }
732 if (ent->is_file == 0U) {
734 }
735 if (ent->is_dir != 0U) {
737 }
738 if (ent->method != (uint8_t)k_ra8_rar_method_store) {
740 }
741 if (ent->unp_size > (uint64_t)cap) {
742 return k_ra8_err_no_mem;
743 }
744 if ((ent->data_off + ent->unp_size) > rar->size) {
746 }
747 return k_ra8_ok;
748}
749
770static bool
771internal_rar_read_exact(const ra8_rar_t* rar, uint64_t data_off, uint64_t need, uint8_t* buf)
772{
773 size_t total = 0U;
774 while ((uint64_t)total < need) { /* bound: need fixed; each pass reads >=1 or breaks */
775 const size_t chunk = (size_t)(need - (uint64_t)total);
776 const size_t r = rar->read(rar->ctx, data_off + (uint64_t)total, &buf[total], chunk);
777 if (r == 0U) {
778 break;
779 }
780 total += r;
781 }
782 return (uint64_t)total == need;
783}
784
786 const ra8_rar_entry_t* ent,
787 uint8_t* buf,
788 size_t cap,
789 size_t* got)
790{
791 RA8_CHECK_NULL_PTR(rar, s_tag_rar, "extract: null rar");
792 RA8_CHECK_NULL_PTR(ent, s_tag_rar, "extract: null ent");
793 RA8_CHECK_NULL_PTR(buf, s_tag_rar, "extract: null buf");
794 RA8_CHECK_NULL_PTR(got, s_tag_rar, "extract: null got");
795 *got = 0U;
796 const ra8_err_t vcheck = internal_rar_check_stored(rar, ent, cap);
797 if (vcheck != k_ra8_ok) {
798 return vcheck;
799 }
800 if (!internal_rar_read_exact(rar, ent->data_off, ent->unp_size, buf)) {
802 }
803 *got = (size_t)ent->unp_size;
804 return k_ra8_ok;
805}
806
829 const ra8_rar_entry_t* ent,
830 const uint8_t* buf,
831 const size_t* got)
832{
833 RA8_CHECK_NULL_PTR(rar, s_tag_rar, "extract: null rar");
834 RA8_CHECK_NULL_PTR(ent, s_tag_rar, "extract: null ent");
835 RA8_CHECK_NULL_PTR(buf, s_tag_rar, "extract: null buf");
836 RA8_CHECK_NULL_PTR(got, s_tag_rar, "extract: null got");
837 return k_ra8_ok;
838}
839
841 const ra8_rar_entry_t* ent,
842 uint8_t* buf,
843 size_t cap,
845 size_t* got)
846{
847 const ra8_err_t nchk = internal_rar_extract_reject_null(rar, ent, buf, got);
848 if (nchk != k_ra8_ok) {
849 return nchk;
850 }
851 *got = 0U;
852 if (rar->version == k_ra8_rar_ver_none) {
854 }
855 if ((ent->is_file == 0U) || (ent->is_dir != 0U)) {
857 }
858 if (ent->method == (uint8_t)k_ra8_rar_method_store) {
859 return ra8_rar_extract_stored(rar, ent, buf, cap, got);
860 }
861 if (rar->version != k_ra8_rar_ver_5) {
862 return k_ra8_err_not_supported; /* RAR4 legacy codec is out of scope */
863 }
864 RA8_CHECK_NULL_PTR(st, s_tag_rar, "extract: null st for compressed");
865 return ra8_rar5_decompress(rar, ent->data_off, ent->pack_size, buf, cap, ent->unp_size, st, got);
866}
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.
Definition ra8_check.h:243
@ k_ra8_err_not_supported
Requested feature not compiled in, not wired, or not supported by this MCU variant.
Definition ra8_err.h:180
@ k_ra8_err_no_mem
Static buffer exhausted (no dynamic memory on this project).
Definition ra8_err.h:142
@ k_ra8_err_invalid_arg
Invalid function argument.
Definition ra8_err.h:152
@ k_ra8_err_invalid_state
Module in wrong state for requested operation.
Definition ra8_err.h:161
@ k_ra8_err_validation_failed
Validation rule failed (caller-supplied invariant not satisfied).
Definition ra8_err.h:459
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
@ k_ra8_err_invalid_size
Invalid size parameter (too large, too small, or misaligned).
Definition ra8_err.h:167
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
int memcmp(const void *a, const void *b, size_t n)
Compare bytes in two memory areas.
void * memcpy(void *dst, const void *src, size_t n)
Copy memory area between non-overlapping regions.
Clean-room RAR 5.0 ("method 50") decompressor – LZ + Huffman + filters.
ra8_err_t ra8_rar5_decompress(const ra8_rar_t *rar, uint64_t data_off, uint64_t pack_size, uint8_t *out, size_t out_cap, uint64_t unp_size, ra8_rar5_state_t *st, size_t *got)
Decompress one RAR5-packed member into the caller's output buffer.
Definition ra8_rar5.c:776
static bool internal_rar5_file(const ra8_rar_t *rar, uint64_t off, const uint8_t *scratch, size_t n, size_t pos, uint64_t data_off, uint64_t dsize, char *nbuf, uint16_t ncap, ra8_rar_entry_t *out)
Decode the RAR5 file-specific fields after the common header vints.
Definition ra8_rar.c:519
static ra8_err_t internal_rar_check_stored(const ra8_rar_t *rar, const ra8_rar_entry_t *ent, size_t cap)
Validate that ent is an extractable STORE member fitting cap.
Definition ra8_rar.c:727
static ra8_err_t internal_rar_extract_reject_null(const ra8_rar_t *rar, const ra8_rar_entry_t *ent, const uint8_t *buf, const size_t *got)
Null-check the required arguments of ra8_rar_extract.
Definition ra8_rar.c:828
rar_word_t
Byte widths and the 32-bit high-dword shift used by the decoders.
Definition ra8_rar.c:152
@ k_rar_w32
uint32 width.
Definition ra8_rar.c:154
@ k_rar_w16
uint16 width.
Definition ra8_rar.c:153
@ k_rar_hi_sh
High-dword shift for 64-bit sizes.
Definition ra8_rar.c:155
static bool internal_bytes_equal(const void *lhs, const void *rhs, size_t len)
Compare byte representations through compatible pointer types.
Definition ra8_rar.c:76
static const char *const s_tag_rar
Log tag for RAR-walker diagnostics.
Definition ra8_rar.c:40
rar4_bits_t
RAR4 header flag bits, block type, and method sentinel.
Definition ra8_rar.c:120
@ k_rar4_type_file
File-header block type ('t').
Definition ra8_rar.c:124
@ k_rar4_method_stor
METHOD value for STORE ('0').
Definition ra8_rar.c:125
@ k_rar4_flag_dirmsk
(flags & this) == this -> directory.
Definition ra8_rar.c:123
@ k_rar4_flag_large
64-bit HIGH_PACK/HIGH_UNP sizes present.
Definition ra8_rar.c:122
@ k_rar4_flag_long
ADD_SIZE present after the base header.
Definition ra8_rar.c:121
ra8_err_t ra8_rar_next(const ra8_rar_t *rar, uint64_t off, char *name_buf, uint16_t name_cap, ra8_rar_entry_t *out)
Decode the block header at off and advance to the next block.
Definition ra8_rar.c:682
rar4_layout_t
RAR4 block/file-header field byte offsets (from the block start).
Definition ra8_rar.c:100
@ k_rar4_off_method
METHOD byte (0x30 = store).
Definition ra8_rar.c:107
@ k_rar4_off_size
HEAD_SIZE uint16.
Definition ra8_rar.c:103
@ k_rar4_off_name
FILE_NAME start (no LARGE flag).
Definition ra8_rar.c:110
@ k_rar4_off_flags
HEAD_FLAGS uint16.
Definition ra8_rar.c:102
@ k_rar4_off_namesz
NAME_SIZE uint16.
Definition ra8_rar.c:108
@ k_rar4_off_add
ADD_SIZE / PACK_SIZE uint32.
Definition ra8_rar.c:104
@ k_rar4_off_attr
ATTR uint32 (fixed fields end +4).
Definition ra8_rar.c:109
@ k_rar4_base_len
Base header length before ADD_SIZE.
Definition ra8_rar.c:105
@ k_rar4_off_type
HEAD_TYPE byte.
Definition ra8_rar.c:101
@ k_rar4_off_unp
UNP_SIZE uint32.
Definition ra8_rar.c:106
@ k_rar4_off_name_large
FILE_NAME start (LARGE 64-bit).
Definition ra8_rar.c:111
ra8_err_t ra8_rar_open(ra8_rar_t *rar, ra8_rar_read_fn read, void *ctx, uint64_t size)
Detect a RAR archive's generation and locate its first block.
Definition ra8_rar.c:659
static uint32_t internal_le32(const uint8_t *p)
Decode a little-endian uint32 from four unaligned bytes.
Definition ra8_rar.c:195
static bool internal_vint(const uint8_t *buf, size_t len, size_t *pos, uint64_t *val)
Decode one RAR5 vint, advancing pos past its bytes.
Definition ra8_rar.c:226
static uint16_t internal_copy_name(const ra8_rar_t *rar, uint64_t name_abs, const uint8_t *scratch, size_t n, size_t in_pos, uint64_t name_len, char *name_buf, uint16_t name_cap)
Copy a member name into the caller buffer, from scratch or a direct read.
Definition ra8_rar.c:279
static bool internal_rar4_file(const ra8_rar_t *rar, uint64_t off, const uint8_t *scratch, size_t n, uint16_t flags, uint16_t hsize, char *nbuf, uint16_t ncap, ra8_rar_entry_t *out)
Decode the RAR4 file-specific fields and fill out.
Definition ra8_rar.c:329
static bool internal_rar5_file_vints(const uint8_t *scratch, size_t n, size_t *pos, uint64_t *fflags, uint64_t *unp, uint64_t *cinfo, uint64_t *namesz)
Decode the RAR5 file-header vint stream, advancing pos past it.
Definition ra8_rar.c:452
static ra8_err_t internal_rar5_block(const ra8_rar_t *rar, uint64_t off, char *nbuf, uint16_t ncap, ra8_rar_entry_t *out)
Walk one RAR5 block at off.
Definition ra8_rar.c:572
ra8_err_t ra8_rar_extract(const ra8_rar_t *rar, const ra8_rar_entry_t *ent, uint8_t *buf, size_t cap, ra8_rar5_state_t *st, size_t *got)
Extract any file member – STORE by copy, RAR5-compressed by decode.
Definition ra8_rar.c:840
static ra8_err_t internal_rar4_block(const ra8_rar_t *rar, uint64_t off, char *nbuf, uint16_t ncap, ra8_rar_entry_t *out)
Walk one RAR4 block at off.
Definition ra8_rar.c:390
static void internal_rar_match_signature(const uint8_t *hdr, size_t got, ra8_rar_t *rar)
Identify the RAR generation from the leading signature bytes.
Definition ra8_rar.c:640
ra8_err_t ra8_rar_extract_stored(const ra8_rar_t *rar, const ra8_rar_entry_t *ent, uint8_t *buf, size_t cap, size_t *got)
Extract a STORE-method member's data into the caller buffer.
Definition ra8_rar.c:785
rar5_bits_t
RAR5 header/file flag bits, method field placement, and type.
Definition ra8_rar.c:135
@ k_rar5_fflag_mtime
4-byte mtime field present.
Definition ra8_rar.c:140
@ k_rar5_hflag_extra
Extra-area-size vint present.
Definition ra8_rar.c:137
@ k_rar5_type_file
File-header block type.
Definition ra8_rar.c:136
@ k_rar5_fflag_dir
Member is a directory.
Definition ra8_rar.c:139
@ k_rar5_fflag_crc
4-byte data-CRC field present.
Definition ra8_rar.c:141
@ k_rar5_fixed_field
Fixed mtime / CRC field width, bytes.
Definition ra8_rar.c:144
@ k_rar5_method_mask
3-bit method mask after the shift.
Definition ra8_rar.c:143
@ k_rar5_hflag_data
Data-size vint present.
Definition ra8_rar.c:138
@ k_rar5_method_shift
Method occupies comp-info bits 7..9.
Definition ra8_rar.c:142
static bool internal_rar_read_exact(const ra8_rar_t *rar, uint64_t data_off, uint64_t need, uint8_t *buf)
Stream exactly need bytes of a STORE member into buf.
Definition ra8_rar.c:771
rar_vint_bits_t
Bit layout of one RAR5 variable-length integer byte.
Definition ra8_rar.c:87
@ k_rar_vint_cont
Continuation flag within one vint byte.
Definition ra8_rar.c:89
@ k_rar_vint_data
Data bits mask within one vint byte.
Definition ra8_rar.c:88
@ k_rar_vint_bits
Data bits contributed per vint byte.
Definition ra8_rar.c:90
static void internal_copy_object(void *dst, const void *src, size_t len)
Copy an object representation through compatible byte-pointer types.
Definition ra8_rar.c:55
static uint16_t internal_le16(const uint8_t *p)
Decode a little-endian uint16 from two unaligned bytes.
Definition ra8_rar.c:173
Clean-room, read-only RAR archive walker (RAR4 + RAR5 headers, STORE data).
@ k_ra8_rar_vint_max
Max bytes in one RAR5 vint (64-bit value).
Definition ra8_rar.h:127
@ k_ra8_rar_sig5_len
"Rar!\x1A\x07\x01\x00" signature length (RAR5).
Definition ra8_rar.h:125
@ k_ra8_rar_sig4_len
"Rar!\x1A\x07\x00" marker length (RAR4).
Definition ra8_rar.h:124
@ k_ra8_rar_hdr_scratch
Per-block header read window (fixed fields).
Definition ra8_rar.h:126
size_t(* ra8_rar_read_fn)(void *ctx, uint64_t offset, void *buf, size_t len)
Seek+read backing over the RAR container bytes.
Definition ra8_rar.h:88
@ k_ra8_rar_ver_none
Not a recognised RAR archive.
Definition ra8_rar.h:98
@ k_ra8_rar_ver_4
RAR 1.5-4.x block format ("RAR4").
Definition ra8_rar.h:99
@ k_ra8_rar_ver_5
RAR 5.0 block format ("RAR5").
Definition ra8_rar.h:100
@ k_ra8_rar_method_compressed
Packed with a RAR compressor (not decoded).
Definition ra8_rar.h:113
@ k_ra8_rar_method_store
Uncompressed: data area is the file bytes.
Definition ra8_rar.h:112
Caller-owned zero-heap scratch for one ra8_rar5_decompress call.
One decoded RAR block: a file member, a directory, or a skipped block.
Definition ra8_rar.h:169
uint8_t method
ra8_rar_method_t (normalised; 0 = store).
Definition ra8_rar.h:175
uint8_t is_file
1 if this block is a file member header.
Definition ra8_rar.h:176
uint64_t unp_size
Unpacked length, bytes.
Definition ra8_rar.h:172
uint64_t data_off
Absolute offset of the member's data area.
Definition ra8_rar.h:170
uint64_t next_off
Absolute offset of the next block header.
Definition ra8_rar.h:173
uint16_t name_len
Name bytes copied into the caller buffer (clamped).
Definition ra8_rar.h:174
uint8_t is_dir
1 if the file member is a directory entry.
Definition ra8_rar.h:177
uint64_t pack_size
Packed (stored/compressed) data length, bytes.
Definition ra8_rar.h:171
One open RAR archive: the backing plus the detected generation.
Definition ra8_rar.h:144
uint64_t size
Container length in bytes.
Definition ra8_rar.h:147
uint64_t first_off
Offset of the first block past the signature.
Definition ra8_rar.h:148
void * ctx
Context for read.
Definition ra8_rar.h:146
ra8_rar_version_t version
Detected container generation.
Definition ra8_rar.h:149
ra8_rar_read_fn read
Byte reader over the container file.
Definition ra8_rar.h:145