Path: blob/master/src/java.base/share/native/libzip/zlib/gzlib.c
41153 views
/*1* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.2*3* This code is free software; you can redistribute it and/or modify it4* under the terms of the GNU General Public License version 2 only, as5* published by the Free Software Foundation. Oracle designates this6* particular file as subject to the "Classpath" exception as provided7* by Oracle in the LICENSE file that accompanied this code.8*9* This code is distributed in the hope that it will be useful, but WITHOUT10* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or11* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License12* version 2 for more details (a copy is included in the LICENSE file that13* accompanied this code).14*15* You should have received a copy of the GNU General Public License version16* 2 along with this work; if not, write to the Free Software Foundation,17* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.18*19* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA20* or visit www.oracle.com if you need additional information or have any21* questions.22*/2324/* gzlib.c -- zlib functions common to reading and writing gzip files25* Copyright (C) 2004-2017 Mark Adler26* For conditions of distribution and use, see copyright notice in zlib.h27*/2829#include "gzguts.h"3031#if defined(_WIN32) && !defined(__BORLANDC__) && !defined(__MINGW32__)32# define LSEEK _lseeki6433#else34#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-035# define LSEEK lseek6436#else37# define LSEEK lseek38#endif39#endif4041/* Local functions */42local void gz_reset OF((gz_statep));43local gzFile gz_open OF((const void *, int, const char *));4445#if defined UNDER_CE4647/* Map the Windows error number in ERROR to a locale-dependent error message48string and return a pointer to it. Typically, the values for ERROR come49from GetLastError.5051The string pointed to shall not be modified by the application, but may be52overwritten by a subsequent call to gz_strwinerror5354The gz_strwinerror function does not change the current setting of55GetLastError. */56char ZLIB_INTERNAL *gz_strwinerror (error)57DWORD error;58{59static char buf[1024];6061wchar_t *msgbuf;62DWORD lasterr = GetLastError();63DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM64| FORMAT_MESSAGE_ALLOCATE_BUFFER,65NULL,66error,670, /* Default language */68(LPVOID)&msgbuf,690,70NULL);71if (chars != 0) {72/* If there is an \r\n appended, zap it. */73if (chars >= 274&& msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {75chars -= 2;76msgbuf[chars] = 0;77}7879if (chars > sizeof (buf) - 1) {80chars = sizeof (buf) - 1;81msgbuf[chars] = 0;82}8384wcstombs(buf, msgbuf, chars + 1);85LocalFree(msgbuf);86}87else {88sprintf(buf, "unknown win32 error (%ld)", error);89}9091SetLastError(lasterr);92return buf;93}9495#endif /* UNDER_CE */9697/* Reset gzip file state */98local void gz_reset(state)99gz_statep state;100{101state->x.have = 0; /* no output data available */102if (state->mode == GZ_READ) { /* for reading ... */103state->eof = 0; /* not at end of file */104state->past = 0; /* have not read past end yet */105state->how = LOOK; /* look for gzip header */106}107state->seek = 0; /* no seek request pending */108gz_error(state, Z_OK, NULL); /* clear error */109state->x.pos = 0; /* no uncompressed data yet */110state->strm.avail_in = 0; /* no input data yet */111}112113/* Open a gzip file either by name or file descriptor. */114local gzFile gz_open(path, fd, mode)115const void *path;116int fd;117const char *mode;118{119gz_statep state;120z_size_t len;121int oflag;122#ifdef O_CLOEXEC123int cloexec = 0;124#endif125#ifdef O_EXCL126int exclusive = 0;127#endif128129/* check input */130if (path == NULL)131return NULL;132133/* allocate gzFile structure to return */134state = (gz_statep)malloc(sizeof(gz_state));135if (state == NULL)136return NULL;137state->size = 0; /* no buffers allocated yet */138state->want = GZBUFSIZE; /* requested buffer size */139state->msg = NULL; /* no error message yet */140141/* interpret mode */142state->mode = GZ_NONE;143state->level = Z_DEFAULT_COMPRESSION;144state->strategy = Z_DEFAULT_STRATEGY;145state->direct = 0;146while (*mode) {147if (*mode >= '0' && *mode <= '9')148state->level = *mode - '0';149else150switch (*mode) {151case 'r':152state->mode = GZ_READ;153break;154#ifndef NO_GZCOMPRESS155case 'w':156state->mode = GZ_WRITE;157break;158case 'a':159state->mode = GZ_APPEND;160break;161#endif162case '+': /* can't read and write at the same time */163free(state);164return NULL;165case 'b': /* ignore -- will request binary anyway */166break;167#ifdef O_CLOEXEC168case 'e':169cloexec = 1;170break;171#endif172#ifdef O_EXCL173case 'x':174exclusive = 1;175break;176#endif177case 'f':178state->strategy = Z_FILTERED;179break;180case 'h':181state->strategy = Z_HUFFMAN_ONLY;182break;183case 'R':184state->strategy = Z_RLE;185break;186case 'F':187state->strategy = Z_FIXED;188break;189case 'T':190state->direct = 1;191break;192default: /* could consider as an error, but just ignore */193;194}195mode++;196}197198/* must provide an "r", "w", or "a" */199if (state->mode == GZ_NONE) {200free(state);201return NULL;202}203204/* can't force transparent read */205if (state->mode == GZ_READ) {206if (state->direct) {207free(state);208return NULL;209}210state->direct = 1; /* for empty file */211}212213/* save the path name for error messages */214#ifdef WIDECHAR215if (fd == -2) {216len = wcstombs(NULL, path, 0);217if (len == (z_size_t)-1)218len = 0;219}220else221#endif222len = strlen((const char *)path);223state->path = (char *)malloc(len + 1);224if (state->path == NULL) {225free(state);226return NULL;227}228#ifdef WIDECHAR229if (fd == -2)230if (len)231wcstombs(state->path, path, len + 1);232else233*(state->path) = 0;234else235#endif236#if !defined(NO_snprintf) && !defined(NO_vsnprintf)237(void)snprintf(state->path, len + 1, "%s", (const char *)path);238#else239strcpy(state->path, path);240#endif241242/* compute the flags for open() */243oflag =244#ifdef O_LARGEFILE245O_LARGEFILE |246#endif247#ifdef O_BINARY248O_BINARY |249#endif250#ifdef O_CLOEXEC251(cloexec ? O_CLOEXEC : 0) |252#endif253(state->mode == GZ_READ ?254O_RDONLY :255(O_WRONLY | O_CREAT |256#ifdef O_EXCL257(exclusive ? O_EXCL : 0) |258#endif259(state->mode == GZ_WRITE ?260O_TRUNC :261O_APPEND)));262263/* open the file with the appropriate flags (or just use fd) */264state->fd = fd > -1 ? fd : (265#ifdef WIDECHAR266fd == -2 ? _wopen(path, oflag, 0666) :267#endif268open((const char *)path, oflag, 0666));269if (state->fd == -1) {270free(state->path);271free(state);272return NULL;273}274if (state->mode == GZ_APPEND) {275LSEEK(state->fd, 0, SEEK_END); /* so gzoffset() is correct */276state->mode = GZ_WRITE; /* simplify later checks */277}278279/* save the current position for rewinding (only if reading) */280if (state->mode == GZ_READ) {281state->start = LSEEK(state->fd, 0, SEEK_CUR);282if (state->start == -1) state->start = 0;283}284285/* initialize stream */286gz_reset(state);287288/* return stream */289return (gzFile)state;290}291292/* -- see zlib.h -- */293gzFile ZEXPORT gzopen(path, mode)294const char *path;295const char *mode;296{297return gz_open(path, -1, mode);298}299300/* -- see zlib.h -- */301gzFile ZEXPORT gzopen64(path, mode)302const char *path;303const char *mode;304{305return gz_open(path, -1, mode);306}307308/* -- see zlib.h -- */309gzFile ZEXPORT gzdopen(fd, mode)310int fd;311const char *mode;312{313char *path; /* identifier for error messages */314gzFile gz;315316if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)317return NULL;318#if !defined(NO_snprintf) && !defined(NO_vsnprintf)319(void)snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd);320#else321sprintf(path, "<fd:%d>", fd); /* for debugging */322#endif323gz = gz_open(path, fd, mode);324free(path);325return gz;326}327328/* -- see zlib.h -- */329#ifdef WIDECHAR330gzFile ZEXPORT gzopen_w(path, mode)331const wchar_t *path;332const char *mode;333{334return gz_open(path, -2, mode);335}336#endif337338/* -- see zlib.h -- */339int ZEXPORT gzbuffer(file, size)340gzFile file;341unsigned size;342{343gz_statep state;344345/* get internal structure and check integrity */346if (file == NULL)347return -1;348state = (gz_statep)file;349if (state->mode != GZ_READ && state->mode != GZ_WRITE)350return -1;351352/* make sure we haven't already allocated memory */353if (state->size != 0)354return -1;355356/* check and set requested size */357if ((size << 1) < size)358return -1; /* need to be able to double it */359if (size < 2)360size = 2; /* need two bytes to check magic header */361state->want = size;362return 0;363}364365/* -- see zlib.h -- */366int ZEXPORT gzrewind(file)367gzFile file;368{369gz_statep state;370371/* get internal structure */372if (file == NULL)373return -1;374state = (gz_statep)file;375376/* check that we're reading and that there's no error */377if (state->mode != GZ_READ ||378(state->err != Z_OK && state->err != Z_BUF_ERROR))379return -1;380381/* back up and start over */382if (LSEEK(state->fd, state->start, SEEK_SET) == -1)383return -1;384gz_reset(state);385return 0;386}387388/* -- see zlib.h -- */389z_off64_t ZEXPORT gzseek64(file, offset, whence)390gzFile file;391z_off64_t offset;392int whence;393{394unsigned n;395z_off64_t ret;396gz_statep state;397398/* get internal structure and check integrity */399if (file == NULL)400return -1;401state = (gz_statep)file;402if (state->mode != GZ_READ && state->mode != GZ_WRITE)403return -1;404405/* check that there's no error */406if (state->err != Z_OK && state->err != Z_BUF_ERROR)407return -1;408409/* can only seek from start or relative to current position */410if (whence != SEEK_SET && whence != SEEK_CUR)411return -1;412413/* normalize offset to a SEEK_CUR specification */414if (whence == SEEK_SET)415offset -= state->x.pos;416else if (state->seek)417offset += state->skip;418state->seek = 0;419420/* if within raw area while reading, just go there */421if (state->mode == GZ_READ && state->how == COPY &&422state->x.pos + offset >= 0) {423ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR);424if (ret == -1)425return -1;426state->x.have = 0;427state->eof = 0;428state->past = 0;429state->seek = 0;430gz_error(state, Z_OK, NULL);431state->strm.avail_in = 0;432state->x.pos += offset;433return state->x.pos;434}435436/* calculate skip amount, rewinding if needed for back seek when reading */437if (offset < 0) {438if (state->mode != GZ_READ) /* writing -- can't go backwards */439return -1;440offset += state->x.pos;441if (offset < 0) /* before start of file! */442return -1;443if (gzrewind(file) == -1) /* rewind, then skip to offset */444return -1;445}446447/* if reading, skip what's in output buffer (one less gzgetc() check) */448if (state->mode == GZ_READ) {449n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ?450(unsigned)offset : state->x.have;451state->x.have -= n;452state->x.next += n;453state->x.pos += n;454offset -= n;455}456457/* request skip (if not zero) */458if (offset) {459state->seek = 1;460state->skip = offset;461}462return state->x.pos + offset;463}464465/* -- see zlib.h -- */466z_off_t ZEXPORT gzseek(file, offset, whence)467gzFile file;468z_off_t offset;469int whence;470{471z_off64_t ret;472473ret = gzseek64(file, (z_off64_t)offset, whence);474return ret == (z_off_t)ret ? (z_off_t)ret : -1;475}476477/* -- see zlib.h -- */478z_off64_t ZEXPORT gztell64(file)479gzFile file;480{481gz_statep state;482483/* get internal structure and check integrity */484if (file == NULL)485return -1;486state = (gz_statep)file;487if (state->mode != GZ_READ && state->mode != GZ_WRITE)488return -1;489490/* return position */491return state->x.pos + (state->seek ? state->skip : 0);492}493494/* -- see zlib.h -- */495z_off_t ZEXPORT gztell(file)496gzFile file;497{498z_off64_t ret;499500ret = gztell64(file);501return ret == (z_off_t)ret ? (z_off_t)ret : -1;502}503504/* -- see zlib.h -- */505z_off64_t ZEXPORT gzoffset64(file)506gzFile file;507{508z_off64_t offset;509gz_statep state;510511/* get internal structure and check integrity */512if (file == NULL)513return -1;514state = (gz_statep)file;515if (state->mode != GZ_READ && state->mode != GZ_WRITE)516return -1;517518/* compute and return effective offset in file */519offset = LSEEK(state->fd, 0, SEEK_CUR);520if (offset == -1)521return -1;522if (state->mode == GZ_READ) /* reading */523offset -= state->strm.avail_in; /* don't count buffered input */524return offset;525}526527/* -- see zlib.h -- */528z_off_t ZEXPORT gzoffset(file)529gzFile file;530{531z_off64_t ret;532533ret = gzoffset64(file);534return ret == (z_off_t)ret ? (z_off_t)ret : -1;535}536537/* -- see zlib.h -- */538int ZEXPORT gzeof(file)539gzFile file;540{541gz_statep state;542543/* get internal structure and check integrity */544if (file == NULL)545return 0;546state = (gz_statep)file;547if (state->mode != GZ_READ && state->mode != GZ_WRITE)548return 0;549550/* return end-of-file state */551return state->mode == GZ_READ ? state->past : 0;552}553554/* -- see zlib.h -- */555const char * ZEXPORT gzerror(file, errnum)556gzFile file;557int *errnum;558{559gz_statep state;560561/* get internal structure and check integrity */562if (file == NULL)563return NULL;564state = (gz_statep)file;565if (state->mode != GZ_READ && state->mode != GZ_WRITE)566return NULL;567568/* return error information */569if (errnum != NULL)570*errnum = state->err;571return state->err == Z_MEM_ERROR ? "out of memory" :572(state->msg == NULL ? "" : state->msg);573}574575/* -- see zlib.h -- */576void ZEXPORT gzclearerr(file)577gzFile file;578{579gz_statep state;580581/* get internal structure and check integrity */582if (file == NULL)583return;584state = (gz_statep)file;585if (state->mode != GZ_READ && state->mode != GZ_WRITE)586return;587588/* clear error and end-of-file */589if (state->mode == GZ_READ) {590state->eof = 0;591state->past = 0;592}593gz_error(state, Z_OK, NULL);594}595596/* Create an error message in allocated memory and set state->err and597state->msg accordingly. Free any previous error message already there. Do598not try to free or allocate space if the error is Z_MEM_ERROR (out of599memory). Simply save the error message as a static string. If there is an600allocation failure constructing the error message, then convert the error to601out of memory. */602void ZLIB_INTERNAL gz_error(state, err, msg)603gz_statep state;604int err;605const char *msg;606{607/* free previously allocated message and clear */608if (state->msg != NULL) {609if (state->err != Z_MEM_ERROR)610free(state->msg);611state->msg = NULL;612}613614/* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */615if (err != Z_OK && err != Z_BUF_ERROR)616state->x.have = 0;617618/* set error code, and if no message, then done */619state->err = err;620if (msg == NULL)621return;622623/* for an out of memory error, return literal string when requested */624if (err == Z_MEM_ERROR)625return;626627/* construct error message with path */628if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) ==629NULL) {630state->err = Z_MEM_ERROR;631return;632}633#if !defined(NO_snprintf) && !defined(NO_vsnprintf)634(void)snprintf(state->msg, strlen(state->path) + strlen(msg) + 3,635"%s%s%s", state->path, ": ", msg);636#else637strcpy(state->msg, state->path);638strcat(state->msg, ": ");639strcat(state->msg, msg);640#endif641}642643#ifndef INT_MAX644/* portably return maximum value for an int (when limits.h presumed not645available) -- we need to do this to cover cases where 2's complement not646used, since C standard permits 1's complement and sign-bit representations,647otherwise we could just use ((unsigned)-1) >> 1 */648unsigned ZLIB_INTERNAL gz_intmax()649{650unsigned p, q;651652p = 1;653do {654q = p;655p <<= 1;656p++;657} while (p > q);658return q >> 1;659}660#endif661662663