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