2025-01-30 18:10:38 +00:00
|
|
|
#include "bin.h"
|
2024-11-02 11:17:36 +00:00
|
|
|
#include "commands.h"
|
2025-02-23 20:52:59 +00:00
|
|
|
#include "image.h"
|
2024-11-02 11:17:36 +00:00
|
|
|
|
|
|
|
|
#include <blue/cmd.h>
|
2025-02-23 20:52:59 +00:00
|
|
|
#include <blue/io/path.h>
|
2025-01-30 18:10:38 +00:00
|
|
|
#include <blue/term.h>
|
|
|
|
|
#include <errno.h>
|
2025-02-23 20:52:59 +00:00
|
|
|
#include <stdlib.h>
|
2024-11-02 11:17:36 +00:00
|
|
|
|
|
|
|
|
enum {
|
|
|
|
|
OPT_OUTPATH,
|
|
|
|
|
OPT_OUTPATH_PATH,
|
|
|
|
|
|
2025-02-04 12:58:22 +00:00
|
|
|
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,
|
2025-02-04 12:58:22 +00:00
|
|
|
|
|
|
|
|
OPT_TAGGED_EXEC,
|
|
|
|
|
OPT_TAGGED_EXEC_TAG,
|
|
|
|
|
OPT_TAGGED_EXEC_PATH,
|
|
|
|
|
|
|
|
|
|
OPT_IDENT,
|
|
|
|
|
OPT_IDENT_VAL,
|
2024-11-02 11:17:36 +00:00
|
|
|
};
|
|
|
|
|
|
2025-02-04 12:58:22 +00:00
|
|
|
static enum ec3_status add_file(
|
2025-02-23 20:52:59 +00:00
|
|
|
struct ec3_image_ioctx *image,
|
2025-02-04 12:58:22 +00:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-23 20:52:59 +00:00
|
|
|
struct ec3_tag_ioctx *tag = NULL;
|
|
|
|
|
enum ec3_status status = ec3_image_ioctx_create_tag(
|
|
|
|
|
image,
|
2025-02-16 08:46:22 +00:00
|
|
|
type,
|
|
|
|
|
id,
|
2025-02-23 20:52:59 +00:00
|
|
|
EC3_TAG_IO_WRITE | EC3_TAG_IO_SEQUENTIAL,
|
2025-02-16 08:46:22 +00:00
|
|
|
&tag);
|
2025-02-04 12:58:22 +00:00
|
|
|
|
|
|
|
|
if (status != EC3_SUCCESS) {
|
|
|
|
|
b_err("cannot initialise EC3 tag writer");
|
2025-02-23 20:52:59 +00:00
|
|
|
b_i("reason: %s", ec3_status_to_string(status));
|
2025-02-04 12:58:22 +00:00
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-23 20:52:59 +00:00
|
|
|
const struct ec3_image_info *image_info
|
|
|
|
|
= ec3_image_ioctx_get_info(image);
|
|
|
|
|
size_t cluster_size = image_info->img_cluster_size;
|
|
|
|
|
|
|
|
|
|
char *buf = malloc(cluster_size);
|
|
|
|
|
|
|
|
|
|
size_t i = 0;
|
2025-02-04 12:58:22 +00:00
|
|
|
|
|
|
|
|
while (1) {
|
2025-02-23 20:52:59 +00:00
|
|
|
size_t r = fread(buf, 1, cluster_size, inp);
|
|
|
|
|
size_t w;
|
|
|
|
|
status = ec3_tag_ioctx_write_cluster(tag, i++, buf, r, &w);
|
2025-02-04 12:58:22 +00:00
|
|
|
|
2025-02-23 20:52:59 +00:00
|
|
|
if (r < cluster_size) {
|
2025-02-04 12:58:22 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-23 20:52:59 +00:00
|
|
|
free(buf);
|
|
|
|
|
ec3_tag_ioctx_close(tag);
|
2025-02-04 12:58:22 +00:00
|
|
|
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)
|
|
|
|
|
{
|
2025-02-04 12:58:22 +00:00
|
|
|
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);
|
|
|
|
|
|
2025-02-04 12:58:22 +00:00
|
|
|
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-02-23 20:52:59 +00:00
|
|
|
b_path *image_path = b_path_create_from_cstr(out_path);
|
|
|
|
|
if (b_path_exists(image_path)) {
|
|
|
|
|
b_path_unlink(image_path);
|
|
|
|
|
}
|
|
|
|
|
b_path_release(image_path);
|
|
|
|
|
|
|
|
|
|
struct ec3_image_ioctx *image = NULL;
|
2025-01-30 18:10:38 +00:00
|
|
|
struct ec3_parameters param = {
|
|
|
|
|
.p_cluster_size = EC3_CLUSTER_16K,
|
|
|
|
|
.p_compression_func = EC3_COMPRESSION_ZSTD,
|
2025-02-04 12:58:22 +00:00
|
|
|
.p_ident = ident,
|
2025-01-30 18:10:38 +00:00
|
|
|
};
|
2025-02-23 20:52:59 +00:00
|
|
|
status = ec3_image_ioctx_open(
|
|
|
|
|
out_path,
|
|
|
|
|
¶m,
|
|
|
|
|
EC3_IMAGE_IO_WRITE,
|
|
|
|
|
&image);
|
2025-01-30 18:10:38 +00:00
|
|
|
|
|
|
|
|
if (status != EC3_SUCCESS) {
|
|
|
|
|
b_err("cannot initialise EC3 writer");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-04 12:58:22 +00:00
|
|
|
uint64_t next_auto_id = 0;
|
2025-01-30 18:10:38 +00:00
|
|
|
|
2025-02-04 12:58:22 +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(
|
2025-02-23 20:52:59 +00:00
|
|
|
image,
|
2025-02-04 12:58:22 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
|
|
2025-02-04 12:58:22 +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(
|
2025-02-23 20:52:59 +00:00
|
|
|
image,
|
2025-02-04 12:58:22 +00:00
|
|
|
EC3_TAG_EXEC,
|
|
|
|
|
next_auto_id,
|
|
|
|
|
it.value->val_str);
|
|
|
|
|
next_auto_id++;
|
2025-01-30 18:10:38 +00:00
|
|
|
|
2025-02-04 12:58:22 +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
|
|
|
|
2025-02-04 12:58:22 +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;
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-23 20:52:59 +00:00
|
|
|
status = add_file(image, EC3_TAG_BLOB, id, path->val_str);
|
2025-02-04 12:58:22 +00:00
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
2025-02-04 12:58:22 +00:00
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-23 20:52:59 +00:00
|
|
|
status = add_file(image, EC3_TAG_EXEC, id, path->val_str);
|
2025-02-04 12:58:22 +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
|
|
|
}
|
|
|
|
|
|
2025-02-23 20:52:59 +00:00
|
|
|
ec3_image_ioctx_close(image);
|
2025-01-30 18:10:38 +00:00
|
|
|
|
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(
|
2025-02-04 12:58:22 +00:00
|
|
|
"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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-04 12:58:22 +00:00
|
|
|
B_COMMAND_OPTION(OPT_IDENT)
|
2024-11-02 11:17:36 +00:00
|
|
|
{
|
2025-02-04 12:58:22 +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
|
|
|
|
2025-02-04 12:58:22 +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)
|
|
|
|
|
{
|
2025-02-04 12:58:22 +00:00
|
|
|
B_OPTION_SHORT_NAME('F');
|
2024-11-02 11:17:36 +00:00
|
|
|
B_OPTION_LONG_NAME("tagged-file");
|
|
|
|
|
B_OPTION_DESC(
|
2025-02-04 12:58:22 +00:00
|
|
|
"a file to add to the container, with an "
|
|
|
|
|
"associated "
|
2024-11-02 11:17:36 +00:00
|
|
|
"tag. "
|
2025-02-04 12:58:22 +00:00
|
|
|
"the tag must be either: (a) a 64-bit "
|
|
|
|
|
"hexadecimal "
|
2024-11-02 11:17:36 +00:00
|
|
|
"number; "
|
2025-02-04 12:58:22 +00:00
|
|
|
"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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-04 12:58:22 +00:00
|
|
|
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);
|
2025-02-04 12:58:22 +00:00
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|