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