1 /* util.c -- utility functions for gzip support
2 * Copyright (C) 1997, 1998, 1999, 2001 Free Software Foundation, Inc.
3 * Copyright (C) 1992-1993 Jean-loup Gailly
4 * This is free software; you can redistribute it and/or modify it under the
5 * terms of the GNU General Public License, see the file COPYING.
9 static char rcsid[] = "$Id: util.c,v 0.15 1993/06/15 09:04:13 jloup Exp $";
28 #if defined STDC_HEADERS || defined HAVE_STDLIB_H
41 extern ulg crc_32_tab[]; /* crc table, defined below */
43 /* ===========================================================================
44 * Copy input to output unchanged: zcat == cat with --force.
45 * IN assertion: insize bytes have already been read in inbuf.
48 int in, out; /* input and output file descriptors */
51 while (insize != 0 && (int)insize != -1) {
52 write_buf(out, (char*)inbuf, insize);
54 insize = read(in, (char*)inbuf, INBUFSIZ);
56 if ((int)insize == -1) {
63 /* ===========================================================================
64 * Run a set of bytes through the crc shift register. If s is a NULL
65 * pointer, then initialize the crc shift register contents instead.
66 * Return the current crc in either case.
69 uch *s; /* pointer to bytes to pump through */
70 unsigned n; /* number of bytes in s[] */
72 register ulg c; /* temporary variable */
74 static ulg crc = (ulg)0xffffffffL; /* shift register contents */
81 c = crc_32_tab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8);
85 return c ^ 0xffffffffL; /* (instead of ~c for 64-bit machines) */
88 /* ===========================================================================
89 * Clear input and output buffers
95 bytes_in = bytes_out = 0L;
98 /* ===========================================================================
99 * Fill the input buffer. This is called only when the buffer is empty.
101 int fill_inbuf(eof_ok)
102 int eof_ok; /* set if EOF acceptable as a result */
106 /* Read as much as possible */
109 len = read(ifd, (char*)inbuf+insize, INBUFSIZ-insize);
116 } while (insize < INBUFSIZ);
119 if (eof_ok) return EOF;
124 bytes_in += (off_t)insize;
129 /* ===========================================================================
130 * Write the output buffer outbuf[0..outcnt-1] and update bytes_out.
131 * (used for the compressed data only)
135 if (outcnt == 0) return;
137 write_buf(ofd, (char *)outbuf, outcnt);
138 bytes_out += (off_t)outcnt;
142 /* ===========================================================================
143 * Write the output window window[0..outcnt-1] and update crc and bytes_out.
144 * (Used for the decompressed data only.)
148 if (outcnt == 0) return;
149 updcrc(window, outcnt);
152 write_buf(ofd, (char *)window, outcnt);
154 bytes_out += (off_t)outcnt;
158 /* ===========================================================================
159 * Does the same as write(), but also handles partial pipe writes and checks
162 void write_buf(fd, buf, cnt)
169 while ((n = write(fd, buf, cnt)) != cnt) {
170 if (n == (unsigned)(-1)) {
174 buf = (voidp)((char*)buf+n);
178 /* ========================================================================
179 * Put string s in lower case, return s.
186 *t = tolow ((unsigned char) *t);
190 /* ========================================================================
191 * Return the base name of a file (remove any directory prefix and
192 * any version suffix). For systems with file names that are not
193 * case sensitive, force the base name to lower case.
195 char *base_name(fname)
200 if ((p = strrchr(fname, PATH_SEP)) != NULL) fname = p+1;
202 if ((p = strrchr(fname, PATH_SEP2)) != NULL) fname = p+1;
205 if ((p = strrchr(fname, PATH_SEP3)) != NULL) fname = p+1;
208 if ((p = strrchr(fname, SUFFIX_SEP)) != NULL) *p = '\0';
210 if (casemap('A') == 'a') strlwr(fname);
214 /* ========================================================================
215 * Unlink a file, working around the unlink readonly bug (if present).
217 int xunlink (filename)
220 int r = unlink (filename);
222 #ifdef UNLINK_READONLY_BUG
226 if (chmod (filename, S_IWUSR) != 0)
232 r = unlink (filename);
239 /* ========================================================================
240 * Make a file name legal for file systems not allowing file names with
241 * multiple dots or starting with a dot (such as MSDOS), by changing
242 * all dots except the last one into underlines. A target dependent
243 * function can be used instead of this simple function by defining the macro
244 * MAKE_LEGAL_NAME in tailor.h and providing the function in a target
247 void make_simple_name(name)
250 char *p = strrchr(name, '.');
251 if (p == NULL) return;
254 if (*--p == '.') *p = '_';
259 #if !defined HAVE_STRING_H && !defined STDC_HEADERS
261 /* Provide missing strspn and strcspn functions. */
267 int strspn OF((const char *s, const char *accept));
268 int strcspn OF((const char *s, const char *reject));
270 /* ========================================================================
271 * Return the length of the maximum initial segment
272 * of s which contains only characters in accept.
274 int strspn(s, accept)
278 register const char *p;
279 register const char *a;
280 register int count = 0;
282 for (p = s; *p != '\0'; ++p) {
283 for (a = accept; *a != '\0'; ++a) {
286 if (*a == '\0') return count;
292 /* ========================================================================
293 * Return the length of the maximum inital segment of s
294 * which contains no characters from reject.
296 int strcspn(s, reject)
300 register int count = 0;
303 if (strchr(reject, *s++) != NULL) return count;
311 /* ========================================================================
312 * Add an environment variable (if any) before argv, and update argc.
313 * Return the expanded environment variable to be freed later, or NULL
314 * if no options were added to argv.
316 #define SEPARATOR " \t" /* separators in env variable */
318 char *add_envopt(argcp, argvp, env)
319 int *argcp; /* pointer to argc */
320 char ***argvp; /* pointer to argv */
321 char *env; /* name of environment variable */
323 char *p; /* running pointer through env variable */
324 char **oargv; /* runs through old argv array */
325 char **nargv; /* runs through new argv array */
326 int oargc = *argcp; /* old argc */
327 int nargc = 0; /* number of arguments in env variable */
329 env = (char*)getenv(env);
330 if (env == NULL) return NULL;
332 p = (char*)xmalloc(strlen(env)+1);
333 env = strcpy(p, env); /* keep env variable intact */
335 for (p = env; *p; nargc++ ) { /* move through env */
336 p += strspn(p, SEPARATOR); /* skip leading separators */
337 if (*p == '\0') break;
339 p += strcspn(p, SEPARATOR); /* find end of word */
340 if (*p) *p++ = '\0'; /* mark it */
347 /* Allocate the new argv array, with an extra element just in case
348 * the original arg list did not end with a NULL.
350 nargv = (char**)calloc(*argcp+1, sizeof(char *));
351 if (nargv == NULL) error("out of memory");
355 /* Copy the program name first */
356 if (oargc-- < 0) error("argc<=0");
357 *(nargv++) = *(oargv++);
359 /* Then copy the environment args */
360 for (p = env; nargc > 0; nargc--) {
361 p += strspn(p, SEPARATOR); /* skip separators */
362 *(nargv++) = p; /* store start */
363 while (*p++) ; /* skip over word */
366 /* Finally copy the old args and add a NULL (usual convention) */
367 while (oargc--) *(nargv++) = *(oargv++);
372 /* ========================================================================
378 fprintf(stderr, "\n%s: %s: %s\n", progname, ifname, m);
385 WARN ((stderr, "%s: %s: warning: %s\n", progname, ifname, m));
391 fprintf(stderr, "\n%s: ", progname);
396 fprintf(stderr, "%s: unexpected end of file\n", ifname);
404 fprintf(stderr, "\n%s: ", progname);
410 /* ========================================================================
411 * Display compression ratio on the given stream on 6 characters.
413 void display_ratio(num, den, file)
418 fprintf(file, "%5.1f%%", den == 0 ? 0 : 100.0 * num / den);
421 /* ========================================================================
422 * Print an off_t. There's no completely portable way to use printf,
423 * so we do it ourselves.
425 void fprint_off(file, offset, width)
430 char buf[CHAR_BIT * sizeof (off_t)];
431 char *p = buf + sizeof buf;
432 int negative = offset < 0;
433 /* Don't negate offset here; it might overflow. */
435 int remainder = offset % 10;
436 int quotient = offset / 10;
437 if (offset < 0 && 0 < remainder) {
441 *--p = (remainder < 0 ? -remainder : remainder) + '0';
444 } while (offset != 0);
445 for (width -= negative; 0 < width; width--) {
451 for (; p < buf + sizeof buf; p++)
455 /* ========================================================================
456 * Semi-safe malloc -- never returns NULL.
461 voidp cp = (voidp)malloc (size);
463 if (cp == NULL) error("out of memory");
467 /* ========================================================================
468 * Table of CRC-32's of all single-byte values (made by makecrc.c)
471 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
472 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
473 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
474 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
475 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
476 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
477 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
478 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
479 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
480 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
481 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
482 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
483 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
484 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
485 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
486 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
487 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
488 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
489 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
490 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
491 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
492 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
493 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
494 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
495 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
496 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
497 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
498 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
499 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
500 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
501 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
502 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
503 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
504 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
505 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
506 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
507 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
508 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
509 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
510 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
511 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
512 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
513 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
514 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
515 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
516 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
517 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
518 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
519 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
520 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
521 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,