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