1381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* gzlib.c -- zlib functions common to reading and writing gzip files 2381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes * Copyright (C) 2004, 2010 Mark Adler 3381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes * For conditions of distribution and use, see copyright notice in zlib.h 4381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes */ 5381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 6381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#include "gzguts.h" 7381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 8381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 9381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes# define LSEEK lseek64 10381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#else 11381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes# define LSEEK lseek 12381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#endif 13381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 14381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* Local functions */ 15381716e9396b55b1adb8235b020c37344f60ab07Elliott Hugheslocal void gz_reset OF((gz_statep)); 16381716e9396b55b1adb8235b020c37344f60ab07Elliott Hugheslocal gzFile gz_open OF((const char *, int, const char *)); 17381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 18381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#if defined UNDER_CE 19381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 20381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* Map the Windows error number in ERROR to a locale-dependent error message 21381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes string and return a pointer to it. Typically, the values for ERROR come 22381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes from GetLastError. 23381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 24381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes The string pointed to shall not be modified by the application, but may be 25381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes overwritten by a subsequent call to gz_strwinerror 26381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 27381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes The gz_strwinerror function does not change the current setting of 28381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes GetLastError. */ 29381716e9396b55b1adb8235b020c37344f60ab07Elliott Hugheschar ZLIB_INTERNAL *gz_strwinerror (error) 30381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes DWORD error; 31381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{ 32381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes static char buf[1024]; 33381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 34381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes wchar_t *msgbuf; 35381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes DWORD lasterr = GetLastError(); 36381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM 37381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes | FORMAT_MESSAGE_ALLOCATE_BUFFER, 38381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes NULL, 39381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes error, 40381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 0, /* Default language */ 41381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes (LPVOID)&msgbuf, 42381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 0, 43381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes NULL); 44381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (chars != 0) { 45381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* If there is an \r\n appended, zap it. */ 46381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (chars >= 2 47381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') { 48381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes chars -= 2; 49381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes msgbuf[chars] = 0; 50381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 51381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 52381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (chars > sizeof (buf) - 1) { 53381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes chars = sizeof (buf) - 1; 54381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes msgbuf[chars] = 0; 55381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 56381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 57381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes wcstombs(buf, msgbuf, chars + 1); 58381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes LocalFree(msgbuf); 59381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 60381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes else { 61381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes sprintf(buf, "unknown win32 error (%ld)", error); 62381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 63381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 64381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes SetLastError(lasterr); 65381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return buf; 66381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes} 67381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 68381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#endif /* UNDER_CE */ 69381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 70381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* Reset gzip file state */ 71381716e9396b55b1adb8235b020c37344f60ab07Elliott Hugheslocal void gz_reset(state) 72381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_statep state; 73381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{ 74381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->mode == GZ_READ) { /* for reading ... */ 75381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->have = 0; /* no output data available */ 76381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->eof = 0; /* not at end of file */ 77381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->how = LOOK; /* look for gzip header */ 78381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->direct = 1; /* default for empty file */ 79381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 80381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->seek = 0; /* no seek request pending */ 81381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_error(state, Z_OK, NULL); /* clear error */ 82381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->pos = 0; /* no uncompressed data yet */ 83381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->strm.avail_in = 0; /* no input data yet */ 84381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes} 85381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 86381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* Open a gzip file either by name or file descriptor. */ 87381716e9396b55b1adb8235b020c37344f60ab07Elliott Hugheslocal gzFile gz_open(path, fd, mode) 88381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes const char *path; 89381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes int fd; 90381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes const char *mode; 91381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{ 92381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_statep state; 93381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 94381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* allocate gzFile structure to return */ 95381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state = malloc(sizeof(gz_state)); 96381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state == NULL) 97381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return NULL; 98381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->size = 0; /* no buffers allocated yet */ 99381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->want = GZBUFSIZE; /* requested buffer size */ 100381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->msg = NULL; /* no error message yet */ 101381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 102381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* interpret mode */ 103381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->mode = GZ_NONE; 104381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->level = Z_DEFAULT_COMPRESSION; 105381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->strategy = Z_DEFAULT_STRATEGY; 106381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes while (*mode) { 107381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (*mode >= '0' && *mode <= '9') 108381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->level = *mode - '0'; 109381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes else 110381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes switch (*mode) { 111381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes case 'r': 112381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->mode = GZ_READ; 113381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes break; 114381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#ifndef NO_GZCOMPRESS 115381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes case 'w': 116381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->mode = GZ_WRITE; 117381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes break; 118381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes case 'a': 119381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->mode = GZ_APPEND; 120381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes break; 121381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#endif 122381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes case '+': /* can't read and write at the same time */ 123381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes free(state); 124381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return NULL; 125381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes case 'b': /* ignore -- will request binary anyway */ 126381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes break; 127381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes case 'f': 128381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->strategy = Z_FILTERED; 129381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes break; 130381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes case 'h': 131381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->strategy = Z_HUFFMAN_ONLY; 132381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes break; 133381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes case 'R': 134381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->strategy = Z_RLE; 135381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes break; 136381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes case 'F': 137381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->strategy = Z_FIXED; 138381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes default: /* could consider as an error, but just ignore */ 139381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes ; 140381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 141381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes mode++; 142381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 143381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 144381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* must provide an "r", "w", or "a" */ 145381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->mode == GZ_NONE) { 146381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes free(state); 147381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return NULL; 148381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 149381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 150381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* save the path name for error messages */ 151381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->path = malloc(strlen(path) + 1); 152381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->path == NULL) { 153381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes free(state); 154381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return NULL; 155381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 156381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes strcpy(state->path, path); 157381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 158381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* open the file with the appropriate mode (or just use fd) */ 159381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->fd = fd != -1 ? fd : 160381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes open(path, 161381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#ifdef O_LARGEFILE 162381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes O_LARGEFILE | 163381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#endif 164381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#ifdef O_BINARY 165381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes O_BINARY | 166381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#endif 167381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes (state->mode == GZ_READ ? 168381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes O_RDONLY : 169381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes (O_WRONLY | O_CREAT | ( 170381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->mode == GZ_WRITE ? 171381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes O_TRUNC : 172381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes O_APPEND))), 173381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 0666); 174381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->fd == -1) { 175381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes free(state->path); 176381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes free(state); 177381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return NULL; 178381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 179381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->mode == GZ_APPEND) 180381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->mode = GZ_WRITE; /* simplify later checks */ 181381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 182381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* save the current position for rewinding (only if reading) */ 183381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->mode == GZ_READ) { 184381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->start = LSEEK(state->fd, 0, SEEK_CUR); 185381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->start == -1) state->start = 0; 186381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 187381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 188381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* initialize stream */ 189381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_reset(state); 190381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 191381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* return stream */ 192381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return (gzFile)state; 193381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes} 194381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 195381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */ 196381716e9396b55b1adb8235b020c37344f60ab07Elliott HughesgzFile ZEXPORT gzopen(path, mode) 197381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes const char *path; 198381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes const char *mode; 199381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{ 200381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return gz_open(path, -1, mode); 201381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes} 202381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 203381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */ 204381716e9396b55b1adb8235b020c37344f60ab07Elliott HughesgzFile ZEXPORT gzopen64(path, mode) 205381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes const char *path; 206381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes const char *mode; 207381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{ 208381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return gz_open(path, -1, mode); 209381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes} 210381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 211381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */ 212381716e9396b55b1adb8235b020c37344f60ab07Elliott HughesgzFile ZEXPORT gzdopen(fd, mode) 213381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes int fd; 214381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes const char *mode; 215381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{ 216381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes char *path; /* identifier for error messages */ 217381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gzFile gz; 218381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 219381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (fd == -1 || (path = malloc(7 + 3 * sizeof(int))) == NULL) 220381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return NULL; 221381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes sprintf(path, "<fd:%d>", fd); /* for debugging */ 222381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz = gz_open(path, fd, mode); 223381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes free(path); 224381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return gz; 225381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes} 226381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 227381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */ 228381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesint ZEXPORT gzbuffer(file, size) 229381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gzFile file; 230381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes unsigned size; 231381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{ 232381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_statep state; 233381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 234381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* get internal structure and check integrity */ 235381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (file == NULL) 236381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 237381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state = (gz_statep)file; 238381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->mode != GZ_READ && state->mode != GZ_WRITE) 239381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 240381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 241381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* make sure we haven't already allocated memory */ 242381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->size != 0) 243381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 244381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 245381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* check and set requested size */ 246381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (size == 0) 247381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 248381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->want = size; 249381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return 0; 250381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes} 251381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 252381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */ 253381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesint ZEXPORT gzrewind(file) 254381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gzFile file; 255381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{ 256381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_statep state; 257381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 258381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* get internal structure */ 259381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (file == NULL) 260381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 261381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state = (gz_statep)file; 262381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 263381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* check that we're reading and that there's no error */ 264381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->mode != GZ_READ || state->err != Z_OK) 265381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 266381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 267381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* back up and start over */ 268381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (LSEEK(state->fd, state->start, SEEK_SET) == -1) 269381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 270381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_reset(state); 271381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return 0; 272381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes} 273381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 274381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */ 275381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesz_off64_t ZEXPORT gzseek64(file, offset, whence) 276381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gzFile file; 277381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes z_off64_t offset; 278381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes int whence; 279381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{ 280381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes unsigned n; 281381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes z_off64_t ret; 282381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_statep state; 283381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 284381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* get internal structure and check integrity */ 285381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (file == NULL) 286381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 287381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state = (gz_statep)file; 288381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->mode != GZ_READ && state->mode != GZ_WRITE) 289381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 290381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 291381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* check that there's no error */ 292381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->err != Z_OK) 293381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 294381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 295381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* can only seek from start or relative to current position */ 296381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (whence != SEEK_SET && whence != SEEK_CUR) 297381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 298381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 299381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* normalize offset to a SEEK_CUR specification */ 300381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (whence == SEEK_SET) 301381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes offset -= state->pos; 302381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes else if (state->seek) 303381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes offset += state->skip; 304381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->seek = 0; 305381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 306381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* if within raw area while reading, just go there */ 307381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->mode == GZ_READ && state->how == COPY && 308381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->pos + offset >= state->raw) { 309381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes ret = LSEEK(state->fd, offset - state->have, SEEK_CUR); 310381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (ret == -1) 311381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 312381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->have = 0; 313381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->eof = 0; 314381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->seek = 0; 315381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_error(state, Z_OK, NULL); 316381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->strm.avail_in = 0; 317381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->pos += offset; 318381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return state->pos; 319381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 320381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 321381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* calculate skip amount, rewinding if needed for back seek when reading */ 322381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (offset < 0) { 323381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->mode != GZ_READ) /* writing -- can't go backwards */ 324381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 325381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes offset += state->pos; 326381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (offset < 0) /* before start of file! */ 327381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 328381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (gzrewind(file) == -1) /* rewind, then skip to offset */ 329381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 330381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 331381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 332381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* if reading, skip what's in output buffer (one less gzgetc() check) */ 333381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->mode == GZ_READ) { 334381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes n = GT_OFF(state->have) || (z_off64_t)state->have > offset ? 335381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes (unsigned)offset : state->have; 336381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->have -= n; 337381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->next += n; 338381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->pos += n; 339381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes offset -= n; 340381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 341381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 342381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* request skip (if not zero) */ 343381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (offset) { 344381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->seek = 1; 345381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->skip = offset; 346381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 347381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return state->pos + offset; 348381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes} 349381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 350381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */ 351381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesz_off_t ZEXPORT gzseek(file, offset, whence) 352381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gzFile file; 353381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes z_off_t offset; 354381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes int whence; 355381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{ 356381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes z_off64_t ret; 357381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 358381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes ret = gzseek64(file, (z_off64_t)offset, whence); 359381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return ret == (z_off_t)ret ? (z_off_t)ret : -1; 360381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes} 361381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 362381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */ 363381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesz_off64_t ZEXPORT gztell64(file) 364381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gzFile file; 365381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{ 366381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_statep state; 367381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 368381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* get internal structure and check integrity */ 369381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (file == NULL) 370381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 371381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state = (gz_statep)file; 372381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->mode != GZ_READ && state->mode != GZ_WRITE) 373381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 374381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 375381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* return position */ 376381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return state->pos + (state->seek ? state->skip : 0); 377381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes} 378381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 379381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */ 380381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesz_off_t ZEXPORT gztell(file) 381381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gzFile file; 382381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{ 383381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes z_off64_t ret; 384381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 385381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes ret = gztell64(file); 386381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return ret == (z_off_t)ret ? (z_off_t)ret : -1; 387381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes} 388381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 389381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */ 390381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesz_off64_t ZEXPORT gzoffset64(file) 391381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gzFile file; 392381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{ 393381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes z_off64_t offset; 394381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_statep state; 395381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 396381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* get internal structure and check integrity */ 397381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (file == NULL) 398381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 399381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state = (gz_statep)file; 400381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->mode != GZ_READ && state->mode != GZ_WRITE) 401381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 402381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 403381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* compute and return effective offset in file */ 404381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes offset = LSEEK(state->fd, 0, SEEK_CUR); 405381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (offset == -1) 406381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return -1; 407381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->mode == GZ_READ) /* reading */ 408381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes offset -= state->strm.avail_in; /* don't count buffered input */ 409381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return offset; 410381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes} 411381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 412381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */ 413381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesz_off_t ZEXPORT gzoffset(file) 414381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gzFile file; 415381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{ 416381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes z_off64_t ret; 417381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 418381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes ret = gzoffset64(file); 419381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return ret == (z_off_t)ret ? (z_off_t)ret : -1; 420381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes} 421381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 422381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */ 423381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesint ZEXPORT gzeof(file) 424381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gzFile file; 425381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{ 426381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_statep state; 427381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 428381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* get internal structure and check integrity */ 429381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (file == NULL) 430381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return 0; 431381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state = (gz_statep)file; 432381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->mode != GZ_READ && state->mode != GZ_WRITE) 433381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return 0; 434381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 435381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* return end-of-file state */ 436381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return state->mode == GZ_READ ? 437381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes (state->eof && state->strm.avail_in == 0 && state->have == 0) : 0; 438381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes} 439381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 440381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */ 441381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesconst char * ZEXPORT gzerror(file, errnum) 442381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gzFile file; 443381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes int *errnum; 444381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{ 445381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_statep state; 446381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 447381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* get internal structure and check integrity */ 448381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (file == NULL) 449381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return NULL; 450381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state = (gz_statep)file; 451381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->mode != GZ_READ && state->mode != GZ_WRITE) 452381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return NULL; 453381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 454381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* return error information */ 455381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (errnum != NULL) 456381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes *errnum = state->err; 457381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return state->msg == NULL ? "" : state->msg; 458381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes} 459381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 460381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */ 461381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesvoid ZEXPORT gzclearerr(file) 462381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gzFile file; 463381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{ 464381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_statep state; 465381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 466381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* get internal structure and check integrity */ 467381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (file == NULL) 468381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return; 469381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state = (gz_statep)file; 470381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->mode != GZ_READ && state->mode != GZ_WRITE) 471381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return; 472381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 473381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* clear error and end-of-file */ 474381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->mode == GZ_READ) 475381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->eof = 0; 476381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_error(state, Z_OK, NULL); 477381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes} 478381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 479381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* Create an error message in allocated memory and set state->err and 480381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->msg accordingly. Free any previous error message already there. Do 481381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes not try to free or allocate space if the error is Z_MEM_ERROR (out of 482381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes memory). Simply save the error message as a static string. If there is an 483381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes allocation failure constructing the error message, then convert the error to 484381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes out of memory. */ 485381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesvoid ZLIB_INTERNAL gz_error(state, err, msg) 486381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes gz_statep state; 487381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes int err; 488381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes const char *msg; 489381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{ 490381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* free previously allocated message and clear */ 491381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->msg != NULL) { 492381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->err != Z_MEM_ERROR) 493381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes free(state->msg); 494381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->msg = NULL; 495381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 496381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 497381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* set error code, and if no message, then done */ 498381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->err = err; 499381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (msg == NULL) 500381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return; 501381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 502381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* for an out of memory error, save as static string */ 503381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (err == Z_MEM_ERROR) { 504381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->msg = (char *)msg; 505381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return; 506381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 507381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 508381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* construct error message with path */ 509381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if ((state->msg = malloc(strlen(state->path) + strlen(msg) + 3)) == NULL) { 510381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->err = Z_MEM_ERROR; 511381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->msg = (char *)"out of memory"; 512381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return; 513381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 514381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes strcpy(state->msg, state->path); 515381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes strcat(state->msg, ": "); 516381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes strcat(state->msg, msg); 517381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return; 518381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes} 519381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 520381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#ifndef INT_MAX 521381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* portably return maximum value for an int (when limits.h presumed not 522381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes available) -- we need to do this to cover cases where 2's complement not 523381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes used, since C standard permits 1's complement and sign-bit representations, 524381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes otherwise we could just use ((unsigned)-1) >> 1 */ 525381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesunsigned ZLIB_INTERNAL gz_intmax() 526381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{ 527381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes unsigned p, q; 528381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 529381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes p = 1; 530381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes do { 531381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes q = p; 532381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes p <<= 1; 533381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes p++; 534381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } while (p > q); 535381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes return q >> 1; 536381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes} 537381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#endif 538