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, 2010, 2011, 2012, 2013 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__)
  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     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 _WIN32
 216     if (fd == -2) {
 217         len = wcstombs(NULL, path, 0);
 218         if (len == (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 _WIN32
 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         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 _WIN32
 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         state->mode = GZ_WRITE;         /* simplify later checks */
 277 
 278     /* save the current position for rewinding (only if reading) */
 279     if (state->mode == GZ_READ) {
 280         state->start = LSEEK(state->fd, 0, SEEK_CUR);
 281         if (state->start == -1) state->start = 0;
 282     }
 283 
 284     /* initialize stream */
 285     gz_reset(state);
 286 
 287     /* return stream */
 288     return (gzFile)state;
 289 }
 290 
 291 /* -- see zlib.h -- */
 292 gzFile ZEXPORT gzopen(path, mode)
 293     const char *path;
 294     const char *mode;
 295 {
 296     return gz_open(path, -1, mode);
 297 }
 298 
 299 /* -- see zlib.h -- */
 300 gzFile ZEXPORT gzopen64(path, mode)
 301     const char *path;
 302     const char *mode;
 303 {
 304     return gz_open(path, -1, mode);
 305 }
 306 
 307 /* -- see zlib.h -- */
 308 gzFile ZEXPORT gzdopen(fd, mode)
 309     int fd;
 310     const char *mode;
 311 {
 312     char *path;         /* identifier for error messages */
 313     gzFile gz;
 314 
 315     if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)
 316         return NULL;
 317 #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
 318     snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd); /* for debugging */
 319 #else
 320     sprintf(path, "<fd:%d>", fd);   /* for debugging */
 321 #endif
 322     gz = gz_open(path, fd, mode);
 323     free(path);
 324     return gz;
 325 }
 326 
 327 /* -- see zlib.h -- */
 328 #ifdef _WIN32
 329 gzFile ZEXPORT gzopen_w(path, mode)
 330     const wchar_t *path;
 331     const char *mode;
 332 {
 333     return gz_open(path, -2, mode);
 334 }
 335 #endif
 336 
 337 /* -- see zlib.h -- */
 338 int ZEXPORT gzbuffer(file, size)
 339     gzFile file;
 340     unsigned size;
 341 {
 342     gz_statep state;
 343 
 344     /* get internal structure and check integrity */
 345     if (file == NULL)
 346         return -1;
 347     state = (gz_statep)file;
 348     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
 349         return -1;
 350 
 351     /* make sure we haven't already allocated memory */
 352     if (state->size != 0)
 353         return -1;
 354 
 355     /* check and set requested size */
 356     if (size < 2)
 357         size = 2;               /* need two bytes to check magic header */
 358     state->want = size;
 359     return 0;
 360 }
 361 
 362 /* -- see zlib.h -- */
 363 int ZEXPORT gzrewind(file)
 364     gzFile file;
 365 {
 366     gz_statep state;
 367 
 368     /* get internal structure */
 369     if (file == NULL)
 370         return -1;
 371     state = (gz_statep)file;
 372 
 373     /* check that we're reading and that there's no error */
 374     if (state->mode != GZ_READ ||
 375             (state->err != Z_OK && state->err != Z_BUF_ERROR))
 376         return -1;
 377 
 378     /* back up and start over */
 379     if (LSEEK(state->fd, state->start, SEEK_SET) == -1)
 380         return -1;
 381     gz_reset(state);
 382     return 0;
 383 }
 384 
 385 /* -- see zlib.h -- */
 386 z_off64_t ZEXPORT gzseek64(file, offset, whence)
 387     gzFile file;
 388     z_off64_t offset;
 389     int whence;
 390 {
 391     unsigned n;
 392     z_off64_t ret;
 393     gz_statep state;
 394 
 395     /* get internal structure and check integrity */
 396     if (file == NULL)
 397         return -1;
 398     state = (gz_statep)file;
 399     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
 400         return -1;
 401 
 402     /* check that there's no error */
 403     if (state->err != Z_OK && state->err != Z_BUF_ERROR)
 404         return -1;
 405 
 406     /* can only seek from start or relative to current position */
 407     if (whence != SEEK_SET && whence != SEEK_CUR)
 408         return -1;
 409 
 410     /* normalize offset to a SEEK_CUR specification */
 411     if (whence == SEEK_SET)
 412         offset -= state->x.pos;
 413     else if (state->seek)
 414         offset += state->skip;
 415     state->seek = 0;
 416 
 417     /* if within raw area while reading, just go there */
 418     if (state->mode == GZ_READ && state->how == COPY &&
 419             state->x.pos + offset >= 0) {
 420         ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR);
 421         if (ret == -1)
 422             return -1;
 423         state->x.have = 0;
 424         state->eof = 0;
 425         state->past = 0;
 426         state->seek = 0;
 427         gz_error(state, Z_OK, NULL);
 428         state->strm.avail_in = 0;
 429         state->x.pos += offset;
 430         return state->x.pos;
 431     }
 432 
 433     /* calculate skip amount, rewinding if needed for back seek when reading */
 434     if (offset < 0) {
 435         if (state->mode != GZ_READ)         /* writing -- can't go backwards */
 436             return -1;
 437         offset += state->x.pos;
 438         if (offset < 0)                     /* before start of file! */
 439             return -1;
 440         if (gzrewind(file) == -1)           /* rewind, then skip to offset */
 441             return -1;
 442     }
 443 
 444     /* if reading, skip what's in output buffer (one less gzgetc() check) */
 445     if (state->mode == GZ_READ) {
 446         n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ?
 447             (unsigned)offset : state->x.have;
 448         state->x.have -= n;
 449         state->x.next += n;
 450         state->x.pos += n;
 451         offset -= n;
 452     }
 453 
 454     /* request skip (if not zero) */
 455     if (offset) {
 456         state->seek = 1;
 457         state->skip = offset;
 458     }
 459     return state->x.pos + offset;
 460 }
 461 
 462 /* -- see zlib.h -- */
 463 z_off_t ZEXPORT gzseek(file, offset, whence)
 464     gzFile file;
 465     z_off_t offset;
 466     int whence;
 467 {
 468     z_off64_t ret;
 469 
 470     ret = gzseek64(file, (z_off64_t)offset, whence);
 471     return ret == (z_off_t)ret ? (z_off_t)ret : -1;
 472 }
 473 
 474 /* -- see zlib.h -- */
 475 z_off64_t ZEXPORT gztell64(file)
 476     gzFile file;
 477 {
 478     gz_statep state;
 479 
 480     /* get internal structure and check integrity */
 481     if (file == NULL)
 482         return -1;
 483     state = (gz_statep)file;
 484     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
 485         return -1;
 486 
 487     /* return position */
 488     return state->x.pos + (state->seek ? state->skip : 0);
 489 }
 490 
 491 /* -- see zlib.h -- */
 492 z_off_t ZEXPORT gztell(file)
 493     gzFile file;
 494 {
 495     z_off64_t ret;
 496 
 497     ret = gztell64(file);
 498     return ret == (z_off_t)ret ? (z_off_t)ret : -1;
 499 }
 500 
 501 /* -- see zlib.h -- */
 502 z_off64_t ZEXPORT gzoffset64(file)
 503     gzFile file;
 504 {
 505     z_off64_t offset;
 506     gz_statep state;
 507 
 508     /* get internal structure and check integrity */
 509     if (file == NULL)
 510         return -1;
 511     state = (gz_statep)file;
 512     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
 513         return -1;
 514 
 515     /* compute and return effective offset in file */
 516     offset = LSEEK(state->fd, 0, SEEK_CUR);
 517     if (offset == -1)
 518         return -1;
 519     if (state->mode == GZ_READ)             /* reading */
 520         offset -= state->strm.avail_in;     /* don't count buffered input */
 521     return offset;
 522 }
 523 
 524 /* -- see zlib.h -- */
 525 z_off_t ZEXPORT gzoffset(file)
 526     gzFile file;
 527 {
 528     z_off64_t ret;
 529 
 530     ret = gzoffset64(file);
 531     return ret == (z_off_t)ret ? (z_off_t)ret : -1;
 532 }
 533 
 534 /* -- see zlib.h -- */
 535 int ZEXPORT gzeof(file)
 536     gzFile file;
 537 {
 538     gz_statep state;
 539 
 540     /* get internal structure and check integrity */
 541     if (file == NULL)
 542         return 0;
 543     state = (gz_statep)file;
 544     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
 545         return 0;
 546 
 547     /* return end-of-file state */
 548     return state->mode == GZ_READ ? state->past : 0;
 549 }
 550 
 551 /* -- see zlib.h -- */
 552 const char * ZEXPORT gzerror(file, errnum)
 553     gzFile file;
 554     int *errnum;
 555 {
 556     gz_statep state;
 557 
 558     /* get internal structure and check integrity */
 559     if (file == NULL)
 560         return NULL;
 561     state = (gz_statep)file;
 562     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
 563         return NULL;
 564 
 565     /* return error information */
 566     if (errnum != NULL)
 567         *errnum = state->err;
 568     return state->err == Z_MEM_ERROR ? "out of memory" :
 569                                        (state->msg == NULL ? "" : state->msg);
 570 }
 571 
 572 /* -- see zlib.h -- */
 573 void ZEXPORT gzclearerr(file)
 574     gzFile file;
 575 {
 576     gz_statep state;
 577 
 578     /* get internal structure and check integrity */
 579     if (file == NULL)
 580         return;
 581     state = (gz_statep)file;
 582     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
 583         return;
 584 
 585     /* clear error and end-of-file */
 586     if (state->mode == GZ_READ) {
 587         state->eof = 0;
 588         state->past = 0;
 589     }
 590     gz_error(state, Z_OK, NULL);
 591 }
 592 
 593 /* Create an error message in allocated memory and set state->err and
 594    state->msg accordingly.  Free any previous error message already there.  Do
 595    not try to free or allocate space if the error is Z_MEM_ERROR (out of
 596    memory).  Simply save the error message as a static string.  If there is an
 597    allocation failure constructing the error message, then convert the error to
 598    out of memory. */
 599 void ZLIB_INTERNAL gz_error(state, err, msg)
 600     gz_statep state;
 601     int err;
 602     const char *msg;
 603 {
 604     /* free previously allocated message and clear */
 605     if (state->msg != NULL) {
 606         if (state->err != Z_MEM_ERROR)
 607             free(state->msg);
 608         state->msg = NULL;
 609     }
 610 
 611     /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */
 612     if (err != Z_OK && err != Z_BUF_ERROR)
 613         state->x.have = 0;
 614 
 615     /* set error code, and if no message, then done */
 616     state->err = err;
 617     if (msg == NULL)
 618         return;
 619 
 620     /* for an out of memory error, return literal string when requested */
 621     if (err == Z_MEM_ERROR)
 622         return;
 623 
 624     /* construct error message with path */
 625     if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) ==
 626             NULL) {
 627         state->err = Z_MEM_ERROR;
 628         return;
 629     }
 630 #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
 631     snprintf(state->msg, strlen(state->path) + strlen(msg) + 3,
 632              "%s%s%s", state->path, ": ", msg);
 633 #else
 634     strcpy(state->msg, state->path);
 635     strcat(state->msg, ": ");
 636     strcat(state->msg, msg);
 637 #endif
 638     return;
 639 }
 640 
 641 #ifndef INT_MAX
 642 /* portably return maximum value for an int (when limits.h presumed not
 643    available) -- we need to do this to cover cases where 2's complement not
 644    used, since C standard permits 1's complement and sign-bit representations,
 645    otherwise we could just use ((unsigned)-1) >> 1 */
 646 unsigned ZLIB_INTERNAL gz_intmax()
 647 {
 648     unsigned p, q;
 649 
 650     p = 1;
 651     do {
 652         q = p;
 653         p <<= 1;
 654         p++;
 655     } while (p > q);
 656     return q >> 1;
 657 }
 658 #endif