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