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