1 /* gzlib.c -- zlib functions common to reading and writing gzip files 2 * Copyright (C) 2004-2017 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__) && !defined(__MINGW32__) 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 */ 19 local void gz_reset OF((gz_statep)); 20 local 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. */ 33 char 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 */ 75 local 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. */ 91 local gzFile gz_open(path, fd, mode) 92 const void *path; 93 int fd; 94 const char *mode; 95 { 96 gz_statep state; 97 z_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 = (gz_statep)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 break; 166 case 'T': 167 state->direct = 1; 168 break; 169 default: /* could consider as an error, but just ignore */ 170 ; 171 } 172 mode++; 173 } 174 175 /* must provide an "r", "w", or "a" */ 176 if (state->mode == GZ_NONE) { 177 free(state); 178 return NULL; 179 } 180 181 /* can't force transparent read */ 182 if (state->mode == GZ_READ) { 183 if (state->direct) { 184 free(state); 185 return NULL; 186 } 187 state->direct = 1; /* for empty file */ 188 } 189 190 /* save the path name for error messages */ 191 #ifdef WIDECHAR 192 if (fd == -2) { 193 len = wcstombs(NULL, path, 0); 194 if (len == (z_size_t)-1) 195 len = 0; 196 } 197 else 198 #endif 199 len = strlen((const char *)path); 200 state->path = (char *)malloc(len + 1); 201 if (state->path == NULL) { 202 free(state); 203 return NULL; 204 } 205 #ifdef WIDECHAR 206 if (fd == -2) 207 if (len) 208 wcstombs(state->path, path, len + 1); 209 else 210 *(state->path) = 0; 211 else 212 #endif 213 #if !defined(NO_snprintf) && !defined(NO_vsnprintf) 214 (void)snprintf(state->path, len + 1, "%s", (const char *)path); 215 #else 216 strcpy(state->path, path); 217 #endif 218 219 /* compute the flags for open() */ 220 oflag = 221 #ifdef O_LARGEFILE 222 O_LARGEFILE | 223 #endif 224 #ifdef O_BINARY 225 O_BINARY | 226 #endif 227 #ifdef O_CLOEXEC 228 (cloexec ? O_CLOEXEC : 0) | 229 #endif 230 (state->mode == GZ_READ ? 231 O_RDONLY : 232 (O_WRONLY | O_CREAT | 233 #ifdef O_EXCL 234 (exclusive ? O_EXCL : 0) | 235 #endif 236 (state->mode == GZ_WRITE ? 237 O_TRUNC : 238 O_APPEND))); 239 240 /* open the file with the appropriate flags (or just use fd) */ 241 state->fd = fd > -1 ? fd : ( 242 #ifdef WIDECHAR 243 fd == -2 ? _wopen(path, oflag, 0666) : 244 #endif 245 open((const char *)path, oflag, 0666)); 246 if (state->fd == -1) { 247 free(state->path); 248 free(state); 249 return NULL; 250 } 251 if (state->mode == GZ_APPEND) { 252 LSEEK(state->fd, 0, SEEK_END); /* so gzoffset() is correct */ 253 state->mode = GZ_WRITE; /* simplify later checks */ 254 } 255 256 /* save the current position for rewinding (only if reading) */ 257 if (state->mode == GZ_READ) { 258 state->start = LSEEK(state->fd, 0, SEEK_CUR); 259 if (state->start == -1) state->start = 0; 260 } 261 262 /* initialize stream */ 263 gz_reset(state); 264 265 /* return stream */ 266 return (gzFile)state; 267 } 268 269 /* -- see zlib.h -- */ 270 gzFile ZEXPORT gzopen(path, mode) 271 const char *path; 272 const char *mode; 273 { 274 return gz_open(path, -1, mode); 275 } 276 277 /* -- see zlib.h -- */ 278 gzFile ZEXPORT gzopen64(path, mode) 279 const char *path; 280 const char *mode; 281 { 282 return gz_open(path, -1, mode); 283 } 284 285 /* -- see zlib.h -- */ 286 gzFile ZEXPORT gzdopen(fd, mode) 287 int fd; 288 const char *mode; 289 { 290 char *path; /* identifier for error messages */ 291 gzFile gz; 292 293 if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL) 294 return NULL; 295 #if !defined(NO_snprintf) && !defined(NO_vsnprintf) 296 (void)snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd); 297 #else 298 sprintf(path, "<fd:%d>", fd); /* for debugging */ 299 #endif 300 gz = gz_open(path, fd, mode); 301 free(path); 302 return gz; 303 } 304 305 /* -- see zlib.h -- */ 306 #ifdef WIDECHAR 307 gzFile ZEXPORT gzopen_w(path, mode) 308 const wchar_t *path; 309 const char *mode; 310 { 311 return gz_open(path, -2, mode); 312 } 313 #endif 314 315 /* -- see zlib.h -- */ 316 int ZEXPORT gzbuffer(file, size) 317 gzFile file; 318 unsigned size; 319 { 320 gz_statep state; 321 322 /* get internal structure and check integrity */ 323 if (file == NULL) 324 return -1; 325 state = (gz_statep)file; 326 if (state->mode != GZ_READ && state->mode != GZ_WRITE) 327 return -1; 328 329 /* make sure we haven't already allocated memory */ 330 if (state->size != 0) 331 return -1; 332 333 /* check and set requested size */ 334 if ((size << 1) < size) 335 return -1; /* need to be able to double it */ 336 if (size < 2) 337 size = 2; /* need two bytes to check magic header */ 338 state->want = size; 339 return 0; 340 } 341 342 /* -- see zlib.h -- */ 343 int ZEXPORT gzrewind(file) 344 gzFile file; 345 { 346 gz_statep state; 347 348 /* get internal structure */ 349 if (file == NULL) 350 return -1; 351 state = (gz_statep)file; 352 353 /* check that we're reading and that there's no error */ 354 if (state->mode != GZ_READ || 355 (state->err != Z_OK && state->err != Z_BUF_ERROR)) 356 return -1; 357 358 /* back up and start over */ 359 if (LSEEK(state->fd, state->start, SEEK_SET) == -1) 360 return -1; 361 gz_reset(state); 362 return 0; 363 } 364 365 /* -- see zlib.h -- */ 366 z_off64_t ZEXPORT gzseek64(file, offset, whence) 367 gzFile file; 368 z_off64_t offset; 369 int whence; 370 { 371 unsigned n; 372 z_off64_t ret; 373 gz_statep state; 374 375 /* get internal structure and check integrity */ 376 if (file == NULL) 377 return -1; 378 state = (gz_statep)file; 379 if (state->mode != GZ_READ && state->mode != GZ_WRITE) 380 return -1; 381 382 /* check that there's no error */ 383 if (state->err != Z_OK && state->err != Z_BUF_ERROR) 384 return -1; 385 386 /* can only seek from start or relative to current position */ 387 if (whence != SEEK_SET && whence != SEEK_CUR) 388 return -1; 389 390 /* normalize offset to a SEEK_CUR specification */ 391 if (whence == SEEK_SET) 392 offset -= state->x.pos; 393 else if (state->seek) 394 offset += state->skip; 395 state->seek = 0; 396 397 /* if within raw area while reading, just go there */ 398 if (state->mode == GZ_READ && state->how == COPY && 399 state->x.pos + offset >= 0) { 400 ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR); 401 if (ret == -1) 402 return -1; 403 state->x.have = 0; 404 state->eof = 0; 405 state->past = 0; 406 state->seek = 0; 407 gz_error(state, Z_OK, NULL); 408 state->strm.avail_in = 0; 409 state->x.pos += offset; 410 return state->x.pos; 411 } 412 413 /* calculate skip amount, rewinding if needed for back seek when reading */ 414 if (offset < 0) { 415 if (state->mode != GZ_READ) /* writing -- can't go backwards */ 416 return -1; 417 offset += state->x.pos; 418 if (offset < 0) /* before start of file! */ 419 return -1; 420 if (gzrewind(file) == -1) /* rewind, then skip to offset */ 421 return -1; 422 } 423 424 /* if reading, skip what's in output buffer (one less gzgetc() check) */ 425 if (state->mode == GZ_READ) { 426 n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ? 427 (unsigned)offset : state->x.have; 428 state->x.have -= n; 429 state->x.next += n; 430 state->x.pos += n; 431 offset -= n; 432 } 433 434 /* request skip (if not zero) */ 435 if (offset) { 436 state->seek = 1; 437 state->skip = offset; 438 } 439 return state->x.pos + offset; 440 } 441 442 /* -- see zlib.h -- */ 443 z_off_t ZEXPORT gzseek(file, offset, whence) 444 gzFile file; 445 z_off_t offset; 446 int whence; 447 { 448 z_off64_t ret; 449 450 ret = gzseek64(file, (z_off64_t)offset, whence); 451 return ret == (z_off_t)ret ? (z_off_t)ret : -1; 452 } 453 454 /* -- see zlib.h -- */ 455 z_off64_t ZEXPORT gztell64(file) 456 gzFile file; 457 { 458 gz_statep state; 459 460 /* get internal structure and check integrity */ 461 if (file == NULL) 462 return -1; 463 state = (gz_statep)file; 464 if (state->mode != GZ_READ && state->mode != GZ_WRITE) 465 return -1; 466 467 /* return position */ 468 return state->x.pos + (state->seek ? state->skip : 0); 469 } 470 471 /* -- see zlib.h -- */ 472 z_off_t ZEXPORT gztell(file) 473 gzFile file; 474 { 475 z_off64_t ret; 476 477 ret = gztell64(file); 478 return ret == (z_off_t)ret ? (z_off_t)ret : -1; 479 } 480 481 /* -- see zlib.h -- */ 482 z_off64_t ZEXPORT gzoffset64(file) 483 gzFile file; 484 { 485 z_off64_t offset; 486 gz_statep state; 487 488 /* get internal structure and check integrity */ 489 if (file == NULL) 490 return -1; 491 state = (gz_statep)file; 492 if (state->mode != GZ_READ && state->mode != GZ_WRITE) 493 return -1; 494 495 /* compute and return effective offset in file */ 496 offset = LSEEK(state->fd, 0, SEEK_CUR); 497 if (offset == -1) 498 return -1; 499 if (state->mode == GZ_READ) /* reading */ 500 offset -= state->strm.avail_in; /* don't count buffered input */ 501 return offset; 502 } 503 504 /* -- see zlib.h -- */ 505 z_off_t ZEXPORT gzoffset(file) 506 gzFile file; 507 { 508 z_off64_t ret; 509 510 ret = gzoffset64(file); 511 return ret == (z_off_t)ret ? (z_off_t)ret : -1; 512 } 513 514 /* -- see zlib.h -- */ 515 int ZEXPORT gzeof(file) 516 gzFile file; 517 { 518 gz_statep state; 519 520 /* get internal structure and check integrity */ 521 if (file == NULL) 522 return 0; 523 state = (gz_statep)file; 524 if (state->mode != GZ_READ && state->mode != GZ_WRITE) 525 return 0; 526 527 /* return end-of-file state */ 528 return state->mode == GZ_READ ? state->past : 0; 529 } 530 531 /* -- see zlib.h -- */ 532 const char * ZEXPORT gzerror(file, errnum) 533 gzFile file; 534 int *errnum; 535 { 536 gz_statep state; 537 538 /* get internal structure and check integrity */ 539 if (file == NULL) 540 return NULL; 541 state = (gz_statep)file; 542 if (state->mode != GZ_READ && state->mode != GZ_WRITE) 543 return NULL; 544 545 /* return error information */ 546 if (errnum != NULL) 547 *errnum = state->err; 548 return state->err == Z_MEM_ERROR ? "out of memory" : 549 (state->msg == NULL ? "" : state->msg); 550 } 551 552 /* -- see zlib.h -- */ 553 void ZEXPORT gzclearerr(file) 554 gzFile file; 555 { 556 gz_statep state; 557 558 /* get internal structure and check integrity */ 559 if (file == NULL) 560 return; 561 state = (gz_statep)file; 562 if (state->mode != GZ_READ && state->mode != GZ_WRITE) 563 return; 564 565 /* clear error and end-of-file */ 566 if (state->mode == GZ_READ) { 567 state->eof = 0; 568 state->past = 0; 569 } 570 gz_error(state, Z_OK, NULL); 571 } 572 573 /* Create an error message in allocated memory and set state->err and 574 state->msg accordingly. Free any previous error message already there. Do 575 not try to free or allocate space if the error is Z_MEM_ERROR (out of 576 memory). Simply save the error message as a static string. If there is an 577 allocation failure constructing the error message, then convert the error to 578 out of memory. */ 579 void ZLIB_INTERNAL gz_error(state, err, msg) 580 gz_statep state; 581 int err; 582 const char *msg; 583 { 584 /* free previously allocated message and clear */ 585 if (state->msg != NULL) { 586 if (state->err != Z_MEM_ERROR) 587 free(state->msg); 588 state->msg = NULL; 589 } 590 591 /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */ 592 if (err != Z_OK && err != Z_BUF_ERROR) 593 state->x.have = 0; 594 595 /* set error code, and if no message, then done */ 596 state->err = err; 597 if (msg == NULL) 598 return; 599 600 /* for an out of memory error, return literal string when requested */ 601 if (err == Z_MEM_ERROR) 602 return; 603 604 /* construct error message with path */ 605 if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) == 606 NULL) { 607 state->err = Z_MEM_ERROR; 608 return; 609 } 610 #if !defined(NO_snprintf) && !defined(NO_vsnprintf) 611 (void)snprintf(state->msg, strlen(state->path) + strlen(msg) + 3, 612 "%s%s%s", state->path, ": ", msg); 613 #else 614 strcpy(state->msg, state->path); 615 strcat(state->msg, ": "); 616 strcat(state->msg, msg); 617 #endif 618 } 619 620 #ifndef INT_MAX 621 /* portably return maximum value for an int (when limits.h presumed not 622 available) -- we need to do this to cover cases where 2's complement not 623 used, since C standard permits 1's complement and sign-bit representations, 624 otherwise we could just use ((unsigned)-1) >> 1 */ 625 unsigned ZLIB_INTERNAL gz_intmax() 626 { 627 unsigned p, q; 628 629 p = 1; 630 do { 631 q = p; 632 p <<= 1; 633 p++; 634 } while (p > q); 635 return q >> 1; 636 } 637 #endif 638