modules/zlib/src/gzlib.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial