Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <fcntl.h>
0003 #include <stdio.h>
0004 #include <string.h>
0005 #include <unistd.h>
0006 #include <sys/stat.h>
0007 #include <sys/mman.h>
0008 #include <zlib.h>
0009 #include <linux/compiler.h>
0010 #include <internal/lib.h>
0011 
0012 #include "util/compress.h"
0013 
0014 #define CHUNK_SIZE  16384
0015 
0016 int gzip_decompress_to_file(const char *input, int output_fd)
0017 {
0018     int ret = Z_STREAM_ERROR;
0019     int input_fd;
0020     void *ptr;
0021     int len;
0022     struct stat stbuf;
0023     unsigned char buf[CHUNK_SIZE];
0024     z_stream zs = {
0025         .zalloc     = Z_NULL,
0026         .zfree      = Z_NULL,
0027         .opaque     = Z_NULL,
0028         .avail_in   = 0,
0029         .next_in    = Z_NULL,
0030     };
0031 
0032     input_fd = open(input, O_RDONLY);
0033     if (input_fd < 0)
0034         return -1;
0035 
0036     if (fstat(input_fd, &stbuf) < 0)
0037         goto out_close;
0038 
0039     ptr = mmap(NULL, stbuf.st_size, PROT_READ, MAP_PRIVATE, input_fd, 0);
0040     if (ptr == MAP_FAILED)
0041         goto out_close;
0042 
0043     if (inflateInit2(&zs, 16 + MAX_WBITS) != Z_OK)
0044         goto out_unmap;
0045 
0046     zs.next_in = ptr;
0047     zs.avail_in = stbuf.st_size;
0048 
0049     do {
0050         zs.next_out = buf;
0051         zs.avail_out = CHUNK_SIZE;
0052 
0053         ret = inflate(&zs, Z_NO_FLUSH);
0054         switch (ret) {
0055         case Z_NEED_DICT:
0056             ret = Z_DATA_ERROR;
0057             /* fall through */
0058         case Z_DATA_ERROR:
0059         case Z_MEM_ERROR:
0060             goto out;
0061         default:
0062             break;
0063         }
0064 
0065         len = CHUNK_SIZE - zs.avail_out;
0066         if (writen(output_fd, buf, len) != len) {
0067             ret = Z_DATA_ERROR;
0068             goto out;
0069         }
0070 
0071     } while (ret != Z_STREAM_END);
0072 
0073 out:
0074     inflateEnd(&zs);
0075 out_unmap:
0076     munmap(ptr, stbuf.st_size);
0077 out_close:
0078     close(input_fd);
0079 
0080     return ret == Z_STREAM_END ? 0 : -1;
0081 }
0082 
0083 bool gzip_is_compressed(const char *input)
0084 {
0085     int fd = open(input, O_RDONLY);
0086     const uint8_t magic[2] = { 0x1f, 0x8b };
0087     char buf[2] = { 0 };
0088     ssize_t rc;
0089 
0090     if (fd < 0)
0091         return -1;
0092 
0093     rc = read(fd, buf, sizeof(buf));
0094     close(fd);
0095     return rc == sizeof(buf) ?
0096            memcmp(buf, magic, sizeof(buf)) == 0 : false;
0097 }