gzip 1.2.4
[debian/gzip] / util.c
1 /* util.c -- utility functions for gzip support
2  * Copyright (C) 1992-1993 Jean-loup Gailly
3  * This is free software; you can redistribute it and/or modify it under the
4  * terms of the GNU General Public License, see the file COPYING.
5  */
6
7 #ifdef RCSID
8 static char rcsid[] = "$Id$";
9 #endif
10
11 #include <ctype.h>
12 #include <errno.h>
13 #include <sys/types.h>
14
15 #include "tailor.h"
16
17 #ifdef HAVE_UNISTD_H
18 #  include <unistd.h>
19 #endif
20 #ifndef NO_FCNTL_H
21 #  include <fcntl.h>
22 #endif
23
24 #if defined(STDC_HEADERS) || !defined(NO_STDLIB_H)
25 #  include <stdlib.h>
26 #else
27    extern int errno;
28 #endif
29
30 #include "gzip.h"
31 #include "crypt.h"
32
33 extern ulg crc_32_tab[];   /* crc table, defined below */
34
35 /* ===========================================================================
36  * Copy input to output unchanged: zcat == cat with --force.
37  * IN assertion: insize bytes have already been read in inbuf.
38  */
39 int copy(in, out)
40     int in, out;   /* input and output file descriptors */
41 {
42     errno = 0;
43     while (insize != 0 && (int)insize != EOF) {
44         write_buf(out, (char*)inbuf, insize);
45         bytes_out += insize;
46         insize = read(in, (char*)inbuf, INBUFSIZ);
47     }
48     if ((int)insize == EOF && errno != 0) {
49         read_error();
50     }
51     bytes_in = bytes_out;
52     return OK;
53 }
54
55 /* ===========================================================================
56  * Run a set of bytes through the crc shift register.  If s is a NULL
57  * pointer, then initialize the crc shift register contents instead.
58  * Return the current crc in either case.
59  */
60 ulg updcrc(s, n)
61     uch *s;                 /* pointer to bytes to pump through */
62     unsigned n;             /* number of bytes in s[] */
63 {
64     register ulg c;         /* temporary variable */
65
66     static ulg crc = (ulg)0xffffffffL; /* shift register contents */
67
68     if (s == NULL) {
69         c = 0xffffffffL;
70     } else {
71         c = crc;
72         if (n) do {
73             c = crc_32_tab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8);
74         } while (--n);
75     }
76     crc = c;
77     return c ^ 0xffffffffL;       /* (instead of ~c for 64-bit machines) */
78 }
79
80 /* ===========================================================================
81  * Clear input and output buffers
82  */
83 void clear_bufs()
84 {
85     outcnt = 0;
86     insize = inptr = 0;
87     bytes_in = bytes_out = 0L;
88 }
89
90 /* ===========================================================================
91  * Fill the input buffer. This is called only when the buffer is empty.
92  */
93 int fill_inbuf(eof_ok)
94     int eof_ok;          /* set if EOF acceptable as a result */
95 {
96     int len;
97
98     /* Read as much as possible */
99     insize = 0;
100     errno = 0;
101     do {
102         len = read(ifd, (char*)inbuf+insize, INBUFSIZ-insize);
103         if (len == 0 || len == EOF) break;
104         insize += len;
105     } while (insize < INBUFSIZ);
106
107     if (insize == 0) {
108         if (eof_ok) return EOF;
109         read_error();
110     }
111     bytes_in += (ulg)insize;
112     inptr = 1;
113     return inbuf[0];
114 }
115
116 /* ===========================================================================
117  * Write the output buffer outbuf[0..outcnt-1] and update bytes_out.
118  * (used for the compressed data only)
119  */
120 void flush_outbuf()
121 {
122     if (outcnt == 0) return;
123
124     write_buf(ofd, (char *)outbuf, outcnt);
125     bytes_out += (ulg)outcnt;
126     outcnt = 0;
127 }
128
129 /* ===========================================================================
130  * Write the output window window[0..outcnt-1] and update crc and bytes_out.
131  * (Used for the decompressed data only.)
132  */
133 void flush_window()
134 {
135     if (outcnt == 0) return;
136     updcrc(window, outcnt);
137
138     if (!test) {
139         write_buf(ofd, (char *)window, outcnt);
140     }
141     bytes_out += (ulg)outcnt;
142     outcnt = 0;
143 }
144
145 /* ===========================================================================
146  * Does the same as write(), but also handles partial pipe writes and checks
147  * for error return.
148  */
149 void write_buf(fd, buf, cnt)
150     int       fd;
151     voidp     buf;
152     unsigned  cnt;
153 {
154     unsigned  n;
155
156     while ((n = write(fd, buf, cnt)) != cnt) {
157         if (n == (unsigned)(-1)) {
158             write_error();
159         }
160         cnt -= n;
161         buf = (voidp)((char*)buf+n);
162     }
163 }
164
165 /* ========================================================================
166  * Put string s in lower case, return s.
167  */
168 char *strlwr(s)
169     char *s;
170 {
171     char *t;
172     for (t = s; *t; t++) *t = tolow(*t);
173     return s;
174 }
175
176 /* ========================================================================
177  * Return the base name of a file (remove any directory prefix and
178  * any version suffix). For systems with file names that are not
179  * case sensitive, force the base name to lower case.
180  */
181 char *basename(fname)
182     char *fname;
183 {
184     char *p;
185
186     if ((p = strrchr(fname, PATH_SEP))  != NULL) fname = p+1;
187 #ifdef PATH_SEP2
188     if ((p = strrchr(fname, PATH_SEP2)) != NULL) fname = p+1;
189 #endif
190 #ifdef PATH_SEP3
191     if ((p = strrchr(fname, PATH_SEP3)) != NULL) fname = p+1;
192 #endif
193 #ifdef SUFFIX_SEP
194     if ((p = strrchr(fname, SUFFIX_SEP)) != NULL) *p = '\0';
195 #endif
196     if (casemap('A') == 'a') strlwr(fname);
197     return fname;
198 }
199
200 /* ========================================================================
201  * Make a file name legal for file systems not allowing file names with
202  * multiple dots or starting with a dot (such as MSDOS), by changing
203  * all dots except the last one into underlines.  A target dependent
204  * function can be used instead of this simple function by defining the macro
205  * MAKE_LEGAL_NAME in tailor.h and providing the function in a target
206  * dependent module.
207  */
208 void make_simple_name(name)
209     char *name;
210 {
211     char *p = strrchr(name, '.');
212     if (p == NULL) return;
213     if (p == name) p++;
214     do {
215         if (*--p == '.') *p = '_';
216     } while (p != name);
217 }
218
219
220 #if defined(NO_STRING_H) && !defined(STDC_HEADERS)
221
222 /* Provide missing strspn and strcspn functions. */
223
224 #  ifndef __STDC__
225 #    define const
226 #  endif
227
228 int strspn  OF((const char *s, const char *accept));
229 int strcspn OF((const char *s, const char *reject));
230
231 /* ========================================================================
232  * Return the length of the maximum initial segment
233  * of s which contains only characters in accept.
234  */
235 int strspn(s, accept)
236     const char *s;
237     const char *accept;
238 {
239     register const char *p;
240     register const char *a;
241     register int count = 0;
242
243     for (p = s; *p != '\0'; ++p) {
244         for (a = accept; *a != '\0'; ++a) {
245             if (*p == *a) break;
246         }
247         if (*a == '\0') return count;
248         ++count;
249     }
250     return count;
251 }
252
253 /* ========================================================================
254  * Return the length of the maximum inital segment of s
255  * which contains no characters from reject.
256  */
257 int strcspn(s, reject)
258     const char *s;
259     const char *reject;
260 {
261     register int count = 0;
262
263     while (*s != '\0') {
264         if (strchr(reject, *s++) != NULL) return count;
265         ++count;
266     }
267     return count;
268 }
269
270 #endif /* NO_STRING_H */
271
272 /* ========================================================================
273  * Add an environment variable (if any) before argv, and update argc.
274  * Return the expanded environment variable to be freed later, or NULL 
275  * if no options were added to argv.
276  */
277 #define SEPARATOR       " \t"   /* separators in env variable */
278
279 char *add_envopt(argcp, argvp, env)
280     int *argcp;          /* pointer to argc */
281     char ***argvp;       /* pointer to argv */
282     char *env;           /* name of environment variable */
283 {
284     char *p;             /* running pointer through env variable */
285     char **oargv;        /* runs through old argv array */
286     char **nargv;        /* runs through new argv array */
287     int  oargc = *argcp; /* old argc */
288     int  nargc = 0;      /* number of arguments in env variable */
289
290     env = (char*)getenv(env);
291     if (env == NULL) return NULL;
292
293     p = (char*)xmalloc(strlen(env)+1);
294     env = strcpy(p, env);                    /* keep env variable intact */
295
296     for (p = env; *p; nargc++ ) {            /* move through env */
297         p += strspn(p, SEPARATOR);           /* skip leading separators */
298         if (*p == '\0') break;
299
300         p += strcspn(p, SEPARATOR);          /* find end of word */
301         if (*p) *p++ = '\0';                 /* mark it */
302     }
303     if (nargc == 0) {
304         free(env);
305         return NULL;
306     }
307     *argcp += nargc;
308     /* Allocate the new argv array, with an extra element just in case
309      * the original arg list did not end with a NULL.
310      */
311     nargv = (char**)calloc(*argcp+1, sizeof(char *));
312     if (nargv == NULL) error("out of memory");
313     oargv  = *argvp;
314     *argvp = nargv;
315
316     /* Copy the program name first */
317     if (oargc-- < 0) error("argc<=0");
318     *(nargv++) = *(oargv++);
319
320     /* Then copy the environment args */
321     for (p = env; nargc > 0; nargc--) {
322         p += strspn(p, SEPARATOR);           /* skip separators */
323         *(nargv++) = p;                      /* store start */
324         while (*p++) ;                       /* skip over word */
325     }
326
327     /* Finally copy the old args and add a NULL (usual convention) */
328     while (oargc--) *(nargv++) = *(oargv++);
329     *nargv = NULL;
330     return env;
331 }
332
333 /* ========================================================================
334  * Error handlers.
335  */
336 void error(m)
337     char *m;
338 {
339     fprintf(stderr, "\n%s: %s: %s\n", progname, ifname, m);
340     abort_gzip();
341 }
342
343 void warn(a, b)
344     char *a, *b;            /* message strings juxtaposed in output */
345 {
346     WARN((stderr, "%s: %s: warning: %s%s\n", progname, ifname, a, b));
347 }
348
349 void read_error()
350 {
351     fprintf(stderr, "\n%s: ", progname);
352     if (errno != 0) {
353         perror(ifname);
354     } else {
355         fprintf(stderr, "%s: unexpected end of file\n", ifname);
356     }
357     abort_gzip();
358 }
359
360 void write_error()
361 {
362     fprintf(stderr, "\n%s: ", progname);
363     perror(ofname);
364     abort_gzip();
365 }
366
367 /* ========================================================================
368  * Display compression ratio on the given stream on 6 characters.
369  */
370 void display_ratio(num, den, file)
371     long num;
372     long den;
373     FILE *file;
374 {
375     long ratio;  /* 1000 times the compression ratio */
376
377     if (den == 0) {
378         ratio = 0; /* no compression */
379     } else if (den < 2147483L) { /* (2**31 -1)/1000 */
380         ratio = 1000L*num/den;
381     } else {
382         ratio = num/(den/1000L);
383     }
384     if (ratio < 0) {
385         putc('-', file);
386         ratio = -ratio;
387     } else {
388         putc(' ', file);
389     }
390     fprintf(file, "%2ld.%1ld%%", ratio / 10L, ratio % 10L);
391 }
392
393
394 /* ========================================================================
395  * Semi-safe malloc -- never returns NULL.
396  */
397 voidp xmalloc (size)
398     unsigned size;
399 {
400     voidp cp = (voidp)malloc (size);
401
402     if (cp == NULL) error("out of memory");
403     return cp;
404 }
405
406 /* ========================================================================
407  * Table of CRC-32's of all single-byte values (made by makecrc.c)
408  */
409 ulg crc_32_tab[] = {
410   0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
411   0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
412   0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
413   0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
414   0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
415   0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
416   0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
417   0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
418   0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
419   0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
420   0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
421   0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
422   0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
423   0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
424   0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
425   0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
426   0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
427   0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
428   0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
429   0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
430   0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
431   0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
432   0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
433   0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
434   0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
435   0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
436   0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
437   0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
438   0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
439   0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
440   0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
441   0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
442   0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
443   0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
444   0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
445   0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
446   0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
447   0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
448   0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
449   0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
450   0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
451   0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
452   0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
453   0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
454   0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
455   0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
456   0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
457   0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
458   0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
459   0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
460   0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
461   0x2d02ef8dL
462 };