1205194Sdelphij/* gzlib.c -- zlib functions common to reading and writing gzip files 2312335Sdelphij * Copyright (C) 2004-2017 Mark Adler 3205194Sdelphij * For conditions of distribution and use, see copyright notice in zlib.h 4205194Sdelphij */ 5205194Sdelphij 6311275Sdelphij/* $FreeBSD: stable/11/sys/contrib/zlib/gzlib.c 312335 2017-01-17 05:55:47Z delphij $ */ 7311275Sdelphij 8205194Sdelphij#include "gzguts.h" 9311275Sdelphij#include "zutil.h" 10205194Sdelphij 11311285Sdelphij#if defined(_WIN32) && !defined(__BORLANDC__) && !defined(__MINGW32__) 12230837Sdelphij# define LSEEK _lseeki64 13230837Sdelphij#else 14206499Sdelphij#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 15205194Sdelphij# define LSEEK lseek64 16205194Sdelphij#else 17205194Sdelphij# define LSEEK lseek 18205194Sdelphij#endif 19230837Sdelphij#endif 20205194Sdelphij 21205194Sdelphij/* Local functions */ 22205194Sdelphijlocal void gz_reset OF((gz_statep)); 23237248Sdelphijlocal gzFile gz_open OF((const void *, int, const char *)); 24205194Sdelphij 25205990Sdelphij#if defined UNDER_CE 26205194Sdelphij 27205194Sdelphij/* Map the Windows error number in ERROR to a locale-dependent error message 28205194Sdelphij string and return a pointer to it. Typically, the values for ERROR come 29205194Sdelphij from GetLastError. 30205194Sdelphij 31205194Sdelphij The string pointed to shall not be modified by the application, but may be 32205194Sdelphij overwritten by a subsequent call to gz_strwinerror 33205194Sdelphij 34205194Sdelphij The gz_strwinerror function does not change the current setting of 35205194Sdelphij GetLastError. */ 36206905Sdelphijchar ZLIB_INTERNAL *gz_strwinerror (error) 37205194Sdelphij DWORD error; 38205194Sdelphij{ 39205194Sdelphij static char buf[1024]; 40205194Sdelphij 41205194Sdelphij wchar_t *msgbuf; 42205194Sdelphij DWORD lasterr = GetLastError(); 43205194Sdelphij DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM 44205194Sdelphij | FORMAT_MESSAGE_ALLOCATE_BUFFER, 45205194Sdelphij NULL, 46205194Sdelphij error, 47205194Sdelphij 0, /* Default language */ 48205194Sdelphij (LPVOID)&msgbuf, 49205194Sdelphij 0, 50205194Sdelphij NULL); 51205194Sdelphij if (chars != 0) { 52205194Sdelphij /* If there is an \r\n appended, zap it. */ 53205194Sdelphij if (chars >= 2 54205194Sdelphij && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') { 55205194Sdelphij chars -= 2; 56205194Sdelphij msgbuf[chars] = 0; 57205194Sdelphij } 58205194Sdelphij 59205194Sdelphij if (chars > sizeof (buf) - 1) { 60205194Sdelphij chars = sizeof (buf) - 1; 61205194Sdelphij msgbuf[chars] = 0; 62205194Sdelphij } 63205194Sdelphij 64205194Sdelphij wcstombs(buf, msgbuf, chars + 1); 65205194Sdelphij LocalFree(msgbuf); 66205194Sdelphij } 67205194Sdelphij else { 68205194Sdelphij sprintf(buf, "unknown win32 error (%ld)", error); 69205194Sdelphij } 70205194Sdelphij 71205194Sdelphij SetLastError(lasterr); 72205194Sdelphij return buf; 73205194Sdelphij} 74205194Sdelphij 75205990Sdelphij#endif /* UNDER_CE */ 76205194Sdelphij 77205194Sdelphij/* Reset gzip file state */ 78205194Sdelphijlocal void gz_reset(state) 79205194Sdelphij gz_statep state; 80205194Sdelphij{ 81230837Sdelphij state->x.have = 0; /* no output data available */ 82205194Sdelphij if (state->mode == GZ_READ) { /* for reading ... */ 83205194Sdelphij state->eof = 0; /* not at end of file */ 84230837Sdelphij state->past = 0; /* have not read past end yet */ 85205194Sdelphij state->how = LOOK; /* look for gzip header */ 86205194Sdelphij } 87205194Sdelphij state->seek = 0; /* no seek request pending */ 88205194Sdelphij gz_error(state, Z_OK, NULL); /* clear error */ 89230837Sdelphij state->x.pos = 0; /* no uncompressed data yet */ 90205194Sdelphij state->strm.avail_in = 0; /* no input data yet */ 91205194Sdelphij} 92205194Sdelphij 93205194Sdelphij/* Open a gzip file either by name or file descriptor. */ 94205194Sdelphijlocal gzFile gz_open(path, fd, mode) 95237248Sdelphij const void *path; 96205194Sdelphij int fd; 97205194Sdelphij const char *mode; 98205194Sdelphij{ 99205194Sdelphij gz_statep state; 100311285Sdelphij z_size_t len; 101237248Sdelphij int oflag; 102237248Sdelphij#ifdef O_CLOEXEC 103237248Sdelphij int cloexec = 0; 104237248Sdelphij#endif 105237248Sdelphij#ifdef O_EXCL 106237248Sdelphij int exclusive = 0; 107237248Sdelphij#endif 108205194Sdelphij 109230837Sdelphij /* check input */ 110230837Sdelphij if (path == NULL) 111230837Sdelphij return NULL; 112230837Sdelphij 113205194Sdelphij /* allocate gzFile structure to return */ 114250224Sdelphij state = (gz_statep)malloc(sizeof(gz_state)); 115205194Sdelphij if (state == NULL) 116205194Sdelphij return NULL; 117205194Sdelphij state->size = 0; /* no buffers allocated yet */ 118205194Sdelphij state->want = GZBUFSIZE; /* requested buffer size */ 119205194Sdelphij state->msg = NULL; /* no error message yet */ 120205194Sdelphij 121205194Sdelphij /* interpret mode */ 122205194Sdelphij state->mode = GZ_NONE; 123205194Sdelphij state->level = Z_DEFAULT_COMPRESSION; 124205194Sdelphij state->strategy = Z_DEFAULT_STRATEGY; 125230837Sdelphij state->direct = 0; 126205194Sdelphij while (*mode) { 127205194Sdelphij if (*mode >= '0' && *mode <= '9') 128205194Sdelphij state->level = *mode - '0'; 129205194Sdelphij else 130205194Sdelphij switch (*mode) { 131205194Sdelphij case 'r': 132205194Sdelphij state->mode = GZ_READ; 133205194Sdelphij break; 134205194Sdelphij#ifndef NO_GZCOMPRESS 135205194Sdelphij case 'w': 136205194Sdelphij state->mode = GZ_WRITE; 137205194Sdelphij break; 138205194Sdelphij case 'a': 139205194Sdelphij state->mode = GZ_APPEND; 140205194Sdelphij break; 141205194Sdelphij#endif 142205194Sdelphij case '+': /* can't read and write at the same time */ 143205194Sdelphij free(state); 144205194Sdelphij return NULL; 145205194Sdelphij case 'b': /* ignore -- will request binary anyway */ 146205194Sdelphij break; 147237248Sdelphij#ifdef O_CLOEXEC 148237248Sdelphij case 'e': 149237248Sdelphij cloexec = 1; 150237248Sdelphij break; 151237248Sdelphij#endif 152237248Sdelphij#ifdef O_EXCL 153237248Sdelphij case 'x': 154237248Sdelphij exclusive = 1; 155237248Sdelphij break; 156237248Sdelphij#endif 157205194Sdelphij case 'f': 158205194Sdelphij state->strategy = Z_FILTERED; 159205194Sdelphij break; 160205194Sdelphij case 'h': 161205194Sdelphij state->strategy = Z_HUFFMAN_ONLY; 162205194Sdelphij break; 163205194Sdelphij case 'R': 164205194Sdelphij state->strategy = Z_RLE; 165205194Sdelphij break; 166205194Sdelphij case 'F': 167205194Sdelphij state->strategy = Z_FIXED; 168250224Sdelphij break; 169230837Sdelphij case 'T': 170230837Sdelphij state->direct = 1; 171250224Sdelphij break; 172205194Sdelphij default: /* could consider as an error, but just ignore */ 173205194Sdelphij ; 174205194Sdelphij } 175205194Sdelphij mode++; 176205194Sdelphij } 177205194Sdelphij 178205194Sdelphij /* must provide an "r", "w", or "a" */ 179205194Sdelphij if (state->mode == GZ_NONE) { 180205194Sdelphij free(state); 181205194Sdelphij return NULL; 182205194Sdelphij } 183205194Sdelphij 184230837Sdelphij /* can't force transparent read */ 185230837Sdelphij if (state->mode == GZ_READ) { 186230837Sdelphij if (state->direct) { 187230837Sdelphij free(state); 188230837Sdelphij return NULL; 189230837Sdelphij } 190230837Sdelphij state->direct = 1; /* for empty file */ 191230837Sdelphij } 192230837Sdelphij 193205194Sdelphij /* save the path name for error messages */ 194311285Sdelphij#ifdef WIDECHAR 195237248Sdelphij if (fd == -2) { 196237248Sdelphij len = wcstombs(NULL, path, 0); 197311285Sdelphij if (len == (z_size_t)-1) 198237248Sdelphij len = 0; 199237248Sdelphij } 200237248Sdelphij else 201237248Sdelphij#endif 202250224Sdelphij len = strlen((const char *)path); 203250224Sdelphij state->path = (char *)malloc(len + 1); 204205194Sdelphij if (state->path == NULL) { 205205194Sdelphij free(state); 206205194Sdelphij return NULL; 207205194Sdelphij } 208311285Sdelphij#ifdef WIDECHAR 209237248Sdelphij if (fd == -2) 210237248Sdelphij if (len) 211237248Sdelphij wcstombs(state->path, path, len + 1); 212237248Sdelphij else 213237248Sdelphij *(state->path) = 0; 214237248Sdelphij else 215237248Sdelphij#endif 216250224Sdelphij#if !defined(NO_snprintf) && !defined(NO_vsnprintf) 217311285Sdelphij (void)snprintf(state->path, len + 1, "%s", (const char *)path); 218250224Sdelphij#else 219237248Sdelphij strcpy(state->path, path); 220250224Sdelphij#endif 221205194Sdelphij 222237248Sdelphij /* compute the flags for open() */ 223237248Sdelphij oflag = 224205194Sdelphij#ifdef O_LARGEFILE 225237248Sdelphij O_LARGEFILE | 226205194Sdelphij#endif 227205194Sdelphij#ifdef O_BINARY 228237248Sdelphij O_BINARY | 229205194Sdelphij#endif 230237248Sdelphij#ifdef O_CLOEXEC 231237248Sdelphij (cloexec ? O_CLOEXEC : 0) | 232237248Sdelphij#endif 233237248Sdelphij (state->mode == GZ_READ ? 234237248Sdelphij O_RDONLY : 235237248Sdelphij (O_WRONLY | O_CREAT | 236237248Sdelphij#ifdef O_EXCL 237237248Sdelphij (exclusive ? O_EXCL : 0) | 238237248Sdelphij#endif 239237248Sdelphij (state->mode == GZ_WRITE ? 240237248Sdelphij O_TRUNC : 241237248Sdelphij O_APPEND))); 242237248Sdelphij 243237248Sdelphij /* open the file with the appropriate flags (or just use fd) */ 244237248Sdelphij state->fd = fd > -1 ? fd : ( 245311285Sdelphij#ifdef WIDECHAR 246237248Sdelphij fd == -2 ? _wopen(path, oflag, 0666) : 247237248Sdelphij#endif 248250224Sdelphij open((const char *)path, oflag, 0666)); 249205194Sdelphij if (state->fd == -1) { 250206499Sdelphij free(state->path); 251205194Sdelphij free(state); 252205194Sdelphij return NULL; 253205194Sdelphij } 254311285Sdelphij if (state->mode == GZ_APPEND) { 255311285Sdelphij LSEEK(state->fd, 0, SEEK_END); /* so gzoffset() is correct */ 256205194Sdelphij state->mode = GZ_WRITE; /* simplify later checks */ 257311285Sdelphij } 258205194Sdelphij 259205194Sdelphij /* save the current position for rewinding (only if reading) */ 260205194Sdelphij if (state->mode == GZ_READ) { 261205194Sdelphij state->start = LSEEK(state->fd, 0, SEEK_CUR); 262205194Sdelphij if (state->start == -1) state->start = 0; 263205194Sdelphij } 264205194Sdelphij 265205194Sdelphij /* initialize stream */ 266205194Sdelphij gz_reset(state); 267205194Sdelphij 268205194Sdelphij /* return stream */ 269205194Sdelphij return (gzFile)state; 270205194Sdelphij} 271205194Sdelphij 272205194Sdelphij/* -- see zlib.h -- */ 273205194SdelphijgzFile ZEXPORT gzopen(path, mode) 274205194Sdelphij const char *path; 275205194Sdelphij const char *mode; 276205194Sdelphij{ 277205194Sdelphij return gz_open(path, -1, mode); 278205194Sdelphij} 279205194Sdelphij 280205194Sdelphij/* -- see zlib.h -- */ 281205194SdelphijgzFile ZEXPORT gzopen64(path, mode) 282205194Sdelphij const char *path; 283205194Sdelphij const char *mode; 284205194Sdelphij{ 285205194Sdelphij return gz_open(path, -1, mode); 286205194Sdelphij} 287205194Sdelphij 288205194Sdelphij/* -- see zlib.h -- */ 289205194SdelphijgzFile ZEXPORT gzdopen(fd, mode) 290205194Sdelphij int fd; 291205194Sdelphij const char *mode; 292205194Sdelphij{ 293205194Sdelphij char *path; /* identifier for error messages */ 294205194Sdelphij gzFile gz; 295205194Sdelphij 296250224Sdelphij if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL) 297205194Sdelphij return NULL; 298250224Sdelphij#if !defined(NO_snprintf) && !defined(NO_vsnprintf) 299311285Sdelphij (void)snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd); 300250224Sdelphij#else 301205990Sdelphij sprintf(path, "<fd:%d>", fd); /* for debugging */ 302250224Sdelphij#endif 303205194Sdelphij gz = gz_open(path, fd, mode); 304205194Sdelphij free(path); 305205194Sdelphij return gz; 306205194Sdelphij} 307205194Sdelphij 308205194Sdelphij/* -- see zlib.h -- */ 309311285Sdelphij#ifdef WIDECHAR 310237248SdelphijgzFile ZEXPORT gzopen_w(path, mode) 311237248Sdelphij const wchar_t *path; 312237248Sdelphij const char *mode; 313237248Sdelphij{ 314237248Sdelphij return gz_open(path, -2, mode); 315237248Sdelphij} 316237248Sdelphij#endif 317237248Sdelphij 318237248Sdelphij/* -- see zlib.h -- */ 319205194Sdelphijint ZEXPORT gzbuffer(file, size) 320205194Sdelphij gzFile file; 321205194Sdelphij unsigned size; 322205194Sdelphij{ 323205194Sdelphij gz_statep state; 324205194Sdelphij 325205194Sdelphij /* get internal structure and check integrity */ 326205194Sdelphij if (file == NULL) 327205194Sdelphij return -1; 328205194Sdelphij state = (gz_statep)file; 329205194Sdelphij if (state->mode != GZ_READ && state->mode != GZ_WRITE) 330205194Sdelphij return -1; 331205194Sdelphij 332205194Sdelphij /* make sure we haven't already allocated memory */ 333205194Sdelphij if (state->size != 0) 334205194Sdelphij return -1; 335205194Sdelphij 336205194Sdelphij /* check and set requested size */ 337311285Sdelphij if ((size << 1) < size) 338311285Sdelphij return -1; /* need to be able to double it */ 339230837Sdelphij if (size < 2) 340230837Sdelphij size = 2; /* need two bytes to check magic header */ 341205194Sdelphij state->want = size; 342205194Sdelphij return 0; 343205194Sdelphij} 344205194Sdelphij 345205194Sdelphij/* -- see zlib.h -- */ 346205194Sdelphijint ZEXPORT gzrewind(file) 347205194Sdelphij gzFile file; 348205194Sdelphij{ 349205194Sdelphij gz_statep state; 350205194Sdelphij 351205194Sdelphij /* get internal structure */ 352205194Sdelphij if (file == NULL) 353205194Sdelphij return -1; 354205194Sdelphij state = (gz_statep)file; 355205194Sdelphij 356205194Sdelphij /* check that we're reading and that there's no error */ 357230837Sdelphij if (state->mode != GZ_READ || 358230837Sdelphij (state->err != Z_OK && state->err != Z_BUF_ERROR)) 359205194Sdelphij return -1; 360205194Sdelphij 361205194Sdelphij /* back up and start over */ 362205194Sdelphij if (LSEEK(state->fd, state->start, SEEK_SET) == -1) 363205194Sdelphij return -1; 364205194Sdelphij gz_reset(state); 365205194Sdelphij return 0; 366205194Sdelphij} 367205194Sdelphij 368205194Sdelphij/* -- see zlib.h -- */ 369205194Sdelphijz_off64_t ZEXPORT gzseek64(file, offset, whence) 370205194Sdelphij gzFile file; 371205194Sdelphij z_off64_t offset; 372205194Sdelphij int whence; 373205194Sdelphij{ 374205194Sdelphij unsigned n; 375205194Sdelphij z_off64_t ret; 376205194Sdelphij gz_statep state; 377205194Sdelphij 378205194Sdelphij /* get internal structure and check integrity */ 379205194Sdelphij if (file == NULL) 380205194Sdelphij return -1; 381205194Sdelphij state = (gz_statep)file; 382205194Sdelphij if (state->mode != GZ_READ && state->mode != GZ_WRITE) 383205194Sdelphij return -1; 384205194Sdelphij 385205194Sdelphij /* check that there's no error */ 386230837Sdelphij if (state->err != Z_OK && state->err != Z_BUF_ERROR) 387205194Sdelphij return -1; 388205194Sdelphij 389205194Sdelphij /* can only seek from start or relative to current position */ 390205194Sdelphij if (whence != SEEK_SET && whence != SEEK_CUR) 391205194Sdelphij return -1; 392205194Sdelphij 393205194Sdelphij /* normalize offset to a SEEK_CUR specification */ 394205194Sdelphij if (whence == SEEK_SET) 395230837Sdelphij offset -= state->x.pos; 396205194Sdelphij else if (state->seek) 397205194Sdelphij offset += state->skip; 398205194Sdelphij state->seek = 0; 399205194Sdelphij 400205194Sdelphij /* if within raw area while reading, just go there */ 401205194Sdelphij if (state->mode == GZ_READ && state->how == COPY && 402230837Sdelphij state->x.pos + offset >= 0) { 403230837Sdelphij ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR); 404205194Sdelphij if (ret == -1) 405205194Sdelphij return -1; 406230837Sdelphij state->x.have = 0; 407205194Sdelphij state->eof = 0; 408230837Sdelphij state->past = 0; 409205194Sdelphij state->seek = 0; 410205194Sdelphij gz_error(state, Z_OK, NULL); 411205194Sdelphij state->strm.avail_in = 0; 412230837Sdelphij state->x.pos += offset; 413230837Sdelphij return state->x.pos; 414205194Sdelphij } 415205194Sdelphij 416205194Sdelphij /* calculate skip amount, rewinding if needed for back seek when reading */ 417205194Sdelphij if (offset < 0) { 418205194Sdelphij if (state->mode != GZ_READ) /* writing -- can't go backwards */ 419205194Sdelphij return -1; 420230837Sdelphij offset += state->x.pos; 421205194Sdelphij if (offset < 0) /* before start of file! */ 422205194Sdelphij return -1; 423205194Sdelphij if (gzrewind(file) == -1) /* rewind, then skip to offset */ 424205194Sdelphij return -1; 425205194Sdelphij } 426205194Sdelphij 427205194Sdelphij /* if reading, skip what's in output buffer (one less gzgetc() check) */ 428205194Sdelphij if (state->mode == GZ_READ) { 429230837Sdelphij n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ? 430230837Sdelphij (unsigned)offset : state->x.have; 431230837Sdelphij state->x.have -= n; 432230837Sdelphij state->x.next += n; 433230837Sdelphij state->x.pos += n; 434205194Sdelphij offset -= n; 435205194Sdelphij } 436205194Sdelphij 437205194Sdelphij /* request skip (if not zero) */ 438205194Sdelphij if (offset) { 439205194Sdelphij state->seek = 1; 440205194Sdelphij state->skip = offset; 441205194Sdelphij } 442230837Sdelphij return state->x.pos + offset; 443205194Sdelphij} 444205194Sdelphij 445205194Sdelphij/* -- see zlib.h -- */ 446205194Sdelphijz_off_t ZEXPORT gzseek(file, offset, whence) 447205194Sdelphij gzFile file; 448205194Sdelphij z_off_t offset; 449205194Sdelphij int whence; 450205194Sdelphij{ 451205194Sdelphij z_off64_t ret; 452205194Sdelphij 453205194Sdelphij ret = gzseek64(file, (z_off64_t)offset, whence); 454205194Sdelphij return ret == (z_off_t)ret ? (z_off_t)ret : -1; 455205194Sdelphij} 456205194Sdelphij 457205194Sdelphij/* -- see zlib.h -- */ 458205194Sdelphijz_off64_t ZEXPORT gztell64(file) 459205194Sdelphij gzFile file; 460205194Sdelphij{ 461205194Sdelphij gz_statep state; 462205194Sdelphij 463205194Sdelphij /* get internal structure and check integrity */ 464205194Sdelphij if (file == NULL) 465205194Sdelphij return -1; 466205194Sdelphij state = (gz_statep)file; 467205194Sdelphij if (state->mode != GZ_READ && state->mode != GZ_WRITE) 468205194Sdelphij return -1; 469205194Sdelphij 470205194Sdelphij /* return position */ 471230837Sdelphij return state->x.pos + (state->seek ? state->skip : 0); 472205194Sdelphij} 473205194Sdelphij 474205194Sdelphij/* -- see zlib.h -- */ 475205194Sdelphijz_off_t ZEXPORT gztell(file) 476205194Sdelphij gzFile file; 477205194Sdelphij{ 478205194Sdelphij z_off64_t ret; 479205194Sdelphij 480205194Sdelphij ret = gztell64(file); 481205194Sdelphij return ret == (z_off_t)ret ? (z_off_t)ret : -1; 482205194Sdelphij} 483205194Sdelphij 484205194Sdelphij/* -- see zlib.h -- */ 485205194Sdelphijz_off64_t ZEXPORT gzoffset64(file) 486205194Sdelphij gzFile file; 487205194Sdelphij{ 488205194Sdelphij z_off64_t offset; 489205194Sdelphij gz_statep state; 490205194Sdelphij 491205194Sdelphij /* get internal structure and check integrity */ 492205194Sdelphij if (file == NULL) 493205194Sdelphij return -1; 494205194Sdelphij state = (gz_statep)file; 495205194Sdelphij if (state->mode != GZ_READ && state->mode != GZ_WRITE) 496205194Sdelphij return -1; 497205194Sdelphij 498205194Sdelphij /* compute and return effective offset in file */ 499205194Sdelphij offset = LSEEK(state->fd, 0, SEEK_CUR); 500205194Sdelphij if (offset == -1) 501205194Sdelphij return -1; 502205194Sdelphij if (state->mode == GZ_READ) /* reading */ 503205194Sdelphij offset -= state->strm.avail_in; /* don't count buffered input */ 504205194Sdelphij return offset; 505205194Sdelphij} 506205194Sdelphij 507205194Sdelphij/* -- see zlib.h -- */ 508205194Sdelphijz_off_t ZEXPORT gzoffset(file) 509205194Sdelphij gzFile file; 510205194Sdelphij{ 511205194Sdelphij z_off64_t ret; 512205194Sdelphij 513205194Sdelphij ret = gzoffset64(file); 514205194Sdelphij return ret == (z_off_t)ret ? (z_off_t)ret : -1; 515205194Sdelphij} 516205194Sdelphij 517205194Sdelphij/* -- see zlib.h -- */ 518205194Sdelphijint ZEXPORT gzeof(file) 519205194Sdelphij gzFile file; 520205194Sdelphij{ 521205194Sdelphij gz_statep state; 522205194Sdelphij 523205194Sdelphij /* get internal structure and check integrity */ 524205194Sdelphij if (file == NULL) 525205194Sdelphij return 0; 526205194Sdelphij state = (gz_statep)file; 527205194Sdelphij if (state->mode != GZ_READ && state->mode != GZ_WRITE) 528205194Sdelphij return 0; 529205194Sdelphij 530205194Sdelphij /* return end-of-file state */ 531230837Sdelphij return state->mode == GZ_READ ? state->past : 0; 532205194Sdelphij} 533205194Sdelphij 534205194Sdelphij/* -- see zlib.h -- */ 535205194Sdelphijconst char * ZEXPORT gzerror(file, errnum) 536205194Sdelphij gzFile file; 537205194Sdelphij int *errnum; 538205194Sdelphij{ 539205194Sdelphij gz_statep state; 540205194Sdelphij 541205194Sdelphij /* get internal structure and check integrity */ 542205194Sdelphij if (file == NULL) 543205194Sdelphij return NULL; 544205194Sdelphij state = (gz_statep)file; 545205194Sdelphij if (state->mode != GZ_READ && state->mode != GZ_WRITE) 546205194Sdelphij return NULL; 547205194Sdelphij 548205194Sdelphij /* return error information */ 549205194Sdelphij if (errnum != NULL) 550205194Sdelphij *errnum = state->err; 551250224Sdelphij return state->err == Z_MEM_ERROR ? "out of memory" : 552250224Sdelphij (state->msg == NULL ? "" : state->msg); 553205194Sdelphij} 554205194Sdelphij 555205194Sdelphij/* -- see zlib.h -- */ 556205194Sdelphijvoid ZEXPORT gzclearerr(file) 557205194Sdelphij gzFile file; 558205194Sdelphij{ 559205194Sdelphij gz_statep state; 560205194Sdelphij 561205194Sdelphij /* get internal structure and check integrity */ 562205194Sdelphij if (file == NULL) 563205194Sdelphij return; 564205194Sdelphij state = (gz_statep)file; 565205194Sdelphij if (state->mode != GZ_READ && state->mode != GZ_WRITE) 566205194Sdelphij return; 567205194Sdelphij 568205194Sdelphij /* clear error and end-of-file */ 569230837Sdelphij if (state->mode == GZ_READ) { 570205194Sdelphij state->eof = 0; 571230837Sdelphij state->past = 0; 572230837Sdelphij } 573205194Sdelphij gz_error(state, Z_OK, NULL); 574205194Sdelphij} 575205194Sdelphij 576205194Sdelphij/* Create an error message in allocated memory and set state->err and 577205194Sdelphij state->msg accordingly. Free any previous error message already there. Do 578205194Sdelphij not try to free or allocate space if the error is Z_MEM_ERROR (out of 579205194Sdelphij memory). Simply save the error message as a static string. If there is an 580205194Sdelphij allocation failure constructing the error message, then convert the error to 581205194Sdelphij out of memory. */ 582206905Sdelphijvoid ZLIB_INTERNAL gz_error(state, err, msg) 583205194Sdelphij gz_statep state; 584205194Sdelphij int err; 585205194Sdelphij const char *msg; 586205194Sdelphij{ 587205194Sdelphij /* free previously allocated message and clear */ 588205194Sdelphij if (state->msg != NULL) { 589205194Sdelphij if (state->err != Z_MEM_ERROR) 590205194Sdelphij free(state->msg); 591205194Sdelphij state->msg = NULL; 592205194Sdelphij } 593205194Sdelphij 594230837Sdelphij /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */ 595230837Sdelphij if (err != Z_OK && err != Z_BUF_ERROR) 596230837Sdelphij state->x.have = 0; 597230837Sdelphij 598205194Sdelphij /* set error code, and if no message, then done */ 599205194Sdelphij state->err = err; 600205194Sdelphij if (msg == NULL) 601205194Sdelphij return; 602205194Sdelphij 603250224Sdelphij /* for an out of memory error, return literal string when requested */ 604250224Sdelphij if (err == Z_MEM_ERROR) 605205194Sdelphij return; 606205194Sdelphij 607205194Sdelphij /* construct error message with path */ 608250224Sdelphij if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) == 609250224Sdelphij NULL) { 610205194Sdelphij state->err = Z_MEM_ERROR; 611205194Sdelphij return; 612205194Sdelphij } 613250224Sdelphij#if !defined(NO_snprintf) && !defined(NO_vsnprintf) 614311285Sdelphij (void)snprintf(state->msg, strlen(state->path) + strlen(msg) + 3, 615311285Sdelphij "%s%s%s", state->path, ": ", msg); 616250224Sdelphij#else 617205194Sdelphij strcpy(state->msg, state->path); 618205194Sdelphij strcat(state->msg, ": "); 619205194Sdelphij strcat(state->msg, msg); 620250224Sdelphij#endif 621205194Sdelphij} 622205194Sdelphij 623205194Sdelphij#ifndef INT_MAX 624205194Sdelphij/* portably return maximum value for an int (when limits.h presumed not 625205194Sdelphij available) -- we need to do this to cover cases where 2's complement not 626205194Sdelphij used, since C standard permits 1's complement and sign-bit representations, 627205194Sdelphij otherwise we could just use ((unsigned)-1) >> 1 */ 628206905Sdelphijunsigned ZLIB_INTERNAL gz_intmax() 629205194Sdelphij{ 630205194Sdelphij unsigned p, q; 631205194Sdelphij 632205194Sdelphij p = 1; 633205194Sdelphij do { 634205194Sdelphij q = p; 635205194Sdelphij p <<= 1; 636205194Sdelphij p++; 637205194Sdelphij } while (p > q); 638205194Sdelphij return q >> 1; 639205194Sdelphij} 640205194Sdelphij#endif 641