summaryrefslogtreecommitdiff
path: root/tools/cpio
diff options
context:
space:
mode:
authorWaldemar Brodkorb <wbx@openadk.org>2010-07-29 15:25:12 +0200
committerWaldemar Brodkorb <wbx@openadk.org>2010-07-29 15:25:12 +0200
commitfd6481d82ff407139157e53df28563d40bb3ad3b (patch)
treeed2ae9e08c31d1eed424793272a60c25cdec6c00 /tools/cpio
parent14804005d5b33beb6f52d4a72034acb00c00eb90 (diff)
add a cpio implementation to tools directory
cpio utility is a mess in point of portability. For example NetBSD cpio implementation does not support userid and groupid changes for the archive. This feature is required for initramfs filesystem targets. This cpio is from the Heirloom project. Fix needed rebuild of tools, when changing targets.
Diffstat (limited to 'tools/cpio')
-rw-r--r--tools/cpio/Makefile33
-rw-r--r--tools/cpio/src/_alloca.h27
-rw-r--r--tools/cpio/src/_malloc.h26
-rw-r--r--tools/cpio/src/_utmpx.h89
-rw-r--r--tools/cpio/src/asciitype.c59
-rw-r--r--tools/cpio/src/asciitype.h60
-rw-r--r--tools/cpio/src/atoll.h8
-rw-r--r--tools/cpio/src/blank.h38
-rw-r--r--tools/cpio/src/blast.c449
-rw-r--r--tools/cpio/src/blast.h76
-rw-r--r--tools/cpio/src/cpio.1943
-rw-r--r--tools/cpio/src/cpio.c7185
-rw-r--r--tools/cpio/src/cpio.h232
-rw-r--r--tools/cpio/src/crc32.c115
-rw-r--r--tools/cpio/src/expand.c193
-rw-r--r--tools/cpio/src/explode.c1138
-rw-r--r--tools/cpio/src/flags.c257
-rw-r--r--tools/cpio/src/getdir.c197
-rw-r--r--tools/cpio/src/getdir.h33
-rw-r--r--tools/cpio/src/getopt.c141
-rw-r--r--tools/cpio/src/gmatch.c136
-rw-r--r--tools/cpio/src/ib_alloc.c61
-rw-r--r--tools/cpio/src/ib_close.c36
-rw-r--r--tools/cpio/src/ib_free.c33
-rw-r--r--tools/cpio/src/ib_getlin.c78
-rw-r--r--tools/cpio/src/ib_getw.c81
-rw-r--r--tools/cpio/src/ib_open.c48
-rw-r--r--tools/cpio/src/ib_popen.c87
-rw-r--r--tools/cpio/src/ib_read.c51
-rw-r--r--tools/cpio/src/ib_seek.c53
-rw-r--r--tools/cpio/src/iblok.h135
-rw-r--r--tools/cpio/src/inflate.c991
-rw-r--r--tools/cpio/src/mbtowi.h22
-rw-r--r--tools/cpio/src/memalign.c51
-rw-r--r--tools/cpio/src/memalign.h35
-rw-r--r--tools/cpio/src/msgselect.h30
-rw-r--r--tools/cpio/src/nonpax.c55
-rw-r--r--tools/cpio/src/oblok.c260
-rw-r--r--tools/cpio/src/oblok.h96
-rw-r--r--tools/cpio/src/pathconf.c51
-rw-r--r--tools/cpio/src/pathconf.h29
-rw-r--r--tools/cpio/src/pax.1919
-rw-r--r--tools/cpio/src/pax.c757
-rw-r--r--tools/cpio/src/pfmt.c39
-rw-r--r--tools/cpio/src/pfmt.h46
-rw-r--r--tools/cpio/src/pfmt_label.c1
-rw-r--r--tools/cpio/src/regexp.h1211
-rw-r--r--tools/cpio/src/regexpr.c90
-rw-r--r--tools/cpio/src/regexpr.h53
-rw-r--r--tools/cpio/src/setlabel.c40
-rw-r--r--tools/cpio/src/setuxlabel.c47
-rw-r--r--tools/cpio/src/sfile.c99
-rw-r--r--tools/cpio/src/sfile.h40
-rw-r--r--tools/cpio/src/sighold.c41
-rw-r--r--tools/cpio/src/sigignore.c45
-rw-r--r--tools/cpio/src/signal.c45
-rw-r--r--tools/cpio/src/sigpause.c48
-rw-r--r--tools/cpio/src/sigrelse.c41
-rw-r--r--tools/cpio/src/sigset.c55
-rw-r--r--tools/cpio/src/sigset.h38
-rw-r--r--tools/cpio/src/strtol.c117
-rw-r--r--tools/cpio/src/unshrink.c307
-rw-r--r--tools/cpio/src/unzip.h121
-rw-r--r--tools/cpio/src/utmpx.c252
-rw-r--r--tools/cpio/src/version.c26
-rw-r--r--tools/cpio/src/vpfmt.c90
66 files changed, 18286 insertions, 0 deletions
diff --git a/tools/cpio/Makefile b/tools/cpio/Makefile
new file mode 100644
index 000000000..e9533a498
--- /dev/null
+++ b/tools/cpio/Makefile
@@ -0,0 +1,33 @@
+# This file is part of the OpenADK project. OpenADK is copyrighted
+# material, please see the LICENCE file in the top-level directory.
+
+include $(TOPDIR)/rules.mk
+
+SRCS+= \
+ src/ib_open.c \
+ src/ib_close.c \
+ src/ib_read.c \
+ src/ib_alloc.c \
+ src/ib_free.c \
+ src/ib_getlin.c \
+ src/sfile.c \
+ src/gmatch.c
+
+SRCS+= \
+ src/version.c \
+ src/blast.c \
+ src/crc32.c \
+ src/expand.c \
+ src/explode.c \
+ src/flags.c \
+ src/inflate.c \
+ src/unshrink.c \
+ src/nonpax.c \
+ src/cpio.c
+
+${STAGING_TOOLS}/bin/cpio: ${SRCS}
+ ${HOSTCC} ${HOSTCFLAGS} -D_GNU_SOURCE -Isrc -o $@ $^
+
+install: ${STAGING_TOOLS}/bin/cpio
+
+include $(TOPDIR)/mk/tools.mk
diff --git a/tools/cpio/src/_alloca.h b/tools/cpio/src/_alloca.h
new file mode 100644
index 000000000..dc2afe5b4
--- /dev/null
+++ b/tools/cpio/src/_alloca.h
@@ -0,0 +1,27 @@
+/*
+ * 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 @(#)_alloca.h 1.5 (gritter) 1/22/06 */
+
+#if defined (__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) || \
+ defined (__DragonFly__) || defined (__APPLE__)
+#include <stdlib.h>
+#endif /* __FreeBSD__, __NetBSD__, __OpenBSD__, __DragonFly__, __APPLE__ */
diff --git a/tools/cpio/src/_malloc.h b/tools/cpio/src/_malloc.h
new file mode 100644
index 000000000..1693e3673
--- /dev/null
+++ b/tools/cpio/src/_malloc.h
@@ -0,0 +1,26 @@
+/*
+ * 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 @(#)_malloc.h 1.2 (gritter) 5/1/04 */
+
+#include <stdlib.h>
+
+extern void *memalign(size_t, size_t);
diff --git a/tools/cpio/src/_utmpx.h b/tools/cpio/src/_utmpx.h
new file mode 100644
index 000000000..c32bd9527
--- /dev/null
+++ b/tools/cpio/src/_utmpx.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2004 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 @(#)_utmpx.h 1.9 (gritter) 1/22/06 */
+
+#if defined (__FreeBSD__) || defined (__dietlibc__) || defined (__NetBSD__) || \
+ defined (__UCLIBC__) || defined (__OpenBSD__) || \
+ defined (__DragonFly__) || defined (__APPLE__)
+#include <sys/types.h>
+#include <sys/time.h>
+#include <utmp.h>
+
+#ifndef __dietlibc__
+struct utmpx {
+ char ut_user[UT_NAMESIZE];
+ char ut_id[UT_LINESIZE];
+ char ut_line[UT_LINESIZE];
+ char ut_host[UT_HOSTSIZE];
+ pid_t ut_pid;
+ short ut_type;
+ struct timeval ut_tv;
+ struct {
+ int e_termination;
+ int e_exit;
+ } ut_exit;
+};
+
+#ifndef EMPTY
+#define EMPTY 0
+#endif
+#ifndef BOOT_TIME
+#define BOOT_TIME 1
+#endif
+#ifndef OLD_TIME
+#define OLD_TIME 2
+#endif
+#ifndef NEW_TIME
+#define NEW_TIME 3
+#endif
+#ifndef USER_PROCESS
+#define USER_PROCESS 4
+#endif
+#ifndef INIT_PROCESS
+#define INIT_PROCESS 5
+#endif
+#ifndef LOGIN_PROCESS
+#define LOGIN_PROCESS 6
+#endif
+#ifndef DEAD_PROCESS
+#define DEAD_PROCESS 7
+#endif
+#ifndef RUN_LVL
+#define RUN_LVL 8
+#endif
+#ifndef ACCOUNTING
+#define ACCOUNTING 9
+#endif
+#else /* __dietlibc__ */
+#define utmpx utmp
+#endif /* __dietlibc__ */
+
+extern void endutxent(void);
+extern struct utmpx *getutxent(void);
+extern struct utmpx *getutxid(const struct utmpx *);
+extern struct utmpx *getutxline(const struct utmpx *);
+extern struct utmpx *pututxline(const struct utmpx *);
+extern void setutxent(void);
+extern int utmpxname(const char *);
+extern void updwtmpx(const char *, const struct utmpx *);
+#endif /* __FreeBSD__ || __dietlibc__ || __NetBSD__ || __UCLIBC__ ||
+ __OpenBSD__ || __DragonFly__ || __APPLE__ */
diff --git a/tools/cpio/src/asciitype.c b/tools/cpio/src/asciitype.c
new file mode 100644
index 000000000..f7f322173
--- /dev/null
+++ b/tools/cpio/src/asciitype.c
@@ -0,0 +1,59 @@
+/*
+ * 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 @(#)asciitype.c 1.4 (gritter) 4/17/03 */
+
+#include "asciitype.h"
+
+const unsigned char class_char[] = {
+/* 000 nul 001 soh 002 stx 003 etx 004 eot 005 enq 006 ack 007 bel */
+ C_CNTRL,C_CNTRL,C_CNTRL,C_CNTRL,C_CNTRL,C_CNTRL,C_CNTRL,C_CNTRL,
+/* 010 bs 011 ht 012 nl 013 vt 014 np 015 cr 016 so 017 si */
+ C_CNTRL,C_BLANK,C_WHITE,C_SPACE,C_SPACE,C_SPACE,C_CNTRL,C_CNTRL,
+/* 020 dle 021 dc1 022 dc2 023 dc3 024 dc4 025 nak 026 syn 027 etb */
+ C_CNTRL,C_CNTRL,C_CNTRL,C_CNTRL,C_CNTRL,C_CNTRL,C_CNTRL,C_CNTRL,
+/* 030 can 031 em 032 sub 033 esc 034 fs 035 gs 036 rs 037 us */
+ C_CNTRL,C_CNTRL,C_CNTRL,C_CNTRL,C_CNTRL,C_CNTRL,C_CNTRL,C_CNTRL,
+/* 040 sp 041 ! 042 " 043 # 044 $ 045 % 046 & 047 ' */
+ C_BLANK,C_PUNCT,C_PUNCT,C_PUNCT,C_PUNCT,C_PUNCT,C_PUNCT,C_PUNCT,
+/* 050 ( 051 ) 052 * 053 + 054 , 055 - 056 . 057 / */
+ C_PUNCT,C_PUNCT,C_PUNCT,C_PUNCT,C_PUNCT,C_PUNCT,C_PUNCT,C_PUNCT,
+/* 060 0 061 1 062 2 063 3 064 4 065 5 066 6 067 7 */
+ C_OCTAL,C_OCTAL,C_OCTAL,C_OCTAL,C_OCTAL,C_OCTAL,C_OCTAL,C_OCTAL,
+/* 070 8 071 9 072 : 073 ; 074 < 075 = 076 > 077 ? */
+ C_DIGIT,C_DIGIT,C_PUNCT,C_PUNCT,C_PUNCT,C_PUNCT,C_PUNCT,C_PUNCT,
+/* 100 @ 101 A 102 B 103 C 104 D 105 E 106 F 107 G */
+ C_PUNCT,C_UPPER,C_UPPER,C_UPPER,C_UPPER,C_UPPER,C_UPPER,C_UPPER,
+/* 110 H 111 I 112 J 113 K 114 L 115 M 116 N 117 O */
+ C_UPPER,C_UPPER,C_UPPER,C_UPPER,C_UPPER,C_UPPER,C_UPPER,C_UPPER,
+/* 120 P 121 Q 122 R 123 S 124 T 125 U 126 V 127 W */
+ C_UPPER,C_UPPER,C_UPPER,C_UPPER,C_UPPER,C_UPPER,C_UPPER,C_UPPER,
+/* 130 X 131 Y 132 Z 133 [ 134 \ 135 ] 136 ^ 137 _ */
+ C_UPPER,C_UPPER,C_UPPER,C_PUNCT,C_PUNCT,C_PUNCT,C_PUNCT,C_PUNCT,
+/* 140 ` 141 a 142 b 143 c 144 d 145 e 146 f 147 g */
+ C_PUNCT,C_LOWER,C_LOWER,C_LOWER,C_LOWER,C_LOWER,C_LOWER,C_LOWER,
+/* 150 h 151 i 152 j 153 k 154 l 155 m 156 n 157 o */
+ C_LOWER,C_LOWER,C_LOWER,C_LOWER,C_LOWER,C_LOWER,C_LOWER,C_LOWER,
+/* 160 p 161 q 162 r 163 s 164 t 165 u 166 v 167 w */
+ C_LOWER,C_LOWER,C_LOWER,C_LOWER,C_LOWER,C_LOWER,C_LOWER,C_LOWER,
+/* 170 x 171 y 172 z 173 { 174 | 175 } 176 ~ 177 del */
+ C_LOWER,C_LOWER,C_LOWER,C_PUNCT,C_PUNCT,C_PUNCT,C_PUNCT,C_CNTRL
+};
diff --git a/tools/cpio/src/asciitype.h b/tools/cpio/src/asciitype.h
new file mode 100644
index 000000000..6ac1961a1
--- /dev/null
+++ b/tools/cpio/src/asciitype.h
@@ -0,0 +1,60 @@
+/*
+ * 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 @(#)asciitype.h 1.6 (gritter) 9/9/05 */
+
+/*
+ * Locale-independent character classes.
+ */
+enum {
+ C_CNTRL = 0000,
+ C_BLANK = 0001,
+ C_WHITE = 0002,
+ C_SPACE = 0004,
+ C_PUNCT = 0010,
+ C_OCTAL = 0020,
+ C_DIGIT = 0040,
+ C_UPPER = 0100,
+ C_LOWER = 0200
+};
+
+extern const unsigned char class_char[];
+
+#define asciichar(c) ((unsigned)(c) <= 0177)
+#define alnumchar(c) (asciichar(c)&&(class_char[c]&\
+ (C_DIGIT|C_OCTAL|C_UPPER|C_LOWER)))
+#define alphachar(c) (asciichar(c)&&(class_char[c]&(C_UPPER|C_LOWER)))
+#define blankchar(c) (asciichar(c)&&(class_char[c]&(C_BLANK)))
+#define cntrlchar(c) (asciichar(c)&&(class_char[c]==C_CNTRL)
+#define digitchar(c) (asciichar(c)&&(class_char[c]&(C_DIGIT|C_OCTAL)))
+#define lowerchar(c) (asciichar(c)&&(class_char[c]&(C_LOWER)))
+#define punctchar(c) (asciichar(c)&&(class_char[c]&(C_PUNCT)))
+#define spacechar(c) (asciichar(c)&&(class_char[c]&(C_BLANK|C_SPACE|C_WHITE)))
+#define upperchar(c) (asciichar(c)&&(class_char[c]&(C_UPPER)))
+#define whitechar(c) (asciichar(c)&&(class_char[c]&(C_BLANK|C_WHITE)))
+#define octalchar(c) (asciichar(c)&&(class_char[c]&(C_OCTAL)))
+#define graphchar(c) (asciichar(c)&&(class_char[c]&\
+ (C_UPPER|C_LOWER|C_DIGIT|C_OCTAL|C_PUNCT)))
+#define printchar(c) ((c)==' ' || asciichar(c)&&(class_char[c]&\
+ (C_UPPER|C_LOWER|C_DIGIT|C_OCTAL|C_PUNCT)))
+
+#define upperconv(c) (lowerchar(c) ? (c)-'a'+'A' : (c))
+#define lowerconv(c) (upperchar(c) ? (c)-'A'+'a' : (c))
diff --git a/tools/cpio/src/atoll.h b/tools/cpio/src/atoll.h
new file mode 100644
index 000000000..8283aff64
--- /dev/null
+++ b/tools/cpio/src/atoll.h
@@ -0,0 +1,8 @@
+/* Sccsid @(#)atoll.h 1.4 (gritter) 7/18/04 */
+
+#if defined (__hpux) || defined (_AIX) || \
+ defined (__FreeBSD__) && (__FreeBSD__) < 5
+extern long long strtoll(const char *nptr, char **endptr, int base);
+extern unsigned long long strtoull(const char *nptr, char **endptr, int base);
+extern long long atoll(const char *nptr);
+#endif /* __hpux || _AIX || __FreeBSD__ < 5 */
diff --git a/tools/cpio/src/blank.h b/tools/cpio/src/blank.h
new file mode 100644
index 000000000..1ab3d57b8
--- /dev/null
+++ b/tools/cpio/src/blank.h
@@ -0,0 +1,38 @@
+/*
+ * isblank() and iswblank() are not available with many pre-XSH6
+ * systems. Check whether isblank was defined, and assume it is
+ * not available if not.
+ */
+/* Sccsid @(#)blank.h 1.3 (gritter) 5/1/04 */
+
+#ifndef __dietlibc__
+#ifndef LIBCOMMON_BLANK_H
+#define LIBCOMMON_BLANK_H 1
+
+#include <ctype.h>
+#include <wctype.h>
+
+#ifndef isblank
+
+static
+#ifdef __GNUC__
+__inline__
+#endif /* __GNUC__ */
+int
+my_isblank(int c)
+{
+ return c == ' ' || c == '\t';
+}
+#define isblank(c) my_isblank(c)
+
+static int
+my_iswblank(wint_t c)
+{
+ return c == L' ' || c == L'\t';
+}
+#undef iswblank
+#define iswblank(c) my_iswblank(c)
+
+#endif /* !isblank */
+#endif /* !LIBCOMMON_BLANK_H */
+#endif /* !__dietlibc__ */
diff --git a/tools/cpio/src/blast.c b/tools/cpio/src/blast.c
new file mode 100644
index 000000000..b62efd585
--- /dev/null
+++ b/tools/cpio/src/blast.c
@@ -0,0 +1,449 @@
+/*
+ * Changes by Gunnar Ritter, Freiburg i. Br., Germany, February 2004.
+ *
+ * Sccsid @(#)blast.c 1.2 (gritter) 2/17/04
+ */
+/* blast.c
+ * Copyright (C) 2003 Mark Adler
+ * For conditions of distribution and use, see copyright notice in blast.h
+ * version 1.1, 16 Feb 2003
+ *
+ * blast.c decompresses data compressed by the PKWare Compression Library.
+ * This function provides functionality similar to the explode() function of
+ * the PKWare library, hence the name "blast".
+ *
+ * This decompressor is based on the excellent format description provided by
+ * Ben Rudiak-Gould in comp.compression on August 13, 2001. Interestingly, the
+ * example Ben provided in the post is incorrect. The distance 110001 should
+ * instead be 111000. When corrected, the example byte stream becomes:
+ *
+ * 00 04 82 24 25 8f 80 7f
+ *
+ * which decompresses to "AIAIAIAIAIAIA" (without the quotes).
+ */
+
+/*
+ * Change history:
+ *
+ * 1.0 12 Feb 2003 - First version
+ * 1.1 16 Feb 2003 - Fixed distance check for > 4 GB uncompressed data
+ */
+
+#include <setjmp.h> /* for setjmp(), longjmp(), and jmp_buf */
+#include "blast.h" /* prototype for blast() */
+
+#define local static /* for local function definitions */
+#define MAXBITS 13 /* maximum code length */
+#define MAXWIN 4096 /* maximum window size */
+
+/* input and output state */
+struct state {
+ /* input state */
+ blast_in infun; /* input function provided by user */
+ void *inhow; /* opaque information passed to infun() */
+ unsigned char *in; /* next input location */
+ unsigned left; /* available input at in */
+ int bitbuf; /* bit buffer */
+ int bitcnt; /* number of bits in bit buffer */
+
+ /* input limit error return state for bits() and decode() */
+ jmp_buf env;
+
+ /* output state */
+ blast_out outfun; /* output function provided by user */
+ void *outhow; /* opaque information passed to outfun() */
+ unsigned next; /* index of next write location in out[] */
+ int first; /* true to check distances (for first 4K) */
+ unsigned char out[MAXWIN]; /* output buffer and sliding window */
+};
+
+/*
+ * Return need bits from the input stream. This always leaves less than
+ * eight bits in the buffer. bits() works properly for need == 0.
+ *
+ * Format notes:
+ *
+ * - Bits are stored in bytes from the least significant bit to the most
+ * significant bit. Therefore bits are dropped from the bottom of the bit
+ * buffer, using shift right, and new bytes are appended to the top of the
+ * bit buffer, using shift left.
+ */
+local int bits(struct state *s, int need)
+{
+ int val; /* bit accumulator */
+
+ /* load at least need bits into val */
+ val = s->bitbuf;
+ while (s->bitcnt < need) {
+ if (s->left == 0) {
+ s->left = s->infun(s->inhow, &(s->in));
+ if (s->left == 0) longjmp(s->env, 1); /* out of input */
+ }
+ val |= (int)(*(s->in)++) << s->bitcnt; /* load eight bits */
+ s->left--;
+ s->bitcnt += 8;
+ }
+
+ /* drop need bits and update buffer, always zero to seven bits left */
+ s->bitbuf = val >> need;
+ s->bitcnt -= need;
+
+ /* return need bits, zeroing the bits above that */
+ return val & ((1 << need) - 1);
+}
+
+/*
+ * Huffman code decoding tables. count[1..MAXBITS] is the number of symbols of
+ * each length, which for a canonical code are stepped through in order.
+ * symbol[] are the symbol values in canonical order, where the number of
+ * entries is the sum of the counts in count[]. The decoding process can be
+ * seen in the function decode() below.
+ */
+struct huffman {
+ short *count; /* number of symbols of each length */
+ short *symbol; /* canonically ordered symbols */
+};
+
+/*
+ * Decode a code from the stream s using huffman table h. Return the symbol or
+ * a negative value if there is an error. If all of the lengths are zero, i.e.
+ * an empty code, or if the code is incomplete and an invalid code is received,
+ * then -9 is returned after reading MAXBITS bits.
+ *
+ * Format notes:
+ *
+ * - The codes as stored in the compressed data are bit-reversed relative to
+ * a simple integer ordering of codes of the same lengths. Hence below the
+ * bits are pulled from the compressed data one at a time and used to
+ * build the code value reversed from what is in the stream in order to
+ * permit simple integer comparisons for decoding.
+ *
+ * - The first code for the shortest length is all ones. Subsequent codes of
+ * the same length are simply integer decrements of the previous code. When
+ * moving up a length, a one bit is appended to the code. For a complete
+ * code, the last code of the longest length will be all zeros. To support
+ * this ordering, the bits pulled during decoding are inverted to apply the
+ * more "natural" ordering starting with all zeros and incrementing.
+ */
+local int decode(struct state *s, struct huffman *h)
+{
+ int len; /* current number of bits in code */
+ int code; /* len bits being decoded */
+ int first; /* first code of length len */
+ int count; /* number of codes of length len */
+ int index; /* index of first code