summaryrefslogtreecommitdiff
path: root/package/heirloom-cpio/src/expand.c
diff options
context:
space:
mode:
Diffstat (limited to 'package/heirloom-cpio/src/expand.c')
-rw-r--r--package/heirloom-cpio/src/expand.c193
1 files changed, 193 insertions, 0 deletions
diff --git a/package/heirloom-cpio/src/expand.c b/package/heirloom-cpio/src/expand.c
new file mode 100644
index 000000000..5a5233f3e
--- /dev/null
+++ b/package/heirloom-cpio/src/expand.c
@@ -0,0 +1,193 @@
+/*
+ * cpio - copy file archives in and out
+ *
+ * Gunnar Ritter, Freiburg i. Br., Germany, April 2003.
+ */
+/*
+ * Copyright (c) 2003 Gunnar Ritter
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute
+ * it freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ *
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ *
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+/* Sccsid @(#)expand.c 1.6 (gritter) 12/15/03 */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "cpio.h"
+
+#define DLE 144
+
+static void
+zexread(char *data, size_t size, int doswap)
+{
+ if (bread(data, size) != size)
+ unexeoa();
+ if (doswap)
+ swap(data, size, bflag || sflag, bflag || Sflag);
+}
+
+#define nextbyte() ( \
+ ipos >= sizeof ibuf && isize > 0 ? ( \
+ zexread(ibuf, isize>sizeof ibuf?sizeof ibuf:isize, doswap), \
+ ipos = 0 \
+ ) : 0, \
+ isize--, \
+ ibuf[ipos++] & 0377 \
+)
+
+#define nextbit() ( \
+ ibit = ibit >= 7 ? (ibyte = nextbyte(), 0) : ibit + 1, \
+ isize < 0 ? (ieof = 1, -1) : (ibyte & (1<<ibit)) >> ibit \
+)
+
+#define sixbits(n) { \
+ int t; \
+ (n) = 0; \
+ for (t = 0; t < 6; t++) \
+ (n) |= nextbit() << t; \
+}
+
+#define eightbits(n) { \
+ int t; \
+ (n) = 0; \
+ for (t = 0; t < 8; t++) \
+ (n) |= nextbit() << t; \
+}
+
+static void
+zexwrite(int *tfd, char *data, size_t size, uint32_t *crc, int *val,
+ const char *tgt, long long *nsize)
+{
+ if (size) {
+ if (size > *nsize)
+ size = *nsize;
+ if (*tfd >= 0 && write(*tfd, data, size) != size) {
+ emsg(3, "Cannot write \"%s\"", tgt);
+ *tfd = -1;
+ *val = -1;
+ }
+ *crc = zipcrc(*crc, (unsigned char *)data, size);
+ *nsize -= size;
+ }
+}
+
+#define wadd(c) ( \
+ wpos >= sizeof wbuf ? ( \
+ zexwrite(&tfd, wbuf, sizeof wbuf, crc, &val, tgt, &nsize), \
+ wpos = 0 \
+ ) : 0, \
+ wsize++, \
+ wbuf[wpos++] = (c) \
+)
+
+#define zex_L(x) ( \
+ f->f_cmethod == C_REDUCED1 ? (x) & 0177 : \
+ f->f_cmethod == C_REDUCED2 ? (x) & 077 : \
+ f->f_cmethod == C_REDUCED3 ? (x) & 037 : \
+ /* f->f_cmethod == C_REDUCED4 */ (x) & 017 \
+)
+
+#define zex_F(x) ( \
+ f->f_cmethod == C_REDUCED1 ? (x) == 0177 ? 2 : 3 : \
+ f->f_cmethod == C_REDUCED2 ? (x) == 077 ? 2 : 3 : \
+ f->f_cmethod == C_REDUCED3 ? (x) == 037 ? 2 : 3 : \
+ /* f->f_cmethod == C_REDUCED4 */ (x) == 017 ? 2 : 3 \
+)
+
+#define zex_D(x, y) ( \
+ f->f_cmethod == C_REDUCED1 ? (((x)&0200)>>7) * 0400 + (y) + 1 : \
+ f->f_cmethod == C_REDUCED2 ? (((x)&0300)>>6) * 0400 + (y) + 1 : \
+ f->f_cmethod == C_REDUCED3 ? (((x)&0340)>>5) * 0400 + (y) + 1 : \
+ /* f->f_cmethod == C_REDUCED4 */ (((x)&0360)>>4) * 0400 + (y) + 1 \
+)
+
+int
+zipexpand(struct file *f, const char *tgt, int tfd, int doswap, uint32_t *crc)
+{
+ char fset[256][33];
+ char ibuf[4096], ibyte = 0, wbuf[8192];
+ long ipos = sizeof ibuf, wpos = 0, isize = f->f_csize, wsize = 0;
+ int val = 0, ieof = 0;
+ int c = 0, i, j, k, n, ibit = 7, lastc, state, v = 0, len = 0;
+ long long nsize = f->f_st.st_size;
+
+ *crc = 0;
+ memset(fset, 0, sizeof fset);
+ for (j = 255; j >= 0; j--) {
+ sixbits(n);
+ for (i = 0; i < n; i++) {
+ eightbits(fset[j][i]);
+ }
+ fset[j][32] = n<1?0:n<3?1:n<5?2:n<9?3:n<17?4:n<37?5:n<65?6:7;
+ }
+ lastc = 0;
+ state = 0;
+ while (ieof == 0) {
+ if (fset[lastc][32] == 0) {
+ eightbits(c);
+ } else {
+ if (nextbit() != 0) {
+ eightbits(c);
+ } else {
+ i = 0;
+ for (k = 0; k < fset[lastc][32]; k++)
+ i |= nextbit() << k;
+ c = fset[lastc][i] & 0377;
+ }
+ }
+ lastc = c;
+ switch (state) {
+ case 0:
+ if (c != DLE)
+ wadd(c);
+ else
+ state = 1;
+ break;
+ case 1:
+ if (c != 0) {
+ v = c;
+ len = zex_L(v);
+ state = zex_F(len);
+ } else {
+ wadd(DLE);
+ state = 0;
+ }
+ break;
+ case 2:
+ len += c;
+ state = 3;
+ break;
+ case 3:
+ n = wsize - zex_D(v, c);
+ for (i = 0; i < len + 3; i++) {
+ c = n+i >= 0 ? wbuf[n+i&sizeof wbuf-1]&0377 : 0;
+ wadd(c);
+ }
+ state = 0;
+ }
+ }
+ zexwrite(&tfd, wbuf, wpos, crc, &val, tgt, &nsize);
+ while (isize >= 0)
+ nextbyte();
+ return val;
+}