diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/binfmt.c | 78 | ||||
-rw-r--r-- | src/hashmap.c | 18 | ||||
-rw-r--r-- | src/hashmap.h | 2 | ||||
-rw-r--r-- | src/modules-load.c | 65 | ||||
-rw-r--r-- | src/sysctl.c | 72 | ||||
-rw-r--r-- | src/util.c | 94 | ||||
-rw-r--r-- | src/util.h | 1 |
7 files changed, 171 insertions, 159 deletions
diff --git a/src/binfmt.c b/src/binfmt.c index 6ebd212ee1..619f6e4aa7 100644 --- a/src/binfmt.c +++ b/src/binfmt.c @@ -25,8 +25,11 @@ #include <string.h> #include <stdio.h> #include <limits.h> +#include <stdarg.h> #include "log.h" +#include "hashmap.h" +#include "strv.h" #include "util.h" static int delete_rule(const char *rule) { @@ -80,6 +83,7 @@ static int apply_file(const char *path, bool ignore_enoent) { return -errno; } + log_debug("apply: %s\n", path); while (!feof(f)) { char l[LINE_MAX], *p; int k; @@ -111,57 +115,6 @@ finish: return r; } -static int scandir_filter(const struct dirent *d) { - assert(d); - - if (ignore_file(d->d_name)) - return 0; - - if (d->d_type != DT_REG && - d->d_type != DT_LNK && - d->d_type != DT_UNKNOWN) - return 0; - - return endswith(d->d_name, ".conf"); -} - -static int apply_tree(const char *path) { - struct dirent **de = NULL; - int n, i, r = 0; - - if ((n = scandir(path, &de, scandir_filter, alphasort)) < 0) { - - if (errno == ENOENT) - return 0; - - log_error("Failed to enumerate %s files: %m", path); - return -errno; - } - - for (i = 0; i < n; i++) { - char *fn; - int k; - - k = asprintf(&fn, "%s/%s", path, de[i]->d_name); - free(de[i]); - - if (k < 0) { - log_error("Failed to allocate file name."); - - if (r == 0) - r = -ENOMEM; - continue; - } - - if ((k = apply_file(fn, true)) < 0 && r == 0) - r = k; - } - - free(de); - - return r; -} - int main(int argc, char *argv[]) { int r = 0; @@ -174,14 +127,29 @@ int main(int argc, char *argv[]) { log_parse_environment(); log_open(); - if (argc > 1) + if (argc > 1) { r = apply_file(argv[1], false); - else { + } else { + char **files, **f; + /* Flush out all rules */ write_one_line_file("/proc/sys/fs/binfmt_misc/status", "-1"); - r = apply_tree("/etc/binfmt.d"); - } + files = conf_files_list(".conf", + "/run/binfmt.d", + "/etc/binfmt.d", + "/usr/lib/binfmt.d", + NULL); + STRV_FOREACH(f, files) { + int k; + + k = apply_file(*f, true); + if (k < 0 && r == 0) + r = k; + } + + strv_free(files); + } return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } diff --git a/src/hashmap.c b/src/hashmap.c index 4b187057ec..53502576ad 100644 --- a/src/hashmap.c +++ b/src/hashmap.c @@ -592,3 +592,21 @@ Hashmap *hashmap_copy(Hashmap *h) { return copy; } + +char **hashmap_get_strv(Hashmap *h) { + char **sv; + Iterator it; + char *path; + int n; + + sv = malloc((h->n_entries+1) * sizeof(char *)); + if (sv == NULL) + return NULL; + + n = 0; + HASHMAP_FOREACH(path, h, it) + sv[n++] = path; + sv[n] = NULL; + + return sv; +} diff --git a/src/hashmap.h b/src/hashmap.h index ac5a8ae085..16ffbd3922 100644 --- a/src/hashmap.h +++ b/src/hashmap.h @@ -76,6 +76,8 @@ void *hashmap_steal_first_key(Hashmap *h); void* hashmap_first(Hashmap *h); void* hashmap_last(Hashmap *h); +char **hashmap_get_strv(Hashmap *h); + #define HASHMAP_FOREACH(e, h, i) \ for ((i) = ITERATOR_FIRST, (e) = hashmap_iterate((h), &(i), NULL); (e); (e) = hashmap_iterate((h), &(i), NULL)) diff --git a/src/modules-load.c b/src/modules-load.c index 3824b57de7..fac4511816 100644 --- a/src/modules-load.c +++ b/src/modules-load.c @@ -31,30 +31,11 @@ #include "util.h" #include "strv.h" -/* This reads all module names listed in /etc/modules-load.d/?*.conf and - * loads them into the kernel. This follows roughly Debian's way to - * handle modules, but uses a directory of fragments instead of a - * single /etc/modules file. */ - -static int scandir_filter(const struct dirent *d) { - assert(d); - - if (ignore_file(d->d_name)) - return 0; - - if (d->d_type != DT_REG && - d->d_type != DT_LNK && - d->d_type != DT_UNKNOWN) - return 0; - - return endswith(d->d_name, ".conf"); -} - int main(int argc, char *argv[]) { - struct dirent **de = NULL; - int r = EXIT_FAILURE, n, i; + int r = EXIT_FAILURE; char **arguments = NULL; unsigned n_arguments = 0, n_allocated = 0; + char **files, **fn; if (argc > 1) { log_error("This program takes no argument."); @@ -72,48 +53,33 @@ int main(int argc, char *argv[]) { n_arguments = n_allocated = 3; - if ((n = scandir("/etc/modules-load.d/", &de, scandir_filter, alphasort)) < 0) { - - if (errno == ENOENT) - r = EXIT_SUCCESS; - else - log_error("Failed to enumerate /etc/modules-load.d/ files: %m"); - + files = conf_files_list(".conf", + "/run/modules-load.d", + "/etc/modules-load.d", + "/usr/lib/modules-load.d", + NULL); + if (files == NULL) { + log_error("Failed to enumerate modules-load.d files: %m"); goto finish; } r = EXIT_SUCCESS; - for (i = 0; i < n; i++) { - int k; - char *fn; + STRV_FOREACH(fn, files) { FILE *f; - k = asprintf(&fn, "/etc/modules-load.d/%s", de[i]->d_name); - free(de[i]); - - if (k < 0) { - log_error("Failed to allocate file name."); - r = EXIT_FAILURE; - continue; - } - - f = fopen(fn, "re"); - + f = fopen(*fn, "re"); if (!f) { - if (errno == ENOENT) { - free(fn); + if (errno == ENOENT) continue; - } - log_error("Failed to open %s: %m", fn); + log_error("Failed to open %s: %m", *fn); free(fn); r = EXIT_FAILURE; continue; } - free(fn); - + log_debug("apply: %s\n", *fn); for (;;) { char line[LINE_MAX], *l, *t; @@ -157,8 +123,7 @@ int main(int argc, char *argv[]) { fclose(f); } - free(de); - + strv_free(files); finish: if (n_arguments > 3) { diff --git a/src/sysctl.c b/src/sysctl.c index 15b6da79dc..1d42e9378b 100644 --- a/src/sysctl.c +++ b/src/sysctl.c @@ -27,6 +27,7 @@ #include <limits.h> #include "log.h" +#include "strv.h" #include "util.h" #define PROC_SYS_PREFIX "/proc/sys/" @@ -77,6 +78,7 @@ static int apply_file(const char *path, bool ignore_enoent) { return -errno; } + log_debug("apply: %s\n", path); while (!feof(f)) { char l[LINE_MAX], *p, *value; int k; @@ -119,57 +121,6 @@ finish: return r; } -static int scandir_filter(const struct dirent *d) { - assert(d); - - if (ignore_file(d->d_name)) - return 0; - - if (d->d_type != DT_REG && - d->d_type != DT_LNK && - d->d_type != DT_UNKNOWN) - return 0; - - return endswith(d->d_name, ".conf"); -} - -static int apply_tree(const char *path) { - struct dirent **de = NULL; - int n, i, r = 0; - - if ((n = scandir(path, &de, scandir_filter, alphasort)) < 0) { - - if (errno == ENOENT) - return 0; - - log_error("Failed to enumerate %s files: %m", path); - return -errno; - } - - for (i = 0; i < n; i++) { - char *fn; - int k; - - k = asprintf(&fn, "%s/%s", path, de[i]->d_name); - free(de[i]); - - if (k < 0) { - log_error("Failed to allocate file name."); - - if (r == 0) - r = -ENOMEM; - continue; - } - - if ((k = apply_file(fn, true)) < 0 && r == 0) - r = k; - } - - free(de); - - return r; -} - int main(int argc, char *argv[]) { int r = 0; @@ -185,12 +136,25 @@ int main(int argc, char *argv[]) { if (argc > 1) r = apply_file(argv[1], false); else { - int k; + char **files, **f; r = apply_file("/etc/sysctl.conf", true); - if ((k = apply_tree("/etc/sysctl.d")) < 0 && r == 0) - r = k; + files = conf_files_list(".conf", + "/run/sysctl.d", + "/etc/sysctl.d", + "/usr/lib/sysctl.d", + NULL); + + STRV_FOREACH(f, files) { + int k; + + k = apply_file(*f, true); + if (k < 0 && r == 0) + r = k; + } + + strv_free(files); } return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; diff --git a/src/util.c b/src/util.c index 5a076e6e34..5029896ef0 100644 --- a/src/util.c +++ b/src/util.c @@ -4528,3 +4528,97 @@ static const char *const signal_table[] = { }; DEFINE_STRING_TABLE_LOOKUP(signal, int); + +static int file_is_conf(const struct dirent *d, const char *suffix) { + assert(d); + + if (ignore_file(d->d_name)) + return 0; + + if (d->d_type != DT_REG && + d->d_type != DT_LNK && + d->d_type != DT_UNKNOWN) + return 0; + + return endswith(d->d_name, suffix); +} + +static int files_add(Hashmap *h, const char *path, const char *suffix) { + DIR *dir; + struct dirent *de; + int r = 0; + + dir = opendir(path); + if (!dir) { + if (errno == ENOENT) + return 0; + return -errno; + } + + for (de = readdir(dir); de; de = readdir(dir)) { + char *f; + const char *base; + + if (!file_is_conf(de, suffix)) + continue; + + if (asprintf(&f, "%s/%s", path, de->d_name) < 0) { + r = -ENOMEM; + goto finish; + } + + log_debug("found: %s\n", f); + base = f + strlen(path) + 1; + if (hashmap_put(h, base, f) <= 0) + free(f); + } + +finish: + closedir(dir); + return r; +} + +static int base_cmp(const void *a, const void *b) { + const char *s1, *s2; + + s1 = *(char * const *)a; + s2 = *(char * const *)b; + return strcmp(file_name_from_path(s1), file_name_from_path(s2)); +} + +char **conf_files_list(const char *suffix, const char *dir, ...) { + Hashmap *fh; + char **files = NULL; + va_list ap; + int e = 0; + + fh = hashmap_new(string_hash_func, string_compare_func); + if (!fh) { + e = ENOMEM; + goto finish; + } + + va_start(ap, dir); + while (dir) { + if (files_add(fh, dir, suffix) < 0) { + log_error("Failed to search for files."); + e = EINVAL; + goto finish; + } + dir = va_arg(ap, const char *); + } + va_end(ap); + + files = hashmap_get_strv(fh); + if (files == NULL) { + log_error("Failed to compose list of files."); + e = ENOMEM; + goto finish; + } + + qsort(files, hashmap_size(fh), sizeof(char *), base_cmp); +finish: + hashmap_free(fh); + errno = e; + return files; +} diff --git a/src/util.h b/src/util.h index fcaeac4ab9..7fa488b0f5 100644 --- a/src/util.h +++ b/src/util.h @@ -441,4 +441,5 @@ int signal_from_string(const char *s); int signal_from_string_try_harder(const char *s); +char **conf_files_list(const char *suffix, const char *dir, ...); #endif |