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