From db5a94788a783a716de6c79e23f2e45093aca398 Mon Sep 17 00:00:00 2001 From: Dexter Morgan Date: Thu, 2 Jun 2011 20:49:50 +0000 Subject: Branch for updates --- modalias.c | 148 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 modalias.c (limited to 'modalias.c') diff --git a/modalias.c b/modalias.c new file mode 100644 index 0000000..86494c6 --- /dev/null +++ b/modalias.c @@ -0,0 +1,148 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "common.h" + +static char *aliasdefault = NULL; + +static void free_aliases(struct module_alias *aliases) { + if (aliases == NULL) + return; + while (aliases->next) { + struct module_alias *next; + next = aliases->next; + free(aliases->module); + free(aliases); + aliases = next; + } + free(aliases); +} + +static void free_options(struct module_options *modoptions) { + if (modoptions == NULL) + return; + while (modoptions->next) { + struct module_options *next; + next = modoptions->next; + free(modoptions->modulename); + free(modoptions->options); + free(modoptions); + modoptions = next; + } + free(modoptions); +} + +static void free_commands(struct module_command *commands) { + if (commands == NULL) + return; + while (commands->next) { + struct module_command *next; + next = commands->next; + free(commands->modulename); + free(commands->command); + free(commands); + commands = next; + } + free(commands); +} + +static void free_blacklist(struct module_blacklist *blacklist) { + if (blacklist == NULL) + return; + while (blacklist->next) { + struct module_blacklist *next; + next = blacklist->next; + free(blacklist->modulename); + free(blacklist); + blacklist = next; + } + free(blacklist); +} + +static void set_default_alias_file(void) { + struct utsname rel_buf; + if (!aliasdefault) { + char *dirname; + char *fallback_aliases = table_name_to_file("fallback-modules.alias"); + char *aliasfilename; + struct stat st_alias, st_fallback; + + uname(&rel_buf); + asprintf(&dirname, "%s/%s", MODULE_DIR, rel_buf.release); + asprintf(&aliasfilename, "%s/modules.alias", dirname); + free(dirname); + + /* fallback on ldetect-lst's modules.alias and prefer it if more recent */ + if (stat(aliasfilename, &st_alias) || + (!stat(fallback_aliases, &st_fallback) && st_fallback.st_mtime > st_alias.st_mtime)) { + free(aliasfilename); + aliasdefault = fallback_aliases; + } else { + aliasdefault = aliasfilename; + } + } +} + +char *modalias_resolve_module(const char *modalias) { + struct module_command *commands = NULL; + struct module_options *modoptions = NULL; + struct module_alias *aliases = NULL; + struct module_blacklist *blacklist = NULL; + const char *config = NULL; + + if (!aliasdefault) + set_default_alias_file(); + + /* Returns the resolved alias, options */ + read_toplevel_config(config, modalias, 0, + 0, &modoptions, &commands, &aliases, &blacklist); + + if (!aliases) { + /* We only use canned aliases as last resort. */ + char *dkms_file = table_name_to_file("dkms-modules.alias"); + char *alias_filelist[] = { + "/lib/module-init-tools/ldetect-lst-modules.alias", + aliasdefault, + dkms_file, + NULL, + }; + char **alias_file = alias_filelist; + while (!aliases && *alias_file) { + read_config(*alias_file, modalias, 0, + 0, &modoptions, &commands, + &aliases, &blacklist); + aliases = apply_blacklist(aliases, blacklist); + alias_file++; + } + free(dkms_file); + } + free_blacklist(blacklist); + free_commands(commands); + free_options(modoptions); + if (aliases) { + char *result; + // take the last one because we find eg: generic/ata_generic/sata_sil + struct module_alias *it = aliases; + while (it->next) + it = it->next; + + result = strdup(it->module); + free_aliases(aliases); + return result; + } + + return NULL; +} + +void modalias_cleanup(void) { + ifree(aliasdefault); +} -- cgit v1.2.1