implement unwrap command to retrieve binary files from containers
This commit is contained in:
168
src/unwrap.c
Normal file
168
src/unwrap.c
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
#include "commands.h"
|
||||||
|
#include "misc.h"
|
||||||
|
#include "read.h"
|
||||||
|
|
||||||
|
#include <blue/cmd.h>
|
||||||
|
#include <blue/term.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
enum {
|
||||||
|
ARG_CONTAINER,
|
||||||
|
OPT_TAG,
|
||||||
|
OPT_TAG_IDENT,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int unwrap(
|
||||||
|
const b_command *self,
|
||||||
|
const b_arglist *opt,
|
||||||
|
const b_array *args)
|
||||||
|
{
|
||||||
|
const char *in_path = NULL;
|
||||||
|
b_arglist_get_string(
|
||||||
|
opt,
|
||||||
|
B_COMMAND_INVALID_ID,
|
||||||
|
ARG_CONTAINER,
|
||||||
|
0,
|
||||||
|
&in_path);
|
||||||
|
|
||||||
|
FILE *inp = fopen(in_path, "rb");
|
||||||
|
if (!inp) {
|
||||||
|
b_err("cannot open '%s'", in_path);
|
||||||
|
b_i("reason: %s", strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ec3_reader *reader = NULL;
|
||||||
|
enum ec3_status status = ec3_reader_create(inp, &reader);
|
||||||
|
|
||||||
|
if (status != EC3_SUCCESS) {
|
||||||
|
fclose(inp);
|
||||||
|
|
||||||
|
b_err("cannot open '%s'", in_path);
|
||||||
|
b_i("reason: corrupted/unknown file format");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct ec3_container_info *c_info
|
||||||
|
= ec3_reader_get_container_info(reader);
|
||||||
|
if (c_info->c_nr_tags == 0) {
|
||||||
|
ec3_reader_finish(reader);
|
||||||
|
fclose(inp);
|
||||||
|
|
||||||
|
b_i("container '%s' has no tags", in_path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t target_tag_ident = 0;
|
||||||
|
const char *target_tag_ident_str = NULL;
|
||||||
|
b_arglist_get_string(
|
||||||
|
opt,
|
||||||
|
OPT_TAG,
|
||||||
|
OPT_TAG_IDENT,
|
||||||
|
0,
|
||||||
|
&target_tag_ident_str);
|
||||||
|
|
||||||
|
if (target_tag_ident_str) {
|
||||||
|
ec3_identifier_from_string(
|
||||||
|
target_tag_ident_str,
|
||||||
|
&target_tag_ident);
|
||||||
|
} else {
|
||||||
|
const struct ec3_tag_info *tags = ec3_reader_get_tags(reader);
|
||||||
|
target_tag_ident = tags[0].tag_ident;
|
||||||
|
}
|
||||||
|
|
||||||
|
char ident_str[32];
|
||||||
|
ec3_identifier_to_string(target_tag_ident, ident_str, sizeof ident_str);
|
||||||
|
|
||||||
|
struct ec3_tag_reader *tag_reader = NULL;
|
||||||
|
status = ec3_reader_open_tag(reader, target_tag_ident, &tag_reader);
|
||||||
|
if (status != EC3_SUCCESS) {
|
||||||
|
b_i("container '%s' has no %s tag", in_path, ident_str);
|
||||||
|
|
||||||
|
ec3_reader_finish(reader);
|
||||||
|
fclose(inp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct ec3_tag_info *target_tag_info
|
||||||
|
= ec3_reader_get_tag_info(reader, target_tag_ident);
|
||||||
|
size_t tag_length = target_tag_info->tag_total_length;
|
||||||
|
|
||||||
|
printf("reading %zu bytes from tag %s...\n", tag_length, ident_str);
|
||||||
|
|
||||||
|
char *buf = malloc(c_info->c_cluster_size);
|
||||||
|
|
||||||
|
int ret = 0;
|
||||||
|
FILE *outp = fopen("data.bin", "wb");
|
||||||
|
for (size_t i = 0;; i++) {
|
||||||
|
size_t nr_read = 0;
|
||||||
|
enum ec3_status status
|
||||||
|
= ec3_tag_reader_read(tag_reader, i, 1, buf, &nr_read);
|
||||||
|
|
||||||
|
if (status != EC3_SUCCESS) {
|
||||||
|
b_err("I/O failure while reading from container",
|
||||||
|
in_path);
|
||||||
|
ret = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("read %zu bytes from cluster %zu\n", nr_read, i);
|
||||||
|
fwrite(buf, 1, nr_read, outp);
|
||||||
|
|
||||||
|
if (nr_read < c_info->c_cluster_size) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(buf);
|
||||||
|
|
||||||
|
fclose(inp);
|
||||||
|
fclose(outp);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
B_COMMAND(CMD_UNWRAP, CMD_ROOT)
|
||||||
|
{
|
||||||
|
B_COMMAND_NAME("unwrap");
|
||||||
|
B_COMMAND_SHORT_NAME('U');
|
||||||
|
B_COMMAND_DESC(
|
||||||
|
"retrieve a binary or executable blob from an ec3 "
|
||||||
|
"container.");
|
||||||
|
B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT);
|
||||||
|
B_COMMAND_FUNCTION(unwrap);
|
||||||
|
|
||||||
|
B_COMMAND_HELP_OPTION();
|
||||||
|
|
||||||
|
B_COMMAND_ARG(ARG_CONTAINER)
|
||||||
|
{
|
||||||
|
B_ARG_NAME("container");
|
||||||
|
B_ARG_DESC("the container to retrieve the blob from");
|
||||||
|
B_ARG_NR_VALUES(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
B_COMMAND_OPTION(OPT_TAG)
|
||||||
|
{
|
||||||
|
B_OPTION_SHORT_NAME('T');
|
||||||
|
B_OPTION_LONG_NAME("tag");
|
||||||
|
B_OPTION_DESC("the identifier of the blob tag to retrieve");
|
||||||
|
|
||||||
|
B_OPTION_ARG(OPT_TAG_IDENT)
|
||||||
|
{
|
||||||
|
B_ARG_NAME("identifier");
|
||||||
|
B_ARG_DESC("the identifier");
|
||||||
|
B_ARG_NR_VALUES(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
B_COMMAND_USAGE()
|
||||||
|
{
|
||||||
|
B_COMMAND_USAGE_ARG(ARG_CONTAINER);
|
||||||
|
}
|
||||||
|
|
||||||
|
B_COMMAND_USAGE()
|
||||||
|
{
|
||||||
|
B_COMMAND_USAGE_OPT(OPT_TAG);
|
||||||
|
B_COMMAND_USAGE_ARG(ARG_CONTAINER);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user