Annotation of embedaddon/sudo/zlib/gzlib.c, revision 1.1.1.1

1.1       misho       1: /* gzlib.c -- zlib functions common to reading and writing gzip files
                      2:  * Copyright (C) 2004, 2010 Mark Adler
                      3:  * For conditions of distribution and use, see copyright notice in zlib.h
                      4:  */
                      5: 
                      6: #include "gzguts.h"
                      7: 
                      8: #if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
                      9: #  define LSEEK lseek64
                     10: #else
                     11: #  define LSEEK lseek
                     12: #endif
                     13: 
                     14: /* Local functions */
                     15: local void gz_reset OF((gz_statep));
                     16: local gzFile gz_open OF((const char *, int, const char *));
                     17: 
                     18: #if defined UNDER_CE
                     19: 
                     20: /* Map the Windows error number in ERROR to a locale-dependent error message
                     21:    string and return a pointer to it.  Typically, the values for ERROR come
                     22:    from GetLastError.
                     23: 
                     24:    The string pointed to shall not be modified by the application, but may be
                     25:    overwritten by a subsequent call to gz_strwinerror
                     26: 
                     27:    The gz_strwinerror function does not change the current setting of
                     28:    GetLastError. */
                     29: char ZLIB_INTERNAL *gz_strwinerror (error)
                     30:      DWORD error;
                     31: {
                     32:     static char buf[1024];
                     33: 
                     34:     wchar_t *msgbuf;
                     35:     DWORD lasterr = GetLastError();
                     36:     DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
                     37:         | FORMAT_MESSAGE_ALLOCATE_BUFFER,
                     38:         NULL,
                     39:         error,
                     40:         0, /* Default language */
                     41:         (LPVOID)&msgbuf,
                     42:         0,
                     43:         NULL);
                     44:     if (chars != 0) {
                     45:         /* If there is an \r\n appended, zap it.  */
                     46:         if (chars >= 2
                     47:             && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
                     48:             chars -= 2;
                     49:             msgbuf[chars] = 0;
                     50:         }
                     51: 
                     52:         if (chars > sizeof (buf) - 1) {
                     53:             chars = sizeof (buf) - 1;
                     54:             msgbuf[chars] = 0;
                     55:         }
                     56: 
                     57:         wcstombs(buf, msgbuf, chars + 1);
                     58:         LocalFree(msgbuf);
                     59:     }
                     60:     else {
                     61:         sprintf(buf, "unknown win32 error (%ld)", error);
                     62:     }
                     63: 
                     64:     SetLastError(lasterr);
                     65:     return buf;
                     66: }
                     67: 
                     68: #endif /* UNDER_CE */
                     69: 
                     70: /* Reset gzip file state */
                     71: local void gz_reset(state)
                     72:     gz_statep state;
                     73: {
                     74:     if (state->mode == GZ_READ) {   /* for reading ... */
                     75:         state->have = 0;            /* no output data available */
                     76:         state->eof = 0;             /* not at end of file */
                     77:         state->how = LOOK;          /* look for gzip header */
                     78:         state->direct = 1;          /* default for empty file */
                     79:     }
                     80:     state->seek = 0;                /* no seek request pending */
                     81:     gz_error(state, Z_OK, NULL);    /* clear error */
                     82:     state->pos = 0;                 /* no uncompressed data yet */
                     83:     state->strm.avail_in = 0;       /* no input data yet */
                     84: }
                     85: 
                     86: /* Open a gzip file either by name or file descriptor. */
                     87: local gzFile gz_open(path, fd, mode)
                     88:     const char *path;
                     89:     int fd;
                     90:     const char *mode;
                     91: {
                     92:     gz_statep state;
                     93: 
                     94:     /* allocate gzFile structure to return */
                     95:     state = malloc(sizeof(gz_state));
                     96:     if (state == NULL)
                     97:         return NULL;
                     98:     state->size = 0;            /* no buffers allocated yet */
                     99:     state->want = GZBUFSIZE;    /* requested buffer size */
                    100:     state->msg = NULL;          /* no error message yet */
                    101: 
                    102:     /* interpret mode */
                    103:     state->mode = GZ_NONE;
                    104:     state->level = Z_DEFAULT_COMPRESSION;
                    105:     state->strategy = Z_DEFAULT_STRATEGY;
                    106:     while (*mode) {
                    107:         if (*mode >= '0' && *mode <= '9')
                    108:             state->level = *mode - '0';
                    109:         else
                    110:             switch (*mode) {
                    111:             case 'r':
                    112:                 state->mode = GZ_READ;
                    113:                 break;
                    114: #ifndef NO_GZCOMPRESS
                    115:             case 'w':
                    116:                 state->mode = GZ_WRITE;
                    117:                 break;
                    118:             case 'a':
                    119:                 state->mode = GZ_APPEND;
                    120:                 break;
                    121: #endif
                    122:             case '+':       /* can't read and write at the same time */
                    123:                 free(state);
                    124:                 return NULL;
                    125:             case 'b':       /* ignore -- will request binary anyway */
                    126:                 break;
                    127:             case 'f':
                    128:                 state->strategy = Z_FILTERED;
                    129:                 break;
                    130:             case 'h':
                    131:                 state->strategy = Z_HUFFMAN_ONLY;
                    132:                 break;
                    133:             case 'R':
                    134:                 state->strategy = Z_RLE;
                    135:                 break;
                    136:             case 'F':
                    137:                 state->strategy = Z_FIXED;
                    138:             default:        /* could consider as an error, but just ignore */
                    139:                 ;
                    140:             }
                    141:         mode++;
                    142:     }
                    143: 
                    144:     /* must provide an "r", "w", or "a" */
                    145:     if (state->mode == GZ_NONE) {
                    146:         free(state);
                    147:         return NULL;
                    148:     }
                    149: 
                    150:     /* save the path name for error messages */
                    151:     state->path = malloc(strlen(path) + 1);
                    152:     if (state->path == NULL) {
                    153:         free(state);
                    154:         return NULL;
                    155:     }
                    156:     strcpy(state->path, path);
                    157: 
                    158:     /* open the file with the appropriate mode (or just use fd) */
                    159:     state->fd = fd != -1 ? fd :
                    160:         open(path,
                    161: #ifdef O_LARGEFILE
                    162:             O_LARGEFILE |
                    163: #endif
                    164: #ifdef O_BINARY
                    165:             O_BINARY |
                    166: #endif
                    167:             (state->mode == GZ_READ ?
                    168:                 O_RDONLY :
                    169:                 (O_WRONLY | O_CREAT | (
                    170:                     state->mode == GZ_WRITE ?
                    171:                         O_TRUNC :
                    172:                         O_APPEND))),
                    173:             0666);
                    174:     if (state->fd == -1) {
                    175:         free(state->path);
                    176:         free(state);
                    177:         return NULL;
                    178:     }
                    179:     if (state->mode == GZ_APPEND)
                    180:         state->mode = GZ_WRITE;         /* simplify later checks */
                    181: 
                    182:     /* save the current position for rewinding (only if reading) */
                    183:     if (state->mode == GZ_READ) {
                    184:         state->start = LSEEK(state->fd, 0, SEEK_CUR);
                    185:         if (state->start == -1) state->start = 0;
                    186:     }
                    187: 
                    188:     /* initialize stream */
                    189:     gz_reset(state);
                    190: 
                    191:     /* return stream */
                    192:     return (gzFile)state;
                    193: }
                    194: 
                    195: /* -- see zlib.h -- */
                    196: gzFile ZEXPORT gzopen(path, mode)
                    197:     const char *path;
                    198:     const char *mode;
                    199: {
                    200:     return gz_open(path, -1, mode);
                    201: }
                    202: 
                    203: /* -- see zlib.h -- */
                    204: gzFile ZEXPORT gzopen64(path, mode)
                    205:     const char *path;
                    206:     const char *mode;
                    207: {
                    208:     return gz_open(path, -1, mode);
                    209: }
                    210: 
                    211: /* -- see zlib.h -- */
                    212: gzFile ZEXPORT gzdopen(fd, mode)
                    213:     int fd;
                    214:     const char *mode;
                    215: {
                    216:     char *path;         /* identifier for error messages */
                    217:     gzFile gz;
                    218: 
                    219:     if (fd == -1 || (path = malloc(7 + 3 * sizeof(int))) == NULL)
                    220:         return NULL;
                    221:     sprintf(path, "<fd:%d>", fd);   /* for debugging */
                    222:     gz = gz_open(path, fd, mode);
                    223:     free(path);
                    224:     return gz;
                    225: }
                    226: 
                    227: /* -- see zlib.h -- */
                    228: int ZEXPORT gzbuffer(file, size)
                    229:     gzFile file;
                    230:     unsigned size;
                    231: {
                    232:     gz_statep state;
                    233: 
                    234:     /* get internal structure and check integrity */
                    235:     if (file == NULL)
                    236:         return -1;
                    237:     state = (gz_statep)file;
                    238:     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
                    239:         return -1;
                    240: 
                    241:     /* make sure we haven't already allocated memory */
                    242:     if (state->size != 0)
                    243:         return -1;
                    244: 
                    245:     /* check and set requested size */
                    246:     if (size == 0)
                    247:         return -1;
                    248:     state->want = size;
                    249:     return 0;
                    250: }
                    251: 
                    252: /* -- see zlib.h -- */
                    253: int ZEXPORT gzrewind(file)
                    254:     gzFile file;
                    255: {
                    256:     gz_statep state;
                    257: 
                    258:     /* get internal structure */
                    259:     if (file == NULL)
                    260:         return -1;
                    261:     state = (gz_statep)file;
                    262: 
                    263:     /* check that we're reading and that there's no error */
                    264:     if (state->mode != GZ_READ || state->err != Z_OK)
                    265:         return -1;
                    266: 
                    267:     /* back up and start over */
                    268:     if (LSEEK(state->fd, state->start, SEEK_SET) == -1)
                    269:         return -1;
                    270:     gz_reset(state);
                    271:     return 0;
                    272: }
                    273: 
                    274: /* -- see zlib.h -- */
                    275: z_off64_t ZEXPORT gzseek64(file, offset, whence)
                    276:     gzFile file;
                    277:     z_off64_t offset;
                    278:     int whence;
                    279: {
                    280:     unsigned n;
                    281:     z_off64_t ret;
                    282:     gz_statep state;
                    283: 
                    284:     /* get internal structure and check integrity */
                    285:     if (file == NULL)
                    286:         return -1;
                    287:     state = (gz_statep)file;
                    288:     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
                    289:         return -1;
                    290: 
                    291:     /* check that there's no error */
                    292:     if (state->err != Z_OK)
                    293:         return -1;
                    294: 
                    295:     /* can only seek from start or relative to current position */
                    296:     if (whence != SEEK_SET && whence != SEEK_CUR)
                    297:         return -1;
                    298: 
                    299:     /* normalize offset to a SEEK_CUR specification */
                    300:     if (whence == SEEK_SET)
                    301:         offset -= state->pos;
                    302:     else if (state->seek)
                    303:         offset += state->skip;
                    304:     state->seek = 0;
                    305: 
                    306:     /* if within raw area while reading, just go there */
                    307:     if (state->mode == GZ_READ && state->how == COPY &&
                    308:         state->pos + offset >= state->raw) {
                    309:         ret = LSEEK(state->fd, offset - state->have, SEEK_CUR);
                    310:         if (ret == -1)
                    311:             return -1;
                    312:         state->have = 0;
                    313:         state->eof = 0;
                    314:         state->seek = 0;
                    315:         gz_error(state, Z_OK, NULL);
                    316:         state->strm.avail_in = 0;
                    317:         state->pos += offset;
                    318:         return state->pos;
                    319:     }
                    320: 
                    321:     /* calculate skip amount, rewinding if needed for back seek when reading */
                    322:     if (offset < 0) {
                    323:         if (state->mode != GZ_READ)         /* writing -- can't go backwards */
                    324:             return -1;
                    325:         offset += state->pos;
                    326:         if (offset < 0)                     /* before start of file! */
                    327:             return -1;
                    328:         if (gzrewind(file) == -1)           /* rewind, then skip to offset */
                    329:             return -1;
                    330:     }
                    331: 
                    332:     /* if reading, skip what's in output buffer (one less gzgetc() check) */
                    333:     if (state->mode == GZ_READ) {
                    334:         n = GT_OFF(state->have) || (z_off64_t)state->have > offset ?
                    335:             (unsigned)offset : state->have;
                    336:         state->have -= n;
                    337:         state->next += n;
                    338:         state->pos += n;
                    339:         offset -= n;
                    340:     }
                    341: 
                    342:     /* request skip (if not zero) */
                    343:     if (offset) {
                    344:         state->seek = 1;
                    345:         state->skip = offset;
                    346:     }
                    347:     return state->pos + offset;
                    348: }
                    349: 
                    350: /* -- see zlib.h -- */
                    351: z_off_t ZEXPORT gzseek(file, offset, whence)
                    352:     gzFile file;
                    353:     z_off_t offset;
                    354:     int whence;
                    355: {
                    356:     z_off64_t ret;
                    357: 
                    358:     ret = gzseek64(file, (z_off64_t)offset, whence);
                    359:     return ret == (z_off_t)ret ? (z_off_t)ret : -1;
                    360: }
                    361: 
                    362: /* -- see zlib.h -- */
                    363: z_off64_t ZEXPORT gztell64(file)
                    364:     gzFile file;
                    365: {
                    366:     gz_statep state;
                    367: 
                    368:     /* get internal structure and check integrity */
                    369:     if (file == NULL)
                    370:         return -1;
                    371:     state = (gz_statep)file;
                    372:     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
                    373:         return -1;
                    374: 
                    375:     /* return position */
                    376:     return state->pos + (state->seek ? state->skip : 0);
                    377: }
                    378: 
                    379: /* -- see zlib.h -- */
                    380: z_off_t ZEXPORT gztell(file)
                    381:     gzFile file;
                    382: {
                    383:     z_off64_t ret;
                    384: 
                    385:     ret = gztell64(file);
                    386:     return ret == (z_off_t)ret ? (z_off_t)ret : -1;
                    387: }
                    388: 
                    389: /* -- see zlib.h -- */
                    390: z_off64_t ZEXPORT gzoffset64(file)
                    391:     gzFile file;
                    392: {
                    393:     z_off64_t offset;
                    394:     gz_statep state;
                    395: 
                    396:     /* get internal structure and check integrity */
                    397:     if (file == NULL)
                    398:         return -1;
                    399:     state = (gz_statep)file;
                    400:     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
                    401:         return -1;
                    402: 
                    403:     /* compute and return effective offset in file */
                    404:     offset = LSEEK(state->fd, 0, SEEK_CUR);
                    405:     if (offset == -1)
                    406:         return -1;
                    407:     if (state->mode == GZ_READ)             /* reading */
                    408:         offset -= state->strm.avail_in;     /* don't count buffered input */
                    409:     return offset;
                    410: }
                    411: 
                    412: /* -- see zlib.h -- */
                    413: z_off_t ZEXPORT gzoffset(file)
                    414:     gzFile file;
                    415: {
                    416:     z_off64_t ret;
                    417: 
                    418:     ret = gzoffset64(file);
                    419:     return ret == (z_off_t)ret ? (z_off_t)ret : -1;
                    420: }
                    421: 
                    422: /* -- see zlib.h -- */
                    423: int ZEXPORT gzeof(file)
                    424:     gzFile file;
                    425: {
                    426:     gz_statep state;
                    427: 
                    428:     /* get internal structure and check integrity */
                    429:     if (file == NULL)
                    430:         return 0;
                    431:     state = (gz_statep)file;
                    432:     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
                    433:         return 0;
                    434: 
                    435:     /* return end-of-file state */
                    436:     return state->mode == GZ_READ ?
                    437:         (state->eof && state->strm.avail_in == 0 && state->have == 0) : 0;
                    438: }
                    439: 
                    440: /* -- see zlib.h -- */
                    441: const char * ZEXPORT gzerror(file, errnum)
                    442:     gzFile file;
                    443:     int *errnum;
                    444: {
                    445:     gz_statep state;
                    446: 
                    447:     /* get internal structure and check integrity */
                    448:     if (file == NULL)
                    449:         return NULL;
                    450:     state = (gz_statep)file;
                    451:     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
                    452:         return NULL;
                    453: 
                    454:     /* return error information */
                    455:     if (errnum != NULL)
                    456:         *errnum = state->err;
                    457:     return state->msg == NULL ? "" : state->msg;
                    458: }
                    459: 
                    460: /* -- see zlib.h -- */
                    461: void ZEXPORT gzclearerr(file)
                    462:     gzFile file;
                    463: {
                    464:     gz_statep state;
                    465: 
                    466:     /* get internal structure and check integrity */
                    467:     if (file == NULL)
                    468:         return;
                    469:     state = (gz_statep)file;
                    470:     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
                    471:         return;
                    472: 
                    473:     /* clear error and end-of-file */
                    474:     if (state->mode == GZ_READ)
                    475:         state->eof = 0;
                    476:     gz_error(state, Z_OK, NULL);
                    477: }
                    478: 
                    479: /* Create an error message in allocated memory and set state->err and
                    480:    state->msg accordingly.  Free any previous error message already there.  Do
                    481:    not try to free or allocate space if the error is Z_MEM_ERROR (out of
                    482:    memory).  Simply save the error message as a static string.  If there is an
                    483:    allocation failure constructing the error message, then convert the error to
                    484:    out of memory. */
                    485: void ZLIB_INTERNAL gz_error(state, err, msg)
                    486:     gz_statep state;
                    487:     int err;
                    488:     const char *msg;
                    489: {
                    490:     /* free previously allocated message and clear */
                    491:     if (state->msg != NULL) {
                    492:         if (state->err != Z_MEM_ERROR)
                    493:             free(state->msg);
                    494:         state->msg = NULL;
                    495:     }
                    496: 
                    497:     /* set error code, and if no message, then done */
                    498:     state->err = err;
                    499:     if (msg == NULL)
                    500:         return;
                    501: 
                    502:     /* for an out of memory error, save as static string */
                    503:     if (err == Z_MEM_ERROR) {
                    504:         state->msg = (char *)msg;
                    505:         return;
                    506:     }
                    507: 
                    508:     /* construct error message with path */
                    509:     if ((state->msg = malloc(strlen(state->path) + strlen(msg) + 3)) == NULL) {
                    510:         state->err = Z_MEM_ERROR;
                    511:         state->msg = (char *)"out of memory";
                    512:         return;
                    513:     }
                    514:     strcpy(state->msg, state->path);
                    515:     strcat(state->msg, ": ");
                    516:     strcat(state->msg, msg);
                    517:     return;
                    518: }
                    519: 
                    520: #ifndef INT_MAX
                    521: /* portably return maximum value for an int (when limits.h presumed not
                    522:    available) -- we need to do this to cover cases where 2's complement not
                    523:    used, since C standard permits 1's complement and sign-bit representations,
                    524:    otherwise we could just use ((unsigned)-1) >> 1 */
                    525: unsigned ZLIB_INTERNAL gz_intmax()
                    526: {
                    527:     unsigned p, q;
                    528: 
                    529:     p = 1;
                    530:     do {
                    531:         q = p;
                    532:         p <<= 1;
                    533:         p++;
                    534:     } while (p > q);
                    535:     return q >> 1;
                    536: }
                    537: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>