Gzip 1.1
[unix-history] / gnu / usr.bin / gzip / util.c
CommitLineData
3013fe88
NW
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.
5 */
6
7#ifndef lint
8static char rcsid[] = "$Id: util.c,v 0.14 1993/05/27 10:31:52 jloup Exp $";
9#endif
10
11#include <stdio.h>
12#include <ctype.h>
13#include <errno.h>
14#include <sys/types.h>
15
16#include "tailor.h"
17
18#ifdef HAVE_UNISTD_H
19# include <unistd.h>
20#endif
21#ifndef NO_FCNTL_H
22# include <fcntl.h>
23#endif
24
25#if defined(STDC_HEADERS) || !defined(NO_STDLIB_H)
26# include <stdlib.h>
27#else
28 extern int errno;
29#endif
30
31#include "gzip.h"
32#include "crypt.h"
33
34extern ulg crc_32_tab[]; /* crc table, defined below */
35
36/* ===========================================================================
37 * Run a set of bytes through the crc shift register. If s is a NULL
38 * pointer, then initialize the crc shift register contents instead.
39 * Return the current crc in either case.
40 */
41ulg updcrc(s, n)
42 uch *s; /* pointer to bytes to pump through */
43 unsigned n; /* number of bytes in s[] */
44{
45 register ulg c; /* temporary variable */
46
47 static ulg crc = (ulg)0xffffffffL; /* shift register contents */
48
49 if (s == NULL) {
50 c = 0xffffffffL;
51 } else {
52 c = crc;
53 if (n) do {
54 c = crc_32_tab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8);
55 } while (--n);
56 }
57 crc = c;
58 return c ^ 0xffffffffL; /* (instead of ~c for 64-bit machines) */
59}
60
61/* ===========================================================================
62 * Clear input and output buffers
63 */
64void clear_bufs()
65{
66 outcnt = 0;
67 insize = inptr = 0;
68 bytes_in = bytes_out = 0L;
69}
70
71/* ===========================================================================
72 * Fill the input buffer. This is called only when the buffer is empty
73 * and at least one byte is really needed.
74 */
75int fill_inbuf()
76{
77 int len;
78
79 /* Read as much as possible */
80 insize = 0;
81 errno = 0;
82 do {
83 len = read(ifd, (char*)inbuf+insize, INBUFSIZ-insize);
84 if (len == 0 || len == EOF) break;
85 insize += len;
86 } while (insize < INBUFSIZ);
87
88 if (insize == 0) {
89 read_error();
90 }
91 bytes_in += (ulg)insize;
92 inptr = 1;
93 return inbuf[0];
94}
95
96/* ===========================================================================
97 * Write the output buffer outbuf[0..outcnt-1] and update bytes_out.
98 * (used for the compressed data only)
99 */
100void flush_outbuf()
101{
102 if (outcnt == 0) return;
103
104 write_buf(ofd, (char *)outbuf, outcnt);
105 bytes_out += (ulg)outcnt;
106 outcnt = 0;
107}
108
109/* ===========================================================================
110 * Write the output window window[0..outcnt-1] and update crc and bytes_out.
111 * (Used for the decompressed data only.)
112 */
113void flush_window()
114{
115 if (outcnt == 0) return;
116 updcrc(window, outcnt);
117
118 if (!test) {
119 write_buf(ofd, (char *)window, outcnt);
120 }
121 bytes_out += (ulg)outcnt;
122 outcnt = 0;
123}
124
125/* ===========================================================================
126 * Does the same as write(), but also handles partial pipe writes and checks
127 * for error return.
128 */
129void write_buf(fd, buf, cnt)
130 int fd;
131 voidp buf;
132 unsigned cnt;
133{
134 unsigned n;
135
136 while ((n = write(fd, buf, cnt)) != cnt) {
137 if (n == (unsigned)(-1)) {
138 write_error();
139 }
140 cnt -= n;
141 buf = (voidp)((char*)buf+n);
142 }
143}
144
145/* ========================================================================
146 * Put string s in lower case, return s.
147 */
148char *strlwr(s)
149 char *s;
150{
151 char *t;
152 for (t = s; *t; t++) *t = tolow(*t);
153 return s;
154}
155
156/* ========================================================================
157 * Return the base name of a file (remove any directory prefix and
158 * any version suffix). For systems with file names that are not
159 * case sensitive, force the base name to lower case.
160 */
161char *basename(fname)
162 char *fname;
163{
164 char *p;
165
166 if ((p = strrchr(fname, PATH_SEP)) != NULL) fname = p+1;
167#ifdef PATH_SEP2
168 if ((p = strrchr(fname, PATH_SEP2)) != NULL) fname = p+1;
169#endif
170#ifdef PATH_SEP3
171 if ((p = strrchr(fname, PATH_SEP3)) != NULL) fname = p+1;
172#endif
173#ifdef SUFFIX_SEP
174 if ((p = strrchr(fname, SUFFIX_SEP)) != NULL) *p = '\0';
175#endif
176 if (casemap('A') == 'a') strlwr(fname);
177 return fname;
178}
179
180#if defined(NO_STRING_H) && !defined(STDC_HEADERS)
181
182/* Provide missing strspn and strcspn functions. */
183
184# ifndef __STDC__
185# define const
186# endif
187
188int strspn OF((const char *s, const char *accept));
189int strcspn OF((const char *s, const char *reject));
190
191/* ========================================================================
192 * Return the length of the maximum initial segment
193 * of s which contains only characters in accept.
194 */
195int strspn(s, accept)
196 const char *s;
197 const char *accept;
198{
199 register const char *p;
200 register const char *a;
201 register int count = 0;
202
203 for (p = s; *p != '\0'; ++p) {
204 for (a = accept; *a != '\0'; ++a) {
205 if (*p == *a) break;
206 }
207 if (*a == '\0') return count;
208 ++count;
209 }
210 return count;
211}
212
213/* ========================================================================
214 * Return the length of the maximum inital segment of s
215 * which contains no characters from reject.
216 */
217int strcspn(s, reject)
218 const char *s;
219 const char *reject;
220{
221 register int count = 0;
222
223 while (*s != '\0') {
224 if (strchr(reject, *s++) != NULL) return count;
225 ++count;
226 }
227 return count;
228}
229
230#endif /* NO_STRING_H */
231
232/* ========================================================================
233 * Add an environment variable (if any) before argv, and update argc.
234 * Return the expanded environment variable to be freed later, or NULL
235 * if no options were added to argv.
236 */
237#define SEPARATOR " \t" /* separators in env variable */
238
239char *add_envopt(argcp, argvp, env)
240 int *argcp; /* pointer to argc */
241 char ***argvp; /* pointer to argv */
242 char *env; /* name of environment variable */
243{
244 char *p; /* running pointer through env variable */
245 char **oargv; /* runs through old argv array */
246 char **nargv; /* runs through new argv array */
247 int oargc = *argcp; /* old argc */
248 int nargc = 0; /* number of arguments in env variable */
249
250 env = (char*)getenv(env);
251 if (env == NULL) return NULL;
252
253 p = (char*)xmalloc(strlen(env)+1);
254 env = strcpy(p, env); /* keep env variable intact */
255
256 for (p = env; *p; nargc++ ) { /* move through env */
257 p += strspn(p, SEPARATOR); /* skip leading separators */
258 if (*p == '\0') break;
259
260 p += strcspn(p, SEPARATOR); /* find end of word */
261 if (*p) *p++ = '\0'; /* mark it */
262 }
263 if (nargc == 0) {
264 free(env); env = NULL;
265 return NULL;
266 }
267 *argcp += nargc;
268 /* Allocate the new argv array, with an extra element just in case
269 * the original arg list did not end with a NULL.
270 */
271 nargv = (char**)calloc(*argcp+1, sizeof(char *));
272 if (nargv == NULL) error("out of memory");
273 oargv = *argvp;
274 *argvp = nargv;
275
276 /* Copy the program name first */
277 if (oargc-- < 0) error("argc<=0");
278 *(nargv++) = *(oargv++);
279
280 /* Then copy the environment args */
281 for (p = env; nargc > 0; nargc--) {
282 p += strspn(p, SEPARATOR); /* skip separators */
283 *(nargv++) = p; /* store start */
284 while (*p++) ; /* skip over word */
285 }
286
287 /* Finally copy the old args and add a NULL (usual convention) */
288 while (oargc--) *(nargv++) = *(oargv++);
289 *nargv = NULL;
290 return env;
291}
292
293/* ========================================================================
294 * Error handlers.
295 */
296void error(m)
297 char *m;
298{
299 fprintf(stderr, "\n%s: %s: %s\n", progname, ifname, m);
300 abort_gzip();
301}
302
303void warn(a, b)
304 char *a, *b; /* message strings juxtaposed in output */
305{
306 WARN((stderr, "%s: %s: warning: %s%s\n", progname, ifname, a, b));
307}
308
309void read_error()
310{
311 fprintf(stderr, "\n%s: ", progname);
312 if (errno != 0) {
313 perror(ifname);
314 } else {
315 fprintf(stderr, "%s: unexpected end of file\n", ifname);
316 }
317 abort_gzip();
318}
319
320void write_error()
321{
322 fprintf(stderr, "\n%s: ", progname);
323 perror(ofname);
324 abort_gzip();
325}
326
327/* ========================================================================
328 * Display compression ratio on stderr.
329 */
330void display_ratio(num, den)
331 long num;
332 long den;
333{
334 long ratio; /* 1000 times the compression ratio */
335
336 if (den == 0) {
337 ratio = 0; /* no compression */
338 } else if (den < 2147483L) { /* (2**31 -1)/1000 */
339 ratio = 1000L*num/den;
340 } else {
341 ratio = num/(den/1000L);
342 }
343 if (ratio < 0) {
344 putc('-', stderr);
345 ratio = -ratio;
346 }
347 fprintf(stderr, "%2ld.%ld%%", ratio / 10L, ratio % 10L);
348}
349
350
351/* ========================================================================
352 * Semi-safe malloc -- never returns NULL.
353 */
354voidp xmalloc (size)
355 unsigned size;
356{
357 voidp cp = (voidp)malloc (size);
358
359 if (cp == NULL) error("out of memory");
360 return cp;
361}
362
363/* ========================================================================
364 * Table of CRC-32's of all single-byte values (made by makecrc.c)
365 */
366ulg crc_32_tab[] = {
367 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
368 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
369 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
370 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
371 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
372 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
373 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
374 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
375 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
376 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
377 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
378 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
379 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
380 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
381 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
382 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
383 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
384 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
385 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
386 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
387 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
388 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
389 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
390 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
391 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
392 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
393 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
394 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
395 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
396 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
397 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
398 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
399 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
400 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
401 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
402 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
403 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
404 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
405 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
406 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
407 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
408 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
409 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
410 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
411 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
412 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
413 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
414 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
415 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
416 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
417 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
418 0x2d02ef8dL
419};