1275793eaSopenharmony_ci/* gzlib.c -- zlib functions common to reading and writing gzip files 2275793eaSopenharmony_ci * Copyright (C) 2004-2024 Mark Adler 3275793eaSopenharmony_ci * For conditions of distribution and use, see copyright notice in zlib.h 4275793eaSopenharmony_ci */ 5275793eaSopenharmony_ci 6275793eaSopenharmony_ci#include "gzguts.h" 7275793eaSopenharmony_ci#include <sys/types.h> 8275793eaSopenharmony_ci#include <unistd.h> 9275793eaSopenharmony_ci 10275793eaSopenharmony_ci#if defined(_WIN32) && !defined(__BORLANDC__) 11275793eaSopenharmony_ci# define LSEEK _lseeki64 12275793eaSopenharmony_ci#else 13275793eaSopenharmony_ci#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 14275793eaSopenharmony_ci# define LSEEK lseek64 15275793eaSopenharmony_ci#else 16275793eaSopenharmony_ci# define LSEEK lseek 17275793eaSopenharmony_ci#endif 18275793eaSopenharmony_ci#endif 19275793eaSopenharmony_ci 20275793eaSopenharmony_ci#if defined UNDER_CE 21275793eaSopenharmony_ci 22275793eaSopenharmony_ci/* Map the Windows error number in ERROR to a locale-dependent error message 23275793eaSopenharmony_ci string and return a pointer to it. Typically, the values for ERROR come 24275793eaSopenharmony_ci from GetLastError. 25275793eaSopenharmony_ci 26275793eaSopenharmony_ci The string pointed to shall not be modified by the application, but may be 27275793eaSopenharmony_ci overwritten by a subsequent call to gz_strwinerror 28275793eaSopenharmony_ci 29275793eaSopenharmony_ci The gz_strwinerror function does not change the current setting of 30275793eaSopenharmony_ci GetLastError. */ 31275793eaSopenharmony_cichar ZLIB_INTERNAL *gz_strwinerror(DWORD error) { 32275793eaSopenharmony_ci static char buf[1024]; 33275793eaSopenharmony_ci 34275793eaSopenharmony_ci wchar_t *msgbuf; 35275793eaSopenharmony_ci DWORD lasterr = GetLastError(); 36275793eaSopenharmony_ci DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM 37275793eaSopenharmony_ci | FORMAT_MESSAGE_ALLOCATE_BUFFER, 38275793eaSopenharmony_ci NULL, 39275793eaSopenharmony_ci error, 40275793eaSopenharmony_ci 0, /* Default language */ 41275793eaSopenharmony_ci (LPVOID)&msgbuf, 42275793eaSopenharmony_ci 0, 43275793eaSopenharmony_ci NULL); 44275793eaSopenharmony_ci if (chars != 0) { 45275793eaSopenharmony_ci /* If there is an \r\n appended, zap it. */ 46275793eaSopenharmony_ci if (chars >= 2 47275793eaSopenharmony_ci && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') { 48275793eaSopenharmony_ci chars -= 2; 49275793eaSopenharmony_ci msgbuf[chars] = 0; 50275793eaSopenharmony_ci } 51275793eaSopenharmony_ci 52275793eaSopenharmony_ci if (chars > sizeof (buf) - 1) { 53275793eaSopenharmony_ci chars = sizeof (buf) - 1; 54275793eaSopenharmony_ci msgbuf[chars] = 0; 55275793eaSopenharmony_ci } 56275793eaSopenharmony_ci 57275793eaSopenharmony_ci wcstombs(buf, msgbuf, chars + 1); 58275793eaSopenharmony_ci LocalFree(msgbuf); 59275793eaSopenharmony_ci } 60275793eaSopenharmony_ci else { 61275793eaSopenharmony_ci sprintf(buf, "unknown win32 error (%ld)", error); 62275793eaSopenharmony_ci } 63275793eaSopenharmony_ci 64275793eaSopenharmony_ci SetLastError(lasterr); 65275793eaSopenharmony_ci return buf; 66275793eaSopenharmony_ci} 67275793eaSopenharmony_ci 68275793eaSopenharmony_ci#endif /* UNDER_CE */ 69275793eaSopenharmony_ci 70275793eaSopenharmony_ci/* Reset gzip file state */ 71275793eaSopenharmony_cilocal void gz_reset(gz_statep state) 72275793eaSopenharmony_ci{ 73275793eaSopenharmony_ci state->x.have = 0; /* no output data available */ 74275793eaSopenharmony_ci if (state->mode == GZ_READ) { /* for reading ... */ 75275793eaSopenharmony_ci state->eof = 0; /* not at end of file */ 76275793eaSopenharmony_ci state->past = 0; /* have not read past end yet */ 77275793eaSopenharmony_ci state->how = LOOK; /* look for gzip header */ 78275793eaSopenharmony_ci } 79275793eaSopenharmony_ci else /* for writing ... */ 80275793eaSopenharmony_ci state->reset = 0; /* no deflateReset pending */ 81275793eaSopenharmony_ci state->seek = 0; /* no seek request pending */ 82275793eaSopenharmony_ci gz_error(state, Z_OK, NULL); /* clear error */ 83275793eaSopenharmony_ci state->x.pos = 0; /* no uncompressed data yet */ 84275793eaSopenharmony_ci state->strm.avail_in = 0; /* no input data yet */ 85275793eaSopenharmony_ci} 86275793eaSopenharmony_ci 87275793eaSopenharmony_ci/* Open a gzip file either by name or file descriptor. */ 88275793eaSopenharmony_cilocal gzFile gz_open(const void *path, int fd, const char *mode) 89275793eaSopenharmony_ci{ 90275793eaSopenharmony_ci gz_statep state; 91275793eaSopenharmony_ci z_size_t len; 92275793eaSopenharmony_ci int oflag; 93275793eaSopenharmony_ci#ifdef O_CLOEXEC 94275793eaSopenharmony_ci int cloexec = 0; 95275793eaSopenharmony_ci#endif 96275793eaSopenharmony_ci#ifdef O_EXCL 97275793eaSopenharmony_ci int exclusive = 0; 98275793eaSopenharmony_ci#endif 99275793eaSopenharmony_ci 100275793eaSopenharmony_ci /* check input */ 101275793eaSopenharmony_ci if (path == NULL) 102275793eaSopenharmony_ci return NULL; 103275793eaSopenharmony_ci 104275793eaSopenharmony_ci /* allocate gzFile structure to return */ 105275793eaSopenharmony_ci state = (gz_statep)malloc(sizeof(gz_state)); 106275793eaSopenharmony_ci if (state == NULL) 107275793eaSopenharmony_ci return NULL; 108275793eaSopenharmony_ci state->size = 0; /* no buffers allocated yet */ 109275793eaSopenharmony_ci state->want = GZBUFSIZE; /* requested buffer size */ 110275793eaSopenharmony_ci state->msg = NULL; /* no error message yet */ 111275793eaSopenharmony_ci 112275793eaSopenharmony_ci /* interpret mode */ 113275793eaSopenharmony_ci state->mode = GZ_NONE; 114275793eaSopenharmony_ci state->level = Z_DEFAULT_COMPRESSION; 115275793eaSopenharmony_ci state->strategy = Z_DEFAULT_STRATEGY; 116275793eaSopenharmony_ci state->direct = 0; 117275793eaSopenharmony_ci while (*mode) { 118275793eaSopenharmony_ci if (*mode >= '0' && *mode <= '9') 119275793eaSopenharmony_ci state->level = *mode - '0'; 120275793eaSopenharmony_ci else 121275793eaSopenharmony_ci switch (*mode) { 122275793eaSopenharmony_ci case 'r': 123275793eaSopenharmony_ci state->mode = GZ_READ; 124275793eaSopenharmony_ci break; 125275793eaSopenharmony_ci#ifndef NO_GZCOMPRESS 126275793eaSopenharmony_ci case 'w': 127275793eaSopenharmony_ci state->mode = GZ_WRITE; 128275793eaSopenharmony_ci break; 129275793eaSopenharmony_ci case 'a': 130275793eaSopenharmony_ci state->mode = GZ_APPEND; 131275793eaSopenharmony_ci break; 132275793eaSopenharmony_ci#endif 133275793eaSopenharmony_ci case '+': /* can't read and write at the same time */ 134275793eaSopenharmony_ci free(state); 135275793eaSopenharmony_ci return NULL; 136275793eaSopenharmony_ci case 'b': /* ignore -- will request binary anyway */ 137275793eaSopenharmony_ci break; 138275793eaSopenharmony_ci#ifdef O_CLOEXEC 139275793eaSopenharmony_ci case 'e': 140275793eaSopenharmony_ci cloexec = 1; 141275793eaSopenharmony_ci break; 142275793eaSopenharmony_ci#endif 143275793eaSopenharmony_ci#ifdef O_EXCL 144275793eaSopenharmony_ci case 'x': 145275793eaSopenharmony_ci exclusive = 1; 146275793eaSopenharmony_ci break; 147275793eaSopenharmony_ci#endif 148275793eaSopenharmony_ci case 'f': 149275793eaSopenharmony_ci state->strategy = Z_FILTERED; 150275793eaSopenharmony_ci break; 151275793eaSopenharmony_ci case 'h': 152275793eaSopenharmony_ci state->strategy = Z_HUFFMAN_ONLY; 153275793eaSopenharmony_ci break; 154275793eaSopenharmony_ci case 'R': 155275793eaSopenharmony_ci state->strategy = Z_RLE; 156275793eaSopenharmony_ci break; 157275793eaSopenharmony_ci case 'F': 158275793eaSopenharmony_ci state->strategy = Z_FIXED; 159275793eaSopenharmony_ci break; 160275793eaSopenharmony_ci case 'T': 161275793eaSopenharmony_ci state->direct = 1; 162275793eaSopenharmony_ci break; 163275793eaSopenharmony_ci default: /* could consider as an error, but just ignore */ 164275793eaSopenharmony_ci ; 165275793eaSopenharmony_ci } 166275793eaSopenharmony_ci mode++; 167275793eaSopenharmony_ci } 168275793eaSopenharmony_ci 169275793eaSopenharmony_ci /* must provide an "r", "w", or "a" */ 170275793eaSopenharmony_ci if (state->mode == GZ_NONE) { 171275793eaSopenharmony_ci free(state); 172275793eaSopenharmony_ci return NULL; 173275793eaSopenharmony_ci } 174275793eaSopenharmony_ci 175275793eaSopenharmony_ci /* can't force transparent read */ 176275793eaSopenharmony_ci if (state->mode == GZ_READ) { 177275793eaSopenharmony_ci if (state->direct) { 178275793eaSopenharmony_ci free(state); 179275793eaSopenharmony_ci return NULL; 180275793eaSopenharmony_ci } 181275793eaSopenharmony_ci state->direct = 1; /* for empty file */ 182275793eaSopenharmony_ci } 183275793eaSopenharmony_ci 184275793eaSopenharmony_ci /* save the path name for error messages */ 185275793eaSopenharmony_ci#ifdef WIDECHAR 186275793eaSopenharmony_ci if (fd == -2) { 187275793eaSopenharmony_ci len = wcstombs(NULL, path, 0); 188275793eaSopenharmony_ci if (len == (z_size_t)-1) 189275793eaSopenharmony_ci len = 0; 190275793eaSopenharmony_ci } 191275793eaSopenharmony_ci else 192275793eaSopenharmony_ci#endif 193275793eaSopenharmony_ci len = strlen((const char *)path); 194275793eaSopenharmony_ci state->path = (char *)malloc(len + 1); 195275793eaSopenharmony_ci if (state->path == NULL) { 196275793eaSopenharmony_ci free(state); 197275793eaSopenharmony_ci return NULL; 198275793eaSopenharmony_ci } 199275793eaSopenharmony_ci#ifdef WIDECHAR 200275793eaSopenharmony_ci if (fd == -2) 201275793eaSopenharmony_ci if (len) 202275793eaSopenharmony_ci wcstombs(state->path, path, len + 1); 203275793eaSopenharmony_ci else 204275793eaSopenharmony_ci *(state->path) = 0; 205275793eaSopenharmony_ci else 206275793eaSopenharmony_ci#endif 207275793eaSopenharmony_ci#if !defined(NO_snprintf) && !defined(NO_vsnprintf) 208275793eaSopenharmony_ci (void)snprintf(state->path, len + 1, "%s", (const char *)path); 209275793eaSopenharmony_ci#else 210275793eaSopenharmony_ci strcpy(state->path, path); 211275793eaSopenharmony_ci#endif 212275793eaSopenharmony_ci 213275793eaSopenharmony_ci /* compute the flags for open() */ 214275793eaSopenharmony_ci oflag = 215275793eaSopenharmony_ci#ifdef O_LARGEFILE 216275793eaSopenharmony_ci O_LARGEFILE | 217275793eaSopenharmony_ci#endif 218275793eaSopenharmony_ci#ifdef O_BINARY 219275793eaSopenharmony_ci O_BINARY | 220275793eaSopenharmony_ci#endif 221275793eaSopenharmony_ci#ifdef O_CLOEXEC 222275793eaSopenharmony_ci (cloexec ? O_CLOEXEC : 0) | 223275793eaSopenharmony_ci#endif 224275793eaSopenharmony_ci (state->mode == GZ_READ ? 225275793eaSopenharmony_ci O_RDONLY : 226275793eaSopenharmony_ci (O_WRONLY | O_CREAT | 227275793eaSopenharmony_ci#ifdef O_EXCL 228275793eaSopenharmony_ci (exclusive ? O_EXCL : 0) | 229275793eaSopenharmony_ci#endif 230275793eaSopenharmony_ci (state->mode == GZ_WRITE ? 231275793eaSopenharmony_ci O_TRUNC : 232275793eaSopenharmony_ci O_APPEND))); 233275793eaSopenharmony_ci 234275793eaSopenharmony_ci /* open the file with the appropriate flags (or just use fd) */ 235275793eaSopenharmony_ci state->fd = fd > -1 ? fd : ( 236275793eaSopenharmony_ci#ifdef WIDECHAR 237275793eaSopenharmony_ci fd == -2 ? _wopen(path, oflag, 0666) : 238275793eaSopenharmony_ci#endif 239275793eaSopenharmony_ci open((const char *)path, oflag, 0666)); 240275793eaSopenharmony_ci if (state->fd == -1) { 241275793eaSopenharmony_ci free(state->path); 242275793eaSopenharmony_ci free(state); 243275793eaSopenharmony_ci return NULL; 244275793eaSopenharmony_ci } 245275793eaSopenharmony_ci if (state->mode == GZ_APPEND) { 246275793eaSopenharmony_ci LSEEK(state->fd, 0, SEEK_END); /* so gzoffset() is correct */ 247275793eaSopenharmony_ci state->mode = GZ_WRITE; /* simplify later checks */ 248275793eaSopenharmony_ci } 249275793eaSopenharmony_ci 250275793eaSopenharmony_ci /* save the current position for rewinding (only if reading) */ 251275793eaSopenharmony_ci if (state->mode == GZ_READ) { 252275793eaSopenharmony_ci state->start = LSEEK(state->fd, 0, SEEK_CUR); 253275793eaSopenharmony_ci if (state->start == -1) state->start = 0; 254275793eaSopenharmony_ci } 255275793eaSopenharmony_ci 256275793eaSopenharmony_ci /* initialize stream */ 257275793eaSopenharmony_ci gz_reset(state); 258275793eaSopenharmony_ci 259275793eaSopenharmony_ci /* return stream */ 260275793eaSopenharmony_ci return (gzFile)state; 261275793eaSopenharmony_ci} 262275793eaSopenharmony_ci 263275793eaSopenharmony_ci/* -- see zlib.h -- */ 264275793eaSopenharmony_cigzFile ZEXPORT gzopen(const char *path, const char *mode) 265275793eaSopenharmony_ci{ 266275793eaSopenharmony_ci return gz_open(path, -1, mode); 267275793eaSopenharmony_ci} 268275793eaSopenharmony_ci 269275793eaSopenharmony_ci/* -- see zlib.h -- */ 270275793eaSopenharmony_cigzFile ZEXPORT gzopen64(const char *path, const char *mode) 271275793eaSopenharmony_ci{ 272275793eaSopenharmony_ci return gz_open(path, -1, mode); 273275793eaSopenharmony_ci} 274275793eaSopenharmony_ci 275275793eaSopenharmony_ci/* -- see zlib.h -- */ 276275793eaSopenharmony_cigzFile ZEXPORT gzdopen(int fd, const char *mode) 277275793eaSopenharmony_ci{ 278275793eaSopenharmony_ci char *path; /* identifier for error messages */ 279275793eaSopenharmony_ci gzFile gz; 280275793eaSopenharmony_ci 281275793eaSopenharmony_ci if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL) 282275793eaSopenharmony_ci return NULL; 283275793eaSopenharmony_ci#if !defined(NO_snprintf) && !defined(NO_vsnprintf) 284275793eaSopenharmony_ci (void)snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd); 285275793eaSopenharmony_ci#else 286275793eaSopenharmony_ci sprintf(path, "<fd:%d>", fd); /* for debugging */ 287275793eaSopenharmony_ci#endif 288275793eaSopenharmony_ci gz = gz_open(path, fd, mode); 289275793eaSopenharmony_ci free(path); 290275793eaSopenharmony_ci return gz; 291275793eaSopenharmony_ci} 292275793eaSopenharmony_ci 293275793eaSopenharmony_ci/* -- see zlib.h -- */ 294275793eaSopenharmony_ci#ifdef WIDECHAR 295275793eaSopenharmony_cigzFile ZEXPORT gzopen_w(const wchar_t *path, const char *mode) 296275793eaSopenharmony_ci{ 297275793eaSopenharmony_ci return gz_open(path, -2, mode); 298275793eaSopenharmony_ci} 299275793eaSopenharmony_ci#endif 300275793eaSopenharmony_ci 301275793eaSopenharmony_ci/* -- see zlib.h -- */ 302275793eaSopenharmony_ciint ZEXPORT gzbuffer(gzFile file, unsigned size) { 303275793eaSopenharmony_ci gz_statep state; 304275793eaSopenharmony_ci 305275793eaSopenharmony_ci /* get internal structure and check integrity */ 306275793eaSopenharmony_ci if (file == NULL) 307275793eaSopenharmony_ci return -1; 308275793eaSopenharmony_ci state = (gz_statep)file; 309275793eaSopenharmony_ci if (state->mode != GZ_READ && state->mode != GZ_WRITE) 310275793eaSopenharmony_ci return -1; 311275793eaSopenharmony_ci 312275793eaSopenharmony_ci /* make sure we haven't already allocated memory */ 313275793eaSopenharmony_ci if (state->size != 0) 314275793eaSopenharmony_ci return -1; 315275793eaSopenharmony_ci 316275793eaSopenharmony_ci /* check and set requested size */ 317275793eaSopenharmony_ci if ((size << 1) < size) 318275793eaSopenharmony_ci return -1; /* need to be able to double it */ 319275793eaSopenharmony_ci if (size < 8) 320275793eaSopenharmony_ci size = 8; /* needed to behave well with flushing */ 321275793eaSopenharmony_ci state->want = size; 322275793eaSopenharmony_ci return 0; 323275793eaSopenharmony_ci} 324275793eaSopenharmony_ci 325275793eaSopenharmony_ci/* -- see zlib.h -- */ 326275793eaSopenharmony_ciint ZEXPORT gzrewind(gzFile file) { 327275793eaSopenharmony_ci gz_statep state; 328275793eaSopenharmony_ci 329275793eaSopenharmony_ci /* get internal structure */ 330275793eaSopenharmony_ci if (file == NULL) 331275793eaSopenharmony_ci return -1; 332275793eaSopenharmony_ci state = (gz_statep)file; 333275793eaSopenharmony_ci 334275793eaSopenharmony_ci /* check that we're reading and that there's no error */ 335275793eaSopenharmony_ci if (state->mode != GZ_READ || 336275793eaSopenharmony_ci (state->err != Z_OK && state->err != Z_BUF_ERROR)) 337275793eaSopenharmony_ci return -1; 338275793eaSopenharmony_ci 339275793eaSopenharmony_ci /* back up and start over */ 340275793eaSopenharmony_ci if (LSEEK(state->fd, state->start, SEEK_SET) == -1) 341275793eaSopenharmony_ci return -1; 342275793eaSopenharmony_ci gz_reset(state); 343275793eaSopenharmony_ci return 0; 344275793eaSopenharmony_ci} 345275793eaSopenharmony_ci 346275793eaSopenharmony_ci/* -- see zlib.h -- */ 347275793eaSopenharmony_ciz_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence) 348275793eaSopenharmony_ci{ 349275793eaSopenharmony_ci unsigned n; 350275793eaSopenharmony_ci z_off64_t ret; 351275793eaSopenharmony_ci gz_statep state; 352275793eaSopenharmony_ci 353275793eaSopenharmony_ci /* get internal structure and check integrity */ 354275793eaSopenharmony_ci if (file == NULL) 355275793eaSopenharmony_ci return -1; 356275793eaSopenharmony_ci state = (gz_statep)file; 357275793eaSopenharmony_ci if (state->mode != GZ_READ && state->mode != GZ_WRITE) 358275793eaSopenharmony_ci return -1; 359275793eaSopenharmony_ci 360275793eaSopenharmony_ci /* check that there's no error */ 361275793eaSopenharmony_ci if (state->err != Z_OK && state->err != Z_BUF_ERROR) 362275793eaSopenharmony_ci return -1; 363275793eaSopenharmony_ci 364275793eaSopenharmony_ci /* can only seek from start or relative to current position */ 365275793eaSopenharmony_ci if (whence != SEEK_SET && whence != SEEK_CUR) 366275793eaSopenharmony_ci return -1; 367275793eaSopenharmony_ci 368275793eaSopenharmony_ci /* normalize offset to a SEEK_CUR specification */ 369275793eaSopenharmony_ci if (whence == SEEK_SET) 370275793eaSopenharmony_ci offset -= state->x.pos; 371275793eaSopenharmony_ci else if (state->seek) 372275793eaSopenharmony_ci offset += state->skip; 373275793eaSopenharmony_ci state->seek = 0; 374275793eaSopenharmony_ci 375275793eaSopenharmony_ci /* if within raw area while reading, just go there */ 376275793eaSopenharmony_ci if (state->mode == GZ_READ && state->how == COPY && 377275793eaSopenharmony_ci state->x.pos + offset >= 0) { 378275793eaSopenharmony_ci ret = LSEEK(state->fd, offset - (z_off64_t)state->x.have, SEEK_CUR); 379275793eaSopenharmony_ci if (ret == -1) 380275793eaSopenharmony_ci return -1; 381275793eaSopenharmony_ci state->x.have = 0; 382275793eaSopenharmony_ci state->eof = 0; 383275793eaSopenharmony_ci state->past = 0; 384275793eaSopenharmony_ci state->seek = 0; 385275793eaSopenharmony_ci gz_error(state, Z_OK, NULL); 386275793eaSopenharmony_ci state->strm.avail_in = 0; 387275793eaSopenharmony_ci state->x.pos += offset; 388275793eaSopenharmony_ci return state->x.pos; 389275793eaSopenharmony_ci } 390275793eaSopenharmony_ci 391275793eaSopenharmony_ci /* calculate skip amount, rewinding if needed for back seek when reading */ 392275793eaSopenharmony_ci if (offset < 0) { 393275793eaSopenharmony_ci if (state->mode != GZ_READ) /* writing -- can't go backwards */ 394275793eaSopenharmony_ci return -1; 395275793eaSopenharmony_ci offset += state->x.pos; 396275793eaSopenharmony_ci if (offset < 0) /* before start of file! */ 397275793eaSopenharmony_ci return -1; 398275793eaSopenharmony_ci if (gzrewind(file) == -1) /* rewind, then skip to offset */ 399275793eaSopenharmony_ci return -1; 400275793eaSopenharmony_ci } 401275793eaSopenharmony_ci 402275793eaSopenharmony_ci /* if reading, skip what's in output buffer (one less gzgetc() check) */ 403275793eaSopenharmony_ci if (state->mode == GZ_READ) { 404275793eaSopenharmony_ci n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ? 405275793eaSopenharmony_ci (unsigned)offset : state->x.have; 406275793eaSopenharmony_ci state->x.have -= n; 407275793eaSopenharmony_ci state->x.next += n; 408275793eaSopenharmony_ci state->x.pos += n; 409275793eaSopenharmony_ci offset -= n; 410275793eaSopenharmony_ci } 411275793eaSopenharmony_ci 412275793eaSopenharmony_ci /* request skip (if not zero) */ 413275793eaSopenharmony_ci if (offset) { 414275793eaSopenharmony_ci state->seek = 1; 415275793eaSopenharmony_ci state->skip = offset; 416275793eaSopenharmony_ci } 417275793eaSopenharmony_ci return state->x.pos + offset; 418275793eaSopenharmony_ci} 419275793eaSopenharmony_ci 420275793eaSopenharmony_ci/* -- see zlib.h -- */ 421275793eaSopenharmony_ciz_off_t ZEXPORT gzseek(gzFile file, z_off_t offset, int whence) 422275793eaSopenharmony_ci{ 423275793eaSopenharmony_ci z_off64_t ret; 424275793eaSopenharmony_ci 425275793eaSopenharmony_ci ret = gzseek64(file, (z_off64_t)offset, whence); 426275793eaSopenharmony_ci return ret == (z_off_t)ret ? (z_off_t)ret : -1; 427275793eaSopenharmony_ci} 428275793eaSopenharmony_ci 429275793eaSopenharmony_ci/* -- see zlib.h -- */ 430275793eaSopenharmony_ciz_off64_t ZEXPORT gztell64(gzFile file) 431275793eaSopenharmony_ci{ 432275793eaSopenharmony_ci gz_statep state; 433275793eaSopenharmony_ci 434275793eaSopenharmony_ci /* get internal structure and check integrity */ 435275793eaSopenharmony_ci if (file == NULL) 436275793eaSopenharmony_ci return -1; 437275793eaSopenharmony_ci state = (gz_statep)file; 438275793eaSopenharmony_ci if (state->mode != GZ_READ && state->mode != GZ_WRITE) 439275793eaSopenharmony_ci return -1; 440275793eaSopenharmony_ci 441275793eaSopenharmony_ci /* return position */ 442275793eaSopenharmony_ci return state->x.pos + (state->seek ? state->skip : 0); 443275793eaSopenharmony_ci} 444275793eaSopenharmony_ci 445275793eaSopenharmony_ci/* -- see zlib.h -- */ 446275793eaSopenharmony_ciz_off_t ZEXPORT gztell(gzFile file) 447275793eaSopenharmony_ci{ 448275793eaSopenharmony_ci z_off64_t ret; 449275793eaSopenharmony_ci 450275793eaSopenharmony_ci ret = gztell64(file); 451275793eaSopenharmony_ci return ret == (z_off_t)ret ? (z_off_t)ret : -1; 452275793eaSopenharmony_ci} 453275793eaSopenharmony_ci 454275793eaSopenharmony_ci/* -- see zlib.h -- */ 455275793eaSopenharmony_ciz_off64_t ZEXPORT gzoffset64(gzFile file) 456275793eaSopenharmony_ci{ 457275793eaSopenharmony_ci z_off64_t offset; 458275793eaSopenharmony_ci gz_statep state; 459275793eaSopenharmony_ci 460275793eaSopenharmony_ci /* get internal structure and check integrity */ 461275793eaSopenharmony_ci if (file == NULL) 462275793eaSopenharmony_ci return -1; 463275793eaSopenharmony_ci state = (gz_statep)file; 464275793eaSopenharmony_ci if (state->mode != GZ_READ && state->mode != GZ_WRITE) 465275793eaSopenharmony_ci return -1; 466275793eaSopenharmony_ci 467275793eaSopenharmony_ci /* compute and return effective offset in file */ 468275793eaSopenharmony_ci offset = LSEEK(state->fd, 0, SEEK_CUR); 469275793eaSopenharmony_ci if (offset == -1) 470275793eaSopenharmony_ci return -1; 471275793eaSopenharmony_ci if (state->mode == GZ_READ) /* reading */ 472275793eaSopenharmony_ci offset -= state->strm.avail_in; /* don't count buffered input */ 473275793eaSopenharmony_ci return offset; 474275793eaSopenharmony_ci} 475275793eaSopenharmony_ci 476275793eaSopenharmony_ci/* -- see zlib.h -- */ 477275793eaSopenharmony_ciz_off_t ZEXPORT gzoffset(gzFile file) 478275793eaSopenharmony_ci{ 479275793eaSopenharmony_ci z_off64_t ret; 480275793eaSopenharmony_ci 481275793eaSopenharmony_ci ret = gzoffset64(file); 482275793eaSopenharmony_ci return ret == (z_off_t)ret ? (z_off_t)ret : -1; 483275793eaSopenharmony_ci} 484275793eaSopenharmony_ci 485275793eaSopenharmony_ci/* -- see zlib.h -- */ 486275793eaSopenharmony_ciint ZEXPORT gzeof(gzFile file) { 487275793eaSopenharmony_ci gz_statep state; 488275793eaSopenharmony_ci 489275793eaSopenharmony_ci /* get internal structure and check integrity */ 490275793eaSopenharmony_ci if (file == NULL) 491275793eaSopenharmony_ci return 0; 492275793eaSopenharmony_ci state = (gz_statep)file; 493275793eaSopenharmony_ci if (state->mode != GZ_READ && state->mode != GZ_WRITE) 494275793eaSopenharmony_ci return 0; 495275793eaSopenharmony_ci 496275793eaSopenharmony_ci /* return end-of-file state */ 497275793eaSopenharmony_ci return state->mode == GZ_READ ? state->past : 0; 498275793eaSopenharmony_ci} 499275793eaSopenharmony_ci 500275793eaSopenharmony_ci/* -- see zlib.h -- */ 501275793eaSopenharmony_ciconst char * ZEXPORT gzerror(gzFile file, int *errnum) { 502275793eaSopenharmony_ci gz_statep state; 503275793eaSopenharmony_ci 504275793eaSopenharmony_ci /* get internal structure and check integrity */ 505275793eaSopenharmony_ci if (file == NULL) 506275793eaSopenharmony_ci return NULL; 507275793eaSopenharmony_ci state = (gz_statep)file; 508275793eaSopenharmony_ci if (state->mode != GZ_READ && state->mode != GZ_WRITE) 509275793eaSopenharmony_ci return NULL; 510275793eaSopenharmony_ci 511275793eaSopenharmony_ci /* return error information */ 512275793eaSopenharmony_ci if (errnum != NULL) 513275793eaSopenharmony_ci *errnum = state->err; 514275793eaSopenharmony_ci return state->err == Z_MEM_ERROR ? "out of memory" : 515275793eaSopenharmony_ci (state->msg == NULL ? "" : state->msg); 516275793eaSopenharmony_ci} 517275793eaSopenharmony_ci 518275793eaSopenharmony_ci/* -- see zlib.h -- */ 519275793eaSopenharmony_civoid ZEXPORT gzclearerr(gzFile file) { 520275793eaSopenharmony_ci gz_statep state; 521275793eaSopenharmony_ci 522275793eaSopenharmony_ci /* get internal structure and check integrity */ 523275793eaSopenharmony_ci if (file == NULL) 524275793eaSopenharmony_ci return; 525275793eaSopenharmony_ci state = (gz_statep)file; 526275793eaSopenharmony_ci if (state->mode != GZ_READ && state->mode != GZ_WRITE) 527275793eaSopenharmony_ci return; 528275793eaSopenharmony_ci 529275793eaSopenharmony_ci /* clear error and end-of-file */ 530275793eaSopenharmony_ci if (state->mode == GZ_READ) { 531275793eaSopenharmony_ci state->eof = 0; 532275793eaSopenharmony_ci state->past = 0; 533275793eaSopenharmony_ci } 534275793eaSopenharmony_ci gz_error(state, Z_OK, NULL); 535275793eaSopenharmony_ci} 536275793eaSopenharmony_ci 537275793eaSopenharmony_ci/* Create an error message in allocated memory and set state->err and 538275793eaSopenharmony_ci state->msg accordingly. Free any previous error message already there. Do 539275793eaSopenharmony_ci not try to free or allocate space if the error is Z_MEM_ERROR (out of 540275793eaSopenharmony_ci memory). Simply save the error message as a static string. If there is an 541275793eaSopenharmony_ci allocation failure constructing the error message, then convert the error to 542275793eaSopenharmony_ci out of memory. */ 543275793eaSopenharmony_civoid ZLIB_INTERNAL gz_error(gz_statep state, int err, const char *msg) { 544275793eaSopenharmony_ci /* free previously allocated message and clear */ 545275793eaSopenharmony_ci if (state->msg != NULL) { 546275793eaSopenharmony_ci if (state->err != Z_MEM_ERROR) 547275793eaSopenharmony_ci free(state->msg); 548275793eaSopenharmony_ci state->msg = NULL; 549275793eaSopenharmony_ci } 550275793eaSopenharmony_ci 551275793eaSopenharmony_ci /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */ 552275793eaSopenharmony_ci if (err != Z_OK && err != Z_BUF_ERROR) 553275793eaSopenharmony_ci state->x.have = 0; 554275793eaSopenharmony_ci 555275793eaSopenharmony_ci /* set error code, and if no message, then done */ 556275793eaSopenharmony_ci state->err = err; 557275793eaSopenharmony_ci if (msg == NULL) 558275793eaSopenharmony_ci return; 559275793eaSopenharmony_ci 560275793eaSopenharmony_ci /* for an out of memory error, return literal string when requested */ 561275793eaSopenharmony_ci if (err == Z_MEM_ERROR) 562275793eaSopenharmony_ci return; 563275793eaSopenharmony_ci 564275793eaSopenharmony_ci /* construct error message with path */ 565275793eaSopenharmony_ci if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) == 566275793eaSopenharmony_ci NULL) { 567275793eaSopenharmony_ci state->err = Z_MEM_ERROR; 568275793eaSopenharmony_ci return; 569275793eaSopenharmony_ci } 570275793eaSopenharmony_ci#if !defined(NO_snprintf) && !defined(NO_vsnprintf) 571275793eaSopenharmony_ci (void)snprintf(state->msg, strlen(state->path) + strlen(msg) + 3, 572275793eaSopenharmony_ci "%s%s%s", state->path, ": ", msg); 573275793eaSopenharmony_ci#else 574275793eaSopenharmony_ci strcpy(state->msg, state->path); 575275793eaSopenharmony_ci strcat(state->msg, ": "); 576275793eaSopenharmony_ci strcat(state->msg, msg); 577275793eaSopenharmony_ci#endif 578275793eaSopenharmony_ci} 579275793eaSopenharmony_ci 580275793eaSopenharmony_ci/* portably return maximum value for an int (when limits.h presumed not 581275793eaSopenharmony_ci available) -- we need to do this to cover cases where 2's complement not 582275793eaSopenharmony_ci used, since C standard permits 1's complement and sign-bit representations, 583275793eaSopenharmony_ci otherwise we could just use ((unsigned)-1) >> 1 */ 584275793eaSopenharmony_ciunsigned ZLIB_INTERNAL gz_intmax(void) { 585275793eaSopenharmony_ci#ifdef INT_MAX 586275793eaSopenharmony_ci return INT_MAX; 587275793eaSopenharmony_ci#else 588275793eaSopenharmony_ci unsigned p = 1, q; 589275793eaSopenharmony_ci do { 590275793eaSopenharmony_ci q = p; 591275793eaSopenharmony_ci p <<= 1; 592275793eaSopenharmony_ci p++; 593275793eaSopenharmony_ci } while (p > q); 594275793eaSopenharmony_ci return q >> 1; 595275793eaSopenharmony_ci#endif 596275793eaSopenharmony_ci} 597