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