diff options
Diffstat (limited to 'lib/trace-cmd/trace-compress-zlib.c')
-rw-r--r-- | lib/trace-cmd/trace-compress-zlib.c | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/lib/trace-cmd/trace-compress-zlib.c b/lib/trace-cmd/trace-compress-zlib.c new file mode 100644 index 00000000..413a0764 --- /dev/null +++ b/lib/trace-cmd/trace-compress-zlib.c @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: LGPL-2.1 +/* + * Copyright (C) 2021, VMware, Tzvetomir Stoyanov tz.stoyanov@gmail.com> + * + */ +#include <stdlib.h> +#include <dlfcn.h> +#include <zlib.h> +#include <errno.h> + +#include "trace-cmd-private.h" + +#define __ZLIB_NAME "zlib" +#define __ZLIB_WEIGTH 10 + +static int zlib_compress(void *ctx, const void *in, int in_bytes, void *out, int out_bytes) +{ + unsigned long obytes = out_bytes; + int ret; + + ret = compress2((unsigned char *)out, &obytes, + (unsigned char *)in, (unsigned long)in_bytes, Z_BEST_COMPRESSION); + switch (ret) { + case Z_OK: + return obytes; + case Z_BUF_ERROR: + errno = -ENOBUFS; + break; + case Z_MEM_ERROR: + errno = -ENOMEM; + break; + case Z_STREAM_ERROR: + errno = -EINVAL; + break; + case Z_ERRNO: + break; + default: + errno = -EFAULT; + break; + } + + return -1; +} + +static int zlib_decompress(void *ctx, const void *in, int in_bytes, void *out, int out_bytes) +{ + unsigned long obytes = out_bytes; + int ret; + + ret = uncompress((unsigned char *)out, &obytes, + (unsigned char *)in, (unsigned long)in_bytes); + switch (ret) { + case Z_OK: + return obytes; + case Z_BUF_ERROR: + errno = -ENOBUFS; + break; + case Z_MEM_ERROR: + errno = -ENOMEM; + break; + case Z_DATA_ERROR: + errno = -EINVAL; + break; + case Z_ERRNO: + break; + default: + errno = -EFAULT; + break; + } + + return -1; +} + +static unsigned int zlib_compress_bound(void *ctx, unsigned int in_bytes) +{ + return compressBound(in_bytes); +} + +static bool zlib_is_supported(const char *name, const char *version) +{ + const char *zver; + + if (!name) + return false; + if (strlen(name) != strlen(__ZLIB_NAME) || strcmp(name, __ZLIB_NAME)) + return false; + + if (!version) + return true; + + zver = zlibVersion(); + if (!zver) + return false; + + /* Compare the major version number */ + if (atoi(version) <= atoi(zver)) + return true; + + return false; +} + +int tracecmd_zlib_init(void) +{ + struct tracecmd_compression_proto proto; + + memset(&proto, 0, sizeof(proto)); + proto.name = __ZLIB_NAME; + proto.version = zlibVersion(); + proto.weight = __ZLIB_WEIGTH; + proto.compress = zlib_compress; + proto.uncompress = zlib_decompress; + proto.is_supported = zlib_is_supported; + proto.compress_size = zlib_compress_bound; + + return tracecmd_compress_proto_register(&proto); +} |