#include #include #include #include #include #include int kf_exists(char *filename) { FILE *fp = fopen(filename, "r"); bool opened = fp != NULL; if (opened) fclose(fp); return opened; } u8 *kf_readbin(char *filename, size_t *plen) { FILE *fp = fopen(filename, "rb"); if (!fp) return NULL; *plen = 0; fseek(fp, 0, SEEK_END); *plen = ftell(fp); fseek(fp, 0, SEEK_SET); if (*plen == 0) { fclose(fp); return NULL; } u8 *data = malloc(*plen); (void)fread(data, 1, *plen, fp); fclose(fp); return data; } int kf_writebin(char *filename, u8 *data, size_t len) { FILE *fp = fopen(filename, "wb"); if (!fp) return 0; size_t n = fwrite(data, 1, len, fp); fclose(fp); if (n != len) return 0; return 1; } static int _kf_compress(lzma_stream *s, FILE *ifp, FILE *ofp) { lzma_action a = LZMA_RUN; u8 inbuf[BUFSIZ], outbuf[BUFSIZ]; s->next_in = NULL; s->avail_in = 0; s->next_out = outbuf; s->avail_out = sizeof(outbuf); for (;;) { if (s->avail_in == 0 && !feof(ifp)) { s->next_in = inbuf; s->avail_in = fread(inbuf, 1, sizeof(inbuf), ifp); if (ferror(ifp)) { KF_THROW("read error: %s", strerror(errno)); return 0; /* unreachable */ } if (feof(ifp)) a = LZMA_FINISH; } lzma_ret r = lzma_code(s, a); if (s->avail_out == 0 || r == LZMA_STREAM_END) { size_t nwrote = sizeof(outbuf) - s->avail_out; if (fwrite(outbuf, 1, nwrote, ofp) != nwrote) { KF_THROW("write error: %s", strerror(errno)); return 0; /* unreachable */ } s->next_out = outbuf; s->avail_out = sizeof(outbuf); } if (r != LZMA_OK) { if (r == LZMA_STREAM_END) return 1; KF_THROW("lzma compression error: code=%d", r); return 0; /* unreachable */ } } KF_UNREACHABLE("broke out of for(;;) loop"); return 0; /* unreachable */ } int kf_compress(char *infile, char *outfile) { FILE *ifp = fopen(infile, "r"); if (!ifp) { KF_THROW("failed to open input file: %s", infile); return 0; /* unreachable */ } FILE *ofp = fopen(outfile, "w"); if (!ofp) { fclose(ifp); KF_THROW("failed to open output file: %s", outfile); return 0; /* unreachable */ } lzma_stream s = LZMA_STREAM_INIT; lzma_ret r = lzma_easy_encoder(&s, LZMA_PRESET_DEFAULT, LZMA_CHECK_CRC64); if (r != LZMA_OK) { KF_THROW("failed to initialize lzma encoder: code=%d\n", r); return 0; /* unreachable */ } int res = _kf_compress(&s, ifp, ofp); lzma_end(&s); fclose(ifp); fclose(ofp); return res; } int kf_decompress(char *infile, char *outfile) { FILE *ifp = fopen(infile, "r"); if (!ifp) { KF_THROW("failed to open input file: %s", infile); return 0; /* unreachable */ } FILE *ofp = fopen(outfile, "w"); if (!ofp) { fclose(ifp); KF_THROW("failed to open output file: %s", outfile); return 0; /* unreachable */ } lzma_stream s = LZMA_STREAM_INIT; lzma_ret r = lzma_stream_decoder(&s, UINT64_MAX, LZMA_CONCATENATED); if (r != LZMA_OK) { KF_THROW("failed to initialize lzma decoder: code=%d\n", r); return 0; /* unreachable */ } int res = _kf_compress(&s, ifp, ofp); lzma_end(&s); fclose(ifp); fclose(ofp); return res; }