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