From d7e149ca36a3adcc54adbe87313047da46fa2918 Mon Sep 17 00:00:00 2001
From: William Brown <firstyear@redhat.com>
Date: Tue, 3 May 2016 14:23:26 +1000
Subject: [PATCH 1/2] Ticket 48163 - Read schema from multiple locations

Bug Description:  We provide system schema that should not be altered or changed.
This schema tends to be version specific to ds versions also. As a result, it
would be good to move system schema to /usr, and keep custom or changing schema
in /etc.

Fix Description:  This adds a new configure option, systemschemadir, which
provides the location of system schema to the schema.c file. Additionally,
get priority filelist is altered to be able to prioritise over a number of
directories to form the filelist.

This leaves the only schema element in /etc as /etc/dirsrv/schema/99user.ldif

https://fedorahosted.org/389/ticket/48163

Author: wibrown

Review by: ???
---
 Makefile.am                      |  11 ++-
 Makefile.in                      |  57 +++++++++---
 configure                        |   6 ++
 configure.ac                     |   5 +
 ldap/servers/slapd/getfilelist.c | 195 ++++++++++++++++++++++++---------------
 ldap/servers/slapd/proto-slap.h  |  13 +--
 ldap/servers/slapd/schema.c      |   7 +-
 7 files changed, 195 insertions(+), 99 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 0e9939a..0b3c935 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -39,7 +39,8 @@ DS_INCLUDES = -I$(srcdir)/ldap/include -I$(srcdir)/ldap/servers/slapd -I$(srcdir
 PATH_DEFINES = -DLOCALSTATEDIR="\"$(localstatedir)\"" -DSYSCONFDIR="\"$(sysconfdir)\"" \
 	-DLIBDIR="\"$(libdir)\"" -DBINDIR="\"$(bindir)\"" \
 	-DDATADIR="\"$(datadir)\"" -DDOCDIR="\"$(docdir)\"" \
-	-DSBINDIR="\"$(sbindir)\"" -DPLUGINDIR="\"$(serverplugindir)\"" -DTEMPLATEDIR="\"$(sampledatadir)\""
+	-DSBINDIR="\"$(sbindir)\"" -DPLUGINDIR="\"$(serverplugindir)\"" \
+	-DTEMPLATEDIR="\"$(sampledatadir)\"" -DSYSTEMSCHEMADIR="\"$(systemschemadir)\""
 
 AM_CPPFLAGS = $(DEBUG_DEFINES) $(GCCSEC_DEFINES) $(ASAN_DEFINES) $(DS_DEFINES) $(DS_INCLUDES) $(PATH_DEFINES) $(SYSTEMD_DEFINES)
 PLUGIN_CPPFLAGS = $(AM_CPPFLAGS) @openldap_inc@ @ldapsdk_inc@ @nss_inc@ @nspr_inc@ @systemd_inc@
@@ -170,6 +171,7 @@ selinux-built/dirsrv.fc: selinux-built
 #------------------------
 configdir = $(sysconfdir)@configdir@
 sampledatadir = $(datadir)@sampledatadir@
+systemschemadir = $(datadir)@systemschemadir@
 propertydir = $(datadir)@propertydir@
 schemadir = $(sysconfdir)@schemadir@
 serverdir = $(libdir)@serverdir@
@@ -536,7 +538,7 @@ sampledata_DATA = ldap/admin/src/scripts/DSSharedLib \
 	$(srcdir)/ldap/schema/60sendmail.ldif \
 	$(LIBPRESENCE_SCHEMA)
 
-schema_DATA = $(srcdir)/ldap/schema/00core.ldif \
+systemschema_DATA = $(srcdir)/ldap/schema/00core.ldif \
 	$(srcdir)/ldap/schema/01core389.ldif \
 	$(srcdir)/ldap/schema/02common.ldif \
 	$(srcdir)/ldap/schema/05rfc2927.ldif \
@@ -569,9 +571,10 @@ schema_DATA = $(srcdir)/ldap/schema/00core.ldif \
 	$(srcdir)/ldap/schema/60sudo.ldif \
 	$(srcdir)/ldap/schema/60trust.ldif \
 	$(srcdir)/ldap/schema/60nss-ldap.ldif \
-	$(srcdir)/ldap/schema/99user.ldif \
 	$(LIBACCTPOLICY_SCHEMA)
 
+schema_DATA = $(srcdir)/ldap/schema/99user.ldif
+
 sbin_SCRIPTS = ldap/admin/src/scripts/setup-ds.pl \
 	ldap/admin/src/scripts/migrate-ds.pl \
 	ldap/admin/src/scripts/remove-ds.pl \
@@ -1788,6 +1791,7 @@ fixupcmd = sed \
 	-e 's,@infdir\@,$(infdir),g' \
 	-e 's,@mibdir\@,$(mibdir),g' \
 	-e 's,@templatedir\@,$(sampledatadir),g' \
+	-e 's,@systemschemadir\@,$(systemschemadir),g' \
 	-e 's,@package_name\@,$(PACKAGE_NAME),g' \
 	-e 's,@instconfigdir\@,$(instconfigdir),g' \
 	-e 's,@enable_ldapi\@,$(enable_ldapi),g' \
@@ -1855,6 +1859,7 @@ fixupcmd = sed \
 	-e 's,@infdir\@,$(infdir),g' \
 	-e 's,@mibdir\@,$(mibdir),g' \
 	-e 's,@templatedir\@,$(sampledatadir),g' \
+	-e 's,@systemschemadir\@,$(systemschemadir),g' \
 	-e 's,@package_name\@,$(PACKAGE_NAME),g' \
 	-e 's,@instconfigdir\@,$(instconfigdir),g' \
 	-e 's,@enable_ldapi\@,$(enable_ldapi),g' \
diff --git a/Makefile.in b/Makefile.in
index 0752ff1..3de47d9 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -180,7 +180,8 @@ am__installdirs = "$(DESTDIR)$(serverdir)" \
 	"$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(propertydir)" \
 	"$(DESTDIR)$(pythondir)" "$(DESTDIR)$(sampledatadir)" \
 	"$(DESTDIR)$(schemadir)" "$(DESTDIR)$(systemdsystemunitdir)" \
-	"$(DESTDIR)$(updatedir)" "$(DESTDIR)$(serverincdir)"
+	"$(DESTDIR)$(systemschemadir)" "$(DESTDIR)$(updatedir)" \
+	"$(DESTDIR)$(serverincdir)"
 LTLIBRARIES = $(server_LTLIBRARIES) $(serverplugin_LTLIBRARIES)
 am__DEPENDENCIES_1 =
 libacctpolicy_plugin_la_DEPENDENCIES = libslapd.la \
@@ -1231,7 +1232,7 @@ DATA = $(config_DATA) $(dist_noinst_DATA) $(inf_DATA) \
 	$(initconfig_DATA) $(mib_DATA) $(nodist_property_DATA) \
 	$(perl_DATA) $(pkgconfig_DATA) $(property_DATA) $(python_DATA) \
 	$(sampledata_DATA) $(schema_DATA) $(systemdsystemunit_DATA) \
-	$(update_DATA)
+	$(systemschema_DATA) $(update_DATA)
 HEADERS = $(dist_noinst_HEADERS) $(serverinc_HEADERS)
 am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \
 	$(LISP)config.h.in
@@ -1485,6 +1486,7 @@ sysconfdir = @sysconfdir@
 systemd_defs = @systemd_defs@
 systemd_inc = @systemd_inc@
 systemd_lib = @systemd_lib@
+systemschemadir = $(datadir)@systemschemadir@
 target_alias = @target_alias@
 top_build_prefix = @top_build_prefix@
 top_builddir = @top_builddir@
@@ -1537,7 +1539,8 @@ DS_INCLUDES = -I$(srcdir)/ldap/include -I$(srcdir)/ldap/servers/slapd -I$(srcdir
 PATH_DEFINES = -DLOCALSTATEDIR="\"$(localstatedir)\"" -DSYSCONFDIR="\"$(sysconfdir)\"" \
 	-DLIBDIR="\"$(libdir)\"" -DBINDIR="\"$(bindir)\"" \
 	-DDATADIR="\"$(datadir)\"" -DDOCDIR="\"$(docdir)\"" \
-	-DSBINDIR="\"$(sbindir)\"" -DPLUGINDIR="\"$(serverplugindir)\"" -DTEMPLATEDIR="\"$(sampledatadir)\""
+	-DSBINDIR="\"$(sbindir)\"" -DPLUGINDIR="\"$(serverplugindir)\"" \
+	-DTEMPLATEDIR="\"$(sampledatadir)\"" -DSYSTEMSCHEMADIR="\"$(systemschemadir)\""
 
 AM_CPPFLAGS = $(DEBUG_DEFINES) $(GCCSEC_DEFINES) $(ASAN_DEFINES) $(DS_DEFINES) $(DS_INCLUDES) $(PATH_DEFINES) $(SYSTEMD_DEFINES)
 PLUGIN_CPPFLAGS = $(AM_CPPFLAGS) @openldap_inc@ @ldapsdk_inc@ @nss_inc@ @nspr_inc@ @systemd_inc@
@@ -1952,7 +1955,7 @@ sampledata_DATA = ldap/admin/src/scripts/DSSharedLib \
 	$(srcdir)/ldap/schema/60sendmail.ldif \
 	$(LIBPRESENCE_SCHEMA)
 
-schema_DATA = $(srcdir)/ldap/schema/00core.ldif \
+systemschema_DATA = $(srcdir)/ldap/schema/00core.ldif \
 	$(srcdir)/ldap/schema/01core389.ldif \
 	$(srcdir)/ldap/schema/02common.ldif \
 	$(srcdir)/ldap/schema/05rfc2927.ldif \
@@ -1985,9 +1988,9 @@ schema_DATA = $(srcdir)/ldap/schema/00core.ldif \
 	$(srcdir)/ldap/schema/60sudo.ldif \
 	$(srcdir)/ldap/schema/60trust.ldif \
 	$(srcdir)/ldap/schema/60nss-ldap.ldif \
-	$(srcdir)/ldap/schema/99user.ldif \
 	$(LIBACCTPOLICY_SCHEMA)
 
+schema_DATA = $(srcdir)/ldap/schema/99user.ldif
 sbin_SCRIPTS = ldap/admin/src/scripts/setup-ds.pl \
 	ldap/admin/src/scripts/migrate-ds.pl \
 	ldap/admin/src/scripts/remove-ds.pl \
@@ -3099,6 +3102,7 @@ rsearch_bin_LDADD = $(NSPR_LINK) $(NSS_LINK) $(LDAPSDK_LINK) $(SASL_LINK) $(LIBS
 @BUNDLE_FALSE@	-e 's,@infdir\@,$(infdir),g' \
 @BUNDLE_FALSE@	-e 's,@mibdir\@,$(mibdir),g' \
 @BUNDLE_FALSE@	-e 's,@templatedir\@,$(sampledatadir),g' \
+@BUNDLE_FALSE@	-e 's,@systemschemadir\@,$(systemschemadir),g' \
 @BUNDLE_FALSE@	-e 's,@package_name\@,$(PACKAGE_NAME),g' \
 @BUNDLE_FALSE@	-e 's,@instconfigdir\@,$(instconfigdir),g' \
 @BUNDLE_FALSE@	-e 's,@enable_ldapi\@,$(enable_ldapi),g' \
@@ -3176,6 +3180,7 @@ rsearch_bin_LDADD = $(NSPR_LINK) $(NSS_LINK) $(LDAPSDK_LINK) $(SASL_LINK) $(LIBS
 @BUNDLE_TRUE@	-e 's,@infdir\@,$(infdir),g' \
 @BUNDLE_TRUE@	-e 's,@mibdir\@,$(mibdir),g' \
 @BUNDLE_TRUE@	-e 's,@templatedir\@,$(sampledatadir),g' \
+@BUNDLE_TRUE@	-e 's,@systemschemadir\@,$(systemschemadir),g' \
 @BUNDLE_TRUE@	-e 's,@package_name\@,$(PACKAGE_NAME),g' \
 @BUNDLE_TRUE@	-e 's,@instconfigdir\@,$(instconfigdir),g' \
 @BUNDLE_TRUE@	-e 's,@enable_ldapi\@,$(enable_ldapi),g' \
@@ -10194,6 +10199,27 @@ uninstall-systemdsystemunitDATA:
 	@list='$(systemdsystemunit_DATA)'; test -n "$(systemdsystemunitdir)" || list=; \
 	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
 	dir='$(DESTDIR)$(systemdsystemunitdir)'; $(am__uninstall_files_from_dir)
+install-systemschemaDATA: $(systemschema_DATA)
+	@$(NORMAL_INSTALL)
+	@list='$(systemschema_DATA)'; test -n "$(systemschemadir)" || list=; \
+	if test -n "$$list"; then \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(systemschemadir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(systemschemadir)" || exit 1; \
+	fi; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(systemschemadir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(systemschemadir)" || exit $$?; \
+	done
+
+uninstall-systemschemaDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(systemschema_DATA)'; test -n "$(systemschemadir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	dir='$(DESTDIR)$(systemschemadir)'; $(am__uninstall_files_from_dir)
 install-updateDATA: $(update_DATA)
 	@$(NORMAL_INSTALL)
 	@list='$(update_DATA)'; test -n "$(updatedir)" || list=; \
@@ -10457,7 +10483,7 @@ check: $(BUILT_SOURCES)
 all-am: Makefile $(LIBRARIES) $(LTLIBRARIES) $(PROGRAMS) $(SCRIPTS) \
 		$(MANS) $(DATA) $(HEADERS) config.h
 installdirs:
-	for dir in "$(DESTDIR)$(serverdir)" "$(DESTDIR)$(serverplugindir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(initdir)" "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(taskdir)" "$(DESTDIR)$(updatedir)" "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man8dir)" "$(DESTDIR)$(configdir)" "$(DESTDIR)$(infdir)" "$(DESTDIR)$(initconfigdir)" "$(DESTDIR)$(mibdir)" "$(DESTDIR)$(propertydir)" "$(DESTDIR)$(perldir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(propertydir)" "$(DESTDIR)$(pythondir)" "$(DESTDIR)$(sampledatadir)" "$(DESTDIR)$(schemadir)" "$(DESTDIR)$(systemdsystemunitdir)" "$(DESTDIR)$(updatedir)" "$(DESTDIR)$(serverincdir)"; do \
+	for dir in "$(DESTDIR)$(serverdir)" "$(DESTDIR)$(serverplugindir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(initdir)" "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(taskdir)" "$(DESTDIR)$(updatedir)" "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man8dir)" "$(DESTDIR)$(configdir)" "$(DESTDIR)$(infdir)" "$(DESTDIR)$(initconfigdir)" "$(DESTDIR)$(mibdir)" "$(DESTDIR)$(propertydir)" "$(DESTDIR)$(perldir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(propertydir)" "$(DESTDIR)$(pythondir)" "$(DESTDIR)$(sampledatadir)" "$(DESTDIR)$(schemadir)" "$(DESTDIR)$(systemdsystemunitdir)" "$(DESTDIR)$(systemschemadir)" "$(DESTDIR)$(updatedir)" "$(DESTDIR)$(serverincdir)"; do \
 	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
 	done
 install: $(BUILT_SOURCES)
@@ -10620,7 +10646,8 @@ install-data-am: install-configDATA install-infDATA \
 	install-sampledataDATA install-schemaDATA \
 	install-serverLTLIBRARIES install-serverincHEADERS \
 	install-serverpluginLTLIBRARIES install-systemdsystemunitDATA \
-	install-taskSCRIPTS install-updateDATA install-updateSCRIPTS
+	install-systemschemaDATA install-taskSCRIPTS \
+	install-updateDATA install-updateSCRIPTS
 
 install-dvi: install-dvi-am
 
@@ -10678,8 +10705,9 @@ uninstall-am: uninstall-binPROGRAMS uninstall-binSCRIPTS \
 	uninstall-sbinPROGRAMS uninstall-sbinSCRIPTS \
 	uninstall-schemaDATA uninstall-serverLTLIBRARIES \
 	uninstall-serverincHEADERS uninstall-serverpluginLTLIBRARIES \
-	uninstall-systemdsystemunitDATA uninstall-taskSCRIPTS \
-	uninstall-updateDATA uninstall-updateSCRIPTS
+	uninstall-systemdsystemunitDATA uninstall-systemschemaDATA \
+	uninstall-taskSCRIPTS uninstall-updateDATA \
+	uninstall-updateSCRIPTS
 
 uninstall-man: uninstall-man1 uninstall-man8
 
@@ -10708,9 +10736,9 @@ uninstall-man: uninstall-man1 uninstall-man8
 	install-sbinSCRIPTS install-schemaDATA \
 	install-serverLTLIBRARIES install-serverincHEADERS \
 	install-serverpluginLTLIBRARIES install-strip \
-	install-systemdsystemunitDATA install-taskSCRIPTS \
-	install-updateDATA install-updateSCRIPTS installcheck \
-	installcheck-am installdirs maintainer-clean \
+	install-systemdsystemunitDATA install-systemschemaDATA \
+	install-taskSCRIPTS install-updateDATA install-updateSCRIPTS \
+	installcheck installcheck-am installdirs maintainer-clean \
 	maintainer-clean-generic mostlyclean mostlyclean-compile \
 	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
 	tags tags-am uninstall uninstall-am uninstall-binPROGRAMS \
@@ -10723,8 +10751,9 @@ uninstall-man: uninstall-man1 uninstall-man8
 	uninstall-sbinPROGRAMS uninstall-sbinSCRIPTS \
 	uninstall-schemaDATA uninstall-serverLTLIBRARIES \
 	uninstall-serverincHEADERS uninstall-serverpluginLTLIBRARIES \
-	uninstall-systemdsystemunitDATA uninstall-taskSCRIPTS \
-	uninstall-updateDATA uninstall-updateSCRIPTS
+	uninstall-systemdsystemunitDATA uninstall-systemschemaDATA \
+	uninstall-taskSCRIPTS uninstall-updateDATA \
+	uninstall-updateSCRIPTS
 
 
 clean-local:
diff --git a/configure b/configure
index 7dc8c3e..b91fe81 100755
--- a/configure
+++ b/configure
@@ -742,6 +742,7 @@ serverincdir
 serverdir
 schemadir
 propertydir
+systemschemadir
 sampledatadir
 configdir
 with_tmpfiles_d
@@ -18163,6 +18164,8 @@ if test "$with_fhs_opt" = "yes"; then
   # relative to datadir
   sampledatadir=/data
   # relative to datadir
+  systemschemadir=/schema
+  # relative to datadir
   scripttemplatedir=/script-templates
   # relative to datadir
   updatedir=/updates
@@ -18194,6 +18197,8 @@ else
   # relative to datadir
   sampledatadir=/$PACKAGE_NAME/data
   # relative to datadir
+  systemschemadir=/$PACKAGE_NAME/schema
+  # relative to datadir
   scripttemplatedir=/$PACKAGE_NAME/script-templates
   # relative to datadir
   updatedir=/$PACKAGE_NAME/updates
@@ -18314,6 +18319,7 @@ fi
 
 
 
+
 # check for --with-instconfigdir
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-instconfigdir" >&5
 $as_echo_n "checking for --with-instconfigdir... " >&6; }
diff --git a/configure.ac b/configure.ac
index 9544bbc..ee0887c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -289,6 +289,8 @@ if test "$with_fhs_opt" = "yes"; then
   # relative to datadir
   sampledatadir=/data
   # relative to datadir
+  systemschemadir=/schema
+  # relative to datadir
   scripttemplatedir=/script-templates
   # relative to datadir
   updatedir=/updates
@@ -322,6 +324,8 @@ else
   # relative to datadir
   sampledatadir=/$PACKAGE_NAME/data
   # relative to datadir
+  systemschemadir=/$PACKAGE_NAME/schema
+  # relative to datadir
   scripttemplatedir=/$PACKAGE_NAME/script-templates
   # relative to datadir
   updatedir=/$PACKAGE_NAME/updates
@@ -414,6 +418,7 @@ fi
 
 AC_SUBST(configdir)
 AC_SUBST(sampledatadir)
+AC_SUBST(systemschemadir)
 AC_SUBST(propertydir)
 AC_SUBST(schemadir)
 AC_SUBST(serverdir)
diff --git a/ldap/servers/slapd/getfilelist.c b/ldap/servers/slapd/getfilelist.c
index f544949..f378485 100644
--- a/ldap/servers/slapd/getfilelist.c
+++ b/ldap/servers/slapd/getfilelist.c
@@ -38,27 +38,46 @@ struct data_wrapper {
 	const char *dirname;
 };
 
-static int
-add_file_to_list(caddr_t data, caddr_t arg)
-{
-	struct data_wrapper *dw = (struct data_wrapper *)arg;
-	if (dw) {
-		/* max is number of entries; the range of n is 0 - max-1 */
-		PR_ASSERT(dw->n <= dw->max);
-		PR_ASSERT(dw->list);
-		PR_ASSERT(data);
-		/* this strdup is free'd by free_filelist */
-		dw->list[dw->n++] = slapi_ch_smprintf("%s/%s", dw->dirname, data);
-		return 0;
-	}
+struct path_wrapper {
+    char *path;
+    char *filename;
+    int order;
+};
 
-	return -1;
+static int
+path_wrapper_cmp(struct path_wrapper *p1, struct path_wrapper *p2) {
+    if (p1->order < p2->order) {
+        /* p1 is "earlier" so put it first */
+        return -1;
+    }
+    return strcmp(p1->filename, p2->filename);
 }
 
 static void
-free_string(caddr_t data)
+path_wrapper_free(struct path_wrapper *p) {
+    if (p != NULL) {
+        slapi_ch_free((void **)&(p->path));
+        slapi_ch_free((void **)&(p->filename));
+        slapi_ch_free((void **)&p);
+    }
+}
+
+static int
+add_file_to_list(caddr_t data, caddr_t arg)
 {
-	slapi_ch_free((void **)&data);
+    struct data_wrapper *dw = (struct data_wrapper *)arg;
+    struct path_wrapper *pw = (struct path_wrapper *)data;
+    if (dw) {
+        /* max is number of entries; the range of n is 0 - max-1 */
+        PR_ASSERT(dw->n <= dw->max);
+        PR_ASSERT(dw->list);
+        PR_ASSERT(data);
+        /* this strdup is free'd by free_filelist */
+        dw->list[dw->n++] = slapi_ch_strdup(pw->path);
+        return 0;
+    }
+
+    return -1;
 }
 
 static int
@@ -125,68 +144,94 @@ matches(const char *filename, const char *pattern)
  * interpreter style regular expression.  For example, to get all files ending
  * in .ldif, use ".*\\.ldif" instead of "*.ldif"
  * The return value is a NULL terminated array of names.
+ *
+ * This takes an array of directories is order of lowest  to highest pref to
+ * search. So if you have:
+ * a/
+ *   00file
+ *   10file
+ * b/
+ *   05file
+ *   15file
+ * These will be order in preference:
+ * 00file, 10file, 05file, 15file
  */
 char **
 get_filelist(
-	const char *dirname, /* directory path; if NULL, uses "." */
-	const char *pattern, /* grep (not shell!) file pattern regex */
-	int hiddenfiles, /* if true, return hidden files and directories too */
-	int nofiles, /* if true, do not return files */
-	int nodirs /* if true, do not return directories */
+    const char **dirnames, /* list of directory paths; if NULL, uses "." */
+    const char *pattern, /* grep (not shell!) file pattern regex */
+    int hiddenfiles, /* if true, return hidden files and directories too */
+    int nofiles, /* if true, do not return files */
+    int nodirs, /* if true, do not return directories */
+    int dirnames_size /* Size of the dirnames array */
 )
 {
-	Avlnode *filetree = 0;
-	PRDir *dirptr = 0;
-	PRDirEntry *dirent = 0;
-	PRDirFlags dirflags = PR_SKIP_BOTH & PR_SKIP_HIDDEN;
-	char **retval = 0;
-	int num = 0;
-	struct data_wrapper dw;
-
-	if (!dirname)
-		dirname = ".";
-
-	if (hiddenfiles)
-		dirflags = PR_SKIP_BOTH;
-
-	if (!(dirptr = PR_OpenDir(dirname))) {
-		return NULL;
-	}
-
-	/* read the directory entries into an ascii sorted avl tree */
-	for (dirent = PR_ReadDir(dirptr, dirflags); dirent ;
-		 dirent = PR_ReadDir(dirptr, dirflags)) {
-
-		if (nofiles && is_a_file(dirname, dirent->name))
-			continue;
-
-		if (nodirs && is_a_dir(dirname, dirent->name))
-			continue;
-
-		if (1 == matches(dirent->name, pattern)) {
-			/* this strdup is free'd by free_string */
-			char *newone = slapi_ch_strdup(dirent->name);
-			avl_insert(&filetree, newone, strcmp, 0);
-			num++;
-		}
-	}
-	PR_CloseDir(dirptr);
-
-	/* allocate space for the list */
-	retval = (char **)slapi_ch_calloc(num+1, sizeof(char *));
-
-	/* traverse the avl tree and copy the filenames into the list */
-	dw.list = retval;
-	dw.n = 0;
-	dw.max = num;
-	dw.dirname = dirname;
-	(void)avl_apply(filetree, add_file_to_list, &dw, -1, AVL_INORDER);
-	retval[num] = 0; /* set last entry to null */
-
-	/* delete the avl tree and all its data */
-	avl_free(filetree, free_string);
-
-	return retval;
+    Avlnode *filetree = 0;
+    PRDir *dirptr = 0;
+    PRDirEntry *dirent = 0;
+    PRDirFlags dirflags = PR_SKIP_BOTH & PR_SKIP_HIDDEN;
+    char **retval = NULL;
+    const char *dirname = NULL;
+    int num = 0;
+    int i = 0;
+    struct data_wrapper dw;
+    struct path_wrapper *pw_ptr = NULL;
+
+
+    if (hiddenfiles) {
+        dirflags = PR_SKIP_BOTH;
+    }
+
+    for (i = 0; i < dirnames_size; i++) {
+        dirname = dirnames[i];
+        /* wibrown - I feel this is a bad default */
+        if (dirname == NULL) {
+            dirname = ".";
+        }
+        if (!(dirptr = PR_OpenDir(dirname))) {
+            continue;
+        }
+        /* read the directory entries into an ascii sorted avl tree */
+        for (dirent = PR_ReadDir(dirptr, dirflags); dirent ;
+             dirent = PR_ReadDir(dirptr, dirflags)) {
+
+            if (nofiles && is_a_file(dirname, dirent->name))
+                continue;
+
+            if (nodirs && is_a_dir(dirname, dirent->name))
+                continue;
+
+            if (1 == matches(dirent->name, pattern)) {
+                /* this strdup is free'd by path_wrapper_free */
+                pw_ptr =  (struct path_wrapper *)slapi_ch_malloc(sizeof(struct path_wrapper));
+                pw_ptr->path = slapi_ch_smprintf("%s/%s", dirname, dirent->name);
+                pw_ptr->filename = slapi_ch_strdup(dirent->name);
+                pw_ptr->order = i;
+                avl_insert(&filetree, pw_ptr, path_wrapper_cmp, 0);
+                num++;
+            }
+        }
+        PR_CloseDir(dirptr);
+    }
+
+    /* allocate space for the list */
+    if (num > 0) {
+        retval = (char **)slapi_ch_calloc(num+1, sizeof(char *));
+
+        /* traverse the avl tree and copy the filenames into the list */
+        dw.list = retval;
+        dw.n = 0;
+        dw.max = num;
+        dw.dirname = dirname;
+        (void)avl_apply(filetree, add_file_to_list, &dw, -1, AVL_INORDER);
+        retval[num] = 0; /* set last entry to null */
+
+        /* delete the avl tree and all its data */
+    }
+
+    avl_free(filetree, path_wrapper_free);
+
+    return retval;
 }
 
 
@@ -214,7 +259,7 @@ free_filelist(char **filelist)
  * under /etc/rcX.d/
  */
 char **
-get_priority_filelist(const char *directory, const char *pattern)
+get_priority_filelist(const char **directories, const char *pattern, int dirnames_size)
 {
 	char *basepattern = "^[0-9][0-9]";
 	char *genericpattern = ".*"; /* used if pattern is null */
@@ -226,7 +271,7 @@ get_priority_filelist(const char *directory, const char *pattern)
 
 	bigpattern = slapi_ch_smprintf("%s%s", basepattern, pattern);
 
-	retval = get_filelist(directory, bigpattern, 0, 0, 1);
+	retval = get_filelist(directories, bigpattern, 0, 0, 1, dirnames_size);
 
 	slapi_ch_free((void **)&bigpattern);
 
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index f4a5eab..400bfc7 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -1340,14 +1340,15 @@ int plugin_get_log_audit (const struct slapdplugin *plugin);
  * getfilelist.c
  */
 char **get_filelist(
-	const char *dirname, /* directory path; if NULL, uses "." */
-	const char *pattern, /* regex pattern, not shell style wildcard */
-	int hiddenfiles, /* if true, return hidden files and directories too */
-	int nofiles, /* if true, do not return files */
-	int nodirs /* if true, do not return directories */
+    const char **dirnames, /* directory paths; if NULL, uses "." */
+    const char *pattern, /* regex pattern, not shell style wildcard */
+    int hiddenfiles, /* if true, return hidden files and directories too */
+    int nofiles, /* if true, do not return files */
+    int nodirs, /* if true, do not return directories */
+    int dirnames_size
 );
 void free_filelist(char **filelist);
-char **get_priority_filelist(const char *directory, const char *pattern);
+char **get_priority_filelist(const char **directories, const char *pattern, int dirnames_size);
 
 /* this interface is exposed to be used by internal operations. 
  */
diff --git a/ldap/servers/slapd/schema.c b/ldap/servers/slapd/schema.c
index 52c1495..a51a063 100644
--- a/ldap/servers/slapd/schema.c
+++ b/ldap/servers/slapd/schema.c
@@ -5252,6 +5252,8 @@ init_schema_dse_ext(char *schemadir, Slapi_Backend *be,
 	char *userschematmpfile = 0;
 	char **filelist = 0;
 	char *myschemadir = NULL;
+    /* SYSTEMSCHEMADIR is set out of the makefile.am -D, from configure.ac */
+    char *myschemadirs[2] = {SYSTEMSCHEMADIR, NULL};
 	Slapi_DN schema;
 
 	if (NULL == local_pschemadse)
@@ -5276,7 +5278,10 @@ init_schema_dse_ext(char *schemadir, Slapi_Backend *be,
 		myschemadir = schemadir;
 	}
 
-	filelist = get_priority_filelist(myschemadir, ".*ldif$");
+    myschemadirs[1] = myschemadir;
+
+    // Make this take an array of strings?
+	filelist = get_priority_filelist(myschemadirs, ".*ldif$", 2);
 	if (!filelist || !*filelist)
 	{
 		slapi_log_error(SLAPI_LOG_FATAL, "schema",
-- 
2.5.5

