diff options
Diffstat (limited to 'libkmod/libkmod-config.c')
-rw-r--r-- | libkmod/libkmod-config.c | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/libkmod/libkmod-config.c b/libkmod/libkmod-config.c index e83621b..a571b6b 100644 --- a/libkmod/libkmod-config.c +++ b/libkmod/libkmod-config.c @@ -58,6 +58,12 @@ struct kmod_softdep { unsigned int n_post; }; +struct kmod_weakdep { + char *name; + const char **weak; + unsigned int n_weak; +}; + const char *kmod_blacklist_get_modname(const struct kmod_list *l) { return l->data; @@ -110,6 +116,16 @@ const char * const *kmod_softdep_get_post(const struct kmod_list *l, unsigned in return dep->post; } +const char *kmod_weakdep_get_name(const struct kmod_list *l) { + const struct kmod_weakdep *dep = l->data; + return dep->name; +} + +const char * const *kmod_weakdep_get_weak(const struct kmod_list *l, unsigned int *count) { + const struct kmod_weakdep *dep = l->data; + *count = dep->n_weak; + return dep->weak; +} static int kmod_config_add_command(struct kmod_config *config, const char *modname, const char *command, @@ -392,6 +408,112 @@ static int kmod_config_add_softdep(struct kmod_config *config, return 0; } +static int kmod_config_add_weakdep(struct kmod_config *config, + const char *modname, + const char *line) +{ + struct kmod_list *list; + struct kmod_weakdep *dep; + const char *s, *p; + char *itr; + unsigned int n_weak = 0; + size_t modnamelen = strlen(modname) + 1; + size_t buflen = 0; + bool was_space = false; + + DBG(config->ctx, "modname=%s\n", modname); + + /* analyze and count */ + for (p = s = line; ; s++) { + size_t plen; + + if (*s != '\0') { + if (!isspace(*s)) { + was_space = false; + continue; + } + + if (was_space) { + p = s + 1; + continue; + } + was_space = true; + + if (p >= s) + continue; + } + plen = s - p; + + if (*s != '\0' || (*s == '\0' && !was_space)) { + buflen += plen + 1; + n_weak++; + } + p = s + 1; + if (*s == '\0') + break; + } + + DBG(config->ctx, "%u weak\n", n_weak); + + dep = malloc(sizeof(struct kmod_weakdep) + modnamelen + + n_weak * sizeof(const char *) + + buflen); + if (dep == NULL) { + ERR(config->ctx, "out-of-memory modname=%s\n", modname); + return -ENOMEM; + } + dep->n_weak = n_weak; + dep->weak = (const char **)((char *)dep + sizeof(struct kmod_weakdep)); + dep->name = (char *)(dep->weak + n_weak); + + memcpy(dep->name, modname, modnamelen); + + /* copy strings */ + itr = dep->name + modnamelen; + n_weak = 0; + was_space = false; + for (p = s = line; ; s++) { + size_t plen; + + if (*s != '\0') { + if (!isspace(*s)) { + was_space = false; + continue; + } + + if (was_space) { + p = s + 1; + continue; + } + was_space = true; + + if (p >= s) + continue; + } + plen = s - p; + + if (*s != '\0' || (*s == '\0' && !was_space)) { + dep->weak[n_weak] = itr; + memcpy(itr, p, plen); + itr[plen] = '\0'; + itr += plen + 1; + n_weak++; + } + p = s + 1; + if (*s == '\0') + break; + } + + list = kmod_list_append(config->weakdeps, dep); + if (list == NULL) { + free(dep); + return -ENOMEM; + } + config->weakdeps = list; + + return 0; +} + static char *softdep_to_char(struct kmod_softdep *dep) { const size_t sz_preprefix = sizeof("pre: ") - 1; const size_t sz_postprefix = sizeof("post: ") - 1; @@ -461,6 +583,44 @@ static char *softdep_to_char(struct kmod_softdep *dep) { return s; } +static char *weakdep_to_char(struct kmod_weakdep *dep) { + size_t sz; + const char *start, *end; + char *s, *itr; + + /* + * Rely on the fact that dep->weak[] and are strv's that point to a + * contiguous buffer + */ + if (dep->n_weak > 0) { + start = dep->weak[0]; + end = dep->weak[dep->n_weak - 1] + + strlen(dep->weak[dep->n_weak - 1]); + sz = end - start; + } else + sz = 0; + + itr = s = malloc(sz); + if (s == NULL) + return NULL; + + if (sz) { + char *p; + + /* include last '\0' */ + memcpy(itr, dep->weak[0], sz + 1); + for (p = itr; p < itr + sz; p++) { + if (*p == '\0') + *p = ' '; + } + itr = p; + } + + *itr = '\0'; + + return s; +} + static void kmod_config_free_softdep(struct kmod_config *config, struct kmod_list *l) { @@ -468,6 +628,13 @@ static void kmod_config_free_softdep(struct kmod_config *config, config->softdeps = kmod_list_remove(l); } +static void kmod_config_free_weakdep(struct kmod_config *config, + struct kmod_list *l) +{ + free(l->data); + config->weakdeps = kmod_list_remove(l); +} + static void kcmdline_parse_result(struct kmod_config *config, char *modname, char *param, char *value) { @@ -703,6 +870,14 @@ static int kmod_config_parse(struct kmod_config *config, int fd, goto syntax_error; kmod_config_add_softdep(config, modname, softdeps); + } else if (streq(cmd, "weakdep")) { + char *modname = strtok_r(NULL, "\t ", &saveptr); + char *weakdeps = strtok_r(NULL, "\0", &saveptr); + + if (underscores(modname) < 0 || weakdeps == NULL) + goto syntax_error; + + kmod_config_add_weakdep(config, modname, weakdeps); } else if (streq(cmd, "include") || streq(cmd, "config")) { ERR(ctx, "%s: command %s is deprecated and not parsed anymore\n", @@ -746,6 +921,9 @@ void kmod_config_free(struct kmod_config *config) while (config->softdeps) kmod_config_free_softdep(config, config->softdeps); + while (config->weakdeps) + kmod_config_free_weakdep(config, config->weakdeps); + for (; config->paths != NULL; config->paths = kmod_list_remove(config->paths)) free(config->paths->data); @@ -889,6 +1067,7 @@ int kmod_config_new(struct kmod_ctx *ctx, struct kmod_config **p_config, size_t i; conf_files_insert_sorted(ctx, &list, kmod_get_dirname(ctx), "modules.softdep"); + conf_files_insert_sorted(ctx, &list, kmod_get_dirname(ctx), "modules.weakdep"); for (i = 0; config_paths[i] != NULL; i++) { const char *path = config_paths[i]; @@ -973,6 +1152,7 @@ enum config_type { CONFIG_TYPE_ALIAS, CONFIG_TYPE_OPTION, CONFIG_TYPE_SOFTDEP, + CONFIG_TYPE_WEAKDEP, }; struct kmod_config_iter { @@ -991,6 +1171,12 @@ static const char *softdep_get_plain_softdep(const struct kmod_list *l) return s; } +static const char *weakdep_get_plain_weakdep(const struct kmod_list *l) +{ + char *s = weakdep_to_char(l->data); + return s; +} + static struct kmod_config_iter *kmod_config_iter_new(const struct kmod_ctx* ctx, enum config_type type) { @@ -1033,6 +1219,12 @@ static struct kmod_config_iter *kmod_config_iter_new(const struct kmod_ctx* ctx, iter->get_value = softdep_get_plain_softdep; iter->intermediate = true; break; + case CONFIG_TYPE_WEAKDEP: + iter->list = config->weakdeps; + iter->get_key = kmod_weakdep_get_name; + iter->get_value = weakdep_get_plain_weakdep; + iter->intermediate = true; + break; } return iter; @@ -1164,6 +1356,26 @@ KMOD_EXPORT struct kmod_config_iter *kmod_config_get_softdeps(const struct kmod_ } /** + * kmod_config_get_weakdeps: + * @ctx: kmod library context + * + * Retrieve an iterator to deal with the weakdeps maintained inside the + * library. See kmod_config_iter_get_key(), kmod_config_iter_get_value() and + * kmod_config_iter_next(). At least one call to kmod_config_iter_next() must + * be made to initialize the iterator and check if it's valid. + * + * Returns: a new iterator over the weakdeps or NULL on failure. Free it with + * kmod_config_iter_free_iter(). + */ +KMOD_EXPORT struct kmod_config_iter *kmod_config_get_weakdeps(const struct kmod_ctx *ctx) +{ + if (ctx == NULL) + return NULL;; + + return kmod_config_iter_new(ctx, CONFIG_TYPE_WEAKDEP); +} + +/** * kmod_config_iter_get_key: * @iter: iterator over a certain configuration * |