Main Page | Class List | Directories | File List | Class Members | File Members

util.c

Go to the documentation of this file.
00001 /* util.c -- utility functions for gzip support
00002 
00003    Copyright (C) 1997, 1998, 1999, 2001, 2002, 2006 Free Software
00004    Foundation, Inc.
00005    Copyright (C) 1992-1993 Jean-loup Gailly
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 2, or (at your option)
00010    any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program; if not, write to the Free Software Foundation,
00019    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
00020 
00021 #ifdef RCSID
00022 static char rcsid[] = "$Id: util.c,v 1.6 2006/12/11 18:54:39 eggert Exp $";
00023 #endif
00024 
00025 #include <config.h>
00026 #include <ctype.h>
00027 #include <errno.h>
00028 
00029 #include "tailor.h"
00030 
00031 #ifdef HAVE_LIMITS_H
00032 #  include <limits.h>
00033 #endif
00034 #ifdef HAVE_UNISTD_H
00035 #  include <unistd.h>
00036 #endif
00037 #ifdef HAVE_FCNTL_H
00038 #  include <fcntl.h>
00039 #endif
00040 
00041 #if defined STDC_HEADERS || defined HAVE_STDLIB_H
00042 #  include <stdlib.h>
00043 #else
00044    extern int errno;
00045 #endif
00046 
00047 #include "gzip.h"
00048 #include "crypt.h"
00049 #include <xalloc.h>
00050 
00051 #ifndef CHAR_BIT
00052 #  define CHAR_BIT 8
00053 #endif
00054 
00055 static int write_buffer OF((int, voidp, unsigned int));
00056 
00057 extern ulg crc_32_tab[];   /* crc table, defined below */
00058 
00059 /* ===========================================================================
00060  * Copy input to output unchanged: zcat == cat with --force.
00061  * IN assertion: insize bytes have already been read in inbuf.
00062  */
00063 int copy(in, out)
00064     int in, out;   /* input and output file descriptors */
00065 {
00066     errno = 0;
00067     while (insize != 0 && (int)insize != -1) {
00068         write_buf(out, (char*)inbuf, insize);
00069         bytes_out += insize;
00070         insize = read_buffer (in, (char *) inbuf, INBUFSIZ);
00071     }
00072     if ((int)insize == -1) {
00073         read_error();
00074     }
00075     bytes_in = bytes_out;
00076     return OK;
00077 }
00078 
00079 /* ===========================================================================
00080  * Run a set of bytes through the crc shift register.  If s is a NULL
00081  * pointer, then initialize the crc shift register contents instead.
00082  * Return the current crc in either case.
00083  */
00084 ulg updcrc(s, n)
00085     uch *s;                 /* pointer to bytes to pump through */
00086     unsigned n;             /* number of bytes in s[] */
00087 {
00088     register ulg c;         /* temporary variable */
00089 
00090     static ulg crc = (ulg)0xffffffffL; /* shift register contents */
00091 
00092     if (s == NULL) {
00093         c = 0xffffffffL;
00094     } else {
00095         c = crc;
00096         if (n) do {
00097             c = crc_32_tab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8);
00098         } while (--n);
00099     }
00100     crc = c;
00101     return c ^ 0xffffffffL;       /* (instead of ~c for 64-bit machines) */
00102 }
00103 
00104 /* ===========================================================================
00105  * Clear input and output buffers
00106  */
00107 void clear_bufs()
00108 {
00109     outcnt = 0;
00110     insize = inptr = 0;
00111     bytes_in = bytes_out = 0L;
00112 }
00113 
00114 /* ===========================================================================
00115  * Fill the input buffer. This is called only when the buffer is empty.
00116  */
00117 int fill_inbuf(eof_ok)
00118     int eof_ok;          /* set if EOF acceptable as a result */
00119 {
00120     int len;
00121 
00122     /* Read as much as possible */
00123     insize = 0;
00124     do {
00125         len = read_buffer (ifd, (char *) inbuf + insize, INBUFSIZ - insize);
00126         if (len == 0) break;
00127         if (len == -1) {
00128           read_error();
00129           break;
00130         }
00131         insize += len;
00132     } while (insize < INBUFSIZ);
00133 
00134     if (insize == 0) {
00135         if (eof_ok) return EOF;
00136         flush_window();
00137         errno = 0;
00138         read_error();
00139     }
00140     bytes_in += (off_t)insize;
00141     inptr = 1;
00142     return inbuf[0];
00143 }
00144 
00145 /* Like the standard read function, except do not attempt to read more
00146    than SSIZE_MAX bytes at a time.  */
00147 int
00148 read_buffer (fd, buf, cnt)
00149      int fd;
00150      voidp buf;
00151      unsigned int cnt;
00152 {
00153 #ifdef SSIZE_MAX
00154   if (SSIZE_MAX < cnt)
00155     cnt = SSIZE_MAX;
00156 #endif
00157   return read (fd, buf, cnt);
00158 }
00159 
00160 /* Likewise for 'write'.  */
00161 static int
00162 write_buffer (fd, buf, cnt)
00163      int fd;
00164      voidp buf;
00165      unsigned int cnt;
00166 {
00167 #ifdef SSIZE_MAX
00168   if (SSIZE_MAX < cnt)
00169     cnt = SSIZE_MAX;
00170 #endif
00171   return write (fd, buf, cnt);
00172 }
00173 
00174 /* ===========================================================================
00175  * Write the output buffer outbuf[0..outcnt-1] and update bytes_out.
00176  * (used for the compressed data only)
00177  */
00178 void flush_outbuf()
00179 {
00180     if (outcnt == 0) return;
00181 
00182     write_buf(ofd, (char *)outbuf, outcnt);
00183     bytes_out += (off_t)outcnt;
00184     outcnt = 0;
00185 }
00186 
00187 /* ===========================================================================
00188  * Write the output window window[0..outcnt-1] and update crc and bytes_out.
00189  * (Used for the decompressed data only.)
00190  */
00191 void flush_window()
00192 {
00193     if (outcnt == 0) return;
00194     updcrc(window, outcnt);
00195 
00196     if (!test) {
00197         write_buf(ofd, (char *)window, outcnt);
00198     }
00199     bytes_out += (off_t)outcnt;
00200     outcnt = 0;
00201 }
00202 
00203 /* ===========================================================================
00204  * Does the same as write(), but also handles partial pipe writes and checks
00205  * for error return.
00206  */
00207 void write_buf(fd, buf, cnt)
00208     int       fd;
00209     voidp     buf;
00210     unsigned  cnt;
00211 {
00212     unsigned  n;
00213 
00214     while ((n = write_buffer (fd, buf, cnt)) != cnt) {
00215         if (n == (unsigned)(-1)) {
00216             write_error();
00217         }
00218         cnt -= n;
00219         buf = (voidp)((char*)buf+n);
00220     }
00221 }
00222 
00223 /* ========================================================================
00224  * Put string s in lower case, return s.
00225  */
00226 char *strlwr(s)
00227     char *s;
00228 {
00229     char *t;
00230     for (t = s; *t; t++)
00231       *t = tolow ((unsigned char) *t);
00232     return s;
00233 }
00234 
00235 /* ========================================================================
00236  * Return the base name of a file (remove any directory prefix and
00237  * any version suffix). For systems with file names that are not
00238  * case sensitive, force the base name to lower case.
00239  */
00240 char *
00241 gzip_base_name (fname)
00242     char *fname;
00243 {
00244     char *p;
00245 
00246     if ((p = strrchr(fname, PATH_SEP))  != NULL) fname = p+1;
00247 #ifdef PATH_SEP2
00248     if ((p = strrchr(fname, PATH_SEP2)) != NULL) fname = p+1;
00249 #endif
00250 #ifdef PATH_SEP3
00251     if ((p = strrchr(fname, PATH_SEP3)) != NULL) fname = p+1;
00252 #endif
00253 #ifdef SUFFIX_SEP
00254     if ((p = strrchr(fname, SUFFIX_SEP)) != NULL) *p = '\0';
00255 #endif
00256     if (casemap('A') == 'a') strlwr(fname);
00257     return fname;
00258 }
00259 
00260 /* ========================================================================
00261  * Unlink a file, working around the unlink readonly bug (if present).
00262  */
00263 int xunlink (filename)
00264      char *filename;
00265 {
00266   int r = unlink (filename);
00267 
00268 #ifdef UNLINK_READONLY_BUG
00269   if (r != 0)
00270     {
00271       int e = errno;
00272       if (chmod (filename, S_IWUSR) != 0)
00273         {
00274           errno = e;
00275           return -1;
00276         }
00277 
00278       r = unlink (filename);
00279     }
00280 #endif
00281 
00282   return r;
00283 }
00284 
00285 /* ========================================================================
00286  * Make a file name legal for file systems not allowing file names with
00287  * multiple dots or starting with a dot (such as MSDOS), by changing
00288  * all dots except the last one into underlines.  A target dependent
00289  * function can be used instead of this simple function by defining the macro
00290  * MAKE_LEGAL_NAME in tailor.h and providing the function in a target
00291  * dependent module.
00292  */
00293 void make_simple_name(name)
00294     char *name;
00295 {
00296     char *p = strrchr(name, '.');
00297     if (p == NULL) return;
00298     if (p == name) p++;
00299     do {
00300         if (*--p == '.') *p = '_';
00301     } while (p != name);
00302 }
00303 
00304 
00305 #if !defined HAVE_STRING_H && !defined STDC_HEADERS
00306 
00307 /* Provide missing strspn and strcspn functions. */
00308 
00309 #  ifndef __STDC__
00310 #    define const
00311 #  endif
00312 
00313 int strspn  OF((const char *s, const char *accept));
00314 int strcspn OF((const char *s, const char *reject));
00315 
00316 /* ========================================================================
00317  * Return the length of the maximum initial segment
00318  * of s which contains only characters in accept.
00319  */
00320 int strspn(s, accept)
00321     const char *s;
00322     const char *accept;
00323 {
00324     register const char *p;
00325     register const char *a;
00326     register int count = 0;
00327 
00328     for (p = s; *p != '\0'; ++p) {
00329         for (a = accept; *a != '\0'; ++a) {
00330             if (*p == *a) break;
00331         }
00332         if (*a == '\0') return count;
00333         ++count;
00334     }
00335     return count;
00336 }
00337 
00338 /* ========================================================================
00339  * Return the length of the maximum inital segment of s
00340  * which contains no characters from reject.
00341  */
00342 int strcspn(s, reject)
00343     const char *s;
00344     const char *reject;
00345 {
00346     register int count = 0;
00347 
00348     while (*s != '\0') {
00349         if (strchr(reject, *s++) != NULL) return count;
00350         ++count;
00351     }
00352     return count;
00353 }
00354 
00355 #endif
00356 
00357 /* ========================================================================
00358  * Add an environment variable (if any) before argv, and update argc.
00359  * Return the expanded environment variable to be freed later, or NULL
00360  * if no options were added to argv.
00361  */
00362 #define SEPARATOR       " \t"   /* separators in env variable */
00363 
00364 char *add_envopt(argcp, argvp, env)
00365     int *argcp;          /* pointer to argc */
00366     char ***argvp;       /* pointer to argv */
00367     char *env;           /* name of environment variable */
00368 {
00369     char *p;             /* running pointer through env variable */
00370     char **oargv;        /* runs through old argv array */
00371     char **nargv;        /* runs through new argv array */
00372     int  oargc = *argcp; /* old argc */
00373     int  nargc = 0;      /* number of arguments in env variable */
00374 
00375     env = (char*)getenv(env);
00376     if (env == NULL) return NULL;
00377 
00378     env = xstrdup (env);
00379 
00380     for (p = env; *p; nargc++ ) {            /* move through env */
00381         p += strspn(p, SEPARATOR);           /* skip leading separators */
00382         if (*p == '\0') break;
00383 
00384         p += strcspn(p, SEPARATOR);          /* find end of word */
00385         if (*p) *p++ = '\0';                 /* mark it */
00386     }
00387     if (nargc == 0) {
00388         free(env);
00389         return NULL;
00390     }
00391     *argcp += nargc;
00392     /* Allocate the new argv array, with an extra element just in case
00393      * the original arg list did not end with a NULL.
00394      */
00395     nargv = (char **) xcalloc (*argcp + 1, sizeof (char *));
00396     oargv  = *argvp;
00397     *argvp = nargv;
00398 
00399     /* Copy the program name first */
00400     if (oargc-- < 0)
00401       gzip_error ("argc<=0");
00402     *(nargv++) = *(oargv++);
00403 
00404     /* Then copy the environment args */
00405     for (p = env; nargc > 0; nargc--) {
00406         p += strspn(p, SEPARATOR);           /* skip separators */
00407         *(nargv++) = p;                      /* store start */
00408         while (*p++) ;                       /* skip over word */
00409     }
00410 
00411     /* Finally copy the old args and add a NULL (usual convention) */
00412     while (oargc--) *(nargv++) = *(oargv++);
00413     *nargv = NULL;
00414     return env;
00415 }
00416 
00417 /* ========================================================================
00418  * Error handlers.
00419  */
00420 void
00421 gzip_error (m)
00422     char *m;
00423 {
00424     fprintf (stderr, "\n%s: %s: %s\n", program_name, ifname, m);
00425     abort_gzip();
00426 }
00427 
00428 void
00429 xalloc_die ()
00430 {
00431   fprintf (stderr, "\n%s: memory_exhausted\n", program_name);
00432   abort_gzip ();
00433 }
00434 
00435 void warning (m)
00436     char *m;
00437 {
00438     WARN ((stderr, "%s: %s: warning: %s\n", program_name, ifname, m));
00439 }
00440 
00441 void read_error()
00442 {
00443     int e = errno;
00444     fprintf (stderr, "\n%s: ", program_name);
00445     if (e != 0) {
00446         errno = e;
00447         perror(ifname);
00448     } else {
00449         fprintf(stderr, "%s: unexpected end of file\n", ifname);
00450     }
00451     abort_gzip();
00452 }
00453 
00454 void write_error()
00455 {
00456     int e = errno;
00457     fprintf (stderr, "\n%s: ", program_name);
00458     errno = e;
00459     perror(ofname);
00460     abort_gzip();
00461 }
00462 
00463 /* ========================================================================
00464  * Display compression ratio on the given stream on 6 characters.
00465  */
00466 void display_ratio(num, den, file)
00467     off_t num;
00468     off_t den;
00469     FILE *file;
00470 {
00471     fprintf(file, "%5.1f%%", den == 0 ? 0 : 100.0 * num / den);
00472 }
00473 
00474 /* ========================================================================
00475  * Print an off_t.  There's no completely portable way to use printf,
00476  * so we do it ourselves.
00477  */
00478 void fprint_off(file, offset, width)
00479     FILE *file;
00480     off_t offset;
00481     int width;
00482 {
00483     char buf[CHAR_BIT * sizeof (off_t)];
00484     char *p = buf + sizeof buf;
00485 
00486     /* Don't negate offset here; it might overflow.  */
00487     if (offset < 0) {
00488         do
00489           *--p = '0' - offset % 10;
00490         while ((offset /= 10) != 0);
00491 
00492         *--p = '-';
00493     } else {
00494         do
00495           *--p = '0' + offset % 10;
00496         while ((offset /= 10) != 0);
00497     }
00498 
00499     width -= buf + sizeof buf - p;
00500     while (0 < width--) {
00501         putc (' ', file);
00502     }
00503     for (;  p < buf + sizeof buf;  p++)
00504         putc (*p, file);
00505 }
00506 
00507 /* ========================================================================
00508  * Table of CRC-32's of all single-byte values (made by makecrc.c)
00509  */
00510 ulg crc_32_tab[] = {
00511   0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
00512   0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
00513   0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
00514   0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
00515   0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
00516   0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
00517   0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
00518   0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
00519   0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
00520   0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
00521   0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
00522   0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
00523   0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
00524   0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
00525   0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
00526   0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
00527   0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
00528   0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
00529   0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
00530   0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
00531   0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
00532   0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
00533   0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
00534   0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
00535   0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
00536   0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
00537   0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
00538   0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
00539   0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
00540   0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
00541   0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
00542   0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
00543   0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
00544   0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
00545   0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
00546   0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
00547   0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
00548   0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
00549   0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
00550   0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
00551   0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
00552   0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
00553   0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
00554   0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
00555   0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
00556   0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
00557   0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
00558   0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
00559   0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
00560   0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
00561   0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
00562   0x2d02ef8dL
00563 };

© sourcejam.com 2005-2008