1 /* gzlib.c -- zlib functions common to reading and writing gzip files
   2  * Copyright (C) 2004, 2010, 2011, 2012, 2013 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(_WIN32) && !defined(__BORLANDC__)
   9 #  define LSEEK _lseeki64
  10 #else
  11 #if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
  12 #  define LSEEK lseek64
  13 #else
  14 #  define LSEEK lseek
  15 #endif
  16 #endif
  17 
  18 /* Local functions */
  19 local void gz_reset OF((gz_statep));
  20 local gzFile gz_open OF((const void *, 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 {
  78     state->x.have = 0;              /* no output data available */
  79     if (state->mode == GZ_READ) {   /* for reading ... */
  80         state->eof = 0;             /* not at end of file */
  81         state->past = 0;            /* have not read past end yet */
  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 */
  86     state->x.pos = 0;               /* no uncompressed data yet */
  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 void *path;
  93     int fd;
  94     const char *mode;
  95 {
  96     gz_statep state;
  97     size_t len;
  98     int oflag;
  99 #ifdef O_CLOEXEC
 100     int cloexec = 0;
 101 #endif
 102 #ifdef O_EXCL
 103     int exclusive = 0;
 104 #endif
 105 
 106     /* check input */
 107     if (path == NULL)
 108         return NULL;
 109 
 110     /* allocate gzFile structure to return */
 111     state = (gz_statep)malloc(sizeof(gz_state));
 112     if (state == NULL)
 113         return NULL;
 114     state->size = 0;            /* no buffers allocated yet */
 115     state->want = GZBUFSIZE;    /* requested buffer size */
 116     state->msg = NULL;          /* no error message yet */
 117 
 118     /* interpret mode */
 119     state->mode = GZ_NONE;
 120     state->level = Z_DEFAULT_COMPRESSION;
 121     state->strategy = Z_DEFAULT_STRATEGY;
 122     state->direct = 0;
 123     while (*mode) {
 124         if (*mode >= '0' && *mode <= '9')
 125             state->level = *mode - '0';
 126         else
 127             switch (*mode) {
 128             case 'r':
 129                 state->mode = GZ_READ;
 130                 break;
 131 #ifndef NO_GZCOMPRESS
 132             case 'w':
 133                 state->mode = GZ_WRITE;
 134                 break;
 135             case 'a':
 136                 state->mode = GZ_APPEND;
 137                 break;
 138 #endif
 139             case '+':       /* can't read and write at the same time */
 140                 free(state);
 141                 return NULL;
 142             case 'b':       /* ignore -- will request binary anyway */
 143                 break;
 144 #ifdef O_CLOEXEC
 145             case 'e':
 146                 cloexec = 1;
 147                 break;
 148 #endif
 149 #ifdef O_EXCL
 150             case 'x':
 151                 exclusive = 1;
 152                 break;
 153 #endif
 154             case 'f':
 155                 state->strategy = Z_FILTERED;
 156                 break;
 157             case 'h':
 158                 state->strategy = Z_HUFFMAN_ONLY;
 159                 break;
 160             case 'R':
 161                 state->strategy = Z_RLE;
 162                 break;
 163             case 'F':
 164                 state->strategy = Z_FIXED;
 165                 break;
 166             case 'T':
 167                 state->direct = 1;
 168                 break;
 169             default:        /* could consider as an error, but just ignore */
 170                 ;
 171             }
 172         mode++;
 173     }
 174 
 175     /* must provide an "r", "w", or "a" */
 176     if (state->mode == GZ_NONE) {
 177         free(state);
 178         return NULL;
 179     }
 180 
 181     /* can't force transparent read */
 182     if (state->mode == GZ_READ) {
 183         if (state->direct) {
 184             free(state);
 185             return NULL;
 186         }
 187         state->direct = 1;      /* for empty file */
 188     }
 189 
 190     /* save the path name for error messages */
 191 #ifdef _WIN32
 192     if (fd == -2) {
 193         len = wcstombs(NULL, path, 0);
 194         if (len == (size_t)-1)
 195             len = 0;
 196     }
 197     else
 198 #endif
 199         len = strlen((const char *)path);
 200     state->path = (char *)malloc(len + 1);
 201     if (state->path == NULL) {
 202         free(state);
 203         return NULL;
 204     }
 205 #ifdef _WIN32
 206     if (fd == -2)
 207         if (len)
 208             wcstombs(state->path, path, len + 1);
 209         else
 210             *(state->path) = 0;
 211     else
 212 #endif
 213 #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
 214         snprintf(state->path, len + 1, "%s", (const char *)path);
 215 #else
 216         strcpy(state->path, path);
 217 #endif
 218 
 219     /* compute the flags for open() */
 220     oflag =
 221 #ifdef O_LARGEFILE
 222         O_LARGEFILE |
 223 #endif
 224 #ifdef O_BINARY
 225         O_BINARY |
 226 #endif
 227 #ifdef O_CLOEXEC
 228         (cloexec ? O_CLOEXEC : 0) |
 229 #endif
 230         (state->mode == GZ_READ ?
 231          O_RDONLY :
 232          (O_WRONLY | O_CREAT |
 233 #ifdef O_EXCL
 234           (exclusive ? O_EXCL : 0) |
 235 #endif
 236           (state->mode == GZ_WRITE ?
 237            O_TRUNC :
 238            O_APPEND)));
 239 
 240     /* open the file with the appropriate flags (or just use fd) */
 241     state->fd = fd > -1 ? fd : (
 242 #ifdef _WIN32
 243         fd == -2 ? _wopen(path, oflag, 0666) :
 244 #endif
 245         open((const char *)path, oflag, 0666));
 246     if (state->fd == -1) {
 247         free(state->path);
 248         free(state);
 249         return NULL;
 250     }
 251     if (state->mode == GZ_APPEND)
 252         state->mode = GZ_WRITE;         /* simplify later checks */
 253 
 254     /* save the current position for rewinding (only if reading) */
 255     if (state->mode == GZ_READ) {
 256         state->start = LSEEK(state->fd, 0, SEEK_CUR);
 257         if (state->start == -1) state->start = 0;
 258     }
 259 
 260     /* initialize stream */
 261     gz_reset(state);
 262 
 263     /* return stream */
 264     return (gzFile)state;
 265 }
 266 
 267 /* -- see zlib.h -- */
 268 gzFile ZEXPORT gzopen(path, mode)
 269     const char *path;
 270     const char *mode;
 271 {
 272     return gz_open(path, -1, mode);
 273 }
 274 
 275 /* -- see zlib.h -- */
 276 gzFile ZEXPORT gzopen64(path, mode)
 277     const char *path;
 278     const char *mode;
 279 {
 280     return gz_open(path, -1, mode);
 281 }
 282 
 283 /* -- see zlib.h -- */
 284 gzFile ZEXPORT gzdopen(fd, mode)
 285     int fd;
 286     const char *mode;
 287 {
 288     char *path;         /* identifier for error messages */
 289     gzFile gz;
 290 
 291     if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)
 292         return NULL;
 293 #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
 294     snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd); /* for debugging */
 295 #else
 296     sprintf(path, "<fd:%d>", fd);   /* for debugging */
 297 #endif
 298     gz = gz_open(path, fd, mode);
 299     free(path);
 300     return gz;
 301 }
 302 
 303 /* -- see zlib.h -- */
 304 #ifdef _WIN32
 305 gzFile ZEXPORT gzopen_w(path, mode)
 306     const wchar_t *path;
 307     const char *mode;
 308 {
 309     return gz_open(path, -2, mode);
 310 }
 311 #endif
 312 
 313 /* -- see zlib.h -- */
 314 int ZEXPORT gzbuffer(file, size)
 315     gzFile file;
 316     unsigned size;
 317 {
 318     gz_statep state;
 319 
 320     /* get internal structure and check integrity */
 321     if (file == NULL)
 322         return -1;
 323     state = (gz_statep)file;
 324     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
 325         return -1;
 326 
 327     /* make sure we haven't already allocated memory */
 328     if (state->size != 0)
 329         return -1;
 330 
 331     /* check and set requested size */
 332     if (size < 2)
 333         size = 2;               /* need two bytes to check magic header */
 334     state->want = size;
 335     return 0;
 336 }
 337 
 338 /* -- see zlib.h -- */
 339 int ZEXPORT gzrewind(file)
 340     gzFile file;
 341 {
 342     gz_statep state;
 343 
 344     /* get internal structure */
 345     if (file == NULL)
 346         return -1;
 347     state = (gz_statep)file;
 348 
 349     /* check that we're reading and that there's no error */
 350     if (state->mode != GZ_READ ||
 351             (state->err != Z_OK && state->err != Z_BUF_ERROR))
 352         return -1;
 353 
 354     /* back up and start over */
 355     if (LSEEK(state->fd, state->start, SEEK_SET) == -1)
 356         return -1;
 357     gz_reset(state);
 358     return 0;
 359 }
 360 
 361 /* -- see zlib.h -- */
 362 z_off64_t ZEXPORT gzseek64(file, offset, whence)
 363     gzFile file;
 364     z_off64_t offset;
 365     int whence;
 366 {
 367     unsigned n;
 368     z_off64_t ret;
 369     gz_statep state;
 370 
 371     /* get internal structure and check integrity */
 372     if (file == NULL)
 373         return -1;
 374     state = (gz_statep)file;
 375     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
 376         return -1;
 377 
 378     /* check that there's no error */
 379     if (state->err != Z_OK && state->err != Z_BUF_ERROR)
 380         return -1;
 381 
 382     /* can only seek from start or relative to current position */
 383     if (whence != SEEK_SET && whence != SEEK_CUR)
 384         return -1;
 385 
 386     /* normalize offset to a SEEK_CUR specification */
 387     if (whence == SEEK_SET)
 388         offset -= state->x.pos;
 389     else if (state->seek)
 390         offset += state->skip;
 391     state->seek = 0;
 392 
 393     /* if within raw area while reading, just go there */
 394     if (state->mode == GZ_READ && state->how == COPY &&
 395             state->x.pos + offset >= 0) {
 396         ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR);
 397         if (ret == -1)
 398             return -1;
 399         state->x.have = 0;
 400         state->eof = 0;
 401         state->past = 0;
 402         state->seek = 0;
 403         gz_error(state, Z_OK, NULL);
 404         state->strm.avail_in = 0;
 405         state->x.pos += offset;
 406         return state->x.pos;
 407     }
 408 
 409     /* calculate skip amount, rewinding if needed for back seek when reading */
 410     if (offset < 0) {
 411         if (state->mode != GZ_READ)         /* writing -- can't go backwards */
 412             return -1;
 413         offset += state->x.pos;
 414         if (offset < 0)                     /* before start of file! */
 415             return -1;
 416         if (gzrewind(file) == -1)           /* rewind, then skip to offset */
 417             return -1;
 418     }
 419 
 420     /* if reading, skip what's in output buffer (one less gzgetc() check) */
 421     if (state->mode == GZ_READ) {
 422         n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ?
 423             (unsigned)offset : state->x.have;
 424         state->x.have -= n;
 425         state->x.next += n;
 426         state->x.pos += n;
 427         offset -= n;
 428     }
 429 
 430     /* request skip (if not zero) */
 431     if (offset) {
 432         state->seek = 1;
 433         state->skip = offset;
 434     }
 435     return state->x.pos + offset;
 436 }
 437 
 438 /* -- see zlib.h -- */
 439 z_off_t ZEXPORT gzseek(file, offset, whence)
 440     gzFile file;
 441     z_off_t offset;
 442     int whence;
 443 {
 444     z_off64_t ret;
 445 
 446     ret = gzseek64(file, (z_off64_t)offset, whence);
 447     return ret == (z_off_t)ret ? (z_off_t)ret : -1;
 448 }
 449 
 450 /* -- see zlib.h -- */
 451 z_off64_t ZEXPORT gztell64(file)
 452     gzFile file;
 453 {
 454     gz_statep state;
 455 
 456     /* get internal structure and check integrity */
 457     if (file == NULL)
 458         return -1;
 459     state = (gz_statep)file;
 460     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
 461         return -1;
 462 
 463     /* return position */
 464     return state->x.pos + (state->seek ? state->skip : 0);
 465 }
 466 
 467 /* -- see zlib.h -- */
 468 z_off_t ZEXPORT gztell(file)
 469     gzFile file;
 470 {
 471     z_off64_t ret;
 472 
 473     ret = gztell64(file);
 474     return ret == (z_off_t)ret ? (z_off_t)ret : -1;
 475 }
 476 
 477 /* -- see zlib.h -- */
 478 z_off64_t ZEXPORT gzoffset64(file)
 479     gzFile file;
 480 {
 481     z_off64_t offset;
 482     gz_statep state;
 483 
 484     /* get internal structure and check integrity */
 485     if (file == NULL)
 486         return -1;
 487     state = (gz_statep)file;
 488     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
 489         return -1;
 490 
 491     /* compute and return effective offset in file */
 492     offset = LSEEK(state->fd, 0, SEEK_CUR);
 493     if (offset == -1)
 494         return -1;
 495     if (state->mode == GZ_READ)             /* reading */
 496         offset -= state->strm.avail_in;     /* don't count buffered input */
 497     return offset;
 498 }
 499 
 500 /* -- see zlib.h -- */
 501 z_off_t ZEXPORT gzoffset(file)
 502     gzFile file;
 503 {
 504     z_off64_t ret;
 505 
 506     ret = gzoffset64(file);
 507     return ret == (z_off_t)ret ? (z_off_t)ret : -1;
 508 }
 509 
 510 /* -- see zlib.h -- */
 511 int ZEXPORT gzeof(file)
 512     gzFile file;
 513 {
 514     gz_statep state;
 515 
 516     /* get internal structure and check integrity */
 517     if (file == NULL)
 518         return 0;
 519     state = (gz_statep)file;
 520     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
 521         return 0;
 522 
 523     /* return end-of-file state */
 524     return state->mode == GZ_READ ? state->past : 0;
 525 }
 526 
 527 /* -- see zlib.h -- */
 528 const char * ZEXPORT gzerror(file, errnum)
 529     gzFile file;
 530     int *errnum;
 531 {
 532     gz_statep state;
 533 
 534     /* get internal structure and check integrity */
 535     if (file == NULL)
 536         return NULL;
 537     state = (gz_statep)file;
 538     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
 539         return NULL;
 540 
 541     /* return error information */
 542     if (errnum != NULL)
 543         *errnum = state->err;
 544     return state->err == Z_MEM_ERROR ? "out of memory" :
 545                                        (state->msg == NULL ? "" : state->msg);
 546 }
 547 
 548 /* -- see zlib.h -- */
 549 void ZEXPORT gzclearerr(file)
 550     gzFile file;
 551 {
 552     gz_statep state;
 553 
 554     /* get internal structure and check integrity */
 555     if (file == NULL)
 556         return;
 557     state = (gz_statep)file;
 558     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
 559         return;
 560 
 561     /* clear error and end-of-file */
 562     if (state->mode == GZ_READ) {
 563         state->eof = 0;
 564         state->past = 0;
 565     }
 566     gz_error(state, Z_OK, NULL);
 567 }
 568 
 569 /* Create an error message in allocated memory and set state->err and
 570    state->msg accordingly.  Free any previous error message already there.  Do
 571    not try to free or allocate space if the error is Z_MEM_ERROR (out of
 572    memory).  Simply save the error message as a static string.  If there is an
 573    allocation failure constructing the error message, then convert the error to
 574    out of memory. */
 575 void ZLIB_INTERNAL gz_error(state, err, msg)
 576     gz_statep state;
 577     int err;
 578     const char *msg;
 579 {
 580     /* free previously allocated message and clear */
 581     if (state->msg != NULL) {
 582         if (state->err != Z_MEM_ERROR)
 583             free(state->msg);
 584         state->msg = NULL;
 585     }
 586 
 587     /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */
 588     if (err != Z_OK && err != Z_BUF_ERROR)
 589         state->x.have = 0;
 590 
 591     /* set error code, and if no message, then done */
 592     state->err = err;
 593     if (msg == NULL)
 594         return;
 595 
 596     /* for an out of memory error, return literal string when requested */
 597     if (err == Z_MEM_ERROR)
 598         return;
 599 
 600     /* construct error message with path */
 601     if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) ==
 602             NULL) {
 603         state->err = Z_MEM_ERROR;
 604         return;
 605     }
 606 #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
 607     snprintf(state->msg, strlen(state->path) + strlen(msg) + 3,
 608              "%s%s%s", state->path, ": ", msg);
 609 #else
 610     strcpy(state->msg, state->path);
 611     strcat(state->msg, ": ");
 612     strcat(state->msg, msg);
 613 #endif
 614     return;
 615 }
 616 
 617 #ifndef INT_MAX
 618 /* portably return maximum value for an int (when limits.h presumed not
 619    available) -- we need to do this to cover cases where 2's complement not
 620    used, since C standard permits 1's complement and sign-bit representations,
 621    otherwise we could just use ((unsigned)-1) >> 1 */
 622 unsigned ZLIB_INTERNAL gz_intmax()
 623 {
 624     unsigned p, q;
 625 
 626     p = 1;
 627     do {
 628         q = p;
 629         p <<= 1;
 630         p++;
 631     } while (p > q);
 632     return q >> 1;
 633 }
 634 #endif