mirror of
https://github.com/AuxXxilium/kmod.git
synced 2025-02-20 16:44:50 +07:00
Support for loading Xz-compressed modules
This commit is contained in:
parent
5a51a357a8
commit
b182f8fb5e
@ -27,6 +27,8 @@ SED_PROCESS = \
|
||||
-e 's,@exec_prefix\@,$(exec_prefix),g' \
|
||||
-e 's,@libdir\@,$(libdir),g' \
|
||||
-e 's,@includedir\@,$(includedir),g' \
|
||||
-e 's,@liblzma_CFLAGS\@,${liblzma_CFLAGS},g' \
|
||||
-e 's,@liblzma_LIBS\@,${liblzma_LIBS},g' \
|
||||
-e 's,@zlib_CFLAGS\@,${zlib_CFLAGS},g' \
|
||||
-e 's,@zlib_LIBS\@,${zlib_LIBS},g' \
|
||||
< $< > $@ || rm $@
|
||||
@ -63,7 +65,7 @@ libkmod_libkmod_la_LDFLAGS = $(AM_LDFLAGS) \
|
||||
-version-info $(LIBKMOD_CURRENT):$(LIBKMOD_REVISION):$(LIBKMOD_AGE) \
|
||||
-Wl,--version-script=$(top_srcdir)/libkmod/libkmod.sym
|
||||
libkmod_libkmod_la_DEPENDENCIES = ${top_srcdir}/libkmod/libkmod.sym
|
||||
libkmod_libkmod_la_LIBADD = ${zlib_LIBS}
|
||||
libkmod_libkmod_la_LIBADD = ${liblzma_LIBS} ${zlib_LIBS}
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = libkmod/libkmod.pc
|
||||
|
12
configure.ac
12
configure.ac
@ -51,6 +51,16 @@ AS_IF([test "x$enable_logging" = "xyes"], [
|
||||
AC_DEFINE(ENABLE_LOGGING, [1], [System logging.])
|
||||
])
|
||||
|
||||
AC_ARG_WITH([xz],
|
||||
AS_HELP_STRING([--with-xz], [handle Xz-compressed modules @<:@default=disabled@:>@]),
|
||||
[], [with_xz=no])
|
||||
AS_IF([test "x$with_xz" != "xno"], [
|
||||
PKG_CHECK_MODULES([liblzma], [liblzma >= 4.99])
|
||||
AC_DEFINE([ENABLE_XZ], [1], [Enable Xz for modules.])
|
||||
], [
|
||||
AC_MSG_NOTICE([Xz support not requested])
|
||||
])
|
||||
|
||||
AC_ARG_WITH([zlib],
|
||||
AS_HELP_STRING([--with-zlib], [handle gzipped modules @<:@default=disabled@:>@]),
|
||||
[], [with_zlib=no])
|
||||
@ -139,6 +149,6 @@ AC_MSG_RESULT([
|
||||
|
||||
tools: ${enable_tools}
|
||||
logging: ${enable_logging}
|
||||
zlib: ${with_zlib}
|
||||
compression: xz=${with_xz} zlib=${with_zlib}
|
||||
debug: ${enable_debug}
|
||||
])
|
||||
|
@ -18,6 +18,7 @@
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
@ -30,11 +31,17 @@
|
||||
#include "libkmod.h"
|
||||
#include "libkmod-private.h"
|
||||
|
||||
#ifdef ENABLE_XZ
|
||||
#include <lzma.h>
|
||||
#endif
|
||||
#ifdef ENABLE_ZLIB
|
||||
#include <zlib.h>
|
||||
#endif
|
||||
|
||||
struct kmod_file {
|
||||
#ifdef ENABLE_XZ
|
||||
bool xz_used;
|
||||
#endif
|
||||
#ifdef ENABLE_ZLIB
|
||||
gzFile gzf;
|
||||
#endif
|
||||
@ -43,6 +50,120 @@ struct kmod_file {
|
||||
void *memory;
|
||||
};
|
||||
|
||||
#ifdef ENABLE_XZ
|
||||
static bool xz_detect(struct kmod_file *file)
|
||||
{
|
||||
ssize_t ret;
|
||||
char buf[6];
|
||||
|
||||
ret = read(file->fd, buf, sizeof(buf));
|
||||
if (ret < 0 || lseek(file->fd, 0, SEEK_SET))
|
||||
return -errno;
|
||||
return ret == sizeof(buf) &&
|
||||
memcmp(buf, "\xFD""7zXZ\x00", sizeof(buf)) == 0;
|
||||
}
|
||||
|
||||
static void xz_uncompress_belch(lzma_ret ret)
|
||||
{
|
||||
switch (ret) {
|
||||
case LZMA_MEM_ERROR:
|
||||
fprintf(stderr, "xz: %s\n", strerror(ENOMEM));
|
||||
break;
|
||||
case LZMA_FORMAT_ERROR:
|
||||
fprintf(stderr, "xz: File format not recognized\n");
|
||||
break;
|
||||
case LZMA_OPTIONS_ERROR:
|
||||
fprintf(stderr, "xz: Unsupported compression options\n");
|
||||
break;
|
||||
case LZMA_DATA_ERROR:
|
||||
fprintf(stderr, "xz: File is corrupt\n");
|
||||
break;
|
||||
case LZMA_BUF_ERROR:
|
||||
fprintf(stderr, "xz: Unexpected end of input\n");
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "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(ret);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
file->memory = p;
|
||||
file->size = total;
|
||||
return 0;
|
||||
out:
|
||||
free(p);
|
||||
close(file->fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int xz_file_open(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) {
|
||||
fprintf(stderr, "xz: %s\n", strerror(ENOMEM));
|
||||
close(file->fd);
|
||||
return -ENOMEM;
|
||||
} else if (lzret != LZMA_OK) {
|
||||
fprintf(stderr, "xz: Internal error (bug)\n");
|
||||
close(file->fd);
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = xz_uncompress(&strm, file);
|
||||
lzma_end(&strm);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_ZLIB
|
||||
#define READ_STEP (4 * 1024 * 1024)
|
||||
|
||||
@ -152,6 +273,11 @@ struct kmod_file *kmod_file_open(const char *filename)
|
||||
goto error;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_XZ
|
||||
if (xz_detect(file))
|
||||
err = xz_file_open(file);
|
||||
else
|
||||
#endif
|
||||
#ifdef ENABLE_ZLIB
|
||||
if (check_zlib(file))
|
||||
err = zlib_file_open(file);
|
||||
@ -181,6 +307,12 @@ off_t kmod_file_get_size(const struct kmod_file *file)
|
||||
|
||||
void kmod_file_unref(struct kmod_file *file)
|
||||
{
|
||||
#ifdef ENABLE_XZ
|
||||
if (file->xz_used) {
|
||||
free(file->memory);
|
||||
close(file->fd);
|
||||
} else
|
||||
#endif
|
||||
#ifdef ENABLE_ZLIB
|
||||
if (file->gzf != NULL) {
|
||||
free(file->memory);
|
||||
|
@ -7,5 +7,5 @@ Name: libkmod
|
||||
Description: Library to deal with kernel modules
|
||||
Version: @VERSION@
|
||||
Libs: -L${libdir} -lkmod
|
||||
Libs.private: @zlib_LIBS@
|
||||
Cflags: -I${includedir} @zlib_CFLAGS@
|
||||
Libs.private: @liblzma_LIBS@ @zlib_LIBS@
|
||||
Cflags: -I${includedir} @liblzma_CFLAGS@ @zlib_CFLAGS@
|
||||
|
Loading…
Reference in New Issue
Block a user