1 /* gzlib.c -- zlib functions common to reading and writing gzip files 2 * Copyright (C) 2004, 2010, 2011, 2012, 2013 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__) 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 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 _WIN32 195 if (fd == -2) { 196 len = wcstombs(NULL, path, 0); 197 if (len == (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 _WIN32 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 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 _WIN32 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 state->mode = GZ_WRITE; /* simplify later checks */ 256 257 /* save the current position for rewinding (only if reading) */ 258 if (state->mode == GZ_READ) { 259 state->start = LSEEK(state->fd, 0, SEEK_CUR); 260 if (state->start == -1) state->start = 0; 261 } 262 263 /* initialize stream */ 264 gz_reset(state); 265 266 /* return stream */ 267 return (gzFile)state; 268 } 269 270 /* -- see zlib.h -- */ 271 gzFile ZEXPORT gzopen(path, mode) 272 const char *path; 273 const char *mode; 274 { 275 return gz_open(path, -1, mode); 276 } 277 278 /* -- see zlib.h -- */ 279 gzFile ZEXPORT gzopen64(path, mode) 280 const char *path; 281 const char *mode; 282 { 283 return gz_open(path, -1, mode); 284 } 285 286 /* -- see zlib.h -- */ 287 gzFile ZEXPORT gzdopen(fd, mode) 288 int fd; 289 const char *mode; 290 { 291 char *path; /* identifier for error messages */ 292 gzFile gz; 293 294 if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL) 295 return NULL; 296 #if !defined(NO_snprintf) && !defined(NO_vsnprintf) 297 snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd); /* for debugging */ 298 #else 299 sprintf(path, "<fd:%d>", fd); /* for debugging */ 300 #endif 301 gz = gz_open(path, fd, mode); 302 free(path); 303 return gz; 304 } 305 306 /* -- see zlib.h -- */ 307 #ifdef _WIN32 308 gzFile ZEXPORT gzopen_w(path, mode) 309 const wchar_t *path; 310 const char *mode; 311 { 312 return gz_open(path, -2, mode); 313 } 314 #endif 315 316 /* -- see zlib.h -- */ 317 int ZEXPORT gzbuffer(file, size) 318 gzFile file; 319 unsigned size; 320 { 321 gz_statep state; 322 323 /* get internal structure and check integrity */ 324 if (file == NULL) 325 return -1; 326 state = (gz_statep)file; 327 if (state->mode != GZ_READ && state->mode != GZ_WRITE) 328 return -1; 329 330 /* make sure we haven't already allocated memory */ 331 if (state->size != 0) 332 return -1; 333 334 /* check and set requested size */ 335 if (size < 2) 336 size = 2; /* need two bytes to check magic header */ 337 state->want = size; 338 return 0; 339 } 340 341 /* -- see zlib.h -- */ 342 int ZEXPORT gzrewind(file) 343 gzFile file; 344 { 345 gz_statep state; 346 347 /* get internal structure */ 348 if (file == NULL) 349 return -1; 350 state = (gz_statep)file; 351 352 /* check that we're reading and that there's no error */ 353 if (state->mode != GZ_READ || 354 (state->err != Z_OK && state->err != Z_BUF_ERROR)) 355 return -1; 356 357 /* back up and start over */ 358 if (LSEEK(state->fd, state->start, SEEK_SET) == -1) 359 return -1; 360 gz_reset(state); 361 return 0; 362 } 363 364 /* -- see zlib.h -- */ 365 z_off64_t ZEXPORT gzseek64(file, offset, whence) 366 gzFile file; 367 z_off64_t offset; 368 int whence; 369 { 370 unsigned n; 371 z_off64_t ret; 372 gz_statep state; 373 374 /* get internal structure and check integrity */ 375 if (file == NULL) 376 return -1; 377 state = (gz_statep)file; 378 if (state->mode != GZ_READ && state->mode != GZ_WRITE) 379 return -1; 380 381 /* check that there's no error */ 382 if (state->err != Z_OK && state->err != Z_BUF_ERROR) 383 return -1; 384 385 /* can only seek from start or relative to current position */ 386 if (whence != SEEK_SET && whence != SEEK_CUR) 387 return -1; 388 389 /* normalize offset to a SEEK_CUR specification */ 390 if (whence == SEEK_SET) 391 offset -= state->x.pos; 392 else if (state->seek) 393 offset += state->skip; 394 state->seek = 0; 395 396 /* if within raw area while reading, just go there */ 397 if (state->mode == GZ_READ && state->how == COPY && 398 state->x.pos + offset >= 0) { 399 ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR); 400 if (ret == -1) 401 return -1; 402 state->x.have = 0; 403 state->eof = 0; 404 state->past = 0; 405 state->seek = 0; 406 gz_error(state, Z_OK, NULL); 407 state->strm.avail_in = 0; 408 state->x.pos += offset; 409 return state->x.pos; 410 } 411 412 /* calculate skip amount, rewinding if needed for back seek when reading */ 413 if (offset < 0) { 414 if (state->mode != GZ_READ) /* writing -- can't go backwards */ 415 return -1; 416 offset += state->x.pos; 417 if (offset < 0) /* before start of file! */ 418 return -1; 419 if (gzrewind(file) == -1) /* rewind, then skip to offset */ 420 return -1; 421 } 422 423 /* if reading, skip what's in output buffer (one less gzgetc() check) */ 424 if (state->mode == GZ_READ) { 425 n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ? 426 (unsigned)offset : state->x.have; 427 state->x.have -= n; 428 state->x.next += n; 429 state->x.pos += n; 430 offset -= n; 431 } 432 433 /* request skip (if not zero) */ 434 if (offset) { 435 state->seek = 1; 436 state->skip = offset; 437 } 438 return state->x.pos + offset; 439 } 440 441 /* -- see zlib.h -- */ 442 z_off_t ZEXPORT gzseek(file, offset, whence) 443 gzFile file; 444 z_off_t offset; 445 int whence; 446 { 447 z_off64_t ret; 448 449 ret = gzseek64(file, (z_off64_t)offset, whence); 450 return ret == (z_off_t)ret ? (z_off_t)ret : -1; 451 } 452 453 /* -- see zlib.h -- */ 454 z_off64_t ZEXPORT gztell64(file) 455 gzFile file; 456 { 457 gz_statep state; 458 459 /* get internal structure and check integrity */ 460 if (file == NULL) 461 return -1; 462 state = (gz_statep)file; 463 if (state->mode != GZ_READ && state->mode != GZ_WRITE) 464 return -1; 465 466 /* return position */ 467 return state->x.pos + (state->seek ? state->skip : 0); 468 } 469 470 /* -- see zlib.h -- */ 471 z_off_t ZEXPORT gztell(file) 472 gzFile file; 473 { 474 z_off64_t ret; 475 476 ret = gztell64(file); 477 return ret == (z_off_t)ret ? (z_off_t)ret : -1; 478 } 479 480 /* -- see zlib.h -- */ 481 z_off64_t ZEXPORT gzoffset64(file) 482 gzFile file; 483 { 484 z_off64_t offset; 485 gz_statep state; 486 487 /* get internal structure and check integrity */ 488 if (file == NULL) 489 return -1; 490 state = (gz_statep)file; 491 if (state->mode != GZ_READ && state->mode != GZ_WRITE) 492 return -1; 493 494 /* compute and return effective offset in file */ 495 offset = LSEEK(state->fd, 0, SEEK_CUR); 496 if (offset == -1) 497 return -1; 498 if (state->mode == GZ_READ) /* reading */ 499 offset -= state->strm.avail_in; /* don't count buffered input */ 500 return offset; 501 } 502 503 /* -- see zlib.h -- */ 504 z_off_t ZEXPORT gzoffset(file) 505 gzFile file; 506 { 507 z_off64_t ret; 508 509 ret = gzoffset64(file); 510 return ret == (z_off_t)ret ? (z_off_t)ret : -1; 511 } 512 513 /* -- see zlib.h -- */ 514 int ZEXPORT gzeof(file) 515 gzFile file; 516 { 517 gz_statep state; 518 519 /* get internal structure and check integrity */ 520 if (file == NULL) 521 return 0; 522 state = (gz_statep)file; 523 if (state->mode != GZ_READ && state->mode != GZ_WRITE) 524 return 0; 525 526 /* return end-of-file state */ 527 return state->mode == GZ_READ ? state->past : 0; 528 } 529 530 /* -- see zlib.h -- */ 531 const char * ZEXPORT gzerror(file, errnum) 532 gzFile file; 533 int *errnum; 534 { 535 gz_statep state; 536 537 /* get internal structure and check integrity */ 538 if (file == NULL) 539 return NULL; 540 state = (gz_statep)file; 541 if (state->mode != GZ_READ && state->mode != GZ_WRITE) 542 return NULL; 543 544 /* return error information */ 545 if (errnum != NULL) 546 *errnum = state->err; 547 return state->err == Z_MEM_ERROR ? "out of memory" : 548 (state->msg == NULL ? "" : state->msg); 549 } 550 551 /* -- see zlib.h -- */ 552 void ZEXPORT gzclearerr(file) 553 gzFile file; 554 { 555 gz_statep state; 556 557 /* get internal structure and check integrity */ 558 if (file == NULL) 559 return; 560 state = (gz_statep)file; 561 if (state->mode != GZ_READ && state->mode != GZ_WRITE) 562 return; 563 564 /* clear error and end-of-file */ 565 if (state->mode == GZ_READ) { 566 state->eof = 0; 567 state->past = 0; 568 } 569 gz_error(state, Z_OK, NULL); 570 } 571 572 /* Create an error message in allocated memory and set state->err and 573 state->msg accordingly. Free any previous error message already there. Do 574 not try to free or allocate space if the error is Z_MEM_ERROR (out of 575 memory). Simply save the error message as a static string. If there is an 576 allocation failure constructing the error message, then convert the error to 577 out of memory. */ 578 void ZLIB_INTERNAL gz_error(state, err, msg) 579 gz_statep state; 580 int err; 581 const char *msg; 582 { 583 /* free previously allocated message and clear */ 584 if (state->msg != NULL) { 585 if (state->err != Z_MEM_ERROR) 586 free(state->msg); 587 state->msg = NULL; 588 } 589 590 /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */ 591 if (err != Z_OK && err != Z_BUF_ERROR) 592 state->x.have = 0; 593 594 /* set error code, and if no message, then done */ 595 state->err = err; 596 if (msg == NULL) 597 return; 598 599 /* for an out of memory error, return literal string when requested */ 600 if (err == Z_MEM_ERROR) 601 return; 602 603 /* construct error message with path */ 604 if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) == 605 NULL) { 606 state->err = Z_MEM_ERROR; 607 return; 608 } 609 #if !defined(NO_snprintf) && !defined(NO_vsnprintf) 610 snprintf(state->msg, strlen(state->path) + strlen(msg) + 3, 611 "%s%s%s", state->path, ": ", msg); 612 #else 613 strcpy(state->msg, state->path); 614 strcat(state->msg, ": "); 615 strcat(state->msg, msg); 616 #endif 617 return; 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