]> git.ipfire.org Git - thirdparty/kmod.git/commitdiff
export module's options and commands.
authorGustavo Sverzut Barbieri <barbieri@profusion.mobi>
Sat, 10 Dec 2011 22:47:01 +0000 (20:47 -0200)
committerGustavo Sverzut Barbieri <barbieri@profusion.mobi>
Sun, 11 Dec 2011 22:58:21 +0000 (20:58 -0200)
This will be required to implement modprobe later. The implementation
follows "man modprobe.conf" and allows options to be specified for
alias as well, thus the need for kmod_resolve_alias_options().

Example mod-a.conf:

    options mod-a a=1 b=2
    options mod-a c=3
    alias mymod-a mod-a
    options mymod-a d=4

Results in:
    options mod-a a=1 b=2 c=3
    options mymod-a a=1 b=2 c=3 d=4

Install commands are being concatenated with ";", but manpage is not
clean about this behavior.

libkmod/libkmod-config.c
libkmod/libkmod-module.c
libkmod/libkmod-private.h
libkmod/libkmod.c
libkmod/libkmod.h
libkmod/libkmod.sym
test/test-lookup.c

index 429f58af611584c3eec6050f80269f01b64ad17b..dd3a036b77fcd2cd09c4a2fea014f27ae7510237 100644 (file)
@@ -63,6 +63,26 @@ const char *kmod_alias_get_modname(const struct kmod_list *l) {
        return alias->modname;
 }
 
+const char *kmod_option_get_options(const struct kmod_list *l) {
+       const struct kmod_options *alias = l->data;
+       return alias->options;
+}
+
+const char *kmod_option_get_modname(const struct kmod_list *l) {
+       const struct kmod_options *alias = l->data;
+       return alias->modname;
+}
+
+const char *kmod_command_get_command(const struct kmod_list *l) {
+       const struct kmod_command *alias = l->data;
+       return alias->command;
+}
+
+const char *kmod_command_get_modname(const struct kmod_list *l) {
+       const struct kmod_command *alias = l->data;
+       return alias->modname;
+}
+
 static int kmod_config_add_command(struct kmod_config *config,
                                                const char *modname,
                                                const char *command,
index b10d41208419ad66504b3bb2dba1a4883ea4d6d2..738c3f3f6ddb230473330d4ac77a88ff63730dcf 100644 (file)
@@ -46,10 +46,16 @@ struct kmod_module {
        struct kmod_ctx *ctx;
        char *path;
        struct kmod_list *dep;
-       int refcount;
+       char *options;
+       char *install_commands;
+       char *remove_commands;
        int n_dep;
+       int refcount;
        struct {
                bool dep : 1;
+               bool options : 1;
+               bool install_commands : 1;
+               bool remove_commands : 1;
        } init;
        char name[];
 };
@@ -285,6 +291,9 @@ KMOD_EXPORT struct kmod_module *kmod_module_unref(struct kmod_module *mod)
 
        kmod_module_unref_list(mod->dep);
        kmod_unref(mod->ctx);
+       free(mod->options);
+       free(mod->install_commands);
+       free(mod->remove_commands);
        free(mod->path);
        free(mod);
        return NULL;
@@ -819,3 +828,156 @@ KMOD_EXPORT void kmod_module_section_free_list(struct kmod_list *list)
                list = kmod_list_remove(list);
        }
 }
+
+KMOD_EXPORT const char *kmod_module_get_options(const struct kmod_module *mod)
+{
+       if (mod == NULL)
+               return NULL;
+
+       if (!mod->init.options) {
+               /* lazy init */
+               struct kmod_module *m = (struct kmod_module *)mod;
+               const struct kmod_list *l, *ctx_options;
+               char *opts = NULL;
+               size_t optslen = 0;
+               ctx_options = kmod_get_options(mod->ctx);
+               kmod_list_foreach(l, ctx_options) {
+                       const char *modname = kmod_option_get_modname(l);
+                       const char *str;
+                       size_t len;
+                       void *tmp;
+
+                       if (strcmp(modname, mod->name) != 0)
+                               continue;
+
+                       str = kmod_option_get_options(l);
+                       len = strlen(str);
+                       if (len < 1)
+                               continue;
+
+                       tmp = realloc(opts, optslen + len + 2);
+                       if (tmp == NULL) {
+                               free(opts);
+                               goto failed;
+                       }
+                       opts = tmp;
+                       if (optslen > 0) {
+                               opts[optslen] = ' ';
+                               optslen++;
+                       }
+                       memcpy(opts + optslen, str, len);
+                       optslen += len;
+                       opts[optslen] = '\0';
+               }
+               m->init.options = true;
+               m->options = opts;
+       }
+
+       return mod->options;
+
+failed:
+       ERR(mod->ctx, "out of memory\n");
+       return NULL;
+}
+
+KMOD_EXPORT const char *kmod_module_get_install_commands(const struct kmod_module *mod)
+{
+       if (mod == NULL)
+               return NULL;
+
+       if (!mod->init.install_commands) {
+               /* lazy init */
+               struct kmod_module *m = (struct kmod_module *)mod;
+               const struct kmod_list *l, *ctx_install_commands;
+               char *cmds = NULL;
+               size_t cmdslen = 0;
+               ctx_install_commands = kmod_get_install_commands(mod->ctx);
+               kmod_list_foreach(l, ctx_install_commands) {
+                       const char *modname = kmod_command_get_modname(l);
+                       const char *str;
+                       size_t len;
+                       void *tmp;
+
+                       if (strcmp(modname, mod->name) != 0)
+                               continue;
+
+                       str = kmod_command_get_command(l);
+                       len = strlen(str);
+                       if (len < 1)
+                               continue;
+
+                       tmp = realloc(cmds, cmdslen + len + 2);
+                       if (tmp == NULL) {
+                               free(cmds);
+                               goto failed;
+                       }
+                       cmds = tmp;
+                       if (cmdslen > 0) {
+                               cmds[cmdslen] = ';';
+                               cmdslen++;
+                       }
+                       memcpy(cmds + cmdslen, str, len);
+                       cmdslen += len;
+                       cmds[cmdslen] = '\0';
+               }
+               m->init.install_commands = true;
+               m->install_commands = cmds;
+       }
+
+       return mod->install_commands;
+
+failed:
+       ERR(mod->ctx, "out of memory\n");
+       return NULL;
+}
+
+KMOD_EXPORT const char *kmod_module_get_remove_commands(const struct kmod_module *mod)
+{
+       if (mod == NULL)
+               return NULL;
+
+       if (!mod->init.remove_commands) {
+               /* lazy init */
+               struct kmod_module *m = (struct kmod_module *)mod;
+               const struct kmod_list *l, *ctx_remove_commands;
+               char *cmds = NULL;
+               size_t cmdslen = 0;
+               ctx_remove_commands = kmod_get_remove_commands(mod->ctx);
+               kmod_list_foreach(l, ctx_remove_commands) {
+                       const char *modname = kmod_command_get_modname(l);
+                       const char *str;
+                       size_t len;
+                       void *tmp;
+
+                       if (strcmp(modname, mod->name) != 0)
+                               continue;
+
+                       str = kmod_command_get_command(l);
+                       len = strlen(str);
+                       if (len < 1)
+                               continue;
+
+                       tmp = realloc(cmds, cmdslen + len + 2);
+                       if (tmp == NULL) {
+                               free(cmds);
+                               goto failed;
+                       }
+                       cmds = tmp;
+                       if (cmdslen > 0) {
+                               cmds[cmdslen] = ';';
+                               cmdslen++;
+                       }
+                       memcpy(cmds + cmdslen, str, len);
+                       cmdslen += len;
+                       cmds[cmdslen] = '\0';
+               }
+               m->init.remove_commands = true;
+               m->remove_commands = cmds;
+       }
+
+       return mod->remove_commands;
+
+failed:
+       ERR(mod->ctx, "out of memory\n");
+       return NULL;
+}
index ce81ae0202c37caac66921b4ba13a99640e80ea4..eb98ddc2f62b872d74f142d08b6ca13ade526cc6 100644 (file)
@@ -78,6 +78,10 @@ struct kmod_module *kmod_pool_get_module(struct kmod_ctx *ctx, const char *name)
 void kmod_pool_add_module(struct kmod_ctx *ctx, struct kmod_module *mod) __attribute__((nonnull(1,2)));
 void kmod_pool_del_module(struct kmod_ctx *ctx, struct kmod_module *mod) __attribute__((nonnull(1,2)));
 
+const struct kmod_list *kmod_get_options(const struct kmod_ctx *ctx) __must_check __attribute__((nonnull(1)));
+const struct kmod_list *kmod_get_install_commands(const struct kmod_ctx *ctx) __must_check __attribute__((nonnull(1)));
+const struct kmod_list *kmod_get_remove_commands(const struct kmod_ctx *ctx) __must_check __attribute__((nonnull(1)));
+
 
 /* libkmod-config.c */
 struct kmod_config {
@@ -92,6 +96,11 @@ int kmod_config_new(struct kmod_ctx *ctx, struct kmod_config **config) __attribu
 void kmod_config_free(struct kmod_config *config) __attribute__((nonnull(1)));
 const char *kmod_alias_get_name(const struct kmod_list *l) __attribute__((nonnull(1)));
 const char *kmod_alias_get_modname(const struct kmod_list *l) __attribute__((nonnull(1)));
+const char *kmod_option_get_options(const struct kmod_list *l) __attribute__((nonnull(1)));
+const char *kmod_option_get_modname(const struct kmod_list *l) __attribute__((nonnull(1)));
+const char *kmod_command_get_command(const struct kmod_list *l) __attribute__((nonnull(1)));
+const char *kmod_command_get_modname(const struct kmod_list *l) __attribute__((nonnull(1)));
+
 
 /* libkmod-module.c */
 int kmod_module_parse_depline(struct kmod_module *mod, char *line) __attribute__((nonnull(1, 2)));
index b1f4b714fb601fc4861c6c5fadd23b43bfe4147d..59ed81b74c465324b578ff05c87bf119fd26610d 100644 (file)
@@ -622,3 +622,102 @@ KMOD_EXPORT void kmod_unload_resources(struct kmod_ctx *ctx)
                }
        }
 }
+
+KMOD_EXPORT int kmod_resolve_alias_options(struct kmod_ctx *ctx, const char *alias, char **options)
+{
+       struct kmod_list *modules = NULL, *l;
+       char *opts = NULL;
+       size_t optslen = 0;
+       int err;
+
+       if (ctx == NULL || options == NULL)
+               return -ENOENT;
+
+       err = kmod_module_new_from_lookup(ctx, alias, &modules);
+       if (err >= 0) {
+               kmod_list_foreach(l, modules) {
+                       const char *str = kmod_module_get_options(l->data);
+                       size_t len;
+                       void *tmp;
+
+                       if (str == NULL)
+                               continue;
+                       len = strlen(str);
+
+                       tmp = realloc(opts, optslen + len + 2);
+                       if (tmp == NULL)
+                               goto failed;
+                       opts = tmp;
+                       if (optslen > 0) {
+                               opts[optslen] = ' ';
+                               optslen++;
+                       }
+                       memcpy(opts + optslen, str, len);
+                       optslen += len;
+                       opts[optslen] = '\0';
+               }
+       }
+
+       kmod_list_foreach(l, ctx->config->options) {
+               const struct kmod_list *ml;
+               const char *modname = kmod_option_get_modname(l);
+               const char *str;
+               bool already_done = false;
+               size_t len;
+               void *tmp;
+
+               if (fnmatch(modname, alias, 0) != 0)
+                       continue;
+
+               kmod_list_foreach(ml, modules) {
+                       const char *mln = kmod_module_get_name(ml->data);
+                       if (fnmatch(modname, mln, 0) == 0) {
+                               already_done = true;
+                               break;
+                       }
+               }
+               if (already_done)
+                       continue;
+
+               str = kmod_option_get_options(l);
+               len = strlen(str);
+               tmp = realloc(opts, optslen + len + 2);
+               if (tmp == NULL)
+                       goto failed;
+               opts = tmp;
+               if (optslen > 0) {
+                       opts[optslen] = ' ';
+                       optslen++;
+               }
+               memcpy(opts + optslen, str, len);
+               optslen += len;
+               opts[optslen] = '\0';
+       }
+
+       DBG(ctx, "alias=%s  options='%s'\n", alias, opts);
+       kmod_module_unref_list(modules);
+       *options = opts;
+       return 0;
+
+failed:
+       kmod_module_unref_list(modules);
+       free(opts);
+       ERR(ctx, "out of memory\n");
+       *options = NULL;
+       return -ENOMEM;
+}
+
+const struct kmod_list *kmod_get_options(const struct kmod_ctx *ctx)
+{
+       return ctx->config->options;
+}
+
+const struct kmod_list *kmod_get_install_commands(const struct kmod_ctx *ctx)
+{
+       return ctx->config->install_commands;
+}
+
+const struct kmod_list *kmod_get_remove_commands(const struct kmod_ctx *ctx)
+{
+       return ctx->config->remove_commands;
+}
index 4bff2a31fbc20e2d9e21ff1fc2fd7eb95a7a2475..a7fc77646434a611d9755cd3d2108cbe9bb9d3a8 100644 (file)
@@ -127,6 +127,12 @@ void kmod_module_section_free_list(struct kmod_list *list);
 
 long kmod_module_get_size(const struct kmod_module *mod);
 
+const char *kmod_module_get_options(const struct kmod_module *mod);
+const char *kmod_module_get_install_commands(const struct kmod_module *mod);
+const char *kmod_module_get_remove_commands(const struct kmod_module *mod);
+
+int kmod_resolve_alias_options(struct kmod_ctx *ctx, const char *alias, char **options);
+
 #ifdef __cplusplus
 } /* extern "C" */
 #endif
index 0487ff8ee86d87d72d13689c5986854d7057b908..f383331a748e73274ca074f7a6bb107e2bd6b51b 100644 (file)
@@ -41,6 +41,11 @@ global:
        kmod_module_section_get_address;
        kmod_module_get_holders;
        kmod_module_get_size;
+
+        kmod_module_get_options;
+        kmod_module_get_install_commands;
+        kmod_module_get_remove_commands;
+        kmod_resolve_alias_options;
 local:
         *;
 };
index 4d6a00d1217be32ebf5079a9dba06d9206816622..9f3bebcc90e15894b678378535cc3c939ae511fb 100644 (file)
@@ -33,8 +33,9 @@ int main(int argc, char *argv[])
        const char *alias = NULL;
        struct kmod_ctx *ctx;
        struct kmod_list *list = NULL, *l;
+       char *options;
        int load_resources = 0;
-       int i, err;
+       int err;
 
        printf("libkmod version %s\n", VERSION);
 
@@ -93,10 +94,27 @@ int main(int argc, char *argv[])
 
        kmod_list_foreach(l, list) {
                struct kmod_module *mod = kmod_module_get_module(l);
+               const char *str;
+
                printf("\t%s\n", kmod_module_get_name(mod));
+               str = kmod_module_get_options(mod);
+               if (str)
+                       printf("\t\toptions: '%s'\n", str);
+               str = kmod_module_get_install_commands(mod);
+               if (str)
+                       printf("\t\tinstall commands: '%s'\n", str);
+               str = kmod_module_get_remove_commands(mod);
+               if (str)
+                       printf("\t\tremove commands: '%s'\n", str);
                kmod_module_unref(mod);
        }
 
+       err = kmod_resolve_alias_options(ctx, alias, &options);
+       if (err == 0) {
+               printf("Alias options: '%s'\n", options);
+               free(options);
+       }
+
        kmod_module_unref_list(list);
        kmod_unref(ctx);