18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci#include <fcntl.h> 38c2ecf20Sopenharmony_ci#include <stdio.h> 48c2ecf20Sopenharmony_ci#include <string.h> 58c2ecf20Sopenharmony_ci#include <unistd.h> 68c2ecf20Sopenharmony_ci#include <sys/stat.h> 78c2ecf20Sopenharmony_ci#include <sys/mman.h> 88c2ecf20Sopenharmony_ci#include <zlib.h> 98c2ecf20Sopenharmony_ci#include <linux/compiler.h> 108c2ecf20Sopenharmony_ci#include <internal/lib.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include "util/compress.h" 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#define CHUNK_SIZE 16384 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ciint gzip_decompress_to_file(const char *input, int output_fd) 178c2ecf20Sopenharmony_ci{ 188c2ecf20Sopenharmony_ci int ret = Z_STREAM_ERROR; 198c2ecf20Sopenharmony_ci int input_fd; 208c2ecf20Sopenharmony_ci void *ptr; 218c2ecf20Sopenharmony_ci int len; 228c2ecf20Sopenharmony_ci struct stat stbuf; 238c2ecf20Sopenharmony_ci unsigned char buf[CHUNK_SIZE]; 248c2ecf20Sopenharmony_ci z_stream zs = { 258c2ecf20Sopenharmony_ci .zalloc = Z_NULL, 268c2ecf20Sopenharmony_ci .zfree = Z_NULL, 278c2ecf20Sopenharmony_ci .opaque = Z_NULL, 288c2ecf20Sopenharmony_ci .avail_in = 0, 298c2ecf20Sopenharmony_ci .next_in = Z_NULL, 308c2ecf20Sopenharmony_ci }; 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci input_fd = open(input, O_RDONLY); 338c2ecf20Sopenharmony_ci if (input_fd < 0) 348c2ecf20Sopenharmony_ci return -1; 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci if (fstat(input_fd, &stbuf) < 0) 378c2ecf20Sopenharmony_ci goto out_close; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci ptr = mmap(NULL, stbuf.st_size, PROT_READ, MAP_PRIVATE, input_fd, 0); 408c2ecf20Sopenharmony_ci if (ptr == MAP_FAILED) 418c2ecf20Sopenharmony_ci goto out_close; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci if (inflateInit2(&zs, 16 + MAX_WBITS) != Z_OK) 448c2ecf20Sopenharmony_ci goto out_unmap; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci zs.next_in = ptr; 478c2ecf20Sopenharmony_ci zs.avail_in = stbuf.st_size; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci do { 508c2ecf20Sopenharmony_ci zs.next_out = buf; 518c2ecf20Sopenharmony_ci zs.avail_out = CHUNK_SIZE; 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci ret = inflate(&zs, Z_NO_FLUSH); 548c2ecf20Sopenharmony_ci switch (ret) { 558c2ecf20Sopenharmony_ci case Z_NEED_DICT: 568c2ecf20Sopenharmony_ci ret = Z_DATA_ERROR; 578c2ecf20Sopenharmony_ci /* fall through */ 588c2ecf20Sopenharmony_ci case Z_DATA_ERROR: 598c2ecf20Sopenharmony_ci case Z_MEM_ERROR: 608c2ecf20Sopenharmony_ci goto out; 618c2ecf20Sopenharmony_ci default: 628c2ecf20Sopenharmony_ci break; 638c2ecf20Sopenharmony_ci } 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci len = CHUNK_SIZE - zs.avail_out; 668c2ecf20Sopenharmony_ci if (writen(output_fd, buf, len) != len) { 678c2ecf20Sopenharmony_ci ret = Z_DATA_ERROR; 688c2ecf20Sopenharmony_ci goto out; 698c2ecf20Sopenharmony_ci } 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci } while (ret != Z_STREAM_END); 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ciout: 748c2ecf20Sopenharmony_ci inflateEnd(&zs); 758c2ecf20Sopenharmony_ciout_unmap: 768c2ecf20Sopenharmony_ci munmap(ptr, stbuf.st_size); 778c2ecf20Sopenharmony_ciout_close: 788c2ecf20Sopenharmony_ci close(input_fd); 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci return ret == Z_STREAM_END ? 0 : -1; 818c2ecf20Sopenharmony_ci} 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_cibool gzip_is_compressed(const char *input) 848c2ecf20Sopenharmony_ci{ 858c2ecf20Sopenharmony_ci int fd = open(input, O_RDONLY); 868c2ecf20Sopenharmony_ci const uint8_t magic[2] = { 0x1f, 0x8b }; 878c2ecf20Sopenharmony_ci char buf[2] = { 0 }; 888c2ecf20Sopenharmony_ci ssize_t rc; 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci if (fd < 0) 918c2ecf20Sopenharmony_ci return -1; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci rc = read(fd, buf, sizeof(buf)); 948c2ecf20Sopenharmony_ci close(fd); 958c2ecf20Sopenharmony_ci return rc == sizeof(buf) ? 968c2ecf20Sopenharmony_ci memcmp(buf, magic, sizeof(buf)) == 0 : false; 978c2ecf20Sopenharmony_ci} 98