Files
ec3/src/wrap.c

384 lines
7.1 KiB
C
Raw Normal View History

2025-01-30 18:10:38 +00:00
#include "bin.h"
2024-11-02 11:17:36 +00:00
#include "commands.h"
2025-01-30 18:10:38 +00:00
#include "write.h"
2024-11-02 11:17:36 +00:00
#include <blue/cmd.h>
2025-01-30 18:10:38 +00:00
#include <blue/term.h>
#include <errno.h>
2024-11-02 11:17:36 +00:00
enum {
OPT_OUTPATH,
OPT_OUTPATH_PATH,
OPT_FILE,
OPT_FILE_PATH,
OPT_EXEC,
OPT_EXEC_PATH,
2024-11-02 11:17:36 +00:00
OPT_TAGGED_FILE,
OPT_TAGGED_FILE_TAG,
OPT_TAGGED_FILE_PATH,
OPT_TAGGED_EXEC,
OPT_TAGGED_EXEC_TAG,
OPT_TAGGED_EXEC_PATH,
OPT_IDENT,
OPT_IDENT_VAL,
2024-11-02 11:17:36 +00:00
};
static enum ec3_status add_file(
struct ec3_writer *writer,
unsigned long type,
uint64_t id,
const char *path)
{
FILE *inp = fopen(path, "rb");
if (!inp) {
b_err("cannot open '%s'", path);
b_i("reason: %s", strerror(errno));
return EC3_ERR_NO_ENTRY;
}
struct ec3_tag_writer *tag = NULL;
enum ec3_status status
= ec3_writer_create_tag(writer, 0, type, id, 0, &tag);
if (status != EC3_SUCCESS) {
b_err("cannot initialise EC3 tag writer");
return status;
}
char buf[4096];
while (1) {
size_t r = fread(buf, 1, sizeof buf, inp);
status = ec3_tag_writer_write(tag, buf, r);
if (r < sizeof buf) {
break;
}
}
ec3_tag_writer_finish(tag);
fclose(inp);
return EC3_SUCCESS;
}
2024-11-02 11:17:36 +00:00
static int wrap(
const b_command *self,
const b_arglist *opt,
const b_array *args)
{
const char *out_path = NULL;
2025-01-30 18:10:38 +00:00
b_arglist_get_string(opt, OPT_OUTPATH, OPT_OUTPATH_PATH, 0, &out_path);
FILE *outp = fopen(out_path, "wb");
if (!outp) {
b_err("cannot open '%s'", out_path);
b_i("reason: %s", strerror(errno));
return -1;
}
enum ec3_status status = EC3_SUCCESS;
uint64_t ident = 0;
const char *ident_str;
b_arglist_get_string(opt, OPT_IDENT, OPT_IDENT_VAL, 0, &ident_str);
if (ident_str) {
status = ec3_identifier_from_string(ident_str, &ident);
}
if (status != EC3_SUCCESS) {
b_err("'%s' is not a valid container identifier", ident_str);
return -1;
}
2025-01-30 18:10:38 +00:00
struct ec3_writer *writer = NULL;
struct ec3_parameters param = {
.p_outp = outp,
.p_cluster_size = EC3_CLUSTER_16K,
.p_compression_func = EC3_COMPRESSION_ZSTD,
.p_ident = ident,
2025-01-30 18:10:38 +00:00
};
status = ec3_writer_create(&param, &writer);
2025-01-30 18:10:38 +00:00
if (status != EC3_SUCCESS) {
b_err("cannot initialise EC3 writer");
return -1;
}
uint64_t next_auto_id = 0;
2025-01-30 18:10:38 +00:00
b_arglist_iterator it = {0};
b_arglist_foreach_filtered(&it, opt, OPT_FILE, OPT_FILE_PATH)
{
printf("%s\n", it.value->val_str);
#if 1
status = add_file(
writer,
EC3_TAG_BLOB,
next_auto_id,
it.value->val_str);
next_auto_id++;
if (status != EC3_SUCCESS) {
b_err("an error occurred while writing to the "
"container");
return -1;
}
#endif
2025-01-30 18:10:38 +00:00
}
b_arglist_foreach_filtered(&it, opt, OPT_EXEC, OPT_EXEC_PATH)
{
printf("%s\n", it.value->val_str);
#if 1
status = add_file(
writer,
EC3_TAG_EXEC,
next_auto_id,
it.value->val_str);
next_auto_id++;
2025-01-30 18:10:38 +00:00
if (status != EC3_SUCCESS) {
b_err("an error occurred while writing to the "
"container");
return -1;
}
#endif
}
2025-01-30 18:10:38 +00:00
for (size_t i = 0;; i++) {
b_arglist_option *option = NULL;
b_status err = b_arglist_get_option(
opt,
OPT_TAGGED_FILE,
i,
&option);
if (!option) {
break;
}
b_arglist_value *tag = NULL, *path = NULL;
err = b_arglist_option_get_value(
option,
OPT_TAGGED_FILE_TAG,
0,
&tag);
err = b_arglist_option_get_value(
option,
OPT_TAGGED_FILE_PATH,
0,
&path);
printf("%s:%s\n", tag->val_str, path->val_str);
#if 1
uint64_t id = 0;
status = ec3_identifier_from_string(tag->val_str, &id);
if (status != EC3_SUCCESS) {
b_err("'%s' is not a valid tag identifier", id);
return -1;
}
status = add_file(writer, EC3_TAG_BLOB, id, path->val_str);
if (status != EC3_SUCCESS) {
b_err("an error occurred while writing to the "
"container");
return -1;
}
#endif
}
for (size_t i = 0;; i++) {
b_arglist_option *option = NULL;
b_status err = b_arglist_get_option(
opt,
OPT_TAGGED_EXEC,
i,
&option);
if (!option) {
2025-01-30 18:10:38 +00:00
break;
}
b_arglist_value *tag = NULL, *path = NULL;
err = b_arglist_option_get_value(
option,
OPT_TAGGED_EXEC_TAG,
0,
&tag);
err = b_arglist_option_get_value(
option,
OPT_TAGGED_EXEC_PATH,
0,
&path);
printf("%s:%s\n", tag->val_str, path->val_str);
#if 1
uint64_t id = 0;
status = ec3_identifier_from_string(tag->val_str, &id);
if (status != EC3_SUCCESS) {
b_err("'%s' is not a valid tag identifier", id);
return -1;
}
status = add_file(writer, EC3_TAG_EXEC, id, path->val_str);
if (status != EC3_SUCCESS) {
b_err("an error occurred while writing to the "
"container");
return -1;
}
#endif
2025-01-30 18:10:38 +00:00
}
ec3_writer_finish(writer);
fclose(outp);
2024-11-02 11:17:36 +00:00
return 0;
}
B_COMMAND(CMD_WRAP, CMD_ROOT)
{
B_COMMAND_NAME("wrap");
B_COMMAND_SHORT_NAME('W');
B_COMMAND_DESC(
"wrap one or more files into an ec3 container. each "
"file will "
2025-01-30 18:10:38 +00:00
"be stored in a separate blob tag within the created "
"container.");
2024-11-02 11:17:36 +00:00
B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT);
B_COMMAND_FUNCTION(wrap);
B_COMMAND_HELP_OPTION();
B_COMMAND_OPTION(OPT_OUTPATH)
{
B_OPTION_SHORT_NAME('o');
B_OPTION_LONG_NAME("out");
B_OPTION_DESC("the path to save the new file to");
B_OPTION_ARG(OPT_OUTPATH_PATH)
{
B_ARG_NAME("path");
B_ARG_NR_VALUES(1);
}
}
B_COMMAND_OPTION(OPT_IDENT)
2024-11-02 11:17:36 +00:00
{
B_OPTION_SHORT_NAME('I');
B_OPTION_LONG_NAME("ident");
B_OPTION_DESC(
"the string or number to use as the container "
"identifier");
2024-11-02 11:17:36 +00:00
B_OPTION_ARG(OPT_IDENT_VAL)
{
B_ARG_NAME("value");
B_ARG_NR_VALUES(1);
}
}
B_COMMAND_OPTION(OPT_FILE)
{
B_OPTION_SHORT_NAME('f');
B_OPTION_LONG_NAME("file");
B_OPTION_DESC("a file to add to the container.");
B_OPTION_ARG(OPT_FILE_PATH)
{
B_ARG_NAME("path");
B_ARG_NR_VALUES(1);
}
2024-11-02 11:17:36 +00:00
}
B_COMMAND_OPTION(OPT_TAGGED_FILE)
{
B_OPTION_SHORT_NAME('F');
2024-11-02 11:17:36 +00:00
B_OPTION_LONG_NAME("tagged-file");
B_OPTION_DESC(
"a file to add to the container, with an "
"associated "
2024-11-02 11:17:36 +00:00
"tag. "
"the tag must be either: (a) a 64-bit "
"hexadecimal "
2024-11-02 11:17:36 +00:00
"number; "
"or (b) a string of no more than 8 "
"characters.");
2024-11-02 11:17:36 +00:00
B_OPTION_ARG(OPT_TAGGED_FILE_TAG)
{
B_ARG_NAME("tag");
B_ARG_DESC("the tag!");
B_ARG_NR_VALUES(1);
}
B_OPTION_ARG(OPT_TAGGED_FILE_PATH)
{
B_ARG_NAME("path");
B_ARG_NR_VALUES(1);
}
}
B_COMMAND_OPTION(OPT_EXEC)
{
B_OPTION_SHORT_NAME('e');
B_OPTION_LONG_NAME("executable");
B_OPTION_DESC("an executable file to add to the container.");
B_OPTION_ARG(OPT_EXEC_PATH)
{
B_ARG_NAME("path");
B_ARG_NR_VALUES(1);
}
}
B_COMMAND_OPTION(OPT_TAGGED_EXEC)
{
B_OPTION_SHORT_NAME('E');
B_OPTION_LONG_NAME("tagged-executable");
B_OPTION_DESC(
"an executable file to add to the container, with an "
"associated "
"tag. "
"the tag must be either: (a) a 64-bit "
"hexadecimal "
"number; "
"or (b) a string of no more than 8 "
"characters.");
B_OPTION_ARG(OPT_TAGGED_EXEC_TAG)
{
B_ARG_NAME("tag");
B_ARG_DESC("the tag!");
B_ARG_NR_VALUES(1);
}
B_OPTION_ARG(OPT_TAGGED_EXEC_PATH)
{
B_ARG_NAME("path");
B_ARG_NR_VALUES(1);
}
}
2024-11-02 11:17:36 +00:00
B_COMMAND_USAGE()
{
B_COMMAND_USAGE_OPT(OPT_OUTPATH);
B_COMMAND_USAGE_OPT(OPT_FILE);
2024-11-02 11:17:36 +00:00
}
B_COMMAND_USAGE()
{
B_COMMAND_USAGE_OPT(OPT_OUTPATH);
B_COMMAND_USAGE_OPT(OPT_TAGGED_FILE);
}
}