build: avoid warning about deprecated use of automake's ACLOCAL_AMFLAGS
[gzip.git] / util.c
blobc4c7f70532d6b14ff492dcecec25f542f500003f
1 /* util.c -- utility functions for gzip support
3 Copyright (C) 1997-1999, 2001-2002, 2006, 2009-2013 Free Software
4 Foundation, 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 #include <limits.h>
28 #include <unistd.h>
29 #include <fcntl.h>
30 #include <stdlib.h>
31 #include <errno.h>
33 #include "gzip.h"
34 #include <xalloc.h>
36 #ifndef CHAR_BIT
37 # define CHAR_BIT 8
38 #endif
40 static int write_buffer (int, voidp, unsigned int);
42 static const ulg crc_32_tab[]; /* crc table, defined below */
44 /* ===========================================================================
45 * Copy input to output unchanged: zcat == cat with --force.
46 * IN assertion: insize bytes have already been read in inbuf and inptr bytes
47 * already processed or copied.
49 int copy(in, out)
50 int in, out; /* input and output file descriptors */
52 int got;
54 errno = 0;
55 while (insize > inptr) {
56 write_buf(out, (char*)inbuf + inptr, insize - inptr);
57 bytes_out += insize - inptr;
58 got = read_buffer (in, (char *) inbuf, INBUFSIZ);
59 if (got == -1)
60 read_error();
61 bytes_in += got;
62 insize = (unsigned)got;
63 inptr = 0;
65 return OK;
68 /* ===========================================================================
69 * Run a set of bytes through the crc shift register. If s is a NULL
70 * pointer, then initialize the crc shift register contents instead.
71 * Return the current crc in either case.
73 ulg updcrc(s, n)
74 uch *s; /* pointer to bytes to pump through */
75 unsigned n; /* number of bytes in s[] */
77 register ulg c; /* temporary variable */
79 static ulg crc = (ulg)0xffffffffL; /* shift register contents */
81 if (s == NULL) {
82 c = 0xffffffffL;
83 } else {
84 c = crc;
85 if (n) do {
86 c = crc_32_tab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8);
87 } while (--n);
89 crc = c;
90 return c ^ 0xffffffffL; /* (instead of ~c for 64-bit machines) */
93 /* ===========================================================================
94 * Clear input and output buffers
96 void clear_bufs()
98 outcnt = 0;
99 insize = inptr = 0;
100 bytes_in = bytes_out = 0L;
103 /* ===========================================================================
104 * Fill the input buffer. This is called only when the buffer is empty.
106 int fill_inbuf(eof_ok)
107 int eof_ok; /* set if EOF acceptable as a result */
109 int len;
111 /* Read as much as possible */
112 insize = 0;
113 do {
114 len = read_buffer (ifd, (char *) inbuf + insize, INBUFSIZ - insize);
115 if (len == 0) break;
116 if (len == -1) {
117 read_error();
118 break;
120 insize += len;
121 } while (insize < INBUFSIZ);
123 if (insize == 0) {
124 if (eof_ok) return EOF;
125 flush_window();
126 errno = 0;
127 read_error();
129 bytes_in += (off_t)insize;
130 inptr = 1;
131 return inbuf[0];
134 /* Like the standard read function, except do not attempt to read more
135 than INT_MAX bytes at a time. */
137 read_buffer (fd, buf, cnt)
138 int fd;
139 voidp buf;
140 unsigned int cnt;
142 int len;
143 if (INT_MAX < cnt)
144 cnt = INT_MAX;
145 len = read (fd, buf, cnt);
147 #if defined F_SETFL && O_NONBLOCK && defined EAGAIN
148 /* Input files are opened O_NONBLOCK for security reasons. On some
149 file systems this can cause read to fail with errno == EAGAIN. */
150 if (len < 0 && errno == EAGAIN)
152 int flags = fcntl (fd, F_GETFL);
153 if (0 <= flags)
155 if (! (flags & O_NONBLOCK))
156 errno = EAGAIN;
157 else if (fcntl (fd, F_SETFL, flags & ~O_NONBLOCK) != -1)
158 len = read (fd, buf, cnt);
161 #endif
163 return len;
166 /* Likewise for 'write'. */
167 static int
168 write_buffer (fd, buf, cnt)
169 int fd;
170 voidp buf;
171 unsigned int cnt;
173 if (INT_MAX < cnt)
174 cnt = INT_MAX;
175 return write (fd, buf, cnt);
178 /* ===========================================================================
179 * Write the output buffer outbuf[0..outcnt-1] and update bytes_out.
180 * (used for the compressed data only)
182 void flush_outbuf()
184 if (outcnt == 0) return;
186 write_buf(ofd, (char *)outbuf, outcnt);
187 bytes_out += (off_t)outcnt;
188 outcnt = 0;
191 /* ===========================================================================
192 * Write the output window window[0..outcnt-1] and update crc and bytes_out.
193 * (Used for the decompressed data only.)
195 void flush_window()
197 if (outcnt == 0) return;
198 updcrc(window, outcnt);
200 if (!test) {
201 write_buf(ofd, (char *)window, outcnt);
203 bytes_out += (off_t)outcnt;
204 outcnt = 0;
207 /* ===========================================================================
208 * Does the same as write(), but also handles partial pipe writes and checks
209 * for error return.
211 void write_buf(fd, buf, cnt)
212 int fd;
213 voidp buf;
214 unsigned cnt;
216 unsigned n;
218 while ((n = write_buffer (fd, buf, cnt)) != cnt) {
219 if (n == (unsigned)(-1)) {
220 write_error();
222 cnt -= n;
223 buf = (voidp)((char*)buf+n);
227 /* ========================================================================
228 * Put string s in lower case, return s.
230 char *strlwr(s)
231 char *s;
233 char *t;
234 for (t = s; *t; t++)
235 *t = tolow ((unsigned char) *t);
236 return s;
239 /* ========================================================================
240 * Return the base name of a file (remove any directory prefix and
241 * any version suffix). For systems with file names that are not
242 * case sensitive, force the base name to lower case.
244 char *
245 gzip_base_name (fname)
246 char *fname;
248 char *p;
250 if ((p = strrchr(fname, PATH_SEP)) != NULL) fname = p+1;
251 #ifdef PATH_SEP2
252 if ((p = strrchr(fname, PATH_SEP2)) != NULL) fname = p+1;
253 #endif
254 #ifdef PATH_SEP3
255 if ((p = strrchr(fname, PATH_SEP3)) != NULL) fname = p+1;
256 #endif
257 #ifdef SUFFIX_SEP
258 if ((p = strrchr(fname, SUFFIX_SEP)) != NULL) *p = '\0';
259 #endif
260 if (casemap('A') == 'a') strlwr(fname);
261 return fname;
264 /* ========================================================================
265 * Unlink a file, working around the unlink readonly bug (if present).
267 int xunlink (filename)
268 char *filename;
270 int r = unlink (filename);
272 #ifdef UNLINK_READONLY_BUG
273 if (r != 0)
275 int e = errno;
276 if (chmod (filename, S_IWUSR) != 0)
278 errno = e;
279 return -1;
282 r = unlink (filename);
284 #endif
286 return r;
289 /* ========================================================================
290 * Make a file name legal for file systems not allowing file names with
291 * multiple dots or starting with a dot (such as MSDOS), by changing
292 * all dots except the last one into underlines. A target dependent
293 * function can be used instead of this simple function by defining the macro
294 * MAKE_LEGAL_NAME in tailor.h and providing the function in a target
295 * dependent module.
297 void make_simple_name(name)
298 char *name;
300 char *p = strrchr(name, '.');
301 if (p == NULL) return;
302 if (p == name) p++;
303 do {
304 if (*--p == '.') *p = '_';
305 } while (p != name);
308 /* ========================================================================
309 * Add an environment variable (if any) before argv, and update argc.
310 * Return the expanded environment variable to be freed later, or NULL
311 * if no options were added to argv.
313 #define SEPARATOR " \t" /* separators in env variable */
315 char *add_envopt(
316 int *argcp, /* pointer to argc */
317 char ***argvp, /* pointer to argv */
318 char const *envvar_name) /* name of environment variable */
320 char *p; /* running pointer through env variable */
321 char **oargv; /* runs through old argv array */
322 char **nargv; /* runs through new argv array */
323 int oargc = *argcp; /* old argc */
324 int nargc = 0; /* number of arguments in env variable */
325 char *env_val;
327 env_val = getenv(envvar_name);
328 if (env_val == NULL) return NULL;
330 env_val = xstrdup (env_val);
332 for (p = env_val; *p; nargc++ ) { /* move through env_val */
333 p += strspn(p, SEPARATOR); /* skip leading separators */
334 if (*p == '\0') break;
336 p += strcspn(p, SEPARATOR); /* find end of word */
337 if (*p) *p++ = '\0'; /* mark it */
339 if (nargc == 0) {
340 free(env_val);
341 return NULL;
343 *argcp += nargc;
344 /* Allocate the new argv array, with an extra element just in case
345 * the original arg list did not end with a NULL.
347 nargv = xcalloc (*argcp + 1, sizeof (char *));
348 oargv = *argvp;
349 *argvp = nargv;
351 /* Copy the program name first */
352 if (oargc-- < 0)
353 gzip_error ("argc<=0");
354 *(nargv++) = *(oargv++);
356 /* Then copy the environment args */
357 for (p = env_val; nargc > 0; nargc--) {
358 p += strspn(p, SEPARATOR); /* skip separators */
359 *(nargv++) = p; /* store start */
360 while (*p++) ; /* skip over word */
363 /* Finally copy the old args and add a NULL (usual convention) */
364 while (oargc--) *(nargv++) = *(oargv++);
365 *nargv = NULL;
366 return env_val;
369 /* ========================================================================
370 * Error handlers.
372 void
373 gzip_error (char const *m)
375 fprintf (stderr, "\n%s: %s: %s\n", program_name, ifname, m);
376 abort_gzip();
379 void
380 xalloc_die ()
382 fprintf (stderr, "\n%s: memory_exhausted\n", program_name);
383 abort_gzip ();
386 void warning (char const *m)
388 WARN ((stderr, "%s: %s: warning: %s\n", program_name, ifname, m));
391 void read_error()
393 int e = errno;
394 fprintf (stderr, "\n%s: ", program_name);
395 if (e != 0) {
396 errno = e;
397 perror(ifname);
398 } else {
399 fprintf(stderr, "%s: unexpected end of file\n", ifname);
401 abort_gzip();
404 void write_error()
406 int e = errno;
407 fprintf (stderr, "\n%s: ", program_name);
408 errno = e;
409 perror(ofname);
410 abort_gzip();
413 /* ========================================================================
414 * Display compression ratio on the given stream on 6 characters.
416 void display_ratio(num, den, file)
417 off_t num;
418 off_t den;
419 FILE *file;
421 fprintf(file, "%5.1f%%", den == 0 ? 0 : 100.0 * num / den);
424 /* ========================================================================
425 * Print an off_t. There's no completely portable way to use printf,
426 * so we do it ourselves.
428 void fprint_off(file, offset, width)
429 FILE *file;
430 off_t offset;
431 int width;
433 char buf[CHAR_BIT * sizeof (off_t)];
434 char *p = buf + sizeof buf;
436 /* Don't negate offset here; it might overflow. */
437 if (offset < 0) {
439 *--p = '0' - offset % 10;
440 while ((offset /= 10) != 0);
442 *--p = '-';
443 } else {
445 *--p = '0' + offset % 10;
446 while ((offset /= 10) != 0);
449 width -= buf + sizeof buf - p;
450 while (0 < width--) {
451 putc (' ', file);
453 for (; p < buf + sizeof buf; p++)
454 putc (*p, file);
457 /* ========================================================================
458 * Table of CRC-32's of all single-byte values (made by makecrc.c)
460 static const ulg crc_32_tab[] = {
461 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
462 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
463 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
464 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
465 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
466 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
467 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
468 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
469 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
470 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
471 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
472 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
473 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
474 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
475 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
476 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
477 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
478 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
479 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
480 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
481 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
482 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
483 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
484 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
485 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
486 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
487 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
488 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
489 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
490 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
491 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
492 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
493 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
494 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
495 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
496 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
497 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
498 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
499 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
500 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
501 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
502 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
503 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
504 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
505 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
506 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
507 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
508 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
509 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
510 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
511 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
512 0x2d02ef8dL