From cb8d4d3e999b1213549fc41618e86bd4ac2f4814 Mon Sep 17 00:00:00 2001 From: Gustavo Sverzut Barbieri Date: Sun, 11 Dec 2011 20:37:01 -0200 Subject: [PATCH] API-BREAK: kmod_new() takes a second parameter for configuration directory. This is required by modprobe and also to help doing unit tests in future. --- libkmod/libkmod-config.c | 52 ++++++++++++++++++++++++++------------------ libkmod/libkmod-private.h | 2 +- libkmod/libkmod.c | 21 ++++++++++++++++-- libkmod/libkmod.h | 2 +- test/test-blacklist.c | 2 +- test/test-get-dependencies.c | 2 +- test/test-init.c | 2 +- test/test-insmod.c | 2 +- test/test-loaded.c | 2 +- test/test-lookup.c | 2 +- test/test-mod-double-ref.c | 2 +- test/test-path-from-name.c | 2 +- test/test-rmmod.c | 2 +- test/test-rmmod2.c | 2 +- tools/kmod-insmod.c | 2 +- tools/kmod-lsmod.c | 2 +- tools/kmod-modprobe.c | 24 +++++++++++++++----- tools/kmod-rmmod.c | 2 +- 18 files changed, 83 insertions(+), 44 deletions(-) diff --git a/libkmod/libkmod-config.c b/libkmod/libkmod-config.c index dd3a036..0e4f92c 100644 --- a/libkmod/libkmod-config.c +++ b/libkmod/libkmod-config.c @@ -32,12 +32,6 @@ #include "libkmod.h" #include "libkmod-private.h" -static const char *config_files[] = { - "/run/modprobe.d", - "/etc/modprobe.d", - "/lib/modprobe.d", -}; - struct kmod_alias { char *name; char modname[]; @@ -458,7 +452,7 @@ fail_read: return NULL; } -int kmod_config_new(struct kmod_ctx *ctx, struct kmod_config **p_config) +int kmod_config_new(struct kmod_ctx *ctx, struct kmod_config **p_config, const char * const *config_paths) { struct kmod_config *config; size_t i; @@ -469,33 +463,49 @@ int kmod_config_new(struct kmod_ctx *ctx, struct kmod_config **p_config) config->ctx = ctx; - for (i = 0; i < ARRAY_SIZE(config_files); i++) { + for (i = 0; config_paths[i] != NULL; i++) { + const char *path = config_paths[i]; struct kmod_list *list = NULL; + struct stat st; DIR *d; - int fd; - d = conf_files_list(ctx, &list, config_files[i]); + if (stat(path, &st) != 0) { + DBG(ctx, "could not load '%s': %s\n", + path, strerror(errno)); + continue; + } + + if (S_ISREG(st.st_mode)) { + int fd = open(path, O_RDONLY); + DBG(ctx, "parsing file '%s': %d\n", path, fd); + if (fd >= 0) + kmod_config_parse(config, fd, path); + continue; + } else if (!S_ISDIR(st.st_mode)) { + ERR(ctx, "unsupported file mode %s: %#x\n", + path, st.st_mode); + continue; + } + + d = conf_files_list(ctx, &list, path); /* there's no entry */ if (list == NULL) continue; - - /* there's only one entry, and it's a file */ if (d == NULL) { - DBG(ctx, "parsing file '%s'\n", config_files[i]); - list = kmod_list_remove(list); - fd = open(config_files[i], O_RDONLY); - if (fd >= 0) - kmod_config_parse(config, fd, config_files[i]); - + ERR(ctx, "returned list but no directory?\n"); + while (list) { + free(list->data); + kmod_list_remove(list); + } continue; } /* treat all the entries in that dir */ for (; list != NULL; list = kmod_list_remove(list)) { - DBG(ctx, "parsing file '%s/%s'\n", config_files[i], - (char *) list->data); - fd = openat(dirfd(d), list->data, O_RDONLY); + int fd = openat(dirfd(d), list->data, O_RDONLY); + DBG(ctx, "parsing file '%s/%s': %d\n", path, + (const char *) list->data, fd); if (fd >= 0) kmod_config_parse(config, fd, list->data); diff --git a/libkmod/libkmod-private.h b/libkmod/libkmod-private.h index ce82964..3e21986 100644 --- a/libkmod/libkmod-private.h +++ b/libkmod/libkmod-private.h @@ -93,7 +93,7 @@ struct kmod_config { struct kmod_list *remove_commands; struct kmod_list *install_commands; }; -int kmod_config_new(struct kmod_ctx *ctx, struct kmod_config **config) __attribute__((nonnull(1))); +int kmod_config_new(struct kmod_ctx *ctx, struct kmod_config **config, const char * const *config_paths) __attribute__((nonnull(1, 2,3))); 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))); diff --git a/libkmod/libkmod.c b/libkmod/libkmod.c index a23bbbd..14c7a2c 100644 --- a/libkmod/libkmod.c +++ b/libkmod/libkmod.c @@ -57,6 +57,13 @@ static const char* index_files[] = { [KMOD_INDEX_SYMBOL] = "modules.symbols", }; +static const char *default_config_paths[] = { + "/run/modprobe.d", + "/etc/modprobe.d", + "/lib/modprobe.d", + NULL +}; + /** * kmod_ctx: * @@ -179,9 +186,17 @@ static char *get_kernel_release(const char *dirname) * The initial refcount is 1, and needs to be decremented to * release the resources of the kmod library context. * + * @dirname: what to consider as linux module's directory, if NULL + * defaults to /lib/modules/`uname -r` + * @config_paths: ordered array of paths (directories or files) where + * to load user-defined configuration parameters such as + * alias, blacklists, commands (install, remove). If + * NULL defaults to /run/modprobe.d, /etc/modprobe.d and + * /lib/modprobe.d. This array must be null terminated. + * * Returns: a new kmod library context */ -KMOD_EXPORT struct kmod_ctx *kmod_new(const char *dirname) +KMOD_EXPORT struct kmod_ctx *kmod_new(const char *dirname, const char * const *config_paths) { const char *env; struct kmod_ctx *ctx; @@ -203,7 +218,9 @@ KMOD_EXPORT struct kmod_ctx *kmod_new(const char *dirname) if (env != NULL) kmod_set_log_priority(ctx, log_priority(env)); - err = kmod_config_new(ctx, &ctx->config); + if (config_paths == NULL) + config_paths = default_config_paths; + err = kmod_config_new(ctx, &ctx->config, config_paths); if (err < 0) { ERR(ctx, "could not create config\n"); goto fail; diff --git a/libkmod/libkmod.h b/libkmod/libkmod.h index 130c703..3a13b9f 100644 --- a/libkmod/libkmod.h +++ b/libkmod/libkmod.h @@ -35,7 +35,7 @@ extern "C" { * environment, user variables, allows custom logging */ struct kmod_ctx; -struct kmod_ctx *kmod_new(const char *dirname); +struct kmod_ctx *kmod_new(const char *dirname, const char * const *config_dirs); struct kmod_ctx *kmod_ref(struct kmod_ctx *ctx); struct kmod_ctx *kmod_unref(struct kmod_ctx *ctx); void kmod_set_log_fn(struct kmod_ctx *ctx, diff --git a/test/test-blacklist.c b/test/test-blacklist.c index 515bfb8..a53c902 100644 --- a/test/test-blacklist.c +++ b/test/test-blacklist.c @@ -24,7 +24,7 @@ int main(int argc, char *argv[]) alias = argv[1]; - ctx = kmod_new(NULL); + ctx = kmod_new(NULL, NULL); if (ctx == NULL) exit(EXIT_FAILURE); diff --git a/test/test-get-dependencies.c b/test/test-get-dependencies.c index 266c5d4..3a7bbf2 100644 --- a/test/test-get-dependencies.c +++ b/test/test-get-dependencies.c @@ -25,7 +25,7 @@ int main(int argc, char *argv[]) name = argv[1]; - ctx = kmod_new(NULL); + ctx = kmod_new(NULL, NULL); if (ctx == NULL) exit(EXIT_FAILURE); diff --git a/test/test-init.c b/test/test-init.c index 18317aa..081a47c 100644 --- a/test/test-init.c +++ b/test/test-init.c @@ -10,7 +10,7 @@ int main(int argc, char *argv[]) { struct kmod_ctx *ctx; - ctx = kmod_new(NULL); + ctx = kmod_new(NULL, NULL); if (ctx == NULL) exit(EXIT_FAILURE); diff --git a/test/test-insmod.c b/test/test-insmod.c index 6deaf77..7198df0 100644 --- a/test/test-insmod.c +++ b/test/test-insmod.c @@ -22,7 +22,7 @@ int main(int argc, char *argv[]) path = argv[1]; - ctx = kmod_new(NULL); + ctx = kmod_new(NULL, NULL); if (ctx == NULL) exit(EXIT_FAILURE); diff --git a/test/test-loaded.c b/test/test-loaded.c index dc45695..5f3dc58 100644 --- a/test/test-loaded.c +++ b/test/test-loaded.c @@ -14,7 +14,7 @@ int main(int argc, char *argv[]) struct kmod_list *list, *itr; int err; - ctx = kmod_new(NULL); + ctx = kmod_new(NULL, NULL); if (ctx == NULL) exit(EXIT_FAILURE); diff --git a/test/test-lookup.c b/test/test-lookup.c index 9f3bebc..34d255d 100644 --- a/test/test-lookup.c +++ b/test/test-lookup.c @@ -67,7 +67,7 @@ int main(int argc, char *argv[]) alias = argv[optind]; - ctx = kmod_new(NULL); + ctx = kmod_new(NULL, NULL); if (ctx == NULL) { kmod_unref(ctx); exit(EXIT_FAILURE); diff --git a/test/test-mod-double-ref.c b/test/test-mod-double-ref.c index 710957f..872fc7e 100644 --- a/test/test-mod-double-ref.c +++ b/test/test-mod-double-ref.c @@ -22,7 +22,7 @@ int main(int argc, char *argv[]) modname = argv[1]; - ctx = kmod_new(NULL); + ctx = kmod_new(NULL, NULL); if (ctx == NULL) exit(EXIT_FAILURE); diff --git a/test/test-path-from-name.c b/test/test-path-from-name.c index c5f8cca..3f3d568 100644 --- a/test/test-path-from-name.c +++ b/test/test-path-from-name.c @@ -22,7 +22,7 @@ int main(int argc, char *argv[]) modname = argv[1]; - ctx = kmod_new(NULL); + ctx = kmod_new(NULL, NULL); if (ctx == NULL) exit(EXIT_FAILURE); diff --git a/test/test-rmmod.c b/test/test-rmmod.c index e1b9fb4..c57a0a7 100644 --- a/test/test-rmmod.c +++ b/test/test-rmmod.c @@ -18,7 +18,7 @@ int main(int argc, char *argv[]) if (argc == 2) modname = argv[1]; - ctx = kmod_new(NULL); + ctx = kmod_new(NULL, NULL); if (ctx == NULL) exit(EXIT_FAILURE); diff --git a/test/test-rmmod2.c b/test/test-rmmod2.c index 5e3fa49..7a7a0ba 100644 --- a/test/test-rmmod2.c +++ b/test/test-rmmod2.c @@ -22,7 +22,7 @@ int main(int argc, char *argv[]) modname = argv[1]; - ctx = kmod_new(NULL); + ctx = kmod_new(NULL, NULL); if (ctx == NULL) exit(EXIT_FAILURE); diff --git a/tools/kmod-insmod.c b/tools/kmod-insmod.c index 10c269a..29a6231 100644 --- a/tools/kmod-insmod.c +++ b/tools/kmod-insmod.c @@ -124,7 +124,7 @@ int main(int argc, char *argv[]) opts[optslen] = '\0'; } - ctx = kmod_new(NULL); + ctx = kmod_new(NULL, NULL); if (!ctx) { fputs("Error: kmod_new() failed!\n", stderr); free(opts); diff --git a/tools/kmod-lsmod.c b/tools/kmod-lsmod.c index 20d0757..4f75fd4 100644 --- a/tools/kmod-lsmod.c +++ b/tools/kmod-lsmod.c @@ -36,7 +36,7 @@ int main(int argc, char *argv[]) return EXIT_FAILURE; } - ctx = kmod_new(NULL); + ctx = kmod_new(NULL, NULL); if (ctx == NULL) { fputs("Error: kmod_new() failed!\n", stderr); return EXIT_FAILURE; diff --git a/tools/kmod-modprobe.c b/tools/kmod-modprobe.c index 7b78e5b..270edd3 100644 --- a/tools/kmod-modprobe.c +++ b/tools/kmod-modprobe.c @@ -947,11 +947,11 @@ int main(int argc, char **orig_argv) { struct kmod_ctx *ctx; char **args = NULL, **argv; - int nargs = 0; + const char **config_paths = NULL; + int nargs = 0, n_config_paths = 0; char dirname_buf[PATH_MAX]; const char *dirname = NULL; const char *root = NULL; - const char *config = NULL; const char *kversion = NULL; const char *list_type = NULL; int use_all = 0; @@ -1025,11 +1025,22 @@ int main(int argc, char **orig_argv) case 'n': dry_run = 1; break; - case 'C': + case 'C': { + size_t bytes = sizeof(char *) * (n_config_paths + 2); + void *tmp = realloc(config_paths, bytes); + if (!tmp) { + fputs("Error: out-of-memory\n", stderr); + goto cmdline_failed; + } + config_paths = tmp; + config_paths[n_config_paths] = optarg; + n_config_paths++; + config_paths[n_config_paths] = NULL; + env_modprobe_options_append("-C"); env_modprobe_options_append(optarg); - config = optarg; break; + } case 'd': root = optarg; break; @@ -1101,7 +1112,7 @@ int main(int argc, char **orig_argv) dirname = dirname_buf; } - ctx = kmod_new(dirname); + ctx = kmod_new(dirname, config_paths); if (!ctx) { fputs("Error: kmod_new() failed!\n", stderr); goto cmdline_failed; @@ -1140,11 +1151,12 @@ int main(int argc, char **orig_argv) if (argv != orig_argv) free(argv); - + free(config_paths); return err >= 0 ? EXIT_SUCCESS : EXIT_FAILURE; cmdline_failed: if (argv != orig_argv) free(argv); + free(config_paths); return EXIT_FAILURE; } diff --git a/tools/kmod-rmmod.c b/tools/kmod-rmmod.c index 8963448..fe0d645 100644 --- a/tools/kmod-rmmod.c +++ b/tools/kmod-rmmod.c @@ -146,7 +146,7 @@ int main(int argc, char *argv[]) return EXIT_FAILURE; } - ctx = kmod_new(NULL); + ctx = kmod_new(NULL, NULL); if (!ctx) { fputs("Error: kmod_new() failed!\n", stderr); return EXIT_FAILURE; -- 2.7.4