compressutils.c
Go to the documentation of this file.
/* SPDX-FileCopyrightText: 2013-2023 Greenbone AG
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#if !defined(ZLIB_CONST)
#define ZLIB_CONST
#endif
#define _GNU_SOURCE
#include "compressutils.h"
#include <glib.h> /* for g_free, g_malloc0 */
#include <zlib.h> /* for z_stream, Z_NULL, Z_OK, Z_BUF_ERROR, Z_STREAM_END */
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "libgvm util"
void *
gvm_compress (const void *src, unsigned long srclen, unsigned long *dstlen)
{
unsigned long buflen = srclen * 2;
if (src == NULL || dstlen == NULL)
return NULL;
if (buflen < 30)
buflen = 30;
while (1)
{
int err;
void *buffer;
z_stream strm;
/* Initialize deflate state */
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = srclen;
#ifdef z_const
strm.next_in = src;
#else
/* Workaround for older zlib. */
strm.next_in = (void *) src;
#endif
if (deflateInit (&strm, Z_DEFAULT_COMPRESSION) != Z_OK)
return NULL;
buffer = g_malloc0 (buflen);
strm.avail_out = buflen;
strm.next_out = buffer;
err = deflate (&strm, Z_SYNC_FLUSH);
deflateEnd (&strm);
switch (err)
{
case Z_OK:
case Z_STREAM_END:
if (strm.avail_out != 0)
{
*dstlen = strm.total_out;
return buffer;
}
/* Fallthrough. */
case Z_BUF_ERROR:
g_free (buffer);
buflen *= 2;
break;
default:
g_free (buffer);
return NULL;
}
}
}
void *
gvm_uncompress (const void *src, unsigned long srclen, unsigned long *dstlen)
{
unsigned long buflen = srclen * 2;
if (src == NULL || dstlen == NULL)
return NULL;
while (1)
{
int err;
void *buffer;
z_stream strm;
/* Initialize inflate state */
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = srclen;
#ifdef z_const
strm.next_in = src;
#else
/* Workaround for older zlib. */
strm.next_in = (void *) src;
#endif
/*
* From: http://www.zlib.net/manual.html
* Add 32 to windowBits to enable zlib and gzip decoding with automatic
* header detection.
*/
if (inflateInit2 (&strm, 15 + 32) != Z_OK)
return NULL;
buffer = g_malloc0 (buflen);
strm.avail_out = buflen;
strm.next_out = buffer;
err = inflate (&strm, Z_SYNC_FLUSH);
inflateEnd (&strm);
switch (err)
{
case Z_OK:
case Z_STREAM_END:
if (strm.avail_out != 0)
{
*dstlen = strm.total_out;
return buffer;
}
/* Fallthrough. */
case Z_BUF_ERROR:
g_free (buffer);
buflen *= 2;
break;
default:
g_free (buffer);
return NULL;
}
}
}
void *
gvm_compress_gzipheader (const void *src, unsigned long srclen,
unsigned long *dstlen)
{
unsigned long buflen = srclen * 2;
int windowsBits = 15;
int GZIP_ENCODING = 16;
if (src == NULL || dstlen == NULL)
return NULL;
if (buflen < 30)
buflen = 30;
while (1)
{
int err;
void *buffer;
z_stream strm;
/* Initialize deflate state */
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = srclen;
#ifdef z_const
strm.next_in = src;
#else
/* Workaround for older zlib. */
strm.next_in = (void *) src;
#endif
if (deflateInit2 (&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
windowsBits | GZIP_ENCODING, 8, Z_DEFAULT_STRATEGY)
!= Z_OK)
return NULL;
buffer = g_malloc0 (buflen);
strm.avail_out = buflen;
strm.next_out = buffer;
err = deflate (&strm, Z_FINISH);
deflateEnd (&strm);
switch (err)
{
case Z_OK:
case Z_STREAM_END:
if (strm.avail_out != 0)
{
*dstlen = strm.total_out;
return buffer;
}
/* Fallthrough. */
case Z_BUF_ERROR:
g_free (buffer);
buflen *= 2;
break;
default:
g_free (buffer);
return NULL;
}
}
}
static ssize_t
gz_file_read (void *cookie, char *buffer, size_t buffer_size)
{
gzFile gz_file = cookie;
return gzread (gz_file, buffer, buffer_size);
}
static int
gz_file_close (void *cookie)
{
gzFile gz_file = cookie;
return gzclose (gz_file);
;
}
FILE *
gvm_gzip_open_file_reader (const char *path)
{
static cookie_io_functions_t io_functions = {
.read = gz_file_read,
.write = NULL,
.seek = NULL,
.close = gz_file_close,
};
if (path == NULL)
{
return NULL;
}
gzFile gz_file = gzopen (path, "r");
if (gz_file == NULL)
{
return NULL;
}
FILE *file = fopencookie (gz_file, "r", io_functions);
return file;
}
FILE *
gvm_gzip_open_file_reader_fd (int fd)
{
static cookie_io_functions_t io_functions = {
.read = gz_file_read,
.write = NULL,
.seek = NULL,
.close = gz_file_close,
};
if (fd < 0)
{
return NULL;
}
gzFile gz_file = gzdopen (fd, "r");
if (gz_file == NULL)
{
return NULL;
}
FILE *file = fopencookie (gz_file, "r", io_functions);
return file;
}
gvm_gzip_open_file_reader_fd
FILE * gvm_gzip_open_file_reader_fd(int fd)
Opens a gzip file as a FILE* stream for reading and decompression.
Definition compressutils.c:316
gvm_uncompress
void * gvm_uncompress(const void *src, unsigned long srclen, unsigned long *dstlen)
Uncompresses data in src buffer.
Definition compressutils.c:109
gvm_compress
void * gvm_compress(const void *src, unsigned long srclen, unsigned long *dstlen)
Compresses data in src buffer.
Definition compressutils.c:41
gvm_gzip_open_file_reader
FILE * gvm_gzip_open_file_reader(const char *path)
Opens a gzip file as a FILE* stream for reading and decompression.
Definition compressutils.c:284
gz_file_close
static int gz_file_close(void *cookie)
Close a gzip file.
Definition compressutils.c:268
gz_file_read
static ssize_t gz_file_read(void *cookie, char *buffer, size_t buffer_size)
Read decompressed data from a gzip file.
Definition compressutils.c:253
gvm_compress_gzipheader
void * gvm_compress_gzipheader(const void *src, unsigned long srclen, unsigned long *dstlen)
Compresses data in src buffer, gzip format compatible.
Definition compressutils.c:179
compressutils.h
API related to data compression (gzip format.)