#include "bin.h" #include "commands.h" #include "image.h" #include #include #include #include #include enum { OPT_OUTPATH, OPT_OUTPATH_PATH, OPT_FILE, OPT_FILE_PATH, OPT_EXEC, OPT_EXEC_PATH, 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, }; static enum ec3_status add_file( struct ec3_image_ioctx *image, 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_ioctx *tag = NULL; enum ec3_status status = ec3_image_ioctx_create_tag( image, type, id, EC3_TAG_IO_WRITE | EC3_TAG_IO_SEQUENTIAL, &tag); if (status != EC3_SUCCESS) { b_err("cannot initialise EC3 tag writer"); b_i("reason: %s", ec3_status_to_string(status)); return status; } 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; while (1) { size_t r = fread(buf, 1, cluster_size, inp); size_t w; status = ec3_tag_ioctx_write_cluster(tag, i++, buf, r, &w); if (r < cluster_size) { break; } } free(buf); ec3_tag_ioctx_close(tag); fclose(inp); return EC3_SUCCESS; } static int wrap( const b_command *self, const b_arglist *opt, const b_array *args) { const char *out_path = NULL; b_arglist_get_string(opt, OPT_OUTPATH, OPT_OUTPATH_PATH, 0, &out_path); 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; } 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; struct ec3_parameters param = { .p_cluster_size = EC3_CLUSTER_16K, .p_compression_func = EC3_COMPRESSION_ZSTD, .p_ident = ident, }; status = ec3_image_ioctx_open( out_path, ¶m, EC3_IMAGE_IO_WRITE, &image); if (status != EC3_SUCCESS) { b_err("cannot initialise EC3 writer"); return -1; } uint64_t next_auto_id = 0; 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( image, 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 } b_arglist_foreach_filtered(&it, opt, OPT_EXEC, OPT_EXEC_PATH) { printf("%s\n", it.value->val_str); #if 1 status = add_file( image, EC3_TAG_EXEC, 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 } 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(image, 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) { 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(image, EC3_TAG_EXEC, id, path->val_str); if (status != EC3_SUCCESS) { b_err("an error occurred while writing to the " "container"); return -1; } #endif } ec3_image_ioctx_close(image); 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 " "be stored in a separate blob tag within the created " "container."); 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) { B_OPTION_SHORT_NAME('I'); B_OPTION_LONG_NAME("ident"); B_OPTION_DESC( "the string or number to use as the container " "identifier"); 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); } } B_COMMAND_OPTION(OPT_TAGGED_FILE) { B_OPTION_SHORT_NAME('F'); B_OPTION_LONG_NAME("tagged-file"); B_OPTION_DESC( "a 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_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); } } B_COMMAND_USAGE() { B_COMMAND_USAGE_OPT(OPT_OUTPATH); B_COMMAND_USAGE_OPT(OPT_FILE); } B_COMMAND_USAGE() { B_COMMAND_USAGE_OPT(OPT_OUTPATH); B_COMMAND_USAGE_OPT(OPT_TAGGED_FILE); } }