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