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