#include #include #include #include #include #include #include #include enum { OPTION_HELP = 'h', OPTION_IMAGE = 'i', OPTION_OUTPUT = 'o', }; struct args { const char *image, *output; }; static struct opt_desc opt_descs[] = { { "-i", "--image=PATH", "the image in ROTS format to unpack" }, { "-o", "--output=PATH", "the file to contain the payload" }, { "-h", "--help", "display this help and exit" }, { NULL, NULL, NULL }, }; static int parse_args(struct args *args, int argc, char *argv[]) { struct option options[] = { { "help", no_argument, NULL, OPTION_HELP }, { "image", required_argument, NULL, OPTION_IMAGE }, { "output", required_argument, NULL, OPTION_OUTPUT }, { NULL, 0, 0, 0 }, }; int ret; while ((ret = getopt_long(argc, (char * const *)argv, "hi:o:", options, NULL)) >= 0) { switch (ret) { case OPTION_HELP: return -1; case OPTION_IMAGE: args->image = optarg; break; case OPTION_OUTPUT: args->output = optarg; break; default: return -1; } } if (!args->image || !args->output) return -1; return 0; } void show_unpack_usage(const char *prog_name, const char *cmd) { fprintf(stderr, "usage: %s %s [option]...\n\n" "unpack the payload of an image\n\n", prog_name, cmd); format_options(opt_descs); } int do_unpack(int argc, char *argv[]) { char data[512]; struct rots_hdr hdr; FILE *in, *out; struct args args; size_t nbytes, size; memset(&args, 0, sizeof args); if (parse_args(&args, argc, argv) < 0) { show_unpack_usage(argv[0], argv[1]); return -1; } if (!(in = fopen(args.image, "rb"))) { fprintf(stderr, "error: file '%s' not found.\n", args.image); return -1; } if (!(out = fopen(args.output, "wb"))) { fprintf(stderr, "error: cannot open '%s' for writing.\n", args.output); goto err_close_in; } if (rots_read_hdr(in, &hdr) < 0) { fprintf(stderr, "error: file '%s' is not a ROTS-image.\n", args.image); goto err_close_out; } size = hdr.size; while (size) { nbytes = fread(data, sizeof *data, min(size, sizeof data), in); if (nbytes == 0) { fprintf(stderr, "error: cannot read the next chunk.\n"); goto err_close_out; } if (fwrite(data, sizeof *data, nbytes, out) < nbytes) { fprintf(stderr, "error: cannot write the current chunk.\n"); goto err_close_out; } size -= nbytes; } fclose(out); fclose(in); return 0; err_close_out: fclose(out); err_close_in: fclose(in); return -1; }