#include #include #include #include #include #include enum { OPTION_HELP = 'h', OPTION_OUTPUT = 'o', }; struct args { const char *input, *output; }; static int parse_args(struct args *args, int argc, char *argv[]) { struct option options[] = { { "help", no_argument, NULL, OPTION_HELP }, { "output", required_argument, 0, OPTION_OUTPUT }, { NULL, 0, 0, 0 }, }; int ret; while ((ret = getopt_long(argc, (char * const *)argv, "ho:", options, NULL)) >= 0) { switch (ret) { case OPTION_HELP: return -1; case OPTION_OUTPUT: args->output = optarg; break; default: break; } } if (optind >= argc) return -1; ++optind; if (optind >= argc) return -1; args->input = argv[optind]; return 0; } int do_pack(int argc, char *argv[]) { char data[4096]; struct rots_hdr hdr; struct args args; FILE *input, *output; size_t nbytes, size; if (parse_args(&args, argc, argv) < 0) { fprintf(stderr, "invalid\n"); return -1; } if (!(input = fopen(args.input, "rb"))) { fprintf(stderr, "unable to open '%s' for reading.\n", args.input); return -1; } if (!(output = fopen(args.output, "wb"))) { fprintf(stderr, "unable to open '%s' for writing.\n", args.output); goto err_close_input; } get_file_size(&size, args.input); hdr.timestamp = (uint64_t)time(NULL); hdr.size = size; if (rots_write_hdr(output, &hdr) < 0) goto err_close_output; while (size) { nbytes = fread(data, sizeof *data, sizeof data, input); if (nbytes == 0) { fprintf(stderr, "unable to read the next chunk\n"); goto err_close_output; } if (fwrite(data, sizeof *data, nbytes, output) < nbytes) { fprintf(stderr, "unable to write the current chunk\n"); goto err_close_output; } size -= nbytes; } fclose(output); fclose(input); return 0; err_close_output: fclose(output); err_close_input: fclose(input); return -1; }