This is required by modprobe and also to help doing unit tests in future.
#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[];
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;
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);
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)));
[KMOD_INDEX_SYMBOL] = "modules.symbols",
};
+static const char *default_config_paths[] = {
+ "/run/modprobe.d",
+ "/etc/modprobe.d",
+ "/lib/modprobe.d",
+ NULL
+};
+
/**
* kmod_ctx:
*
* 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;
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;
* 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,
alias = argv[1];
- ctx = kmod_new(NULL);
+ ctx = kmod_new(NULL, NULL);
if (ctx == NULL)
exit(EXIT_FAILURE);
name = argv[1];
- ctx = kmod_new(NULL);
+ ctx = kmod_new(NULL, NULL);
if (ctx == NULL)
exit(EXIT_FAILURE);
{
struct kmod_ctx *ctx;
- ctx = kmod_new(NULL);
+ ctx = kmod_new(NULL, NULL);
if (ctx == NULL)
exit(EXIT_FAILURE);
path = argv[1];
- ctx = kmod_new(NULL);
+ ctx = kmod_new(NULL, NULL);
if (ctx == NULL)
exit(EXIT_FAILURE);
struct kmod_list *list, *itr;
int err;
- ctx = kmod_new(NULL);
+ ctx = kmod_new(NULL, NULL);
if (ctx == NULL)
exit(EXIT_FAILURE);
alias = argv[optind];
- ctx = kmod_new(NULL);
+ ctx = kmod_new(NULL, NULL);
if (ctx == NULL) {
kmod_unref(ctx);
exit(EXIT_FAILURE);
modname = argv[1];
- ctx = kmod_new(NULL);
+ ctx = kmod_new(NULL, NULL);
if (ctx == NULL)
exit(EXIT_FAILURE);
modname = argv[1];
- ctx = kmod_new(NULL);
+ ctx = kmod_new(NULL, NULL);
if (ctx == NULL)
exit(EXIT_FAILURE);
if (argc == 2)
modname = argv[1];
- ctx = kmod_new(NULL);
+ ctx = kmod_new(NULL, NULL);
if (ctx == NULL)
exit(EXIT_FAILURE);
modname = argv[1];
- ctx = kmod_new(NULL);
+ ctx = kmod_new(NULL, NULL);
if (ctx == NULL)
exit(EXIT_FAILURE);
opts[optslen] = '\0';
}
- ctx = kmod_new(NULL);
+ ctx = kmod_new(NULL, NULL);
if (!ctx) {
fputs("Error: kmod_new() failed!\n", stderr);
free(opts);
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;
{
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;
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;
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;
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;
}
return EXIT_FAILURE;
}
- ctx = kmod_new(NULL);
+ ctx = kmod_new(NULL, NULL);
if (!ctx) {
fputs("Error: kmod_new() failed!\n", stderr);
return EXIT_FAILURE;