diff options
Diffstat (limited to 'package/cfgfs/src/minilzop.c')
-rw-r--r-- | package/cfgfs/src/minilzop.c | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/package/cfgfs/src/minilzop.c b/package/cfgfs/src/minilzop.c new file mode 100644 index 000000000..51935185c --- /dev/null +++ b/package/cfgfs/src/minilzop.c @@ -0,0 +1,178 @@ +/* $MirOS: contrib/hosted/fwcf/minilzop.c,v 1.2 2007/03/09 22:25:45 tg Exp $ */ + +/*- + * Copyright (c) 2007 + * Thorsten Glaser <tg@mirbsd.de> + * + * Provided that these terms and disclaimer and all copyright notices + * are retained or reproduced in an accompanying document, permission + * is granted to deal in this work without restriction, including un- + * limited rights to use, publicly perform, distribute, sell, modify, + * merge, give away, or sublicence. + * + * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to + * the utmost extent permitted by applicable law, neither express nor + * implied; without malicious intent or gross negligence. In no event + * may a licensor, author or contributor be held liable for indirect, + * direct, other damage, loss, or other issues arising in any way out + * of dealing in the work, even if advised of the possibility of such + * damage or existence of a defect, except proven that it results out + * of said person's immediate fault when using the work as intended. + */ + +#include <sys/param.h> +#include <err.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "defs.h" +#include "adler.h" +#include "compress.h" +#include "minilzop.h" + +__RCSID("$MirOS: contrib/hosted/fwcf/minilzop.c,v 1.2 2007/03/09 22:25:45 tg Exp $"); + +#define lodsw(s) __extension__({ \ + const uint8_t *lodsw_buf = (const uint8_t *)(s);\ + uint16_t lodsw_val; \ + \ + lodsw_val = lodsw_buf[0]; \ + lodsw_val |= lodsw_buf[1] << 8; \ + (lodsw_val); \ + }) +#define lodsd(s) __extension__({ \ + const uint8_t *lodsd_buf = (const uint8_t *)(s);\ + uint32_t lodsd_val; \ + \ + lodsd_val = lodsd_buf[0]; \ + lodsd_val |= lodsd_buf[1] << 8; \ + lodsd_val |= lodsd_buf[2] << 16; \ + lodsd_val |= lodsd_buf[3] << 24; \ + (lodsd_val); \ + }) +#define stosw(s,w) do { \ + uint8_t *stosw_buf = (uint8_t *)(s); \ + uint16_t stosw_val = (w); \ + \ + stosw_buf[0] = stosw_val & 0xFF; \ + stosw_buf[1] = (stosw_val >> 8) & 0xFF; \ + } while (0) +#define stosd(s,dw) do { \ + uint8_t *stosd_buf = (uint8_t *)(s); \ + uint32_t stosd_val = (dw); \ + \ + stosd_buf[0] = stosd_val & 0xFF; \ + stosd_buf[1] = (stosd_val >> 8) & 0xFF; \ + stosd_buf[2] = (stosd_val >> 16) & 0xFF; \ + stosd_buf[3] = (stosd_val >> 24) & 0xFF; \ + } while (0) + +void +read_aszdata(int dfd, char **dbuf, size_t *dlen) +{ + size_t len; + uint8_t hdrbuf[8]; + ADLER_DECL; + + if (read(dfd, hdrbuf, 8) != 8) + err(1, "short read"); + *dlen = lodsd(hdrbuf + 4); + if ((*dbuf = malloc(*dlen)) == NULL) + err(255, "out of memory trying to allocate %zu bytes", *dlen); + if ((size_t)read(dfd, *dbuf, *dlen) != *dlen) + err(1, "short read"); + len = 4; + ADLER_CALC(hdrbuf + 4); + len = *dlen; + ADLER_CALC(*dbuf); + if ((lodsw(hdrbuf) != s1) || (lodsw(hdrbuf + 2) != s2)) + err(2, "checksum mismatch, size %zu," + " want 0x%02X%02X%02X%02X got 0x%04X%04X", *dlen, + hdrbuf[3], hdrbuf[2], hdrbuf[1], hdrbuf[0], s2, s1); +} + +void +write_aszdata(int dfd, const char *dbuf, size_t dlen) +{ + size_t len; + uint8_t hdrbuf[8]; + ADLER_DECL; + + stosd(hdrbuf + 4, dlen); + len = 4; + ADLER_CALC(hdrbuf + 4); + len = dlen; + ADLER_CALC(dbuf); + stosw(hdrbuf, s1); + stosw(hdrbuf + 2, s2); + if (write(dfd, hdrbuf, 8) != 8) + err(1, "short write"); + if ((size_t)write(dfd, dbuf, dlen) != dlen) + err(1, "short write"); +} + +int +minilzop(int ifd, int ofd, int compr_alg, int decompress) +{ + size_t ilen, olen, n; + char *idata, *odata; + +#ifndef SMALL + fprintf(stderr, "minilzop: using algorithm %02X (%s)\n", + compr_alg, compressor_get(compr_alg)->name); +#endif + if (decompress) { + read_aszdata(ifd, &idata, &ilen); + olen = lodsd(idata); + if ((odata = malloc(olen)) == NULL) + err(255, "out of memory trying to allocate %zu bytes", + olen); + if ((n = compressor_get(compr_alg)->decompress(odata, olen, + idata + 4, ilen - 4)) != olen) + errx(1, "size mismatch: decompressed %zu, want %zu", + n, olen); + free(idata); + idata = odata; /* save for later free(3) */ + while (olen) { + if ((n = write(ofd, odata, olen)) == (size_t)-1) + err(1, "cannot write"); + olen -= n; + odata += n; + } + free(idata); + } else { + size_t cc; + + n = 16384; + idata = NULL; + ilen = 0; + slurp_file: + if ((idata = realloc(idata, (n <<= 1))) == NULL) + err(255, "out of memory trying to allocate %zu bytes", + n); + slurp_retry: + if ((cc = read(ifd, idata + ilen, n - ilen)) == (size_t)-1) + err(1, "cannot read"); + ilen += cc; + if (cc > 0) { + if (ilen < n) + goto slurp_retry; + goto slurp_file; + } + if ((olen = compressor_get(compr_alg)->compress(&odata, idata, + ilen)) == (size_t)-1) + errx(1, "%s compression failed", + compressor_get(compr_alg)->name); + free(idata); + if ((idata = malloc(olen + 4)) == NULL) + err(255, "out of memory trying to allocate %zu bytes", + olen + 4); + stosd(idata, ilen); + memcpy(idata + 4, odata, olen); + write_aszdata(ofd, idata, olen + 4); + free(idata); + } + return (0); +} |