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