implement zlib module loading.

This commit is contained in:
Gustavo Sverzut Barbieri 2011-12-16 16:08:53 -02:00 committed by Lucas De Marchi
parent f4fc552368
commit 3d8226edfe
7 changed files with 224 additions and 18 deletions

View File

@ -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
View File

@ -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:
=========== ===========

View File

@ -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
View 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);
}

View 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;
} }

View File

@ -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)));

View File

@ -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}