• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

contrib/zlib/gzlib.c

00001 /* gzlib.c -- zlib functions common to reading and writing gzip files
00002  * Copyright (C) 2004, 2010 Mark Adler
00003  * For conditions of distribution and use, see copyright notice in zlib.h
00004  */
00005 
00006 #include "gzguts.h"
00007 
00008 #if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
00009 #  define LSEEK lseek64
00010 #else
00011 #  define LSEEK lseek
00012 #endif
00013 
00014 /* Local functions */
00015 local void gz_reset OF((gz_statep));
00016 local gzFile gz_open OF((const char *, int, const char *));
00017 
00018 #if defined UNDER_CE
00019 
00020 /* Map the Windows error number in ERROR to a locale-dependent error message
00021    string and return a pointer to it.  Typically, the values for ERROR come
00022    from GetLastError.
00023 
00024    The string pointed to shall not be modified by the application, but may be
00025    overwritten by a subsequent call to gz_strwinerror
00026 
00027    The gz_strwinerror function does not change the current setting of
00028    GetLastError. */
00029 char ZLIB_INTERNAL *gz_strwinerror (error)
00030      DWORD error;
00031 {
00032     static char buf[1024];
00033 
00034     wchar_t *msgbuf;
00035     DWORD lasterr = GetLastError();
00036     DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
00037         | FORMAT_MESSAGE_ALLOCATE_BUFFER,
00038         NULL,
00039         error,
00040         0, /* Default language */
00041         (LPVOID)&msgbuf,
00042         0,
00043         NULL);
00044     if (chars != 0) {
00045         /* If there is an \r\n appended, zap it.  */
00046         if (chars >= 2
00047             && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
00048             chars -= 2;
00049             msgbuf[chars] = 0;
00050         }
00051 
00052         if (chars > sizeof (buf) - 1) {
00053             chars = sizeof (buf) - 1;
00054             msgbuf[chars] = 0;
00055         }
00056 
00057         wcstombs(buf, msgbuf, chars + 1);
00058         LocalFree(msgbuf);
00059     }
00060     else {
00061         sprintf(buf, "unknown win32 error (%ld)", error);
00062     }
00063 
00064     SetLastError(lasterr);
00065     return buf;
00066 }
00067 
00068 #endif /* UNDER_CE */
00069 
00070 /* Reset gzip file state */
00071 local void gz_reset(state)
00072     gz_statep state;
00073 {
00074     if (state->mode == GZ_READ) {   /* for reading ... */
00075         state->have = 0;            /* no output data available */
00076         state->eof = 0;             /* not at end of file */
00077         state->how = LOOK;          /* look for gzip header */
00078         state->direct = 1;          /* default for empty file */
00079     }
00080     state->seek = 0;                /* no seek request pending */
00081     gz_error(state, Z_OK, NULL);    /* clear error */
00082     state->pos = 0;                 /* no uncompressed data yet */
00083     state->strm.avail_in = 0;       /* no input data yet */
00084 }
00085 
00086 /* Open a gzip file either by name or file descriptor. */
00087 local gzFile gz_open(path, fd, mode)
00088     const char *path;
00089     int fd;
00090     const char *mode;
00091 {
00092     gz_statep state;
00093 
00094     /* allocate gzFile structure to return */
00095     state = malloc(sizeof(gz_state));
00096     if (state == NULL)
00097         return NULL;
00098     state->size = 0;            /* no buffers allocated yet */
00099     state->want = GZBUFSIZE;    /* requested buffer size */
00100     state->msg = NULL;          /* no error message yet */
00101 
00102     /* interpret mode */
00103     state->mode = GZ_NONE;
00104     state->level = Z_DEFAULT_COMPRESSION;
00105     state->strategy = Z_DEFAULT_STRATEGY;
00106     while (*mode) {
00107         if (*mode >= '0' && *mode <= '9')
00108             state->level = *mode - '0';
00109         else
00110             switch (*mode) {
00111             case 'r':
00112                 state->mode = GZ_READ;
00113                 break;
00114 #ifndef NO_GZCOMPRESS
00115             case 'w':
00116                 state->mode = GZ_WRITE;
00117                 break;
00118             case 'a':
00119                 state->mode = GZ_APPEND;
00120                 break;
00121 #endif
00122             case '+':       /* can't read and write at the same time */
00123                 free(state);
00124                 return NULL;
00125             case 'b':       /* ignore -- will request binary anyway */
00126                 break;
00127             case 'f':
00128                 state->strategy = Z_FILTERED;
00129                 break;
00130             case 'h':
00131                 state->strategy = Z_HUFFMAN_ONLY;
00132                 break;
00133             case 'R':
00134                 state->strategy = Z_RLE;
00135                 break;
00136             case 'F':
00137                 state->strategy = Z_FIXED;
00138             default:        /* could consider as an error, but just ignore */
00139                 ;
00140             }
00141         mode++;
00142     }
00143 
00144     /* must provide an "r", "w", or "a" */
00145     if (state->mode == GZ_NONE) {
00146         free(state);
00147         return NULL;
00148     }
00149 
00150     /* save the path name for error messages */
00151     state->path = malloc(strlen(path) + 1);
00152     if (state->path == NULL) {
00153         free(state);
00154         return NULL;
00155     }
00156     strcpy(state->path, path);
00157 
00158     /* open the file with the appropriate mode (or just use fd) */
00159     state->fd = fd != -1 ? fd :
00160         open(path,
00161 #ifdef O_LARGEFILE
00162             O_LARGEFILE |
00163 #endif
00164 #ifdef O_BINARY
00165             O_BINARY |
00166 #endif
00167             (state->mode == GZ_READ ?
00168                 O_RDONLY :
00169                 (O_WRONLY | O_CREAT | (
00170                     state->mode == GZ_WRITE ?
00171                         O_TRUNC :
00172                         O_APPEND))),
00173             0666);
00174     if (state->fd == -1) {
00175         free(state->path);
00176         free(state);
00177         return NULL;
00178     }
00179     if (state->mode == GZ_APPEND)
00180         state->mode = GZ_WRITE;         /* simplify later checks */
00181 
00182     /* save the current position for rewinding (only if reading) */
00183     if (state->mode == GZ_READ) {
00184         state->start = LSEEK(state->fd, 0, SEEK_CUR);
00185         if (state->start == -1) state->start = 0;
00186     }
00187 
00188     /* initialize stream */
00189     gz_reset(state);
00190 
00191     /* return stream */
00192     return (gzFile)state;
00193 }
00194 
00195 /* -- see zlib.h -- */
00196 gzFile ZEXPORT gzopen(path, mode)
00197     const char *path;
00198     const char *mode;
00199 {
00200     return gz_open(path, -1, mode);
00201 }
00202 
00203 /* -- see zlib.h -- */
00204 gzFile ZEXPORT gzopen64(path, mode)
00205     const char *path;
00206     const char *mode;
00207 {
00208     return gz_open(path, -1, mode);
00209 }
00210 
00211 /* -- see zlib.h -- */
00212 gzFile ZEXPORT gzdopen(fd, mode)
00213     int fd;
00214     const char *mode;
00215 {
00216     char *path;         /* identifier for error messages */
00217     gzFile gz;
00218 
00219     if (fd == -1 || (path = malloc(7 + 3 * sizeof(int))) == NULL)
00220         return NULL;
00221     sprintf(path, "<fd:%d>", fd);   /* for debugging */
00222     gz = gz_open(path, fd, mode);
00223     free(path);
00224     return gz;
00225 }
00226 
00227 /* -- see zlib.h -- */
00228 int ZEXPORT gzbuffer(file, size)
00229     gzFile file;
00230     unsigned size;
00231 {
00232     gz_statep state;
00233 
00234     /* get internal structure and check integrity */
00235     if (file == NULL)
00236         return -1;
00237     state = (gz_statep)file;
00238     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
00239         return -1;
00240 
00241     /* make sure we haven't already allocated memory */
00242     if (state->size != 0)
00243         return -1;
00244 
00245     /* check and set requested size */
00246     if (size == 0)
00247         return -1;
00248     state->want = size;
00249     return 0;
00250 }
00251 
00252 /* -- see zlib.h -- */
00253 int ZEXPORT gzrewind(file)
00254     gzFile file;
00255 {
00256     gz_statep state;
00257 
00258     /* get internal structure */
00259     if (file == NULL)
00260         return -1;
00261     state = (gz_statep)file;
00262 
00263     /* check that we're reading and that there's no error */
00264     if (state->mode != GZ_READ || state->err != Z_OK)
00265         return -1;
00266 
00267     /* back up and start over */
00268     if (LSEEK(state->fd, state->start, SEEK_SET) == -1)
00269         return -1;
00270     gz_reset(state);
00271     return 0;
00272 }
00273 
00274 /* -- see zlib.h -- */
00275 z_off64_t ZEXPORT gzseek64(file, offset, whence)
00276     gzFile file;
00277     z_off64_t offset;
00278     int whence;
00279 {
00280     unsigned n;
00281     z_off64_t ret;
00282     gz_statep state;
00283 
00284     /* get internal structure and check integrity */
00285     if (file == NULL)
00286         return -1;
00287     state = (gz_statep)file;
00288     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
00289         return -1;
00290 
00291     /* check that there's no error */
00292     if (state->err != Z_OK)
00293         return -1;
00294 
00295     /* can only seek from start or relative to current position */
00296     if (whence != SEEK_SET && whence != SEEK_CUR)
00297         return -1;
00298 
00299     /* normalize offset to a SEEK_CUR specification */
00300     if (whence == SEEK_SET)
00301         offset -= state->pos;
00302     else if (state->seek)
00303         offset += state->skip;
00304     state->seek = 0;
00305 
00306     /* if within raw area while reading, just go there */
00307     if (state->mode == GZ_READ && state->how == COPY &&
00308         state->pos + offset >= state->raw) {
00309         ret = LSEEK(state->fd, offset - state->have, SEEK_CUR);
00310         if (ret == -1)
00311             return -1;
00312         state->have = 0;
00313         state->eof = 0;
00314         state->seek = 0;
00315         gz_error(state, Z_OK, NULL);
00316         state->strm.avail_in = 0;
00317         state->pos += offset;
00318         return state->pos;
00319     }
00320 
00321     /* calculate skip amount, rewinding if needed for back seek when reading */
00322     if (offset < 0) {
00323         if (state->mode != GZ_READ)         /* writing -- can't go backwards */
00324             return -1;
00325         offset += state->pos;
00326         if (offset < 0)                     /* before start of file! */
00327             return -1;
00328         if (gzrewind(file) == -1)           /* rewind, then skip to offset */
00329             return -1;
00330     }
00331 
00332     /* if reading, skip what's in output buffer (one less gzgetc() check) */
00333     if (state->mode == GZ_READ) {
00334         n = GT_OFF(state->have) || (z_off64_t)state->have > offset ?
00335             (unsigned)offset : state->have;
00336         state->have -= n;
00337         state->next += n;
00338         state->pos += n;
00339         offset -= n;
00340     }
00341 
00342     /* request skip (if not zero) */
00343     if (offset) {
00344         state->seek = 1;
00345         state->skip = offset;
00346     }
00347     return state->pos + offset;
00348 }
00349 
00350 /* -- see zlib.h -- */
00351 z_off_t ZEXPORT gzseek(file, offset, whence)
00352     gzFile file;
00353     z_off_t offset;
00354     int whence;
00355 {
00356     z_off64_t ret;
00357 
00358     ret = gzseek64(file, (z_off64_t)offset, whence);
00359     return ret == (z_off_t)ret ? (z_off_t)ret : -1;
00360 }
00361 
00362 /* -- see zlib.h -- */
00363 z_off64_t ZEXPORT gztell64(file)
00364     gzFile file;
00365 {
00366     gz_statep state;
00367 
00368     /* get internal structure and check integrity */
00369     if (file == NULL)
00370         return -1;
00371     state = (gz_statep)file;
00372     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
00373         return -1;
00374 
00375     /* return position */
00376     return state->pos + (state->seek ? state->skip : 0);
00377 }
00378 
00379 /* -- see zlib.h -- */
00380 z_off_t ZEXPORT gztell(file)
00381     gzFile file;
00382 {
00383     z_off64_t ret;
00384 
00385     ret = gztell64(file);
00386     return ret == (z_off_t)ret ? (z_off_t)ret : -1;
00387 }
00388 
00389 /* -- see zlib.h -- */
00390 z_off64_t ZEXPORT gzoffset64(file)
00391     gzFile file;
00392 {
00393     z_off64_t offset;
00394     gz_statep state;
00395 
00396     /* get internal structure and check integrity */
00397     if (file == NULL)
00398         return -1;
00399     state = (gz_statep)file;
00400     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
00401         return -1;
00402 
00403     /* compute and return effective offset in file */
00404     offset = LSEEK(state->fd, 0, SEEK_CUR);
00405     if (offset == -1)
00406         return -1;
00407     if (state->mode == GZ_READ)             /* reading */
00408         offset -= state->strm.avail_in;     /* don't count buffered input */
00409     return offset;
00410 }
00411 
00412 /* -- see zlib.h -- */
00413 z_off_t ZEXPORT gzoffset(file)
00414     gzFile file;
00415 {
00416     z_off64_t ret;
00417 
00418     ret = gzoffset64(file);
00419     return ret == (z_off_t)ret ? (z_off_t)ret : -1;
00420 }
00421 
00422 /* -- see zlib.h -- */
00423 int ZEXPORT gzeof(file)
00424     gzFile file;
00425 {
00426     gz_statep state;
00427 
00428     /* get internal structure and check integrity */
00429     if (file == NULL)
00430         return 0;
00431     state = (gz_statep)file;
00432     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
00433         return 0;
00434 
00435     /* return end-of-file state */
00436     return state->mode == GZ_READ ?
00437         (state->eof && state->strm.avail_in == 0 && state->have == 0) : 0;
00438 }
00439 
00440 /* -- see zlib.h -- */
00441 const char * ZEXPORT gzerror(file, errnum)
00442     gzFile file;
00443     int *errnum;
00444 {
00445     gz_statep state;
00446 
00447     /* get internal structure and check integrity */
00448     if (file == NULL)
00449         return NULL;
00450     state = (gz_statep)file;
00451     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
00452         return NULL;
00453 
00454     /* return error information */
00455     if (errnum != NULL)
00456         *errnum = state->err;
00457     return state->msg == NULL ? "" : state->msg;
00458 }
00459 
00460 /* -- see zlib.h -- */
00461 void ZEXPORT gzclearerr(file)
00462     gzFile file;
00463 {
00464     gz_statep state;
00465 
00466     /* get internal structure and check integrity */
00467     if (file == NULL)
00468         return;
00469     state = (gz_statep)file;
00470     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
00471         return;
00472 
00473     /* clear error and end-of-file */
00474     if (state->mode == GZ_READ)
00475         state->eof = 0;
00476     gz_error(state, Z_OK, NULL);
00477 }
00478 
00479 /* Create an error message in allocated memory and set state->err and
00480    state->msg accordingly.  Free any previous error message already there.  Do
00481    not try to free or allocate space if the error is Z_MEM_ERROR (out of
00482    memory).  Simply save the error message as a static string.  If there is an
00483    allocation failure constructing the error message, then convert the error to
00484    out of memory. */
00485 void ZLIB_INTERNAL gz_error(state, err, msg)
00486     gz_statep state;
00487     int err;
00488     const char *msg;
00489 {
00490     /* free previously allocated message and clear */
00491     if (state->msg != NULL) {
00492         if (state->err != Z_MEM_ERROR)
00493             free(state->msg);
00494         state->msg = NULL;
00495     }
00496 
00497     /* set error code, and if no message, then done */
00498     state->err = err;
00499     if (msg == NULL)
00500         return;
00501 
00502     /* for an out of memory error, save as static string */
00503     if (err == Z_MEM_ERROR) {
00504         state->msg = (char *)msg;
00505         return;
00506     }
00507 
00508     /* construct error message with path */
00509     if ((state->msg = malloc(strlen(state->path) + strlen(msg) + 3)) == NULL) {
00510         state->err = Z_MEM_ERROR;
00511         state->msg = (char *)"out of memory";
00512         return;
00513     }
00514     strcpy(state->msg, state->path);
00515     strcat(state->msg, ": ");
00516     strcat(state->msg, msg);
00517     return;
00518 }
00519 
00520 #ifndef INT_MAX
00521 /* portably return maximum value for an int (when limits.h presumed not
00522    available) -- we need to do this to cover cases where 2's complement not
00523    used, since C standard permits 1's complement and sign-bit representations,
00524    otherwise we could just use ((unsigned)-1) >> 1 */
00525 unsigned ZLIB_INTERNAL gz_intmax()
00526 {
00527     unsigned p, q;
00528 
00529     p = 1;
00530     do {
00531         q = p;
00532         p <<= 1;
00533         p++;
00534     } while (p > q);
00535     return q >> 1;
00536 }
00537 #endif

Generated on Wed Oct 20 2010 11:12:17 for APBS by  doxygen 1.7.2