1
0
mirror of https://github.com/facebook/zstd.git synced 2025-08-01 09:47:01 +03:00

gzwrite.c updated to zlib 1.2.11

This commit is contained in:
Przemyslaw Skibinski
2017-01-18 12:47:32 +01:00
parent 5735fd74ee
commit 3805a00904

View File

@ -1,9 +1,9 @@
/* gzwrite.c contains minimal changes required to be compiled with zlibWrapper: /* gzwrite.c contains minimal changes required to be compiled with zlibWrapper:
* - gz_statep was converted to union to work with -Wstrict-aliasing=1 */ * - gz_statep was converted to union to work with -Wstrict-aliasing=1 */
/* gzwrite.c -- zlib functions for writing gzip files /* gzwrite.c -- zlib functions for writing gzip files
* Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler * Copyright (C) 2004-2017 Mark Adler
* For conditions of distribution and use, see http://www.zlib.net/zlib_license.html * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
#include "gzguts.h" #include "gzguts.h"
@ -12,17 +12,19 @@
local int gz_init OF((gz_statep)); local int gz_init OF((gz_statep));
local int gz_comp OF((gz_statep, int)); local int gz_comp OF((gz_statep, int));
local int gz_zero OF((gz_statep, z_off64_t)); local int gz_zero OF((gz_statep, z_off64_t));
local z_size_t gz_write OF((gz_statep, voidpc, z_size_t));
/* Initialize state for writing a gzip file. Mark initialization by setting /* Initialize state for writing a gzip file. Mark initialization by setting
state->size to non-zero. Return -1 on failure or 0 on success. */ state.state->size to non-zero. Return -1 on a memory allocation failure, or 0 on
success. */
local int gz_init(state) local int gz_init(state)
gz_statep state; gz_statep state;
{ {
int ret; int ret;
z_streamp strm = &(state.state->strm); z_streamp strm = &(state.state->strm);
/* allocate input buffer */ /* allocate input buffer (double size for gzprintf) */
state.state->in = (unsigned char *)malloc(state.state->want); state.state->in = (unsigned char *)malloc(state.state->want << 1);
if (state.state->in == NULL) { if (state.state->in == NULL) {
gz_error(state, Z_MEM_ERROR, "out of memory"); gz_error(state, Z_MEM_ERROR, "out of memory");
return -1; return -1;
@ -50,6 +52,7 @@ local int gz_init(state)
gz_error(state, Z_MEM_ERROR, "out of memory"); gz_error(state, Z_MEM_ERROR, "out of memory");
return -1; return -1;
} }
strm->next_in = NULL;
} }
/* mark state as initialized */ /* mark state as initialized */
@ -65,17 +68,17 @@ local int gz_init(state)
} }
/* Compress whatever is at avail_in and next_in and write to the output file. /* Compress whatever is at avail_in and next_in and write to the output file.
Return -1 if there is an error writing to the output file, otherwise 0. Return -1 if there is an error writing to the output file or if gz_init()
flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH, fails to allocate memory, otherwise 0. flush is assumed to be a valid
then the deflate() state is reset to start a new gzip stream. If gz->direct deflate() flush value. If flush is Z_FINISH, then the deflate() state is
is true, then simply write to the output file without compressing, and reset to start a new gzip stream. If gz->direct is true, then simply write
ignore flush. */ to the output file without compressing, and ignore flush. */
local int gz_comp(state, flush) local int gz_comp(state, flush)
gz_statep state; gz_statep state;
int flush; int flush;
{ {
int ret, got; int ret, writ;
unsigned have; unsigned have, put, max = ((unsigned)-1 >> 2) + 1;
z_streamp strm = &(state.state->strm); z_streamp strm = &(state.state->strm);
/* allocate memory if this is the first time through */ /* allocate memory if this is the first time through */
@ -84,12 +87,16 @@ local int gz_comp(state, flush)
/* write directly if requested */ /* write directly if requested */
if (state.state->direct) { if (state.state->direct) {
got = (int)write(state.state->fd, strm->next_in, strm->avail_in); while (strm->avail_in) {
if (got < 0 || (unsigned)got != strm->avail_in) { put = strm->avail_in > max ? max : strm->avail_in;
gz_error(state, Z_ERRNO, zstrerror()); writ = write(state.state->fd, strm->next_in, put);
return -1; if (writ < 0) {
gz_error(state, Z_ERRNO, zstrerror());
return -1;
}
strm->avail_in -= (unsigned)writ;
strm->next_in += writ;
} }
strm->avail_in = 0;
return 0; return 0;
} }
@ -100,17 +107,21 @@ local int gz_comp(state, flush)
doing Z_FINISH then don't write until we get to Z_STREAM_END */ doing Z_FINISH then don't write until we get to Z_STREAM_END */
if (strm->avail_out == 0 || (flush != Z_NO_FLUSH && if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
(flush != Z_FINISH || ret == Z_STREAM_END))) { (flush != Z_FINISH || ret == Z_STREAM_END))) {
have = (unsigned)(strm->next_out - state.state->x.next); while (strm->next_out > state.state->x.next) {
if (have && ((got = (int)write(state.state->fd, state.state->x.next, have)) < 0 || put = strm->next_out - state.state->x.next > (int)max ? max :
(unsigned)got != have)) { (unsigned)(strm->next_out - state.state->x.next);
gz_error(state, Z_ERRNO, zstrerror()); writ = write(state.state->fd, state.state->x.next, put);
return -1; if (writ < 0) {
gz_error(state, Z_ERRNO, zstrerror());
return -1;
}
state.state->x.next += writ;
} }
if (strm->avail_out == 0) { if (strm->avail_out == 0) {
strm->avail_out = state.state->size; strm->avail_out = state.state->size;
strm->next_out = state.state->out; strm->next_out = state.state->out;
state.state->x.next = state.state->out;
} }
state.state->x.next = strm->next_out;
} }
/* compress */ /* compress */
@ -132,7 +143,8 @@ local int gz_comp(state, flush)
return 0; return 0;
} }
/* Compress len zeros to output. Return -1 on error, 0 on success. */ /* Compress len zeros to output. Return -1 on a write error or memory
allocation failure by gz_comp(), or 0 on success. */
local int gz_zero(state, len) local int gz_zero(state, len)
gz_statep state; gz_statep state;
z_off64_t len; z_off64_t len;
@ -164,32 +176,14 @@ local int gz_zero(state, len)
return 0; return 0;
} }
/* -- see zlib.h -- */ /* Write len bytes from buf to file. Return the number of bytes written. If
int ZEXPORT gzwrite(file, buf, len) the returned value is less than len, then there was an error. */
gzFile file; local z_size_t gz_write(state, buf, len)
voidpc buf;
unsigned len;
{
unsigned put = len;
gz_statep state; gz_statep state;
z_streamp strm; voidpc buf;
z_size_t len;
/* get internal structure */ {
if (file == NULL) z_size_t put = len;
return 0;
state = (gz_statep)file;
strm = &(state.state->strm);
/* check that we're writing and that there's no error */
if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)
return 0;
/* since an int is returned, make sure len fits in one, otherwise return
with an error (this avoids the flaw in the interface) */
if ((int)len < 0) {
gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
return 0;
}
/* if len is zero, avoid unnecessary operations */ /* if len is zero, avoid unnecessary operations */
if (len == 0) if (len == 0)
@ -212,14 +206,15 @@ int ZEXPORT gzwrite(file, buf, len)
do { do {
unsigned have, copy; unsigned have, copy;
if (strm->avail_in == 0) if (state.state->strm.avail_in == 0)
strm->next_in = state.state->in; state.state->strm.next_in = state.state->in;
have = (unsigned)((strm->next_in + strm->avail_in) - state.state->in); have = (unsigned)((state.state->strm.next_in + state.state->strm.avail_in) -
state.state->in);
copy = state.state->size - have; copy = state.state->size - have;
if (copy > len) if (copy > len)
copy = len; copy = len;
memcpy(state.state->in + have, buf, copy); memcpy(state.state->in + have, buf, copy);
strm->avail_in += copy; state.state->strm.avail_in += copy;
state.state->x.pos += copy; state.state->x.pos += copy;
buf = (const char *)buf + copy; buf = (const char *)buf + copy;
len -= copy; len -= copy;
@ -229,19 +224,83 @@ int ZEXPORT gzwrite(file, buf, len)
} }
else { else {
/* consume whatever's left in the input buffer */ /* consume whatever's left in the input buffer */
if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) if (state.state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
return 0; return 0;
/* directly compress user buffer to file */ /* directly compress user buffer to file */
strm->avail_in = len; state.state->strm.next_in = (z_const Bytef *)buf;
strm->next_in = (z_const Bytef *)buf; do {
state.state->x.pos += len; unsigned n = (unsigned)-1;
if (gz_comp(state, Z_NO_FLUSH) == -1) if (n > len)
return 0; n = len;
state.state->strm.avail_in = n;
state.state->x.pos += n;
if (gz_comp(state, Z_NO_FLUSH) == -1)
return 0;
len -= n;
} while (len);
} }
/* input was all buffered or compressed (put will fit in int) */ /* input was all buffered or compressed */
return (int)put; return put;
}
/* -- see zlib.h -- */
int ZEXPORT gzwrite(file, buf, len)
gzFile file;
voidpc buf;
unsigned len;
{
gz_statep state;
/* get internal structure */
if (file == NULL)
return 0;
state = (gz_statep)file;
/* check that we're writing and that there's no error */
if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)
return 0;
/* since an int is returned, make sure len fits in one, otherwise return
with an error (this avoids a flaw in the interface) */
if ((int)len < 0) {
gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
return 0;
}
/* write len bytes from buf (the return value will fit in an int) */
return (int)gz_write(state, buf, len);
}
/* -- see zlib.h -- */
z_size_t ZEXPORT gzfwrite(buf, size, nitems, file)
voidpc buf;
z_size_t size;
z_size_t nitems;
gzFile file;
{
z_size_t len;
gz_statep state;
/* get internal structure */
if (file == NULL)
return 0;
state = (gz_statep)file;
/* check that we're writing and that there's no error */
if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)
return 0;
/* compute bytes to read -- error on overflow */
len = nitems * size;
if (size && len / size != nitems) {
gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
return 0;
}
/* write len bytes to buf, return the number of full items written */
return len ? gz_write(state, buf, len) / size : 0;
} }
/* -- see zlib.h -- */ /* -- see zlib.h -- */
@ -271,7 +330,7 @@ int ZEXPORT gzputc(file, c)
return -1; return -1;
} }
/* try writing to input buffer for speed (state->size == 0 if buffer not /* try writing to input buffer for speed (state.state->size == 0 if buffer not
initialized) */ initialized) */
if (state.state->size) { if (state.state->size) {
if (strm->avail_in == 0) if (strm->avail_in == 0)
@ -287,7 +346,7 @@ int ZEXPORT gzputc(file, c)
/* no room in buffer or not initialized, use gz_write() */ /* no room in buffer or not initialized, use gz_write() */
buf[0] = (unsigned char)c; buf[0] = (unsigned char)c;
if (gzwrite(file, buf, 1) != 1) if (gz_write(state, buf, 1) != 1)
return -1; return -1;
return c & 0xff; return c & 0xff;
} }
@ -298,11 +357,21 @@ int ZEXPORT gzputs(file, str)
const char *str; const char *str;
{ {
int ret; int ret;
unsigned len; z_size_t len;
gz_statep state;
/* get internal structure */
if (file == NULL)
return -1;
state = (gz_statep)file;
/* check that we're writing and that there's no error */
if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)
return -1;
/* write string */ /* write string */
len = (unsigned)strlen(str); len = strlen(str);
ret = gzwrite(file, str, len); ret = gz_write(state, str, len);
return ret == 0 && len != 0 ? -1 : ret; return ret == 0 && len != 0 ? -1 : ret;
} }
@ -312,63 +381,73 @@ int ZEXPORT gzputs(file, str)
/* -- see zlib.h -- */ /* -- see zlib.h -- */
int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va)
{ {
int size, len; int len;
unsigned left;
char *next;
gz_statep state; gz_statep state;
z_streamp strm; z_streamp strm;
/* get internal structure */ /* get internal structure */
if (file == NULL) if (file == NULL)
return -1; return Z_STREAM_ERROR;
state = (gz_statep)file; state = (gz_statep)file;
strm = &(state.state->strm); strm = &(state.state->strm);
/* check that we're writing and that there's no error */ /* check that we're writing and that there's no error */
if (state.state->mode != GZ_WRITE || state.state->err != Z_OK) if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)
return 0; return Z_STREAM_ERROR;
/* make sure we have some buffer space */ /* make sure we have some buffer space */
if (state.state->size == 0 && gz_init(state) == -1) if (state.state->size == 0 && gz_init(state) == -1)
return 0; return state.state->err;
/* check for seek request */ /* check for seek request */
if (state.state->seek) { if (state.state->seek) {
state.state->seek = 0; state.state->seek = 0;
if (gz_zero(state, state.state->skip) == -1) if (gz_zero(state, state.state->skip) == -1)
return 0; return state.state->err;
} }
/* consume whatever's left in the input buffer */ /* do the printf() into the input buffer, put length in len -- the input
if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) buffer is double-sized just for this function, so there is guaranteed to
return 0; be state.state->size bytes available after the current contents */
if (strm->avail_in == 0)
/* do the printf() into the input buffer, put length in len */ strm->next_in = state.state->in;
size = (int)(state.state->size); next = (char *)(state.state->in + (strm->next_in - state.state->in) + strm->avail_in);
state.state->in[size - 1] = 0; next[state.state->size - 1] = 0;
#ifdef NO_vsnprintf #ifdef NO_vsnprintf
# ifdef HAS_vsprintf_void # ifdef HAS_vsprintf_void
(void)vsprintf((char *)(state.state->in), format, va); (void)vsprintf(next, format, va);
for (len = 0; len < size; len++) for (len = 0; len < state.state->size; len++)
if (state.state->in[len] == 0) break; if (next[len] == 0) break;
# else # else
len = vsprintf((char *)(state.state->in), format, va); len = vsprintf(next, format, va);
# endif # endif
#else #else
# ifdef HAS_vsnprintf_void # ifdef HAS_vsnprintf_void
(void)vsnprintf((char *)(state.state->in), size, format, va); (void)vsnprintf(next, state.state->size, format, va);
len = strlen((char *)(state.state->in)); len = strlen(next);
# else # else
len = vsnprintf((char *)(state.state->in), size, format, va); len = vsnprintf(next, state.state->size, format, va);
# endif # endif
#endif #endif
/* check that printf() results fit in buffer */ /* check that printf() results fit in buffer */
if (len <= 0 || len >= (int)size || state.state->in[size - 1] != 0) if (len == 0 || (unsigned)len >= state.state->size || next[state.state->size - 1] != 0)
return 0; return 0;
/* update buffer and position, defer compression until needed */ /* update buffer and position, compress first half if past that */
strm->avail_in = (unsigned)len; strm->avail_in += (unsigned)len;
strm->next_in = state.state->in;
state.state->x.pos += len; state.state->x.pos += len;
if (strm->avail_in >= state.state->size) {
left = strm->avail_in - state.state->size;
strm->avail_in = state.state->size;
if (gz_comp(state, Z_NO_FLUSH) == -1)
return state.state->err;
memcpy(state.state->in, state.state->in + state.state->size, left);
strm->next_in = state.state->in;
strm->avail_in = left;
}
return len; return len;
} }
@ -393,73 +472,82 @@ int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
{ {
int size, len; unsigned len, left;
char *next;
gz_statep state; gz_statep state;
z_streamp strm; z_streamp strm;
/* get internal structure */ /* get internal structure */
if (file == NULL) if (file == NULL)
return -1; return Z_STREAM_ERROR;
state = (gz_statep)file; state = (gz_statep)file;
strm = &(state.state->strm); strm = &(state.state->strm);
/* check that can really pass pointer in ints */ /* check that can really pass pointer in ints */
if (sizeof(int) != sizeof(void *)) if (sizeof(int) != sizeof(void *))
return 0; return Z_STREAM_ERROR;
/* check that we're writing and that there's no error */ /* check that we're writing and that there's no error */
if (state.state->mode != GZ_WRITE || state.state->err != Z_OK) if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)
return 0; return Z_STREAM_ERROR;
/* make sure we have some buffer space */ /* make sure we have some buffer space */
if (state.state->size == 0 && gz_init(state) == -1) if (state.state->size == 0 && gz_init(state) == -1)
return 0; return state.state->error;
/* check for seek request */ /* check for seek request */
if (state.state->seek) { if (state.state->seek) {
state.state->seek = 0; state.state->seek = 0;
if (gz_zero(state, state.state->skip) == -1) if (gz_zero(state, state.state->skip) == -1)
return 0; return state.state->error;
} }
/* consume whatever's left in the input buffer */ /* do the printf() into the input buffer, put length in len -- the input
if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) buffer is double-sized just for this function, so there is guaranteed to
return 0; be state.state->size bytes available after the current contents */
if (strm->avail_in == 0)
/* do the printf() into the input buffer, put length in len */ strm->next_in = state.state->in;
size = (int)(state.state->size); next = (char *)(strm->next_in + strm->avail_in);
state.state->in[size - 1] = 0; next[state.state->size - 1] = 0;
#ifdef NO_snprintf #ifdef NO_snprintf
# ifdef HAS_sprintf_void # ifdef HAS_sprintf_void
sprintf((char *)(state.state->in), format, a1, a2, a3, a4, a5, a6, a7, a8, sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12,
a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); a13, a14, a15, a16, a17, a18, a19, a20);
for (len = 0; len < size; len++) for (len = 0; len < size; len++)
if (state.state->in[len] == 0) break; if (next[len] == 0)
break;
# else # else
len = sprintf((char *)(state.state->in), format, a1, a2, a3, a4, a5, a6, a7, a8, len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11,
a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); a12, a13, a14, a15, a16, a17, a18, a19, a20);
# endif # endif
#else #else
# ifdef HAS_snprintf_void # ifdef HAS_snprintf_void
snprintf((char *)(state.state->in), size, format, a1, a2, a3, a4, a5, a6, a7, a8, snprintf(next, state.state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9,
a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
len = strlen((char *)(state.state->in)); len = strlen(next);
# else # else
len = snprintf((char *)(state.state->in), size, format, a1, a2, a3, a4, a5, a6, len = snprintf(next, state.state->size, format, a1, a2, a3, a4, a5, a6, a7, a8,
a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
a19, a20);
# endif # endif
#endif #endif
/* check that printf() results fit in buffer */ /* check that printf() results fit in buffer */
if (len <= 0 || len >= (int)size || state.state->in[size - 1] != 0) if (len == 0 || len >= state.state->size || next[state.state->size - 1] != 0)
return 0; return 0;
/* update buffer and position, defer compression until needed */ /* update buffer and position, compress first half if past that */
strm->avail_in = (unsigned)len; strm->avail_in += len;
strm->next_in = state.state->in;
state.state->x.pos += len; state.state->x.pos += len;
return len; if (strm->avail_in >= state.state->size) {
left = strm->avail_in - state.state->size;
strm->avail_in = state.state->size;
if (gz_comp(state, Z_NO_FLUSH) == -1)
return state.state->err;
memcpy(state.state->in, state.state->in + state.state->size, left);
strm->next_in = state.state->in;
strm->avail_in = left;
}
return (int)len;
} }
#endif #endif
@ -473,7 +561,7 @@ int ZEXPORT gzflush(file, flush)
/* get internal structure */ /* get internal structure */
if (file == NULL) if (file == NULL)
return -1; return Z_STREAM_ERROR;
state = (gz_statep)file; state = (gz_statep)file;
/* check that we're writing and that there's no error */ /* check that we're writing and that there's no error */
@ -488,11 +576,11 @@ int ZEXPORT gzflush(file, flush)
if (state.state->seek) { if (state.state->seek) {
state.state->seek = 0; state.state->seek = 0;
if (gz_zero(state, state.state->skip) == -1) if (gz_zero(state, state.state->skip) == -1)
return -1; return state.state->err;
} }
/* compress remaining data with requested flush */ /* compress remaining data with requested flush */
gz_comp(state, flush); (void)gz_comp(state, flush);
return state.state->err; return state.state->err;
} }
@ -523,13 +611,13 @@ int ZEXPORT gzsetparams(file, level, strategy)
if (state.state->seek) { if (state.state->seek) {
state.state->seek = 0; state.state->seek = 0;
if (gz_zero(state, state.state->skip) == -1) if (gz_zero(state, state.state->skip) == -1)
return -1; return state.state->err;
} }
/* change compression parameters for subsequent input */ /* change compression parameters for subsequent input */
if (state.state->size) { if (state.state->size) {
/* flush previous input with previous parameters before changing */ /* flush previous input with previous parameters before changing */
if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1) if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1)
return state.state->err; return state.state->err;
deflateParams(strm, level, strategy); deflateParams(strm, level, strategy);
} }