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

mercurial