Update a few remaining zlib source files

This commit is contained in:
Justine Tunney 2022-10-03 19:18:34 -07:00
parent 32321ab1e9
commit 01bd7d1008
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
23 changed files with 1276 additions and 778 deletions

View file

@ -1,22 +1,26 @@
#include "third_party/zlib/gz/gzguts.inc"
// clang-format off
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=4 sts=4 sw=4 fenc=utf-8 :vi
*/
/* gzclose.c -- zlib gzclose() function
* Copyright (C) 2004, 2010 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include "third_party/zlib/gz/gzguts.inc"
#include "third_party/zlib/macros.internal.h"
asm(".ident\t\"\\n\\n\
zlib (zlib License)\\n\
Copyright 1995-2017 Jean-loup Gailly and Mark Adler\"");
asm(".include \"libc/disclaimer.inc\"");
// clang-format off
/* gzclose() is in a separate file so that it is linked in only if it is used.
That way the other gzclose functions can be used instead to avoid linking in
unneeded compression or decompression routines. */
int gzclose(file)
int ZEXPORT gzclose(file)
gzFile file;
{
#ifndef NO_GZCOMPRESS
gz_statep state;
if (file == NULL)
@ -24,4 +28,7 @@ int gzclose(file)
state = (gz_statep)file;
return state->mode == GZ_READ ? gzclose_r(file) : gzclose_w(file);
#else
return gzclose_r(file);
#endif
}

View file

@ -1,7 +1,9 @@
#include "libc/errno.h"
#include "libc/limits.h"
#include "libc/str/str.h"
#include "third_party/zlib/macros.internal.h"
#include "third_party/zlib/zlib.h"
#include "third_party/zlib/zutil.internal.h"
// clang-format off
/* gzguts.h -- zlib internal header definitions for gz* operations
@ -18,7 +20,6 @@
# endif
#endif
#define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
#define _POSIX_SOURCE
#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550)
@ -81,14 +82,15 @@ typedef struct {
int direct; /* 0 if processing gzip, 1 if transparent */
/* just for reading */
int how; /* 0: get header, 1: copy, 2: decompress */
int64_t start; /* where the gzip data started, for rewinding */
z_off64_t start; /* where the gzip data started, for rewinding */
int eof; /* true if end of input file reached */
int past; /* true if read requested past end */
/* just for writing */
int level; /* compression level */
int strategy; /* compression strategy */
int reset; /* true if a reset is pending after a Z_FINISH */
/* seek request */
int64_t skip; /* amount to skip (already rewound if backwards) */
z_off64_t skip; /* amount to skip (already rewound if backwards) */
int seek; /* true if seek request pending */
/* error information */
int err; /* error code */
@ -96,20 +98,20 @@ typedef struct {
/* zlib inflate or deflate stream */
z_stream strm; /* stream structure in-place (not a pointer) */
} gz_state;
typedef gz_state *gz_statep;
typedef gz_state FAR *gz_statep;
/* shared functions */
void ZLIB_INTERNAL gz_error (gz_statep, int, const char *);
void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *));
#if defined UNDER_CE
char ZLIB_INTERNAL *gz_strwinerror (DWORD error);
char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error));
#endif
/* GT_OFF(x), where x is an unsigned value, is true if x > maximum int64_t
value -- needed when comparing unsigned to int64_t, which is signed
(possible int64_t types off_t, off64_t, and long are all signed) */
/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t
value -- needed when comparing unsigned to z_off64_t, which is signed
(possible z_off64_t types off_t, off64_t, and long are all signed) */
#ifdef INT_MAX
# define GT_OFF(x) (sizeof(int) == sizeof(int64_t) && (x) > INT_MAX)
# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX)
#else
unsigned ZLIB_INTERNAL gz_intmax (void);
# define GT_OFF(x) (sizeof(int) == sizeof(int64_t) && (x) > gz_intmax())
unsigned ZLIB_INTERNAL gz_intmax OF((void));
# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax())
#endif

View file

@ -1,3 +1,10 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=4 sts=4 sw=4 fenc=utf-8 :vi
*/
/* gzlib.c -- zlib functions common to reading and writing gzip files
* Copyright (C) 2004-2017 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include "libc/calls/calls.h"
#include "libc/fmt/fmt.h"
#include "libc/limits.h"
@ -6,24 +13,22 @@
#include "libc/sysv/consts/o.h"
#include "third_party/zlib/gz/gzguts.inc"
#include "third_party/zlib/zlib.h"
// clang-format off
#include "third_party/zlib/zutil.internal.h"
/* gzlib.c -- zlib functions common to reading and writing gzip files
* Copyright (C) 2004-2017 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#define LSEEK lseek
asm(".ident\t\"\\n\\n\
zlib (zlib License)\\n\
Copyright 1995-2017 Jean-loup Gailly and Mark Adler\"");
asm(".include \"libc/disclaimer.inc\"");
// clang-format off
/* Local functions */
static void gz_reset(gz_statep);
static gzFile gz_open(const void *, int, const char *);
/* Reset gzip file state */
static void gz_reset(state)
local void gz_reset(state)
gz_statep state;
{
state->x.have = 0; /* no output data available */
@ -32,6 +37,8 @@ static void gz_reset(state)
state->past = 0; /* have not read past end yet */
state->how = LOOK; /* look for gzip header */
}
else /* for writing ... */
state->reset = 0; /* no deflateReset pending */
state->seek = 0; /* no seek request pending */
gz_error(state, Z_OK, NULL); /* clear error */
state->x.pos = 0; /* no uncompressed data yet */
@ -39,16 +46,20 @@ static void gz_reset(state)
}
/* Open a gzip file either by name or file descriptor. */
static gzFile gz_open(path, fd, mode)
local gzFile gz_open(path, fd, mode)
const void *path;
int fd;
const char *mode;
{
gz_statep state;
size_t len;
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)
@ -75,23 +86,29 @@ static gzFile gz_open(path, fd, mode)
case 'r':
state->mode = GZ_READ;
break;
#ifndef NO_GZCOMPRESS
case 'w':
state->mode = GZ_WRITE;
break;
case 'a':
state->mode = GZ_APPEND;
break;
#endif
case '+': /* can't read and write at the same time */
free(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->strategy = Z_FILTERED;
break;
@ -129,27 +146,60 @@ static gzFile gz_open(path, fd, mode)
}
/* save the path name for error messages */
len = strlen((const char *)path);
#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->path = (char *)malloc(len + 1);
if (state->path == NULL) {
free(state);
return NULL;
}
snprintf(state->path, len + 1, "%s", (const char *)path);
#ifdef WIDECHAR
if (fd == -2)
if (len)
wcstombs(state->path, path, len + 1);
else
*(state->path) = 0;
else
#endif
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
(void)snprintf(state->path, len + 1, "%s", (const char *)path);
#else
strcpy(state->path, 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->mode == GZ_READ ?
O_RDONLY :
(O_WRONLY | O_CREAT |
#ifdef O_EXCL
(exclusive ? O_EXCL : 0) |
#endif
(state->mode == GZ_WRITE ?
O_TRUNC :
O_APPEND)));
/* open the file with the appropriate flags (or just use fd) */
state->fd = fd > -1 ? fd : (
#ifdef WIDECHAR
fd == -2 ? _wopen(path, oflag, 0666) :
#endif
open((const char *)path, oflag, 0666));
if (state->fd == -1) {
free(state->path);
@ -157,13 +207,13 @@ static gzFile gz_open(path, fd, mode)
return NULL;
}
if (state->mode == GZ_APPEND) {
lseek(state->fd, 0, SEEK_END); /* so gzoffset() is correct */
LSEEK(state->fd, 0, SEEK_END); /* so gzoffset() is correct */
state->mode = GZ_WRITE; /* simplify later checks */
}
/* save the current position for rewinding (only if reading) */
if (state->mode == GZ_READ) {
state->start = lseek(state->fd, 0, SEEK_CUR);
state->start = LSEEK(state->fd, 0, SEEK_CUR);
if (state->start == -1) state->start = 0;
}
@ -175,7 +225,7 @@ static gzFile gz_open(path, fd, mode)
}
/* -- see zlib.h -- */
gzFile gzopen(path, mode)
gzFile ZEXPORT gzopen(path, mode)
const char *path;
const char *mode;
{
@ -183,7 +233,7 @@ gzFile gzopen(path, mode)
}
/* -- see zlib.h -- */
gzFile gzopen64(path, mode)
gzFile ZEXPORT gzopen64(path, mode)
const char *path;
const char *mode;
{
@ -191,7 +241,7 @@ gzFile gzopen64(path, mode)
}
/* -- see zlib.h -- */
gzFile gzdopen(fd, mode)
gzFile ZEXPORT gzdopen(fd, mode)
int fd;
const char *mode;
{
@ -203,7 +253,7 @@ gzFile gzdopen(fd, mode)
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
(void)snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd);
#else
sprintf(path, "<%s:%d>", "fd", fd); /* for debugging */
sprintf(path, "<fd:%d>", fd); /* for debugging */
#endif
gz = gz_open(path, fd, mode);
free(path);
@ -211,7 +261,17 @@ gzFile gzdopen(fd, mode)
}
/* -- see zlib.h -- */
int gzbuffer(file, size)
#ifdef WIDECHAR
gzFile ZEXPORT gzopen_w(path, mode)
const wchar_t *path;
const char *mode;
{
return gz_open(path, -2, mode);
}
#endif
/* -- see zlib.h -- */
int ZEXPORT gzbuffer(file, size)
gzFile file;
unsigned size;
{
@ -238,7 +298,7 @@ int gzbuffer(file, size)
}
/* -- see zlib.h -- */
int gzrewind(file)
int ZEXPORT gzrewind(file)
gzFile file;
{
gz_statep state;
@ -254,20 +314,20 @@ int gzrewind(file)
return -1;
/* back up and start over */
if (lseek(state->fd, state->start, SEEK_SET) == -1)
if (LSEEK(state->fd, state->start, SEEK_SET) == -1)
return -1;
gz_reset(state);
return 0;
}
/* -- see zlib.h -- */
int64_t gzseek64(file, offset, whence)
z_off64_t ZEXPORT gzseek64(file, offset, whence)
gzFile file;
int64_t offset;
z_off64_t offset;
int whence;
{
unsigned n;
int64_t ret;
z_off64_t ret;
gz_statep state;
/* get internal structure and check integrity */
@ -295,7 +355,7 @@ int64_t gzseek64(file, offset, whence)
/* if within raw area while reading, just go there */
if (state->mode == GZ_READ && state->how == COPY &&
state->x.pos + offset >= 0) {
ret = lseek(state->fd, offset - state->x.have, SEEK_CUR);
ret = LSEEK(state->fd, offset - (z_off64_t)state->x.have, SEEK_CUR);
if (ret == -1)
return -1;
state->x.have = 0;
@ -321,7 +381,7 @@ int64_t gzseek64(file, offset, whence)
/* if reading, skip what's in output buffer (one less gzgetc() check) */
if (state->mode == GZ_READ) {
n = GT_OFF(state->x.have) || (int64_t)state->x.have > offset ?
n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ?
(unsigned)offset : state->x.have;
state->x.have -= n;
state->x.next += n;
@ -338,19 +398,19 @@ int64_t gzseek64(file, offset, whence)
}
/* -- see zlib.h -- */
int64_t gzseek(file, offset, whence)
z_off_t ZEXPORT gzseek(file, offset, whence)
gzFile file;
int64_t offset;
z_off_t offset;
int whence;
{
int64_t ret;
z_off64_t ret;
ret = gzseek64(file, (int64_t)offset, whence);
return ret == (int64_t)ret ? (int64_t)ret : -1;
ret = gzseek64(file, (z_off64_t)offset, whence);
return ret == (z_off_t)ret ? (z_off_t)ret : -1;
}
/* -- see zlib.h -- */
int64_t gztell64(file)
z_off64_t ZEXPORT gztell64(file)
gzFile file;
{
gz_statep state;
@ -367,20 +427,20 @@ int64_t gztell64(file)
}
/* -- see zlib.h -- */
int64_t gztell(file)
z_off_t ZEXPORT gztell(file)
gzFile file;
{
int64_t ret;
z_off64_t ret;
ret = gztell64(file);
return ret == (int64_t)ret ? (int64_t)ret : -1;
return ret == (z_off_t)ret ? (z_off_t)ret : -1;
}
/* -- see zlib.h -- */
int64_t gzoffset64(file)
z_off64_t ZEXPORT gzoffset64(file)
gzFile file;
{
int64_t offset;
z_off64_t offset;
gz_statep state;
/* get internal structure and check integrity */
@ -391,7 +451,7 @@ int64_t gzoffset64(file)
return -1;
/* compute and return effective offset in file */
offset = lseek(state->fd, 0, SEEK_CUR);
offset = LSEEK(state->fd, 0, SEEK_CUR);
if (offset == -1)
return -1;
if (state->mode == GZ_READ) /* reading */
@ -400,17 +460,17 @@ int64_t gzoffset64(file)
}
/* -- see zlib.h -- */
int64_t gzoffset(file)
z_off_t ZEXPORT gzoffset(file)
gzFile file;
{
int64_t ret;
z_off64_t ret;
ret = gzoffset64(file);
return ret == (int64_t)ret ? (int64_t)ret : -1;
return ret == (z_off_t)ret ? (z_off_t)ret : -1;
}
/* -- see zlib.h -- */
int gzeof(file)
int ZEXPORT gzeof(file)
gzFile file;
{
gz_statep state;
@ -427,7 +487,7 @@ int gzeof(file)
}
/* -- see zlib.h -- */
const char * gzerror(file, errnum)
const char * ZEXPORT gzerror(file, errnum)
gzFile file;
int *errnum;
{
@ -448,7 +508,7 @@ const char * gzerror(file, errnum)
}
/* -- see zlib.h -- */
void gzclearerr(file)
void ZEXPORT gzclearerr(file)
gzFile file;
{
gz_statep state;
@ -505,6 +565,31 @@ void ZLIB_INTERNAL gz_error(state, err, msg)
state->err = Z_MEM_ERROR;
return;
}
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
(void)snprintf(state->msg, strlen(state->path) + strlen(msg) + 3,
"%s%s%s", state->path, ": ", msg);
#else
strcpy(state->msg, state->path);
strcat(state->msg, ": ");
strcat(state->msg, msg);
#endif
}
#ifndef INT_MAX
/* portably return maximum value for an int (when limits.h presumed not
available) -- we need to do this to cover cases where 2's complement not
used, since C standard permits 1's complement and sign-bit representations,
otherwise we could just use ((unsigned)-1) >> 1 */
unsigned ZLIB_INTERNAL gz_intmax()
{
unsigned p, q;
p = 1;
do {
q = p;
p <<= 1;
p++;
} while (p > q);
return q >> 1;
}
#endif

View file

@ -1,3 +1,10 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=4 sts=4 sw=4 fenc=utf-8 :vi
*/
/* gzread.c -- zlib functions for reading gzip files
* Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include "libc/calls/calls.h"
#include "libc/errno.h"
#include "libc/limits.h"
@ -5,32 +12,27 @@
#include "libc/str/str.h"
#include "third_party/zlib/gz/gzguts.inc"
#include "third_party/zlib/zlib.h"
// clang-format off
/* gzread.c -- zlib functions for reading gzip files
* Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
asm(".ident\t\"\\n\\n\
zlib (zlib License)\\n\
Copyright 1995-2017 Jean-loup Gailly and Mark Adler\"");
asm(".include \"libc/disclaimer.inc\"");
// clang-format off
/* Static functions */
static int gz_load(gz_statep, unsigned char *, unsigned, unsigned *);
static int gz_avail(gz_statep);
static int gz_look(gz_statep);
static int gz_decomp(gz_statep);
static int gz_fetch(gz_statep);
static int gz_skip(gz_statep, int64_t);
static size_t gz_read(gz_statep, voidp, size_t);
/* Local functions */
local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *));
local int gz_avail OF((gz_statep));
local int gz_look OF((gz_statep));
local int gz_decomp OF((gz_statep));
local int gz_fetch OF((gz_statep));
local int gz_skip OF((gz_statep, z_off64_t));
local z_size_t gz_read OF((gz_statep, voidp, z_size_t));
/* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from
state->fd, and update state->eof, state->err, and state->msg as appropriate.
This function needs to loop on read(), since read() is not guaranteed to
read the number of bytes requested, depending on the type of descriptor. */
static int gz_load(state, buf, len, have)
local int gz_load(state, buf, len, have)
gz_statep state;
unsigned char *buf;
unsigned len;
@ -65,7 +67,7 @@ static int gz_load(state, buf, len, have)
If strm->avail_in != 0, then the current data is moved to the beginning of
the input buffer, and then the remainder of the buffer is loaded with the
available data from the input file. */
static int gz_avail(state)
local int gz_avail(state)
gz_statep state;
{
unsigned got;
@ -100,7 +102,7 @@ static int gz_avail(state)
case, all further file reads will be directly to either the output buffer or
a user buffer. If decompressing, the inflate state will be initialized.
gz_look() will return 0 on success or -1 on failure. */
static int gz_look(state)
local int gz_look(state)
gz_statep state;
{
z_streamp strm = &(state->strm);
@ -184,7 +186,7 @@ static int gz_look(state)
data. If the gzip stream completes, state->how is reset to LOOK to look for
the next gzip stream or raw data, once state->x.have is depleted. Returns 0
on success, -1 on failure. */
static int gz_decomp(state)
local int gz_decomp(state)
gz_statep state;
{
int ret = Z_OK;
@ -238,7 +240,7 @@ static int gz_decomp(state)
looked for to determine whether to copy or decompress. Returns -1 on error,
otherwise 0. gz_fetch() will leave state->how as COPY or GZIP unless the
end of the input file has been reached and all data has been processed. */
static int gz_fetch(state)
local int gz_fetch(state)
gz_statep state;
{
z_streamp strm = &(state->strm);
@ -268,9 +270,9 @@ static int gz_fetch(state)
}
/* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */
static int gz_skip(state, len)
local int gz_skip(state, len)
gz_statep state;
int64_t len;
z_off64_t len;
{
unsigned n;
@ -278,7 +280,7 @@ static int gz_skip(state, len)
while (len)
/* skip over whatever is in output buffer */
if (state->x.have) {
n = GT_OFF(state->x.have) || (int64_t)state->x.have > len ?
n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ?
(unsigned)len : state->x.have;
state->x.have -= n;
state->x.next += n;
@ -303,12 +305,12 @@ static int gz_skip(state, len)
input. Return the number of bytes read. If zero is returned, either the
end of file was reached, or there was an error. state->err must be
consulted in that case to determine which. */
static size_t gz_read(state, buf, len)
local z_size_t gz_read(state, buf, len)
gz_statep state;
voidp buf;
size_t len;
z_size_t len;
{
size_t got;
z_size_t got;
unsigned n;
/* if len is zero, avoid unnecessary operations */
@ -326,9 +328,9 @@ static size_t gz_read(state, buf, len)
got = 0;
do {
/* set n to the maximum amount of len that fits in an unsigned int */
n = -1;
n = (unsigned)-1;
if (n > len)
n = len;
n = (unsigned)len;
/* first just try copying data from the output buffer */
if (state->x.have) {
@ -384,7 +386,7 @@ static size_t gz_read(state, buf, len)
}
/* -- see zlib.h -- */
int gzread(file, buf, len)
int ZEXPORT gzread(file, buf, len)
gzFile file;
voidp buf;
unsigned len;
@ -409,7 +411,7 @@ int gzread(file, buf, len)
}
/* read len or fewer bytes to buf */
len = gz_read(state, buf, len);
len = (unsigned)gz_read(state, buf, len);
/* check for an error */
if (len == 0 && state->err != Z_OK && state->err != Z_BUF_ERROR)
@ -420,13 +422,13 @@ int gzread(file, buf, len)
}
/* -- see zlib.h -- */
size_t gzfread(buf, size, nitems, file)
z_size_t ZEXPORT gzfread(buf, size, nitems, file)
voidp buf;
size_t size;
size_t nitems;
z_size_t size;
z_size_t nitems;
gzFile file;
{
size_t len;
z_size_t len;
gz_statep state;
/* get internal structure */
@ -460,10 +462,9 @@ size_t gzfread(buf, size, nitems, file)
# endif
#endif
int gzgetc(file)
int ZEXPORT gzgetc(file)
gzFile file;
{
int ret;
unsigned char buf[1];
gz_statep state;
@ -485,18 +486,17 @@ int gzgetc(file)
}
/* nothing there -- try gz_read() */
ret = gz_read(state, buf, 1);
return ret < 1 ? -1 : buf[0];
return gz_read(state, buf, 1) < 1 ? -1 : buf[0];
}
int gzgetc_(file)
int ZEXPORT gzgetc_(file)
gzFile file;
{
return gzgetc(file);
}
/* -- see zlib.h -- */
int gzungetc(c, file)
int ZEXPORT gzungetc(c, file)
int c;
gzFile file;
{
@ -556,7 +556,7 @@ int gzungetc(c, file)
}
/* -- see zlib.h -- */
char * gzgets(file, buf, len)
char * ZEXPORT gzgets(file, buf, len)
gzFile file;
char *buf;
int len;
@ -620,7 +620,7 @@ char * gzgets(file, buf, len)
}
/* -- see zlib.h -- */
int gzdirect(file)
int ZEXPORT gzdirect(file)
gzFile file;
{
gz_statep state;
@ -640,7 +640,7 @@ int gzdirect(file)
}
/* -- see zlib.h -- */
int gzclose_r(file)
int ZEXPORT gzclose_r(file)
gzFile file;
{
int ret, err;

View file

@ -1,29 +1,31 @@
#include "libc/calls/calls.h"
#include "libc/fmt/fmt.h"
#include "libc/mem/mem.h"
#include "third_party/zlib/gz/gzguts.inc"
// clang-format off
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=4 sts=4 sw=4 fenc=utf-8 :vi
*/
/* gzwrite.c -- zlib functions for writing gzip files
* Copyright (C) 2004-2017 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include "libc/calls/calls.h"
#include "libc/fmt/fmt.h"
#include "libc/mem/mem.h"
#include "third_party/zlib/gz/gzguts.inc"
asm(".ident\t\"\\n\\n\
zlib (zlib License)\\n\
Copyright 1995-2017 Jean-loup Gailly and Mark Adler\"");
asm(".include \"libc/disclaimer.inc\"");
// clang-format off
/* Static functions */
static int gz_init(gz_statep);
static int gz_comp(gz_statep, int);
static int gz_zero(gz_statep, int64_t);
static size_t gz_write(gz_statep, voidpc, size_t);
/* Local functions */
local int gz_init OF((gz_statep));
local int gz_comp OF((gz_statep, int));
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
state->size to non-zero. Return -1 on a memory allocation failure, or 0 on
success. */
static int gz_init(state)
local int gz_init(state)
gz_statep state;
{
int ret;
@ -79,7 +81,7 @@ static int gz_init(state)
deflate() flush value. If flush is Z_FINISH, then the deflate() state is
reset to start a new gzip stream. If gz->direct is true, then simply write
to the output file without compressing, and ignore flush. */
static int gz_comp(state, flush)
local int gz_comp(state, flush)
gz_statep state;
int flush;
{
@ -106,6 +108,15 @@ static int gz_comp(state, flush)
return 0;
}
/* check for a pending reset */
if (state->reset) {
/* don't start a new gzip member unless there is data to write */
if (strm->avail_in == 0)
return 0;
deflateReset(strm);
state->reset = 0;
}
/* run deflate() on provided input until it produces no more output */
ret = Z_OK;
do {
@ -143,7 +154,7 @@ static int gz_comp(state, flush)
/* if that completed a deflate stream, allow another to start */
if (flush == Z_FINISH)
deflateReset(strm);
state->reset = 1;
/* all done, no errors */
return 0;
@ -151,9 +162,9 @@ static int gz_comp(state, flush)
/* Compress len zeros to output. Return -1 on a write error or memory
allocation failure by gz_comp(), or 0 on success. */
static int gz_zero(state, len)
local int gz_zero(state, len)
gz_statep state;
int64_t len;
z_off64_t len;
{
int first;
unsigned n;
@ -166,7 +177,7 @@ static int gz_zero(state, len)
/* compress len zeros (len guaranteed > 0) */
first = 1;
while (len) {
n = GT_OFF(state->size) || (int64_t)state->size > len ?
n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
(unsigned)len : state->size;
if (first) {
memset(state->in, 0, n);
@ -184,12 +195,12 @@ static int gz_zero(state, len)
/* Write len bytes from buf to file. Return the number of bytes written. If
the returned value is less than len, then there was an error. */
static size_t gz_write(state, buf, len)
local z_size_t gz_write(state, buf, len)
gz_statep state;
voidpc buf;
size_t len;
z_size_t len;
{
size_t put = len;
z_size_t put = len;
/* if len is zero, avoid unnecessary operations */
if (len == 0)
@ -218,7 +229,7 @@ static size_t gz_write(state, buf, len)
state->in);
copy = state->size - have;
if (copy > len)
copy = len;
copy = (unsigned)len;
memcpy(state->in + have, buf, copy);
state->strm.avail_in += copy;
state->x.pos += copy;
@ -234,11 +245,11 @@ static size_t gz_write(state, buf, len)
return 0;
/* directly compress user buffer to file */
state->strm.next_in = (const Bytef *)buf;
state->strm.next_in = (Bytef *)buf;
do {
unsigned n = (unsigned)-1;
if (n > len)
n = len;
n = (unsigned)len;
state->strm.avail_in = n;
state->x.pos += n;
if (gz_comp(state, Z_NO_FLUSH) == -1)
@ -252,7 +263,7 @@ static size_t gz_write(state, buf, len)
}
/* -- see zlib.h -- */
int gzwrite(file, buf, len)
int ZEXPORT gzwrite(file, buf, len)
gzFile file;
voidpc buf;
unsigned len;
@ -280,13 +291,13 @@ int gzwrite(file, buf, len)
}
/* -- see zlib.h -- */
size_t gzfwrite(buf, size, nitems, file)
z_size_t ZEXPORT gzfwrite(buf, size, nitems, file)
voidpc buf;
size_t size;
size_t nitems;
z_size_t size;
z_size_t nitems;
gzFile file;
{
size_t len;
z_size_t len;
gz_statep state;
/* get internal structure */
@ -310,7 +321,7 @@ size_t gzfwrite(buf, size, nitems, file)
}
/* -- see zlib.h -- */
int gzputc(file, c)
int ZEXPORT gzputc(file, c)
gzFile file;
int c;
{
@ -358,12 +369,11 @@ int gzputc(file, c)
}
/* -- see zlib.h -- */
int gzputs(file, str)
int ZEXPORT gzputs(file, s)
gzFile file;
const char *str;
const char *s;
{
int ret;
size_t len;
z_size_t len, put;
gz_statep state;
/* get internal structure */
@ -376,13 +386,19 @@ int gzputs(file, str)
return -1;
/* write string */
len = strlen(str);
ret = gz_write(state, str, len);
return ret == 0 && len != 0 ? -1 : ret;
len = strlen(s);
if ((int)len < 0 || (unsigned)len != len) {
gz_error(state, Z_STREAM_ERROR, "string length does not fit in int");
return -1;
}
put = gz_write(state, s, len);
return put < len ? -1 : (int)len;
}
#if defined(STDC) || defined(Z_HAVE_STDARG_H)
/* -- see zlib.h -- */
int gzvprintf(gzFile file, const char *format, va_list va)
int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va)
{
int len;
unsigned left;
@ -418,7 +434,22 @@ int gzvprintf(gzFile file, const char *format, va_list va)
strm->next_in = state->in;
next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in);
next[state->size - 1] = 0;
len = (vsnprintf)(next, state->size, format, va);
#ifdef NO_vsnprintf
# ifdef HAS_vsprintf_void
(void)vsprintf(next, format, va);
for (len = 0; len < state->size; len++)
if (next[len] == 0) break;
# else
len = vsprintf(next, format, va);
# endif
#else
# ifdef HAS_vsnprintf_void
(void)vsnprintf(next, state->size, format, va);
len = strlen(next);
# else
len = vsnprintf(next, state->size, format, va);
# endif
#endif
/* check that printf() results fit in buffer */
if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0)
@ -432,14 +463,14 @@ int gzvprintf(gzFile file, const char *format, va_list va)
strm->avail_in = state->size;
if (gz_comp(state, Z_NO_FLUSH) == -1)
return state->err;
memcpy(state->in, state->in + state->size, left);
memmove(state->in, state->in + state->size, left);
strm->next_in = state->in;
strm->avail_in = left;
}
return len;
}
int gzprintf(gzFile file, const char *format, ...)
int ZEXPORTVA gzprintf(gzFile file, const char *format, ...)
{
va_list va;
int ret;
@ -450,8 +481,98 @@ int gzprintf(gzFile file, const char *format, ...)
return ret;
}
#else /* !STDC && !Z_HAVE_STDARG_H */
/* -- see zlib.h -- */
int gzflush(file, flush)
int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
gzFile file;
const char *format;
int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
{
unsigned len, left;
char *next;
gz_statep state;
z_streamp strm;
/* get internal structure */
if (file == NULL)
return Z_STREAM_ERROR;
state = (gz_statep)file;
strm = &(state->strm);
/* check that can really pass pointer in ints */
if (sizeof(int) != sizeof(void *))
return Z_STREAM_ERROR;
/* check that we're writing and that there's no error */
if (state->mode != GZ_WRITE || state->err != Z_OK)
return Z_STREAM_ERROR;
/* make sure we have some buffer space */
if (state->size == 0 && gz_init(state) == -1)
return state->error;
/* check for seek request */
if (state->seek) {
state->seek = 0;
if (gz_zero(state, state->skip) == -1)
return state->error;
}
/* do the printf() into the input buffer, put length in len -- the input
buffer is double-sized just for this function, so there is guaranteed to
be state->size bytes available after the current contents */
if (strm->avail_in == 0)
strm->next_in = state->in;
next = (char *)(strm->next_in + strm->avail_in);
next[state->size - 1] = 0;
#ifdef NO_snprintf
# ifdef HAS_sprintf_void
sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12,
a13, a14, a15, a16, a17, a18, a19, a20);
for (len = 0; len < size; len++)
if (next[len] == 0)
break;
# else
len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11,
a12, a13, a14, a15, a16, a17, a18, a19, a20);
# endif
#else
# ifdef HAS_snprintf_void
snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9,
a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
len = strlen(next);
# else
len = snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8,
a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
# endif
#endif
/* check that printf() results fit in buffer */
if (len == 0 || len >= state->size || next[state->size - 1] != 0)
return 0;
/* update buffer and position, compress first half if past that */
strm->avail_in += len;
state->x.pos += len;
if (strm->avail_in >= state->size) {
left = strm->avail_in - state->size;
strm->avail_in = state->size;
if (gz_comp(state, Z_NO_FLUSH) == -1)
return state->err;
memmove(state->in, state->in + state->size, left);
strm->next_in = state->in;
strm->avail_in = left;
}
return (int)len;
}
#endif
/* -- see zlib.h -- */
int ZEXPORT gzflush(file, flush)
gzFile file;
int flush;
{
@ -483,7 +604,7 @@ int gzflush(file, flush)
}
/* -- see zlib.h -- */
int gzsetparams(file, level, strategy)
int ZEXPORT gzsetparams(file, level, strategy)
gzFile file;
int level;
int strategy;
@ -525,7 +646,7 @@ int gzsetparams(file, level, strategy)
}
/* -- see zlib.h -- */
int gzclose_w(file)
int ZEXPORT gzclose_w(file)
gzFile file;
{
int ret = Z_OK;