1 /* gzcompress.h -- definitions for the .Z decompression routine used in CFITSIO */
2 
3 #include <stdlib.h>
4 #include <stdio.h>
5 #include <string.h>
6 #include <ctype.h>
7 
8 #define get_char() get_byte()
9 
10 /* gzip.h -- common declarations for all gzip modules  */
11 
12 #define OF(args)  args
13 typedef void *voidp;
14 
15 #define memzero(s, n)     memset ((voidp)(s), 0, (n))
16 
17 typedef unsigned char  uch;
18 typedef unsigned short ush;
19 typedef unsigned long  ulg;
20 
21 /* private version of MIN function */
22 #define MINZIP(a,b) ((a) <= (b) ? (a) : (b))
23 
24 /* Return codes from gzip */
25 #define OK      0
26 #define ERROR   1
27 #define COMPRESSED  1
28 #define DEFLATED    8
29 #define INBUFSIZ  0x8000    /* input buffer size */
30 #define INBUF_EXTRA  64     /* required by unlzw() */
31 #define OUTBUFSIZ  16384    /* output buffer size */
32 #define OUTBUF_EXTRA 2048   /* required by unlzw() */
33 #define DIST_BUFSIZE 0x8000 /* buffer for distances, see trees.c */
34 #define WSIZE 0x8000        /* window size--must be a power of two, and */
35 #define DECLARE(type, array, size)  type array[size]
36 #define tab_suffix window
37 #define tab_prefix prev    /* hash link (see deflate.c) */
38 #define head (prev+WSIZE)  /* hash head (see deflate.c) */
39 #define	LZW_MAGIC      "\037\235" /* Magic header for lzw files, 1F 9D */
40 #define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf(0))
41 
42 /* Diagnostic functions */
43 #  define Assert(cond,msg)
44 #  define Trace(x)
45 #  define Tracev(x)
46 #  define Tracevv(x)
47 #  define Tracec(c,x)
48 #  define Tracecv(c,x)
49 
50 /* lzw.h -- define the lzw functions. */
51 
52 #ifndef BITS
53 #  define BITS 16
54 #endif
55 #define INIT_BITS 9              /* Initial number of bits per code */
56 #define BIT_MASK    0x1f /* Mask for 'number of compression bits' */
57 #define BLOCK_MODE  0x80
58 #define LZW_RESERVED 0x60 /* reserved bits */
59 #define	CLEAR  256       /* flush the dictionary */
60 #define FIRST  (CLEAR+1) /* first free entry */
61 
62 /* prototypes */
63 
64 #define local static
65 void ffpmsg(const char *err_message);
66 
67 local int  fill_inbuf    OF((int eof_ok));
68 local void write_buf     OF((voidp buf, unsigned cnt));
69 local void error         OF((char *m));
70 local int unlzw  OF((FILE *in, FILE *out));
71 
72 typedef int file_t;     /* Do not use stdio */
73 
74 int (*work) OF((FILE *infile, FILE *outfile)) = unlzw; /* function to call */
75 
76 local void error         OF((char *m));
77 
78 		/* global buffers */
79 
80 static DECLARE(uch, inbuf,  INBUFSIZ +INBUF_EXTRA);
81 static DECLARE(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA);
82 static DECLARE(ush, d_buf,  DIST_BUFSIZE);
83 static DECLARE(uch, window, 2L*WSIZE);
84 
85 #ifndef MAXSEG_64K
86     static DECLARE(ush, tab_prefix, 1L<<BITS);
87 #else
88     static DECLARE(ush, tab_prefix0, 1L<<(BITS-1));
89     static DECLARE(ush, tab_prefix1, 1L<<(BITS-1));
90 #endif
91 
92 		/* local variables */
93 
94 /* 11/25/98: added 'static' to local variable definitions, to avoid */
95 /* conflict with external source files */
96 
97 static int maxbits = BITS;   /* max bits per code for LZW */
98 static int method = DEFLATED;/* compression method */
99 static int exit_code = OK;   /* program exit code */
100 static int last_member;      /* set for .zip and .Z files */
101 static long bytes_in;             /* number of input bytes */
102 static long bytes_out;            /* number of output bytes */
103 static char ifname[128];          /* input file name */
104 static FILE *ifd;               /* input file descriptor */
105 static FILE *ofd;               /* output file descriptor */
106 static void **memptr;          /* memory location for uncompressed file */
107 static size_t *memsize;        /* size (bytes) of memory allocated for file */
108 void *(*realloc_fn)(void *p, size_t newsize);  /* reallocation function */
109 static unsigned insize;     /* valid bytes in inbuf */
110 static unsigned inptr;      /* index of next byte to be processed in inbuf */
111 
112 /* prototype for the following functions */
113 int zuncompress2mem(char *filename,
114              FILE *diskfile,
115              char **buffptr,
116              size_t *buffsize,
117              void *(*mem_realloc)(void *p, size_t newsize),
118              size_t *filesize,
119              int *status);
120 
121 /*--------------------------------------------------------------------------*/
zuncompress2mem(char * filename,FILE * indiskfile,char ** buffptr,size_t * buffsize,void * (* mem_realloc)(void * p,size_t newsize),size_t * filesize,int * status)122 int zuncompress2mem(char *filename,  /* name of input file                 */
123              FILE *indiskfile,     /* I - file pointer                        */
124              char **buffptr,   /* IO - memory pointer                     */
125              size_t *buffsize,   /* IO - size of buffer, in bytes           */
126              void *(*mem_realloc)(void *p, size_t newsize), /* function     */
127              size_t *filesize,   /* O - size of file, in bytes              */
128              int *status)        /* IO - error status                       */
129 
130 /*
131   Uncompress the file into memory.  Fill whatever amount of memory has
132   already been allocated, then realloc more memory, using the supplied
133   input function, if necessary.
134 */
135 {
136     char magic[2]; /* magic header */
137 
138     if (*status > 0)
139         return(*status);
140 
141     /*  save input parameters into global variables */
142     ifname[0] = '\0';
143     strncat(ifname, filename, 127);
144     ifd = indiskfile;
145     memptr = (void **) buffptr;
146     memsize = buffsize;
147     realloc_fn = mem_realloc;
148 
149     /* clear input and output buffers */
150 
151     insize = inptr = 0;
152     bytes_in = bytes_out = 0L;
153 
154     magic[0] = (char)get_byte();
155     magic[1] = (char)get_byte();
156 
157     if (memcmp(magic, LZW_MAGIC, 2) != 0) {
158       error("ERROR: input .Z file is in unrecognized compression format.\n");
159       return(-1);
160     }
161 
162     work = unlzw;
163     method = COMPRESSED;
164     last_member = 1;
165 
166     /* do the uncompression */
167     if ((*work)(ifd, ofd) != OK) {
168         method = -1; /* force cleanup */
169         *status = 414;    /* report some sort of decompression error */
170     }
171 
172     if (filesize)  *filesize = bytes_out;
173 
174     return(*status);
175 }
176 /*=========================================================================*/
177 /*=========================================================================*/
178 /* this marks the begining of the original file 'unlzw.c'                  */
179 /*=========================================================================*/
180 /*=========================================================================*/
181 
182 /* unlzw.c -- decompress files in LZW format.
183  * The code in this file is directly derived from the public domain 'compress'
184  * written by Spencer Thomas, Joe Orost, James Woods, Jim McKie, Steve Davies,
185  * Ken Turkowski, Dave Mack and Peter Jannesen.
186  */
187 
188 typedef	unsigned char	char_type;
189 typedef          long   code_int;
190 typedef unsigned long 	count_int;
191 typedef unsigned short	count_short;
192 typedef unsigned long 	cmp_code_int;
193 
194 #define MAXCODE(n)	(1L << (n))
195 
196 #ifndef	REGISTERS
197 #	define	REGISTERS	2
198 #endif
199 #define	REG1
200 #define	REG2
201 #define	REG3
202 #define	REG4
203 #define	REG5
204 #define	REG6
205 #define	REG7
206 #define	REG8
207 #define	REG9
208 #define	REG10
209 #define	REG11
210 #define	REG12
211 #define	REG13
212 #define	REG14
213 #define	REG15
214 #define	REG16
215 #if REGISTERS >= 1
216 #	undef	REG1
217 #	define	REG1	register
218 #endif
219 #if REGISTERS >= 2
220 #	undef	REG2
221 #	define	REG2	register
222 #endif
223 #if REGISTERS >= 3
224 #	undef	REG3
225 #	define	REG3	register
226 #endif
227 #if REGISTERS >= 4
228 #	undef	REG4
229 #	define	REG4	register
230 #endif
231 #if REGISTERS >= 5
232 #	undef	REG5
233 #	define	REG5	register
234 #endif
235 #if REGISTERS >= 6
236 #	undef	REG6
237 #	define	REG6	register
238 #endif
239 #if REGISTERS >= 7
240 #	undef	REG7
241 #	define	REG7	register
242 #endif
243 #if REGISTERS >= 8
244 #	undef	REG8
245 #	define	REG8	register
246 #endif
247 #if REGISTERS >= 9
248 #	undef	REG9
249 #	define	REG9	register
250 #endif
251 #if REGISTERS >= 10
252 #	undef	REG10
253 #	define	REG10	register
254 #endif
255 #if REGISTERS >= 11
256 #	undef	REG11
257 #	define	REG11	register
258 #endif
259 #if REGISTERS >= 12
260 #	undef	REG12
261 #	define	REG12	register
262 #endif
263 #if REGISTERS >= 13
264 #	undef	REG13
265 #	define	REG13	register
266 #endif
267 #if REGISTERS >= 14
268 #	undef	REG14
269 #	define	REG14	register
270 #endif
271 #if REGISTERS >= 15
272 #	undef	REG15
273 #	define	REG15	register
274 #endif
275 #if REGISTERS >= 16
276 #	undef	REG16
277 #	define	REG16	register
278 #endif
279 
280 #ifndef	BYTEORDER
281 #	define	BYTEORDER	0000
282 #endif
283 
284 #ifndef	NOALLIGN
285 #	define	NOALLIGN	0
286 #endif
287 
288 
289 union	bytes {
290     long  word;
291     struct {
292 #if BYTEORDER == 4321
293 	char_type	b1;
294 	char_type	b2;
295 	char_type	b3;
296 	char_type	b4;
297 #else
298 #if BYTEORDER == 1234
299 	char_type	b4;
300 	char_type	b3;
301 	char_type	b2;
302 	char_type	b1;
303 #else
304 #	undef	BYTEORDER
305 	int  dummy;
306 #endif
307 #endif
308     } bytes;
309 };
310 
311 #if BYTEORDER == 4321 && NOALLIGN == 1
312 #  define input(b,o,c,n,m){ \
313      (c) = (*(long *)(&(b)[(o)>>3])>>((o)&0x7))&(m); \
314      (o) += (n); \
315    }
316 #else
317 #  define input(b,o,c,n,m){ \
318      REG1 char_type *p = &(b)[(o)>>3]; \
319      (c) = ((((long)(p[0]))|((long)(p[1])<<8)| \
320      ((long)(p[2])<<16))>>((o)&0x7))&(m); \
321      (o) += (n); \
322    }
323 #endif
324 
325 #ifndef MAXSEG_64K
326    /* DECLARE(ush, tab_prefix, (1<<BITS)); -- prefix code */
327 #  define tab_prefixof(i) tab_prefix[i]
328 #  define clear_tab_prefixof()	memzero(tab_prefix, 256);
329 #else
330    /* DECLARE(ush, tab_prefix0, (1<<(BITS-1)); -- prefix for even codes */
331    /* DECLARE(ush, tab_prefix1, (1<<(BITS-1)); -- prefix for odd  codes */
332    ush *tab_prefix[2];
333 #  define tab_prefixof(i) tab_prefix[(i)&1][(i)>>1]
334 #  define clear_tab_prefixof()	\
335       memzero(tab_prefix0, 128), \
336       memzero(tab_prefix1, 128);
337 #endif
338 #define de_stack        ((char_type *)(&d_buf[DIST_BUFSIZE-1]))
339 #define tab_suffixof(i) tab_suffix[i]
340 
341 int block_mode = BLOCK_MODE; /* block compress mode -C compatible with 2.0 */
342 
343 /* ============================================================================
344  * Decompress in to out.  This routine adapts to the codes in the
345  * file building the "string" table on-the-fly; requiring no table to
346  * be stored in the compressed file.
347  * IN assertions: the buffer inbuf contains already the beginning of
348  *   the compressed data, from offsets iptr to insize-1 included.
349  *   The magic header has already been checked and skipped.
350  *   bytes_in and bytes_out have been initialized.
351  */
unlzw(FILE * in,FILE * out)352 local int unlzw(FILE *in, FILE *out)
353     /* input and output file descriptors */
354 {
355     REG2   char_type  *stackp;
356     REG3   code_int   code;
357     REG4   int        finchar;
358     REG5   code_int   oldcode;
359     REG6   code_int   incode;
360     REG7   long       inbits;
361     REG8   long       posbits;
362     REG9   int        outpos;
363 /*  REG10  int        insize; (global) */
364     REG11  unsigned   bitmask;
365     REG12  code_int   free_ent;
366     REG13  code_int   maxcode;
367     REG14  code_int   maxmaxcode;
368     REG15  int        n_bits;
369     REG16  int        rsize;
370 
371     ofd = out;
372 
373 #ifdef MAXSEG_64K
374     tab_prefix[0] = tab_prefix0;
375     tab_prefix[1] = tab_prefix1;
376 #endif
377     maxbits = get_byte();
378     block_mode = maxbits & BLOCK_MODE;
379     if ((maxbits & LZW_RESERVED) != 0) {
380 	error( "warning, unknown flags in unlzw decompression");
381     }
382     maxbits &= BIT_MASK;
383     maxmaxcode = MAXCODE(maxbits);
384 
385     if (maxbits > BITS) {
386 	error("compressed with too many bits; cannot handle file");
387 	exit_code = ERROR;
388 	return ERROR;
389     }
390     rsize = insize;
391     maxcode = MAXCODE(n_bits = INIT_BITS)-1;
392     bitmask = (1<<n_bits)-1;
393     oldcode = -1;
394     finchar = 0;
395     outpos = 0;
396     posbits = inptr<<3;
397 
398     free_ent = ((block_mode) ? FIRST : 256);
399 
400     clear_tab_prefixof(); /* Initialize the first 256 entries in the table. */
401 
402     for (code = 255 ; code >= 0 ; --code) {
403 	tab_suffixof(code) = (char_type)code;
404     }
405     do {
406 	REG1 int i;
407 	int  e;
408 	int  o;
409 
410     resetbuf:
411 	e = insize-(o = (posbits>>3));
412 
413 	for (i = 0 ; i < e ; ++i) {
414 	    inbuf[i] = inbuf[i+o];
415 	}
416 	insize = e;
417 	posbits = 0;
418 
419 	if (insize < INBUF_EXTRA) {
420 /*  modified to use fread instead of read - WDP 10/22/97  */
421 /*	    if ((rsize = read(in, (char*)inbuf+insize, INBUFSIZ)) == EOF) { */
422 
423 	    if ((rsize = fread((char*)inbuf+insize, 1, INBUFSIZ, in)) == EOF) {
424 		error("unexpected end of file");
425 	        exit_code = ERROR;
426                 return ERROR;
427 	    }
428 	    insize += rsize;
429 	    bytes_in += (ulg)rsize;
430 	}
431 	inbits = ((rsize != 0) ? ((long)insize - insize%n_bits)<<3 :
432 		  ((long)insize<<3)-(n_bits-1));
433 
434 	while (inbits > posbits) {
435 	    if (free_ent > maxcode) {
436 		posbits = ((posbits-1) +
437 			   ((n_bits<<3)-(posbits-1+(n_bits<<3))%(n_bits<<3)));
438 		++n_bits;
439 		if (n_bits == maxbits) {
440 		    maxcode = maxmaxcode;
441 		} else {
442 		    maxcode = MAXCODE(n_bits)-1;
443 		}
444 		bitmask = (1<<n_bits)-1;
445 		goto resetbuf;
446 	    }
447 	    input(inbuf,posbits,code,n_bits,bitmask);
448 	    Tracev((stderr, "%d ", code));
449 
450 	    if (oldcode == -1) {
451 		if (code >= 256) {
452                     error("corrupt input.");
453 	            exit_code = ERROR;
454                     return ERROR;
455                 }
456 
457 		outbuf[outpos++] = (char_type)(finchar = (int)(oldcode=code));
458 		continue;
459 	    }
460 	    if (code == CLEAR && block_mode) {
461 		clear_tab_prefixof();
462 		free_ent = FIRST - 1;
463 		posbits = ((posbits-1) +
464 			   ((n_bits<<3)-(posbits-1+(n_bits<<3))%(n_bits<<3)));
465 		maxcode = MAXCODE(n_bits = INIT_BITS)-1;
466 		bitmask = (1<<n_bits)-1;
467 		goto resetbuf;
468 	    }
469 	    incode = code;
470 	    stackp = de_stack;
471 
472 	    if (code >= free_ent) { /* Special case for KwKwK string. */
473 		if (code > free_ent) {
474 		    if (outpos > 0) {
475 			write_buf((char*)outbuf, outpos);
476 			bytes_out += (ulg)outpos;
477 		    }
478 		    error("corrupt input.");
479 	            exit_code = ERROR;
480                     return ERROR;
481 
482 		}
483 		*--stackp = (char_type)finchar;
484 		code = oldcode;
485 	    }
486 
487 	    while ((cmp_code_int)code >= (cmp_code_int)256) {
488 		/* Generate output characters in reverse order */
489 		*--stackp = tab_suffixof(code);
490 		code = tab_prefixof(code);
491 	    }
492 	    *--stackp =	(char_type)(finchar = tab_suffixof(code));
493 
494 	    /* And put them out in forward order */
495 	    {
496 	/*	REG1 int	i;   already defined above (WDP) */
497 
498 		if (outpos+(i = (de_stack-stackp)) >= OUTBUFSIZ) {
499 		    do {
500 			if (i > OUTBUFSIZ-outpos) i = OUTBUFSIZ-outpos;
501 
502 			if (i > 0) {
503 			    memcpy(outbuf+outpos, stackp, i);
504 			    outpos += i;
505 			}
506 			if (outpos >= OUTBUFSIZ) {
507 			    write_buf((char*)outbuf, outpos);
508 			    bytes_out += (ulg)outpos;
509 			    outpos = 0;
510 			}
511 			stackp+= i;
512 		    } while ((i = (de_stack-stackp)) > 0);
513 		} else {
514 		    memcpy(outbuf+outpos, stackp, i);
515 		    outpos += i;
516 		}
517 	    }
518 
519 	    if ((code = free_ent) < maxmaxcode) { /* Generate the new entry. */
520 
521 		tab_prefixof(code) = (unsigned short)oldcode;
522 		tab_suffixof(code) = (char_type)finchar;
523 		free_ent = code+1;
524 	    }
525 	    oldcode = incode;	/* Remember previous code.	*/
526 	}
527     } while (rsize != 0);
528 
529     if (outpos > 0) {
530 	write_buf((char*)outbuf, outpos);
531 	bytes_out += (ulg)outpos;
532     }
533     return OK;
534 }
535 /* ========================================================================*/
536 /* this marks the start of the code from 'util.c'  */
537 
fill_inbuf(int eof_ok)538 local int fill_inbuf(int eof_ok)
539          /* set if EOF acceptable as a result */
540 {
541     int len;
542 
543       /* Read as much as possible from file */
544       insize = 0;
545       do {
546         len = fread((char*)inbuf+insize, 1, INBUFSIZ-insize, ifd);
547         if (len == 0 || len == EOF) break;
548 	insize += len;
549       } while (insize < INBUFSIZ);
550 
551     if (insize == 0) {
552 	if (eof_ok) return EOF;
553 	error("unexpected end of file");
554         exit_code = ERROR;
555         return ERROR;
556     }
557 
558     bytes_in += (ulg)insize;
559     inptr = 1;
560     return inbuf[0];
561 }
562 /* =========================================================================== */
write_buf(voidp buf,unsigned cnt)563 local void write_buf(voidp buf, unsigned cnt)
564 /*              copy buffer into memory; allocate more memory if required*/
565 {
566     if (!realloc_fn)
567     {
568       /* append buffer to file */
569       /* added 'unsigned' to get rid of compiler warning (WDP 1/1/99) */
570       if ((unsigned long) fwrite(buf, 1, cnt, ofd) != cnt)
571       {
572           error
573           ("failed to write buffer to uncompressed output file (write_buf)");
574           exit_code = ERROR;
575           return;
576       }
577     }
578     else
579     {
580       /* get more memory if current buffer is too small */
581       if (bytes_out + cnt > *memsize)
582       {
583         *memptr = realloc_fn(*memptr, bytes_out + cnt);
584         *memsize = bytes_out + cnt;  /* new memory buffer size */
585 
586         if (!(*memptr))
587         {
588             error("malloc failed while uncompressing (write_buf)");
589             exit_code = ERROR;
590             return;
591         }
592       }
593       /* copy  into memory buffer */
594       memcpy((char *) *memptr + bytes_out, (char *) buf, cnt);
595     }
596 }
597 /* ======================================================================== */
error(char * m)598 local void error(char *m)
599 /*                Error handler */
600 {
601     ffpmsg(ifname);
602     ffpmsg(m);
603 }
604