#include "pmix_config.h"
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#if HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <zlib-ng.h>
#include "src/include/pmix_stdint.h"
#include "src/util/pmix_argv.h"
#include "src/util/pmix_output.h"
#include "src/util/pmix_environ.h"
#include "src/util/pmix_printf.h"
#include "pmix_common.h"
#include "src/util/pmix_basename.h"
#include "src/mca/pcompress/base/base.h"
#include "compress_zlibng.h"
static bool zlibng_compress(const uint8_t *inbytes, size_t inlen, uint8_t **outbytes, size_t *outlen);
static bool zlibng_decompress(uint8_t **outbytes, size_t *outlen, const uint8_t *inbytes, size_t inlen);
static bool compress_string(char *instring, uint8_t **outbytes, size_t *nbytes);
static bool decompress_string(char **outstring, uint8_t *inbytes, size_t len);
pmix_compress_base_module_t pmix_pcompress_zlibng_module = {
.compress = zlibng_compress,
.decompress = zlibng_decompress,
.compress_string = compress_string,
.decompress_string = decompress_string,
};
static bool zlibng_compress(const uint8_t *inbytes, size_t inlen, uint8_t **outbytes, size_t *outlen)
{
zng_stream strm;
size_t len, len2;
uint8_t *tmp, *ptr;
uint32_t len3;
int rc;
*outbytes = NULL;
*outlen = 0;
if (inlen < pmix_compress_base.compress_limit || inlen >= UINT32_MAX) {
return false;
}
len3 = inlen;
memset(&strm, 0, sizeof(strm));
if (Z_OK != zng_deflateInit(&strm, 9)) {
return false;
}
len = zng_deflateBound(&strm, inlen);
if (len >= inlen) {
(void) zng_deflateEnd(&strm);
return false;
}
if (NULL == (tmp = (uint8_t *) malloc(len))) {
(void) zng_deflateEnd(&strm);
return false;
}
strm.next_in = (uint8_t*)inbytes;
strm.avail_in = inlen;
strm.avail_out = len;
strm.next_out = tmp;
rc = zng_deflate(&strm, Z_FINISH);
(void) zng_deflateEnd(&strm);
if (Z_STREAM_END != rc) {
free(tmp);
return false;
}
len2 = len - strm.avail_out + sizeof(uint32_t);
ptr = (uint8_t *) malloc(len2);
if (NULL == ptr) {
free(tmp);
return false;
}
*outbytes = ptr;
*outlen = len2;
memcpy(ptr, &len3, sizeof(uint32_t));
ptr += sizeof(uint32_t);
memcpy(ptr, tmp, len2 - sizeof(uint32_t));
free(tmp);
pmix_output_verbose(2, pmix_pcompress_base_framework.framework_output,
"COMPRESS INPUT BLOCK OF LEN %" PRIsize_t " OUTPUT SIZE %" PRIsize_t "",
inlen, len2 - sizeof(uint32_t));
return true; }
static bool compress_string(char *instring, uint8_t **outbytes, size_t *nbytes)
{
uint32_t inlen;
inlen = strlen(instring);
return zlibng_compress((uint8_t *) instring, inlen, outbytes, nbytes);
}
static bool doit(uint8_t **outbytes, size_t len2, const uint8_t *inbytes, size_t inlen)
{
uint8_t *dest;
zng_stream strm;
int rc;
*outbytes = NULL;
dest = (uint8_t *) malloc(len2);
if (NULL == dest) {
return false;
}
memset(dest, 0, len2);
memset(&strm, 0, sizeof(strm));
if (Z_OK != zng_inflateInit(&strm)) {
free(dest);
return false;
}
strm.avail_in = inlen;
strm.next_in = (uint8_t*)inbytes;
strm.avail_out = len2;
strm.next_out = dest;
rc = zng_inflate(&strm, Z_FINISH);
zng_inflateEnd(&strm);
if (Z_STREAM_END == rc) {
*outbytes = dest;
return true;
}
free(dest);
return false;
}
static bool zlibng_decompress(uint8_t **outbytes, size_t *outlen, const uint8_t *inbytes, size_t inlen)
{
uint32_t len2;
bool rc;
uint8_t *input;
*outlen = 0;
memcpy(&len2, inbytes, sizeof(uint32_t));
pmix_output_verbose(2, pmix_pcompress_base_framework.framework_output,
"DECOMPRESSING INPUT OF LEN %" PRIsize_t " OUTPUT %u", inlen, len2);
input = (uint8_t *) (inbytes + sizeof(uint32_t)); rc = doit(outbytes, len2, input, inlen);
if (rc) {
*outlen = len2;
return true;
}
return false;
}
static bool decompress_string(char **outstring, uint8_t *inbytes, size_t len)
{
uint32_t len2;
bool rc;
uint8_t *input;
memcpy(&len2, inbytes, sizeof(uint32_t));
if (len2 == UINT32_MAX) {
*outstring = NULL;
return false;
}
++len2;
input = (uint8_t *) (inbytes + sizeof(uint32_t)); rc = doit((uint8_t **) outstring, len2, input, len);
if (rc) {
*outstring[len2 - 1] = '\0';
return true;
}
*outstring = NULL;
return false;
}