--- /dev/null
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * Copyright © 2024 Intel Corporation
+ */
+
+#include <errno.h>
+#include <lzma.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <shared/util.h>
+
+#include "libkmod.h"
+#include "libkmod-internal.h"
+#include "libkmod-internal-file.h"
+
+static void xz_uncompress_belch(struct kmod_file *file, lzma_ret ret)
+{
+ switch (ret) {
+ case LZMA_MEM_ERROR:
+ ERR(file->ctx, "xz: %s\n", strerror(ENOMEM));
+ break;
+ case LZMA_FORMAT_ERROR:
+ ERR(file->ctx, "xz: File format not recognized\n");
+ break;
+ case LZMA_OPTIONS_ERROR:
+ ERR(file->ctx, "xz: Unsupported compression options\n");
+ break;
+ case LZMA_DATA_ERROR:
+ ERR(file->ctx, "xz: File is corrupt\n");
+ break;
+ case LZMA_BUF_ERROR:
+ ERR(file->ctx, "xz: Unexpected end of input\n");
+ break;
+ default:
+ ERR(file->ctx, "xz: Internal error (bug)\n");
+ break;
+ }
+}
+
+static int xz_uncompress(lzma_stream *strm, struct kmod_file *file)
+{
+ uint8_t in_buf[BUFSIZ], out_buf[BUFSIZ];
+ lzma_action action = LZMA_RUN;
+ lzma_ret ret;
+ void *p = NULL;
+ size_t total = 0;
+
+ strm->avail_in = 0;
+ strm->next_out = out_buf;
+ strm->avail_out = sizeof(out_buf);
+
+ while (true) {
+ if (strm->avail_in == 0) {
+ ssize_t rdret = read(file->fd, in_buf, sizeof(in_buf));
+ if (rdret < 0) {
+ ret = -errno;
+ goto out;
+ }
+ strm->next_in = in_buf;
+ strm->avail_in = rdret;
+ if (rdret == 0)
+ action = LZMA_FINISH;
+ }
+ ret = lzma_code(strm, action);
+ if (strm->avail_out == 0 || ret != LZMA_OK) {
+ size_t write_size = BUFSIZ - strm->avail_out;
+ char *tmp = realloc(p, total + write_size);
+ if (tmp == NULL) {
+ ret = -errno;
+ goto out;
+ }
+ memcpy(tmp + total, out_buf, write_size);
+ total += write_size;
+ p = tmp;
+ strm->next_out = out_buf;
+ strm->avail_out = BUFSIZ;
+ }
+ if (ret == LZMA_STREAM_END)
+ break;
+ if (ret != LZMA_OK) {
+ xz_uncompress_belch(file, ret);
+ ret = -EINVAL;
+ goto out;
+ }
+ }
+ file->memory = p;
+ file->size = total;
+ return 0;
+ out:
+ free(p);
+ return ret;
+}
+
+int kmod_file_load_xz(struct kmod_file *file)
+{
+ lzma_stream strm = LZMA_STREAM_INIT;
+ lzma_ret lzret;
+ int ret;
+
+ lzret = lzma_stream_decoder(&strm, UINT64_MAX, LZMA_CONCATENATED);
+ if (lzret == LZMA_MEM_ERROR) {
+ ERR(file->ctx, "xz: %s\n", strerror(ENOMEM));
+ return -ENOMEM;
+ } else if (lzret != LZMA_OK) {
+ ERR(file->ctx, "xz: Internal error (bug)\n");
+ return -EINVAL;
+ }
+ ret = xz_uncompress(&strm, file);
+ lzma_end(&strm);
+ return ret;
+}
#ifdef ENABLE_ZSTD
#include <zstd.h>
#endif
-#ifdef ENABLE_XZ
-#include <lzma.h>
-#endif
#ifdef ENABLE_ZLIB
#include <zlib.h>
#endif
#include "libkmod.h"
#include "libkmod-internal.h"
-
-struct kmod_file {
- int fd;
- enum kmod_file_compression_type compression;
- off_t size;
- void *memory;
- int (*load)(struct kmod_file *file);
- const struct kmod_ctx *ctx;
- struct kmod_elf *elf;
-};
+#include "libkmod-internal-file.h"
#ifdef ENABLE_ZSTD
static int zstd_read_block(struct kmod_file *file, size_t block_size,
#endif
static const char magic_zstd[] = {0x28, 0xB5, 0x2F, 0xFD};
-
-#ifdef ENABLE_XZ
-static void xz_uncompress_belch(struct kmod_file *file, lzma_ret ret)
-{
- switch (ret) {
- case LZMA_MEM_ERROR:
- ERR(file->ctx, "xz: %s\n", strerror(ENOMEM));
- break;
- case LZMA_FORMAT_ERROR:
- ERR(file->ctx, "xz: File format not recognized\n");
- break;
- case LZMA_OPTIONS_ERROR:
- ERR(file->ctx, "xz: Unsupported compression options\n");
- break;
- case LZMA_DATA_ERROR:
- ERR(file->ctx, "xz: File is corrupt\n");
- break;
- case LZMA_BUF_ERROR:
- ERR(file->ctx, "xz: Unexpected end of input\n");
- break;
- default:
- ERR(file->ctx, "xz: Internal error (bug)\n");
- break;
- }
-}
-
-static int xz_uncompress(lzma_stream *strm, struct kmod_file *file)
-{
- uint8_t in_buf[BUFSIZ], out_buf[BUFSIZ];
- lzma_action action = LZMA_RUN;
- lzma_ret ret;
- void *p = NULL;
- size_t total = 0;
-
- strm->avail_in = 0;
- strm->next_out = out_buf;
- strm->avail_out = sizeof(out_buf);
-
- while (true) {
- if (strm->avail_in == 0) {
- ssize_t rdret = read(file->fd, in_buf, sizeof(in_buf));
- if (rdret < 0) {
- ret = -errno;
- goto out;
- }
- strm->next_in = in_buf;
- strm->avail_in = rdret;
- if (rdret == 0)
- action = LZMA_FINISH;
- }
- ret = lzma_code(strm, action);
- if (strm->avail_out == 0 || ret != LZMA_OK) {
- size_t write_size = BUFSIZ - strm->avail_out;
- char *tmp = realloc(p, total + write_size);
- if (tmp == NULL) {
- ret = -errno;
- goto out;
- }
- memcpy(tmp + total, out_buf, write_size);
- total += write_size;
- p = tmp;
- strm->next_out = out_buf;
- strm->avail_out = BUFSIZ;
- }
- if (ret == LZMA_STREAM_END)
- break;
- if (ret != LZMA_OK) {
- xz_uncompress_belch(file, ret);
- ret = -EINVAL;
- goto out;
- }
- }
- file->memory = p;
- file->size = total;
- return 0;
- out:
- free(p);
- return ret;
-}
-
-static int load_xz(struct kmod_file *file)
-{
- lzma_stream strm = LZMA_STREAM_INIT;
- lzma_ret lzret;
- int ret;
-
- lzret = lzma_stream_decoder(&strm, UINT64_MAX, LZMA_CONCATENATED);
- if (lzret == LZMA_MEM_ERROR) {
- ERR(file->ctx, "xz: %s\n", strerror(ENOMEM));
- return -ENOMEM;
- } else if (lzret != LZMA_OK) {
- ERR(file->ctx, "xz: Internal error (bug)\n");
- return -EINVAL;
- }
- ret = xz_uncompress(&strm, file);
- lzma_end(&strm);
- return ret;
-}
-#else
-static int load_xz(struct kmod_file *file)
-{
- return -ENOSYS;
-}
-#endif
-
static const char magic_xz[] = {0xfd, '7', 'z', 'X', 'Z', 0};
#ifdef ENABLE_ZLIB
int (*load)(struct kmod_file *file);
} comp_types[] = {
{sizeof(magic_zstd), KMOD_FILE_COMPRESSION_ZSTD, magic_zstd, load_zstd},
- {sizeof(magic_xz), KMOD_FILE_COMPRESSION_XZ, magic_xz, load_xz},
+ {sizeof(magic_xz), KMOD_FILE_COMPRESSION_XZ, magic_xz, kmod_file_load_xz},
{sizeof(magic_zlib), KMOD_FILE_COMPRESSION_ZLIB, magic_zlib, load_zlib},
{0, KMOD_FILE_COMPRESSION_NONE, NULL, load_reg}
};