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