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