+static int is_subdirectory(char *child, char *parent)
+{
+ int l = strlen(parent);
+
+ return strcmp(child, parent) == 0
+ || (strncmp(child, parent, l) == 0 && child[l] == '/');
+}
+
+static int path_matches(nfs_export *exp, char *path)
+{
+ if (exp->m_export.e_flags & NFSEXP_CROSSMOUNT)
+ return is_subdirectory(path, exp->m_export.e_path);
+ return strcmp(path, exp->m_export.e_path) == 0;
+}
+
+static int
+client_matches(nfs_export *exp, char *dom, struct addrinfo *ai)
+{
+ if (use_ipaddr)
+ return client_check(exp->m_client, ai);
+ return client_member(dom, exp->m_client->m_hostname);
+}
+
+static int
+export_matches(nfs_export *exp, char *dom, char *path, struct addrinfo *ai)
+{
+ return path_matches(exp, path) && client_matches(exp, dom, ai);
+}
+
+static nfs_export *
+lookup_export(char *dom, char *path, struct addrinfo *ai)
+{
+ nfs_export *exp;
+ nfs_export *found = NULL;
+ int found_type = 0;
+ int i;
+
+ for (i=0 ; i < MCL_MAXTYPES; i++) {
+ for (exp = exportlist[i].p_head; exp; exp = exp->m_next) {
+ if (!export_matches(exp, dom, path, ai))
+ continue;
+ if (!found) {
+ found = exp;
+ found_type = i;
+ continue;
+ }
+
+ /* Always prefer non-V4ROOT mounts */
+ if (found->m_export.e_flags & NFSEXP_V4ROOT)
+ continue;
+
+ /* If one is a CROSSMOUNT, then prefer the longest path */
+ if (((found->m_export.e_flags & NFSEXP_CROSSMOUNT) ||
+ (exp->m_export.e_flags & NFSEXP_CROSSMOUNT)) &&
+ strlen(found->m_export.e_path) !=
+ strlen(exp->m_export.e_path)) {
+
+ if (strlen(exp->m_export.e_path) >
+ strlen(found->m_export.e_path)) {
+ found = exp;
+ found_type = i;
+ }
+ continue;
+
+ } else if (found_type == i && found->m_warned == 0) {
+ xlog(L_WARNING, "%s exported to both %s and %s, "
+ "arbitrarily choosing options from first",
+ path, found->m_client->m_hostname, exp->m_client->m_hostname,
+ dom);
+ found->m_warned = 1;
+ }
+ }
+ }
+ return found;
+}
+
+static void nfsd_export(FILE *f)