linux/tools/perf/util/zlib.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2#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  16384
  15
  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