2012-07-25 15:37:36 +00:00
|
|
|
/*
|
|
|
|
* This file is a part of Pcompress, a chunked parallel multi-
|
|
|
|
* algorithm lossless compression and decompression program.
|
|
|
|
*
|
2013-03-07 14:56:48 +00:00
|
|
|
* Copyright (C) 2012-2013 Moinak Ghosh. All rights reserved.
|
2012-07-25 15:37:36 +00:00
|
|
|
* Use is subject to license terms.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 3 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
2013-03-07 14:56:48 +00:00
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this program.
|
|
|
|
* If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*
|
2012-07-25 15:37:36 +00:00
|
|
|
* moinakg@belenix.org, http://moinakg.wordpress.com/
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <strings.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <limits.h>
|
|
|
|
#include <utils.h>
|
|
|
|
#include <pcompress.h>
|
|
|
|
#include <lz4.h>
|
|
|
|
#include <lz4hc.h>
|
|
|
|
#include <allocator.h>
|
|
|
|
|
2012-08-04 12:25:20 +00:00
|
|
|
#define LZ4_MAX_CHUNK 2147450621L
|
|
|
|
|
2012-07-25 15:37:36 +00:00
|
|
|
struct lz4_params {
|
|
|
|
int level;
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
lz4_stats(int show)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2012-08-04 12:25:20 +00:00
|
|
|
int
|
2012-12-27 17:36:48 +00:00
|
|
|
lz4_buf_extra(uint64_t buflen)
|
2012-08-04 12:25:20 +00:00
|
|
|
{
|
|
|
|
if (buflen > LZ4_MAX_CHUNK)
|
|
|
|
buflen = LZ4_MAX_CHUNK;
|
|
|
|
return (LZ4_compressBound(buflen) - buflen + sizeof(int));
|
|
|
|
}
|
|
|
|
|
2012-08-18 04:50:52 +00:00
|
|
|
void
|
2012-12-27 17:36:48 +00:00
|
|
|
lz4_props(algo_props_t *data, int level, uint64_t chunksize) {
|
2012-08-18 04:50:52 +00:00
|
|
|
data->compress_mt_capable = 0;
|
|
|
|
data->decompress_mt_capable = 0;
|
|
|
|
data->buf_extra = lz4_buf_extra(chunksize);
|
2012-12-15 16:33:23 +00:00
|
|
|
data->delta2_span = 100;
|
2013-01-14 07:50:07 +00:00
|
|
|
data->deltac_min_distance = FOURM;
|
2012-08-18 04:50:52 +00:00
|
|
|
}
|
|
|
|
|
2012-07-25 15:37:36 +00:00
|
|
|
int
|
2012-12-27 17:36:48 +00:00
|
|
|
lz4_init(void **data, int *level, int nthreads, uint64_t chunksize,
|
2012-11-22 15:32:50 +00:00
|
|
|
int file_version, compress_op_t op)
|
2012-07-25 15:37:36 +00:00
|
|
|
{
|
|
|
|
struct lz4_params *lzdat;
|
|
|
|
int lev;
|
|
|
|
|
2012-08-04 12:25:20 +00:00
|
|
|
if (chunksize > LZ4_MAX_CHUNK) {
|
2013-10-02 15:15:33 +00:00
|
|
|
log_msg(LOG_ERR, 0, "Max allowed chunk size for LZ4 is: %ld \n",
|
2012-08-04 12:25:20 +00:00
|
|
|
LZ4_MAX_CHUNK);
|
2012-07-25 15:37:36 +00:00
|
|
|
return (1);
|
|
|
|
}
|
2012-12-27 17:36:48 +00:00
|
|
|
lzdat = (struct lz4_params *)slab_alloc(NULL, sizeof (struct lz4_params));
|
2012-07-25 15:37:36 +00:00
|
|
|
|
|
|
|
lev = *level;
|
|
|
|
if (lev > 3) lev = 3;
|
|
|
|
lzdat->level = lev;
|
|
|
|
*data = lzdat;
|
|
|
|
|
|
|
|
if (*level > 9) *level = 9;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
lz4_deinit(void **data)
|
|
|
|
{
|
|
|
|
struct lz4_params *lzdat = (struct lz4_params *)(*data);
|
|
|
|
|
|
|
|
if (lzdat) {
|
|
|
|
slab_free(NULL, lzdat);
|
|
|
|
}
|
|
|
|
*data = NULL;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2012-12-09 04:45:06 +00:00
|
|
|
lz4_compress(void *src, uint64_t srclen, void *dst, uint64_t *dstlen,
|
2013-11-08 18:20:28 +00:00
|
|
|
int level, uchar_t chdr, int btype, void *data)
|
2012-07-25 15:37:36 +00:00
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
struct lz4_params *lzdat = (struct lz4_params *)data;
|
|
|
|
int _srclen = srclen;
|
|
|
|
uchar_t *dst2;
|
|
|
|
|
2013-11-09 11:16:19 +00:00
|
|
|
/*
|
|
|
|
* Ignore compressed data in fast modes.
|
|
|
|
*/
|
|
|
|
if (lzdat->level < 3 && PC_TYPE(btype) == TYPE_COMPRESSED)
|
|
|
|
return (-1);
|
|
|
|
|
2012-07-25 15:37:36 +00:00
|
|
|
if (lzdat->level == 1) {
|
2012-12-27 17:36:48 +00:00
|
|
|
rv = LZ4_compress((const char *)src, (char *)dst, _srclen);
|
2012-08-04 12:25:20 +00:00
|
|
|
|
2012-07-25 15:37:36 +00:00
|
|
|
} else if (lzdat->level == 2) {
|
2012-12-27 17:36:48 +00:00
|
|
|
rv = LZ4_compress((const char *)src, (char *)dst, _srclen);
|
2012-08-04 12:25:20 +00:00
|
|
|
if (rv == 0 || rv > *dstlen) {
|
2012-07-25 15:37:36 +00:00
|
|
|
return (-1);
|
|
|
|
}
|
2012-12-27 17:36:48 +00:00
|
|
|
dst2 = (uchar_t *)slab_alloc(NULL, rv + sizeof (int) + LZ4_compressBound(rv));
|
2012-07-25 15:37:36 +00:00
|
|
|
*((int *)dst2) = htonl(rv);
|
2012-12-27 17:36:48 +00:00
|
|
|
rv = LZ4_compressHC((const char *)dst, (char *)(dst2 + sizeof (int)), rv);
|
2012-07-25 15:37:36 +00:00
|
|
|
if (rv != 0) {
|
|
|
|
rv += sizeof (int);
|
|
|
|
memcpy(dst, dst2, rv);
|
|
|
|
}
|
|
|
|
slab_free(NULL, dst2);
|
|
|
|
} else {
|
2012-12-27 17:36:48 +00:00
|
|
|
rv = LZ4_compressHC((const char *)src, (char *)dst, _srclen);
|
2012-07-25 15:37:36 +00:00
|
|
|
}
|
|
|
|
if (rv == 0) {
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
*dstlen = rv;
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2012-12-09 04:45:06 +00:00
|
|
|
lz4_decompress(void *src, uint64_t srclen, void *dst, uint64_t *dstlen,
|
2013-11-08 18:20:28 +00:00
|
|
|
int level, uchar_t chdr, int btype, void *data)
|
2012-07-25 15:37:36 +00:00
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
struct lz4_params *lzdat = (struct lz4_params *)data;
|
|
|
|
int _dstlen = *dstlen;
|
|
|
|
|
|
|
|
if (lzdat->level == 1 || lzdat->level == 3) {
|
2012-12-27 17:36:48 +00:00
|
|
|
rv = LZ4_uncompress((const char *)src, (char *)dst, _dstlen);
|
2012-08-04 12:25:20 +00:00
|
|
|
if (rv != srclen) {
|
|
|
|
return (-1);
|
|
|
|
}
|
2012-07-25 15:37:36 +00:00
|
|
|
|
|
|
|
} else if (lzdat->level == 2) {
|
|
|
|
int sz1;
|
|
|
|
|
|
|
|
sz1 = ntohl(*((int *)src));
|
2012-12-27 17:36:48 +00:00
|
|
|
rv = LZ4_uncompress((const char *)src + sizeof (int), (char *)dst, sz1);
|
2012-08-04 12:25:20 +00:00
|
|
|
if (rv != srclen - sizeof (int)) {
|
2012-07-25 15:37:36 +00:00
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
memcpy(src, dst, sz1);
|
2012-12-27 17:36:48 +00:00
|
|
|
rv = LZ4_uncompress((const char *)src, (char *)dst, _dstlen);
|
2012-08-04 12:25:20 +00:00
|
|
|
if (rv != sz1) {
|
|
|
|
return (-1);
|
|
|
|
}
|
2012-07-25 15:37:36 +00:00
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
}
|