perf tools: Add LZMA decompression from FILE
authorStephen Brennan <stephen.s.brennan@oracle.com>
Fri, 7 Mar 2025 23:22:02 +0000 (15:22 -0800)
committerNamhyung Kim <namhyung@kernel.org>
Mon, 10 Mar 2025 21:37:02 +0000 (14:37 -0700)
Internally lzma_decompress_to_file() creates a FILE from the filename.
Add an API that takes an existing FILE directly. This allows
decompressing already-open files and even buffers opened by fmemopen().
It is necessary for supporting .gnu_debugdata in the next patch.

Signed-off-by: Stephen Brennan <stephen.s.brennan@oracle.com>
Reviewed-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Link: https://lore.kernel.org/r/20250307232206.2102440-3-stephen.s.brennan@oracle.com
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
tools/perf/util/compress.h
tools/perf/util/lzma.c

index a7650353c662299137d92e65cd7e5ca43ff19cb4..6cfecfca16f24d719933bf8a0ab22a945c03fcba 100644 (file)
@@ -4,6 +4,7 @@
 
 #include <stdbool.h>
 #include <stddef.h>
+#include <stdio.h>
 #include <sys/types.h>
 #include <linux/compiler.h>
 #ifdef HAVE_ZSTD_SUPPORT
@@ -16,10 +17,17 @@ bool gzip_is_compressed(const char *input);
 #endif
 
 #ifdef HAVE_LZMA_SUPPORT
+int lzma_decompress_stream_to_file(FILE *input, int output_fd);
 int lzma_decompress_to_file(const char *input, int output_fd);
 bool lzma_is_compressed(const char *input);
 #else
 static inline
+int lzma_decompress_stream_to_file(FILE *input __maybe_unused,
+                                  int output_fd __maybe_unused)
+{
+       return -1;
+}
+static inline
 int lzma_decompress_to_file(const char *input __maybe_unused,
                            int output_fd __maybe_unused)
 {
index af9a97612f9df39206031b7b8dcbe86114ebe5c6..bbcd2ffcf4bd133f5e23d41f7137cefd95618295 100644 (file)
@@ -32,7 +32,7 @@ static const char *lzma_strerror(lzma_ret ret)
        }
 }
 
-int lzma_decompress_to_file(const char *input, int output_fd)
+int lzma_decompress_stream_to_file(FILE *infile, int output_fd)
 {
        lzma_action action = LZMA_RUN;
        lzma_stream strm   = LZMA_STREAM_INIT;
@@ -41,18 +41,11 @@ int lzma_decompress_to_file(const char *input, int output_fd)
 
        u8 buf_in[BUFSIZE];
        u8 buf_out[BUFSIZE];
-       FILE *infile;
-
-       infile = fopen(input, "rb");
-       if (!infile) {
-               pr_debug("lzma: fopen failed on %s: '%s'\n", input, strerror(errno));
-               return -1;
-       }
 
        ret = lzma_stream_decoder(&strm, UINT64_MAX, LZMA_CONCATENATED);
        if (ret != LZMA_OK) {
                pr_debug("lzma: lzma_stream_decoder failed %s (%d)\n", lzma_strerror(ret), ret);
-               goto err_fclose;
+               return err;
        }
 
        strm.next_in   = NULL;
@@ -100,11 +93,25 @@ int lzma_decompress_to_file(const char *input, int output_fd)
        err = 0;
 err_lzma_end:
        lzma_end(&strm);
-err_fclose:
-       fclose(infile);
        return err;
 }
 
+int lzma_decompress_to_file(const char *input, int output_fd)
+{
+       FILE *infile;
+       int ret;
+
+       infile = fopen(input, "rb");
+       if (!infile) {
+               pr_debug("lzma: fopen failed on %s: '%s'\n", input, strerror(errno));
+               return -1;
+       }
+
+       ret = lzma_decompress_stream_to_file(infile, output_fd);
+       fclose(infile);
+       return ret;
+}
+
 bool lzma_is_compressed(const char *input)
 {
        int fd = open(input, O_RDONLY);