doc: use gnu-web-doc-update module
[gzip.git] / util.c
blob40b36fc3a1f4ac7eea0a6e6df326435673326691
1 /* util.c -- utility functions for gzip support
3 Copyright (C) 1997-1999, 2001-2002, 2006, 2009 Free Software Foundation,
4 Inc.
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)
10 any later version.
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. */
21 #include <config.h>
22 #include <ctype.h>
23 #include <errno.h>
25 #include "tailor.h"
27 #ifdef HAVE_LIMITS_H
28 # include <limits.h>
29 #endif
30 #ifdef HAVE_UNISTD_H
31 # include <unistd.h>
32 #endif
33 #ifdef HAVE_FCNTL_H
34 # include <fcntl.h>
35 #endif
37 #if defined STDC_HEADERS || defined HAVE_STDLIB_H
38 # include <stdlib.h>
39 #else
40 extern int errno;
41 #endif
43 #include "gzip.h"
44 #include "crypt.h"
45 #include <xalloc.h>
47 #ifndef CHAR_BIT
48 # define CHAR_BIT 8
49 #endif
51 static int write_buffer OF((int, voidp, unsigned int));
53 extern ulg crc_32_tab[]; /* crc table, defined below */
55 /* ===========================================================================
56 * Copy input to output unchanged: zcat == cat with --force.
57 * IN assertion: insize bytes have already been read in inbuf.
59 int copy(in, out)
60 int in, out; /* input and output file descriptors */
62 errno = 0;
63 while (insize != 0 && (int)insize != -1) {
64 write_buf(out, (char*)inbuf, insize);
65 bytes_out += insize;
66 insize = read_buffer (in, (char *) inbuf, INBUFSIZ);
68 if ((int)insize == -1) {
69 read_error();
71 bytes_in = bytes_out;
72 return OK;
75 /* ===========================================================================
76 * Run a set of bytes through the crc shift register. If s is a NULL
77 * pointer, then initialize the crc shift register contents instead.
78 * Return the current crc in either case.
80 ulg updcrc(s, n)
81 uch *s; /* pointer to bytes to pump through */
82 unsigned n; /* number of bytes in s[] */
84 register ulg c; /* temporary variable */
86 static ulg crc = (ulg)0xffffffffL; /* shift register contents */
88 if (s == NULL) {
89 c = 0xffffffffL;
90 } else {
91 c = crc;
92 if (n) do {
93 c = crc_32_tab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8);
94 } while (--n);
96 crc = c;
97 return c ^ 0xffffffffL; /* (instead of ~c for 64-bit machines) */
100 /* ===========================================================================
101 * Clear input and output buffers
103 void clear_bufs()
105 outcnt = 0;
106 insize = inptr = 0;
107 bytes_in = bytes_out = 0L;
110 /* ===========================================================================
111 * Fill the input buffer. This is called only when the buffer is empty.
113 int fill_inbuf(eof_ok)
114 int eof_ok; /* set if EOF acceptable as a result */
116 int len;
118 /* Read as much as possible */
119 insize = 0;
120 do {
121 len = read_buffer (ifd, (char *) inbuf + insize, INBUFSIZ - insize);
122 if (len == 0) break;
123 if (len == -1) {
124 read_error();
125 break;
127 insize += len;
128 } while (insize < INBUFSIZ);
130 if (insize == 0) {
131 if (eof_ok) return EOF;
132 flush_window();
133 errno = 0;
134 read_error();
136 bytes_in += (off_t)insize;
137 inptr = 1;
138 return inbuf[0];
141 /* Like the standard read function, except do not attempt to read more
142 than SSIZE_MAX bytes at a time. */
144 read_buffer (fd, buf, cnt)
145 int fd;
146 voidp buf;
147 unsigned int cnt;
149 #ifdef SSIZE_MAX
150 if (SSIZE_MAX < cnt)
151 cnt = SSIZE_MAX;
152 #endif
153 return read (fd, buf, cnt);
156 /* Likewise for 'write'. */
157 static int
158 write_buffer (fd, buf, cnt)
159 int fd;
160 voidp buf;
161 unsigned int cnt;
163 #ifdef SSIZE_MAX
164 if (SSIZE_MAX < cnt)
165 cnt = SSIZE_MAX;
166 #endif
167 return write (fd, buf, cnt);
170 /* ===========================================================================
171 * Write the output buffer outbuf[0..outcnt-1] and update bytes_out.
172 * (used for the compressed data only)
174 void flush_outbuf()
176 if (outcnt == 0) return;
178 write_buf(ofd, (char *)outbuf, outcnt);
179 bytes_out += (off_t)outcnt;
180 outcnt = 0;
183 /* ===========================================================================
184 * Write the output window window[0..outcnt-1] and update crc and bytes_out.
185 * (Used for the decompressed data only.)
187 void flush_window()
189 if (outcnt == 0) return;
190 updcrc(window, outcnt);
192 if (!test) {
193 write_buf(ofd, (char *)window, outcnt);
195 bytes_out += (off_t)outcnt;
196 outcnt = 0;
199 /* ===========================================================================
200 * Does the same as write(), but also handles partial pipe writes and checks
201 * for error return.
203 void write_buf(fd, buf, cnt)
204 int fd;
205 voidp buf;
206 unsigned cnt;
208 unsigned n;
210 while ((n = write_buffer (fd, buf, cnt)) != cnt) {
211 if (n == (unsigned)(-1)) {
212 write_error();
214 cnt -= n;
215 buf = (voidp)((char*)buf+n);
219 /* ========================================================================
220 * Put string s in lower case, return s.
222 char *strlwr(s)
223 char *s;
225 char *t;
226 for (t = s; *t; t++)
227 *t = tolow ((unsigned char) *t);
228 return s;
231 /* ========================================================================
232 * Return the base name of a file (remove any directory prefix and
233 * any version suffix). For systems with file names that are not
234 * case sensitive, force the base name to lower case.
236 char *
237 gzip_base_name (fname)
238 char *fname;
240 char *p;
242 if ((p = strrchr(fname, PATH_SEP)) != NULL) fname = p+1;
243 #ifdef PATH_SEP2
244 if ((p = strrchr(fname, PATH_SEP2)) != NULL) fname = p+1;
245 #endif
246 #ifdef PATH_SEP3
247 if ((p = strrchr(fname, PATH_SEP3)) != NULL) fname = p+1;
248 #endif
249 #ifdef SUFFIX_SEP
250 if ((p = strrchr(fname, SUFFIX_SEP)) != NULL) *p = '\0';
251 #endif
252 if (casemap('A') == 'a') strlwr(fname);
253 return fname;
256 /* ========================================================================
257 * Unlink a file, working around the unlink readonly bug (if present).
259 int xunlink (filename)
260 char *filename;
262 int r = unlink (filename);
264 #ifdef UNLINK_READONLY_BUG
265 if (r != 0)
267 int e = errno;
268 if (chmod (filename, S_IWUSR) != 0)
270 errno = e;
271 return -1;
274 r = unlink (filename);
276 #endif
278 return r;
281 /* ========================================================================
282 * Make a file name legal for file systems not allowing file names with
283 * multiple dots or starting with a dot (such as MSDOS), by changing
284 * all dots except the last one into underlines. A target dependent
285 * function can be used instead of this simple function by defining the macro
286 * MAKE_LEGAL_NAME in tailor.h and providing the function in a target
287 * dependent module.
289 void make_simple_name(name)
290 char *name;
292 char *p = strrchr(name, '.');
293 if (p == NULL) return;
294 if (p == name) p++;
295 do {
296 if (*--p == '.') *p = '_';
297 } while (p != name);
301 #if !defined HAVE_STRING_H && !defined STDC_HEADERS
303 /* Provide missing strspn and strcspn functions. */
305 # ifndef __STDC__
306 # define const
307 # endif
309 int strspn OF((const char *s, const char *accept));
310 int strcspn OF((const char *s, const char *reject));
312 /* ========================================================================
313 * Return the length of the maximum initial segment
314 * of s which contains only characters in accept.
316 int strspn(s, accept)
317 const char *s;
318 const char *accept;
320 register const char *p;
321 register const char *a;
322 register int count = 0;
324 for (p = s; *p != '\0'; ++p) {
325 for (a = accept; *a != '\0'; ++a) {
326 if (*p == *a) break;
328 if (*a == '\0') return count;
329 ++count;
331 return count;
334 /* ========================================================================
335 * Return the length of the maximum inital segment of s
336 * which contains no characters from reject.
338 int strcspn(s, reject)
339 const char *s;
340 const char *reject;
342 register int count = 0;
344 while (*s != '\0') {
345 if (strchr(reject, *s++) != NULL) return count;
346 ++count;
348 return count;
351 #endif
353 /* ========================================================================
354 * Add an environment variable (if any) before argv, and update argc.
355 * Return the expanded environment variable to be freed later, or NULL
356 * if no options were added to argv.
358 #define SEPARATOR " \t" /* separators in env variable */
360 char *add_envopt(argcp, argvp, env)
361 int *argcp; /* pointer to argc */
362 char ***argvp; /* pointer to argv */
363 char *env; /* name of environment variable */
365 char *p; /* running pointer through env variable */
366 char **oargv; /* runs through old argv array */
367 char **nargv; /* runs through new argv array */
368 int oargc = *argcp; /* old argc */
369 int nargc = 0; /* number of arguments in env variable */
371 env = (char*)getenv(env);
372 if (env == NULL) return NULL;
374 env = xstrdup (env);
376 for (p = env; *p; nargc++ ) { /* move through env */
377 p += strspn(p, SEPARATOR); /* skip leading separators */
378 if (*p == '\0') break;
380 p += strcspn(p, SEPARATOR); /* find end of word */
381 if (*p) *p++ = '\0'; /* mark it */
383 if (nargc == 0) {
384 free(env);
385 return NULL;
387 *argcp += nargc;
388 /* Allocate the new argv array, with an extra element just in case
389 * the original arg list did not end with a NULL.
391 nargv = xcalloc (*argcp + 1, sizeof (char *));
392 oargv = *argvp;
393 *argvp = nargv;
395 /* Copy the program name first */
396 if (oargc-- < 0)
397 gzip_error ("argc<=0");
398 *(nargv++) = *(oargv++);
400 /* Then copy the environment args */
401 for (p = env; nargc > 0; nargc--) {
402 p += strspn(p, SEPARATOR); /* skip separators */
403 *(nargv++) = p; /* store start */
404 while (*p++) ; /* skip over word */
407 /* Finally copy the old args and add a NULL (usual convention) */
408 while (oargc--) *(nargv++) = *(oargv++);
409 *nargv = NULL;
410 return env;
413 /* ========================================================================
414 * Error handlers.
416 void
417 gzip_error (m)
418 char *m;
420 fprintf (stderr, "\n%s: %s: %s\n", program_name, ifname, m);
421 abort_gzip();
424 void
425 xalloc_die ()
427 fprintf (stderr, "\n%s: memory_exhausted\n", program_name);
428 abort_gzip ();
431 void warning (m)
432 char *m;
434 WARN ((stderr, "%s: %s: warning: %s\n", program_name, ifname, m));
437 void read_error()
439 int e = errno;
440 fprintf (stderr, "\n%s: ", program_name);
441 if (e != 0) {
442 errno = e;
443 perror(ifname);
444 } else {
445 fprintf(stderr, "%s: unexpected end of file\n", ifname);
447 abort_gzip();
450 void write_error()
452 int e = errno;
453 fprintf (stderr, "\n%s: ", program_name);
454 errno = e;
455 perror(ofname);
456 abort_gzip();
459 /* ========================================================================
460 * Display compression ratio on the given stream on 6 characters.
462 void display_ratio(num, den, file)
463 off_t num;
464 off_t den;
465 FILE *file;
467 fprintf(file, "%5.1f%%", den == 0 ? 0 : 100.0 * num / den);
470 /* ========================================================================
471 * Print an off_t. There's no completely portable way to use printf,
472 * so we do it ourselves.
474 void fprint_off(file, offset, width)
475 FILE *file;
476 off_t offset;
477 int width;
479 char buf[CHAR_BIT * sizeof (off_t)];
480 char *p = buf + sizeof buf;
482 /* Don't negate offset here; it might overflow. */
483 if (offset < 0) {
485 *--p = '0' - offset % 10;
486 while ((offset /= 10) != 0);
488 *--p = '-';
489 } else {
491 *--p = '0' + offset % 10;
492 while ((offset /= 10) != 0);
495 width -= buf + sizeof buf - p;
496 while (0 < width--) {
497 putc (' ', file);
499 for (; p < buf + sizeof buf; p++)
500 putc (*p, file);
503 /* ========================================================================
504 * Table of CRC-32's of all single-byte values (made by makecrc.c)
506 ulg crc_32_tab[] = {
507 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
508 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
509 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
510 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
511 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
512 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
513 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
514 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
515 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
516 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
517 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
518 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
519 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
520 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
521 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
522 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
523 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
524 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
525 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
526 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
527 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
528 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
529 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
530 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
531 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
532 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
533 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
534 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
535 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
536 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
537 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
538 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
539 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
540 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
541 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
542 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
543 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
544 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
545 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
546 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
547 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
548 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
549 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
550 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
551 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
552 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
553 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
554 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
555 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
556 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
557 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
558 0x2d02ef8dL