mirror of
https://github.com/AuxXxilium/kmod.git
synced 2025-01-20 02:49:27 +07:00
implement zlib module loading.
This commit is contained in:
parent
f4fc552368
commit
3d8226edfe
@ -36,7 +36,8 @@ libkmod_libkmod_la_SOURCES =\
|
|||||||
libkmod/libkmod-util.c \
|
libkmod/libkmod-util.c \
|
||||||
libkmod/libkmod-index.c \
|
libkmod/libkmod-index.c \
|
||||||
libkmod/libkmod-index.h \
|
libkmod/libkmod-index.h \
|
||||||
libkmod/libkmod-module.c
|
libkmod/libkmod-module.c \
|
||||||
|
libkmod/libkmod-file.c
|
||||||
|
|
||||||
EXTRA_DIST += libkmod/libkmod.sym
|
EXTRA_DIST += libkmod/libkmod.sym
|
||||||
EXTRA_DIST += libkmod/COPYING libkmod/README
|
EXTRA_DIST += libkmod/COPYING libkmod/README
|
||||||
@ -45,6 +46,7 @@ libkmod_libkmod_la_LDFLAGS = $(AM_LDFLAGS) \
|
|||||||
-version-info $(LIBKMOD_CURRENT):$(LIBKMOD_REVISION):$(LIBKMOD_AGE) \
|
-version-info $(LIBKMOD_CURRENT):$(LIBKMOD_REVISION):$(LIBKMOD_AGE) \
|
||||||
-Wl,--version-script=$(top_srcdir)/libkmod/libkmod.sym
|
-Wl,--version-script=$(top_srcdir)/libkmod/libkmod.sym
|
||||||
libkmod_libkmod_la_DEPENDENCIES = ${top_srcdir}/libkmod/libkmod.sym
|
libkmod_libkmod_la_DEPENDENCIES = ${top_srcdir}/libkmod/libkmod.sym
|
||||||
|
libkmod_libkmod_la_LIBADD = @zlib_libs@
|
||||||
|
|
||||||
pkgconfigdir = $(libdir)/pkgconfig
|
pkgconfigdir = $(libdir)/pkgconfig
|
||||||
pkgconfig_DATA = libkmod/libkmod.pc
|
pkgconfig_DATA = libkmod/libkmod.pc
|
||||||
|
2
TODO
2
TODO
@ -26,8 +26,6 @@ Features:
|
|||||||
- install and remove commands may exist when there's no module with that
|
- install and remove commands may exist when there's no module with that
|
||||||
name. Properly handle this case
|
name. Properly handle this case
|
||||||
|
|
||||||
* gzip support for modprobe
|
|
||||||
|
|
||||||
Known Bugs:
|
Known Bugs:
|
||||||
===========
|
===========
|
||||||
|
|
||||||
|
42
configure.ac
42
configure.ac
@ -23,6 +23,8 @@ AC_C_TYPEOF
|
|||||||
AM_PROG_CC_C_O
|
AM_PROG_CC_C_O
|
||||||
AC_PROG_GCC_TRADITIONAL
|
AC_PROG_GCC_TRADITIONAL
|
||||||
|
|
||||||
|
required_private_libs=""
|
||||||
|
|
||||||
AC_ARG_ENABLE([tools],
|
AC_ARG_ENABLE([tools],
|
||||||
AS_HELP_STRING([--disable-tools], [disable building tools that provide same functionality as module-init-tools @<:@default=enabled@:>@]),
|
AS_HELP_STRING([--disable-tools], [disable building tools that provide same functionality as module-init-tools @<:@default=enabled@:>@]),
|
||||||
[], enable_tools=yes)
|
[], enable_tools=yes)
|
||||||
@ -35,6 +37,43 @@ AS_IF([test "x$enable_logging" = "xyes"], [
|
|||||||
AC_DEFINE(ENABLE_LOGGING, [1], [System logging.])
|
AC_DEFINE(ENABLE_LOGGING, [1], [System logging.])
|
||||||
])
|
])
|
||||||
|
|
||||||
|
AC_ARG_ENABLE([zlib],
|
||||||
|
AS_HELP_STRING([--enable-zlib], [handle gzipped modules (options: static or dynamic) @<:@default=disabled@:>@]),
|
||||||
|
[], enable_zlib=no)
|
||||||
|
if test "x$enable_zlib" = "xyes" -o "x$enable_zlib" = "xstatic"; then
|
||||||
|
enable_zlib="static"
|
||||||
|
zlib_libs="-Wl,-Bstatic -lz -Wl,-Bdynamic"
|
||||||
|
SAVE_LIBS="${LIBS}"
|
||||||
|
LIBS="${LIBS} ${zlib_libs}"
|
||||||
|
AC_MSG_CHECKING([if static zlib exists])
|
||||||
|
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||||
|
#include <zlib.h>
|
||||||
|
]], [[
|
||||||
|
gzFile f = gzopen("/tmp", "rb");
|
||||||
|
]])],
|
||||||
|
[have_zlib=yes], [have_zlib=no])
|
||||||
|
LIBS="${SAVE_LIBS}"
|
||||||
|
AC_MSG_RESULT([$have_zlib])
|
||||||
|
if test "x$have_zlib" != "xyes"; then
|
||||||
|
zlib_libs=""
|
||||||
|
AC_MSG_ERROR([static zlib is not present])
|
||||||
|
fi
|
||||||
|
elif test "x$enable_zlib" = "xdynamic"; then
|
||||||
|
AC_CHECK_LIB([z], [gzopen],
|
||||||
|
[
|
||||||
|
zlib_libs="-lz"
|
||||||
|
required_private_libs="${required_private_libs} ${zlib_libs}"
|
||||||
|
],
|
||||||
|
[AC_MSG_ERROR([dynamic zlib is not present])])
|
||||||
|
else
|
||||||
|
AC_MSG_NOTICE([zlib support not requested])
|
||||||
|
zlib_libs=""
|
||||||
|
fi
|
||||||
|
if test "x$zlib_libs" != "x"; then
|
||||||
|
AC_DEFINE(ENABLE_ZLIB, [1], [Enable zlib for modules.])
|
||||||
|
fi
|
||||||
|
AC_SUBST(zlib_libs)
|
||||||
|
|
||||||
AC_ARG_ENABLE([debug],
|
AC_ARG_ENABLE([debug],
|
||||||
AS_HELP_STRING([--enable-debug], [enable debug messages @<:@default=disabled@:>@]),
|
AS_HELP_STRING([--enable-debug], [enable debug messages @<:@default=disabled@:>@]),
|
||||||
[], [enable_debug=no])
|
[], [enable_debug=no])
|
||||||
@ -92,6 +131,8 @@ CC_CHECK_CFLAGS_APPEND([ \
|
|||||||
-Wl,--gc-sections])
|
-Wl,--gc-sections])
|
||||||
|
|
||||||
|
|
||||||
|
AC_SUBST(required_private_libs)
|
||||||
|
|
||||||
AC_CONFIG_HEADERS(config.h)
|
AC_CONFIG_HEADERS(config.h)
|
||||||
AC_CONFIG_FILES([
|
AC_CONFIG_FILES([
|
||||||
Makefile
|
Makefile
|
||||||
@ -115,5 +156,6 @@ AC_MSG_RESULT([
|
|||||||
|
|
||||||
tools: ${enable_tools}
|
tools: ${enable_tools}
|
||||||
logging: ${enable_logging}
|
logging: ${enable_logging}
|
||||||
|
zlib: ${enable_zlib}
|
||||||
debug: ${enable_debug}
|
debug: ${enable_debug}
|
||||||
])
|
])
|
||||||
|
163
libkmod/libkmod-file.c
Normal file
163
libkmod/libkmod-file.c
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
/*
|
||||||
|
* libkmod - interface to kernel module operations
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 ProFUSION embedded systems
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "libkmod.h"
|
||||||
|
#include "libkmod-private.h"
|
||||||
|
|
||||||
|
#ifdef ENABLE_ZLIB
|
||||||
|
#include <zlib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct kmod_file {
|
||||||
|
#ifdef ENABLE_ZLIB
|
||||||
|
gzFile gzf;
|
||||||
|
#else
|
||||||
|
int fd;
|
||||||
|
#endif
|
||||||
|
off_t size;
|
||||||
|
void *memory;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef ENABLE_ZLIB
|
||||||
|
#define READ_STEP (4 * 1024 * 1024)
|
||||||
|
static int zlip_file_open(struct kmod_file *file, const char *filename)
|
||||||
|
{
|
||||||
|
int err = 0;
|
||||||
|
off_t did = 0, total = 0;
|
||||||
|
unsigned char *p = NULL;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
file->gzf = gzopen(filename, "rbe");
|
||||||
|
if (file->gzf == NULL)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (did == total) {
|
||||||
|
void *tmp = realloc(p, total + READ_STEP);
|
||||||
|
if (tmp == NULL) {
|
||||||
|
err = -errno;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
total += READ_STEP;
|
||||||
|
p = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = gzread(file->gzf, p + did, total - did);
|
||||||
|
if (r == 0)
|
||||||
|
break;
|
||||||
|
else if (r < 0) {
|
||||||
|
err = -errno;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
did += r;
|
||||||
|
}
|
||||||
|
|
||||||
|
file->memory = p;
|
||||||
|
file->size = did;
|
||||||
|
return 0;
|
||||||
|
error:
|
||||||
|
free(p);
|
||||||
|
gzclose(file->gzf);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static int reg_file_open(struct kmod_file *file, const char *filename)
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
file->fd = open(filename, O_RDONLY|O_CLOEXEC);
|
||||||
|
if (file->fd < 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
if (fstat(file->fd, &st) < 0) {
|
||||||
|
err = -errno;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
file->size = st.st_size;
|
||||||
|
file->memory = mmap(0, file->size, PROT_READ, MAP_PRIVATE, file->fd, 0);
|
||||||
|
if (file->memory == MAP_FAILED) {
|
||||||
|
err = -errno;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
error:
|
||||||
|
close(file->fd);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct kmod_file *kmod_file_open(const char *filename)
|
||||||
|
{
|
||||||
|
struct kmod_file *file = calloc(1, sizeof(struct kmod_file));
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (file == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
#ifdef ENABLE_ZLIB
|
||||||
|
err = zlip_file_open(file, filename);
|
||||||
|
#else
|
||||||
|
err = reg_file_open(file, filename);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (err < 0) {
|
||||||
|
free(file);
|
||||||
|
errno = -err;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *kmod_file_get_contents(const struct kmod_file *file)
|
||||||
|
{
|
||||||
|
return file->memory;
|
||||||
|
}
|
||||||
|
|
||||||
|
off_t kmod_file_get_size(const struct kmod_file *file)
|
||||||
|
{
|
||||||
|
return file->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void kmod_file_unref(struct kmod_file *file)
|
||||||
|
{
|
||||||
|
#ifdef ENABLE_ZLIB
|
||||||
|
free(file->memory);
|
||||||
|
gzclose(file->gzf);
|
||||||
|
#else
|
||||||
|
munmap(file->memory, file->size);
|
||||||
|
close(file->fd);
|
||||||
|
#endif
|
||||||
|
free(file);
|
||||||
|
}
|
@ -693,9 +693,9 @@ KMOD_EXPORT int kmod_module_insert_module(struct kmod_module *mod,
|
|||||||
const char *options)
|
const char *options)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
void *mmaped_file;
|
void *mem;
|
||||||
struct stat st;
|
off_t size;
|
||||||
int fd;
|
struct kmod_file *file;
|
||||||
const char *args = options ? options : "";
|
const char *args = options ? options : "";
|
||||||
|
|
||||||
if (mod == NULL)
|
if (mod == NULL)
|
||||||
@ -709,25 +709,20 @@ KMOD_EXPORT int kmod_module_insert_module(struct kmod_module *mod,
|
|||||||
if (flags != 0)
|
if (flags != 0)
|
||||||
INFO(mod->ctx, "Flags are not implemented yet\n");
|
INFO(mod->ctx, "Flags are not implemented yet\n");
|
||||||
|
|
||||||
if ((fd = open(mod->path, O_RDONLY|O_CLOEXEC)) < 0) {
|
file = kmod_file_open(mod->path);
|
||||||
|
if (file == NULL) {
|
||||||
err = -errno;
|
err = -errno;
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
fstat(fd, &st);
|
size = kmod_file_get_size(file);
|
||||||
|
mem = kmod_file_get_contents(file);
|
||||||
|
|
||||||
if ((mmaped_file = mmap(0, st.st_size, PROT_READ,
|
err = init_module(mem, size, args);
|
||||||
MAP_PRIVATE, fd, 0)) == MAP_FAILED) {
|
|
||||||
close(fd);
|
|
||||||
return -errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = init_module(mmaped_file, st.st_size, args);
|
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
ERR(mod->ctx, "Failed to insert module '%s'\n", mod->path);
|
ERR(mod->ctx, "Failed to insert module '%s'\n", mod->path);
|
||||||
|
|
||||||
munmap(mmaped_file, st.st_size);
|
kmod_file_unref(file);
|
||||||
close(fd);
|
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -121,6 +121,12 @@ int kmod_hash_add(struct kmod_hash *hash, const char *key, const void *value);
|
|||||||
int kmod_hash_del(struct kmod_hash *hash, const char *key);
|
int kmod_hash_del(struct kmod_hash *hash, const char *key);
|
||||||
void *kmod_hash_find(const struct kmod_hash *hash, const char *key);
|
void *kmod_hash_find(const struct kmod_hash *hash, const char *key);
|
||||||
|
|
||||||
|
/* libkmod-file.c */
|
||||||
|
struct kmod_file *kmod_file_open(const char *filename) __must_check __attribute__((nonnull(1)));
|
||||||
|
void *kmod_file_get_contents(const struct kmod_file *file) __must_check __attribute__((nonnull(1)));
|
||||||
|
off_t kmod_file_get_size(const struct kmod_file *file) __must_check __attribute__((nonnull(1)));
|
||||||
|
void kmod_file_unref(struct kmod_file *file) __attribute__((nonnull(1)));
|
||||||
|
|
||||||
|
|
||||||
/* util functions */
|
/* util functions */
|
||||||
char *getline_wrapped(FILE *fp, unsigned int *linenum) __attribute__((nonnull(1)));
|
char *getline_wrapped(FILE *fp, unsigned int *linenum) __attribute__((nonnull(1)));
|
||||||
|
@ -7,5 +7,5 @@ Name: libkmod
|
|||||||
Description: Library to deal with kernel modules
|
Description: Library to deal with kernel modules
|
||||||
Version: @VERSION@
|
Version: @VERSION@
|
||||||
Libs: -L${libdir} -lkmod
|
Libs: -L${libdir} -lkmod
|
||||||
Libs.private:
|
Libs.private: @required_private_libs@
|
||||||
Cflags: -I${includedir}
|
Cflags: -I${includedir}
|
||||||
|
Loading…
Reference in New Issue
Block a user