Merge from vendor branch AWK:
[dragonfly.git] / sys / i386 / boot / kzipboot / misc.c
1 /*
2  * misc.c
3  *
4  * This is a collection of several routines from gzip-1.0.3
5  * adapted for Linux.
6  *
7  * Ported to 386bsd by Serge Vakulenko
8  *
9  * $DragonFly: src/sys/i386/boot/kzipboot/Attic/misc.c,v 1.2 2003/08/07 21:17:20 dillon Exp $
10  */
11
12 #include "use_gzip.h"
13
14 unsigned outcnt;
15 unsigned insize;
16 unsigned inptr;
17
18 extern const char input_data[];
19 extern const int input_len;
20
21 int input_ptr;
22
23 int method;
24
25 char *output_data;
26 ulong output_ptr;
27
28 void makecrc (void);
29 void putstr (char *c);
30 void *memcpy (void *to, const void *from, unsigned len);
31 int memcmp (const void *arg1, const void *arg2, unsigned len);
32
33 ulong crc;                              /* shift register contents */
34 ulong crc_32_tab[256];                  /* crc table, defined below */
35
36 /*
37  * Run a set of bytes through the crc shift register.  If s is a NULL
38  * pointer, then initialize the crc shift register contents instead.
39  * Return the current crc in either case.
40  */
41 void updcrc(s, n)
42 uchar *s;                       /* pointer to bytes to pump through */
43 unsigned n;                     /* number of bytes in s[] */
44 {
45         while (n--)
46                 crc = crc_32_tab[(uchar)crc ^ (*s++)] ^ (crc >> 8);
47 }
48
49 /*
50  * Clear input and output buffers
51  */
52 void clear_bufs()
53 {
54         outcnt = 0;
55         insize = inptr = 0;
56 }
57
58 /*
59  * Fill the input buffer. This is called only when the buffer is empty
60  * and at least one byte is really needed.
61  */
62 void fill_inbuf ()
63 {
64         int len, i;
65
66         /* Read as much as possible */
67         insize = 0;
68         do {
69                 len = INBUFSIZ - insize;
70                 if (len > input_len - input_ptr + 1)
71                         len = input_len-input_ptr+1;
72                 if (len <= 0)
73                         break;
74                 for (i=0; i<len; i++)
75                         inbuf[insize+i] = input_data[input_ptr+i];
76                 insize += len;
77                 input_ptr += len;
78         } while (insize < INBUFSIZ);
79         if (insize == 0)
80                 error("unable to fill buffer");
81         inptr = 0;
82 }
83
84 /*
85  * Write the output window window[0..outcnt-1] and update crc and bytes_out.
86  * (Used for the decompressed data only.)
87  */
88 void flush_window()
89 {
90         if (outcnt == 0) return;
91         updcrc(window, outcnt);
92
93         memcpy(&output_data[output_ptr], (char *)window, outcnt);
94
95         output_ptr += outcnt;
96         outcnt = 0;
97 }
98
99 /*
100  * Code to compute the CRC-32 table. Borrowed from
101  * gzip-1.0.3/makecrc.c.
102  * Not copyrighted 1990 Mark Adler
103  */
104 void makecrc(void)
105 {
106         ulong c;        /* crc shift register */
107         ulong e;        /* polynomial exclusive-or pattern */
108         int i;          /* counter for all possible eight bit values */
109         int k;          /* byte being shifted into crc apparatus */
110
111         /* terms of polynomial defining this crc (except x^32): */
112         static const uchar poly[] = { 0,1,2,4,5,7,8,10,11,12,16,22,23,26, };
113
114         /* Make exclusive-or pattern from polynomial */
115         e = 0;
116         for (i = 0; i < sizeof(poly)/sizeof(*poly); i++)
117                 e |= 1L << (31 - poly[i]);
118
119         crc_32_tab[0] = 0;
120
121         for (i = 1; i < 256; i++) {
122                 c = 0;
123                 for (k = i | 256; k != 1; k >>= 1) {
124                         c = c & 1 ? (c >> 1) ^ e : c >> 1;
125                         if (k & 1)
126                                 c ^= e;
127                 }
128                 crc_32_tab[i] = c;
129         }
130 }
131
132 /*
133  * Check the magic number of the input file and update ofname if an
134  * original name was given and to_stdout is not set.
135  * Set inptr to the offset of the next byte to be processed.
136  */
137 static void get_method()
138 {
139         uchar flags;
140         char magic[2];  /* magic header */
141
142         magic[0] = get_byte();
143         magic[1] = get_byte();
144
145         method = -1;            /* unknown yet */
146         extended = pkzip = 0;
147         /* assume multiple members in gzip file except for record oriented I/O */
148
149         if (memcmp(magic, GZIP_MAGIC, 2) == 0
150             || memcmp(magic, OLD_GZIP_MAGIC, 2) == 0) {
151                 method = get_byte();
152                 flags  = get_byte();
153                 if (flags & ENCRYPTED)
154                         error("Input is encrypted");
155                 if (flags & CONTINUATION)
156                         error("Multi part input");
157                 if (flags & RESERVED)
158                         error("Input has invalid flags");
159
160                 (void) get_byte();      /* Get timestamp */
161                 (void) get_byte();
162                 (void) get_byte();
163                 (void) get_byte();
164
165                 (void) get_byte();      /* Ignore extra flags for the moment */
166                 (void) get_byte();      /* Ignore OS type for the moment */
167
168                 if (flags & EXTRA_FIELD) {
169                         unsigned len = get_byte();
170                         len |= get_byte() << 8;
171                         while (len--)
172                                 (void) get_byte();
173                 }
174
175                 /* Discard file comment if any */
176                 if (flags & COMMENT)
177                         while (get_byte())
178                                 continue;
179
180         } else if (memcmp(magic, PKZIP_MAGIC, 2) == 0 && inptr == 2
181             && memcmp(inbuf, PKZIP_MAGIC, 4) == 0) {
182                 /*
183                  * To simplify the code, we support a zip file when alone only.
184                  * We are thus guaranteed that the entire local header fits in inbuf.
185                  */
186                 inptr = 0;
187                 check_zipfile();
188
189         } else if (memcmp(magic, PACK_MAGIC, 2) == 0)
190                 error("packed input");
191         else if (memcmp(magic, LZW_MAGIC, 2) == 0)
192                 error("compressed input");
193         if (method == -1)
194                 error("Corrupted input");
195 }
196
197 void
198 decompress_kernel (void *dest)
199 {
200         output_data = dest;
201         output_ptr = 0;
202
203         input_ptr = 0;
204
205         clear_bufs ();
206         makecrc ();
207         get_method ();
208         unzip ();
209 }