11cb0ef41Sopenharmony_ci/* gzlib.c -- zlib functions common to reading and writing gzip files 21cb0ef41Sopenharmony_ci * Copyright (C) 2004-2019 Mark Adler 31cb0ef41Sopenharmony_ci * For conditions of distribution and use, see copyright notice in zlib.h 41cb0ef41Sopenharmony_ci */ 51cb0ef41Sopenharmony_ci 61cb0ef41Sopenharmony_ci#include "gzguts.h" 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ci#if defined(_WIN32) && !defined(__BORLANDC__) 91cb0ef41Sopenharmony_ci# define LSEEK _lseeki64 101cb0ef41Sopenharmony_ci# define OPEN open 111cb0ef41Sopenharmony_ci#else 121cb0ef41Sopenharmony_ci#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 131cb0ef41Sopenharmony_ci# define LSEEK lseek64 141cb0ef41Sopenharmony_ci# define OPEN open64 151cb0ef41Sopenharmony_ci#else 161cb0ef41Sopenharmony_ci# define LSEEK lseek 171cb0ef41Sopenharmony_ci# define OPEN open 181cb0ef41Sopenharmony_ci#endif 191cb0ef41Sopenharmony_ci#endif 201cb0ef41Sopenharmony_ci 211cb0ef41Sopenharmony_ci#if defined UNDER_CE 221cb0ef41Sopenharmony_ci 231cb0ef41Sopenharmony_ci/* Map the Windows error number in ERROR to a locale-dependent error message 241cb0ef41Sopenharmony_ci string and return a pointer to it. Typically, the values for ERROR come 251cb0ef41Sopenharmony_ci from GetLastError. 261cb0ef41Sopenharmony_ci 271cb0ef41Sopenharmony_ci The string pointed to shall not be modified by the application, but may be 281cb0ef41Sopenharmony_ci overwritten by a subsequent call to gz_strwinerror 291cb0ef41Sopenharmony_ci 301cb0ef41Sopenharmony_ci The gz_strwinerror function does not change the current setting of 311cb0ef41Sopenharmony_ci GetLastError. */ 321cb0ef41Sopenharmony_cichar ZLIB_INTERNAL *gz_strwinerror(DWORD error) { 331cb0ef41Sopenharmony_ci static char buf[1024]; 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_ci wchar_t *msgbuf; 361cb0ef41Sopenharmony_ci DWORD lasterr = GetLastError(); 371cb0ef41Sopenharmony_ci DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM 381cb0ef41Sopenharmony_ci | FORMAT_MESSAGE_ALLOCATE_BUFFER, 391cb0ef41Sopenharmony_ci NULL, 401cb0ef41Sopenharmony_ci error, 411cb0ef41Sopenharmony_ci 0, /* Default language */ 421cb0ef41Sopenharmony_ci (LPVOID)&msgbuf, 431cb0ef41Sopenharmony_ci 0, 441cb0ef41Sopenharmony_ci NULL); 451cb0ef41Sopenharmony_ci if (chars != 0) { 461cb0ef41Sopenharmony_ci /* If there is an \r\n appended, zap it. */ 471cb0ef41Sopenharmony_ci if (chars >= 2 481cb0ef41Sopenharmony_ci && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') { 491cb0ef41Sopenharmony_ci chars -= 2; 501cb0ef41Sopenharmony_ci msgbuf[chars] = 0; 511cb0ef41Sopenharmony_ci } 521cb0ef41Sopenharmony_ci 531cb0ef41Sopenharmony_ci if (chars > sizeof (buf) - 1) { 541cb0ef41Sopenharmony_ci chars = sizeof (buf) - 1; 551cb0ef41Sopenharmony_ci msgbuf[chars] = 0; 561cb0ef41Sopenharmony_ci } 571cb0ef41Sopenharmony_ci 581cb0ef41Sopenharmony_ci wcstombs(buf, msgbuf, chars + 1); 591cb0ef41Sopenharmony_ci LocalFree(msgbuf); 601cb0ef41Sopenharmony_ci } 611cb0ef41Sopenharmony_ci else { 621cb0ef41Sopenharmony_ci sprintf(buf, "unknown win32 error (%ld)", error); 631cb0ef41Sopenharmony_ci } 641cb0ef41Sopenharmony_ci 651cb0ef41Sopenharmony_ci SetLastError(lasterr); 661cb0ef41Sopenharmony_ci return buf; 671cb0ef41Sopenharmony_ci} 681cb0ef41Sopenharmony_ci 691cb0ef41Sopenharmony_ci#endif /* UNDER_CE */ 701cb0ef41Sopenharmony_ci 711cb0ef41Sopenharmony_ci/* Reset gzip file state */ 721cb0ef41Sopenharmony_cilocal void gz_reset(gz_statep state) { 731cb0ef41Sopenharmony_ci state->x.have = 0; /* no output data available */ 741cb0ef41Sopenharmony_ci if (state->mode == GZ_READ) { /* for reading ... */ 751cb0ef41Sopenharmony_ci state->eof = 0; /* not at end of file */ 761cb0ef41Sopenharmony_ci state->past = 0; /* have not read past end yet */ 771cb0ef41Sopenharmony_ci state->how = LOOK; /* look for gzip header */ 781cb0ef41Sopenharmony_ci } 791cb0ef41Sopenharmony_ci else /* for writing ... */ 801cb0ef41Sopenharmony_ci state->reset = 0; /* no deflateReset pending */ 811cb0ef41Sopenharmony_ci state->seek = 0; /* no seek request pending */ 821cb0ef41Sopenharmony_ci gz_error(state, Z_OK, NULL); /* clear error */ 831cb0ef41Sopenharmony_ci state->x.pos = 0; /* no uncompressed data yet */ 841cb0ef41Sopenharmony_ci state->strm.avail_in = 0; /* no input data yet */ 851cb0ef41Sopenharmony_ci} 861cb0ef41Sopenharmony_ci 871cb0ef41Sopenharmony_ci/* Open a gzip file either by name or file descriptor. */ 881cb0ef41Sopenharmony_cilocal gzFile gz_open(const void *path, int fd, const char *mode) { 891cb0ef41Sopenharmony_ci gz_statep state; 901cb0ef41Sopenharmony_ci z_size_t len; 911cb0ef41Sopenharmony_ci int oflag; 921cb0ef41Sopenharmony_ci#ifdef O_CLOEXEC 931cb0ef41Sopenharmony_ci int cloexec = 0; 941cb0ef41Sopenharmony_ci#endif 951cb0ef41Sopenharmony_ci#ifdef O_EXCL 961cb0ef41Sopenharmony_ci int exclusive = 0; 971cb0ef41Sopenharmony_ci#endif 981cb0ef41Sopenharmony_ci 991cb0ef41Sopenharmony_ci /* check input */ 1001cb0ef41Sopenharmony_ci if (path == NULL) 1011cb0ef41Sopenharmony_ci return NULL; 1021cb0ef41Sopenharmony_ci 1031cb0ef41Sopenharmony_ci /* allocate gzFile structure to return */ 1041cb0ef41Sopenharmony_ci state = (gz_statep)malloc(sizeof(gz_state)); 1051cb0ef41Sopenharmony_ci if (state == NULL) 1061cb0ef41Sopenharmony_ci return NULL; 1071cb0ef41Sopenharmony_ci state->size = 0; /* no buffers allocated yet */ 1081cb0ef41Sopenharmony_ci state->want = GZBUFSIZE; /* requested buffer size */ 1091cb0ef41Sopenharmony_ci state->msg = NULL; /* no error message yet */ 1101cb0ef41Sopenharmony_ci 1111cb0ef41Sopenharmony_ci /* interpret mode */ 1121cb0ef41Sopenharmony_ci state->mode = GZ_NONE; 1131cb0ef41Sopenharmony_ci state->level = Z_DEFAULT_COMPRESSION; 1141cb0ef41Sopenharmony_ci state->strategy = Z_DEFAULT_STRATEGY; 1151cb0ef41Sopenharmony_ci state->direct = 0; 1161cb0ef41Sopenharmony_ci while (*mode) { 1171cb0ef41Sopenharmony_ci if (*mode >= '0' && *mode <= '9') 1181cb0ef41Sopenharmony_ci state->level = *mode - '0'; 1191cb0ef41Sopenharmony_ci else 1201cb0ef41Sopenharmony_ci switch (*mode) { 1211cb0ef41Sopenharmony_ci case 'r': 1221cb0ef41Sopenharmony_ci state->mode = GZ_READ; 1231cb0ef41Sopenharmony_ci break; 1241cb0ef41Sopenharmony_ci#ifndef NO_GZCOMPRESS 1251cb0ef41Sopenharmony_ci case 'w': 1261cb0ef41Sopenharmony_ci state->mode = GZ_WRITE; 1271cb0ef41Sopenharmony_ci break; 1281cb0ef41Sopenharmony_ci case 'a': 1291cb0ef41Sopenharmony_ci state->mode = GZ_APPEND; 1301cb0ef41Sopenharmony_ci break; 1311cb0ef41Sopenharmony_ci#endif 1321cb0ef41Sopenharmony_ci case '+': /* can't read and write at the same time */ 1331cb0ef41Sopenharmony_ci free(state); 1341cb0ef41Sopenharmony_ci return NULL; 1351cb0ef41Sopenharmony_ci case 'b': /* ignore -- will request binary anyway */ 1361cb0ef41Sopenharmony_ci break; 1371cb0ef41Sopenharmony_ci#ifdef O_CLOEXEC 1381cb0ef41Sopenharmony_ci case 'e': 1391cb0ef41Sopenharmony_ci cloexec = 1; 1401cb0ef41Sopenharmony_ci break; 1411cb0ef41Sopenharmony_ci#endif 1421cb0ef41Sopenharmony_ci#ifdef O_EXCL 1431cb0ef41Sopenharmony_ci case 'x': 1441cb0ef41Sopenharmony_ci exclusive = 1; 1451cb0ef41Sopenharmony_ci break; 1461cb0ef41Sopenharmony_ci#endif 1471cb0ef41Sopenharmony_ci case 'f': 1481cb0ef41Sopenharmony_ci state->strategy = Z_FILTERED; 1491cb0ef41Sopenharmony_ci break; 1501cb0ef41Sopenharmony_ci case 'h': 1511cb0ef41Sopenharmony_ci state->strategy = Z_HUFFMAN_ONLY; 1521cb0ef41Sopenharmony_ci break; 1531cb0ef41Sopenharmony_ci case 'R': 1541cb0ef41Sopenharmony_ci state->strategy = Z_RLE; 1551cb0ef41Sopenharmony_ci break; 1561cb0ef41Sopenharmony_ci case 'F': 1571cb0ef41Sopenharmony_ci state->strategy = Z_FIXED; 1581cb0ef41Sopenharmony_ci break; 1591cb0ef41Sopenharmony_ci case 'T': 1601cb0ef41Sopenharmony_ci state->direct = 1; 1611cb0ef41Sopenharmony_ci break; 1621cb0ef41Sopenharmony_ci default: /* could consider as an error, but just ignore */ 1631cb0ef41Sopenharmony_ci ; 1641cb0ef41Sopenharmony_ci } 1651cb0ef41Sopenharmony_ci mode++; 1661cb0ef41Sopenharmony_ci } 1671cb0ef41Sopenharmony_ci 1681cb0ef41Sopenharmony_ci /* must provide an "r", "w", or "a" */ 1691cb0ef41Sopenharmony_ci if (state->mode == GZ_NONE) { 1701cb0ef41Sopenharmony_ci free(state); 1711cb0ef41Sopenharmony_ci return NULL; 1721cb0ef41Sopenharmony_ci } 1731cb0ef41Sopenharmony_ci 1741cb0ef41Sopenharmony_ci /* can't force transparent read */ 1751cb0ef41Sopenharmony_ci if (state->mode == GZ_READ) { 1761cb0ef41Sopenharmony_ci if (state->direct) { 1771cb0ef41Sopenharmony_ci free(state); 1781cb0ef41Sopenharmony_ci return NULL; 1791cb0ef41Sopenharmony_ci } 1801cb0ef41Sopenharmony_ci state->direct = 1; /* for empty file */ 1811cb0ef41Sopenharmony_ci } 1821cb0ef41Sopenharmony_ci 1831cb0ef41Sopenharmony_ci /* save the path name for error messages */ 1841cb0ef41Sopenharmony_ci#ifdef WIDECHAR 1851cb0ef41Sopenharmony_ci if (fd == -2) { 1861cb0ef41Sopenharmony_ci len = wcstombs(NULL, path, 0); 1871cb0ef41Sopenharmony_ci if (len == (z_size_t)-1) 1881cb0ef41Sopenharmony_ci len = 0; 1891cb0ef41Sopenharmony_ci } 1901cb0ef41Sopenharmony_ci else 1911cb0ef41Sopenharmony_ci#endif 1921cb0ef41Sopenharmony_ci len = strlen((const char *)path); 1931cb0ef41Sopenharmony_ci state->path = (char *)malloc(len + 1); 1941cb0ef41Sopenharmony_ci if (state->path == NULL) { 1951cb0ef41Sopenharmony_ci free(state); 1961cb0ef41Sopenharmony_ci return NULL; 1971cb0ef41Sopenharmony_ci } 1981cb0ef41Sopenharmony_ci#ifdef WIDECHAR 1991cb0ef41Sopenharmony_ci if (fd == -2) 2001cb0ef41Sopenharmony_ci if (len) 2011cb0ef41Sopenharmony_ci wcstombs(state->path, path, len + 1); 2021cb0ef41Sopenharmony_ci else 2031cb0ef41Sopenharmony_ci *(state->path) = 0; 2041cb0ef41Sopenharmony_ci else 2051cb0ef41Sopenharmony_ci#endif 2061cb0ef41Sopenharmony_ci#if !defined(NO_snprintf) && !defined(NO_vsnprintf) 2071cb0ef41Sopenharmony_ci (void)snprintf(state->path, len + 1, "%s", (const char *)path); 2081cb0ef41Sopenharmony_ci#else 2091cb0ef41Sopenharmony_ci strcpy(state->path, path); 2101cb0ef41Sopenharmony_ci#endif 2111cb0ef41Sopenharmony_ci 2121cb0ef41Sopenharmony_ci /* compute the flags for open() */ 2131cb0ef41Sopenharmony_ci oflag = 2141cb0ef41Sopenharmony_ci#ifdef O_LARGEFILE 2151cb0ef41Sopenharmony_ci O_LARGEFILE | 2161cb0ef41Sopenharmony_ci#endif 2171cb0ef41Sopenharmony_ci#ifdef O_BINARY 2181cb0ef41Sopenharmony_ci O_BINARY | 2191cb0ef41Sopenharmony_ci#endif 2201cb0ef41Sopenharmony_ci#ifdef O_CLOEXEC 2211cb0ef41Sopenharmony_ci (cloexec ? O_CLOEXEC : 0) | 2221cb0ef41Sopenharmony_ci#endif 2231cb0ef41Sopenharmony_ci (state->mode == GZ_READ ? 2241cb0ef41Sopenharmony_ci O_RDONLY : 2251cb0ef41Sopenharmony_ci (O_WRONLY | O_CREAT | 2261cb0ef41Sopenharmony_ci#ifdef O_EXCL 2271cb0ef41Sopenharmony_ci (exclusive ? O_EXCL : 0) | 2281cb0ef41Sopenharmony_ci#endif 2291cb0ef41Sopenharmony_ci (state->mode == GZ_WRITE ? 2301cb0ef41Sopenharmony_ci O_TRUNC : 2311cb0ef41Sopenharmony_ci O_APPEND))); 2321cb0ef41Sopenharmony_ci 2331cb0ef41Sopenharmony_ci /* open the file with the appropriate flags (or just use fd) */ 2341cb0ef41Sopenharmony_ci state->fd = fd > -1 ? fd : ( 2351cb0ef41Sopenharmony_ci#ifdef WIDECHAR 2361cb0ef41Sopenharmony_ci fd == -2 ? _wopen(path, oflag, 0666) : 2371cb0ef41Sopenharmony_ci#endif 2381cb0ef41Sopenharmony_ci OPEN((const char *)path, oflag, 0666)); 2391cb0ef41Sopenharmony_ci if (state->fd == -1) { 2401cb0ef41Sopenharmony_ci free(state->path); 2411cb0ef41Sopenharmony_ci free(state); 2421cb0ef41Sopenharmony_ci return NULL; 2431cb0ef41Sopenharmony_ci } 2441cb0ef41Sopenharmony_ci if (state->mode == GZ_APPEND) { 2451cb0ef41Sopenharmony_ci LSEEK(state->fd, 0, SEEK_END); /* so gzoffset() is correct */ 2461cb0ef41Sopenharmony_ci state->mode = GZ_WRITE; /* simplify later checks */ 2471cb0ef41Sopenharmony_ci } 2481cb0ef41Sopenharmony_ci 2491cb0ef41Sopenharmony_ci /* save the current position for rewinding (only if reading) */ 2501cb0ef41Sopenharmony_ci if (state->mode == GZ_READ) { 2511cb0ef41Sopenharmony_ci state->start = LSEEK(state->fd, 0, SEEK_CUR); 2521cb0ef41Sopenharmony_ci if (state->start == -1) state->start = 0; 2531cb0ef41Sopenharmony_ci } 2541cb0ef41Sopenharmony_ci 2551cb0ef41Sopenharmony_ci /* initialize stream */ 2561cb0ef41Sopenharmony_ci gz_reset(state); 2571cb0ef41Sopenharmony_ci 2581cb0ef41Sopenharmony_ci /* return stream */ 2591cb0ef41Sopenharmony_ci return (gzFile)state; 2601cb0ef41Sopenharmony_ci} 2611cb0ef41Sopenharmony_ci 2621cb0ef41Sopenharmony_ci/* -- see zlib.h -- */ 2631cb0ef41Sopenharmony_cigzFile ZEXPORT gzopen(const char *path, const char *mode) { 2641cb0ef41Sopenharmony_ci return gz_open(path, -1, mode); 2651cb0ef41Sopenharmony_ci} 2661cb0ef41Sopenharmony_ci 2671cb0ef41Sopenharmony_ci/* -- see zlib.h -- */ 2681cb0ef41Sopenharmony_cigzFile ZEXPORT gzopen64(const char *path, const char *mode) { 2691cb0ef41Sopenharmony_ci return gz_open(path, -1, mode); 2701cb0ef41Sopenharmony_ci} 2711cb0ef41Sopenharmony_ci 2721cb0ef41Sopenharmony_ci/* -- see zlib.h -- */ 2731cb0ef41Sopenharmony_cigzFile ZEXPORT gzdopen(int fd, const char *mode) { 2741cb0ef41Sopenharmony_ci char *path; /* identifier for error messages */ 2751cb0ef41Sopenharmony_ci gzFile gz; 2761cb0ef41Sopenharmony_ci 2771cb0ef41Sopenharmony_ci if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL) 2781cb0ef41Sopenharmony_ci return NULL; 2791cb0ef41Sopenharmony_ci#if !defined(NO_snprintf) && !defined(NO_vsnprintf) 2801cb0ef41Sopenharmony_ci (void)snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd); 2811cb0ef41Sopenharmony_ci#else 2821cb0ef41Sopenharmony_ci sprintf(path, "<fd:%d>", fd); /* for debugging */ 2831cb0ef41Sopenharmony_ci#endif 2841cb0ef41Sopenharmony_ci gz = gz_open(path, fd, mode); 2851cb0ef41Sopenharmony_ci free(path); 2861cb0ef41Sopenharmony_ci return gz; 2871cb0ef41Sopenharmony_ci} 2881cb0ef41Sopenharmony_ci 2891cb0ef41Sopenharmony_ci/* -- see zlib.h -- */ 2901cb0ef41Sopenharmony_ci#ifdef WIDECHAR 2911cb0ef41Sopenharmony_cigzFile ZEXPORT gzopen_w(const wchar_t *path, const char *mode) { 2921cb0ef41Sopenharmony_ci return gz_open(path, -2, mode); 2931cb0ef41Sopenharmony_ci} 2941cb0ef41Sopenharmony_ci#endif 2951cb0ef41Sopenharmony_ci 2961cb0ef41Sopenharmony_ci/* -- see zlib.h -- */ 2971cb0ef41Sopenharmony_ciint ZEXPORT gzbuffer(gzFile file, unsigned size) { 2981cb0ef41Sopenharmony_ci gz_statep state; 2991cb0ef41Sopenharmony_ci 3001cb0ef41Sopenharmony_ci /* get internal structure and check integrity */ 3011cb0ef41Sopenharmony_ci if (file == NULL) 3021cb0ef41Sopenharmony_ci return -1; 3031cb0ef41Sopenharmony_ci state = (gz_statep)file; 3041cb0ef41Sopenharmony_ci if (state->mode != GZ_READ && state->mode != GZ_WRITE) 3051cb0ef41Sopenharmony_ci return -1; 3061cb0ef41Sopenharmony_ci 3071cb0ef41Sopenharmony_ci /* make sure we haven't already allocated memory */ 3081cb0ef41Sopenharmony_ci if (state->size != 0) 3091cb0ef41Sopenharmony_ci return -1; 3101cb0ef41Sopenharmony_ci 3111cb0ef41Sopenharmony_ci /* check and set requested size */ 3121cb0ef41Sopenharmony_ci if ((size << 1) < size) 3131cb0ef41Sopenharmony_ci return -1; /* need to be able to double it */ 3141cb0ef41Sopenharmony_ci if (size < 8) 3151cb0ef41Sopenharmony_ci size = 8; /* needed to behave well with flushing */ 3161cb0ef41Sopenharmony_ci state->want = size; 3171cb0ef41Sopenharmony_ci return 0; 3181cb0ef41Sopenharmony_ci} 3191cb0ef41Sopenharmony_ci 3201cb0ef41Sopenharmony_ci/* -- see zlib.h -- */ 3211cb0ef41Sopenharmony_ciint ZEXPORT gzrewind(gzFile file) { 3221cb0ef41Sopenharmony_ci gz_statep state; 3231cb0ef41Sopenharmony_ci 3241cb0ef41Sopenharmony_ci /* get internal structure */ 3251cb0ef41Sopenharmony_ci if (file == NULL) 3261cb0ef41Sopenharmony_ci return -1; 3271cb0ef41Sopenharmony_ci state = (gz_statep)file; 3281cb0ef41Sopenharmony_ci 3291cb0ef41Sopenharmony_ci /* check that we're reading and that there's no error */ 3301cb0ef41Sopenharmony_ci if (state->mode != GZ_READ || 3311cb0ef41Sopenharmony_ci (state->err != Z_OK && state->err != Z_BUF_ERROR)) 3321cb0ef41Sopenharmony_ci return -1; 3331cb0ef41Sopenharmony_ci 3341cb0ef41Sopenharmony_ci /* back up and start over */ 3351cb0ef41Sopenharmony_ci if (LSEEK(state->fd, state->start, SEEK_SET) == -1) 3361cb0ef41Sopenharmony_ci return -1; 3371cb0ef41Sopenharmony_ci gz_reset(state); 3381cb0ef41Sopenharmony_ci return 0; 3391cb0ef41Sopenharmony_ci} 3401cb0ef41Sopenharmony_ci 3411cb0ef41Sopenharmony_ci/* -- see zlib.h -- */ 3421cb0ef41Sopenharmony_ciz_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence) { 3431cb0ef41Sopenharmony_ci unsigned n; 3441cb0ef41Sopenharmony_ci z_off64_t ret; 3451cb0ef41Sopenharmony_ci gz_statep state; 3461cb0ef41Sopenharmony_ci 3471cb0ef41Sopenharmony_ci /* get internal structure and check integrity */ 3481cb0ef41Sopenharmony_ci if (file == NULL) 3491cb0ef41Sopenharmony_ci return -1; 3501cb0ef41Sopenharmony_ci state = (gz_statep)file; 3511cb0ef41Sopenharmony_ci if (state->mode != GZ_READ && state->mode != GZ_WRITE) 3521cb0ef41Sopenharmony_ci return -1; 3531cb0ef41Sopenharmony_ci 3541cb0ef41Sopenharmony_ci /* check that there's no error */ 3551cb0ef41Sopenharmony_ci if (state->err != Z_OK && state->err != Z_BUF_ERROR) 3561cb0ef41Sopenharmony_ci return -1; 3571cb0ef41Sopenharmony_ci 3581cb0ef41Sopenharmony_ci /* can only seek from start or relative to current position */ 3591cb0ef41Sopenharmony_ci if (whence != SEEK_SET && whence != SEEK_CUR) 3601cb0ef41Sopenharmony_ci return -1; 3611cb0ef41Sopenharmony_ci 3621cb0ef41Sopenharmony_ci /* normalize offset to a SEEK_CUR specification */ 3631cb0ef41Sopenharmony_ci if (whence == SEEK_SET) 3641cb0ef41Sopenharmony_ci offset -= state->x.pos; 3651cb0ef41Sopenharmony_ci else if (state->seek) 3661cb0ef41Sopenharmony_ci offset += state->skip; 3671cb0ef41Sopenharmony_ci state->seek = 0; 3681cb0ef41Sopenharmony_ci 3691cb0ef41Sopenharmony_ci /* if within raw area while reading, just go there */ 3701cb0ef41Sopenharmony_ci if (state->mode == GZ_READ && state->how == COPY && 3711cb0ef41Sopenharmony_ci state->x.pos + offset >= 0) { 3721cb0ef41Sopenharmony_ci ret = LSEEK(state->fd, offset - (z_off64_t)state->x.have, SEEK_CUR); 3731cb0ef41Sopenharmony_ci if (ret == -1) 3741cb0ef41Sopenharmony_ci return -1; 3751cb0ef41Sopenharmony_ci state->x.have = 0; 3761cb0ef41Sopenharmony_ci state->eof = 0; 3771cb0ef41Sopenharmony_ci state->past = 0; 3781cb0ef41Sopenharmony_ci state->seek = 0; 3791cb0ef41Sopenharmony_ci gz_error(state, Z_OK, NULL); 3801cb0ef41Sopenharmony_ci state->strm.avail_in = 0; 3811cb0ef41Sopenharmony_ci state->x.pos += offset; 3821cb0ef41Sopenharmony_ci return state->x.pos; 3831cb0ef41Sopenharmony_ci } 3841cb0ef41Sopenharmony_ci 3851cb0ef41Sopenharmony_ci /* calculate skip amount, rewinding if needed for back seek when reading */ 3861cb0ef41Sopenharmony_ci if (offset < 0) { 3871cb0ef41Sopenharmony_ci if (state->mode != GZ_READ) /* writing -- can't go backwards */ 3881cb0ef41Sopenharmony_ci return -1; 3891cb0ef41Sopenharmony_ci offset += state->x.pos; 3901cb0ef41Sopenharmony_ci if (offset < 0) /* before start of file! */ 3911cb0ef41Sopenharmony_ci return -1; 3921cb0ef41Sopenharmony_ci if (gzrewind(file) == -1) /* rewind, then skip to offset */ 3931cb0ef41Sopenharmony_ci return -1; 3941cb0ef41Sopenharmony_ci } 3951cb0ef41Sopenharmony_ci 3961cb0ef41Sopenharmony_ci /* if reading, skip what's in output buffer (one less gzgetc() check) */ 3971cb0ef41Sopenharmony_ci if (state->mode == GZ_READ) { 3981cb0ef41Sopenharmony_ci n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ? 3991cb0ef41Sopenharmony_ci (unsigned)offset : state->x.have; 4001cb0ef41Sopenharmony_ci state->x.have -= n; 4011cb0ef41Sopenharmony_ci state->x.next += n; 4021cb0ef41Sopenharmony_ci state->x.pos += n; 4031cb0ef41Sopenharmony_ci offset -= n; 4041cb0ef41Sopenharmony_ci } 4051cb0ef41Sopenharmony_ci 4061cb0ef41Sopenharmony_ci /* request skip (if not zero) */ 4071cb0ef41Sopenharmony_ci if (offset) { 4081cb0ef41Sopenharmony_ci state->seek = 1; 4091cb0ef41Sopenharmony_ci state->skip = offset; 4101cb0ef41Sopenharmony_ci } 4111cb0ef41Sopenharmony_ci return state->x.pos + offset; 4121cb0ef41Sopenharmony_ci} 4131cb0ef41Sopenharmony_ci 4141cb0ef41Sopenharmony_ci/* -- see zlib.h -- */ 4151cb0ef41Sopenharmony_ciz_off_t ZEXPORT gzseek(gzFile file, z_off_t offset, int whence) { 4161cb0ef41Sopenharmony_ci z_off64_t ret; 4171cb0ef41Sopenharmony_ci 4181cb0ef41Sopenharmony_ci ret = gzseek64(file, (z_off64_t)offset, whence); 4191cb0ef41Sopenharmony_ci return ret == (z_off_t)ret ? (z_off_t)ret : -1; 4201cb0ef41Sopenharmony_ci} 4211cb0ef41Sopenharmony_ci 4221cb0ef41Sopenharmony_ci/* -- see zlib.h -- */ 4231cb0ef41Sopenharmony_ciz_off64_t ZEXPORT gztell64(gzFile file) { 4241cb0ef41Sopenharmony_ci gz_statep state; 4251cb0ef41Sopenharmony_ci 4261cb0ef41Sopenharmony_ci /* get internal structure and check integrity */ 4271cb0ef41Sopenharmony_ci if (file == NULL) 4281cb0ef41Sopenharmony_ci return -1; 4291cb0ef41Sopenharmony_ci state = (gz_statep)file; 4301cb0ef41Sopenharmony_ci if (state->mode != GZ_READ && state->mode != GZ_WRITE) 4311cb0ef41Sopenharmony_ci return -1; 4321cb0ef41Sopenharmony_ci 4331cb0ef41Sopenharmony_ci /* return position */ 4341cb0ef41Sopenharmony_ci return state->x.pos + (state->seek ? state->skip : 0); 4351cb0ef41Sopenharmony_ci} 4361cb0ef41Sopenharmony_ci 4371cb0ef41Sopenharmony_ci/* -- see zlib.h -- */ 4381cb0ef41Sopenharmony_ciz_off_t ZEXPORT gztell(gzFile file) { 4391cb0ef41Sopenharmony_ci z_off64_t ret; 4401cb0ef41Sopenharmony_ci 4411cb0ef41Sopenharmony_ci ret = gztell64(file); 4421cb0ef41Sopenharmony_ci return ret == (z_off_t)ret ? (z_off_t)ret : -1; 4431cb0ef41Sopenharmony_ci} 4441cb0ef41Sopenharmony_ci 4451cb0ef41Sopenharmony_ci/* -- see zlib.h -- */ 4461cb0ef41Sopenharmony_ciz_off64_t ZEXPORT gzoffset64(gzFile file) { 4471cb0ef41Sopenharmony_ci z_off64_t offset; 4481cb0ef41Sopenharmony_ci gz_statep state; 4491cb0ef41Sopenharmony_ci 4501cb0ef41Sopenharmony_ci /* get internal structure and check integrity */ 4511cb0ef41Sopenharmony_ci if (file == NULL) 4521cb0ef41Sopenharmony_ci return -1; 4531cb0ef41Sopenharmony_ci state = (gz_statep)file; 4541cb0ef41Sopenharmony_ci if (state->mode != GZ_READ && state->mode != GZ_WRITE) 4551cb0ef41Sopenharmony_ci return -1; 4561cb0ef41Sopenharmony_ci 4571cb0ef41Sopenharmony_ci /* compute and return effective offset in file */ 4581cb0ef41Sopenharmony_ci offset = LSEEK(state->fd, 0, SEEK_CUR); 4591cb0ef41Sopenharmony_ci if (offset == -1) 4601cb0ef41Sopenharmony_ci return -1; 4611cb0ef41Sopenharmony_ci if (state->mode == GZ_READ) /* reading */ 4621cb0ef41Sopenharmony_ci offset -= state->strm.avail_in; /* don't count buffered input */ 4631cb0ef41Sopenharmony_ci return offset; 4641cb0ef41Sopenharmony_ci} 4651cb0ef41Sopenharmony_ci 4661cb0ef41Sopenharmony_ci/* -- see zlib.h -- */ 4671cb0ef41Sopenharmony_ciz_off_t ZEXPORT gzoffset(gzFile file) { 4681cb0ef41Sopenharmony_ci z_off64_t ret; 4691cb0ef41Sopenharmony_ci 4701cb0ef41Sopenharmony_ci ret = gzoffset64(file); 4711cb0ef41Sopenharmony_ci return ret == (z_off_t)ret ? (z_off_t)ret : -1; 4721cb0ef41Sopenharmony_ci} 4731cb0ef41Sopenharmony_ci 4741cb0ef41Sopenharmony_ci/* -- see zlib.h -- */ 4751cb0ef41Sopenharmony_ciint ZEXPORT gzeof(gzFile file) { 4761cb0ef41Sopenharmony_ci gz_statep state; 4771cb0ef41Sopenharmony_ci 4781cb0ef41Sopenharmony_ci /* get internal structure and check integrity */ 4791cb0ef41Sopenharmony_ci if (file == NULL) 4801cb0ef41Sopenharmony_ci return 0; 4811cb0ef41Sopenharmony_ci state = (gz_statep)file; 4821cb0ef41Sopenharmony_ci if (state->mode != GZ_READ && state->mode != GZ_WRITE) 4831cb0ef41Sopenharmony_ci return 0; 4841cb0ef41Sopenharmony_ci 4851cb0ef41Sopenharmony_ci /* return end-of-file state */ 4861cb0ef41Sopenharmony_ci return state->mode == GZ_READ ? state->past : 0; 4871cb0ef41Sopenharmony_ci} 4881cb0ef41Sopenharmony_ci 4891cb0ef41Sopenharmony_ci/* -- see zlib.h -- */ 4901cb0ef41Sopenharmony_ciconst char * ZEXPORT gzerror(gzFile file, int *errnum) { 4911cb0ef41Sopenharmony_ci gz_statep state; 4921cb0ef41Sopenharmony_ci 4931cb0ef41Sopenharmony_ci /* get internal structure and check integrity */ 4941cb0ef41Sopenharmony_ci if (file == NULL) 4951cb0ef41Sopenharmony_ci return NULL; 4961cb0ef41Sopenharmony_ci state = (gz_statep)file; 4971cb0ef41Sopenharmony_ci if (state->mode != GZ_READ && state->mode != GZ_WRITE) 4981cb0ef41Sopenharmony_ci return NULL; 4991cb0ef41Sopenharmony_ci 5001cb0ef41Sopenharmony_ci /* return error information */ 5011cb0ef41Sopenharmony_ci if (errnum != NULL) 5021cb0ef41Sopenharmony_ci *errnum = state->err; 5031cb0ef41Sopenharmony_ci return state->err == Z_MEM_ERROR ? "out of memory" : 5041cb0ef41Sopenharmony_ci (state->msg == NULL ? "" : state->msg); 5051cb0ef41Sopenharmony_ci} 5061cb0ef41Sopenharmony_ci 5071cb0ef41Sopenharmony_ci/* -- see zlib.h -- */ 5081cb0ef41Sopenharmony_civoid ZEXPORT gzclearerr(gzFile file) { 5091cb0ef41Sopenharmony_ci gz_statep state; 5101cb0ef41Sopenharmony_ci 5111cb0ef41Sopenharmony_ci /* get internal structure and check integrity */ 5121cb0ef41Sopenharmony_ci if (file == NULL) 5131cb0ef41Sopenharmony_ci return; 5141cb0ef41Sopenharmony_ci state = (gz_statep)file; 5151cb0ef41Sopenharmony_ci if (state->mode != GZ_READ && state->mode != GZ_WRITE) 5161cb0ef41Sopenharmony_ci return; 5171cb0ef41Sopenharmony_ci 5181cb0ef41Sopenharmony_ci /* clear error and end-of-file */ 5191cb0ef41Sopenharmony_ci if (state->mode == GZ_READ) { 5201cb0ef41Sopenharmony_ci state->eof = 0; 5211cb0ef41Sopenharmony_ci state->past = 0; 5221cb0ef41Sopenharmony_ci } 5231cb0ef41Sopenharmony_ci gz_error(state, Z_OK, NULL); 5241cb0ef41Sopenharmony_ci} 5251cb0ef41Sopenharmony_ci 5261cb0ef41Sopenharmony_ci/* Create an error message in allocated memory and set state->err and 5271cb0ef41Sopenharmony_ci state->msg accordingly. Free any previous error message already there. Do 5281cb0ef41Sopenharmony_ci not try to free or allocate space if the error is Z_MEM_ERROR (out of 5291cb0ef41Sopenharmony_ci memory). Simply save the error message as a static string. If there is an 5301cb0ef41Sopenharmony_ci allocation failure constructing the error message, then convert the error to 5311cb0ef41Sopenharmony_ci out of memory. */ 5321cb0ef41Sopenharmony_civoid ZLIB_INTERNAL gz_error(gz_statep state, int err, const char *msg) { 5331cb0ef41Sopenharmony_ci /* free previously allocated message and clear */ 5341cb0ef41Sopenharmony_ci if (state->msg != NULL) { 5351cb0ef41Sopenharmony_ci if (state->err != Z_MEM_ERROR) 5361cb0ef41Sopenharmony_ci free(state->msg); 5371cb0ef41Sopenharmony_ci state->msg = NULL; 5381cb0ef41Sopenharmony_ci } 5391cb0ef41Sopenharmony_ci 5401cb0ef41Sopenharmony_ci /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */ 5411cb0ef41Sopenharmony_ci if (err != Z_OK && err != Z_BUF_ERROR) 5421cb0ef41Sopenharmony_ci state->x.have = 0; 5431cb0ef41Sopenharmony_ci 5441cb0ef41Sopenharmony_ci /* set error code, and if no message, then done */ 5451cb0ef41Sopenharmony_ci state->err = err; 5461cb0ef41Sopenharmony_ci if (msg == NULL) 5471cb0ef41Sopenharmony_ci return; 5481cb0ef41Sopenharmony_ci 5491cb0ef41Sopenharmony_ci /* for an out of memory error, return literal string when requested */ 5501cb0ef41Sopenharmony_ci if (err == Z_MEM_ERROR) 5511cb0ef41Sopenharmony_ci return; 5521cb0ef41Sopenharmony_ci 5531cb0ef41Sopenharmony_ci /* construct error message with path */ 5541cb0ef41Sopenharmony_ci if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) == 5551cb0ef41Sopenharmony_ci NULL) { 5561cb0ef41Sopenharmony_ci state->err = Z_MEM_ERROR; 5571cb0ef41Sopenharmony_ci return; 5581cb0ef41Sopenharmony_ci } 5591cb0ef41Sopenharmony_ci#if !defined(NO_snprintf) && !defined(NO_vsnprintf) 5601cb0ef41Sopenharmony_ci (void)snprintf(state->msg, strlen(state->path) + strlen(msg) + 3, 5611cb0ef41Sopenharmony_ci "%s%s%s", state->path, ": ", msg); 5621cb0ef41Sopenharmony_ci#else 5631cb0ef41Sopenharmony_ci strcpy(state->msg, state->path); 5641cb0ef41Sopenharmony_ci strcat(state->msg, ": "); 5651cb0ef41Sopenharmony_ci strcat(state->msg, msg); 5661cb0ef41Sopenharmony_ci#endif 5671cb0ef41Sopenharmony_ci} 5681cb0ef41Sopenharmony_ci 5691cb0ef41Sopenharmony_ci#ifndef INT_MAX 5701cb0ef41Sopenharmony_ci/* portably return maximum value for an int (when limits.h presumed not 5711cb0ef41Sopenharmony_ci available) -- we need to do this to cover cases where 2's complement not 5721cb0ef41Sopenharmony_ci used, since C standard permits 1's complement and sign-bit representations, 5731cb0ef41Sopenharmony_ci otherwise we could just use ((unsigned)-1) >> 1 */ 5741cb0ef41Sopenharmony_ciunsigned ZLIB_INTERNAL gz_intmax(void) { 5751cb0ef41Sopenharmony_ci unsigned p, q; 5761cb0ef41Sopenharmony_ci 5771cb0ef41Sopenharmony_ci p = 1; 5781cb0ef41Sopenharmony_ci do { 5791cb0ef41Sopenharmony_ci q = p; 5801cb0ef41Sopenharmony_ci p <<= 1; 5811cb0ef41Sopenharmony_ci p++; 5821cb0ef41Sopenharmony_ci } while (p > q); 5831cb0ef41Sopenharmony_ci return q >> 1; 5841cb0ef41Sopenharmony_ci} 5851cb0ef41Sopenharmony_ci#endif 586