in zlibWrapper/gzlib.c [94:270]
local gzFile gz_open(path, fd, mode)
const void *path;
int fd;
const char *mode;
{
gz_statep state;
z_size_t len;
int oflag;
#ifdef O_CLOEXEC
int cloexec = 0;
#endif
#ifdef O_EXCL
int exclusive = 0;
#endif
/* check input */
if (path == NULL)
return NULL;
/* allocate gzFile structure to return */
state.state = (gz_state*)malloc(sizeof(gz_state));
if (state.state == NULL)
return NULL;
state.state->size = 0; /* no buffers allocated yet */
state.state->want = GZBUFSIZE; /* requested buffer size */
state.state->msg = NULL; /* no error message yet */
/* interpret mode */
state.state->mode = GZ_NONE;
state.state->level = Z_DEFAULT_COMPRESSION;
state.state->strategy = Z_DEFAULT_STRATEGY;
state.state->direct = 0;
while (*mode) {
if (*mode >= '0' && *mode <= '9')
state.state->level = *mode - '0';
else
switch (*mode) {
case 'r':
state.state->mode = GZ_READ;
break;
#ifndef NO_GZCOMPRESS
case 'w':
state.state->mode = GZ_WRITE;
break;
case 'a':
state.state->mode = GZ_APPEND;
break;
#endif
case '+': /* can't read and write at the same time */
free(state.state);
return NULL;
case 'b': /* ignore -- will request binary anyway */
break;
#ifdef O_CLOEXEC
case 'e':
cloexec = 1;
break;
#endif
#ifdef O_EXCL
case 'x':
exclusive = 1;
break;
#endif
case 'f':
state.state->strategy = Z_FILTERED;
break;
case 'h':
state.state->strategy = Z_HUFFMAN_ONLY;
break;
case 'R':
state.state->strategy = Z_RLE;
break;
case 'F':
state.state->strategy = Z_FIXED;
break;
case 'T':
state.state->direct = 1;
break;
default: /* could consider as an error, but just ignore */
;
}
mode++;
}
/* must provide an "r", "w", or "a" */
if (state.state->mode == GZ_NONE) {
free(state.state);
return NULL;
}
/* can't force transparent read */
if (state.state->mode == GZ_READ) {
if (state.state->direct) {
free(state.state);
return NULL;
}
state.state->direct = 1; /* for empty file */
}
/* save the path name for error messages */
#ifdef WIDECHAR
if (fd == -2) {
len = wcstombs(NULL, path, 0);
if (len == (z_size_t)-1)
len = 0;
}
else
#endif
len = strlen((const char *)path);
state.state->path = (char *)malloc(len + 1);
if (state.state->path == NULL) {
free(state.state);
return NULL;
}
#ifdef WIDECHAR
if (fd == -2)
if (len)
wcstombs(state.state->path, path, len + 1);
else
*(state.state->path) = 0;
else
#endif
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
(void)snprintf(state.state->path, len + 1, "%s", (const char *)path);
#else
strcpy(state.state->path, (const char*)path);
#endif
/* compute the flags for open() */
oflag =
#ifdef O_LARGEFILE
O_LARGEFILE |
#endif
#ifdef O_BINARY
O_BINARY |
#endif
#ifdef O_CLOEXEC
(cloexec ? O_CLOEXEC : 0) |
#endif
(state.state->mode == GZ_READ ?
O_RDONLY :
(O_WRONLY | O_CREAT |
#ifdef O_EXCL
(exclusive ? O_EXCL : 0) |
#endif
(state.state->mode == GZ_WRITE ?
O_TRUNC :
O_APPEND)));
/* open the file with the appropriate flags (or just use fd) */
state.state->fd = fd > -1 ? fd : (
#ifdef WIDECHAR
fd == -2 ? _wopen(path, oflag, 0666) :
#endif
open((const char *)path, oflag, 0666));
if (state.state->fd == -1) {
free(state.state->path);
free(state.state);
return NULL;
}
if (state.state->mode == GZ_APPEND) {
LSEEK(state.state->fd, 0, SEEK_END); /* so gzoffset() is correct */
state.state->mode = GZ_WRITE; /* simplify later checks */
}
/* save the current position for rewinding (only if reading) */
if (state.state->mode == GZ_READ) {
state.state->start = LSEEK(state.state->fd, 0, SEEK_CUR);
if (state.state->start == -1) state.state->start = 0;
}
/* initialize stream */
gz_reset(state);
/* return stream */
return state.file;
}