@@ -52,6 +52,7 @@
#include <libgen.h>
#include <sys/file.h>
#include <time.h>
+#include <dirent.h>
#include "conffile.h"
#include "xlog.h"
@@ -456,7 +457,7 @@ conf_parse_line(int trans, char *line, const char *filename, int lineno, char **
free(subconf);
} else {
/* XXX Perhaps should we not ignore errors? */
- conf_set(trans, *section, *subsection, line, val, 0, 0);
+ conf_set(trans, *section, *subsection, line, val, 1, 0);
}
}
@@ -577,6 +578,30 @@ static void conf_free_bindings(void)
}
}
+static int
+conf_load_files(int trans, const char *conf_file)
+{
+ char *conf_data;
+ char *section = NULL;
+ char *subsection = NULL;
+
+ conf_data = conf_readfile(conf_file);
+ if (conf_data == NULL)
+ return 1;
+
+ /* Load default configuration values. */
+ conf_load_defaults();
+
+ /* Parse config contents into the transaction queue */
+ conf_parse(trans, conf_data, §ion, &subsection, conf_file);
+ if (section)
+ free(section);
+ if (subsection)
+ free(subsection);
+ free(conf_data);
+
+ return 0;
+}
/* Open the config file and map it into our address space, then parse it. */
static int
conf_load_file(const char *conf_file)
@@ -609,18 +634,106 @@ conf_load_file(const char *conf_file)
return 0;
}
+static void
+conf_init_dir(const char *conf_file)
+{
+ struct dirent **namelist = NULL;
+ char *dname, fname[PATH_MAX + 1];
+ int n = 0, i, nfiles = 0, fname_len, dname_len;
+ int trans;
+
+ dname = malloc(strlen(conf_file) + 3);
+ if (dname == NULL) {
+ xlog(L_WARNING, "conf_init_dir: malloc: %s", strerror(errno));
+ return;
+ }
+ sprintf(dname, "%s.d", conf_file);
+
+ n = scandir(dname, &namelist, NULL, versionsort);
+ if (n < 0) {
+ if (errno != ENOENT) {
+ xlog(L_WARNING, "conf_init_dir: scandir %s: %s",
+ dname, strerror(errno));
+ }
+ free(dname);
+ return;
+ } else if (n == 0) {
+ free(dname);
+ return;
+ }
+
+ trans = conf_begin();
+ dname_len = strlen(dname);
+ for (i = 0; i < n; i++ ) {
+ struct dirent *d = namelist[i];
+
+ switch (d->d_type) {
+ case DT_UNKNOWN:
+ case DT_REG:
+ case DT_LNK:
+ break;
+ default:
+ continue;
+ }
+ if (*d->d_name == '.')
+ continue;
+
+ fname_len = strlen(d->d_name);
+ if (!fname_len || (fname_len + dname_len) > PATH_MAX) {
+ xlog(L_WARNING, "conf_init_dir: Too long file name: %s in %s",
+ d->d_name, dname);
+ continue;
+ }
+ sprintf(fname, "%s/%s", dname, d->d_name);
+
+ if (conf_load_files(trans, fname))
+ continue;
+ nfiles++;
+ }
+
+ if (nfiles) {
+ /* Apply the configuration values */
+ conf_end(trans, 1);
+ }
+ for (i = 0; i < n; i++)
+ free(namelist[i]);
+ free(namelist);
+ free(dname);
+
+ return;
+}
+
int
conf_init_file(const char *conf_file)
{
unsigned int i;
+ int ret;
for (i = 0; i < sizeof conf_bindings / sizeof conf_bindings[0]; i++)
LIST_INIT (&conf_bindings[i]);
TAILQ_INIT (&conf_trans_queue);
- if (conf_file == NULL) conf_file=NFS_CONFFILE;
- return conf_load_file(conf_file);
+ if (conf_file == NULL)
+ conf_file=NFS_CONFFILE;
+
+ /*
+ * First parse the give config file
+ * then parse the config.conf.d directory
+ * (if it exists)
+ *
+ */
+ ret = conf_load_file(conf_file);
+
+ /*
+ * When the same variable is set in both files
+ * the conf.d file will override the config file.
+ * This allows automated admin systems to
+ * have the final say.
+ */
+ conf_init_dir(conf_file);
+
+ return ret;
}
/*
When a /etc/nfs.conf.d or /etc/nfsmount.conf.d directory exists and config file(s) do exist in those directories, those file(s) will be used and will override the same settings that are set in the main config files. Signed-off-by: Steve Dickson <steved@redhat.com> --- support/nfs/conffile.c | 119 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 116 insertions(+), 3 deletions(-)