ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
main.c
Go to the documentation of this file.
1
28#include <errno.h>
29#include <fcntl.h>
30#include <limits.h>
31#include <signal.h>
32#include <stdint.h>
33#include <stdlib.h>
34#include <string.h>
35#include <sys/stat.h>
36#include <unistd.h>
37
38#include "fw_if_fs_posix.h"
39#include "mdl_app.h"
40#include "mdl_cli_internal.h"
43#include "mdl_sanitize.h"
44#include "mdl_stream_internal.h"
45#include "ra8_attributes.h"
46#include "ra8_io_stream_posix.h"
47
49typedef struct {
50 alignas(max_align_t) uint8_t bytes[k_export_arena_bytes];
52
54typedef struct {
55 alignas(max_align_t) uint8_t bytes[k_storage_work_bytes];
57
59typedef struct {
60 alignas(max_align_t) uint8_t bytes[k_mdl_storage_io_bytes];
62
64typedef enum : size_t {
66 k_ca_pem_input_capacity = 512U * 1024U,
68
73static fw_fs_posix_state_t s_fs_posix = {.root_fd = -1};
83static char s_config_path[PATH_MAX];
85static char s_library_path[PATH_MAX];
87static char s_cache_path[PATH_MAX];
89static char s_mode_path[PATH_MAX];
103
122{
123 struct sigaction action = {.sa_handler = SIG_IGN};
124 if ((sigemptyset(&action.sa_mask) != 0) || (sigaction(SIGPIPE, &action, nullptr) != 0)) {
126 }
128 if (err == k_ra8_ok) {
130 }
131 return err;
132}
133
150RA8_INTERNAL static ra8_err_t internal_diagnostic(const char* message)
151{
152 return ra8_io_stream_puts(&s_diagnostic, message);
153}
154
175internal_read_credential(int fd, const struct stat* before, uint8_t* destination, size_t length)
176{
177 size_t offset = 0U;
178 while (offset < length) {
179 ssize_t received = pread(fd, destination + offset, length - offset, (off_t)offset);
180 if ((received < 0) && (errno == EINTR)) {
181 continue;
182 }
183 if (received <= 0) {
185 }
186 offset += (size_t)received;
187 }
188 uint8_t extra = 0U;
189 ssize_t overflow = 0;
190 do {
191 overflow = pread(fd, &extra, 1U, (off_t)length);
192 } while ((overflow < 0) && (errno == EINTR));
193 struct stat after = {};
194 if ((overflow != 0) || (fstat(fd, &after) != 0) ||
197 }
198 return k_ra8_ok;
199}
200
224 uint8_t* destination,
225 size_t supplied,
226 size_t* required,
227 size_t* used)
228{
229 *required = 0U;
230 *used = 0U;
231 const int fd = open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK);
232 if (fd < 0) {
234 }
235 struct stat before = {};
236 ra8_err_t error = k_ra8_ok;
237 if ((fstat(fd, &before) != 0) || (before.st_size < 0)) {
239 } else if (!S_ISREG(before.st_mode)) {
240 error = k_ra8_err_invalid_arg;
241 } else if ((uintmax_t)before.st_size > (uintmax_t)SIZE_MAX) {
242 *required = SIZE_MAX;
244 } else {
245 *required = (size_t)before.st_size;
246 error = (*required > supplied) ? k_ra8_err_invalid_size
247 : internal_read_credential(fd, &before, destination, *required);
248 }
249 if ((close(fd) != 0) && (error == k_ra8_ok)) {
251 }
252 if (error == k_ra8_ok) {
253 *used = *required;
254 }
255 return error;
256}
257
278 const char* option,
279 size_t required,
280 size_t supplied)
281{
282 ra8_err_t error = priv_mdl_stream_text(k_ra8_ok, diagnostic, "mdl: ");
283 error = priv_mdl_stream_text(error, diagnostic, option);
284 error = priv_mdl_stream_text(error, diagnostic, " input exceeds credential capacity (required ");
285 error = priv_mdl_stream_u64(error, diagnostic, required);
286 error = priv_mdl_stream_text(error, diagnostic, ", supplied ");
287 error = priv_mdl_stream_u64(error, diagnostic, supplied);
288 return priv_mdl_stream_text(error, diagnostic, ")\n");
289}
290
310 mdl_net_policy_t* policy,
311 ra8_io_stream_t* diagnostic)
312{
313 mdl_net_bytes_t cookies = {};
314 size_t required = 0U;
315 size_t used = 0U;
316 policy->cookies = (mdl_net_bytes_t){};
317 policy->ca_pem = (mdl_net_bytes_t){};
318 if (args->cookie_file != nullptr) {
321 sizeof(s_cookie_input),
322 &required,
323 &used);
324 if (error == k_ra8_err_invalid_size) {
325 (void)internal_credential_capacity_error(diagnostic,
326 "--cookie-file",
327 required,
328 sizeof(s_cookie_input));
329 } else if (error != k_ra8_ok) {
330 (void)ra8_io_stream_puts(diagnostic, "mdl: could not load safe --cookie-file input\n");
331 }
332 if (error != k_ra8_ok) {
333 return error;
334 }
335 cookies = (used == 0U) ? (mdl_net_bytes_t){}
336 : (mdl_net_bytes_t){.data = s_cookie_input, .length = used};
337 }
338 if (args->ca_file == nullptr) {
339 policy->cookies = cookies;
340 return k_ra8_ok;
341 }
342 const ra8_err_t error = internal_load_credential(args->ca_file,
344 sizeof(s_ca_pem_input),
345 &required,
346 &used);
347 if (error == k_ra8_err_invalid_size) {
348 (void)
349 internal_credential_capacity_error(diagnostic, "--ca-file", required, sizeof(s_ca_pem_input));
350 } else if ((error != k_ra8_ok) || (used == 0U)) {
351 (void)ra8_io_stream_puts(diagnostic, "mdl: could not load safe nonempty --ca-file input\n");
352 }
353 if ((error != k_ra8_ok) || (used == 0U)) {
354 return (error == k_ra8_ok) ? k_ra8_err_invalid_arg : error;
355 }
356 policy->cookies = cookies;
357 policy->ca_pem = (mdl_net_bytes_t){.data = s_ca_pem_input, .length = used};
358 return k_ra8_ok;
359}
360
379RA8_INTERNAL static int internal_exit_from_error(ra8_err_t err, bool usage_error)
380{
381 if (err == k_ra8_ok) {
382 return 0;
383 }
384 return (usage_error && (err == k_ra8_err_invalid_arg)) ? 2 : 1;
385}
386
402{
403 const fw_fs_posix_cfg_t cfg = {.root_path = "/", .removable_media = false};
405 if (err != k_ra8_ok) {
406 return err;
407 }
408 err = mdl_storage_init(&s_app.storage,
409 &s_fs,
410 s_fs_file_work.bytes,
411 sizeof(s_fs_file_work.bytes),
413 sizeof(s_fs_transaction_work.bytes),
415 sizeof(s_fs_io_buffer));
416 if (err == k_ra8_ok) {
417 err = mdl_library_workspace_init(&s_app.library_workspace,
419 (uint32_t)sizeof(s_fs_directory_work.bytes));
420 }
421 if (err != k_ra8_ok) {
423 }
424 return err;
425}
426
445{
446 if (args->cfg == nullptr) {
447 return k_ra8_ok;
448 }
449 if (realpath(args->cfg, s_config_path) == nullptr) {
450 return k_ra8_err_not_found;
451 }
452 if (strlen(s_config_path) >= (size_t)k_fw_fs_path_cap) {
454 }
455 args->cfg = s_config_path;
456 return k_ra8_ok;
457}
458
478internal_resolve_one_leaf(const char* input, char* destination, size_t capacity)
479{
480 if (realpath(input, destination) != nullptr) {
481 if ((strlen(destination) >= capacity) || (strlen(destination) >= (size_t)k_fw_fs_path_cap)) {
483 }
484 return k_ra8_ok;
485 }
486 const char* slash = strrchr(input, '/');
487 const char* leaf = (slash == nullptr) ? input : slash + 1;
488 if ((leaf[0] == '\0') || (strcmp(leaf, ".") == 0) || (strcmp(leaf, "..") == 0)) {
490 }
491 char parent[PATH_MAX];
492 if (slash == nullptr) {
493 (void)memcpy(parent, ".", 2U);
494 } else if (slash == input) {
495 (void)memcpy(parent, "/", 2U);
496 } else {
497 const size_t parent_bytes = (size_t)(slash - input);
498 if (parent_bytes >= sizeof(parent)) {
500 }
501 memcpy(parent, input, parent_bytes);
502 parent[parent_bytes] = '\0';
503 }
504 char canonical_parent[PATH_MAX];
505 if (realpath(parent, canonical_parent) == nullptr) {
506 return k_ra8_err_not_found;
507 }
508 if (!mdl_path_join(canonical_parent, leaf, destination, capacity)) {
510 }
511 return k_ra8_ok;
512}
513
530{
531 const ra8_err_t error =
533 if (error != k_ra8_ok) {
534 return error;
535 }
536 args->out = s_library_path;
537 return k_ra8_ok;
538}
539
556{
557 ra8_err_t error = k_ra8_ok;
558 if (args->cache_dir == nullptr) {
559 if (!mdl_path_join(args->out, ".mdl_cache", s_cache_path, sizeof(s_cache_path))) {
561 }
562 } else {
564 }
565 if (error == k_ra8_ok) {
566 args->cache_dir = s_cache_path;
567 }
568 return error;
569}
570
588{
589 return (mode == k_mdl_cli_mode_series) || (mode == k_mdl_cli_mode_search) ||
590 (mode == k_mdl_cli_mode_browse) || (mode == k_mdl_cli_mode_list) ||
591 (mode == k_mdl_cli_mode_update_all) || (mode == k_mdl_cli_mode_remove) ||
592 (mode == k_mdl_cli_mode_artifact) || (mode == k_mdl_cli_mode_page);
593}
594
611{
612 return (mode == k_mdl_cli_mode_series) || (mode == k_mdl_cli_mode_search) ||
614}
615
634{
635 if (realpath(args->pack, s_mode_path) == nullptr) {
636 return k_ra8_err_not_found;
637 }
638 if (strlen(s_mode_path) >= (size_t)k_fw_fs_path_cap) {
640 }
641 args->pack = s_mode_path;
642 return k_ra8_ok;
643}
644
662{
663 const char* const saved_out = args->out;
664 if (args->verify_dir != nullptr) {
665 args->out = args->verify_dir;
666 }
667 const ra8_err_t error = internal_resolve_output_path(args);
668 if (args->verify_dir != nullptr) {
669 if (error == k_ra8_ok) {
670 args->verify_dir = args->out;
671 }
672 args->out = saved_out;
673 }
674 return error;
675}
676
697{
698 if (realpath(".", s_mode_path) == nullptr) {
699 return k_ra8_err_not_found;
700 }
701 if (strlen(s_mode_path) >= (size_t)k_fw_fs_path_cap) {
703 }
704 char sites[k_fw_fs_path_cap];
705 if (!mdl_path_join(s_mode_path, "sites", sites, sizeof(sites))) {
707 }
708 struct stat status = {};
709 if (lstat(sites, &status) == 0) {
710 if (S_ISDIR(status.st_mode) && !S_ISLNK(status.st_mode)) {
711 (void)memcpy(s_mode_path, sites, strlen(sites) + 1U);
712 }
713 } else if (errno != ENOENT) {
715 }
716 args->out = s_mode_path;
717 return k_ra8_ok;
718}
719
739RA8_INTERNAL static int
741{
742 if (args->out == nullptr) {
743 args->out = "downloads";
744 }
745 if (args->attr == nullptr) {
746 args->attr = "data-src";
747 }
749 (void)ra8_io_stream_puts(diagnostic, "mdl: could not resolve config path\n");
750 return 1;
751 }
752 ra8_err_t path_error = k_ra8_ok;
753 if (internal_uses_output_path(mode)) {
754 path_error = internal_resolve_output_path(args);
755 } else if (mode == k_mdl_cli_mode_verify) {
756 path_error = internal_resolve_verify_path(args);
757 } else if (mode == k_mdl_cli_mode_pack) {
758 path_error = internal_resolve_pack_path(args);
759 } else if (mode == k_mdl_cli_mode_init_site) {
760 path_error = internal_resolve_descriptor_path(args);
761 }
762 if (path_error != k_ra8_ok) {
763 (void)ra8_io_stream_puts(diagnostic, "mdl: could not resolve portable command path\n");
764 return 1;
765 }
767 (void)ra8_io_stream_puts(diagnostic, "mdl: could not resolve persistent cache path\n");
768 return 1;
769 }
770 if (args->ignore_robots) {
771 (void)ra8_io_stream_puts(diagnostic,
772 "mdl: WARNING: --ignore-robots set; "
773 "robots.txt will NOT be honoured\n");
774 }
775 return 0;
776}
777
797RA8_INTERNAL static int
799{
800 *format = mdl_format_from_str(args->format);
801 if (*format == k_mdl_format_invalid) {
802 const char* const parts[] = {"mdl: bad --format '",
803 args->format,
804 "' (loose|cbz|cbt|cbt.gz|epub|jof|rabook)\n"};
805 const ra8_err_t error =
806 priv_mdl_cli_reject_parts(&s_diagnostic, parts, sizeof(parts) / sizeof(parts[0]));
807 return internal_exit_from_error(error, true);
808 }
809 return (internal_prepare_credentials(args, &opts->policy, &s_diagnostic) == k_ra8_ok) ? 0 : 1;
810}
811
829RA8_INTERNAL static int internal_main_init(int argc, char** argv, mdl_args_t* a)
830{
832 return 1;
833 }
834 s_app.output = &s_output;
835 s_app.diagnostic = &s_diagnostic;
836 s_app.io_error = k_ra8_ok;
837 mdl_export_workspace_init(&s_app.export_ws, s_export_arena.bytes, sizeof(s_export_arena.bytes));
839 mdl_cli_parse(argc, argv, a);
840 return 0;
841}
842
864 mdl_cli_mode_t mode,
865 mdl_format_t format,
866 const mdl_run_opts_t* opts,
867 const mdl_nums_t* nums)
868{
869 const mdl_series_run_t run = priv_mdl_compose_build_run(a, format, opts, nums);
871 (void)internal_diagnostic("mdl: could not initialize portable filesystem binding\n");
872 return 1;
873 }
874 const int result = priv_mdl_compose_dispatch(a, mode, format, opts, nums, &run);
876 (void)internal_diagnostic("mdl: filesystem shutdown failed\n");
877 return 1;
878 }
879 return result;
880}
881
894int main(int argc, char** argv)
895{
896 mdl_args_t a = {};
897 if (internal_main_init(argc, argv, &a) != 0) {
898 return 1;
899 }
901 ra8_err_t cli_err = mdl_cli_validate(&a, &s_diagnostic, &mode);
902 if (cli_err != k_ra8_ok) {
903 if ((cli_err == k_ra8_err_invalid_arg) && (mdl_cli_usage(&s_diagnostic, argv[0]) != k_ra8_ok)) {
904 return 1;
905 }
906 return internal_exit_from_error(cli_err, true);
907 }
908 if (mode == k_mdl_cli_mode_help) {
909 return internal_exit_from_error(mdl_cli_usage(&s_diagnostic, argv[0]), false);
910 }
911 if (mode == k_mdl_cli_mode_version) {
912 return internal_exit_from_error(ra8_io_stream_puts(&s_output, "mdl 0.1.0\n"), false);
913 }
914 if (internal_prepare_args(&a, mode, &s_diagnostic) != 0) {
915 return 1;
916 }
917
918 mdl_nums_t nums = {};
919 cli_err = mdl_cli_parse_nums(&a, &s_diagnostic, &nums);
920 if (cli_err != k_ra8_ok) {
921 return internal_exit_from_error(cli_err, true);
922 }
924 /* The one place this build form's transport is chosen. */
927 const int policy_status = internal_prepare_run_policy(&a, &opts, &format);
928 if (policy_status != 0) {
929 return policy_status;
930 }
931
932 return internal_main_run(&a, mode, format, &opts, &nums);
933}
void main(void)
Secure fallback main entry point.
Definition main.c:37
static int internal_prepare_args(mdl_args_t *args, mdl_cli_mode_t mode, ra8_io_stream_t *diagnostic)
Apply host defaults and canonicalize paths for the selected mode.
Definition main.c:740
static export_arena_storage_t s_export_arena
Process-lifetime exporter workspace storage (zero heap).
Definition main.c:70
static char s_cache_path[PATH_MAX]
Canonical host cache root retained through one command run.
Definition main.c:87
static ra8_err_t internal_read_credential(int fd, const struct stat *before, uint8_t *destination, size_t length)
Read one already-open credential file and reject concurrent mutation.
Definition main.c:175
static fw_fs_posix_state_t s_fs_posix
Definition main.c:73
static char s_mode_path[PATH_MAX]
Canonical verify, pack, or descriptor path retained for one run.
Definition main.c:89
static ra8_io_stream_posix_state_t s_diagnostic_posix
Definition main.c:102
static ra8_err_t internal_resolve_pack_path(mdl_args_t *args)
Canonicalize the existing pack input directory.
Definition main.c:633
static ra8_err_t internal_storage_init(void)
Bind the host root through the POSIX composition adapter.
Definition main.c:401
static uint8_t s_ca_pem_input[k_ca_pem_input_capacity]
Process-lifetime, caller-owned custom CA PEM bytes.
Definition main.c:93
static ra8_err_t internal_resolve_verify_path(mdl_args_t *args)
Canonicalize a verify target while preserving absent-leaf diagnostics.
Definition main.c:661
credential_input_capacity_t
Explicit host credential input capacities.
Definition main.c:64
@ k_cookie_input_capacity
Maximum cookie-file bytes.
Definition main.c:65
@ k_ca_pem_input_capacity
Maximum custom CA bytes.
Definition main.c:66
static ra8_io_stream_t s_output
Process stdout and stderr exposed through the portable byte-stream facade.
Definition main.c:98
static bool internal_uses_output_path(mdl_cli_mode_t mode)
True when a validated mode consumes the canonical output root.
Definition main.c:587
static ra8_err_t internal_output_init(void)
Bind process output descriptors and surface broken pipes as errors.
Definition main.c:121
static ra8_err_t internal_resolve_config_path(mdl_args_t *args)
Resolve an optional host config argument into the root-bound namespace.
Definition main.c:444
static mdl_app_context_t s_app
Process-lifetime bounded application state.
Definition main.c:95
static char s_config_path[PATH_MAX]
Canonical host config path retained through one command run.
Definition main.c:83
static ra8_io_stream_posix_state_t s_output_posix
Borrowed raw-descriptor backend state for process output streams.
Definition main.c:101
static ra8_err_t internal_resolve_one_leaf(const char *input, char *destination, size_t capacity)
Resolve a library root, including one absent final directory.
Definition main.c:478
static fw_fs_t s_fs
Host-selected filesystem facade and adapter state.
Definition main.c:72
static ra8_err_t internal_prepare_credentials(const mdl_args_t *args, mdl_net_policy_t *policy, ra8_io_stream_t *diagnostic)
Snapshot optional host credential paths into portable byte policy.
Definition main.c:309
static int internal_main_init(int argc, char **argv, mdl_args_t *a)
Bootstrap process I/O and workspace state, then parse arguments.
Definition main.c:829
static directory_workspace_t s_fs_directory_work
One bounded host directory-cursor workspace.
Definition main.c:79
static ra8_err_t internal_resolve_cache_path(mdl_args_t *args)
Resolve or derive the persistent per-host cache root.
Definition main.c:555
static int internal_exit_from_error(ra8_err_t err, bool usage_error)
Convert one CLI or output status to the process exit convention.
Definition main.c:379
static ra8_err_t internal_resolve_descriptor_path(mdl_args_t *args)
Select the canonical init-site descriptor directory.
Definition main.c:696
static storage_workspace_t s_fs_file_work
One file and one transaction workspace for single-threaded storage.
Definition main.c:76
static ra8_err_t internal_credential_capacity_error(ra8_io_stream_t *diagnostic, const char *option, size_t required, size_t supplied)
Emit an exact required-versus-supplied credential capacity error.
Definition main.c:277
static uint8_t s_fs_io_buffer[k_mdl_storage_io_bytes]
Caller-owned streaming buffer shared by serial storage operations.
Definition main.c:81
static storage_workspace_t s_fs_transaction_work
Definition main.c:77
static ra8_io_stream_t s_diagnostic
Definition main.c:99
static char s_library_path[PATH_MAX]
Canonical host library root retained through one command run.
Definition main.c:85
static ra8_err_t internal_resolve_output_path(mdl_args_t *args)
Canonicalize the command output root with one absent leaf allowed.
Definition main.c:529
static ra8_err_t internal_diagnostic(const char *message)
Write one fixed process diagnostic through the injected sink.
Definition main.c:150
static ra8_err_t internal_load_credential(const char *path, uint8_t *destination, size_t supplied, size_t *required, size_t *used)
Load one path argument into exact caller-supplied credential storage.
Definition main.c:223
static int internal_main_run(const mdl_args_t *a, mdl_cli_mode_t mode, mdl_format_t format, const mdl_run_opts_t *opts, const mdl_nums_t *nums)
Build the series-run plan, then dispatch and shut down cleanly.
Definition main.c:863
static int internal_prepare_run_policy(const mdl_args_t *args, mdl_run_opts_t *opts, mdl_format_t *format)
Validate output format and attach bounded credential byte views.
Definition main.c:798
static uint8_t s_cookie_input[k_cookie_input_capacity]
Process-lifetime, caller-owned cookie input bytes.
Definition main.c:91
static bool internal_uses_cache_path(mdl_cli_mode_t mode)
Classify modes that perform persistent document caching.
Definition main.c:610
#define O_NOFOLLOW
Zero fallback paired with explicit no-follow metadata validation.
#define O_CLOEXEC
Zero fallback when the host lacks close-on-exec open flags.
Root-confined hosted POSIX adapter for fw_if_fs.
ra8_err_t fw_fs_posix_deinit(fw_fs_posix_state_t *state)
Close the root descriptor; no bound operation is valid afterward.
ra8_err_t fw_fs_posix_init(fw_fs_t *out, fw_fs_posix_state_t *state, const fw_fs_posix_cfg_t *cfg)
Open/configure a root-confined POSIX binding.
@ k_fw_fs_path_cap
Largest portable path including its NUL.
The downloader's portable application layer: one run mode, one call.
void mdl_app_bind(mdl_app_context_t *ctx)
Bind the caller-owned working set every application mode will use.
Definition mdl_app.c:28
@ k_storage_work_bytes
Per-handle FS backend state.
Definition mdl_app.h:57
@ k_export_arena_bytes
Host export scratch ceiling.
Definition mdl_app.h:56
ra8_err_t mdl_cli_validate(const mdl_args_t *a, ra8_io_stream_t *diagnostic, mdl_cli_mode_t *mode)
Validate mode selection, required arguments, and per-mode options.
Definition mdl_cli.c:832
ra8_err_t mdl_cli_parse_nums(const mdl_args_t *a, ra8_io_stream_t *diagnostic, mdl_nums_t *n)
Strictly parse and validate every numeric CLI field.
mdl_cli_mode_t
Exactly one command mode selected by a valid invocation.
Definition mdl_cli.h:31
@ k_mdl_cli_mode_verify
Verify tracked state/pages/containers.
Definition mdl_cli.h:39
@ k_mdl_cli_mode_series
Download or update one configured series.
Definition mdl_cli.h:33
@ k_mdl_cli_mode_artifact
Download one verified HTTPS artifact.
Definition mdl_cli.h:42
@ k_mdl_cli_mode_page
Debug-download images from one page URL.
Definition mdl_cli.h:43
@ k_mdl_cli_mode_invalid
No valid primary mode.
Definition mdl_cli.h:32
@ k_mdl_cli_mode_search
Search a descriptor and optionally pick.
Definition mdl_cli.h:34
@ k_mdl_cli_mode_pack
Package a local page-image directory.
Definition mdl_cli.h:41
@ k_mdl_cli_mode_update_all
Update every tracked local series.
Definition mdl_cli.h:37
@ k_mdl_cli_mode_help
Print command help without running a mode.
Definition mdl_cli.h:44
@ k_mdl_cli_mode_list
List tracked local series.
Definition mdl_cli.h:36
@ k_mdl_cli_mode_remove
Remove one tracked local series.
Definition mdl_cli.h:38
@ k_mdl_cli_mode_browse
Browse a descriptor and optionally pick.
Definition mdl_cli.h:35
@ k_mdl_cli_mode_version
Print the program version and exit.
Definition mdl_cli.h:45
@ k_mdl_cli_mode_init_site
Generate a starter descriptor template.
Definition mdl_cli.h:40
mdl_run_opts_t mdl_cli_run_opts(const mdl_args_t *a)
Fold parsed args into the cross-cutting run options.
Definition mdl_cli.c:862
void mdl_cli_parse(int argc, char **argv, mdl_args_t *a)
Parse argv into a; numeric fields stay as strings for main.
Definition mdl_cli.c:278
ra8_err_t mdl_cli_usage(ra8_io_stream_t *diagnostic, const char *a0)
Write the complete usage block to an injected byte stream.
Private byte-stream helpers shared by mdl CLI units.
ra8_err_t priv_mdl_cli_reject_parts(ra8_io_stream_t *stream, const char *const *parts, size_t count)
Write a rejection diagnostic and return invalid-argument status.
const mdl_net_provider_t * priv_mdl_compose_net_provider(void)
The libcurl transport factory this form injects into every run.
Definition mdl_compose.c:66
mdl_series_run_t priv_mdl_compose_build_run(const mdl_args_t *a, mdl_format_t format, const mdl_run_opts_t *opts, const mdl_nums_t *n)
Translate validated argv state into one portable series-run value.
Definition mdl_compose.c:71
int priv_mdl_compose_dispatch(const mdl_args_t *a, mdl_cli_mode_t mode, mdl_format_t format, const mdl_run_opts_t *opts, const mdl_nums_t *nums, const mdl_series_run_t *run)
Route the one validated mode to its portable application entry point.
Definition mdl_compose.c:91
What this FORM injects, and how one parsed invocation reaches a mode.
mdl_format_t mdl_format_from_str(const char *s)
Map a --format string to a container kind.
Definition mdl_export.c:32
void mdl_export_workspace_init(mdl_export_workspace_t *ws, void *data, size_t cap)
Bind an exporter arena without allocating memory.
mdl_format_t
Artifact format selected by a media-download composition root.
Definition mdl_format.h:35
@ k_mdl_format_invalid
Unrecognized or unsupported selection.
Definition mdl_format.h:45
bool priv_mdl_host_credential_stat_unchanged(const struct stat *before, const struct stat *after)
Compare identity, size, mode, and nanosecond mutation metadata.
Private host credential-snapshot hardening helpers.
ra8_err_t mdl_library_workspace_init(mdl_library_workspace_t *workspace, void *directory_workspace, uint32_t directory_workspace_bytes)
Bind caller-owned directory storage to a reusable library workspace.
Definition mdl_library.c:36
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_init(mdl_storage_t *storage, const fw_fs_t *fs, void *file_workspace, uint32_t file_workspace_bytes, void *transaction_workspace, uint32_t transaction_workspace_bytes, uint8_t *io_buffer, uint32_t io_buffer_bytes)
Validate and retain one filesystem plus caller-owned workspaces.
@ k_mdl_storage_io_bytes
One bounded read/write chunk.
Definition mdl_storage.h:28
ra8_err_t priv_mdl_stream_text(ra8_err_t prior, ra8_io_stream_t *stream, const char *text)
Append text unless an earlier operation already failed.
Definition mdl_stream.c:16
ra8_err_t priv_mdl_stream_u64(ra8_err_t prior, ra8_io_stream_t *stream, uint64_t value)
Append one unsigned integer unless an earlier append failed.
Definition mdl_stream.c:21
Private bounded text helpers over the portable byte-stream contract.
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.
Definition ra8_err.h:152
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
@ k_ra8_err_access_denied
Operation refused because the target is protected against it.
Definition ra8_err.h:276
@ k_ra8_err_not_found
Requested item not found (lookup / search missed).
Definition ra8_err.h:173
@ k_ra8_err_comm_error
Generic communication error (use a more specific code when possible).
Definition ra8_err.h:399
@ 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 strcmp(const char *s1, const char *s2)
Compare two null-terminated strings.
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.
char * strrchr(const char *s, int c)
Locate last occurrence of character in string.
ra8_err_t ra8_io_stream_puts(ra8_io_stream_t *s, const char *str)
Write a NUL-terminated string (without the NUL) to the bound sink.
Borrowed raw-descriptor backend for the portable byte-stream facade.
ra8_err_t ra8_io_stream_posix_init(ra8_io_stream_t *stream, ra8_io_stream_posix_state_t *state, int fd)
Bind a borrowed writable descriptor as a byte-stream sink.
Maximally aligned storage for one filesystem directory cursor.
Definition main.c:59
uint8_t bytes[k_mdl_storage_io_bytes]
Opaque cursor state.
Definition main.c:60
Naturally aligned, caller-owned exporter workspace storage.
Definition main.c:49
uint8_t bytes[k_export_arena_bytes]
Bounded scratch bytes.
Definition main.c:50
POSIX composition-root settings.
Caller-owned POSIX adapter state.
One complete composition-root filesystem binding.
The one bounded working set every application mode shares.
Definition mdl_app.h:162
Parsed command-line options in string form (converted by main).
Definition mdl_cli.h:57
const char * verify_dir
–verify [DIR]: directory to verify.
Definition mdl_cli.h:80
const char * pack
–pack DIR: package an existing folder, no network.
Definition mdl_cli.h:70
const char * cfg
–config path.
Definition mdl_cli.h:58
const char * ca_file
–ca-file FILE: host composition CA input path.
Definition mdl_cli.h:79
bool ignore_robots
–ignore-robots: escape hatch (off by default).
Definition mdl_cli.h:88
const char * out
–out dir.
Definition mdl_cli.h:61
const char * attr
–attr.
Definition mdl_cli.h:63
const char * cookie_file
–cookie-file FILE: host composition input path.
Definition mdl_cli.h:78
const char * cache_dir
–cache-dir: persistent per-host cache root.
Definition mdl_cli.h:62
const char * format
–format (cbz/cbt/cbt.gz/epub/jof/rabook).
Definition mdl_cli.h:69
Read-only caller-owned byte view retained by a network backend.
Definition mdl_net.h:60
Session-wide security policy for the network backend.
Definition mdl_net.h:81
mdl_net_bytes_t cookies
Newline-delimited input cookies.
Definition mdl_net.h:87
mdl_net_bytes_t ca_pem
Complete PEM CA bundle, or an empty view.
Definition mdl_net.h:88
The validated numeric CLI scalars, parsed once before any run mode.
Definition mdl_cli.h:162
Cross-cutting policy and injected transport threaded into every mode.
Definition mdl_app.h:73
mdl_net_policy_t policy
Backend security policy.
Definition mdl_app.h:74
const mdl_net_provider_t * net
Injected transport factory.
Definition mdl_app.h:75
Parameters of one series download, as values rather than arguments.
Definition mdl_app.h:114
Caller-owned state retained by one POSIX stream binding.
Caller-allocated byte-stream handle binding a sink to its context.
Maximally aligned storage for one filesystem backend handle.
Definition main.c:54
uint8_t bytes[k_storage_work_bytes]
Opaque backend state.
Definition main.c:55