conf: add better support for fragmented configuration
Add a confdirs directive to include *.conf files from multiple directories. If a file with the same name exists in multiple directories, only the first one in the order of the specified directories will be included.
This commit is contained in:
parent
6901df5c18
commit
3470ab66f0
2 changed files with 106 additions and 12 deletions
81
conf.c
81
conf.c
|
@ -42,6 +42,11 @@
|
|||
#include "cmdparse.h"
|
||||
#include "util.h"
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
#define MAX_LINE_LENGTH 2048
|
||||
#define MAX_CONF_DIRS 10
|
||||
|
||||
/* ================================================== */
|
||||
/* Forward prototypes */
|
||||
|
||||
|
@ -57,6 +62,7 @@ static void parse_bindaddress(char *);
|
|||
static void parse_bindcmdaddress(char *);
|
||||
static void parse_broadcast(char *);
|
||||
static void parse_clientloglimit(char *);
|
||||
static void parse_confdirs(char *);
|
||||
static void parse_fallbackdrift(char *);
|
||||
static void parse_hwtimestamp(char *);
|
||||
static void parse_include(char *);
|
||||
|
@ -424,7 +430,7 @@ void
|
|||
CNF_ReadFile(const char *filename)
|
||||
{
|
||||
FILE *in;
|
||||
char line[2048];
|
||||
char line[MAX_LINE_LENGTH];
|
||||
int i;
|
||||
|
||||
in = UTI_OpenFile(NULL, filename, NULL, 'R', 0);
|
||||
|
@ -486,6 +492,8 @@ CNF_ParseLine(const char *filename, int number, char *line)
|
|||
&cmd_ratelimit_burst, &cmd_ratelimit_leak);
|
||||
} else if (!strcasecmp(command, "combinelimit")) {
|
||||
parse_double(p, &combine_limit);
|
||||
} else if (!strcasecmp(command, "confdirs")) {
|
||||
parse_confdirs(p);
|
||||
} else if (!strcasecmp(command, "corrtimeratio")) {
|
||||
parse_double(p, &correction_time_ratio);
|
||||
} else if (!strcasecmp(command, "deny")) {
|
||||
|
@ -1407,6 +1415,77 @@ parse_hwtimestamp(char *line)
|
|||
|
||||
/* ================================================== */
|
||||
|
||||
static const char *
|
||||
get_basename(const char *path)
|
||||
{
|
||||
const char *b = strrchr(path, '/');
|
||||
return b ? b + 1 : path;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static int
|
||||
compare_basenames(const void *a, const void *b)
|
||||
{
|
||||
return strcmp(get_basename(*(const char * const *)a),
|
||||
get_basename(*(const char * const *)b));
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
parse_confdirs(char *line)
|
||||
{
|
||||
char *dirs[MAX_CONF_DIRS], buf[MAX_LINE_LENGTH], *path;
|
||||
size_t i, j, k, locations, n_dirs;
|
||||
glob_t gl;
|
||||
|
||||
n_dirs = UTI_SplitString(line, dirs, MAX_CONF_DIRS);
|
||||
if (n_dirs < 1 || n_dirs > MAX_CONF_DIRS) {
|
||||
command_parse_error();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get the paths of all config files in the specified directories */
|
||||
for (i = 0; i < n_dirs; i++) {
|
||||
if (snprintf(buf, sizeof (buf), "%s/%s", dirs[i], "*.conf") >= sizeof (buf))
|
||||
assert(0);
|
||||
if (glob(buf, GLOB_NOSORT | (i > 0 ? GLOB_APPEND : 0), NULL, &gl) != 0)
|
||||
;
|
||||
}
|
||||
|
||||
if (gl.gl_pathc > 0) {
|
||||
/* Sort the paths by filenames */
|
||||
qsort(gl.gl_pathv, gl.gl_pathc, sizeof (gl.gl_pathv[0]), compare_basenames);
|
||||
|
||||
for (i = 0; i < gl.gl_pathc; i += locations) {
|
||||
/* Count directories containing files with this name */
|
||||
for (j = i + 1, locations = 1; j < gl.gl_pathc; j++, locations++) {
|
||||
if (compare_basenames(&gl.gl_pathv[i], &gl.gl_pathv[j]) != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Read the first file of this name in the order of the directive */
|
||||
for (j = 0; j < n_dirs; j++) {
|
||||
for (k = 0; k < locations; k++) {
|
||||
path = gl.gl_pathv[i + k];
|
||||
if (strncmp(path, dirs[j], strlen(dirs[j])) == 0 &&
|
||||
strlen(dirs[j]) + 1 + strlen(get_basename(path)) == strlen(path)) {
|
||||
CNF_ReadFile(path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (k < locations)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
globfree(&gl);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
parse_include(char *line)
|
||||
{
|
||||
|
|
|
@ -2121,6 +2121,32 @@ sendmail binary.
|
|||
|
||||
=== Miscellaneous
|
||||
|
||||
[[confdirs]]*confdirs* _directory_...::
|
||||
The *confdirs* directive includes configuration files with the _.conf_ suffix
|
||||
from up to 10 directories. The files are included in the lexicographical order
|
||||
(ignoring the names of the directories). If multiple directories contain a file
|
||||
with the same name, only the first file in the order of the specified
|
||||
directories will be included. This enables a fragmented configuration, where
|
||||
existing fragments can be replaced by adding files to a different directory.
|
||||
+
|
||||
An example of the directive is:
|
||||
+
|
||||
----
|
||||
confdirs @SYSCONFDIR@/chrony.d /var/run/chrony.d /usr/lib/chrony.d
|
||||
----
|
||||
|
||||
[[include]]*include* _pattern_::
|
||||
The *include* directive includes a configuration file, or multiple configuration
|
||||
files if a wildcard pattern is specified. Unlike with the *confdirs* directive,
|
||||
the full name of the files needs to be specified and at least one file is
|
||||
required to exist.
|
||||
+
|
||||
An example of the directive is:
|
||||
+
|
||||
----
|
||||
include @SYSCONFDIR@/chrony.d/*.conf
|
||||
----
|
||||
|
||||
[[hwtimestamp]]*hwtimestamp* _interface_ [_option_]...::
|
||||
This directive enables hardware timestamping of NTP packets sent to and
|
||||
received from the specified network interface. The network interface controller
|
||||
|
@ -2208,17 +2234,6 @@ hwtimestamp eth1 txcomp 300e-9 rxcomp 645e-9
|
|||
hwtimestamp *
|
||||
----
|
||||
|
||||
[[include]]*include* _pattern_::
|
||||
The *include* directive includes a configuration file or multiple configuration
|
||||
files if a wildcard pattern is specified. This can be useful when maintaining
|
||||
configuration on multiple hosts to keep the differences in separate files.
|
||||
+
|
||||
An example of the directive is:
|
||||
+
|
||||
----
|
||||
include @SYSCONFDIR@/chrony.d/*.conf
|
||||
----
|
||||
|
||||
[[keyfile]]*keyfile* _file_::
|
||||
This directive is used to specify the location of the file containing symmetric
|
||||
keys which are shared between NTP servers and clients, or peers, in order to
|
||||
|
|
Loading…
Reference in a new issue