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

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

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