]> git.ipfire.org Git - thirdparty/kmod.git/commitdiff
Add functions to operate on modules
authorLucas De Marchi <lucas.demarchi@profusion.mobi>
Fri, 25 Nov 2011 03:22:56 +0000 (01:22 -0200)
committerLucas De Marchi <lucas.demarchi@profusion.mobi>
Fri, 25 Nov 2011 03:22:56 +0000 (01:22 -0200)
Makefile.am
libkmod/libkmod-module.c [new file with mode: 0644]
libkmod/libkmod.h
libkmod/libkmod.sym
libkmod/macro.h

index e4a730571b812c4764d565ce15af39ea8e10a764..db30172ffb9298685900e42dfdcc9c52fea68b7b 100644 (file)
@@ -32,7 +32,8 @@ libkmod_libkmod_la_SOURCES =\
        libkmod/macro.h \
        libkmod/libkmod.c \
        libkmod/libkmod-list.c \
-       libkmod/libkmod-loaded.c
+       libkmod/libkmod-loaded.c \
+       libkmod/libkmod-module.c
 
 EXTRA_DIST += libkmod/libkmod.sym
 
diff --git a/libkmod/libkmod-module.c b/libkmod/libkmod-module.c
new file mode 100644 (file)
index 0000000..5e8ae73
--- /dev/null
@@ -0,0 +1,224 @@
+/*
+ * libkmod - interface to kernel module operations
+ *
+ * Copyright (C) 2011  ProFUSION embedded systems
+ * Copyright (C) 2011  Lucas De Marchi <lucas.de.marchi@gmail.com>
+ *
+ * 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 version 2.1.
+ *
+ * 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 <stddef.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <ctype.h>
+#include <inttypes.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <string.h>
+
+#include "libkmod.h"
+#include "libkmod-private.h"
+
+/**
+ * kmod_module:
+ *
+ * Opaque object representing a module.
+ */
+struct kmod_module {
+       struct kmod_ctx *ctx;
+       int refcount;
+       const char *path;
+       const char *name;
+};
+
+static char *path_to_modname(const char *path)
+{
+       char *modname;
+       char *c;
+
+       modname = basename(path);
+       if (modname == NULL || modname[0] == '\0')
+               return NULL;
+
+       modname = strdup(modname);
+       for (c = modname; *c != '\0' && *c != '.'; c++) {
+               if (*c == '-')
+                       *c = '_';
+       }
+
+       *c = '\0';
+       return modname;
+}
+
+static const char *get_modname(struct kmod_module *mod)
+{
+       if (mod->name == NULL)
+               mod->name = path_to_modname(mod->path);
+
+       return mod->name;
+}
+
+KMOD_EXPORT int kmod_module_new_from_name(struct kmod_ctx *ctx,
+                                               const char *name,
+                                               struct kmod_module **mod)
+{
+       struct kmod_module *m;
+
+       if (ctx == NULL || name == NULL)
+               return -ENOENT;
+
+       m = calloc(1, sizeof(*m));
+       if (m == NULL) {
+               free(m);
+               return -ENOMEM;
+       }
+
+       m->ctx = kmod_ref(ctx);
+       m->name = strdup(name);
+
+       *mod = m;
+
+       return 0;
+}
+
+KMOD_EXPORT int kmod_module_new_from_path(struct kmod_ctx *ctx,
+                                               const char *path,
+                                               struct kmod_module **mod)
+{
+       struct kmod_module *m;
+       int err;
+       struct stat st;
+
+       if (ctx == NULL || path == NULL)
+               return -ENOENT;
+
+       err = stat(path, &st);
+       if (err < 0)
+               return -errno;
+
+       m = calloc(1, sizeof(*m));
+       if (m == NULL) {
+               free(m);
+               return -ENOMEM;
+       }
+
+       m->ctx = kmod_ref(ctx);
+       m->path = strdup(path);
+
+       *mod = m;
+
+       return 0;
+}
+
+KMOD_EXPORT struct kmod_module *kmod_module_unref(struct kmod_module *mod)
+{
+       if (mod == NULL)
+               return NULL;
+
+       if (--mod->refcount > 0)
+               return mod;
+
+       DBG(mod->ctx, "kmod_module %p released\n", mod);
+
+       kmod_unref(mod->ctx);
+       free((char *) mod->path);
+       free((char *) mod->name);
+       free(mod);
+       return NULL;
+}
+
+KMOD_EXPORT struct kmod_module *kmod_module_ref(struct kmod_module *mod)
+{
+       if (mod == NULL)
+               return NULL;
+
+       mod->refcount++;
+
+       return mod;
+}
+
+extern long delete_module(const char *name, unsigned int flags);
+
+KMOD_EXPORT int kmod_module_remove_module(struct kmod_module *mod,
+                                                       unsigned int flags)
+{
+       int err;
+       const char *modname;
+
+       if (mod == NULL)
+               return -ENOENT;
+
+       /* Filter out other flags */
+       flags &= (KMOD_REMOVE_FORCE | KMOD_REMOVE_NOWAIT);
+
+       modname = get_modname(mod);
+       err = delete_module(modname, flags);
+       if (err != 0) {
+               ERR(mod->ctx, "Removing '%s': %s\n", modname,
+                                                       strerror(-err));
+               return err;
+       }
+
+       return 0;
+}
+
+extern long init_module(void *mem, unsigned long len, const char *args);
+
+KMOD_EXPORT int kmod_module_insert_module(struct kmod_module *mod,
+                                                       unsigned int flags)
+{
+       int err;
+       void *mmaped_file;
+       struct stat st;
+       int fd;
+       const char *args = "";
+
+       if (mod == NULL)
+               return -ENOENT;
+
+       if (mod->path == NULL) {
+               ERR(mod->ctx, "Not supported to load a module by name yet");
+               return -ENOSYS;
+       }
+
+       if (flags != 0)
+               INFO(mod->ctx, "Flags are not implemented yet");
+
+       if ((fd = open(mod->path, O_RDONLY)) < 0) {
+               err = -errno;
+               return err;
+       }
+
+       stat(mod->path, &st);
+
+       if ((mmaped_file = mmap(0, st.st_size, PROT_READ,
+                                       MAP_PRIVATE, fd, 0)) == MAP_FAILED) {
+               close(fd);
+               return -errno;
+       }
+
+       err = init_module(mmaped_file, st.st_size, args);
+       if (err < 0)
+               ERR(mod->ctx, "Failed to insert module '%s'", mod->path);
+
+       munmap(mmaped_file, st.st_size);
+       close(fd);
+
+       return err;
+}
index d68d2ef36f7e5a71736c16fbd8e62a1398ed1c1c..23ba079bb09d574af8061a5037480171fc9b3511 100644 (file)
@@ -66,6 +66,11 @@ struct kmod_list *kmod_list_next(struct kmod_list *first_entry,
 } /* extern "C" */
 #endif
 
+/*
+ * kmod_loaded
+ *
+ * retrieve info from /proc/modules regarding loaded modules
+ */
 struct kmod_loaded;
 int kmod_loaded_new(struct kmod_ctx *ctx, struct kmod_loaded **mod);
 struct kmod_loaded *kmod_loaded_ref(struct kmod_loaded *mod);
@@ -82,4 +87,29 @@ enum kmod_remove {
 
 int kmod_loaded_remove_module(struct kmod_loaded *kmod,
                                struct kmod_list *entry, unsigned int flags);
+
+enum kmod_insert {
+       KMOD_INSERT_FORCE_VERMAGIC = 0x1,
+       KMOD_INSERT_FORCE_MODVERSION = 0x2,
+       KMOD_INSERT_HANDLE_DEPENDENCIES = 0x4,
+       KMOD_INSERT_IGNORE_CONFIG = 0x8,
+};
+
+/*
+ * kmod_module
+ *
+ * Operate on kernel modules
+ */
+struct kmod_module;
+int kmod_module_new_from_name(struct kmod_ctx *ctx, const char *name,
+                                               struct kmod_module **mod);
+int kmod_module_new_from_path(struct kmod_ctx *ctx, const char *path,
+                                               struct kmod_module **mod);
+
+struct kmod_module *kmod_module_ref(struct kmod_module *mod);
+struct kmod_module *kmod_module_unref(struct kmod_module *mod);
+
+int kmod_module_remove_module(struct kmod_module *mod, unsigned int flags);
+int kmod_module_insert_module(struct kmod_module *mod, unsigned int flags);
+
 #endif
index b22312d84d59ddb3c08ead0cda73829ee6aa8043..8972dd94d2d935e94baba208c28bbcc42722a6e1 100644 (file)
@@ -16,6 +16,14 @@ global:
        kmod_loaded_get_list;
        kmod_loaded_get_module_info;
        kmod_loaded_remove_module;
+
+       kmod_module_new_from_name;
+       kmod_module_new_from_path;
+       kmod_module_ref;
+       kmod_module_unref;
+       kmod_module_remove_module;
+       kmod_module_insert_module;
+
 local:
         *;
 };
index 4c8f543254337b445f2380e307be9c46fbcf842e..76fdedb6d53087f141401d268fd7b9bef59fa48a 100644 (file)
@@ -49,6 +49,8 @@
         ((char *)(member_ptr) - offsetof(containing_type, member))     \
         - check_types_match(*(member_ptr), ((containing_type *)0)->member))
 
+/* Attributes */
+
 #define __must_check __attribute__((warn_unused_result))
 #define __printf_format(a,b) __attribute__((format (printf, a, b)))
 #if !defined(__always_inline)