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