summaryrefslogtreecommitdiff
path: root/package/cfgfs/src/minilzop.c
diff options
context:
space:
mode:
Diffstat (limited to 'package/cfgfs/src/minilzop.c')
-rw-r--r--package/cfgfs/src/minilzop.c178
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);
+}