source: vendor/gzip/1.3.11/util.c@ 3325

Last change on this file since 3325 was 3325, checked in by bird, 18 years ago

gzip 1.3.11

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