1 /* util.c -- utility functions for gzip support
3 Copyright (C) 1997-1999, 2001-2002, 2006, 2009-2010 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 3, 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. */
41 static int write_buffer OF((int, voidp, unsigned int));
43 extern ulg crc_32_tab[]; /* crc table, defined below */
45 /* ===========================================================================
46 * Copy input to output unchanged: zcat == cat with --force.
47 * IN assertion: insize bytes have already been read in inbuf.
50 int in, out; /* input and output file descriptors */
53 while (insize != 0 && (int)insize != -1) {
54 write_buf(out, (char*)inbuf, insize);
56 insize = read_buffer (in, (char *) inbuf, INBUFSIZ);
58 if ((int)insize == -1) {
65 /* ===========================================================================
66 * Run a set of bytes through the crc shift register. If s is a NULL
67 * pointer, then initialize the crc shift register contents instead.
68 * Return the current crc in either case.
71 uch *s; /* pointer to bytes to pump through */
72 unsigned n; /* number of bytes in s[] */
74 register ulg c; /* temporary variable */
76 static ulg crc = (ulg)0xffffffffL; /* shift register contents */
83 c = crc_32_tab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8);
87 return c ^ 0xffffffffL; /* (instead of ~c for 64-bit machines) */
90 /* ===========================================================================
91 * Clear input and output buffers
97 bytes_in = bytes_out = 0L;
100 /* ===========================================================================
101 * Fill the input buffer. This is called only when the buffer is empty.
103 int fill_inbuf(eof_ok)
104 int eof_ok; /* set if EOF acceptable as a result */
108 /* Read as much as possible */
111 len = read_buffer (ifd, (char *) inbuf + insize, INBUFSIZ - insize);
118 } while (insize < INBUFSIZ);
121 if (eof_ok) return EOF;
126 bytes_in += (off_t)insize;
131 /* Like the standard read function, except do not attempt to read more
132 than SSIZE_MAX bytes at a time. */
134 read_buffer (fd, buf, cnt)
141 return read (fd, buf, cnt);
144 /* Likewise for 'write'. */
146 write_buffer (fd, buf, cnt)
153 return write (fd, buf, cnt);
156 /* ===========================================================================
157 * Write the output buffer outbuf[0..outcnt-1] and update bytes_out.
158 * (used for the compressed data only)
162 if (outcnt == 0) return;
164 write_buf(ofd, (char *)outbuf, outcnt);
165 bytes_out += (off_t)outcnt;
169 /* ===========================================================================
170 * Write the output window window[0..outcnt-1] and update crc and bytes_out.
171 * (Used for the decompressed data only.)
175 if (outcnt == 0) return;
176 updcrc(window, outcnt);
179 write_buf(ofd, (char *)window, outcnt);
181 bytes_out += (off_t)outcnt;
185 /* ===========================================================================
186 * Does the same as write(), but also handles partial pipe writes and checks
189 void write_buf(fd, buf, cnt)
196 while ((n = write_buffer (fd, buf, cnt)) != cnt) {
197 if (n == (unsigned)(-1)) {
201 buf = (voidp)((char*)buf+n);
205 /* ========================================================================
206 * Put string s in lower case, return s.
213 *t = tolow ((unsigned char) *t);
217 /* ========================================================================
218 * Return the base name of a file (remove any directory prefix and
219 * any version suffix). For systems with file names that are not
220 * case sensitive, force the base name to lower case.
223 gzip_base_name (fname)
228 if ((p = strrchr(fname, PATH_SEP)) != NULL) fname = p+1;
230 if ((p = strrchr(fname, PATH_SEP2)) != NULL) fname = p+1;
233 if ((p = strrchr(fname, PATH_SEP3)) != NULL) fname = p+1;
236 if ((p = strrchr(fname, SUFFIX_SEP)) != NULL) *p = '\0';
238 if (casemap('A') == 'a') strlwr(fname);
242 /* ========================================================================
243 * Unlink a file, working around the unlink readonly bug (if present).
245 int xunlink (filename)
248 int r = unlink (filename);
250 #ifdef UNLINK_READONLY_BUG
254 if (chmod (filename, S_IWUSR) != 0)
260 r = unlink (filename);
267 /* ========================================================================
268 * Make a file name legal for file systems not allowing file names with
269 * multiple dots or starting with a dot (such as MSDOS), by changing
270 * all dots except the last one into underlines. A target dependent
271 * function can be used instead of this simple function by defining the macro
272 * MAKE_LEGAL_NAME in tailor.h and providing the function in a target
275 void make_simple_name(name)
278 char *p = strrchr(name, '.');
279 if (p == NULL) return;
282 if (*--p == '.') *p = '_';
286 /* ========================================================================
287 * Add an environment variable (if any) before argv, and update argc.
288 * Return the expanded environment variable to be freed later, or NULL
289 * if no options were added to argv.
291 #define SEPARATOR " \t" /* separators in env variable */
294 int *argcp, /* pointer to argc */
295 char ***argvp, /* pointer to argv */
296 char const *envvar_name) /* name of environment variable */
298 char *p; /* running pointer through env variable */
299 char **oargv; /* runs through old argv array */
300 char **nargv; /* runs through new argv array */
301 int oargc = *argcp; /* old argc */
302 int nargc = 0; /* number of arguments in env variable */
305 env_val = getenv(envvar_name);
306 if (env_val == NULL) return NULL;
308 env_val = xstrdup (env_val);
310 for (p = env_val; *p; nargc++ ) { /* move through env_val */
311 p += strspn(p, SEPARATOR); /* skip leading separators */
312 if (*p == '\0') break;
314 p += strcspn(p, SEPARATOR); /* find end of word */
315 if (*p) *p++ = '\0'; /* mark it */
322 /* Allocate the new argv array, with an extra element just in case
323 * the original arg list did not end with a NULL.
325 nargv = xcalloc (*argcp + 1, sizeof (char *));
329 /* Copy the program name first */
331 gzip_error ("argc<=0");
332 *(nargv++) = *(oargv++);
334 /* Then copy the environment args */
335 for (p = env_val; nargc > 0; nargc--) {
336 p += strspn(p, SEPARATOR); /* skip separators */
337 *(nargv++) = p; /* store start */
338 while (*p++) ; /* skip over word */
341 /* Finally copy the old args and add a NULL (usual convention) */
342 while (oargc--) *(nargv++) = *(oargv++);
347 /* ========================================================================
351 gzip_error (char const *m)
353 fprintf (stderr, "\n%s: %s: %s\n", program_name, ifname, m);
360 fprintf (stderr, "\n%s: memory_exhausted\n", program_name);
364 void warning (char const *m)
366 WARN ((stderr, "%s: %s: warning: %s\n", program_name, ifname, m));
372 fprintf (stderr, "\n%s: ", program_name);
377 fprintf(stderr, "%s: unexpected end of file\n", ifname);
385 fprintf (stderr, "\n%s: ", program_name);
391 /* ========================================================================
392 * Display compression ratio on the given stream on 6 characters.
394 void display_ratio(num, den, file)
399 fprintf(file, "%5.1f%%", den == 0 ? 0 : 100.0 * num / den);
402 /* ========================================================================
403 * Print an off_t. There's no completely portable way to use printf,
404 * so we do it ourselves.
406 void fprint_off(file, offset, width)
411 char buf[CHAR_BIT * sizeof (off_t)];
412 char *p = buf + sizeof buf;
414 /* Don't negate offset here; it might overflow. */
417 *--p = '0' - offset % 10;
418 while ((offset /= 10) != 0);
423 *--p = '0' + offset % 10;
424 while ((offset /= 10) != 0);
427 width -= buf + sizeof buf - p;
428 while (0 < width--) {
431 for (; p < buf + sizeof buf; p++)
435 /* ========================================================================
436 * Table of CRC-32's of all single-byte values (made by makecrc.c)
439 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
440 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
441 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
442 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
443 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
444 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
445 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
446 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
447 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
448 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
449 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
450 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
451 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
452 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
453 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
454 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
455 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
456 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
457 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
458 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
459 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
460 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
461 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
462 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
463 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
464 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
465 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
466 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
467 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
468 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
469 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
470 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
471 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
472 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
473 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
474 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
475 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
476 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
477 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
478 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
479 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
480 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
481 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
482 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
483 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
484 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
485 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
486 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
487 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
488 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
489 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,