export module's options and commands.

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.
This commit is contained in:
Gustavo Sverzut Barbieri 2011-12-10 20:47:01 -02:00
parent b6a534f72c
commit bd3f553526
7 changed files with 321 additions and 2 deletions

View 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,

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

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

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

View 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

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

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