1 /* util.c -- utility functions for gzip support
3 Copyright (C) 1997, 1998, 1999, 2001, 2002 Free Software Foundation, Inc.
4 Copyright (C) 1992-1993 Jean-loup Gailly
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software Foundation,
18 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
21 static char rcsid[] = "$Id$";
40 #if defined STDC_HEADERS || defined HAVE_STDLIB_H
54 extern ulg crc_32_tab[]; /* crc table, defined below */
56 /* ===========================================================================
57 * Copy input to output unchanged: zcat == cat with --force.
58 * IN assertion: insize bytes have already been read in inbuf.
61 int in, out; /* input and output file descriptors */
64 while (insize != 0 && (int)insize != -1) {
65 write_buf(out, (char*)inbuf, insize);
67 insize = read(in, (char*)inbuf, INBUFSIZ);
69 if ((int)insize == -1) {
76 /* ===========================================================================
77 * Run a set of bytes through the crc shift register. If s is a NULL
78 * pointer, then initialize the crc shift register contents instead.
79 * Return the current crc in either case.
82 uch *s; /* pointer to bytes to pump through */
83 unsigned n; /* number of bytes in s[] */
85 register ulg c; /* temporary variable */
87 static ulg crc = (ulg)0xffffffffL; /* shift register contents */
94 c = crc_32_tab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8);
98 return c ^ 0xffffffffL; /* (instead of ~c for 64-bit machines) */
101 /* ===========================================================================
102 * Clear input and output buffers
108 bytes_in = bytes_out = 0L;
111 /* ===========================================================================
112 * Fill the input buffer. This is called only when the buffer is empty.
114 int fill_inbuf(eof_ok)
115 int eof_ok; /* set if EOF acceptable as a result */
119 /* Read as much as possible */
122 len = read(ifd, (char*)inbuf+insize, INBUFSIZ-insize);
129 } while (insize < INBUFSIZ);
132 if (eof_ok) return EOF;
137 bytes_in += (off_t)insize;
142 /* ===========================================================================
143 * Write the output buffer outbuf[0..outcnt-1] and update bytes_out.
144 * (used for the compressed data only)
148 if (outcnt == 0) return;
150 write_buf(ofd, (char *)outbuf, outcnt);
151 bytes_out += (off_t)outcnt;
155 /* ===========================================================================
156 * Write the output window window[0..outcnt-1] and update crc and bytes_out.
157 * (Used for the decompressed data only.)
161 if (outcnt == 0) return;
162 updcrc(window, outcnt);
165 write_buf(ofd, (char *)window, outcnt);
167 bytes_out += (off_t)outcnt;
171 /* ===========================================================================
172 * Does the same as write(), but also handles partial pipe writes and checks
175 void write_buf(fd, buf, cnt)
182 while ((n = write(fd, buf, cnt)) != cnt) {
183 if (n == (unsigned)(-1)) {
187 buf = (voidp)((char*)buf+n);
191 /* ========================================================================
192 * Put string s in lower case, return s.
199 *t = tolow ((unsigned char) *t);
203 /* ========================================================================
204 * Return the base name of a file (remove any directory prefix and
205 * any version suffix). For systems with file names that are not
206 * case sensitive, force the base name to lower case.
209 gzip_base_name (fname)
214 if ((p = strrchr(fname, PATH_SEP)) != NULL) fname = p+1;
216 if ((p = strrchr(fname, PATH_SEP2)) != NULL) fname = p+1;
219 if ((p = strrchr(fname, PATH_SEP3)) != NULL) fname = p+1;
222 if ((p = strrchr(fname, SUFFIX_SEP)) != NULL) *p = '\0';
224 if (casemap('A') == 'a') strlwr(fname);
228 /* ========================================================================
229 * Unlink a file, working around the unlink readonly bug (if present).
231 int xunlink (filename)
234 int r = unlink (filename);
236 #ifdef UNLINK_READONLY_BUG
240 if (chmod (filename, S_IWUSR) != 0)
246 r = unlink (filename);
253 /* ========================================================================
254 * Make a file name legal for file systems not allowing file names with
255 * multiple dots or starting with a dot (such as MSDOS), by changing
256 * all dots except the last one into underlines. A target dependent
257 * function can be used instead of this simple function by defining the macro
258 * MAKE_LEGAL_NAME in tailor.h and providing the function in a target
261 void make_simple_name(name)
264 char *p = strrchr(name, '.');
265 if (p == NULL) return;
268 if (*--p == '.') *p = '_';
273 #if !defined HAVE_STRING_H && !defined STDC_HEADERS
275 /* Provide missing strspn and strcspn functions. */
281 int strspn OF((const char *s, const char *accept));
282 int strcspn OF((const char *s, const char *reject));
284 /* ========================================================================
285 * Return the length of the maximum initial segment
286 * of s which contains only characters in accept.
288 int strspn(s, accept)
292 register const char *p;
293 register const char *a;
294 register int count = 0;
296 for (p = s; *p != '\0'; ++p) {
297 for (a = accept; *a != '\0'; ++a) {
300 if (*a == '\0') return count;
306 /* ========================================================================
307 * Return the length of the maximum inital segment of s
308 * which contains no characters from reject.
310 int strcspn(s, reject)
314 register int count = 0;
317 if (strchr(reject, *s++) != NULL) return count;
325 /* ========================================================================
326 * Add an environment variable (if any) before argv, and update argc.
327 * Return the expanded environment variable to be freed later, or NULL
328 * if no options were added to argv.
330 #define SEPARATOR " \t" /* separators in env variable */
332 char *add_envopt(argcp, argvp, env)
333 int *argcp; /* pointer to argc */
334 char ***argvp; /* pointer to argv */
335 char *env; /* name of environment variable */
337 char *p; /* running pointer through env variable */
338 char **oargv; /* runs through old argv array */
339 char **nargv; /* runs through new argv array */
340 int oargc = *argcp; /* old argc */
341 int nargc = 0; /* number of arguments in env variable */
343 env = (char*)getenv(env);
344 if (env == NULL) return NULL;
348 for (p = env; *p; nargc++ ) { /* move through env */
349 p += strspn(p, SEPARATOR); /* skip leading separators */
350 if (*p == '\0') break;
352 p += strcspn(p, SEPARATOR); /* find end of word */
353 if (*p) *p++ = '\0'; /* mark it */
360 /* Allocate the new argv array, with an extra element just in case
361 * the original arg list did not end with a NULL.
363 nargv = (char **) xcalloc (*argcp + 1, sizeof (char *));
367 /* Copy the program name first */
369 gzip_error ("argc<=0");
370 *(nargv++) = *(oargv++);
372 /* Then copy the environment args */
373 for (p = env; nargc > 0; nargc--) {
374 p += strspn(p, SEPARATOR); /* skip separators */
375 *(nargv++) = p; /* store start */
376 while (*p++) ; /* skip over word */
379 /* Finally copy the old args and add a NULL (usual convention) */
380 while (oargc--) *(nargv++) = *(oargv++);
385 /* ========================================================================
392 fprintf (stderr, "\n%s: %s: %s\n", program_name, ifname, m);
399 fprintf (stderr, "\n%s: memory_exhausted\n", program_name);
406 WARN ((stderr, "%s: %s: warning: %s\n", program_name, ifname, m));
412 fprintf (stderr, "\n%s: ", program_name);
417 fprintf(stderr, "%s: unexpected end of file\n", ifname);
425 fprintf (stderr, "\n%s: ", program_name);
431 /* ========================================================================
432 * Display compression ratio on the given stream on 6 characters.
434 void display_ratio(num, den, file)
439 fprintf(file, "%5.1f%%", den == 0 ? 0 : 100.0 * num / den);
442 /* ========================================================================
443 * Print an off_t. There's no completely portable way to use printf,
444 * so we do it ourselves.
446 void fprint_off(file, offset, width)
451 char buf[CHAR_BIT * sizeof (off_t)];
452 char *p = buf + sizeof buf;
454 /* Don't negate offset here; it might overflow. */
457 *--p = '0' - offset % 10;
458 while ((offset /= 10) != 0);
463 *--p = '0' + offset % 10;
464 while ((offset /= 10) != 0);
467 width -= buf + sizeof buf - p;
468 while (0 < width--) {
471 for (; p < buf + sizeof buf; p++)
475 /* ========================================================================
476 * Table of CRC-32's of all single-byte values (made by makecrc.c)
479 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
480 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
481 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
482 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
483 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
484 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
485 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
486 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
487 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
488 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
489 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
490 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
491 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
492 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
493 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
494 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
495 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
496 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
497 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
498 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
499 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
500 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
501 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
502 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
503 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
504 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
505 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
506 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
507 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
508 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
509 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
510 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
511 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
512 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
513 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
514 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
515 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
516 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
517 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
518 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
519 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
520 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
521 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
522 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
523 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
524 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
525 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
526 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
527 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
528 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
529 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,