forked from Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
97 lines
1.8 KiB
97 lines
1.8 KiB
// SPDX-License-Identifier: GPL-2.0 |
|
#include <fcntl.h> |
|
#include <stdio.h> |
|
#include <string.h> |
|
#include <unistd.h> |
|
#include <sys/stat.h> |
|
#include <sys/mman.h> |
|
#include <zlib.h> |
|
#include <linux/compiler.h> |
|
#include <internal/lib.h> |
|
|
|
#include "util/compress.h" |
|
|
|
#define CHUNK_SIZE 16384 |
|
|
|
int gzip_decompress_to_file(const char *input, int output_fd) |
|
{ |
|
int ret = Z_STREAM_ERROR; |
|
int input_fd; |
|
void *ptr; |
|
int len; |
|
struct stat stbuf; |
|
unsigned char buf[CHUNK_SIZE]; |
|
z_stream zs = { |
|
.zalloc = Z_NULL, |
|
.zfree = Z_NULL, |
|
.opaque = Z_NULL, |
|
.avail_in = 0, |
|
.next_in = Z_NULL, |
|
}; |
|
|
|
input_fd = open(input, O_RDONLY); |
|
if (input_fd < 0) |
|
return -1; |
|
|
|
if (fstat(input_fd, &stbuf) < 0) |
|
goto out_close; |
|
|
|
ptr = mmap(NULL, stbuf.st_size, PROT_READ, MAP_PRIVATE, input_fd, 0); |
|
if (ptr == MAP_FAILED) |
|
goto out_close; |
|
|
|
if (inflateInit2(&zs, 16 + MAX_WBITS) != Z_OK) |
|
goto out_unmap; |
|
|
|
zs.next_in = ptr; |
|
zs.avail_in = stbuf.st_size; |
|
|
|
do { |
|
zs.next_out = buf; |
|
zs.avail_out = CHUNK_SIZE; |
|
|
|
ret = inflate(&zs, Z_NO_FLUSH); |
|
switch (ret) { |
|
case Z_NEED_DICT: |
|
ret = Z_DATA_ERROR; |
|
/* fall through */ |
|
case Z_DATA_ERROR: |
|
case Z_MEM_ERROR: |
|
goto out; |
|
default: |
|
break; |
|
} |
|
|
|
len = CHUNK_SIZE - zs.avail_out; |
|
if (writen(output_fd, buf, len) != len) { |
|
ret = Z_DATA_ERROR; |
|
goto out; |
|
} |
|
|
|
} while (ret != Z_STREAM_END); |
|
|
|
out: |
|
inflateEnd(&zs); |
|
out_unmap: |
|
munmap(ptr, stbuf.st_size); |
|
out_close: |
|
close(input_fd); |
|
|
|
return ret == Z_STREAM_END ? 0 : -1; |
|
} |
|
|
|
bool gzip_is_compressed(const char *input) |
|
{ |
|
int fd = open(input, O_RDONLY); |
|
const uint8_t magic[2] = { 0x1f, 0x8b }; |
|
char buf[2] = { 0 }; |
|
ssize_t rc; |
|
|
|
if (fd < 0) |
|
return -1; |
|
|
|
rc = read(fd, buf, sizeof(buf)); |
|
close(fd); |
|
return rc == sizeof(buf) ? |
|
memcmp(buf, magic, sizeof(buf)) == 0 : false; |
|
}
|
|
|