1 /* util.c -- utility functions for gzip support
3 Copyright (C) 1997, 1998, 1999, 2001, 2002, 2006 Free Software
5 Copyright (C) 1992-1993 Jean-loup Gailly
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)
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.
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. */
22 static char rcsid[] = "$Id$";
38 #if defined STDC_HEADERS || defined HAVE_STDLIB_H
52 extern ulg crc_32_tab[]; /* crc table, defined below */
54 /* ===========================================================================
55 * Copy input to output unchanged: zcat == cat with --force.
56 * IN assertion: insize bytes have already been read in inbuf.
59 int in, out; /* input and output file descriptors */
62 while (insize != 0 && (int)insize != -1) {
63 write_buf(out, (char*)inbuf, insize);
65 insize = read(in, (char*)inbuf, INBUFSIZ);
67 if ((int)insize == -1) {
74 /* ===========================================================================
75 * Run a set of bytes through the crc shift register. If s is a NULL
76 * pointer, then initialize the crc shift register contents instead.
77 * Return the current crc in either case.
80 uch *s; /* pointer to bytes to pump through */
81 unsigned n; /* number of bytes in s[] */
83 register ulg c; /* temporary variable */
85 static ulg crc = (ulg)0xffffffffL; /* shift register contents */
92 c = crc_32_tab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8);
96 return c ^ 0xffffffffL; /* (instead of ~c for 64-bit machines) */
99 /* ===========================================================================
100 * Clear input and output buffers
106 bytes_in = bytes_out = 0L;
109 /* ===========================================================================
110 * Fill the input buffer. This is called only when the buffer is empty.
112 int fill_inbuf(eof_ok)
113 int eof_ok; /* set if EOF acceptable as a result */
117 /* Read as much as possible */
120 len = read(ifd, (char*)inbuf+insize, INBUFSIZ-insize);
127 } while (insize < INBUFSIZ);
130 if (eof_ok) return EOF;
135 bytes_in += (off_t)insize;
140 /* ===========================================================================
141 * Write the output buffer outbuf[0..outcnt-1] and update bytes_out.
142 * (used for the compressed data only)
146 if (outcnt == 0) return;
148 write_buf(ofd, (char *)outbuf, outcnt);
149 bytes_out += (off_t)outcnt;
153 /* ===========================================================================
154 * Write the output window window[0..outcnt-1] and update crc and bytes_out.
155 * (Used for the decompressed data only.)
159 if (outcnt == 0) return;
160 updcrc(window, outcnt);
163 write_buf(ofd, (char *)window, outcnt);
165 bytes_out += (off_t)outcnt;
169 /* ===========================================================================
170 * Does the same as write(), but also handles partial pipe writes and checks
173 void write_buf(fd, buf, cnt)
180 while ((n = write(fd, buf, cnt)) != cnt) {
181 if (n == (unsigned)(-1)) {
185 buf = (voidp)((char*)buf+n);
189 /* ========================================================================
190 * Put string s in lower case, return s.
197 *t = tolow ((unsigned char) *t);
201 /* ========================================================================
202 * Return the base name of a file (remove any directory prefix and
203 * any version suffix). For systems with file names that are not
204 * case sensitive, force the base name to lower case.
207 gzip_base_name (fname)
212 if ((p = strrchr(fname, PATH_SEP)) != NULL) fname = p+1;
214 if ((p = strrchr(fname, PATH_SEP2)) != NULL) fname = p+1;
217 if ((p = strrchr(fname, PATH_SEP3)) != NULL) fname = p+1;
220 if ((p = strrchr(fname, SUFFIX_SEP)) != NULL) *p = '\0';
222 if (casemap('A') == 'a') strlwr(fname);
226 /* ========================================================================
227 * Unlink a file, working around the unlink readonly bug (if present).
229 int xunlink (filename)
232 int r = unlink (filename);
234 #ifdef UNLINK_READONLY_BUG
238 if (chmod (filename, S_IWUSR) != 0)
244 r = unlink (filename);
251 /* ========================================================================
252 * Make a file name legal for file systems not allowing file names with
253 * multiple dots or starting with a dot (such as MSDOS), by changing
254 * all dots except the last one into underlines. A target dependent
255 * function can be used instead of this simple function by defining the macro
256 * MAKE_LEGAL_NAME in tailor.h and providing the function in a target
259 void make_simple_name(name)
262 char *p = strrchr(name, '.');
263 if (p == NULL) return;
266 if (*--p == '.') *p = '_';
271 #if !defined HAVE_STRING_H && !defined STDC_HEADERS
273 /* Provide missing strspn and strcspn functions. */
279 int strspn OF((const char *s, const char *accept));
280 int strcspn OF((const char *s, const char *reject));
282 /* ========================================================================
283 * Return the length of the maximum initial segment
284 * of s which contains only characters in accept.
286 int strspn(s, accept)
290 register const char *p;
291 register const char *a;
292 register int count = 0;
294 for (p = s; *p != '\0'; ++p) {
295 for (a = accept; *a != '\0'; ++a) {
298 if (*a == '\0') return count;
304 /* ========================================================================
305 * Return the length of the maximum inital segment of s
306 * which contains no characters from reject.
308 int strcspn(s, reject)
312 register int count = 0;
315 if (strchr(reject, *s++) != NULL) return count;
323 /* ========================================================================
324 * Add an environment variable (if any) before argv, and update argc.
325 * Return the expanded environment variable to be freed later, or NULL
326 * if no options were added to argv.
328 #define SEPARATOR " \t" /* separators in env variable */
330 char *add_envopt(argcp, argvp, env)
331 int *argcp; /* pointer to argc */
332 char ***argvp; /* pointer to argv */
333 char *env; /* name of environment variable */
335 char *p; /* running pointer through env variable */
336 char **oargv; /* runs through old argv array */
337 char **nargv; /* runs through new argv array */
338 int oargc = *argcp; /* old argc */
339 int nargc = 0; /* number of arguments in env variable */
341 env = (char*)getenv(env);
342 if (env == NULL) return NULL;
346 for (p = env; *p; nargc++ ) { /* move through env */
347 p += strspn(p, SEPARATOR); /* skip leading separators */
348 if (*p == '\0') break;
350 p += strcspn(p, SEPARATOR); /* find end of word */
351 if (*p) *p++ = '\0'; /* mark it */
358 /* Allocate the new argv array, with an extra element just in case
359 * the original arg list did not end with a NULL.
361 nargv = (char **) xcalloc (*argcp + 1, sizeof (char *));
365 /* Copy the program name first */
367 gzip_error ("argc<=0");
368 *(nargv++) = *(oargv++);
370 /* Then copy the environment args */
371 for (p = env; nargc > 0; nargc--) {
372 p += strspn(p, SEPARATOR); /* skip separators */
373 *(nargv++) = p; /* store start */
374 while (*p++) ; /* skip over word */
377 /* Finally copy the old args and add a NULL (usual convention) */
378 while (oargc--) *(nargv++) = *(oargv++);
383 /* ========================================================================
390 fprintf (stderr, "\n%s: %s: %s\n", program_name, ifname, m);
397 fprintf (stderr, "\n%s: memory_exhausted\n", program_name);
404 WARN ((stderr, "%s: %s: warning: %s\n", program_name, ifname, m));
410 fprintf (stderr, "\n%s: ", program_name);
415 fprintf(stderr, "%s: unexpected end of file\n", ifname);
423 fprintf (stderr, "\n%s: ", program_name);
429 /* ========================================================================
430 * Display compression ratio on the given stream on 6 characters.
432 void display_ratio(num, den, file)
437 fprintf(file, "%5.1f%%", den == 0 ? 0 : 100.0 * num / den);
440 /* ========================================================================
441 * Print an off_t. There's no completely portable way to use printf,
442 * so we do it ourselves.
444 void fprint_off(file, offset, width)
449 char buf[CHAR_BIT * sizeof (off_t)];
450 char *p = buf + sizeof buf;
452 /* Don't negate offset here; it might overflow. */
455 *--p = '0' - offset % 10;
456 while ((offset /= 10) != 0);
461 *--p = '0' + offset % 10;
462 while ((offset /= 10) != 0);
465 width -= buf + sizeof buf - p;
466 while (0 < width--) {
469 for (; p < buf + sizeof buf; p++)
473 /* ========================================================================
474 * Table of CRC-32's of all single-byte values (made by makecrc.c)
477 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
478 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
479 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
480 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
481 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
482 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
483 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
484 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
485 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
486 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
487 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
488 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
489 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
490 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
491 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
492 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
493 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
494 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
495 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
496 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
497 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
498 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
499 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
500 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
501 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
502 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
503 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
504 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
505 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
506 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
507 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
508 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
509 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
510 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
511 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
512 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
513 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
514 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
515 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
516 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
517 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
518 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
519 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
520 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
521 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
522 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
523 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
524 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
525 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
526 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
527 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,