98 lines · c
1// SPDX-License-Identifier: GPL-2.02#include <fcntl.h>3#include <stdio.h>4#include <string.h>5#include <unistd.h>6#include <sys/stat.h>7#include <sys/mman.h>8#include <zlib.h>9#include <linux/compiler.h>10#include <internal/lib.h>11 12#include "util/compress.h"13 14#define CHUNK_SIZE 1638415 16int gzip_decompress_to_file(const char *input, int output_fd)17{18 int ret = Z_STREAM_ERROR;19 int input_fd;20 void *ptr;21 int len;22 struct stat stbuf;23 unsigned char buf[CHUNK_SIZE];24 z_stream zs = {25 .zalloc = Z_NULL,26 .zfree = Z_NULL,27 .opaque = Z_NULL,28 .avail_in = 0,29 .next_in = Z_NULL,30 };31 32 input_fd = open(input, O_RDONLY);33 if (input_fd < 0)34 return -1;35 36 if (fstat(input_fd, &stbuf) < 0)37 goto out_close;38 39 ptr = mmap(NULL, stbuf.st_size, PROT_READ, MAP_PRIVATE, input_fd, 0);40 if (ptr == MAP_FAILED)41 goto out_close;42 43 if (inflateInit2(&zs, 16 + MAX_WBITS) != Z_OK)44 goto out_unmap;45 46 zs.next_in = ptr;47 zs.avail_in = stbuf.st_size;48 49 do {50 zs.next_out = buf;51 zs.avail_out = CHUNK_SIZE;52 53 ret = inflate(&zs, Z_NO_FLUSH);54 switch (ret) {55 case Z_NEED_DICT:56 ret = Z_DATA_ERROR;57 /* fall through */58 case Z_DATA_ERROR:59 case Z_MEM_ERROR:60 goto out;61 default:62 break;63 }64 65 len = CHUNK_SIZE - zs.avail_out;66 if (writen(output_fd, buf, len) != len) {67 ret = Z_DATA_ERROR;68 goto out;69 }70 71 } while (ret != Z_STREAM_END);72 73out:74 inflateEnd(&zs);75out_unmap:76 munmap(ptr, stbuf.st_size);77out_close:78 close(input_fd);79 80 return ret == Z_STREAM_END ? 0 : -1;81}82 83bool gzip_is_compressed(const char *input)84{85 int fd = open(input, O_RDONLY);86 const uint8_t magic[2] = { 0x1f, 0x8b };87 char buf[2] = { 0 };88 ssize_t rc;89 90 if (fd < 0)91 return -1;92 93 rc = read(fd, buf, sizeof(buf));94 close(fd);95 return rc == sizeof(buf) ?96 memcmp(buf, magic, sizeof(buf)) == 0 : false;97}98