summaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/dso.c12
-rw-r--r--tools/perf/util/util.h5
-rw-r--r--tools/perf/util/zlib.c78
3 files changed, 87 insertions, 8 deletions
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 36a607c..45be944 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -141,18 +141,14 @@ int dso__read_binary_type_filename(const struct dso *dso,
return ret;
}
-static int decompress_dummy(const char *input __maybe_unused,
- int output __maybe_unused)
-{
- return -1;
-}
-
static const struct {
const char *fmt;
int (*decompress)(const char *input, int output);
} compressions[] = {
- { "gz", decompress_dummy },
- { NULL, },
+#ifdef HAVE_ZLIB_SUPPORT
+ { "gz", gzip_decompress_to_file },
+#endif
+ { NULL, NULL },
};
bool is_supported_compression(const char *ext)
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 80bfdaa..7dc44cfe 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -351,4 +351,9 @@ void mem_bswap_32(void *src, int byte_size);
const char *get_filename_for_perf_kvm(void);
bool find_process(const char *name);
+
+#ifdef HAVE_ZLIB_SUPPORT
+int gzip_decompress_to_file(const char *input, int output_fd);
+#endif
+
#endif /* GIT_COMPAT_UTIL_H */
diff --git a/tools/perf/util/zlib.c b/tools/perf/util/zlib.c
new file mode 100644
index 0000000..495a449
--- /dev/null
+++ b/tools/perf/util/zlib.c
@@ -0,0 +1,78 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <zlib.h>
+
+#include "util/util.h"
+#include "util/debug.h"
+
+
+#define CHUNK_SIZE 16384
+
+int gzip_decompress_to_file(const char *input, int output_fd)
+{
+ int ret = Z_STREAM_ERROR;
+ int input_fd;
+ void *ptr;
+ int len;
+ struct stat stbuf;
+ unsigned char buf[CHUNK_SIZE];
+ z_stream zs = {
+ .zalloc = Z_NULL,
+ .zfree = Z_NULL,
+ .opaque = Z_NULL,
+ .avail_in = 0,
+ .next_in = Z_NULL,
+ };
+
+ input_fd = open(input, O_RDONLY);
+ if (input_fd < 0)
+ return -1;
+
+ if (fstat(input_fd, &stbuf) < 0)
+ goto out_close;
+
+ ptr = mmap(NULL, stbuf.st_size, PROT_READ, MAP_PRIVATE, input_fd, 0);
+ if (ptr == MAP_FAILED)
+ goto out_close;
+
+ if (inflateInit2(&zs, 16 + MAX_WBITS) != Z_OK)
+ goto out_unmap;
+
+ zs.next_in = ptr;
+ zs.avail_in = stbuf.st_size;
+
+ do {
+ zs.next_out = buf;
+ zs.avail_out = CHUNK_SIZE;
+
+ ret = inflate(&zs, Z_NO_FLUSH);
+ switch (ret) {
+ case Z_NEED_DICT:
+ ret = Z_DATA_ERROR;
+ /* fall through */
+ case Z_DATA_ERROR:
+ case Z_MEM_ERROR:
+ goto out;
+ default:
+ break;
+ }
+
+ len = CHUNK_SIZE - zs.avail_out;
+ if (writen(output_fd, buf, len) != len) {
+ ret = Z_DATA_ERROR;
+ goto out;
+ }
+
+ } while (ret != Z_STREAM_END);
+
+out:
+ inflateEnd(&zs);
+out_unmap:
+ munmap(ptr, stbuf.st_size);
+out_close:
+ close(input_fd);
+
+ return ret == Z_STREAM_END ? 0 : -1;
+}
OpenPOWER on IntegriCloud