1205194Sdelphij/* gzlib.c -- zlib functions common to reading and writing gzip files 2250261Sdelphij * Copyright (C) 2004, 2010, 2011, 2012, 2013 Mark Adler 3205194Sdelphij * For conditions of distribution and use, see copyright notice in zlib.h 4205194Sdelphij */ 5205194Sdelphij 6206002Sdelphij/* $FreeBSD$ */ 7206002Sdelphij 8205194Sdelphij#include "gzguts.h" 9206002Sdelphij#include "zutil.h" 10205194Sdelphij 11237410Sdelphij#if defined(_WIN32) && !defined(__BORLANDC__) 12237410Sdelphij# define LSEEK _lseeki64 13237410Sdelphij#else 14206708Sdelphij#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 15205194Sdelphij# define LSEEK lseek64 16205194Sdelphij#else 17205194Sdelphij# define LSEEK lseek 18205194Sdelphij#endif 19237410Sdelphij#endif 20205194Sdelphij 21205194Sdelphij/* Local functions */ 22205194Sdelphijlocal void gz_reset OF((gz_statep)); 23237410Sdelphijlocal gzFile gz_open OF((const void *, int, const char *)); 24205194Sdelphij 25206002Sdelphij#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. */ 36206924Sdelphijchar 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 75206002Sdelphij#endif /* UNDER_CE */ 76205194Sdelphij 77205194Sdelphij/* Reset gzip file state */ 78205194Sdelphijlocal void gz_reset(state) 79205194Sdelphij gz_statep state; 80205194Sdelphij{ 81237410Sdelphij 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 */ 84237410Sdelphij 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 */ 89237410Sdelphij 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) 95237410Sdelphij const void *path; 96205194Sdelphij int fd; 97205194Sdelphij const char *mode; 98205194Sdelphij{ 99205194Sdelphij gz_statep state; 100237410Sdelphij size_t len; 101237410Sdelphij int oflag; 102237410Sdelphij#ifdef O_CLOEXEC 103237410Sdelphij int cloexec = 0; 104237410Sdelphij#endif 105237410Sdelphij#ifdef O_EXCL 106237410Sdelphij int exclusive = 0; 107237410Sdelphij#endif 108205194Sdelphij 109237410Sdelphij /* check input */ 110237410Sdelphij if (path == NULL) 111237410Sdelphij return NULL; 112237410Sdelphij 113205194Sdelphij /* allocate gzFile structure to return */ 114250261Sdelphij 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; 125237410Sdelphij 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; 147237410Sdelphij#ifdef O_CLOEXEC 148237410Sdelphij case 'e': 149237410Sdelphij cloexec = 1; 150237410Sdelphij break; 151237410Sdelphij#endif 152237410Sdelphij#ifdef O_EXCL 153237410Sdelphij case 'x': 154237410Sdelphij exclusive = 1; 155237410Sdelphij break; 156237410Sdelphij#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; 168250261Sdelphij break; 169237410Sdelphij case 'T': 170237410Sdelphij state->direct = 1; 171250261Sdelphij 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 184237410Sdelphij /* can't force transparent read */ 185237410Sdelphij if (state->mode == GZ_READ) { 186237410Sdelphij if (state->direct) { 187237410Sdelphij free(state); 188237410Sdelphij return NULL; 189237410Sdelphij } 190237410Sdelphij state->direct = 1; /* for empty file */ 191237410Sdelphij } 192237410Sdelphij 193205194Sdelphij /* save the path name for error messages */ 194237410Sdelphij#ifdef _WIN32 195237410Sdelphij if (fd == -2) { 196237410Sdelphij len = wcstombs(NULL, path, 0); 197237410Sdelphij if (len == (size_t)-1) 198237410Sdelphij len = 0; 199237410Sdelphij } 200237410Sdelphij else 201237410Sdelphij#endif 202250261Sdelphij len = strlen((const char *)path); 203250261Sdelphij state->path = (char *)malloc(len + 1); 204205194Sdelphij if (state->path == NULL) { 205205194Sdelphij free(state); 206205194Sdelphij return NULL; 207205194Sdelphij } 208237410Sdelphij#ifdef _WIN32 209237410Sdelphij if (fd == -2) 210237410Sdelphij if (len) 211237410Sdelphij wcstombs(state->path, path, len + 1); 212237410Sdelphij else 213237410Sdelphij *(state->path) = 0; 214237410Sdelphij else 215237410Sdelphij#endif 216250261Sdelphij#if !defined(NO_snprintf) && !defined(NO_vsnprintf) 217250261Sdelphij snprintf(state->path, len + 1, "%s", (const char *)path); 218250261Sdelphij#else 219237410Sdelphij strcpy(state->path, path); 220250261Sdelphij#endif 221205194Sdelphij 222237410Sdelphij /* compute the flags for open() */ 223237410Sdelphij oflag = 224205194Sdelphij#ifdef O_LARGEFILE 225237410Sdelphij O_LARGEFILE | 226205194Sdelphij#endif 227205194Sdelphij#ifdef O_BINARY 228237410Sdelphij O_BINARY | 229205194Sdelphij#endif 230237410Sdelphij#ifdef O_CLOEXEC 231237410Sdelphij (cloexec ? O_CLOEXEC : 0) | 232237410Sdelphij#endif 233237410Sdelphij (state->mode == GZ_READ ? 234237410Sdelphij O_RDONLY : 235237410Sdelphij (O_WRONLY | O_CREAT | 236237410Sdelphij#ifdef O_EXCL 237237410Sdelphij (exclusive ? O_EXCL : 0) | 238237410Sdelphij#endif 239237410Sdelphij (state->mode == GZ_WRITE ? 240237410Sdelphij O_TRUNC : 241237410Sdelphij O_APPEND))); 242237410Sdelphij 243237410Sdelphij /* open the file with the appropriate flags (or just use fd) */ 244237410Sdelphij state->fd = fd > -1 ? fd : ( 245237410Sdelphij#ifdef _WIN32 246237410Sdelphij fd == -2 ? _wopen(path, oflag, 0666) : 247237410Sdelphij#endif 248250261Sdelphij open((const char *)path, oflag, 0666)); 249205194Sdelphij if (state->fd == -1) { 250206708Sdelphij free(state->path); 251205194Sdelphij free(state); 252205194Sdelphij return NULL; 253205194Sdelphij } 254205194Sdelphij if (state->mode == GZ_APPEND) 255205194Sdelphij state->mode = GZ_WRITE; /* simplify later checks */ 256205194Sdelphij 257205194Sdelphij /* save the current position for rewinding (only if reading) */ 258205194Sdelphij if (state->mode == GZ_READ) { 259205194Sdelphij state->start = LSEEK(state->fd, 0, SEEK_CUR); 260205194Sdelphij if (state->start == -1) state->start = 0; 261205194Sdelphij } 262205194Sdelphij 263205194Sdelphij /* initialize stream */ 264205194Sdelphij gz_reset(state); 265205194Sdelphij 266205194Sdelphij /* return stream */ 267205194Sdelphij return (gzFile)state; 268205194Sdelphij} 269205194Sdelphij 270205194Sdelphij/* -- see zlib.h -- */ 271205194SdelphijgzFile ZEXPORT gzopen(path, mode) 272205194Sdelphij const char *path; 273205194Sdelphij const char *mode; 274205194Sdelphij{ 275205194Sdelphij return gz_open(path, -1, mode); 276205194Sdelphij} 277205194Sdelphij 278205194Sdelphij/* -- see zlib.h -- */ 279205194SdelphijgzFile ZEXPORT gzopen64(path, mode) 280205194Sdelphij const char *path; 281205194Sdelphij const char *mode; 282205194Sdelphij{ 283205194Sdelphij return gz_open(path, -1, mode); 284205194Sdelphij} 285205194Sdelphij 286205194Sdelphij/* -- see zlib.h -- */ 287205194SdelphijgzFile ZEXPORT gzdopen(fd, mode) 288205194Sdelphij int fd; 289205194Sdelphij const char *mode; 290205194Sdelphij{ 291205194Sdelphij char *path; /* identifier for error messages */ 292205194Sdelphij gzFile gz; 293205194Sdelphij 294250261Sdelphij if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL) 295205194Sdelphij return NULL; 296250261Sdelphij#if !defined(NO_snprintf) && !defined(NO_vsnprintf) 297250261Sdelphij snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd); /* for debugging */ 298250261Sdelphij#else 299206002Sdelphij sprintf(path, "<fd:%d>", fd); /* for debugging */ 300250261Sdelphij#endif 301205194Sdelphij gz = gz_open(path, fd, mode); 302205194Sdelphij free(path); 303205194Sdelphij return gz; 304205194Sdelphij} 305205194Sdelphij 306205194Sdelphij/* -- see zlib.h -- */ 307237410Sdelphij#ifdef _WIN32 308237410SdelphijgzFile ZEXPORT gzopen_w(path, mode) 309237410Sdelphij const wchar_t *path; 310237410Sdelphij const char *mode; 311237410Sdelphij{ 312237410Sdelphij return gz_open(path, -2, mode); 313237410Sdelphij} 314237410Sdelphij#endif 315237410Sdelphij 316237410Sdelphij/* -- see zlib.h -- */ 317205194Sdelphijint ZEXPORT gzbuffer(file, size) 318205194Sdelphij gzFile file; 319205194Sdelphij unsigned size; 320205194Sdelphij{ 321205194Sdelphij gz_statep state; 322205194Sdelphij 323205194Sdelphij /* get internal structure and check integrity */ 324205194Sdelphij if (file == NULL) 325205194Sdelphij return -1; 326205194Sdelphij state = (gz_statep)file; 327205194Sdelphij if (state->mode != GZ_READ && state->mode != GZ_WRITE) 328205194Sdelphij return -1; 329205194Sdelphij 330205194Sdelphij /* make sure we haven't already allocated memory */ 331205194Sdelphij if (state->size != 0) 332205194Sdelphij return -1; 333205194Sdelphij 334205194Sdelphij /* check and set requested size */ 335237410Sdelphij if (size < 2) 336237410Sdelphij size = 2; /* need two bytes to check magic header */ 337205194Sdelphij state->want = size; 338205194Sdelphij return 0; 339205194Sdelphij} 340205194Sdelphij 341205194Sdelphij/* -- see zlib.h -- */ 342205194Sdelphijint ZEXPORT gzrewind(file) 343205194Sdelphij gzFile file; 344205194Sdelphij{ 345205194Sdelphij gz_statep state; 346205194Sdelphij 347205194Sdelphij /* get internal structure */ 348205194Sdelphij if (file == NULL) 349205194Sdelphij return -1; 350205194Sdelphij state = (gz_statep)file; 351205194Sdelphij 352205194Sdelphij /* check that we're reading and that there's no error */ 353237410Sdelphij if (state->mode != GZ_READ || 354237410Sdelphij (state->err != Z_OK && state->err != Z_BUF_ERROR)) 355205194Sdelphij return -1; 356205194Sdelphij 357205194Sdelphij /* back up and start over */ 358205194Sdelphij if (LSEEK(state->fd, state->start, SEEK_SET) == -1) 359205194Sdelphij return -1; 360205194Sdelphij gz_reset(state); 361205194Sdelphij return 0; 362205194Sdelphij} 363205194Sdelphij 364205194Sdelphij/* -- see zlib.h -- */ 365205194Sdelphijz_off64_t ZEXPORT gzseek64(file, offset, whence) 366205194Sdelphij gzFile file; 367205194Sdelphij z_off64_t offset; 368205194Sdelphij int whence; 369205194Sdelphij{ 370205194Sdelphij unsigned n; 371205194Sdelphij z_off64_t ret; 372205194Sdelphij gz_statep state; 373205194Sdelphij 374205194Sdelphij /* get internal structure and check integrity */ 375205194Sdelphij if (file == NULL) 376205194Sdelphij return -1; 377205194Sdelphij state = (gz_statep)file; 378205194Sdelphij if (state->mode != GZ_READ && state->mode != GZ_WRITE) 379205194Sdelphij return -1; 380205194Sdelphij 381205194Sdelphij /* check that there's no error */ 382237410Sdelphij if (state->err != Z_OK && state->err != Z_BUF_ERROR) 383205194Sdelphij return -1; 384205194Sdelphij 385205194Sdelphij /* can only seek from start or relative to current position */ 386205194Sdelphij if (whence != SEEK_SET && whence != SEEK_CUR) 387205194Sdelphij return -1; 388205194Sdelphij 389205194Sdelphij /* normalize offset to a SEEK_CUR specification */ 390205194Sdelphij if (whence == SEEK_SET) 391237410Sdelphij offset -= state->x.pos; 392205194Sdelphij else if (state->seek) 393205194Sdelphij offset += state->skip; 394205194Sdelphij state->seek = 0; 395205194Sdelphij 396205194Sdelphij /* if within raw area while reading, just go there */ 397205194Sdelphij if (state->mode == GZ_READ && state->how == COPY && 398237410Sdelphij state->x.pos + offset >= 0) { 399237410Sdelphij ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR); 400205194Sdelphij if (ret == -1) 401205194Sdelphij return -1; 402237410Sdelphij state->x.have = 0; 403205194Sdelphij state->eof = 0; 404237410Sdelphij state->past = 0; 405205194Sdelphij state->seek = 0; 406205194Sdelphij gz_error(state, Z_OK, NULL); 407205194Sdelphij state->strm.avail_in = 0; 408237410Sdelphij state->x.pos += offset; 409237410Sdelphij return state->x.pos; 410205194Sdelphij } 411205194Sdelphij 412205194Sdelphij /* calculate skip amount, rewinding if needed for back seek when reading */ 413205194Sdelphij if (offset < 0) { 414205194Sdelphij if (state->mode != GZ_READ) /* writing -- can't go backwards */ 415205194Sdelphij return -1; 416237410Sdelphij offset += state->x.pos; 417205194Sdelphij if (offset < 0) /* before start of file! */ 418205194Sdelphij return -1; 419205194Sdelphij if (gzrewind(file) == -1) /* rewind, then skip to offset */ 420205194Sdelphij return -1; 421205194Sdelphij } 422205194Sdelphij 423205194Sdelphij /* if reading, skip what's in output buffer (one less gzgetc() check) */ 424205194Sdelphij if (state->mode == GZ_READ) { 425237410Sdelphij n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ? 426237410Sdelphij (unsigned)offset : state->x.have; 427237410Sdelphij state->x.have -= n; 428237410Sdelphij state->x.next += n; 429237410Sdelphij state->x.pos += n; 430205194Sdelphij offset -= n; 431205194Sdelphij } 432205194Sdelphij 433205194Sdelphij /* request skip (if not zero) */ 434205194Sdelphij if (offset) { 435205194Sdelphij state->seek = 1; 436205194Sdelphij state->skip = offset; 437205194Sdelphij } 438237410Sdelphij return state->x.pos + offset; 439205194Sdelphij} 440205194Sdelphij 441205194Sdelphij/* -- see zlib.h -- */ 442205194Sdelphijz_off_t ZEXPORT gzseek(file, offset, whence) 443205194Sdelphij gzFile file; 444205194Sdelphij z_off_t offset; 445205194Sdelphij int whence; 446205194Sdelphij{ 447205194Sdelphij z_off64_t ret; 448205194Sdelphij 449205194Sdelphij ret = gzseek64(file, (z_off64_t)offset, whence); 450205194Sdelphij return ret == (z_off_t)ret ? (z_off_t)ret : -1; 451205194Sdelphij} 452205194Sdelphij 453205194Sdelphij/* -- see zlib.h -- */ 454205194Sdelphijz_off64_t ZEXPORT gztell64(file) 455205194Sdelphij gzFile file; 456205194Sdelphij{ 457205194Sdelphij gz_statep state; 458205194Sdelphij 459205194Sdelphij /* get internal structure and check integrity */ 460205194Sdelphij if (file == NULL) 461205194Sdelphij return -1; 462205194Sdelphij state = (gz_statep)file; 463205194Sdelphij if (state->mode != GZ_READ && state->mode != GZ_WRITE) 464205194Sdelphij return -1; 465205194Sdelphij 466205194Sdelphij /* return position */ 467237410Sdelphij return state->x.pos + (state->seek ? state->skip : 0); 468205194Sdelphij} 469205194Sdelphij 470205194Sdelphij/* -- see zlib.h -- */ 471205194Sdelphijz_off_t ZEXPORT gztell(file) 472205194Sdelphij gzFile file; 473205194Sdelphij{ 474205194Sdelphij z_off64_t ret; 475205194Sdelphij 476205194Sdelphij ret = gztell64(file); 477205194Sdelphij return ret == (z_off_t)ret ? (z_off_t)ret : -1; 478205194Sdelphij} 479205194Sdelphij 480205194Sdelphij/* -- see zlib.h -- */ 481205194Sdelphijz_off64_t ZEXPORT gzoffset64(file) 482205194Sdelphij gzFile file; 483205194Sdelphij{ 484205194Sdelphij z_off64_t offset; 485205194Sdelphij gz_statep state; 486205194Sdelphij 487205194Sdelphij /* get internal structure and check integrity */ 488205194Sdelphij if (file == NULL) 489205194Sdelphij return -1; 490205194Sdelphij state = (gz_statep)file; 491205194Sdelphij if (state->mode != GZ_READ && state->mode != GZ_WRITE) 492205194Sdelphij return -1; 493205194Sdelphij 494205194Sdelphij /* compute and return effective offset in file */ 495205194Sdelphij offset = LSEEK(state->fd, 0, SEEK_CUR); 496205194Sdelphij if (offset == -1) 497205194Sdelphij return -1; 498205194Sdelphij if (state->mode == GZ_READ) /* reading */ 499205194Sdelphij offset -= state->strm.avail_in; /* don't count buffered input */ 500205194Sdelphij return offset; 501205194Sdelphij} 502205194Sdelphij 503205194Sdelphij/* -- see zlib.h -- */ 504205194Sdelphijz_off_t ZEXPORT gzoffset(file) 505205194Sdelphij gzFile file; 506205194Sdelphij{ 507205194Sdelphij z_off64_t ret; 508205194Sdelphij 509205194Sdelphij ret = gzoffset64(file); 510205194Sdelphij return ret == (z_off_t)ret ? (z_off_t)ret : -1; 511205194Sdelphij} 512205194Sdelphij 513205194Sdelphij/* -- see zlib.h -- */ 514205194Sdelphijint ZEXPORT gzeof(file) 515205194Sdelphij gzFile file; 516205194Sdelphij{ 517205194Sdelphij gz_statep state; 518205194Sdelphij 519205194Sdelphij /* get internal structure and check integrity */ 520205194Sdelphij if (file == NULL) 521205194Sdelphij return 0; 522205194Sdelphij state = (gz_statep)file; 523205194Sdelphij if (state->mode != GZ_READ && state->mode != GZ_WRITE) 524205194Sdelphij return 0; 525205194Sdelphij 526205194Sdelphij /* return end-of-file state */ 527237410Sdelphij return state->mode == GZ_READ ? state->past : 0; 528205194Sdelphij} 529205194Sdelphij 530205194Sdelphij/* -- see zlib.h -- */ 531205194Sdelphijconst char * ZEXPORT gzerror(file, errnum) 532205194Sdelphij gzFile file; 533205194Sdelphij int *errnum; 534205194Sdelphij{ 535205194Sdelphij gz_statep state; 536205194Sdelphij 537205194Sdelphij /* get internal structure and check integrity */ 538205194Sdelphij if (file == NULL) 539205194Sdelphij return NULL; 540205194Sdelphij state = (gz_statep)file; 541205194Sdelphij if (state->mode != GZ_READ && state->mode != GZ_WRITE) 542205194Sdelphij return NULL; 543205194Sdelphij 544205194Sdelphij /* return error information */ 545205194Sdelphij if (errnum != NULL) 546205194Sdelphij *errnum = state->err; 547250261Sdelphij return state->err == Z_MEM_ERROR ? "out of memory" : 548250261Sdelphij (state->msg == NULL ? "" : state->msg); 549205194Sdelphij} 550205194Sdelphij 551205194Sdelphij/* -- see zlib.h -- */ 552205194Sdelphijvoid ZEXPORT gzclearerr(file) 553205194Sdelphij gzFile file; 554205194Sdelphij{ 555205194Sdelphij gz_statep state; 556205194Sdelphij 557205194Sdelphij /* get internal structure and check integrity */ 558205194Sdelphij if (file == NULL) 559205194Sdelphij return; 560205194Sdelphij state = (gz_statep)file; 561205194Sdelphij if (state->mode != GZ_READ && state->mode != GZ_WRITE) 562205194Sdelphij return; 563205194Sdelphij 564205194Sdelphij /* clear error and end-of-file */ 565237410Sdelphij if (state->mode == GZ_READ) { 566205194Sdelphij state->eof = 0; 567237410Sdelphij state->past = 0; 568237410Sdelphij } 569205194Sdelphij gz_error(state, Z_OK, NULL); 570205194Sdelphij} 571205194Sdelphij 572205194Sdelphij/* Create an error message in allocated memory and set state->err and 573205194Sdelphij state->msg accordingly. Free any previous error message already there. Do 574205194Sdelphij not try to free or allocate space if the error is Z_MEM_ERROR (out of 575205194Sdelphij memory). Simply save the error message as a static string. If there is an 576205194Sdelphij allocation failure constructing the error message, then convert the error to 577205194Sdelphij out of memory. */ 578206924Sdelphijvoid ZLIB_INTERNAL gz_error(state, err, msg) 579205194Sdelphij gz_statep state; 580205194Sdelphij int err; 581205194Sdelphij const char *msg; 582205194Sdelphij{ 583205194Sdelphij /* free previously allocated message and clear */ 584205194Sdelphij if (state->msg != NULL) { 585205194Sdelphij if (state->err != Z_MEM_ERROR) 586205194Sdelphij free(state->msg); 587205194Sdelphij state->msg = NULL; 588205194Sdelphij } 589205194Sdelphij 590237410Sdelphij /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */ 591237410Sdelphij if (err != Z_OK && err != Z_BUF_ERROR) 592237410Sdelphij state->x.have = 0; 593237410Sdelphij 594205194Sdelphij /* set error code, and if no message, then done */ 595205194Sdelphij state->err = err; 596205194Sdelphij if (msg == NULL) 597205194Sdelphij return; 598205194Sdelphij 599250261Sdelphij /* for an out of memory error, return literal string when requested */ 600250261Sdelphij if (err == Z_MEM_ERROR) 601205194Sdelphij return; 602205194Sdelphij 603205194Sdelphij /* construct error message with path */ 604250261Sdelphij if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) == 605250261Sdelphij NULL) { 606205194Sdelphij state->err = Z_MEM_ERROR; 607205194Sdelphij return; 608205194Sdelphij } 609250261Sdelphij#if !defined(NO_snprintf) && !defined(NO_vsnprintf) 610250261Sdelphij snprintf(state->msg, strlen(state->path) + strlen(msg) + 3, 611250261Sdelphij "%s%s%s", state->path, ": ", msg); 612250261Sdelphij#else 613205194Sdelphij strcpy(state->msg, state->path); 614205194Sdelphij strcat(state->msg, ": "); 615205194Sdelphij strcat(state->msg, msg); 616250261Sdelphij#endif 617205194Sdelphij return; 618205194Sdelphij} 619205194Sdelphij 620205194Sdelphij#ifndef INT_MAX 621205194Sdelphij/* portably return maximum value for an int (when limits.h presumed not 622205194Sdelphij available) -- we need to do this to cover cases where 2's complement not 623205194Sdelphij used, since C standard permits 1's complement and sign-bit representations, 624205194Sdelphij otherwise we could just use ((unsigned)-1) >> 1 */ 625206924Sdelphijunsigned ZLIB_INTERNAL gz_intmax() 626205194Sdelphij{ 627205194Sdelphij unsigned p, q; 628205194Sdelphij 629205194Sdelphij p = 1; 630205194Sdelphij do { 631205194Sdelphij q = p; 632205194Sdelphij p <<= 1; 633205194Sdelphij p++; 634205194Sdelphij } while (p > q); 635205194Sdelphij return q >> 1; 636205194Sdelphij} 637205194Sdelphij#endif 638