]> git.ipfire.org Git - thirdparty/kmod.git/commitdiff
no more kmod_loaded and kmod_loaded_module.
authorGustavo Sverzut Barbieri <barbieri@profusion.mobi>
Sun, 4 Dec 2011 16:02:30 +0000 (14:02 -0200)
committerLucas De Marchi <lucas.demarchi@profusion.mobi>
Sun, 4 Dec 2011 19:24:08 +0000 (17:24 -0200)
kmod_loaded_get_list() now returns a regular list of kmod_modules, use
kmod_module_get_module(), kmod_module_unref() and
kmod_module_unref_list() to operate on it.

libkmod/libkmod-loaded.c
libkmod/libkmod-module.c
libkmod/libkmod.h
libkmod/libkmod.sym
test/test-loaded.c
test/test-rmmod.c

index 06f7f314c59bda56d80130f85227fb50275c5811..6914e57a7719ae7e08d5924dfd29bf5156ef81b7 100644 (file)
  *
  * Information about currently loaded modules, as reported by Linux kernel
  */
-
-/**
- * kmod_loaded:
- *
- * Opaque object representing a loaded module.
- */
-struct kmod_loaded {
-       struct kmod_ctx *ctx;
-       struct kmod_list *modules;
-       int refcount;
-       bool parsed;
-};
-
-struct kmod_loaded_module {
-       char *name;
-       long size;
-       char *deps;
-       uintptr_t addr;
-       int use_count;
-};
-
-KMOD_EXPORT int kmod_loaded_new(struct kmod_ctx *ctx, struct kmod_loaded **mod)
-{
-       struct kmod_loaded *m;
-
-       m = calloc(1, sizeof(*m));
-       if (m == NULL)
-               return -ENOMEM;
-
-       m->refcount = 1;
-       m->ctx = kmod_ref(ctx);
-       *mod = m;
-       return 0;
-}
-
-KMOD_EXPORT struct kmod_loaded *kmod_loaded_ref(struct kmod_loaded *mod)
-{
-       if (mod == NULL)
-               return NULL;
-       mod->refcount++;
-       return mod;
-}
-
-static void loaded_modules_free_module(struct kmod_loaded_module *m)
-{
-       free(m->name);
-       free(m->deps);
-       free(m);
-}
-
-static void loaded_modules_free(struct kmod_loaded *mod)
-{
-       while (mod->modules != NULL) {
-               loaded_modules_free_module(mod->modules->data);
-               mod->modules = kmod_list_remove(mod->modules);
-       }
-}
-
-KMOD_EXPORT struct kmod_loaded *kmod_loaded_unref(struct kmod_loaded *mod)
-{
-       if (mod == NULL)
-               return NULL;
-
-       if (--mod->refcount > 0)
-               return mod;
-
-       DBG(mod->ctx, "kmod_loaded %p released\n", mod);
-
-       kmod_unref(mod->ctx);
-       loaded_modules_free(mod);
-       free(mod);
-       return NULL;
-}
-
-static int loaded_modules_parse(struct kmod_loaded *mod,
+KMOD_EXPORT int kmod_loaded_get_list(struct kmod_ctx *ctx,
                                                struct kmod_list **list)
 {
        struct kmod_list *l = NULL;
        FILE *fp;
        char line[4096];
 
+       if (ctx == NULL || list == NULL)
+               return -ENOENT;
+
        fp = fopen("/proc/modules", "r");
-       if (fp == NULL)
-               return -errno;
+       if (fp == NULL) {
+               int err = -errno;
+               ERR(ctx, "could not open /proc/modules: %s\n", strerror(errno));
+               return err;
+       }
 
        while (fgets(line, sizeof(line), fp)) {
-               char *tok;
-               struct kmod_loaded_module *m;
-
-               m = calloc(1, sizeof(*m));
-               if (m == NULL)
-                       goto err;
-
-               tok = strtok(line, " \t");
-               m->name = strdup(tok);
-
-               tok = strtok(NULL, " \t\n");
-               m->size = atoi(tok);
-
-               /* Null if no module unloading is supported */
-               tok = strtok(NULL, " \t\n");
-               if (tok == NULL)
-                       goto done;
-
-               m->use_count = atoi(tok);
-               tok = strtok(NULL, "\n");
-               if (tok == NULL)
-                       goto done;
-
-               /* Strip trailing comma */
-               if (strchr(tok, ',')) {
-                       char *end;
-                       tok = strtok(tok, " \t");
-                       end = &tok[strlen(tok) - 1];
-                       if (*end == ',')
-                               *end = '\0';
-                       m->deps = strdup(tok);
-                       tok = &end[2];
-               } else if (tok[0] == '-' && tok[1] == '\0')
-                       goto done;
-               else if (tok[0] == '-' && isspace(tok[1]))
-                       tok = &tok[3];
-
-               tok = strtok(tok, " \t\n");
-               if (tok == NULL)
-                       goto done;
-
-               tok = strtok(NULL, " \t\n");
-               if (tok == NULL)
-                       goto done;
-
-               m->addr = strtoull(tok, NULL, 16);
-
-done:
-               l = kmod_list_append(l, m);
+               struct kmod_module *m;
+               struct kmod_list *node;
+               int err;
+               char *saveptr, *name = strtok_r(line, " \t", &saveptr);
+
+               err = kmod_module_new_from_name(ctx, name, &m);
+               if (err < 0) {
+                       ERR(ctx, "could not get module from name '%s': %s\n",
+                               name, strerror(-err));
+                       continue;
+               }
+
+               node = kmod_list_append(l, m);
+               if (node)
+                       l = node;
+               else {
+                       ERR(ctx, "out of memory\n");
+                       kmod_module_unref(m);
+               }
        }
 
        fclose(fp);
-       mod->parsed = 1;
        *list = l;
 
-       return 0;
-
-err:
-       fclose(fp);
-       mod->modules = l;
-       loaded_modules_free(mod);
-       mod->modules = NULL;
-       return -ENOMEM;
-}
-
-KMOD_EXPORT int kmod_loaded_get_list(struct kmod_loaded *mod,
-                                               struct kmod_list **list)
-{
-       if (mod == NULL)
-               return -ENOENT;
-
-       if (!mod->parsed) {
-               int err = loaded_modules_parse(mod, &mod->modules);
-               if (err < 0)
-                       return err;
-       }
-
-       *list = mod->modules;
-
-       return 0;
-}
-
-KMOD_EXPORT int kmod_loaded_get_module_info(const struct kmod_list *entry,
-                                               const char **name,
-                                               long *size, int *use_count,
-                                               const char **deps,
-                                               uintptr_t *addr)
-{
-       const struct kmod_loaded_module *m;
-
-       if (entry == NULL)
-               return -ENOENT;
-
-       m = entry->data;
-
-       if (name)
-               *name = m->name;
-       if (size)
-               *size = m->size;
-       if (use_count)
-               *use_count = m->use_count;
-       if (addr)
-               *addr = m->addr;
-       if (deps)
-               *deps = m->deps;
-
-       return 0;
-}
-
-extern long delete_module(const char *name, unsigned int flags);
-
-KMOD_EXPORT int kmod_loaded_remove_module(struct kmod_loaded *mod,
-                                               struct kmod_list *entry,
-                                               unsigned int flags)
-{
-       struct kmod_loaded_module *m;
-       int err;
-
-       if (mod == NULL)
-               return -ENOSYS;
-
-       if (entry == NULL)
-               return -ENOENT;
-
-       m = entry->data;
-
-       /* Filter out other flags */
-       flags &= (KMOD_REMOVE_FORCE | KMOD_REMOVE_NOWAIT);
-
-       err = delete_module(m->name, flags);
-       if (err != 0) {
-               ERR(mod->ctx, "Removing '%s': %s\n", m->name,
-                                                       strerror(-err));
-               return err;
-       }
-
-       loaded_modules_free_module(m);
-       entry = kmod_list_remove(entry);
-
        return 0;
 }
index 10c8b16501588b8be4d88936f78d9bc39cfb5ce4..f18dbb07ee406978230273de85c23ffd49e5c2fd 100644 (file)
@@ -279,6 +279,54 @@ KMOD_EXPORT struct kmod_module *kmod_module_get_module(const struct kmod_list *e
        return kmod_module_ref(entry->data);
 }
 
+KMOD_EXPORT long kmod_module_get_size(const struct kmod_module *mod)
+{
+       // FIXME TODO: this should be available from /sys/module/foo
+       FILE *fp;
+       char line[4096];
+       int lineno = 0;
+       long size = -ENOENT;
+
+       if (mod == NULL)
+               return -ENOENT;
+
+       fp = fopen("/proc/modules", "r");
+       if (fp == NULL) {
+               int err = -errno;
+               ERR(mod->ctx,
+                   "could not open /proc/modules: %s\n", strerror(errno));
+               return err;
+       }
+
+       while (fgets(line, sizeof(line), fp)) {
+               char *saveptr, *endptr, *tok = strtok_r(line, " \t", &saveptr);
+               long value;
+
+               lineno++;
+               if (tok == NULL || strcmp(tok, mod->name) != 0)
+                       continue;
+
+               tok = strtok_r(NULL, " \t", &saveptr);
+               if (tok == NULL) {
+                       ERR(mod->ctx,
+                       "invalid line format at /proc/modules:%d\n", lineno);
+                       break;
+               }
+
+               value = strtol(tok, &endptr, 10);
+               if (endptr == tok || *endptr != '\0') {
+                       ERR(mod->ctx,
+                       "invalid line format at /proc/modules:%d\n", lineno);
+                       break;
+               }
+
+               size = value;
+               break;
+       }
+       fclose(fp);
+       return size;
+}
+
 KMOD_EXPORT const char *kmod_module_get_name(const struct kmod_module *mod)
 {
        // FIXME calculate name if name == NULL
index c552f2903868543662f8a50cae052c60e16a3d85..c6d27a353dd25f221e3cdec1a47cc44d3da55af3 100644 (file)
@@ -63,28 +63,13 @@ struct kmod_list *kmod_list_prev(const struct kmod_list *first_entry,
                list_entry != NULL; \
                list_entry = kmod_list_next(first_entry, list_entry))
 
-/*
- * 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);
-struct kmod_loaded *kmod_loaded_unref(struct kmod_loaded *mod);
-int kmod_loaded_get_list(struct kmod_loaded *mod, struct kmod_list **list);
-int kmod_loaded_get_module_info(const struct kmod_list *entry,
-                               const char **name, long *size, int *use_count,
-                               const char **deps, uintptr_t *addr);
+int kmod_loaded_get_list(struct kmod_ctx *ctx, struct kmod_list **list);
 
 enum kmod_remove {
        KMOD_REMOVE_FORCE = O_TRUNC,
        KMOD_REMOVE_NOWAIT = O_NONBLOCK,
 };
 
-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,
@@ -133,6 +118,7 @@ const char *kmod_module_section_get_name(const struct kmod_list *entry);
 unsigned long kmod_module_section_get_address(const struct kmod_list *entry);
 void kmod_module_section_free_list(struct kmod_list *list);
 
+long kmod_module_get_size(const struct kmod_module *mod);
 
 #ifdef __cplusplus
 } /* extern "C" */
index 07690ddd896fcd49a5dc4f1ddeb4d6f95b0ce74e..7b95749f01d6589e3132b16f6f194e76b0773ef1 100644 (file)
@@ -11,12 +11,7 @@ global:
        kmod_unref;
        kmod_list_next;
        kmod_list_prev;
-       kmod_loaded_new;
-       kmod_loaded_ref;
-       kmod_loaded_unref;
        kmod_loaded_get_list;
-       kmod_loaded_get_module_info;
-       kmod_loaded_remove_module;
 
        kmod_module_new_from_name;
        kmod_module_new_from_path;
@@ -42,6 +37,8 @@ global:
        kmod_module_section_get_address;
 
        kmod_module_get_holders;
+
+       kmod_module_get_size;
 local:
         *;
 };
index e5cfe13d47fc320a0bc0751714e84735bb21446c..c862cd9798a0cd7dbf38c9b7ca8519d9bdf67cc6 100644 (file)
@@ -11,7 +11,6 @@
 int main(int argc, char *argv[])
 {
        struct kmod_ctx *ctx;
-       struct kmod_loaded *mod;
        struct kmod_list *list, *itr;
        int err;
 
@@ -21,11 +20,7 @@ int main(int argc, char *argv[])
 
        printf("libkmod version %s\n", VERSION);
 
-       err = kmod_loaded_new(ctx, &mod);
-       if (err < 0)
-               exit(EXIT_FAILURE);
-
-       err = kmod_loaded_get_list(mod, &list);
+       err = kmod_loaded_get_list(ctx, &list);
        if (err < 0) {
                fprintf(stderr, "%s\n", strerror(-err));
                exit(EXIT_FAILURE);
@@ -34,16 +29,31 @@ int main(int argc, char *argv[])
        printf("Module                  Size  Used by\n");
 
        kmod_list_foreach(itr, list) {
-               const char *name, *deps;
-               long size;
-               int use_count;
-               kmod_loaded_get_module_info(itr, &name, &size, &use_count,
-                                                               &deps, NULL);
-               printf("%-19s %8ld  %d %s\n", name, size,
-                                       use_count, deps ? deps : "");
+               struct kmod_module *mod = kmod_module_get_module(itr);
+               const char *name = kmod_module_get_name(mod);
+               int use_count = kmod_module_get_refcnt(mod);
+               long size = kmod_module_get_size(mod);
+               struct kmod_list *holders, *hitr;
+               int first = 1;
+
+               printf("%-19s %8ld  %d ", name, size, use_count);
+               holders = kmod_module_get_holders(mod);
+               kmod_list_foreach(hitr, holders) {
+                       struct kmod_module *hm = kmod_module_get_module(hitr);
+
+                       if (!first)
+                               putchar(',');
+                       else
+                               first = 0;
+
+                       fputs(kmod_module_get_name(hm), stdout);
+                       kmod_module_unref(hm);
+               }
+               putchar('\n');
+               kmod_module_unref_list(holders);
+               kmod_module_unref(mod);
        }
-
-       kmod_loaded_unref(mod);
+       kmod_module_unref_list(list);
 
        kmod_unref(ctx);
 
index d7690b34debb3b465e7ddd82116d8afe3faec433..7a7bc5b442dbe96241d324728839a609377ecf1b 100644 (file)
@@ -12,9 +12,8 @@ int main(int argc, char *argv[])
 {
        const char *modname = NULL;
        struct kmod_ctx *ctx;
-       struct kmod_loaded *mod;
        struct kmod_list *list, *itr;
-       int err;
+       int err, count = 0;
 
        if (argc == 2)
                modname = argv[1];
@@ -25,33 +24,33 @@ int main(int argc, char *argv[])
 
        printf("libkmod version %s\n", VERSION);
 
-       err = kmod_loaded_new(ctx, &mod);
-       if (err < 0)
-               exit(EXIT_FAILURE);
-
-       err = kmod_loaded_get_list(mod, &list);
+       err = kmod_loaded_get_list(ctx, &list);
        if (err < 0) {
                fprintf(stderr, "%s\n", strerror(-err));
                exit(EXIT_FAILURE);
        }
 
+       err = 0;
        kmod_list_foreach(itr, list) {
-               const char *name;
-               int use_count;
-
-               kmod_loaded_get_module_info(itr, &name, NULL, &use_count,
-                                                               NULL, NULL);
+               struct kmod_module *mod = kmod_module_get_module(itr);
+               const char *name = kmod_module_get_name(mod);
 
                if ((modname && !strcmp(modname, name)) ||
-                                       (modname == NULL && use_count == 0)) {
+                   (modname == NULL && kmod_module_get_refcnt(mod) < 1)) {
                        printf("Trying to remove '%s'\n", name);
-                       kmod_loaded_remove_module(mod, itr, 0);
-                       break;
+                       err = kmod_module_remove_module(mod, 0);
+                       if (err == 0)
+                               count++;
+                       else {
+                               fprintf(stderr, "Error removing %s: %s\n",
+                                       name, strerror(-err));
+                       }
                }
-       }
 
-       kmod_loaded_unref(mod);
+               kmod_module_unref(mod);
+       }
+       kmod_module_unref_list(list);
        kmod_unref(ctx);
 
-       return EXIT_SUCCESS;
+       return count > 0;
 }