mirror of
https://github.com/systemd/systemd.git
synced 2025-01-09 01:18:19 +03:00
sysctl.d, binfmt.d, modules-load.d: switch to stacked config dirs in /lib, /etc, /run
This commit is contained in:
parent
3a90ae0482
commit
db1413d738
@ -1287,8 +1287,11 @@ install-data-hook:
|
||||
$(MKDIR_P) -m 0755 \
|
||||
$(DESTDIR)$(tmpfilesdir) \
|
||||
$(DESTDIR)$(sysconfdir)/modules-load.d \
|
||||
$(DESTDIR)$(prefix)/lib/modules-load.d \
|
||||
$(DESTDIR)$(sysconfdir)/sysctl.d \
|
||||
$(DESTDIR)$(prefix)/lib/sysctl.d \
|
||||
$(DESTDIR)$(sysconfdir)/binfmt.d \
|
||||
$(DESTDIR)$(prefix)/lib/binfmt.d \
|
||||
$(DESTDIR)$(systemshutdowndir) \
|
||||
$(DESTDIR)$(systemgeneratordir) \
|
||||
$(DESTDIR)$(usergeneratordir)
|
||||
|
@ -46,20 +46,20 @@
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<para><filename>/usr/lib/binfmt.d/*.conf</filename></para>
|
||||
<para><filename>/etc/binfmt.d/*.conf</filename></para>
|
||||
<para><filename>/run/binfmt.d/*.conf</filename></para>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para><command>systemd</command> uses
|
||||
<filename>/etc/binfmt.d/</filename> to configure
|
||||
files from the above directories to configure
|
||||
additional binary formats to register during boot in
|
||||
the kernel. Each configuration file is named in the
|
||||
style of
|
||||
<filename>/etc/binfmt.d/<program>.conf</filename>.</para>
|
||||
|
||||
|
||||
<filename><program>.conf</filename>.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
@ -75,11 +75,19 @@
|
||||
ignored. Note that this means you may not use ; and #
|
||||
as delimiter in binary format rules.</para>
|
||||
|
||||
<para>Configuration files are loaded in alphabetical
|
||||
order. To ensure that a specific rule takes precedence
|
||||
over another place it in a file with an alphabetically
|
||||
later name.</para>
|
||||
|
||||
<para>Files in <filename>/etc/</filename> overwrite
|
||||
files with the same name in <filename>/usr/lib/</filename>.
|
||||
Files in <filename>/run</filename> overwrite files with
|
||||
the same name in <filename>/etc/</filename> and
|
||||
<filename>/usr/lib/</filename>. Packages should install their
|
||||
configuration files in <filename>/usr/lib/</filename>, files
|
||||
in <filename>/etc/</filename> are reserved for the local
|
||||
administration, which possibly decides to overwrite the
|
||||
configurations installed from packages. All files are sorted
|
||||
by filename in alphabetical order, regardless in which of the
|
||||
directories they reside, to ensure that a specific
|
||||
configuration file takes precedence over another file with
|
||||
an alphabetically later name.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
|
@ -46,14 +46,16 @@
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<para><filename>/usr/lib/modules-load.d/*.conf</filename></para>
|
||||
<para><filename>/etc/modules-load.d/*.conf</filename></para>
|
||||
<para><filename>/run/modules-load.d/*.conf</filename></para>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para><command>systemd</command> uses
|
||||
<filename>/etc/modules-load.d/</filename> to configure
|
||||
files from the above directories to configure
|
||||
kernel modules to load during boot in a static list.
|
||||
Each configuration file is named in the style of
|
||||
<filename>/etc/modules-load.d/<program>.conf</filename>. Note
|
||||
@ -72,6 +74,19 @@
|
||||
newlines. Empty lines and lines whose first
|
||||
non-whitespace character is # or ; are ignored.</para>
|
||||
|
||||
<para>Files in <filename>/etc/</filename> overwrite
|
||||
files with the same name in <filename>/usr/lib/</filename>.
|
||||
Files in <filename>/run</filename> overwrite files with
|
||||
the same name in <filename>/etc/</filename> and
|
||||
<filename>/usr/lib/</filename>. Packages should install their
|
||||
configuration files in <filename>/usr/lib/</filename>, files
|
||||
in <filename>/etc/</filename> are reserved for the local
|
||||
administration, which possibly decides to overwrite the
|
||||
configurations installed from packages. All files are sorted
|
||||
by filename in alphabetical order, regardless in which of the
|
||||
directories they reside, to ensure that a specific
|
||||
configuration file takes precedence over another file with
|
||||
an alphabetically later name.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
|
@ -46,7 +46,9 @@
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<para><filename>/usr/lib/sysctl.d/*.conf</filename></para>
|
||||
<para><filename>/etc/sysctl.d/*.conf</filename></para>
|
||||
<para><filename>/run/sysctl.d/*.conf</filename></para>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
@ -71,6 +73,19 @@
|
||||
<para>Note that both / and . are accepted as
|
||||
separators in sysctl variable names.</para>
|
||||
|
||||
<para>Files in <filename>/etc/</filename> overwrite
|
||||
files with the same name in <filename>/usr/lib/</filename>.
|
||||
Files in <filename>/run</filename> overwrite files with
|
||||
the same name in <filename>/etc/</filename> and
|
||||
<filename>/usr/lib/</filename>. Packages should install their
|
||||
configuration files in <filename>/usr/lib/</filename>, files
|
||||
in <filename>/etc/</filename> are reserved for the local
|
||||
administration, which possibly decides to overwrite the
|
||||
configurations installed from packages. All files are sorted
|
||||
by filename in alphabetical order, regardless in which of the
|
||||
directories they reside, to ensure that a specific
|
||||
configuration file takes precedence over another file with
|
||||
an alphabetically later name.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
|
76
src/binfmt.c
76
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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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))
|
||||
|
||||
|
@ -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) {
|
||||
|
70
src/sysctl.c
70
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,13 +136,26 @@ 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)
|
||||
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;
|
||||
}
|
||||
|
94
src/util.c
94
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;
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user