+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;
+ char *confdir = NULL;
+ char *head;
+
+ if (loaded)
+ return;
+ if (conffile == NULL) {
+ conffile = DefaultConfFile;
+ confdir = DefaultConfDir;
+ }
+
+ if (strcmp(conffile, "partitions") == 0) {
+ char *list = dl_strdup("DEV");
+ dl_init(list);
+ dl_add(list, dl_strdup("partitions"));
+ devline(list);
+ free_line(list);
+ } else if (strcmp(conffile, "none") != 0) {
+ f = fopen(conffile, "r");
+ /* Debian chose to relocate mdadm.conf into /etc/mdadm/.
+ * To allow Debian users to compile from clean source and still
+ * have a working mdadm, we read /etc/mdadm/mdadm.conf
+ * if /etc/mdadm.conf doesn't exist
+ */
+ if (f == NULL && conffile == DefaultConfFile) {
+ f = fopen(DefaultAltConfFile, "r");
+ if (f) {
+ conffile = DefaultAltConfFile;
+ confdir = DefaultAltConfDir;
+ }
+ }
+ if (f) {
+ conf_file_or_dir(f);
+ fclose(f);
+ }
+ if (confdir) {
+ f = fopen(confdir, "r");
+ if (f) {
+ conf_file_or_dir(f);
+ fclose(f);
+ }
+ }
+ }
+ /* If there was no AUTO line, process an empty line
+ * now so that the MDADM_CONF_AUTO env var gets processed.
+ */
+ head = dl_strdup("AUTO");
+ dl_init(head);
+ autoline(head);
+ free_line(head);
+
+ loaded = 1;