#include "commands.h" #include #include #include #include enum { ARG_INPATH, OPT_OUTPATH, OPT_OUTPATH_PATH, }; static int create( const b_command *self, const b_arglist *opt, const b_array *args) { const char *in_path = NULL, *out_path = NULL; b_arglist_get_string(opt, B_COMMAND_INVALID_ID, ARG_INPATH, 0, &in_path); b_arglist_get_string(opt, OPT_OUTPATH, OPT_OUTPATH_PATH, 0, &out_path); printf("in path: %s\n", in_path); printf("out path: %s\n", out_path); size_t in_bufsz = ZSTD_CStreamInSize(); size_t out_bufsz = ZSTD_CStreamOutSize(); printf("in buffer: %zu\n", in_bufsz); printf("out buffer: %zu\n", out_bufsz); FILE *in = fopen(in_path, "rb"); if (!in) { return -1; } FILE *out = fopen(out_path, "wb"); if (!out) { return -1; } ZSTD_CCtx *zstd = ZSTD_createCCtx(); ZSTD_CCtx_setParameter(zstd, ZSTD_c_compressionLevel, 22); ZSTD_CCtx_setParameter(zstd, ZSTD_c_checksumFlag, 1); void *in_buf = malloc(in_bufsz); void *out_buf = malloc(out_bufsz); size_t total = 0; while (1) { size_t r = fread(in_buf, 1, in_bufsz, in); if (r == 0) { break; } if ((total % 0x1000000) == 0) { printf("read %zu MB bytes\n", total / 1000000); } total += r; bool last_chunk = r < in_bufsz; ZSTD_EndDirective mode = last_chunk ? ZSTD_e_end : ZSTD_e_continue; ZSTD_inBuffer input = { in_buf, r, 0 }; int finished; do { ZSTD_outBuffer output = { out_buf, out_bufsz, 0 }; size_t remaining = ZSTD_compressStream2(zstd, &output, &input, mode); fwrite(out_buf, 1, output.pos, out); finished = last_chunk ? (remaining == 0) : (input.pos == input.size); } while (!finished); if (last_chunk) { break; } } ZSTD_freeCCtx(zstd); fclose(out); fclose(in); free(in_buf); free(out_buf); return 0; } B_COMMAND(CMD_CREATE, CMD_ROOT) { B_COMMAND_NAME("create"); B_COMMAND_SHORT_NAME('C'); B_COMMAND_DESC("create an ec3 file"); B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT); B_COMMAND_FUNCTION(create); 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_ARG(ARG_INPATH) { B_ARG_NAME("input file"); B_ARG_NR_VALUES(1); } B_COMMAND_USAGE() { B_COMMAND_USAGE_ARG(ARG_INPATH); B_COMMAND_USAGE_OPT(OPT_OUTPATH); } }