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