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