diff options
author | NeilBrown <neilb@suse.de> | 2013-09-03 01:03:56 +0200 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2013-09-03 01:16:33 +0200 |
commit | 343b7e75e886c3b1d38fdedf1ecc2e9cd7ec96ad (patch) | |
tree | c97a68608fcf328e88325b2f47679bc44e1ac7ca /config.c | |
parent | Config: factor reading of file out into separate function. (diff) | |
download | mdadm-343b7e75e886c3b1d38fdedf1ecc2e9cd7ec96ad.tar.xz mdadm-343b7e75e886c3b1d38fdedf1ecc2e9cd7ec96ad.zip |
Conf: allow conf file to be a directory.
If config file is a directory, process each file within with a name
ending in ".conf" that doesn't start with ".".
Files are processed in lexical order.
Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'config.c')
-rw-r--r-- | config.c | 63 |
1 files changed, 62 insertions, 1 deletions
@@ -728,6 +728,67 @@ void conf_file(FILE *f) } } +struct fname { + struct fname *next; + char name[]; +}; + +void conf_file_or_dir(FILE *f) +{ + struct stat st; + DIR *dir; + struct dirent *dp; + struct fname *list = NULL; + + fstat(fileno(f), &st); + if (S_ISREG(st.st_mode)) + conf_file(f); + else if (!S_ISDIR(st.st_mode)) + return; +#if _XOPEN_SOURCE >= 700 || _POSIX_C_SOURCE >= 200809L + dir = fdopendir(fileno(f)); + if (!dir) + return; + while ((dp = readdir(dir)) != NULL) { + int l; + struct fname *fn, **p; + if (dp->d_ino == 0) + continue; + if (dp->d_name[0] == '.') + continue; + l = strlen(dp->d_name); + if (l < 6 || strcmp(dp->d_name+l-5, ".conf") != 0) + continue; + fn = xmalloc(sizeof(*fn)+l+1); + strcpy(fn->name, dp->d_name); + for (p = &list; + *p && strcmp((*p)->name, fn->name) < 0; + p = & (*p)->next) + ; + fn->next = *p; + *p = fn; + } + while (list) { + int fd; + FILE *f2; + struct fname *fn = list; + list = list->next; + fd = openat(fileno(f), fn->name, O_RDONLY); + free(fn); + if (fd < 0) + continue; + f2 = fdopen(fd, "r"); + if (!f2) { + close(fd); + continue; + } + conf_file(f2); + fclose(f2); + } + closedir(dir); +#endif +} + void load_conffile(void) { FILE *f; @@ -765,7 +826,7 @@ void load_conffile(void) return; loaded = 1; - conf_file(f); + conf_file_or_dir(f); fclose(f); |