1 /* util.c -- utility functions for gzip support
2 * Copyright (C) 1992-1993 Jean-loup Gailly
3 * This is free software; you can redistribute it and/or modify it under the
4 * terms of the GNU General Public License, see the file COPYING.
8 static char rcsid[] = "$FreeBSD$";
13 #include <sys/types.h>
24 #if defined(STDC_HEADERS) || !defined(NO_STDLIB_H)
33 extern ulg crc_32_tab[]; /* crc table, defined below */
35 /* ===========================================================================
36 * Copy input to output unchanged: zcat == cat with --force.
37 * IN assertion: insize bytes have already been read in inbuf.
40 int in, out; /* input and output file descriptors */
43 while (insize != 0 && (int)insize != EOF) {
44 write_buf(out, (char*)inbuf, insize);
46 insize = read(in, (char*)inbuf, INBUFSIZ);
48 if ((int)insize == EOF && errno != 0) {
55 /* ===========================================================================
56 * Run a set of bytes through the crc shift register. If s is a NULL
57 * pointer, then initialize the crc shift register contents instead.
58 * Return the current crc in either case.
61 uch *s; /* pointer to bytes to pump through */
62 unsigned n; /* number of bytes in s[] */
64 register ulg c; /* temporary variable */
66 static ulg crc = (ulg)0xffffffffL; /* shift register contents */
73 c = crc_32_tab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8);
77 return c ^ 0xffffffffL; /* (instead of ~c for 64-bit machines) */
80 /* ===========================================================================
81 * Clear input and output buffers
87 bytes_in = bytes_out = 0L;
90 /* ===========================================================================
91 * Fill the input buffer. This is called only when the buffer is empty.
93 int fill_inbuf(eof_ok)
94 int eof_ok; /* set if EOF acceptable as a result */
98 /* Read as much as possible */
102 len = read(ifd, (char*)inbuf+insize, INBUFSIZ-insize);
103 if (len == 0 || len == EOF) break;
105 } while (insize < INBUFSIZ);
108 if (eof_ok) return EOF;
111 bytes_in += (ulg)insize;
116 /* ===========================================================================
117 * Write the output buffer outbuf[0..outcnt-1] and update bytes_out.
118 * (used for the compressed data only)
122 if (outcnt == 0) return;
124 write_buf(ofd, (char *)outbuf, outcnt);
125 bytes_out += (ulg)outcnt;
129 /* ===========================================================================
130 * Write the output window window[0..outcnt-1] and update crc and bytes_out.
131 * (Used for the decompressed data only.)
135 if (outcnt == 0) return;
136 updcrc(window, outcnt);
139 write_buf(ofd, (char *)window, outcnt);
141 bytes_out += (ulg)outcnt;
145 /* ===========================================================================
146 * Does the same as write(), but also handles partial pipe writes and checks
149 void write_buf(fd, buf, cnt)
156 while ((n = write(fd, buf, cnt)) != cnt) {
157 if (n == (unsigned)(-1)) {
161 buf = (voidp)((char*)buf+n);
165 /* ========================================================================
166 * Put string s in lower case, return s.
172 for (t = s; *t; t++) *t = tolow(*t);
176 /* ========================================================================
177 * Return the base name of a file (remove any directory prefix and
178 * any version suffix). For systems with file names that are not
179 * case sensitive, force the base name to lower case.
181 char *basename(fname)
186 if ((p = strrchr(fname, PATH_SEP)) != NULL) fname = p+1;
188 if ((p = strrchr(fname, PATH_SEP2)) != NULL) fname = p+1;
191 if ((p = strrchr(fname, PATH_SEP3)) != NULL) fname = p+1;
194 if ((p = strrchr(fname, SUFFIX_SEP)) != NULL) *p = '\0';
196 if (casemap('A') == 'a') strlwr(fname);
200 /* ========================================================================
201 * Make a file name legal for file systems not allowing file names with
202 * multiple dots or starting with a dot (such as MSDOS), by changing
203 * all dots except the last one into underlines. A target dependent
204 * function can be used instead of this simple function by defining the macro
205 * MAKE_LEGAL_NAME in tailor.h and providing the function in a target
208 void make_simple_name(name)
211 char *p = strrchr(name, '.');
212 if (p == NULL) return;
215 if (*--p == '.') *p = '_';
220 #if defined(NO_STRING_H) && !defined(STDC_HEADERS)
222 /* Provide missing strspn and strcspn functions. */
228 int strspn OF((const char *s, const char *accept));
229 int strcspn OF((const char *s, const char *reject));
231 /* ========================================================================
232 * Return the length of the maximum initial segment
233 * of s which contains only characters in accept.
235 int strspn(s, accept)
239 register const char *p;
240 register const char *a;
241 register int count = 0;
243 for (p = s; *p != '\0'; ++p) {
244 for (a = accept; *a != '\0'; ++a) {
247 if (*a == '\0') return count;
253 /* ========================================================================
254 * Return the length of the maximum inital segment of s
255 * which contains no characters from reject.
257 int strcspn(s, reject)
261 register int count = 0;
264 if (strchr(reject, *s++) != NULL) return count;
270 #endif /* NO_STRING_H */
272 /* ========================================================================
273 * Add an environment variable (if any) before argv, and update argc.
274 * Return the expanded environment variable to be freed later, or NULL
275 * if no options were added to argv.
277 #define SEPARATOR " \t" /* separators in env variable */
279 char *add_envopt(argcp, argvp, env)
280 int *argcp; /* pointer to argc */
281 char ***argvp; /* pointer to argv */
282 char *env; /* name of environment variable */
284 char *p; /* running pointer through env variable */
285 char **oargv; /* runs through old argv array */
286 char **nargv; /* runs through new argv array */
287 int oargc = *argcp; /* old argc */
288 int nargc = 0; /* number of arguments in env variable */
290 env = (char*)getenv(env);
291 if (env == NULL) return NULL;
293 p = (char*)xmalloc(strlen(env)+1);
294 env = strcpy(p, env); /* keep env variable intact */
296 for (p = env; *p; nargc++ ) { /* move through env */
297 p += strspn(p, SEPARATOR); /* skip leading separators */
298 if (*p == '\0') break;
300 p += strcspn(p, SEPARATOR); /* find end of word */
301 if (*p) *p++ = '\0'; /* mark it */
308 /* Allocate the new argv array, with an extra element just in case
309 * the original arg list did not end with a NULL.
311 nargv = (char**)calloc(*argcp+1, sizeof(char *));
312 if (nargv == NULL) error("out of memory");
316 /* Copy the program name first */
317 if (oargc-- < 0) error("argc<=0");
318 *(nargv++) = *(oargv++);
320 /* Then copy the environment args */
321 for (p = env; nargc > 0; nargc--) {
322 p += strspn(p, SEPARATOR); /* skip separators */
323 *(nargv++) = p; /* store start */
324 while (*p++) ; /* skip over word */
327 /* Finally copy the old args and add a NULL (usual convention) */
328 while (oargc--) *(nargv++) = *(oargv++);
333 /* ========================================================================
339 fprintf(stderr, "\n%s: %s: %s\n", progname, ifname, m);
345 fprintf(stderr, "\n%s: ", progname);
349 fprintf(stderr, "%s: unexpected end of file\n", ifname);
356 fprintf(stderr, "\n%s: ", progname);
361 /* ========================================================================
362 * Display compression ratio on the given stream on 6 characters.
364 void display_ratio(num, den, file)
369 long ratio; /* 1000 times the compression ratio */
372 ratio = 0; /* no compression */
373 } else if (den < 2147483L) { /* (2**31 -1)/1000 */
374 ratio = 1000L*num/den;
376 ratio = num/(den/1000L);
384 fprintf(file, "%2ld.%1ld%%", ratio / 10L, ratio % 10L);
388 /* ========================================================================
389 * Semi-safe malloc -- never returns NULL.
394 voidp cp = (voidp)malloc (size);
396 if (cp == NULL) error("out of memory");
400 /* ========================================================================
401 * Table of CRC-32's of all single-byte values (made by makecrc.c)
404 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
405 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
406 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
407 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
408 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
409 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
410 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
411 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
412 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
413 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
414 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
415 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
416 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
417 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
418 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
419 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
420 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
421 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
422 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
423 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
424 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
425 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
426 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
427 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
428 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
429 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
430 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
431 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
432 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
433 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
434 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
435 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
436 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
437 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
438 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
439 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
440 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
441 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
442 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
443 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
444 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
445 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
446 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
447 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
448 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
449 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
450 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
451 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
452 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
453 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
454 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,