mirror of
https://github.com/AuxXxilium/kmod.git
synced 2024-11-23 15:00:52 +07:00
libkmod: Move xz-related functions to separate file
Move xz-related function to a separate file so it's easier to isolate the dependency on each decompression library. Declare struct kmod_file in a shared libkmod-internal-file.h that will be included only by sources implementing kmod_file decompression routines. Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com> Link: https://github.com/kmod-project/kmod/pull/58 Signed-off-by: Lucas De Marchi <lucas.de.marchi@gmail.com>
This commit is contained in:
parent
d4d3df1089
commit
929ca4c92a
@ -63,6 +63,7 @@ lib_LTLIBRARIES = libkmod/libkmod.la
|
||||
|
||||
libkmod_libkmod_la_SOURCES = \
|
||||
libkmod/libkmod.h \
|
||||
libkmod/libkmod-internal-file.h \
|
||||
libkmod/libkmod-internal.h \
|
||||
libkmod/libkmod.c \
|
||||
libkmod/libkmod-builtin.c \
|
||||
@ -75,6 +76,10 @@ libkmod_libkmod_la_SOURCES = \
|
||||
libkmod/libkmod-elf.c \
|
||||
libkmod/libkmod-signature.c
|
||||
|
||||
if ENABLE_XZ
|
||||
libkmod_libkmod_la_SOURCES += libkmod/libkmod-file-xz.c
|
||||
endif
|
||||
|
||||
EXTRA_DIST += libkmod/libkmod.sym
|
||||
EXTRA_DIST += libkmod/README \
|
||||
libkmod/COPYING testsuite/COPYING tools/COPYING COPYING
|
||||
|
@ -137,6 +137,7 @@ AS_IF([test "x$with_xz" != "xno"], [
|
||||
AC_MSG_NOTICE([Xz support not requested])
|
||||
])
|
||||
CC_FEATURE_APPEND([with_features], [with_xz], [XZ])
|
||||
AM_CONDITIONAL([ENABLE_XZ], [test "x$with_xz" != "xno"])
|
||||
|
||||
AC_ARG_WITH([zlib],
|
||||
AS_HELP_STRING([--with-zlib], [handle gzipped modules @<:@default=disabled@:>@]),
|
||||
|
116
libkmod/libkmod-file-xz.c
Normal file
116
libkmod/libkmod-file-xz.c
Normal file
@ -0,0 +1,116 @@
|
||||
// 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;
|
||||
}
|
@ -29,9 +29,6 @@
|
||||
#ifdef ENABLE_ZSTD
|
||||
#include <zstd.h>
|
||||
#endif
|
||||
#ifdef ENABLE_XZ
|
||||
#include <lzma.h>
|
||||
#endif
|
||||
#ifdef ENABLE_ZLIB
|
||||
#include <zlib.h>
|
||||
#endif
|
||||
@ -40,16 +37,7 @@
|
||||
|
||||
#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,
|
||||
@ -186,111 +174,6 @@ static int load_zstd(struct kmod_file *file)
|
||||
#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
|
||||
@ -387,7 +270,7 @@ static const struct comp_type {
|
||||
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}
|
||||
};
|
||||
|
27
libkmod/libkmod-internal-file.h
Normal file
27
libkmod/libkmod-internal-file.h
Normal file
@ -0,0 +1,27 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
/*
|
||||
* Copyright © 2024 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <libkmod/libkmod-internal.h>
|
||||
|
||||
struct kmod_ctx;
|
||||
struct kmod_elf;
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
#ifdef ENABLE_XZ
|
||||
int kmod_file_load_xz(struct kmod_file *file);
|
||||
#else
|
||||
static inline int kmod_file_load_xz(struct kmod_file *file) { return -ENOSYS; }
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user