File indexing completed on 2024-04-21 03:48:30
0001 /* gzlib.c -- zlib functions common to reading and writing gzip files 0002 * Copyright (C) 2004, 2010, 2011, 2012, 2013 Mark Adler 0003 * For conditions of distribution and use, see copyright notice in zlib.h 0004 */ 0005 0006 #include "gzguts.h" 0007 0008 #if defined(_WIN32) && !defined(__BORLANDC__) 0009 # define LSEEK _lseeki64 0010 #else 0011 #if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 0012 # define LSEEK lseek64 0013 #else 0014 # define LSEEK lseek 0015 #endif 0016 #endif 0017 0018 /* Local functions */ 0019 local void gz_reset OF((gz_statep)); 0020 local gzFile gz_open OF((const void *, int, const char *)); 0021 0022 #if defined UNDER_CE 0023 0024 /* Map the Windows error number in ERROR to a locale-dependent error message 0025 string and return a pointer to it. Typically, the values for ERROR come 0026 from GetLastError. 0027 0028 The string pointed to shall not be modified by the application, but may be 0029 overwritten by a subsequent call to gz_strwinerror 0030 0031 The gz_strwinerror function does not change the current setting of 0032 GetLastError. */ 0033 char ZLIB_INTERNAL *gz_strwinerror (error) 0034 DWORD error; 0035 { 0036 static char buf[1024]; 0037 0038 wchar_t *msgbuf; 0039 DWORD lasterr = GetLastError(); 0040 DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM 0041 | FORMAT_MESSAGE_ALLOCATE_BUFFER, 0042 NULL, 0043 error, 0044 0, /* Default language */ 0045 (LPVOID)&msgbuf, 0046 0, 0047 NULL); 0048 if (chars != 0) { 0049 /* If there is an \r\n appended, zap it. */ 0050 if (chars >= 2 0051 && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') { 0052 chars -= 2; 0053 msgbuf[chars] = 0; 0054 } 0055 0056 if (chars > sizeof (buf) - 1) { 0057 chars = sizeof (buf) - 1; 0058 msgbuf[chars] = 0; 0059 } 0060 0061 wcstombs(buf, msgbuf, chars + 1); 0062 LocalFree(msgbuf); 0063 } 0064 else { 0065 sprintf(buf, "unknown win32 error (%ld)", error); 0066 } 0067 0068 SetLastError(lasterr); 0069 return buf; 0070 } 0071 0072 #endif /* UNDER_CE */ 0073 0074 /* Reset gzip file state */ 0075 local void gz_reset(state) 0076 gz_statep state; 0077 { 0078 state->x.have = 0; /* no output data available */ 0079 if (state->mode == GZ_READ) { /* for reading ... */ 0080 state->eof = 0; /* not at end of file */ 0081 state->past = 0; /* have not read past end yet */ 0082 state->how = LOOK; /* look for gzip header */ 0083 } 0084 state->seek = 0; /* no seek request pending */ 0085 gz_error(state, Z_OK, NULL); /* clear error */ 0086 state->x.pos = 0; /* no uncompressed data yet */ 0087 state->strm.avail_in = 0; /* no input data yet */ 0088 } 0089 0090 /* Open a gzip file either by name or file descriptor. */ 0091 local gzFile gz_open(path, fd, mode) 0092 const void *path; 0093 int fd; 0094 const char *mode; 0095 { 0096 gz_statep state; 0097 size_t len; 0098 int oflag; 0099 #ifdef O_CLOEXEC 0100 int cloexec = 0; 0101 #endif 0102 #ifdef O_EXCL 0103 int exclusive = 0; 0104 #endif 0105 0106 /* check input */ 0107 if (path == NULL) 0108 return NULL; 0109 0110 /* allocate gzFile structure to return */ 0111 state = (gz_statep)malloc(sizeof(gz_state)); 0112 if (state == NULL) 0113 return NULL; 0114 state->size = 0; /* no buffers allocated yet */ 0115 state->want = GZBUFSIZE; /* requested buffer size */ 0116 state->msg = NULL; /* no error message yet */ 0117 0118 /* interpret mode */ 0119 state->mode = GZ_NONE; 0120 state->level = Z_DEFAULT_COMPRESSION; 0121 state->strategy = Z_DEFAULT_STRATEGY; 0122 state->direct = 0; 0123 while (*mode) { 0124 if (*mode >= '0' && *mode <= '9') 0125 state->level = *mode - '0'; 0126 else 0127 switch (*mode) { 0128 case 'r': 0129 state->mode = GZ_READ; 0130 break; 0131 #ifndef NO_GZCOMPRESS 0132 case 'w': 0133 state->mode = GZ_WRITE; 0134 break; 0135 case 'a': 0136 state->mode = GZ_APPEND; 0137 break; 0138 #endif 0139 case '+': /* can't read and write at the same time */ 0140 free(state); 0141 return NULL; 0142 case 'b': /* ignore -- will request binary anyway */ 0143 break; 0144 #ifdef O_CLOEXEC 0145 case 'e': 0146 cloexec = 1; 0147 break; 0148 #endif 0149 #ifdef O_EXCL 0150 case 'x': 0151 exclusive = 1; 0152 break; 0153 #endif 0154 case 'f': 0155 state->strategy = Z_FILTERED; 0156 break; 0157 case 'h': 0158 state->strategy = Z_HUFFMAN_ONLY; 0159 break; 0160 case 'R': 0161 state->strategy = Z_RLE; 0162 break; 0163 case 'F': 0164 state->strategy = Z_FIXED; 0165 break; 0166 case 'T': 0167 state->direct = 1; 0168 break; 0169 default: /* could consider as an error, but just ignore */ 0170 ; 0171 } 0172 mode++; 0173 } 0174 0175 /* must provide an "r", "w", or "a" */ 0176 if (state->mode == GZ_NONE) { 0177 free(state); 0178 return NULL; 0179 } 0180 0181 /* can't force transparent read */ 0182 if (state->mode == GZ_READ) { 0183 if (state->direct) { 0184 free(state); 0185 return NULL; 0186 } 0187 state->direct = 1; /* for empty file */ 0188 } 0189 0190 /* save the path name for error messages */ 0191 #ifdef _WIN32 0192 if (fd == -2) { 0193 len = wcstombs(NULL, path, 0); 0194 if (len == (size_t)-1) 0195 len = 0; 0196 } 0197 else 0198 #endif 0199 len = strlen((const char *)path); 0200 state->path = (char *)malloc(len + 1); 0201 if (state->path == NULL) { 0202 free(state); 0203 return NULL; 0204 } 0205 #ifdef _WIN32 0206 if (fd == -2) 0207 if (len) 0208 wcstombs(state->path, path, len + 1); 0209 else 0210 *(state->path) = 0; 0211 else 0212 #endif 0213 #if !defined(NO_snprintf) && !defined(NO_vsnprintf) 0214 snprintf(state->path, len + 1, "%s", (const char *)path); 0215 #else 0216 strcpy(state->path, path); 0217 #endif 0218 0219 /* compute the flags for open() */ 0220 oflag = 0221 #ifdef O_LARGEFILE 0222 O_LARGEFILE | 0223 #endif 0224 #ifdef O_BINARY 0225 O_BINARY | 0226 #endif 0227 #ifdef O_CLOEXEC 0228 (cloexec ? O_CLOEXEC : 0) | 0229 #endif 0230 (state->mode == GZ_READ ? 0231 O_RDONLY : 0232 (O_WRONLY | O_CREAT | 0233 #ifdef O_EXCL 0234 (exclusive ? O_EXCL : 0) | 0235 #endif 0236 (state->mode == GZ_WRITE ? 0237 O_TRUNC : 0238 O_APPEND))); 0239 0240 /* open the file with the appropriate flags (or just use fd) */ 0241 state->fd = fd > -1 ? fd : ( 0242 #ifdef _WIN32 0243 fd == -2 ? _wopen(path, oflag, 0666) : 0244 #endif 0245 open((const char *)path, oflag, 0666)); 0246 if (state->fd == -1) { 0247 free(state->path); 0248 free(state); 0249 return NULL; 0250 } 0251 if (state->mode == GZ_APPEND) 0252 state->mode = GZ_WRITE; /* simplify later checks */ 0253 0254 /* save the current position for rewinding (only if reading) */ 0255 if (state->mode == GZ_READ) { 0256 state->start = LSEEK(state->fd, 0, SEEK_CUR); 0257 if (state->start == -1) state->start = 0; 0258 } 0259 0260 /* initialize stream */ 0261 gz_reset(state); 0262 0263 /* return stream */ 0264 return (gzFile)state; 0265 } 0266 0267 /* -- see zlib.h -- */ 0268 gzFile ZEXPORT gzopen(path, mode) 0269 const char *path; 0270 const char *mode; 0271 { 0272 return gz_open(path, -1, mode); 0273 } 0274 0275 /* -- see zlib.h -- */ 0276 gzFile ZEXPORT gzopen64(path, mode) 0277 const char *path; 0278 const char *mode; 0279 { 0280 return gz_open(path, -1, mode); 0281 } 0282 0283 /* -- see zlib.h -- */ 0284 gzFile ZEXPORT gzdopen(fd, mode) 0285 int fd; 0286 const char *mode; 0287 { 0288 char *path; /* identifier for error messages */ 0289 gzFile gz; 0290 0291 if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL) 0292 return NULL; 0293 #if !defined(NO_snprintf) && !defined(NO_vsnprintf) 0294 snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd); /* for debugging */ 0295 #else 0296 sprintf(path, "<fd:%d>", fd); /* for debugging */ 0297 #endif 0298 gz = gz_open(path, fd, mode); 0299 free(path); 0300 return gz; 0301 } 0302 0303 /* -- see zlib.h -- */ 0304 #ifdef _WIN32 0305 gzFile ZEXPORT gzopen_w(path, mode) 0306 const wchar_t *path; 0307 const char *mode; 0308 { 0309 return gz_open(path, -2, mode); 0310 } 0311 #endif 0312 0313 /* -- see zlib.h -- */ 0314 int ZEXPORT gzbuffer(file, size) 0315 gzFile file; 0316 unsigned size; 0317 { 0318 gz_statep state; 0319 0320 /* get internal structure and check integrity */ 0321 if (file == NULL) 0322 return -1; 0323 state = (gz_statep)file; 0324 if (state->mode != GZ_READ && state->mode != GZ_WRITE) 0325 return -1; 0326 0327 /* make sure we haven't already allocated memory */ 0328 if (state->size != 0) 0329 return -1; 0330 0331 /* check and set requested size */ 0332 if (size < 2) 0333 size = 2; /* need two bytes to check magic header */ 0334 state->want = size; 0335 return 0; 0336 } 0337 0338 /* -- see zlib.h -- */ 0339 int ZEXPORT gzrewind(file) 0340 gzFile file; 0341 { 0342 gz_statep state; 0343 0344 /* get internal structure */ 0345 if (file == NULL) 0346 return -1; 0347 state = (gz_statep)file; 0348 0349 /* check that we're reading and that there's no error */ 0350 if (state->mode != GZ_READ || 0351 (state->err != Z_OK && state->err != Z_BUF_ERROR)) 0352 return -1; 0353 0354 /* back up and start over */ 0355 if (LSEEK(state->fd, state->start, SEEK_SET) == -1) 0356 return -1; 0357 gz_reset(state); 0358 return 0; 0359 } 0360 0361 /* -- see zlib.h -- */ 0362 z_off64_t ZEXPORT gzseek64(file, offset, whence) 0363 gzFile file; 0364 z_off64_t offset; 0365 int whence; 0366 { 0367 unsigned n; 0368 z_off64_t ret; 0369 gz_statep state; 0370 0371 /* get internal structure and check integrity */ 0372 if (file == NULL) 0373 return -1; 0374 state = (gz_statep)file; 0375 if (state->mode != GZ_READ && state->mode != GZ_WRITE) 0376 return -1; 0377 0378 /* check that there's no error */ 0379 if (state->err != Z_OK && state->err != Z_BUF_ERROR) 0380 return -1; 0381 0382 /* can only seek from start or relative to current position */ 0383 if (whence != SEEK_SET && whence != SEEK_CUR) 0384 return -1; 0385 0386 /* normalize offset to a SEEK_CUR specification */ 0387 if (whence == SEEK_SET) 0388 offset -= state->x.pos; 0389 else if (state->seek) 0390 offset += state->skip; 0391 state->seek = 0; 0392 0393 /* if within raw area while reading, just go there */ 0394 if (state->mode == GZ_READ && state->how == COPY && 0395 state->x.pos + offset >= 0) { 0396 ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR); 0397 if (ret == -1) 0398 return -1; 0399 state->x.have = 0; 0400 state->eof = 0; 0401 state->past = 0; 0402 state->seek = 0; 0403 gz_error(state, Z_OK, NULL); 0404 state->strm.avail_in = 0; 0405 state->x.pos += offset; 0406 return state->x.pos; 0407 } 0408 0409 /* calculate skip amount, rewinding if needed for back seek when reading */ 0410 if (offset < 0) { 0411 if (state->mode != GZ_READ) /* writing -- can't go backwards */ 0412 return -1; 0413 offset += state->x.pos; 0414 if (offset < 0) /* before start of file! */ 0415 return -1; 0416 if (gzrewind(file) == -1) /* rewind, then skip to offset */ 0417 return -1; 0418 } 0419 0420 /* if reading, skip what's in output buffer (one less gzgetc() check) */ 0421 if (state->mode == GZ_READ) { 0422 n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ? 0423 (unsigned)offset : state->x.have; 0424 state->x.have -= n; 0425 state->x.next += n; 0426 state->x.pos += n; 0427 offset -= n; 0428 } 0429 0430 /* request skip (if not zero) */ 0431 if (offset) { 0432 state->seek = 1; 0433 state->skip = offset; 0434 } 0435 return state->x.pos + offset; 0436 } 0437 0438 /* -- see zlib.h -- */ 0439 z_off_t ZEXPORT gzseek(file, offset, whence) 0440 gzFile file; 0441 z_off_t offset; 0442 int whence; 0443 { 0444 z_off64_t ret; 0445 0446 ret = gzseek64(file, (z_off64_t)offset, whence); 0447 return ret == (z_off_t)ret ? (z_off_t)ret : -1; 0448 } 0449 0450 /* -- see zlib.h -- */ 0451 z_off64_t ZEXPORT gztell64(file) 0452 gzFile file; 0453 { 0454 gz_statep state; 0455 0456 /* get internal structure and check integrity */ 0457 if (file == NULL) 0458 return -1; 0459 state = (gz_statep)file; 0460 if (state->mode != GZ_READ && state->mode != GZ_WRITE) 0461 return -1; 0462 0463 /* return position */ 0464 return state->x.pos + (state->seek ? state->skip : 0); 0465 } 0466 0467 /* -- see zlib.h -- */ 0468 z_off_t ZEXPORT gztell(file) 0469 gzFile file; 0470 { 0471 z_off64_t ret; 0472 0473 ret = gztell64(file); 0474 return ret == (z_off_t)ret ? (z_off_t)ret : -1; 0475 } 0476 0477 /* -- see zlib.h -- */ 0478 z_off64_t ZEXPORT gzoffset64(file) 0479 gzFile file; 0480 { 0481 z_off64_t offset; 0482 gz_statep state; 0483 0484 /* get internal structure and check integrity */ 0485 if (file == NULL) 0486 return -1; 0487 state = (gz_statep)file; 0488 if (state->mode != GZ_READ && state->mode != GZ_WRITE) 0489 return -1; 0490 0491 /* compute and return effective offset in file */ 0492 offset = LSEEK(state->fd, 0, SEEK_CUR); 0493 if (offset == -1) 0494 return -1; 0495 if (state->mode == GZ_READ) /* reading */ 0496 offset -= state->strm.avail_in; /* don't count buffered input */ 0497 return offset; 0498 } 0499 0500 /* -- see zlib.h -- */ 0501 z_off_t ZEXPORT gzoffset(file) 0502 gzFile file; 0503 { 0504 z_off64_t ret; 0505 0506 ret = gzoffset64(file); 0507 return ret == (z_off_t)ret ? (z_off_t)ret : -1; 0508 } 0509 0510 /* -- see zlib.h -- */ 0511 int ZEXPORT gzeof(file) 0512 gzFile file; 0513 { 0514 gz_statep state; 0515 0516 /* get internal structure and check integrity */ 0517 if (file == NULL) 0518 return 0; 0519 state = (gz_statep)file; 0520 if (state->mode != GZ_READ && state->mode != GZ_WRITE) 0521 return 0; 0522 0523 /* return end-of-file state */ 0524 return state->mode == GZ_READ ? state->past : 0; 0525 } 0526 0527 /* -- see zlib.h -- */ 0528 const char * ZEXPORT gzerror(file, errnum) 0529 gzFile file; 0530 int *errnum; 0531 { 0532 gz_statep state; 0533 0534 /* get internal structure and check integrity */ 0535 if (file == NULL) 0536 return NULL; 0537 state = (gz_statep)file; 0538 if (state->mode != GZ_READ && state->mode != GZ_WRITE) 0539 return NULL; 0540 0541 /* return error information */ 0542 if (errnum != NULL) 0543 *errnum = state->err; 0544 return state->err == Z_MEM_ERROR ? "out of memory" : 0545 (state->msg == NULL ? "" : state->msg); 0546 } 0547 0548 /* -- see zlib.h -- */ 0549 void ZEXPORT gzclearerr(file) 0550 gzFile file; 0551 { 0552 gz_statep state; 0553 0554 /* get internal structure and check integrity */ 0555 if (file == NULL) 0556 return; 0557 state = (gz_statep)file; 0558 if (state->mode != GZ_READ && state->mode != GZ_WRITE) 0559 return; 0560 0561 /* clear error and end-of-file */ 0562 if (state->mode == GZ_READ) { 0563 state->eof = 0; 0564 state->past = 0; 0565 } 0566 gz_error(state, Z_OK, NULL); 0567 } 0568 0569 /* Create an error message in allocated memory and set state->err and 0570 state->msg accordingly. Free any previous error message already there. Do 0571 not try to free or allocate space if the error is Z_MEM_ERROR (out of 0572 memory). Simply save the error message as a static string. If there is an 0573 allocation failure constructing the error message, then convert the error to 0574 out of memory. */ 0575 void ZLIB_INTERNAL gz_error(state, err, msg) 0576 gz_statep state; 0577 int err; 0578 const char *msg; 0579 { 0580 /* free previously allocated message and clear */ 0581 if (state->msg != NULL) { 0582 if (state->err != Z_MEM_ERROR) 0583 free(state->msg); 0584 state->msg = NULL; 0585 } 0586 0587 /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */ 0588 if (err != Z_OK && err != Z_BUF_ERROR) 0589 state->x.have = 0; 0590 0591 /* set error code, and if no message, then done */ 0592 state->err = err; 0593 if (msg == NULL) 0594 return; 0595 0596 /* for an out of memory error, return literal string when requested */ 0597 if (err == Z_MEM_ERROR) 0598 return; 0599 0600 /* construct error message with path */ 0601 if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) == 0602 NULL) { 0603 state->err = Z_MEM_ERROR; 0604 return; 0605 } 0606 #if !defined(NO_snprintf) && !defined(NO_vsnprintf) 0607 snprintf(state->msg, strlen(state->path) + strlen(msg) + 3, 0608 "%s%s%s", state->path, ": ", msg); 0609 #else 0610 strcpy(state->msg, state->path); 0611 strcat(state->msg, ": "); 0612 strcat(state->msg, msg); 0613 #endif 0614 return; 0615 } 0616 0617 #ifndef INT_MAX 0618 /* portably return maximum value for an int (when limits.h presumed not 0619 available) -- we need to do this to cover cases where 2's complement not 0620 used, since C standard permits 1's complement and sign-bit representations, 0621 otherwise we could just use ((unsigned)-1) >> 1 */ 0622 unsigned ZLIB_INTERNAL gz_intmax() 0623 { 0624 unsigned p, q; 0625 0626 p = 1; 0627 do { 0628 q = p; 0629 p <<= 1; 0630 p++; 0631 } while (p > q); 0632 return q >> 1; 0633 } 0634 #endif