commit
4ab3a4228f
|
@ -6,30 +6,48 @@
|
|||
|
||||
|
||||
# Paths to static and dynamic zlib and zstd libraries
|
||||
# Use "make ZLIB_LIBRARY=path/to/zlib" to select a path to library
|
||||
# Use "make ZLIB_PATH=path/to/zlib ZLIB_LIBRARY=path/to/libz.a" to select a path to library
|
||||
ZLIB_LIBRARY ?= -lz
|
||||
ZLIB_PATH ?= .
|
||||
|
||||
ZSTDLIBDIR = ../lib
|
||||
ZSTDLIBRARY = $(ZSTDLIBDIR)/libzstd.a
|
||||
ZLIBWRAPPER_PATH = .
|
||||
GZFILES = gzclose.o gzlib.o gzread.o gzwrite.o
|
||||
EXAMPLE_PATH = examples
|
||||
PROGRAMS_PATH = ../programs
|
||||
TEST_FILE = ../doc/zstd_compression_format.md
|
||||
|
||||
CPPFLAGS = -DXXH_NAMESPACE=XXH_ -I$(PROGRAMS_PATH) -I$(ZSTDLIBDIR) -I$(ZSTDLIBDIR)/common -I$(ZLIBWRAPPER_PATH)
|
||||
CPPFLAGS = -DXXH_NAMESPACE=XXH_ -I$(ZLIB_PATH) -I$(PROGRAMS_PATH) -I$(ZSTDLIBDIR) -I$(ZSTDLIBDIR)/common -I$(ZLIBWRAPPER_PATH)
|
||||
CFLAGS ?= $(MOREFLAGS) -O3 -std=gnu99
|
||||
CFLAGS += -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow -Wswitch-enum -Wdeclaration-after-statement -Wstrict-prototypes -Wstrict-aliasing=1 -Wundef
|
||||
CFLAGS += -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow -Wswitch-enum -Wdeclaration-after-statement -Wstrict-prototypes -Wundef -Wstrict-aliasing=1
|
||||
|
||||
|
||||
all: clean fitblk example zwrapbench
|
||||
# Define *.exe as extension for Windows systems
|
||||
ifneq (,$(filter Windows%,$(OS)))
|
||||
EXT =.exe
|
||||
else
|
||||
EXT =
|
||||
endif
|
||||
|
||||
test: example fitblk example_zstd fitblk_zstd zwrapbench
|
||||
|
||||
all: clean fitblk example zwrapbench minigzip
|
||||
|
||||
test: example fitblk example_zstd fitblk_zstd zwrapbench minigzip minigzip_zstd
|
||||
./example
|
||||
./example_zstd
|
||||
./fitblk 10240 <$(TEST_FILE)
|
||||
./fitblk 40960 <$(TEST_FILE)
|
||||
./fitblk_zstd 10240 <$(TEST_FILE)
|
||||
./fitblk_zstd 40960 <$(TEST_FILE)
|
||||
@echo ---- minigzip start ----
|
||||
./minigzip_zstd example$(EXT)
|
||||
cp example$(EXT).gz example$(EXT)_zstd.gz
|
||||
./minigzip_zstd -d example$(EXT).gz
|
||||
./minigzip example$(EXT)
|
||||
cp example$(EXT).gz example$(EXT)_gz.gz
|
||||
./minigzip_zstd -d example$(EXT).gz
|
||||
@echo ---- minigzip end ----
|
||||
./zwrapbench -qb3B1K $(TEST_FILE)
|
||||
./zwrapbench -rqb1e5 ../lib ../programs ../tests
|
||||
|
||||
|
@ -49,22 +67,27 @@ valgrindTest: clean example fitblk example_zstd fitblk_zstd zwrapbench
|
|||
#.c.o:
|
||||
# $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
|
||||
|
||||
example: $(EXAMPLE_PATH)/example.o $(ZLIBWRAPPER_PATH)/zstd_zlibwrapper.o $(ZSTDLIBRARY)
|
||||
$(CC) $(LDFLAGS) -o $@ $(EXAMPLE_PATH)/example.o $(ZLIBWRAPPER_PATH)/zstd_zlibwrapper.o $(ZSTDLIBRARY) $(ZLIB_LIBRARY)
|
||||
minigzip: $(EXAMPLE_PATH)/minigzip.o $(ZLIBWRAPPER_PATH)/zstd_zlibwrapper.o $(GZFILES) $(ZSTDLIBRARY)
|
||||
$(CC) $(LDFLAGS) $^ $(ZSTDLIBRARY) $(ZLIB_LIBRARY) -o $@
|
||||
|
||||
example_zstd: $(EXAMPLE_PATH)/example.o $(ZLIBWRAPPER_PATH)/zstdTurnedOn_zlibwrapper.o $(ZSTDLIBRARY)
|
||||
$(CC) $(LDFLAGS) -o $@ $(EXAMPLE_PATH)/example.o $(ZLIBWRAPPER_PATH)/zstdTurnedOn_zlibwrapper.o $(ZSTDLIBRARY) $(ZLIB_LIBRARY)
|
||||
minigzip_zstd: $(EXAMPLE_PATH)/minigzip.o $(ZLIBWRAPPER_PATH)/zstdTurnedOn_zlibwrapper.o $(GZFILES) $(ZSTDLIBRARY)
|
||||
$(CC) $(LDFLAGS) $^ $(ZSTDLIBRARY) $(ZLIB_LIBRARY) -o $@
|
||||
|
||||
example: $(EXAMPLE_PATH)/example.o $(ZLIBWRAPPER_PATH)/zstd_zlibwrapper.o $(GZFILES) $(ZSTDLIBRARY)
|
||||
$(CC) $(LDFLAGS) $^ $(ZLIB_LIBRARY) -o $@
|
||||
|
||||
example_zstd: $(EXAMPLE_PATH)/example.o $(ZLIBWRAPPER_PATH)/zstdTurnedOn_zlibwrapper.o $(GZFILES) $(ZSTDLIBRARY)
|
||||
$(CC) $(LDFLAGS) $^ $(ZLIB_LIBRARY) -o $@
|
||||
|
||||
fitblk: $(EXAMPLE_PATH)/fitblk.o $(ZLIBWRAPPER_PATH)/zstd_zlibwrapper.o $(ZSTDLIBRARY)
|
||||
$(CC) $(LDFLAGS) -o $@ $(EXAMPLE_PATH)/fitblk.o $(ZLIBWRAPPER_PATH)/zstd_zlibwrapper.o $(ZSTDLIBRARY) $(ZLIB_LIBRARY)
|
||||
$(CC) $(LDFLAGS) $^ $(ZLIB_LIBRARY) -o $@
|
||||
|
||||
fitblk_zstd: $(EXAMPLE_PATH)/fitblk.o $(ZLIBWRAPPER_PATH)/zstd_zlibwrapper.o $(ZSTDLIBRARY)
|
||||
$(CC) $(LDFLAGS) -o $@ $(EXAMPLE_PATH)/fitblk.o $(ZLIBWRAPPER_PATH)/zstdTurnedOn_zlibwrapper.o $(ZSTDLIBRARY) $(ZLIB_LIBRARY)
|
||||
fitblk_zstd: $(EXAMPLE_PATH)/fitblk.o $(ZLIBWRAPPER_PATH)/zstdTurnedOn_zlibwrapper.o $(ZSTDLIBRARY)
|
||||
$(CC) $(LDFLAGS) $^ $(ZLIB_LIBRARY) -o $@
|
||||
|
||||
zwrapbench: $(EXAMPLE_PATH)/zwrapbench.o $(ZLIBWRAPPER_PATH)/zstd_zlibwrapper.o $(PROGRAMS_PATH)/datagen.o $(ZSTDLIBRARY)
|
||||
$(CC) $(LDFLAGS) -o $@ $(EXAMPLE_PATH)/zwrapbench.o $(ZLIBWRAPPER_PATH)/zstd_zlibwrapper.o $(PROGRAMS_PATH)/datagen.o $(ZSTDLIBRARY) $(ZLIB_LIBRARY)
|
||||
$(CC) $(LDFLAGS) $^ $(ZLIB_LIBRARY) -o $@
|
||||
|
||||
$(EXAMPLE_PATH)/zwrapbench.o: $(EXAMPLE_PATH)/zwrapbench.c
|
||||
|
||||
$(ZLIBWRAPPER_PATH)/zstd_zlibwrapper.o: $(ZLIBWRAPPER_PATH)/zstd_zlibwrapper.c $(ZLIBWRAPPER_PATH)/zstd_zlibwrapper.h
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) -I. -c -o $@ $(ZLIBWRAPPER_PATH)/zstd_zlibwrapper.c
|
||||
|
@ -78,6 +101,7 @@ $(ZSTDLIBDIR)/libzstd.a:
|
|||
$(ZSTDLIBDIR)/libzstd.so:
|
||||
$(MAKE) -C $(ZSTDLIBDIR) libzstd
|
||||
|
||||
|
||||
clean:
|
||||
-$(RM) $(ZLIBWRAPPER_PATH)/*.o $(EXAMPLE_PATH)/*.o *.o *.exe foo.gz example example_zstd fitblk fitblk_zstd zwrapbench
|
||||
-$(RM) $(ZLIBWRAPPER_PATH)/*.o $(EXAMPLE_PATH)/*.o *.o foo.gz example$(EXT) example_zstd$(EXT) fitblk$(EXT) fitblk_zstd$(EXT) zwrapbench$(EXT) minigzip$(EXT) minigzip_zstd$(EXT)
|
||||
@echo Cleaning completed
|
||||
|
|
|
@ -137,12 +137,12 @@ Supported methods:
|
|||
- compress2
|
||||
- compressBound
|
||||
- uncompress
|
||||
- gzip file access functions
|
||||
|
||||
Ignored methods (they do nothing):
|
||||
- deflateParams
|
||||
|
||||
Unsupported methods:
|
||||
- gzip file access functions
|
||||
- deflateCopy
|
||||
- deflateTune
|
||||
- deflatePending
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
/* example.c -- usage example of the zlib compression library
|
||||
* the file contains minimal changes required to be compiled with zstd wrapper for zlib
|
||||
*/
|
||||
/* example.c contains minimal changes required to be compiled with zlibWrapper:
|
||||
* - #include "zlib.h" was changed to #include "zstd_zlibwrapper.h"
|
||||
* - test_flush() and test_sync() use functions not supported by zlibWrapper
|
||||
therefore they are disabled while zstd compression is turned on */
|
||||
|
||||
/*
|
||||
/* example.c -- usage example of the zlib compression library
|
||||
*/
|
||||
/*
|
||||
Copyright (c) 1995-2006, 2011 Jean-loup Gailly
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
|
@ -600,9 +603,8 @@ int main(argc, argv)
|
|||
#else
|
||||
test_compress(compr, comprLen, uncompr, uncomprLen);
|
||||
|
||||
if (!ZWRAP_isUsingZSTDcompression())
|
||||
test_gzio((argc > 1 ? argv[1] : TESTFILE),
|
||||
uncompr, uncomprLen);
|
||||
test_gzio((argc > 1 ? argv[1] : TESTFILE),
|
||||
uncompr, uncomprLen);
|
||||
#endif
|
||||
|
||||
test_deflate(compr, comprLen);
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
/* fitblk.c contains minimal changes required to be compiled with zlibWrapper:
|
||||
* - #include "zlib.h" was changed to #include "zstd_zlibwrapper.h"
|
||||
* - writing block to stdout was disabled */
|
||||
|
||||
/* fitblk.c: example of fitting compressed output to a specified size
|
||||
Not copyrighted -- provided to the public domain
|
||||
Version 1.1 25 November 2004 Mark Adler */
|
||||
|
@ -54,7 +58,6 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
//#include "zlib.h"
|
||||
#include "zstd_zlibwrapper.h"
|
||||
|
||||
#define LOG_FITBLK(...) /*printf(__VA_ARGS__)*/
|
||||
|
|
|
@ -0,0 +1,654 @@
|
|||
/* minigzip.c contains minimal changes required to be compiled with zlibWrapper:
|
||||
* - #include "zlib.h" was changed to #include "zstd_zlibwrapper.h" */
|
||||
|
||||
/* minigzip.c -- simulate gzip using the zlib compression library
|
||||
* Copyright (C) 1995-2006, 2010, 2011 Jean-loup Gailly.
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/*
|
||||
* minigzip is a minimal implementation of the gzip utility. This is
|
||||
* only an example of using zlib and isn't meant to replace the
|
||||
* full-featured gzip. No attempt is made to deal with file systems
|
||||
* limiting names to 14 or 8+3 characters, etc... Error checking is
|
||||
* very limited. So use minigzip only for testing; use gzip for the
|
||||
* real thing. On MSDOS, use only on file names without extension
|
||||
* or in pipe mode.
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#include "zstd_zlibwrapper.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef STDC
|
||||
# include <string.h>
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_MMAP
|
||||
# include <sys/types.h>
|
||||
# include <sys/mman.h>
|
||||
# include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
|
||||
# include <fcntl.h>
|
||||
# include <io.h>
|
||||
# ifdef UNDER_CE
|
||||
# include <stdlib.h>
|
||||
# endif
|
||||
# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
|
||||
#else
|
||||
# define SET_BINARY_MODE(file)
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
#ifdef VMS
|
||||
# define unlink delete
|
||||
# define GZ_SUFFIX "-gz"
|
||||
#endif
|
||||
#ifdef RISCOS
|
||||
# define unlink remove
|
||||
# define GZ_SUFFIX "-gz"
|
||||
# define fileno(file) file->__file
|
||||
#endif
|
||||
#if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
|
||||
# include <unix.h> /* for fileno */
|
||||
#endif
|
||||
|
||||
#if !defined(Z_HAVE_UNISTD_H) && !defined(_LARGEFILE64_SOURCE)
|
||||
#ifndef WIN32 /* unlink already in stdio.h for WIN32 */
|
||||
extern int unlink OF((const char *));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(UNDER_CE)
|
||||
# include <windows.h>
|
||||
# define perror(s) pwinerror(s)
|
||||
|
||||
/* Map the Windows error number in ERROR to a locale-dependent error
|
||||
message string and return a pointer to it. Typically, the values
|
||||
for ERROR come from GetLastError.
|
||||
|
||||
The string pointed to shall not be modified by the application,
|
||||
but may be overwritten by a subsequent call to strwinerror
|
||||
|
||||
The strwinerror function does not change the current setting
|
||||
of GetLastError. */
|
||||
|
||||
static char *strwinerror (error)
|
||||
DWORD error;
|
||||
{
|
||||
static char buf[1024];
|
||||
|
||||
wchar_t *msgbuf;
|
||||
DWORD lasterr = GetLastError();
|
||||
DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
|
||||
| FORMAT_MESSAGE_ALLOCATE_BUFFER,
|
||||
NULL,
|
||||
error,
|
||||
0, /* Default language */
|
||||
(LPVOID)&msgbuf,
|
||||
0,
|
||||
NULL);
|
||||
if (chars != 0) {
|
||||
/* If there is an \r\n appended, zap it. */
|
||||
if (chars >= 2
|
||||
&& msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
|
||||
chars -= 2;
|
||||
msgbuf[chars] = 0;
|
||||
}
|
||||
|
||||
if (chars > sizeof (buf) - 1) {
|
||||
chars = sizeof (buf) - 1;
|
||||
msgbuf[chars] = 0;
|
||||
}
|
||||
|
||||
wcstombs(buf, msgbuf, chars + 1);
|
||||
LocalFree(msgbuf);
|
||||
}
|
||||
else {
|
||||
sprintf(buf, "unknown win32 error (%ld)", error);
|
||||
}
|
||||
|
||||
SetLastError(lasterr);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void pwinerror (s)
|
||||
const char *s;
|
||||
{
|
||||
if (s && *s)
|
||||
fprintf(stderr, "%s: %s\n", s, strwinerror(GetLastError ()));
|
||||
else
|
||||
fprintf(stderr, "%s\n", strwinerror(GetLastError ()));
|
||||
}
|
||||
|
||||
#endif /* UNDER_CE */
|
||||
|
||||
#ifndef GZ_SUFFIX
|
||||
# define GZ_SUFFIX ".gz"
|
||||
#endif
|
||||
#define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1)
|
||||
|
||||
#define BUFLEN 16384
|
||||
#define MAX_NAME_LEN 1024
|
||||
|
||||
#ifdef MAXSEG_64K
|
||||
# define local static
|
||||
/* Needed for systems with limitation on stack size. */
|
||||
#else
|
||||
# define local
|
||||
#endif
|
||||
|
||||
#ifdef Z_SOLO
|
||||
/* for Z_SOLO, create simplified gz* functions using deflate and inflate */
|
||||
|
||||
#if defined(Z_HAVE_UNISTD_H) || defined(Z_LARGE)
|
||||
# include <unistd.h> /* for unlink() */
|
||||
#endif
|
||||
|
||||
void *myalloc OF((void *, unsigned, unsigned));
|
||||
void myfree OF((void *, void *));
|
||||
|
||||
void *myalloc(q, n, m)
|
||||
void *q;
|
||||
unsigned n, m;
|
||||
{
|
||||
q = Z_NULL;
|
||||
return calloc(n, m);
|
||||
}
|
||||
|
||||
void myfree(q, p)
|
||||
void *q, *p;
|
||||
{
|
||||
q = Z_NULL;
|
||||
free(p);
|
||||
}
|
||||
|
||||
typedef struct gzFile_s {
|
||||
FILE *file;
|
||||
int write;
|
||||
int err;
|
||||
char *msg;
|
||||
z_stream strm;
|
||||
} *gzFile;
|
||||
|
||||
gzFile gzopen OF((const char *, const char *));
|
||||
gzFile gzdopen OF((int, const char *));
|
||||
gzFile gz_open OF((const char *, int, const char *));
|
||||
|
||||
gzFile gzopen(path, mode)
|
||||
const char *path;
|
||||
const char *mode;
|
||||
{
|
||||
return gz_open(path, -1, mode);
|
||||
}
|
||||
|
||||
gzFile gzdopen(fd, mode)
|
||||
int fd;
|
||||
const char *mode;
|
||||
{
|
||||
return gz_open(NULL, fd, mode);
|
||||
}
|
||||
|
||||
gzFile gz_open(path, fd, mode)
|
||||
const char *path;
|
||||
int fd;
|
||||
const char *mode;
|
||||
{
|
||||
gzFile gz;
|
||||
int ret;
|
||||
|
||||
gz = malloc(sizeof(struct gzFile_s));
|
||||
if (gz == NULL)
|
||||
return NULL;
|
||||
gz->write = strchr(mode, 'w') != NULL;
|
||||
gz->strm.zalloc = myalloc;
|
||||
gz->strm.zfree = myfree;
|
||||
gz->strm.opaque = Z_NULL;
|
||||
if (gz->write)
|
||||
ret = deflateInit2(&(gz->strm), -1, 8, 15 + 16, 8, 0);
|
||||
else {
|
||||
gz->strm.next_in = 0;
|
||||
gz->strm.avail_in = Z_NULL;
|
||||
ret = inflateInit2(&(gz->strm), 15 + 16);
|
||||
}
|
||||
if (ret != Z_OK) {
|
||||
free(gz);
|
||||
return NULL;
|
||||
}
|
||||
gz->file = path == NULL ? fdopen(fd, gz->write ? "wb" : "rb") :
|
||||
fopen(path, gz->write ? "wb" : "rb");
|
||||
if (gz->file == NULL) {
|
||||
gz->write ? deflateEnd(&(gz->strm)) : inflateEnd(&(gz->strm));
|
||||
free(gz);
|
||||
return NULL;
|
||||
}
|
||||
gz->err = 0;
|
||||
gz->msg = "";
|
||||
return gz;
|
||||
}
|
||||
|
||||
int gzwrite OF((gzFile, const void *, unsigned));
|
||||
|
||||
int gzwrite(gz, buf, len)
|
||||
gzFile gz;
|
||||
const void *buf;
|
||||
unsigned len;
|
||||
{
|
||||
z_stream *strm;
|
||||
unsigned char out[BUFLEN];
|
||||
|
||||
if (gz == NULL || !gz->write)
|
||||
return 0;
|
||||
strm = &(gz->strm);
|
||||
strm->next_in = (void *)buf;
|
||||
strm->avail_in = len;
|
||||
do {
|
||||
strm->next_out = out;
|
||||
strm->avail_out = BUFLEN;
|
||||
(void)deflate(strm, Z_NO_FLUSH);
|
||||
fwrite(out, 1, BUFLEN - strm->avail_out, gz->file);
|
||||
} while (strm->avail_out == 0);
|
||||
return len;
|
||||
}
|
||||
|
||||
int gzread OF((gzFile, void *, unsigned));
|
||||
|
||||
int gzread(gz, buf, len)
|
||||
gzFile gz;
|
||||
void *buf;
|
||||
unsigned len;
|
||||
{
|
||||
int ret;
|
||||
unsigned got;
|
||||
unsigned char in[1];
|
||||
z_stream *strm;
|
||||
|
||||
if (gz == NULL || gz->write)
|
||||
return 0;
|
||||
if (gz->err)
|
||||
return 0;
|
||||
strm = &(gz->strm);
|
||||
strm->next_out = (void *)buf;
|
||||
strm->avail_out = len;
|
||||
do {
|
||||
got = fread(in, 1, 1, gz->file);
|
||||
if (got == 0)
|
||||
break;
|
||||
strm->next_in = in;
|
||||
strm->avail_in = 1;
|
||||
ret = inflate(strm, Z_NO_FLUSH);
|
||||
if (ret == Z_DATA_ERROR) {
|
||||
gz->err = Z_DATA_ERROR;
|
||||
gz->msg = strm->msg;
|
||||
return 0;
|
||||
}
|
||||
if (ret == Z_STREAM_END)
|
||||
inflateReset(strm);
|
||||
} while (strm->avail_out);
|
||||
return len - strm->avail_out;
|
||||
}
|
||||
|
||||
int gzclose OF((gzFile));
|
||||
|
||||
int gzclose(gz)
|
||||
gzFile gz;
|
||||
{
|
||||
z_stream *strm;
|
||||
unsigned char out[BUFLEN];
|
||||
|
||||
if (gz == NULL)
|
||||
return Z_STREAM_ERROR;
|
||||
strm = &(gz->strm);
|
||||
if (gz->write) {
|
||||
strm->next_in = Z_NULL;
|
||||
strm->avail_in = 0;
|
||||
do {
|
||||
strm->next_out = out;
|
||||
strm->avail_out = BUFLEN;
|
||||
(void)deflate(strm, Z_FINISH);
|
||||
fwrite(out, 1, BUFLEN - strm->avail_out, gz->file);
|
||||
} while (strm->avail_out == 0);
|
||||
deflateEnd(strm);
|
||||
}
|
||||
else
|
||||
inflateEnd(strm);
|
||||
fclose(gz->file);
|
||||
free(gz);
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
const char *gzerror OF((gzFile, int *));
|
||||
|
||||
const char *gzerror(gz, err)
|
||||
gzFile gz;
|
||||
int *err;
|
||||
{
|
||||
*err = gz->err;
|
||||
return gz->msg;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
char *prog;
|
||||
|
||||
void error OF((const char *msg));
|
||||
void gz_compress OF((FILE *in, gzFile out));
|
||||
#ifdef USE_MMAP
|
||||
int gz_compress_mmap OF((FILE *in, gzFile out));
|
||||
#endif
|
||||
void gz_uncompress OF((gzFile in, FILE *out));
|
||||
void file_compress OF((char *file, char *mode));
|
||||
void file_uncompress OF((char *file));
|
||||
int main OF((int argc, char *argv[]));
|
||||
|
||||
/* ===========================================================================
|
||||
* Display error message and exit
|
||||
*/
|
||||
void error(msg)
|
||||
const char *msg;
|
||||
{
|
||||
fprintf(stderr, "%s: %s\n", prog, msg);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
* Compress input to output then close both files.
|
||||
*/
|
||||
|
||||
void gz_compress(in, out)
|
||||
FILE *in;
|
||||
gzFile out;
|
||||
{
|
||||
local char buf[BUFLEN];
|
||||
int len;
|
||||
int err;
|
||||
|
||||
#ifdef USE_MMAP
|
||||
/* Try first compressing with mmap. If mmap fails (minigzip used in a
|
||||
* pipe), use the normal fread loop.
|
||||
*/
|
||||
if (gz_compress_mmap(in, out) == Z_OK) return;
|
||||
#endif
|
||||
for (;;) {
|
||||
len = (int)fread(buf, 1, sizeof(buf), in);
|
||||
if (ferror(in)) {
|
||||
perror("fread");
|
||||
exit(1);
|
||||
}
|
||||
if (len == 0) break;
|
||||
|
||||
if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err));
|
||||
}
|
||||
fclose(in);
|
||||
if (gzclose(out) != Z_OK) error("failed gzclose");
|
||||
}
|
||||
|
||||
#ifdef USE_MMAP /* MMAP version, Miguel Albrecht <malbrech@eso.org> */
|
||||
|
||||
/* Try compressing the input file at once using mmap. Return Z_OK if
|
||||
* if success, Z_ERRNO otherwise.
|
||||
*/
|
||||
int gz_compress_mmap(in, out)
|
||||
FILE *in;
|
||||
gzFile out;
|
||||
{
|
||||
int len;
|
||||
int err;
|
||||
int ifd = fileno(in);
|
||||
caddr_t buf; /* mmap'ed buffer for the entire input file */
|
||||
off_t buf_len; /* length of the input file */
|
||||
struct stat sb;
|
||||
|
||||
/* Determine the size of the file, needed for mmap: */
|
||||
if (fstat(ifd, &sb) < 0) return Z_ERRNO;
|
||||
buf_len = sb.st_size;
|
||||
if (buf_len <= 0) return Z_ERRNO;
|
||||
|
||||
/* Now do the actual mmap: */
|
||||
buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0);
|
||||
if (buf == (caddr_t)(-1)) return Z_ERRNO;
|
||||
|
||||
/* Compress the whole file at once: */
|
||||
len = gzwrite(out, (char *)buf, (unsigned)buf_len);
|
||||
|
||||
if (len != (int)buf_len) error(gzerror(out, &err));
|
||||
|
||||
munmap(buf, buf_len);
|
||||
fclose(in);
|
||||
if (gzclose(out) != Z_OK) error("failed gzclose");
|
||||
return Z_OK;
|
||||
}
|
||||
#endif /* USE_MMAP */
|
||||
|
||||
/* ===========================================================================
|
||||
* Uncompress input to output then close both files.
|
||||
*/
|
||||
void gz_uncompress(in, out)
|
||||
gzFile in;
|
||||
FILE *out;
|
||||
{
|
||||
local char buf[BUFLEN];
|
||||
int len;
|
||||
int err;
|
||||
|
||||
for (;;) {
|
||||
len = gzread(in, buf, sizeof(buf));
|
||||
if (len < 0) error (gzerror(in, &err));
|
||||
if (len == 0) break;
|
||||
|
||||
if ((int)fwrite(buf, 1, (unsigned)len, out) != len) {
|
||||
error("failed fwrite");
|
||||
}
|
||||
}
|
||||
if (fclose(out)) error("failed fclose");
|
||||
|
||||
if (gzclose(in) != Z_OK) error("failed gzclose");
|
||||
}
|
||||
|
||||
|
||||
/* ===========================================================================
|
||||
* Compress the given file: create a corresponding .gz file and remove the
|
||||
* original.
|
||||
*/
|
||||
void file_compress(file, mode)
|
||||
char *file;
|
||||
char *mode;
|
||||
{
|
||||
local char outfile[MAX_NAME_LEN];
|
||||
FILE *in;
|
||||
gzFile out;
|
||||
|
||||
if (strlen(file) + strlen(GZ_SUFFIX) >= sizeof(outfile)) {
|
||||
fprintf(stderr, "%s: filename too long\n", prog);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
|
||||
snprintf(outfile, sizeof(outfile), "%s%s", file, GZ_SUFFIX);
|
||||
#else
|
||||
strcpy(outfile, file);
|
||||
strcat(outfile, GZ_SUFFIX);
|
||||
#endif
|
||||
|
||||
in = fopen(file, "rb");
|
||||
if (in == NULL) {
|
||||
perror(file);
|
||||
exit(1);
|
||||
}
|
||||
out = gzopen(outfile, mode);
|
||||
if (out == NULL) {
|
||||
fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile);
|
||||
exit(1);
|
||||
}
|
||||
gz_compress(in, out);
|
||||
|
||||
unlink(file);
|
||||
}
|
||||
|
||||
|
||||
/* ===========================================================================
|
||||
* Uncompress the given file and remove the original.
|
||||
*/
|
||||
void file_uncompress(file)
|
||||
char *file;
|
||||
{
|
||||
local char buf[MAX_NAME_LEN];
|
||||
char *infile, *outfile;
|
||||
FILE *out;
|
||||
gzFile in;
|
||||
size_t len = strlen(file);
|
||||
|
||||
if (len + strlen(GZ_SUFFIX) >= sizeof(buf)) {
|
||||
fprintf(stderr, "%s: filename too long\n", prog);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
|
||||
snprintf(buf, sizeof(buf), "%s", file);
|
||||
#else
|
||||
strcpy(buf, file);
|
||||
#endif
|
||||
|
||||
if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) {
|
||||
infile = file;
|
||||
outfile = buf;
|
||||
outfile[len-3] = '\0';
|
||||
} else {
|
||||
outfile = file;
|
||||
infile = buf;
|
||||
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
|
||||
snprintf(buf + len, sizeof(buf) - len, "%s", GZ_SUFFIX);
|
||||
#else
|
||||
strcat(infile, GZ_SUFFIX);
|
||||
#endif
|
||||
}
|
||||
in = gzopen(infile, "rb");
|
||||
if (in == NULL) {
|
||||
fprintf(stderr, "%s: can't gzopen %s\n", prog, infile);
|
||||
exit(1);
|
||||
}
|
||||
out = fopen(outfile, "wb");
|
||||
if (out == NULL) {
|
||||
perror(file);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
gz_uncompress(in, out);
|
||||
|
||||
unlink(infile);
|
||||
}
|
||||
|
||||
|
||||
/* ===========================================================================
|
||||
* Usage: minigzip [-c] [-d] [-f] [-h] [-r] [-1 to -9] [files...]
|
||||
* -c : write to standard output
|
||||
* -d : decompress
|
||||
* -f : compress with Z_FILTERED
|
||||
* -h : compress with Z_HUFFMAN_ONLY
|
||||
* -r : compress with Z_RLE
|
||||
* -1 to -9 : compression level
|
||||
*/
|
||||
|
||||
int main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
int copyout = 0;
|
||||
int uncompr = 0;
|
||||
gzFile file;
|
||||
char *bname, outmode[20];
|
||||
|
||||
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
|
||||
snprintf(outmode, sizeof(outmode), "%s", "wb6 ");
|
||||
#else
|
||||
strcpy(outmode, "wb6 ");
|
||||
#endif
|
||||
|
||||
prog = argv[0];
|
||||
bname = strrchr(argv[0], '/');
|
||||
if (bname)
|
||||
bname++;
|
||||
else
|
||||
bname = argv[0];
|
||||
argc--, argv++;
|
||||
|
||||
if (!strcmp(bname, "gunzip"))
|
||||
uncompr = 1;
|
||||
else if (!strcmp(bname, "zcat"))
|
||||
copyout = uncompr = 1;
|
||||
|
||||
while (argc > 0) {
|
||||
if (strcmp(*argv, "-c") == 0)
|
||||
copyout = 1;
|
||||
else if (strcmp(*argv, "-d") == 0)
|
||||
uncompr = 1;
|
||||
else if (strcmp(*argv, "-f") == 0)
|
||||
outmode[3] = 'f';
|
||||
else if (strcmp(*argv, "-h") == 0)
|
||||
outmode[3] = 'h';
|
||||
else if (strcmp(*argv, "-r") == 0)
|
||||
outmode[3] = 'R';
|
||||
else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' &&
|
||||
(*argv)[2] == 0)
|
||||
outmode[2] = (*argv)[1];
|
||||
else
|
||||
break;
|
||||
argc--, argv++;
|
||||
}
|
||||
if (outmode[3] == ' ')
|
||||
outmode[3] = 0;
|
||||
if (argc == 0) {
|
||||
SET_BINARY_MODE(stdin);
|
||||
SET_BINARY_MODE(stdout);
|
||||
if (uncompr) {
|
||||
file = gzdopen(fileno(stdin), "rb");
|
||||
if (file == NULL) error("can't gzdopen stdin");
|
||||
gz_uncompress(file, stdout);
|
||||
} else {
|
||||
file = gzdopen(fileno(stdout), outmode);
|
||||
if (file == NULL) error("can't gzdopen stdout");
|
||||
gz_compress(stdin, file);
|
||||
}
|
||||
} else {
|
||||
if (copyout) {
|
||||
SET_BINARY_MODE(stdout);
|
||||
}
|
||||
do {
|
||||
if (uncompr) {
|
||||
if (copyout) {
|
||||
file = gzopen(*argv, "rb");
|
||||
if (file == NULL)
|
||||
fprintf(stderr, "%s: can't gzopen %s\n", prog, *argv);
|
||||
else
|
||||
gz_uncompress(file, stdout);
|
||||
} else {
|
||||
file_uncompress(*argv);
|
||||
}
|
||||
} else {
|
||||
if (copyout) {
|
||||
FILE * in = fopen(*argv, "rb");
|
||||
|
||||
if (in == NULL) {
|
||||
perror(*argv);
|
||||
} else {
|
||||
file = gzdopen(fileno(stdout), outmode);
|
||||
if (file == NULL) error("can't gzdopen stdout");
|
||||
|
||||
gz_compress(in, file);
|
||||
}
|
||||
|
||||
} else {
|
||||
file_compress(*argv, outmode);
|
||||
}
|
||||
}
|
||||
} while (argv++, --argc);
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -239,11 +239,18 @@ static int BMK_benchMem(z_const void* srcBuffer, size_t srcSize,
|
|||
|
||||
do {
|
||||
U32 blockNb;
|
||||
size_t rSize;
|
||||
for (blockNb=0; blockNb<nbBlocks; blockNb++) {
|
||||
size_t const rSize = ZSTD_compress_usingCDict(ctx,
|
||||
if (dictBufferSize) {
|
||||
rSize = ZSTD_compress_usingCDict(ctx,
|
||||
blockTable[blockNb].cPtr, blockTable[blockNb].cRoom,
|
||||
blockTable[blockNb].srcPtr,blockTable[blockNb].srcSize,
|
||||
cdict);
|
||||
} else {
|
||||
rSize = ZSTD_compressCCtx (ctx,
|
||||
blockTable[blockNb].cPtr, blockTable[blockNb].cRoom,
|
||||
blockTable[blockNb].srcPtr,blockTable[blockNb].srcSize, cLevel);
|
||||
}
|
||||
if (ZSTD_isError(rSize)) EXM_THROW(1, "ZSTD_compress_usingCDict() failed : %s", ZSTD_getErrorName(rSize));
|
||||
blockTable[blockNb].cSize = rSize;
|
||||
}
|
||||
|
@ -591,14 +598,6 @@ static void BMK_benchCLevel(void* srcBuffer, size_t benchedSize,
|
|||
|
||||
if (cLevelLast < cLevel) cLevelLast = cLevel;
|
||||
|
||||
DISPLAY("benchmarking zstd %s (using ZSTD_CCtx)\n", ZSTD_VERSION_STRING);
|
||||
for (l=cLevel; l <= cLevelLast; l++) {
|
||||
BMK_benchMem(srcBuffer, benchedSize,
|
||||
displayName, l,
|
||||
fileSizes, nbFiles,
|
||||
dictBuffer, dictBufferSize, BMK_ZSTD);
|
||||
}
|
||||
|
||||
DISPLAY("benchmarking zstd %s (using ZSTD_CStream)\n", ZSTD_VERSION_STRING);
|
||||
for (l=cLevel; l <= cLevelLast; l++) {
|
||||
BMK_benchMem(srcBuffer, benchedSize,
|
||||
|
@ -607,6 +606,14 @@ static void BMK_benchCLevel(void* srcBuffer, size_t benchedSize,
|
|||
dictBuffer, dictBufferSize, BMK_ZSTD_STREAM);
|
||||
}
|
||||
|
||||
DISPLAY("benchmarking zstd %s (using ZSTD_CCtx)\n", ZSTD_VERSION_STRING);
|
||||
for (l=cLevel; l <= cLevelLast; l++) {
|
||||
BMK_benchMem(srcBuffer, benchedSize,
|
||||
displayName, l,
|
||||
fileSizes, nbFiles,
|
||||
dictBuffer, dictBufferSize, BMK_ZSTD);
|
||||
}
|
||||
|
||||
DISPLAY("benchmarking zstd %s (using zlibWrapper)\n", ZSTD_VERSION_STRING);
|
||||
for (l=cLevel; l <= cLevelLast; l++) {
|
||||
BMK_benchMem(srcBuffer, benchedSize,
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/* gzclose.c contains minimal changes required to be compiled with zlibWrapper:
|
||||
* - gz_statep was converted to union to work with -Wstrict-aliasing=1 */
|
||||
|
||||
/* gzclose.c -- zlib gzclose() function
|
||||
* Copyright (C) 2004, 2010 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "gzguts.h"
|
||||
|
||||
/* 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 ZEXPORT gzclose(file)
|
||||
gzFile file;
|
||||
{
|
||||
#ifndef NO_GZCOMPRESS
|
||||
gz_statep state;
|
||||
|
||||
if (file == NULL)
|
||||
return Z_STREAM_ERROR;
|
||||
state = (gz_statep)file;
|
||||
|
||||
return state.state->mode == GZ_READ ? gzclose_r(file) : gzclose_w(file);
|
||||
#else
|
||||
return gzclose_r(file);
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/**
|
||||
* Copyright (c) 2016-present, Przemyslaw Skibinski, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#if ZLIB_VERNUM <= 0x1240
|
||||
ZEXTERN int ZEXPORT gzclose_r OF((gzFile file));
|
||||
ZEXTERN int ZEXPORT gzclose_w OF((gzFile file));
|
||||
ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size));
|
||||
ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file));
|
||||
|
||||
#if !defined(_WIN32) && defined(Z_LARGE64)
|
||||
# define z_off64_t off64_t
|
||||
#else
|
||||
# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO)
|
||||
# define z_off64_t __int64
|
||||
# else
|
||||
# define z_off64_t z_off_t
|
||||
# endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#if ZLIB_VERNUM <= 0x1250
|
||||
struct gzFile_s {
|
||||
unsigned have;
|
||||
unsigned char *next;
|
||||
z_off64_t pos;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#if ZLIB_VERNUM <= 0x1270
|
||||
#if defined(_WIN32) && !defined(Z_SOLO)
|
||||
# include <stddef.h> /* for wchar_t */
|
||||
ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path,
|
||||
const char *mode));
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,218 @@
|
|||
/* gzguts.h contains minimal changes required to be compiled with zlibWrapper:
|
||||
* - #include "zlib.h" was changed to #include "zstd_zlibwrapper.h"
|
||||
* - gz_statep was converted to union to work with -Wstrict-aliasing=1 */
|
||||
|
||||
/* gzguts.h -- zlib internal header definitions for gz* operations
|
||||
* Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#ifdef _LARGEFILE64_SOURCE
|
||||
# ifndef _LARGEFILE_SOURCE
|
||||
# define _LARGEFILE_SOURCE 1
|
||||
# endif
|
||||
# ifdef _FILE_OFFSET_BITS
|
||||
# undef _FILE_OFFSET_BITS
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_HIDDEN
|
||||
# define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
|
||||
#else
|
||||
# define ZLIB_INTERNAL
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include "zstd_zlibwrapper.h"
|
||||
#include "gzcompatibility.h"
|
||||
#ifdef STDC
|
||||
# include <string.h>
|
||||
# include <stdlib.h>
|
||||
# include <limits.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <stddef.h>
|
||||
#endif
|
||||
|
||||
#if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32)
|
||||
# include <io.h>
|
||||
#endif
|
||||
|
||||
#ifdef WINAPI_FAMILY
|
||||
# define open _open
|
||||
# define read _read
|
||||
# define write _write
|
||||
# define close _close
|
||||
#endif
|
||||
|
||||
#ifdef NO_DEFLATE /* for compatibility with old definition */
|
||||
# define NO_GZCOMPRESS
|
||||
#endif
|
||||
|
||||
#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550)
|
||||
# ifndef HAVE_VSNPRINTF
|
||||
# define HAVE_VSNPRINTF
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(__CYGWIN__)
|
||||
# ifndef HAVE_VSNPRINTF
|
||||
# define HAVE_VSNPRINTF
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(MSDOS) && defined(__BORLANDC__) && (BORLANDC > 0x410)
|
||||
# ifndef HAVE_VSNPRINTF
|
||||
# define HAVE_VSNPRINTF
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_VSNPRINTF
|
||||
# ifdef MSDOS
|
||||
/* vsnprintf may exist on some MS-DOS compilers (DJGPP?),
|
||||
but for now we just assume it doesn't. */
|
||||
# define NO_vsnprintf
|
||||
# endif
|
||||
# ifdef __TURBOC__
|
||||
# define NO_vsnprintf
|
||||
# endif
|
||||
# ifdef WIN32
|
||||
/* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */
|
||||
# if !defined(vsnprintf) && !defined(NO_vsnprintf)
|
||||
# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 )
|
||||
# define vsnprintf _vsnprintf
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
# ifdef __SASC
|
||||
# define NO_vsnprintf
|
||||
# endif
|
||||
# ifdef VMS
|
||||
# define NO_vsnprintf
|
||||
# endif
|
||||
# ifdef __OS400__
|
||||
# define NO_vsnprintf
|
||||
# endif
|
||||
# ifdef __MVS__
|
||||
# define NO_vsnprintf
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* unlike snprintf (which is required in C99, yet still not supported by
|
||||
Microsoft more than a decade later!), _snprintf does not guarantee null
|
||||
termination of the result -- however this is only used in gzlib.c where
|
||||
the result is assured to fit in the space provided */
|
||||
#ifdef _MSC_VER
|
||||
# define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
#ifndef local
|
||||
# define local static
|
||||
#endif
|
||||
/* compile with -Dlocal if your debugger can't find static symbols */
|
||||
|
||||
/* gz* functions always use library allocation functions */
|
||||
#ifndef STDC
|
||||
extern voidp malloc OF((uInt size));
|
||||
extern void free OF((voidpf ptr));
|
||||
#endif
|
||||
|
||||
/* get errno and strerror definition */
|
||||
#if defined UNDER_CE
|
||||
# include <windows.h>
|
||||
# define zstrerror() gz_strwinerror((DWORD)GetLastError())
|
||||
#else
|
||||
# ifndef NO_STRERROR
|
||||
# include <errno.h>
|
||||
# define zstrerror() strerror(errno)
|
||||
# else
|
||||
# define zstrerror() "stdio error (consult errno)"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* provide prototypes for these when building zlib without LFS */
|
||||
#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0
|
||||
ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
|
||||
ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));
|
||||
ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));
|
||||
ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));
|
||||
#endif
|
||||
|
||||
/* default memLevel */
|
||||
#if MAX_MEM_LEVEL >= 8
|
||||
# define DEF_MEM_LEVEL 8
|
||||
#else
|
||||
# define DEF_MEM_LEVEL MAX_MEM_LEVEL
|
||||
#endif
|
||||
|
||||
/* default i/o buffer size -- double this for output when reading (this and
|
||||
twice this must be able to fit in an unsigned type) */
|
||||
#define GZBUFSIZE 8192
|
||||
|
||||
/* gzip modes, also provide a little integrity check on the passed structure */
|
||||
#define GZ_NONE 0
|
||||
#define GZ_READ 7247
|
||||
#define GZ_WRITE 31153
|
||||
#define GZ_APPEND 1 /* mode set to GZ_WRITE after the file is opened */
|
||||
|
||||
/* values for gz_state how */
|
||||
#define LOOK 0 /* look for a gzip header */
|
||||
#define COPY 1 /* copy input directly */
|
||||
#define GZIP 2 /* decompress a gzip stream */
|
||||
|
||||
/* internal gzip file state data structure */
|
||||
typedef struct {
|
||||
/* exposed contents for gzgetc() macro */
|
||||
struct gzFile_s x; /* "x" for exposed */
|
||||
/* x.have: number of bytes available at x.next */
|
||||
/* x.next: next output data to deliver or write */
|
||||
/* x.pos: current position in uncompressed data */
|
||||
/* used for both reading and writing */
|
||||
int mode; /* see gzip modes above */
|
||||
int fd; /* file descriptor */
|
||||
char *path; /* path or fd for error messages */
|
||||
unsigned size; /* buffer size, zero if not allocated yet */
|
||||
unsigned want; /* requested buffer size, default is GZBUFSIZE */
|
||||
unsigned char *in; /* input buffer */
|
||||
unsigned char *out; /* output buffer (double-sized when reading) */
|
||||
int direct; /* 0 if processing gzip, 1 if transparent */
|
||||
/* just for reading */
|
||||
int how; /* 0: get header, 1: copy, 2: decompress */
|
||||
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 */
|
||||
/* seek request */
|
||||
z_off64_t skip; /* amount to skip (already rewound if backwards) */
|
||||
int seek; /* true if seek request pending */
|
||||
/* error information */
|
||||
int err; /* error code */
|
||||
char *msg; /* error message */
|
||||
/* zlib inflate or deflate stream */
|
||||
z_stream strm; /* stream structure in-place (not a pointer) */
|
||||
} gz_state;
|
||||
|
||||
typedef union {
|
||||
gz_state FAR *state;
|
||||
gzFile file;
|
||||
} gz_statep;
|
||||
|
||||
/* shared functions */
|
||||
void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *));
|
||||
#if defined UNDER_CE
|
||||
char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error));
|
||||
#endif
|
||||
|
||||
/* 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(z_off64_t) && (x) > INT_MAX)
|
||||
#else
|
||||
unsigned ZLIB_INTERNAL gz_intmax OF((void));
|
||||
# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax())
|
||||
#endif
|
|
@ -0,0 +1,637 @@
|
|||
/* gzlib.c contains minimal changes required to be compiled with zlibWrapper:
|
||||
* - gz_statep was converted to union to work with -Wstrict-aliasing=1 */
|
||||
|
||||
/* gzlib.c -- zlib functions common to reading and writing gzip files
|
||||
* Copyright (C) 2004, 2010, 2011, 2012, 2013 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "gzguts.h"
|
||||
|
||||
#if defined(_WIN32) && !defined(__BORLANDC__)
|
||||
# define LSEEK _lseeki64
|
||||
#else
|
||||
#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
|
||||
# define LSEEK lseek64
|
||||
#else
|
||||
# define LSEEK lseek
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Local functions */
|
||||
local void gz_reset OF((gz_statep));
|
||||
local gzFile gz_open OF((const void *, int, const char *));
|
||||
|
||||
#if defined UNDER_CE
|
||||
|
||||
/* Map the Windows error number in ERROR to a locale-dependent error message
|
||||
string and return a pointer to it. Typically, the values for ERROR come
|
||||
from GetLastError.
|
||||
|
||||
The string pointed to shall not be modified by the application, but may be
|
||||
overwritten by a subsequent call to gz_strwinerror
|
||||
|
||||
The gz_strwinerror function does not change the current setting of
|
||||
GetLastError. */
|
||||
char ZLIB_INTERNAL *gz_strwinerror (error)
|
||||
DWORD error;
|
||||
{
|
||||
static char buf[1024];
|
||||
|
||||
wchar_t *msgbuf;
|
||||
DWORD lasterr = GetLastError();
|
||||
DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
|
||||
| FORMAT_MESSAGE_ALLOCATE_BUFFER,
|
||||
NULL,
|
||||
error,
|
||||
0, /* Default language */
|
||||
(LPVOID)&msgbuf,
|
||||
0,
|
||||
NULL);
|
||||
if (chars != 0) {
|
||||
/* If there is an \r\n appended, zap it. */
|
||||
if (chars >= 2
|
||||
&& msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
|
||||
chars -= 2;
|
||||
msgbuf[chars] = 0;
|
||||
}
|
||||
|
||||
if (chars > sizeof (buf) - 1) {
|
||||
chars = sizeof (buf) - 1;
|
||||
msgbuf[chars] = 0;
|
||||
}
|
||||
|
||||
wcstombs(buf, msgbuf, chars + 1);
|
||||
LocalFree(msgbuf);
|
||||
}
|
||||
else {
|
||||
sprintf(buf, "unknown win32 error (%ld)", error);
|
||||
}
|
||||
|
||||
SetLastError(lasterr);
|
||||
return buf;
|
||||
}
|
||||
|
||||
#endif /* UNDER_CE */
|
||||
|
||||
/* Reset gzip file state */
|
||||
local void gz_reset(state)
|
||||
gz_statep state;
|
||||
{
|
||||
state.state->x.have = 0; /* no output data available */
|
||||
if (state.state->mode == GZ_READ) { /* for reading ... */
|
||||
state.state->eof = 0; /* not at end of file */
|
||||
state.state->past = 0; /* have not read past end yet */
|
||||
state.state->how = LOOK; /* look for gzip header */
|
||||
}
|
||||
state.state->seek = 0; /* no seek request pending */
|
||||
gz_error(state, Z_OK, NULL); /* clear error */
|
||||
state.state->x.pos = 0; /* no uncompressed data yet */
|
||||
state.state->strm.avail_in = 0; /* no input data yet */
|
||||
}
|
||||
|
||||
/* Open a gzip file either by name or file descriptor. */
|
||||
local gzFile gz_open(path, fd, mode)
|
||||
const void *path;
|
||||
int fd;
|
||||
const char *mode;
|
||||
{
|
||||
gz_statep state;
|
||||
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 = (gz_statep)(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 _WIN32
|
||||
if (fd == -2) {
|
||||
len = wcstombs(NULL, path, 0);
|
||||
if (len == (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 _WIN32
|
||||
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)
|
||||
snprintf(state.state->path, len + 1, "%s", (const char *)path);
|
||||
#else
|
||||
strcpy(state.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.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 _WIN32
|
||||
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)
|
||||
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 (gzFile)state.file;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
gzFile ZEXPORT gzopen(path, mode)
|
||||
const char *path;
|
||||
const char *mode;
|
||||
{
|
||||
return gz_open(path, -1, mode);
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
gzFile ZEXPORT gzopen64(path, mode)
|
||||
const char *path;
|
||||
const char *mode;
|
||||
{
|
||||
return gz_open(path, -1, mode);
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
gzFile ZEXPORT gzdopen(fd, mode)
|
||||
int fd;
|
||||
const char *mode;
|
||||
{
|
||||
char *path; /* identifier for error messages */
|
||||
gzFile gz;
|
||||
|
||||
if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)
|
||||
return NULL;
|
||||
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
|
||||
snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd); /* for debugging */
|
||||
#else
|
||||
sprintf(path, "<fd:%d>", fd); /* for debugging */
|
||||
#endif
|
||||
gz = gz_open(path, fd, mode);
|
||||
free(path);
|
||||
return gz;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
#ifdef _WIN32
|
||||
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;
|
||||
{
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure and check integrity */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
|
||||
return -1;
|
||||
|
||||
/* make sure we haven't already allocated memory */
|
||||
if (state.state->size != 0)
|
||||
return -1;
|
||||
|
||||
/* check and set requested size */
|
||||
if (size < 2)
|
||||
size = 2; /* need two bytes to check magic header */
|
||||
state.state->want = size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzrewind(file)
|
||||
gzFile file;
|
||||
{
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
|
||||
/* check that we're reading and that there's no error */
|
||||
if (state.state->mode != GZ_READ ||
|
||||
(state.state->err != Z_OK && state.state->err != Z_BUF_ERROR))
|
||||
return -1;
|
||||
|
||||
/* back up and start over */
|
||||
if (LSEEK(state.state->fd, state.state->start, SEEK_SET) == -1)
|
||||
return -1;
|
||||
gz_reset(state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
z_off64_t ZEXPORT gzseek64(file, offset, whence)
|
||||
gzFile file;
|
||||
z_off64_t offset;
|
||||
int whence;
|
||||
{
|
||||
unsigned n;
|
||||
z_off64_t ret;
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure and check integrity */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
|
||||
return -1;
|
||||
|
||||
/* check that there's no error */
|
||||
if (state.state->err != Z_OK && state.state->err != Z_BUF_ERROR)
|
||||
return -1;
|
||||
|
||||
/* can only seek from start or relative to current position */
|
||||
if (whence != SEEK_SET && whence != SEEK_CUR)
|
||||
return -1;
|
||||
|
||||
/* normalize offset to a SEEK_CUR specification */
|
||||
if (whence == SEEK_SET)
|
||||
offset -= state.state->x.pos;
|
||||
else if (state.state->seek)
|
||||
offset += state.state->skip;
|
||||
state.state->seek = 0;
|
||||
|
||||
/* if within raw area while reading, just go there */
|
||||
if (state.state->mode == GZ_READ && state.state->how == COPY &&
|
||||
state.state->x.pos + offset >= 0) {
|
||||
ret = LSEEK(state.state->fd, offset - state.state->x.have, SEEK_CUR);
|
||||
if (ret == -1)
|
||||
return -1;
|
||||
state.state->x.have = 0;
|
||||
state.state->eof = 0;
|
||||
state.state->past = 0;
|
||||
state.state->seek = 0;
|
||||
gz_error(state, Z_OK, NULL);
|
||||
state.state->strm.avail_in = 0;
|
||||
state.state->x.pos += offset;
|
||||
return state.state->x.pos;
|
||||
}
|
||||
|
||||
/* calculate skip amount, rewinding if needed for back seek when reading */
|
||||
if (offset < 0) {
|
||||
if (state.state->mode != GZ_READ) /* writing -- can't go backwards */
|
||||
return -1;
|
||||
offset += state.state->x.pos;
|
||||
if (offset < 0) /* before start of file! */
|
||||
return -1;
|
||||
if (gzrewind(file) == -1) /* rewind, then skip to offset */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* if reading, skip what's in output buffer (one less gzgetc() check) */
|
||||
if (state.state->mode == GZ_READ) {
|
||||
n = GT_OFF(state.state->x.have) || (z_off64_t)state.state->x.have > offset ?
|
||||
(unsigned)offset : state.state->x.have;
|
||||
state.state->x.have -= n;
|
||||
state.state->x.next += n;
|
||||
state.state->x.pos += n;
|
||||
offset -= n;
|
||||
}
|
||||
|
||||
/* request skip (if not zero) */
|
||||
if (offset) {
|
||||
state.state->seek = 1;
|
||||
state.state->skip = offset;
|
||||
}
|
||||
return state.state->x.pos + offset;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
z_off_t ZEXPORT gzseek(file, offset, whence)
|
||||
gzFile file;
|
||||
z_off_t offset;
|
||||
int whence;
|
||||
{
|
||||
z_off64_t ret;
|
||||
|
||||
ret = gzseek64(file, (z_off64_t)offset, whence);
|
||||
return ret == (z_off_t)ret ? (z_off_t)ret : -1;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
z_off64_t ZEXPORT gztell64(file)
|
||||
gzFile file;
|
||||
{
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure and check integrity */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
|
||||
return -1;
|
||||
|
||||
/* return position */
|
||||
return state.state->x.pos + (state.state->seek ? state.state->skip : 0);
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
z_off_t ZEXPORT gztell(file)
|
||||
gzFile file;
|
||||
{
|
||||
z_off64_t ret;
|
||||
|
||||
ret = gztell64(file);
|
||||
return ret == (z_off_t)ret ? (z_off_t)ret : -1;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
z_off64_t ZEXPORT gzoffset64(file)
|
||||
gzFile file;
|
||||
{
|
||||
z_off64_t offset;
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure and check integrity */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
|
||||
return -1;
|
||||
|
||||
/* compute and return effective offset in file */
|
||||
offset = LSEEK(state.state->fd, 0, SEEK_CUR);
|
||||
if (offset == -1)
|
||||
return -1;
|
||||
if (state.state->mode == GZ_READ) /* reading */
|
||||
offset -= state.state->strm.avail_in; /* don't count buffered input */
|
||||
return offset;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
z_off_t ZEXPORT gzoffset(file)
|
||||
gzFile file;
|
||||
{
|
||||
z_off64_t ret;
|
||||
|
||||
ret = gzoffset64(file);
|
||||
return ret == (z_off_t)ret ? (z_off_t)ret : -1;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzeof(file)
|
||||
gzFile file;
|
||||
{
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure and check integrity */
|
||||
if (file == NULL)
|
||||
return 0;
|
||||
state = (gz_statep)file;
|
||||
if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
|
||||
return 0;
|
||||
|
||||
/* return end-of-file state */
|
||||
return state.state->mode == GZ_READ ? state.state->past : 0;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
const char * ZEXPORT gzerror(file, errnum)
|
||||
gzFile file;
|
||||
int *errnum;
|
||||
{
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure and check integrity */
|
||||
if (file == NULL)
|
||||
return NULL;
|
||||
state = (gz_statep)file;
|
||||
if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
|
||||
return NULL;
|
||||
|
||||
/* return error information */
|
||||
if (errnum != NULL)
|
||||
*errnum = state.state->err;
|
||||
return state.state->err == Z_MEM_ERROR ? "out of memory" :
|
||||
(state.state->msg == NULL ? "" : state.state->msg);
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
void ZEXPORT gzclearerr(file)
|
||||
gzFile file;
|
||||
{
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure and check integrity */
|
||||
if (file == NULL)
|
||||
return;
|
||||
state = (gz_statep)file;
|
||||
if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
|
||||
return;
|
||||
|
||||
/* clear error and end-of-file */
|
||||
if (state.state->mode == GZ_READ) {
|
||||
state.state->eof = 0;
|
||||
state.state->past = 0;
|
||||
}
|
||||
gz_error(state, Z_OK, NULL);
|
||||
}
|
||||
|
||||
/* Create an error message in allocated memory and set state->err and
|
||||
state->msg accordingly. Free any previous error message already there. Do
|
||||
not try to free or allocate space if the error is Z_MEM_ERROR (out of
|
||||
memory). Simply save the error message as a static string. If there is an
|
||||
allocation failure constructing the error message, then convert the error to
|
||||
out of memory. */
|
||||
void ZLIB_INTERNAL gz_error(state, err, msg)
|
||||
gz_statep state;
|
||||
int err;
|
||||
const char *msg;
|
||||
{
|
||||
/* free previously allocated message and clear */
|
||||
if (state.state->msg != NULL) {
|
||||
if (state.state->err != Z_MEM_ERROR)
|
||||
free(state.state->msg);
|
||||
state.state->msg = NULL;
|
||||
}
|
||||
|
||||
/* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */
|
||||
if (err != Z_OK && err != Z_BUF_ERROR)
|
||||
state.state->x.have = 0;
|
||||
|
||||
/* set error code, and if no message, then done */
|
||||
state.state->err = err;
|
||||
if (msg == NULL)
|
||||
return;
|
||||
|
||||
/* for an out of memory error, return literal string when requested */
|
||||
if (err == Z_MEM_ERROR)
|
||||
return;
|
||||
|
||||
/* construct error message with path */
|
||||
if ((state.state->msg = (char *)malloc(strlen(state.state->path) + strlen(msg) + 3)) ==
|
||||
NULL) {
|
||||
state.state->err = Z_MEM_ERROR;
|
||||
return;
|
||||
}
|
||||
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
|
||||
snprintf(state.state->msg, strlen(state.state->path) + strlen(msg) + 3,
|
||||
"%s%s%s", state.state->path, ": ", msg);
|
||||
#else
|
||||
strcpy(state.state->msg, state.state->path);
|
||||
strcat(state.state->msg, ": ");
|
||||
strcat(state.state->msg, msg);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
#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
|
|
@ -0,0 +1,612 @@
|
|||
/* gzread.c contains minimal changes required to be compiled with zlibWrapper:
|
||||
* - gz_statep was converted to union to work with -Wstrict-aliasing=1 */
|
||||
|
||||
/* gzread.c -- zlib functions for reading gzip files
|
||||
* Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "gzguts.h"
|
||||
|
||||
/* 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));
|
||||
|
||||
/* 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. */
|
||||
local int gz_load(state, buf, len, have)
|
||||
gz_statep state;
|
||||
unsigned char *buf;
|
||||
unsigned len;
|
||||
unsigned *have;
|
||||
{
|
||||
int ret;
|
||||
|
||||
*have = 0;
|
||||
do {
|
||||
ret = read(state.state->fd, buf + *have, len - *have);
|
||||
if (ret <= 0)
|
||||
break;
|
||||
*have += ret;
|
||||
} while (*have < len);
|
||||
if (ret < 0) {
|
||||
gz_error(state, Z_ERRNO, zstrerror());
|
||||
return -1;
|
||||
}
|
||||
if (ret == 0)
|
||||
state.state->eof = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Load up input buffer and set eof flag if last data loaded -- return -1 on
|
||||
error, 0 otherwise. Note that the eof flag is set when the end of the input
|
||||
file is reached, even though there may be unused data in the buffer. Once
|
||||
that data has been used, no more attempts will be made to read the file.
|
||||
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. */
|
||||
local int gz_avail(state)
|
||||
gz_statep state;
|
||||
{
|
||||
unsigned got;
|
||||
z_streamp strm = &(state.state->strm);
|
||||
|
||||
if (state.state->err != Z_OK && state.state->err != Z_BUF_ERROR)
|
||||
return -1;
|
||||
if (state.state->eof == 0) {
|
||||
if (strm->avail_in) { /* copy what's there to the start */
|
||||
unsigned char *p = state.state->in;
|
||||
unsigned const char *q = strm->next_in;
|
||||
unsigned n = strm->avail_in;
|
||||
do {
|
||||
*p++ = *q++;
|
||||
} while (--n);
|
||||
}
|
||||
if (gz_load(state, state.state->in + strm->avail_in,
|
||||
state.state->size - strm->avail_in, &got) == -1)
|
||||
return -1;
|
||||
strm->avail_in += got;
|
||||
strm->next_in = state.state->in;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Look for gzip header, set up for inflate or copy. state->x.have must be 0.
|
||||
If this is the first time in, allocate required memory. state->how will be
|
||||
left unchanged if there is no more input data available, will be set to COPY
|
||||
if there is no gzip header and direct copying will be performed, or it will
|
||||
be set to GZIP for decompression. If direct copying, then leftover input
|
||||
data from the input buffer will be copied to the output buffer. In that
|
||||
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. */
|
||||
local int gz_look(state)
|
||||
gz_statep state;
|
||||
{
|
||||
z_streamp strm = &(state.state->strm);
|
||||
|
||||
/* allocate read buffers and inflate memory */
|
||||
if (state.state->size == 0) {
|
||||
/* allocate buffers */
|
||||
state.state->in = (unsigned char *)malloc(state.state->want);
|
||||
state.state->out = (unsigned char *)malloc(state.state->want << 1);
|
||||
if (state.state->in == NULL || state.state->out == NULL) {
|
||||
if (state.state->out != NULL)
|
||||
free(state.state->out);
|
||||
if (state.state->in != NULL)
|
||||
free(state.state->in);
|
||||
gz_error(state, Z_MEM_ERROR, "out of memory");
|
||||
return -1;
|
||||
}
|
||||
state.state->size = state.state->want;
|
||||
|
||||
/* allocate inflate memory */
|
||||
state.state->strm.zalloc = Z_NULL;
|
||||
state.state->strm.zfree = Z_NULL;
|
||||
state.state->strm.opaque = Z_NULL;
|
||||
state.state->strm.avail_in = 0;
|
||||
state.state->strm.next_in = Z_NULL;
|
||||
if (inflateInit2(&(state.state->strm), 15 + 16) != Z_OK) { /* gunzip */
|
||||
free(state.state->out);
|
||||
free(state.state->in);
|
||||
state.state->size = 0;
|
||||
gz_error(state, Z_MEM_ERROR, "out of memory");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* get at least the magic bytes in the input buffer */
|
||||
if (strm->avail_in < 2) {
|
||||
if (gz_avail(state) == -1)
|
||||
return -1;
|
||||
if (strm->avail_in == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* look for gzip magic bytes -- if there, do gzip decoding (note: there is
|
||||
a logical dilemma here when considering the case of a partially written
|
||||
gzip file, to wit, if a single 31 byte is written, then we cannot tell
|
||||
whether this is a single-byte file, or just a partially written gzip
|
||||
file -- for here we assume that if a gzip file is being written, then
|
||||
the header will be written in a single operation, so that reading a
|
||||
single byte is sufficient indication that it is not a gzip file) */
|
||||
//printf("strm->next_in[0]=%d strm->next_in[1]=%d\n", strm->next_in[0], strm->next_in[1]);
|
||||
if (strm->avail_in > 1 &&
|
||||
((strm->next_in[0] == 31 && strm->next_in[1] == 139)
|
||||
|| (strm->next_in[0] == 40 && strm->next_in[1] == 181))) { // zstd
|
||||
inflateReset(strm);
|
||||
state.state->how = GZIP;
|
||||
state.state->direct = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* no gzip header -- if we were decoding gzip before, then this is trailing
|
||||
garbage. Ignore the trailing garbage and finish. */
|
||||
if (state.state->direct == 0) {
|
||||
strm->avail_in = 0;
|
||||
state.state->eof = 1;
|
||||
state.state->x.have = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* doing raw i/o, copy any leftover input to output -- this assumes that
|
||||
the output buffer is larger than the input buffer, which also assures
|
||||
space for gzungetc() */
|
||||
state.state->x.next = state.state->out;
|
||||
if (strm->avail_in) {
|
||||
memcpy(state.state->x.next, strm->next_in, strm->avail_in);
|
||||
state.state->x.have = strm->avail_in;
|
||||
strm->avail_in = 0;
|
||||
}
|
||||
state.state->how = COPY;
|
||||
state.state->direct = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Decompress from input to the provided next_out and avail_out in the state.
|
||||
On return, state->x.have and state->x.next point to the just decompressed
|
||||
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. */
|
||||
local int gz_decomp(state)
|
||||
gz_statep state;
|
||||
{
|
||||
int ret = Z_OK;
|
||||
unsigned had;
|
||||
z_streamp strm = &(state.state->strm);
|
||||
|
||||
/* fill output buffer up to end of deflate stream */
|
||||
had = strm->avail_out;
|
||||
do {
|
||||
/* get more input for inflate() */
|
||||
if (strm->avail_in == 0 && gz_avail(state) == -1)
|
||||
return -1;
|
||||
if (strm->avail_in == 0) {
|
||||
gz_error(state, Z_BUF_ERROR, "unexpected end of file");
|
||||
break;
|
||||
}
|
||||
|
||||
/* decompress and handle errors */
|
||||
ret = inflate(strm, Z_NO_FLUSH);
|
||||
if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) {
|
||||
gz_error(state, Z_STREAM_ERROR,
|
||||
"internal error: inflate stream corrupt");
|
||||
return -1;
|
||||
}
|
||||
if (ret == Z_MEM_ERROR) {
|
||||
gz_error(state, Z_MEM_ERROR, "out of memory");
|
||||
return -1;
|
||||
}
|
||||
if (ret == Z_DATA_ERROR) { /* deflate stream invalid */
|
||||
gz_error(state, Z_DATA_ERROR,
|
||||
strm->msg == NULL ? "compressed data error" : strm->msg);
|
||||
return -1;
|
||||
}
|
||||
} while (strm->avail_out && ret != Z_STREAM_END);
|
||||
|
||||
/* update available output */
|
||||
state.state->x.have = had - strm->avail_out;
|
||||
state.state->x.next = strm->next_out - state.state->x.have;
|
||||
|
||||
/* if the gzip stream completed successfully, look for another */
|
||||
if (ret == Z_STREAM_END)
|
||||
state.state->how = LOOK;
|
||||
|
||||
/* good decompression */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Fetch data and put it in the output buffer. Assumes state->x.have is 0.
|
||||
Data is either copied from the input file or decompressed from the input
|
||||
file depending on state->how. If state->how is LOOK, then a gzip header is
|
||||
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. */
|
||||
local int gz_fetch(state)
|
||||
gz_statep state;
|
||||
{
|
||||
z_streamp strm = &(state.state->strm);
|
||||
|
||||
do {
|
||||
switch(state.state->how) {
|
||||
case LOOK: /* -> LOOK, COPY (only if never GZIP), or GZIP */
|
||||
if (gz_look(state) == -1)
|
||||
return -1;
|
||||
if (state.state->how == LOOK)
|
||||
return 0;
|
||||
break;
|
||||
case COPY: /* -> COPY */
|
||||
if (gz_load(state, state.state->out, state.state->size << 1, &(state.state->x.have))
|
||||
== -1)
|
||||
return -1;
|
||||
state.state->x.next = state.state->out;
|
||||
return 0;
|
||||
case GZIP: /* -> GZIP or LOOK (if end of gzip stream) */
|
||||
strm->avail_out = state.state->size << 1;
|
||||
strm->next_out = state.state->out;
|
||||
if (gz_decomp(state) == -1)
|
||||
return -1;
|
||||
}
|
||||
} while (state.state->x.have == 0 && (!state.state->eof || strm->avail_in));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */
|
||||
local int gz_skip(state, len)
|
||||
gz_statep state;
|
||||
z_off64_t len;
|
||||
{
|
||||
unsigned n;
|
||||
|
||||
/* skip over len bytes or reach end-of-file, whichever comes first */
|
||||
while (len)
|
||||
/* skip over whatever is in output buffer */
|
||||
if (state.state->x.have) {
|
||||
n = GT_OFF(state.state->x.have) || (z_off64_t)state.state->x.have > len ?
|
||||
(unsigned)len : state.state->x.have;
|
||||
state.state->x.have -= n;
|
||||
state.state->x.next += n;
|
||||
state.state->x.pos += n;
|
||||
len -= n;
|
||||
}
|
||||
|
||||
/* output buffer empty -- return if we're at the end of the input */
|
||||
else if (state.state->eof && state.state->strm.avail_in == 0)
|
||||
break;
|
||||
|
||||
/* need more data to skip -- load up output buffer */
|
||||
else {
|
||||
/* get more output, looking for header if required */
|
||||
if (gz_fetch(state) == -1)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzread(file, buf, len)
|
||||
gzFile file;
|
||||
voidp buf;
|
||||
unsigned len;
|
||||
{
|
||||
unsigned got, n;
|
||||
gz_statep state;
|
||||
z_streamp strm;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
strm = &(state.state->strm);
|
||||
|
||||
/* check that we're reading and that there's no (serious) error */
|
||||
if (state.state->mode != GZ_READ ||
|
||||
(state.state->err != Z_OK && state.state->err != Z_BUF_ERROR))
|
||||
return -1;
|
||||
|
||||
/* 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 -1;
|
||||
}
|
||||
|
||||
/* if len is zero, avoid unnecessary operations */
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
/* process a skip request */
|
||||
if (state.state->seek) {
|
||||
state.state->seek = 0;
|
||||
if (gz_skip(state, state.state->skip) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* get len bytes to buf, or less than len if at the end */
|
||||
got = 0;
|
||||
do {
|
||||
/* first just try copying data from the output buffer */
|
||||
if (state.state->x.have) {
|
||||
n = state.state->x.have > len ? len : state.state->x.have;
|
||||
memcpy(buf, state.state->x.next, n);
|
||||
state.state->x.next += n;
|
||||
state.state->x.have -= n;
|
||||
}
|
||||
|
||||
/* output buffer empty -- return if we're at the end of the input */
|
||||
else if (state.state->eof && strm->avail_in == 0) {
|
||||
state.state->past = 1; /* tried to read past end */
|
||||
break;
|
||||
}
|
||||
|
||||
/* need output data -- for small len or new stream load up our output
|
||||
buffer */
|
||||
else if (state.state->how == LOOK || len < (state.state->size << 1)) {
|
||||
/* get more output, looking for header if required */
|
||||
if (gz_fetch(state) == -1)
|
||||
return -1;
|
||||
continue; /* no progress yet -- go back to copy above */
|
||||
/* the copy above assures that we will leave with space in the
|
||||
output buffer, allowing at least one gzungetc() to succeed */
|
||||
}
|
||||
|
||||
/* large len -- read directly into user buffer */
|
||||
else if (state.state->how == COPY) { /* read directly */
|
||||
if (gz_load(state, (unsigned char *)buf, len, &n) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* large len -- decompress directly into user buffer */
|
||||
else { /* state->how == GZIP */
|
||||
strm->avail_out = len;
|
||||
strm->next_out = (unsigned char *)buf;
|
||||
if (gz_decomp(state) == -1)
|
||||
return -1;
|
||||
n = state.state->x.have;
|
||||
state.state->x.have = 0;
|
||||
}
|
||||
|
||||
/* update progress */
|
||||
len -= n;
|
||||
buf = (char *)buf + n;
|
||||
got += n;
|
||||
state.state->x.pos += n;
|
||||
} while (len);
|
||||
|
||||
/* return number of bytes read into user buffer (will fit in int) */
|
||||
return (int)got;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
#if ZLIB_VERNUM >= 0x1261
|
||||
#ifdef Z_PREFIX_SET
|
||||
# undef z_gzgetc
|
||||
#else
|
||||
# undef gzgetc
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ZLIB_VERNUM == 0x1260
|
||||
# undef gzgetc
|
||||
#endif
|
||||
|
||||
#if ZLIB_VERNUM <= 0x1250
|
||||
ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
|
||||
ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file));
|
||||
#endif
|
||||
|
||||
|
||||
int ZEXPORT gzgetc(file)
|
||||
gzFile file;
|
||||
{
|
||||
int ret;
|
||||
unsigned char buf[1];
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
|
||||
/* check that we're reading and that there's no (serious) error */
|
||||
if (state.state->mode != GZ_READ ||
|
||||
(state.state->err != Z_OK && state.state->err != Z_BUF_ERROR))
|
||||
return -1;
|
||||
|
||||
/* try output buffer (no need to check for skip request) */
|
||||
if (state.state->x.have) {
|
||||
state.state->x.have--;
|
||||
state.state->x.pos++;
|
||||
return *(state.state->x.next)++;
|
||||
}
|
||||
|
||||
/* nothing there -- try gzread() */
|
||||
ret = gzread(file, buf, 1);
|
||||
return ret < 1 ? -1 : buf[0];
|
||||
}
|
||||
|
||||
int ZEXPORT gzgetc_(file)
|
||||
gzFile file;
|
||||
{
|
||||
return gzgetc(file);
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzungetc(c, file)
|
||||
int c;
|
||||
gzFile file;
|
||||
{
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
|
||||
/* check that we're reading and that there's no (serious) error */
|
||||
if (state.state->mode != GZ_READ ||
|
||||
(state.state->err != Z_OK && state.state->err != Z_BUF_ERROR))
|
||||
return -1;
|
||||
|
||||
/* process a skip request */
|
||||
if (state.state->seek) {
|
||||
state.state->seek = 0;
|
||||
if (gz_skip(state, state.state->skip) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* can't push EOF */
|
||||
if (c < 0)
|
||||
return -1;
|
||||
|
||||
/* if output buffer empty, put byte at end (allows more pushing) */
|
||||
if (state.state->x.have == 0) {
|
||||
state.state->x.have = 1;
|
||||
state.state->x.next = state.state->out + (state.state->size << 1) - 1;
|
||||
state.state->x.next[0] = c;
|
||||
state.state->x.pos--;
|
||||
state.state->past = 0;
|
||||
return c;
|
||||
}
|
||||
|
||||
/* if no room, give up (must have already done a gzungetc()) */
|
||||
if (state.state->x.have == (state.state->size << 1)) {
|
||||
gz_error(state, Z_DATA_ERROR, "out of room to push characters");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* slide output data if needed and insert byte before existing data */
|
||||
if (state.state->x.next == state.state->out) {
|
||||
unsigned char *src = state.state->out + state.state->x.have;
|
||||
unsigned char *dest = state.state->out + (state.state->size << 1);
|
||||
while (src > state.state->out)
|
||||
*--dest = *--src;
|
||||
state.state->x.next = dest;
|
||||
}
|
||||
state.state->x.have++;
|
||||
state.state->x.next--;
|
||||
state.state->x.next[0] = c;
|
||||
state.state->x.pos--;
|
||||
state.state->past = 0;
|
||||
return c;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
char * ZEXPORT gzgets(file, buf, len)
|
||||
gzFile file;
|
||||
char *buf;
|
||||
int len;
|
||||
{
|
||||
unsigned left, n;
|
||||
char *str;
|
||||
unsigned char *eol;
|
||||
gz_statep state;
|
||||
|
||||
/* check parameters and get internal structure */
|
||||
if (file == NULL || buf == NULL || len < 1)
|
||||
return NULL;
|
||||
state = (gz_statep)file;
|
||||
|
||||
/* check that we're reading and that there's no (serious) error */
|
||||
if (state.state->mode != GZ_READ ||
|
||||
(state.state->err != Z_OK && state.state->err != Z_BUF_ERROR))
|
||||
return NULL;
|
||||
|
||||
/* process a skip request */
|
||||
if (state.state->seek) {
|
||||
state.state->seek = 0;
|
||||
if (gz_skip(state, state.state->skip) == -1)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* copy output bytes up to new line or len - 1, whichever comes first --
|
||||
append a terminating zero to the string (we don't check for a zero in
|
||||
the contents, let the user worry about that) */
|
||||
str = buf;
|
||||
left = (unsigned)len - 1;
|
||||
if (left) do {
|
||||
/* assure that something is in the output buffer */
|
||||
if (state.state->x.have == 0 && gz_fetch(state) == -1)
|
||||
return NULL; /* error */
|
||||
if (state.state->x.have == 0) { /* end of file */
|
||||
state.state->past = 1; /* read past end */
|
||||
break; /* return what we have */
|
||||
}
|
||||
|
||||
/* look for end-of-line in current output buffer */
|
||||
n = state.state->x.have > left ? left : state.state->x.have;
|
||||
eol = (unsigned char *)memchr(state.state->x.next, '\n', n);
|
||||
if (eol != NULL)
|
||||
n = (unsigned)(eol - state.state->x.next) + 1;
|
||||
|
||||
/* copy through end-of-line, or remainder if not found */
|
||||
memcpy(buf, state.state->x.next, n);
|
||||
state.state->x.have -= n;
|
||||
state.state->x.next += n;
|
||||
state.state->x.pos += n;
|
||||
left -= n;
|
||||
buf += n;
|
||||
} while (left && eol == NULL);
|
||||
|
||||
/* return terminated string, or if nothing, end of file */
|
||||
if (buf == str)
|
||||
return NULL;
|
||||
buf[0] = 0;
|
||||
return str;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzdirect(file)
|
||||
gzFile file;
|
||||
{
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return 0;
|
||||
state = (gz_statep)file;
|
||||
|
||||
/* if the state is not known, but we can find out, then do so (this is
|
||||
mainly for right after a gzopen() or gzdopen()) */
|
||||
if (state.state->mode == GZ_READ && state.state->how == LOOK && state.state->x.have == 0)
|
||||
(void)gz_look(state);
|
||||
|
||||
/* return 1 if transparent, 0 if processing a gzip stream */
|
||||
return state.state->direct;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzclose_r(file)
|
||||
gzFile file;
|
||||
{
|
||||
int ret, err;
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return Z_STREAM_ERROR;
|
||||
state = (gz_statep)file;
|
||||
|
||||
/* check that we're reading */
|
||||
if (state.state->mode != GZ_READ)
|
||||
return Z_STREAM_ERROR;
|
||||
|
||||
/* free memory and close file */
|
||||
if (state.state->size) {
|
||||
inflateEnd(&(state.state->strm));
|
||||
free(state.state->out);
|
||||
free(state.state->in);
|
||||
}
|
||||
err = state.state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK;
|
||||
gz_error(state, Z_OK, NULL);
|
||||
free(state.state->path);
|
||||
ret = close(state.state->fd);
|
||||
free(state.state);
|
||||
return ret ? Z_ERRNO : err;
|
||||
}
|
|
@ -0,0 +1,580 @@
|
|||
/* gzwrite.c contains minimal changes required to be compiled with zlibWrapper:
|
||||
* - gz_statep was converted to union to work with -Wstrict-aliasing=1 */
|
||||
|
||||
/* gzwrite.c -- zlib functions for writing gzip files
|
||||
* Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "gzguts.h"
|
||||
|
||||
/* 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));
|
||||
|
||||
/* Initialize state for writing a gzip file. Mark initialization by setting
|
||||
state->size to non-zero. Return -1 on failure or 0 on success. */
|
||||
local int gz_init(state)
|
||||
gz_statep state;
|
||||
{
|
||||
int ret;
|
||||
z_streamp strm = &(state.state->strm);
|
||||
|
||||
/* allocate input buffer */
|
||||
state.state->in = (unsigned char *)malloc(state.state->want);
|
||||
if (state.state->in == NULL) {
|
||||
gz_error(state, Z_MEM_ERROR, "out of memory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* only need output buffer and deflate state if compressing */
|
||||
if (!state.state->direct) {
|
||||
/* allocate output buffer */
|
||||
state.state->out = (unsigned char *)malloc(state.state->want);
|
||||
if (state.state->out == NULL) {
|
||||
free(state.state->in);
|
||||
gz_error(state, Z_MEM_ERROR, "out of memory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* allocate deflate memory, set up for gzip compression */
|
||||
strm->zalloc = Z_NULL;
|
||||
strm->zfree = Z_NULL;
|
||||
strm->opaque = Z_NULL;
|
||||
ret = deflateInit2(strm, state.state->level, Z_DEFLATED,
|
||||
MAX_WBITS + 16, DEF_MEM_LEVEL, state.state->strategy);
|
||||
if (ret != Z_OK) {
|
||||
free(state.state->out);
|
||||
free(state.state->in);
|
||||
gz_error(state, Z_MEM_ERROR, "out of memory");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* mark state as initialized */
|
||||
state.state->size = state.state->want;
|
||||
|
||||
/* initialize write buffer if compressing */
|
||||
if (!state.state->direct) {
|
||||
strm->avail_out = state.state->size;
|
||||
strm->next_out = state.state->out;
|
||||
state.state->x.next = strm->next_out;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 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.
|
||||
flush is assumed to be a valid 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. */
|
||||
local int gz_comp(state, flush)
|
||||
gz_statep state;
|
||||
int flush;
|
||||
{
|
||||
int ret, got;
|
||||
unsigned have;
|
||||
z_streamp strm = &(state.state->strm);
|
||||
|
||||
/* allocate memory if this is the first time through */
|
||||
if (state.state->size == 0 && gz_init(state) == -1)
|
||||
return -1;
|
||||
|
||||
/* write directly if requested */
|
||||
if (state.state->direct) {
|
||||
got = write(state.state->fd, strm->next_in, strm->avail_in);
|
||||
if (got < 0 || (unsigned)got != strm->avail_in) {
|
||||
gz_error(state, Z_ERRNO, zstrerror());
|
||||
return -1;
|
||||
}
|
||||
strm->avail_in = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* run deflate() on provided input until it produces no more output */
|
||||
ret = Z_OK;
|
||||
do {
|
||||
/* write out current buffer contents if full, or if flushing, but if
|
||||
doing Z_FINISH then don't write until we get to Z_STREAM_END */
|
||||
if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
|
||||
(flush != Z_FINISH || ret == Z_STREAM_END))) {
|
||||
have = (unsigned)(strm->next_out - state.state->x.next);
|
||||
if (have && ((got = write(state.state->fd, state.state->x.next, have)) < 0 ||
|
||||
(unsigned)got != have)) {
|
||||
gz_error(state, Z_ERRNO, zstrerror());
|
||||
return -1;
|
||||
}
|
||||
if (strm->avail_out == 0) {
|
||||
strm->avail_out = state.state->size;
|
||||
strm->next_out = state.state->out;
|
||||
}
|
||||
state.state->x.next = strm->next_out;
|
||||
}
|
||||
|
||||
/* compress */
|
||||
have = strm->avail_out;
|
||||
ret = deflate(strm, flush);
|
||||
if (ret == Z_STREAM_ERROR) {
|
||||
gz_error(state, Z_STREAM_ERROR,
|
||||
"internal error: deflate stream corrupt");
|
||||
return -1;
|
||||
}
|
||||
have -= strm->avail_out;
|
||||
} while (have);
|
||||
|
||||
/* if that completed a deflate stream, allow another to start */
|
||||
if (flush == Z_FINISH)
|
||||
deflateReset(strm);
|
||||
|
||||
/* all done, no errors */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Compress len zeros to output. Return -1 on error, 0 on success. */
|
||||
local int gz_zero(state, len)
|
||||
gz_statep state;
|
||||
z_off64_t len;
|
||||
{
|
||||
int first;
|
||||
unsigned n;
|
||||
z_streamp strm = &(state.state->strm);
|
||||
|
||||
/* consume whatever's left in the input buffer */
|
||||
if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
|
||||
return -1;
|
||||
|
||||
/* compress len zeros (len guaranteed > 0) */
|
||||
first = 1;
|
||||
while (len) {
|
||||
n = GT_OFF(state.state->size) || (z_off64_t)state.state->size > len ?
|
||||
(unsigned)len : state.state->size;
|
||||
if (first) {
|
||||
memset(state.state->in, 0, n);
|
||||
first = 0;
|
||||
}
|
||||
strm->avail_in = n;
|
||||
strm->next_in = state.state->in;
|
||||
state.state->x.pos += n;
|
||||
if (gz_comp(state, Z_NO_FLUSH) == -1)
|
||||
return -1;
|
||||
len -= n;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzwrite(file, buf, len)
|
||||
gzFile file;
|
||||
voidpc buf;
|
||||
unsigned len;
|
||||
{
|
||||
unsigned put = len;
|
||||
gz_statep state;
|
||||
z_streamp strm;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
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 == 0)
|
||||
return 0;
|
||||
|
||||
/* allocate memory if this is the first time through */
|
||||
if (state.state->size == 0 && gz_init(state) == -1)
|
||||
return 0;
|
||||
|
||||
/* check for seek request */
|
||||
if (state.state->seek) {
|
||||
state.state->seek = 0;
|
||||
if (gz_zero(state, state.state->skip) == -1)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* for small len, copy to input buffer, otherwise compress directly */
|
||||
if (len < state.state->size) {
|
||||
/* copy to input buffer, compress when full */
|
||||
do {
|
||||
unsigned have, copy;
|
||||
|
||||
if (strm->avail_in == 0)
|
||||
strm->next_in = state.state->in;
|
||||
have = (unsigned)((strm->next_in + strm->avail_in) - state.state->in);
|
||||
copy = state.state->size - have;
|
||||
if (copy > len)
|
||||
copy = len;
|
||||
memcpy(state.state->in + have, buf, copy);
|
||||
strm->avail_in += copy;
|
||||
state.state->x.pos += copy;
|
||||
buf = (const char *)buf + copy;
|
||||
len -= copy;
|
||||
if (len && gz_comp(state, Z_NO_FLUSH) == -1)
|
||||
return 0;
|
||||
} while (len);
|
||||
}
|
||||
else {
|
||||
/* consume whatever's left in the input buffer */
|
||||
if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
|
||||
return 0;
|
||||
|
||||
/* directly compress user buffer to file */
|
||||
strm->avail_in = len;
|
||||
strm->next_in = (z_const Bytef *)buf;
|
||||
state.state->x.pos += len;
|
||||
if (gz_comp(state, Z_NO_FLUSH) == -1)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* input was all buffered or compressed (put will fit in int) */
|
||||
return (int)put;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzputc(file, c)
|
||||
gzFile file;
|
||||
int c;
|
||||
{
|
||||
unsigned have;
|
||||
unsigned char buf[1];
|
||||
gz_statep state;
|
||||
z_streamp strm;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
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 -1;
|
||||
|
||||
/* check for seek request */
|
||||
if (state.state->seek) {
|
||||
state.state->seek = 0;
|
||||
if (gz_zero(state, state.state->skip) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* try writing to input buffer for speed (state->size == 0 if buffer not
|
||||
initialized) */
|
||||
if (state.state->size) {
|
||||
if (strm->avail_in == 0)
|
||||
strm->next_in = state.state->in;
|
||||
have = (unsigned)((strm->next_in + strm->avail_in) - state.state->in);
|
||||
if (have < state.state->size) {
|
||||
state.state->in[have] = c;
|
||||
strm->avail_in++;
|
||||
state.state->x.pos++;
|
||||
return c & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
/* no room in buffer or not initialized, use gz_write() */
|
||||
buf[0] = c;
|
||||
if (gzwrite(file, buf, 1) != 1)
|
||||
return -1;
|
||||
return c & 0xff;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzputs(file, str)
|
||||
gzFile file;
|
||||
const char *str;
|
||||
{
|
||||
int ret;
|
||||
unsigned len;
|
||||
|
||||
/* write string */
|
||||
len = (unsigned)strlen(str);
|
||||
ret = gzwrite(file, str, len);
|
||||
return ret == 0 && len != 0 ? -1 : ret;
|
||||
}
|
||||
|
||||
#if defined(STDC) || defined(Z_HAVE_STDARG_H)
|
||||
#include <stdarg.h>
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va)
|
||||
{
|
||||
int size, len;
|
||||
gz_statep state;
|
||||
z_streamp strm;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
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;
|
||||
|
||||
/* make sure we have some buffer space */
|
||||
if (state.state->size == 0 && gz_init(state) == -1)
|
||||
return 0;
|
||||
|
||||
/* check for seek request */
|
||||
if (state.state->seek) {
|
||||
state.state->seek = 0;
|
||||
if (gz_zero(state, state.state->skip) == -1)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* consume whatever's left in the input buffer */
|
||||
if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
|
||||
return 0;
|
||||
|
||||
/* do the printf() into the input buffer, put length in len */
|
||||
size = (int)(state.state->size);
|
||||
state.state->in[size - 1] = 0;
|
||||
#ifdef NO_vsnprintf
|
||||
# ifdef HAS_vsprintf_void
|
||||
(void)vsprintf((char *)(state.state->in), format, va);
|
||||
for (len = 0; len < size; len++)
|
||||
if (state.state->in[len] == 0) break;
|
||||
# else
|
||||
len = vsprintf((char *)(state.state->in), format, va);
|
||||
# endif
|
||||
#else
|
||||
# ifdef HAS_vsnprintf_void
|
||||
(void)vsnprintf((char *)(state.state->in), size, format, va);
|
||||
len = strlen((char *)(state.state->in));
|
||||
# else
|
||||
len = vsnprintf((char *)(state.state->in), size, format, va);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* check that printf() results fit in buffer */
|
||||
if (len <= 0 || len >= (int)size || state.state->in[size - 1] != 0)
|
||||
return 0;
|
||||
|
||||
/* update buffer and position, defer compression until needed */
|
||||
strm->avail_in = (unsigned)len;
|
||||
strm->next_in = state.state->in;
|
||||
state.state->x.pos += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
int ZEXPORTVA gzprintf(gzFile file, const char *format, ...)
|
||||
{
|
||||
va_list va;
|
||||
int ret;
|
||||
|
||||
va_start(va, format);
|
||||
ret = gzvprintf(file, format, va);
|
||||
va_end(va);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else /* !STDC && !Z_HAVE_STDARG_H */
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
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;
|
||||
{
|
||||
int size, len;
|
||||
gz_statep state;
|
||||
z_streamp strm;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
strm = &(state.state->strm);
|
||||
|
||||
/* check that can really pass pointer in ints */
|
||||
if (sizeof(int) != sizeof(void *))
|
||||
return 0;
|
||||
|
||||
/* check that we're writing and that there's no error */
|
||||
if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)
|
||||
return 0;
|
||||
|
||||
/* make sure we have some buffer space */
|
||||
if (state.state->size == 0 && gz_init(state) == -1)
|
||||
return 0;
|
||||
|
||||
/* check for seek request */
|
||||
if (state.state->seek) {
|
||||
state.state->seek = 0;
|
||||
if (gz_zero(state, state.state->skip) == -1)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* consume whatever's left in the input buffer */
|
||||
if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
|
||||
return 0;
|
||||
|
||||
/* do the printf() into the input buffer, put length in len */
|
||||
size = (int)(state.state->size);
|
||||
state.state->in[size - 1] = 0;
|
||||
#ifdef NO_snprintf
|
||||
# ifdef HAS_sprintf_void
|
||||
sprintf((char *)(state.state->in), 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 (state.state->in[len] == 0) break;
|
||||
# else
|
||||
len = sprintf((char *)(state.state->in), 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((char *)(state.state->in), size, format, a1, a2, a3, a4, a5, a6, a7, a8,
|
||||
a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
|
||||
len = strlen((char *)(state.state->in));
|
||||
# else
|
||||
len = snprintf((char *)(state.state->in), 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 >= (int)size || state.state->in[size - 1] != 0)
|
||||
return 0;
|
||||
|
||||
/* update buffer and position, defer compression until needed */
|
||||
strm->avail_in = (unsigned)len;
|
||||
strm->next_in = state.state->in;
|
||||
state.state->x.pos += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzflush(file, flush)
|
||||
gzFile file;
|
||||
int flush;
|
||||
{
|
||||
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 Z_STREAM_ERROR;
|
||||
|
||||
/* check flush parameter */
|
||||
if (flush < 0 || flush > Z_FINISH)
|
||||
return Z_STREAM_ERROR;
|
||||
|
||||
/* check for seek request */
|
||||
if (state.state->seek) {
|
||||
state.state->seek = 0;
|
||||
if (gz_zero(state, state.state->skip) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* compress remaining data with requested flush */
|
||||
gz_comp(state, flush);
|
||||
return state.state->err;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzsetparams(file, level, strategy)
|
||||
gzFile file;
|
||||
int level;
|
||||
int strategy;
|
||||
{
|
||||
gz_statep state;
|
||||
z_streamp strm;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return Z_STREAM_ERROR;
|
||||
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 Z_STREAM_ERROR;
|
||||
|
||||
/* if no change is requested, then do nothing */
|
||||
if (level == state.state->level && strategy == state.state->strategy)
|
||||
return Z_OK;
|
||||
|
||||
/* check for seek request */
|
||||
if (state.state->seek) {
|
||||
state.state->seek = 0;
|
||||
if (gz_zero(state, state.state->skip) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* change compression parameters for subsequent input */
|
||||
if (state.state->size) {
|
||||
/* flush previous input with previous parameters before changing */
|
||||
if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1)
|
||||
return state.state->err;
|
||||
deflateParams(strm, level, strategy);
|
||||
}
|
||||
state.state->level = level;
|
||||
state.state->strategy = strategy;
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzclose_w(file)
|
||||
gzFile file;
|
||||
{
|
||||
int ret = Z_OK;
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return Z_STREAM_ERROR;
|
||||
state = (gz_statep)file;
|
||||
|
||||
/* check that we're writing */
|
||||
if (state.state->mode != GZ_WRITE)
|
||||
return Z_STREAM_ERROR;
|
||||
|
||||
/* check for seek request */
|
||||
if (state.state->seek) {
|
||||
state.state->seek = 0;
|
||||
if (gz_zero(state, state.state->skip) == -1)
|
||||
ret = state.state->err;
|
||||
}
|
||||
|
||||
/* flush, free memory, and close file */
|
||||
if (gz_comp(state, Z_FINISH) == -1)
|
||||
ret = state.state->err;
|
||||
if (state.state->size) {
|
||||
if (!state.state->direct) {
|
||||
(void)deflateEnd(&(state.state->strm));
|
||||
free(state.state->out);
|
||||
}
|
||||
free(state.state->in);
|
||||
}
|
||||
gz_error(state, Z_OK, NULL);
|
||||
free(state.state->path);
|
||||
if (close(state.state->fd) == -1)
|
||||
ret = Z_ERRNO;
|
||||
free(state.state);
|
||||
return ret;
|
||||
}
|
|
@ -24,8 +24,8 @@
|
|||
#define ZSTD_HEADERSIZE ZSTD_frameHeaderSize_min
|
||||
#define ZWRAP_DEFAULT_CLEVEL 3 /* Z_DEFAULT_COMPRESSION is translated to ZWRAP_DEFAULT_CLEVEL for zstd */
|
||||
|
||||
#define LOG_WRAPPERC(...) /* printf(__VA_ARGS__) */
|
||||
#define LOG_WRAPPERD(...) /* printf(__VA_ARGS__) */
|
||||
#define LOG_WRAPPERC(...) /* printf(__VA_ARGS__) */
|
||||
#define LOG_WRAPPERD(...) /* printf(__VA_ARGS__) */
|
||||
|
||||
#define FINISH_WITH_GZ_ERR(msg) { (void)msg; return Z_STREAM_ERROR; }
|
||||
#define FINISH_WITH_NULL_ERR(msg) { (void)msg; return NULL; }
|
||||
|
@ -81,6 +81,7 @@ typedef enum { ZWRAP_useInit, ZWRAP_useReset, ZWRAP_streamEnd } ZWRAP_state_t;
|
|||
typedef struct {
|
||||
ZSTD_CStream* zbc;
|
||||
int compressionLevel;
|
||||
int streamEnd;
|
||||
ZSTD_customMem customMem;
|
||||
z_stream allocFunc; /* copy of zalloc, zfree, opaque */
|
||||
ZSTD_inBuffer inBuffer;
|
||||
|
@ -187,6 +188,7 @@ ZEXTERN int ZEXPORT z_deflateInit_ OF((z_streamp strm, int level,
|
|||
if (level == Z_DEFAULT_COMPRESSION)
|
||||
level = ZWRAP_DEFAULT_CLEVEL;
|
||||
|
||||
zwc->streamEnd = 0;
|
||||
zwc->compressionLevel = level;
|
||||
strm->state = (struct internal_state*) zwc; /* use state which in not used by user */
|
||||
strm->total_in = 0;
|
||||
|
@ -214,6 +216,10 @@ int ZWRAP_deflateReset_keepDict(z_streamp strm)
|
|||
if (!g_ZWRAP_useZSTDcompression)
|
||||
return deflateReset(strm);
|
||||
|
||||
{ ZWRAP_CCtx* zwc = (ZWRAP_CCtx*) strm->state;
|
||||
if (zwc) zwc->streamEnd = 0;
|
||||
}
|
||||
|
||||
strm->total_in = 0;
|
||||
strm->total_out = 0;
|
||||
strm->adler = 0;
|
||||
|
@ -230,7 +236,7 @@ ZEXTERN int ZEXPORT z_deflateReset OF((z_streamp strm))
|
|||
ZWRAP_deflateReset_keepDict(strm);
|
||||
|
||||
{ ZWRAP_CCtx* zwc = (ZWRAP_CCtx*) strm->state;
|
||||
if (zwc) zwc->comprState = 0;
|
||||
if (zwc) zwc->comprState = ZWRAP_useInit;
|
||||
}
|
||||
return Z_OK;
|
||||
}
|
||||
|
@ -315,10 +321,16 @@ ZEXTERN int ZEXPORT z_deflate OF((z_streamp strm, int flush))
|
|||
strm->avail_in -= zwc->inBuffer.pos;
|
||||
}
|
||||
|
||||
if (flush == Z_FULL_FLUSH || flush == Z_BLOCK || flush == Z_TREES) return ZWRAPC_finishWithErrorMsg(strm, "Z_FULL_FLUSH, Z_BLOCK and Z_TREES are not supported!");
|
||||
if (flush == Z_FULL_FLUSH
|
||||
#if ZLIB_VERNUM >= 0x1240
|
||||
|| flush == Z_TREES
|
||||
#endif
|
||||
|| flush == Z_BLOCK)
|
||||
return ZWRAPC_finishWithErrorMsg(strm, "Z_FULL_FLUSH, Z_BLOCK and Z_TREES are not supported!");
|
||||
|
||||
if (flush == Z_FINISH) {
|
||||
size_t bytesLeft;
|
||||
if (zwc->streamEnd) return Z_STREAM_END;
|
||||
zwc->outBuffer.dst = strm->next_out;
|
||||
zwc->outBuffer.size = strm->avail_out;
|
||||
zwc->outBuffer.pos = 0;
|
||||
|
@ -328,7 +340,7 @@ ZEXTERN int ZEXPORT z_deflate OF((z_streamp strm, int flush))
|
|||
strm->next_out += zwc->outBuffer.pos;
|
||||
strm->total_out += zwc->outBuffer.pos;
|
||||
strm->avail_out -= zwc->outBuffer.pos;
|
||||
if (bytesLeft == 0) { LOG_WRAPPERC("Z_STREAM_END2 strm->total_in=%d strm->avail_out=%d strm->total_out=%d\n", (int)strm->total_in, (int)strm->avail_out, (int)strm->total_out); return Z_STREAM_END; }
|
||||
if (bytesLeft == 0) { zwc->streamEnd = 1; LOG_WRAPPERC("Z_STREAM_END2 strm->total_in=%d strm->avail_out=%d strm->total_out=%d\n", (int)strm->total_in, (int)strm->avail_out, (int)strm->total_out); return Z_STREAM_END; }
|
||||
}
|
||||
else
|
||||
if (flush == Z_SYNC_FLUSH || flush == Z_PARTIAL_FLUSH) {
|
||||
|
@ -519,6 +531,7 @@ ZEXTERN int ZEXPORT z_inflateInit2_ OF((z_streamp strm, int windowBits,
|
|||
|
||||
{
|
||||
int ret = z_inflateInit_ (strm, version, stream_size);
|
||||
LOG_WRAPPERD("- inflateInit2 windowBits=%d\n", windowBits);
|
||||
if (ret == Z_OK) {
|
||||
ZWRAP_DCtx* zwd = (ZWRAP_DCtx*)strm->state;
|
||||
if (zwd == NULL) return Z_STREAM_ERROR;
|
||||
|
@ -1015,220 +1028,6 @@ ZEXTERN int ZEXPORT z_uncompress OF((Bytef *dest, uLongf *destLen,
|
|||
return Z_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* gzip file access functions */
|
||||
ZEXTERN gzFile ZEXPORT z_gzopen OF((const char *path, const char *mode))
|
||||
{
|
||||
if (!g_ZWRAP_useZSTDcompression)
|
||||
return gzopen(path, mode);
|
||||
FINISH_WITH_NULL_ERR("gzopen is not supported!");
|
||||
}
|
||||
|
||||
|
||||
ZEXTERN gzFile ZEXPORT z_gzdopen OF((int fd, const char *mode))
|
||||
{
|
||||
if (!g_ZWRAP_useZSTDcompression)
|
||||
return gzdopen(fd, mode);
|
||||
FINISH_WITH_NULL_ERR("gzdopen is not supported!");
|
||||
}
|
||||
|
||||
|
||||
#if ZLIB_VERNUM >= 0x1240
|
||||
ZEXTERN int ZEXPORT z_gzbuffer OF((gzFile file, unsigned size))
|
||||
{
|
||||
if (!g_ZWRAP_useZSTDcompression)
|
||||
return gzbuffer(file, size);
|
||||
FINISH_WITH_GZ_ERR("gzbuffer is not supported!");
|
||||
}
|
||||
|
||||
|
||||
ZEXTERN z_off_t ZEXPORT z_gzoffset OF((gzFile file))
|
||||
{
|
||||
if (!g_ZWRAP_useZSTDcompression)
|
||||
return gzoffset(file);
|
||||
FINISH_WITH_GZ_ERR("gzoffset is not supported!");
|
||||
}
|
||||
|
||||
|
||||
ZEXTERN int ZEXPORT z_gzclose_r OF((gzFile file))
|
||||
{
|
||||
if (!g_ZWRAP_useZSTDcompression)
|
||||
return gzclose_r(file);
|
||||
FINISH_WITH_GZ_ERR("gzclose_r is not supported!");
|
||||
}
|
||||
|
||||
|
||||
ZEXTERN int ZEXPORT z_gzclose_w OF((gzFile file))
|
||||
{
|
||||
if (!g_ZWRAP_useZSTDcompression)
|
||||
return gzclose_w(file);
|
||||
FINISH_WITH_GZ_ERR("gzclose_w is not supported!");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
ZEXTERN int ZEXPORT z_gzsetparams OF((gzFile file, int level, int strategy))
|
||||
{
|
||||
if (!g_ZWRAP_useZSTDcompression)
|
||||
return gzsetparams(file, level, strategy);
|
||||
FINISH_WITH_GZ_ERR("gzsetparams is not supported!");
|
||||
}
|
||||
|
||||
|
||||
ZEXTERN int ZEXPORT z_gzread OF((gzFile file, voidp buf, unsigned len))
|
||||
{
|
||||
if (!g_ZWRAP_useZSTDcompression)
|
||||
return gzread(file, buf, len);
|
||||
FINISH_WITH_GZ_ERR("gzread is not supported!");
|
||||
}
|
||||
|
||||
|
||||
ZEXTERN int ZEXPORT z_gzwrite OF((gzFile file,
|
||||
voidpc buf, unsigned len))
|
||||
{
|
||||
if (!g_ZWRAP_useZSTDcompression)
|
||||
return gzwrite(file, buf, len);
|
||||
FINISH_WITH_GZ_ERR("gzwrite is not supported!");
|
||||
}
|
||||
|
||||
|
||||
#if ZLIB_VERNUM >= 0x1260
|
||||
ZEXTERN int ZEXPORTVA z_gzprintf Z_ARG((gzFile file, const char *format, ...))
|
||||
#else
|
||||
ZEXTERN int ZEXPORTVA z_gzprintf OF((gzFile file, const char *format, ...))
|
||||
#endif
|
||||
{
|
||||
if (!g_ZWRAP_useZSTDcompression) {
|
||||
int ret;
|
||||
char buf[1024];
|
||||
va_list args;
|
||||
va_start (args, format);
|
||||
ret = vsprintf (buf, format, args);
|
||||
va_end (args);
|
||||
|
||||
ret = gzprintf(file, buf);
|
||||
return ret;
|
||||
}
|
||||
FINISH_WITH_GZ_ERR("gzprintf is not supported!");
|
||||
}
|
||||
|
||||
|
||||
ZEXTERN int ZEXPORT z_gzputs OF((gzFile file, const char *s))
|
||||
{
|
||||
if (!g_ZWRAP_useZSTDcompression)
|
||||
return gzputs(file, s);
|
||||
FINISH_WITH_GZ_ERR("gzputs is not supported!");
|
||||
}
|
||||
|
||||
|
||||
ZEXTERN char * ZEXPORT z_gzgets OF((gzFile file, char *buf, int len))
|
||||
{
|
||||
if (!g_ZWRAP_useZSTDcompression)
|
||||
return gzgets(file, buf, len);
|
||||
FINISH_WITH_NULL_ERR("gzgets is not supported!");
|
||||
}
|
||||
|
||||
|
||||
ZEXTERN int ZEXPORT z_gzputc OF((gzFile file, int c))
|
||||
{
|
||||
if (!g_ZWRAP_useZSTDcompression)
|
||||
return gzputc(file, c);
|
||||
FINISH_WITH_GZ_ERR("gzputc is not supported!");
|
||||
}
|
||||
|
||||
|
||||
#if ZLIB_VERNUM == 0x1260
|
||||
ZEXTERN int ZEXPORT z_gzgetc_ OF((gzFile file))
|
||||
#else
|
||||
ZEXTERN int ZEXPORT z_gzgetc OF((gzFile file))
|
||||
#endif
|
||||
{
|
||||
if (!g_ZWRAP_useZSTDcompression)
|
||||
return gzgetc(file);
|
||||
FINISH_WITH_GZ_ERR("gzgetc is not supported!");
|
||||
}
|
||||
|
||||
|
||||
ZEXTERN int ZEXPORT z_gzungetc OF((int c, gzFile file))
|
||||
{
|
||||
if (!g_ZWRAP_useZSTDcompression)
|
||||
return gzungetc(c, file);
|
||||
FINISH_WITH_GZ_ERR("gzungetc is not supported!");
|
||||
}
|
||||
|
||||
|
||||
ZEXTERN int ZEXPORT z_gzflush OF((gzFile file, int flush))
|
||||
{
|
||||
if (!g_ZWRAP_useZSTDcompression)
|
||||
return gzflush(file, flush);
|
||||
FINISH_WITH_GZ_ERR("gzflush is not supported!");
|
||||
}
|
||||
|
||||
|
||||
ZEXTERN z_off_t ZEXPORT z_gzseek OF((gzFile file, z_off_t offset, int whence))
|
||||
{
|
||||
if (!g_ZWRAP_useZSTDcompression)
|
||||
return gzseek(file, offset, whence);
|
||||
FINISH_WITH_GZ_ERR("gzseek is not supported!");
|
||||
}
|
||||
|
||||
|
||||
ZEXTERN int ZEXPORT z_gzrewind OF((gzFile file))
|
||||
{
|
||||
if (!g_ZWRAP_useZSTDcompression)
|
||||
return gzrewind(file);
|
||||
FINISH_WITH_GZ_ERR("gzrewind is not supported!");
|
||||
}
|
||||
|
||||
|
||||
ZEXTERN z_off_t ZEXPORT z_gztell OF((gzFile file))
|
||||
{
|
||||
if (!g_ZWRAP_useZSTDcompression)
|
||||
return gztell(file);
|
||||
FINISH_WITH_GZ_ERR("gztell is not supported!");
|
||||
}
|
||||
|
||||
|
||||
ZEXTERN int ZEXPORT z_gzeof OF((gzFile file))
|
||||
{
|
||||
if (!g_ZWRAP_useZSTDcompression)
|
||||
return gzeof(file);
|
||||
FINISH_WITH_GZ_ERR("gzeof is not supported!");
|
||||
}
|
||||
|
||||
|
||||
ZEXTERN int ZEXPORT z_gzdirect OF((gzFile file))
|
||||
{
|
||||
if (!g_ZWRAP_useZSTDcompression)
|
||||
return gzdirect(file);
|
||||
FINISH_WITH_GZ_ERR("gzdirect is not supported!");
|
||||
}
|
||||
|
||||
|
||||
ZEXTERN int ZEXPORT z_gzclose OF((gzFile file))
|
||||
{
|
||||
if (!g_ZWRAP_useZSTDcompression)
|
||||
return gzclose(file);
|
||||
FINISH_WITH_GZ_ERR("gzclose is not supported!");
|
||||
}
|
||||
|
||||
|
||||
ZEXTERN const char * ZEXPORT z_gzerror OF((gzFile file, int *errnum))
|
||||
{
|
||||
if (!g_ZWRAP_useZSTDcompression)
|
||||
return gzerror(file, errnum);
|
||||
FINISH_WITH_NULL_ERR("gzerror is not supported!");
|
||||
}
|
||||
|
||||
|
||||
ZEXTERN void ZEXPORT z_gzclearerr OF((gzFile file))
|
||||
{
|
||||
if (!g_ZWRAP_useZSTDcompression)
|
||||
gzclearerr(file);
|
||||
}
|
||||
|
||||
|
||||
#endif /* !Z_SOLO */
|
||||
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ extern "C" {
|
|||
|
||||
#define ZLIB_CONST
|
||||
#define Z_PREFIX
|
||||
#define ZLIB_INTERNAL /* disables gz*64 functions but fixes zlib 1.2.4 with Z_PREFIX */
|
||||
#include <zlib.h>
|
||||
|
||||
#if !defined(z_const)
|
||||
|
|
Loading…
Reference in New Issue