summaryrefslogtreecommitdiffstats
path: root/support/export/export.c
diff options
context:
space:
mode:
Diffstat (limited to 'support/export/export.c')
-rw-r--r--support/export/export.c259
1 files changed, 259 insertions, 0 deletions
diff --git a/support/export/export.c b/support/export/export.c
new file mode 100644
index 0000000..09efaa8
--- /dev/null
+++ b/support/export/export.c
@@ -0,0 +1,259 @@
+/*
+ * support/export/export.c
+ *
+ * Maintain list of exported file systems.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <stdlib.h>
+#include "xmalloc.h"
+#include "nfslib.h"
+#include "exportfs.h"
+
+nfs_export *exportlist[MCL_MAXTYPES] = { NULL, };
+
+static void export_init(nfs_export *exp, nfs_client *clp,
+ struct exportent *nep);
+static int export_check(nfs_export *, struct hostent *, char *);
+static nfs_export *
+ export_allowed_internal(struct hostent *hp, char *path);
+
+int
+export_read(char *fname)
+{
+ struct exportent *eep;
+ nfs_export *exp;
+
+ setexportent(fname, "r");
+ while ((eep = getexportent()) != NULL) {
+ exp = export_lookup(eep->e_hostname, eep->e_path);
+ if (!exp)
+ export_create(eep);
+ else {
+ if (exp->m_export.e_flags != eep->e_flags) {
+ xlog(L_ERROR, "incompatible dupilcated export entries:");
+ xlog(L_ERROR, "\t%s:%s (0x%x) [IGNORED]", eep->e_hostname,
+ eep->e_path, eep->e_flags);
+ xlog(L_ERROR, "\t%s:%s (0x%x)", exp->m_export.e_hostname,
+ exp->m_export.e_path, exp->m_export.e_flags);
+ }
+ else {
+ xlog(L_ERROR, "dupilcated export entries:");
+ xlog(L_ERROR, "\t%s:%s", eep->e_hostname, eep->e_path);
+ xlog(L_ERROR, "\t%s:%s", exp->m_export.e_hostname,
+ exp->m_export.e_path);
+ }
+ }
+ }
+ endexportent();
+
+ return 0;
+}
+
+/*
+ * Create an in-core export struct from an export entry.
+ */
+nfs_export *
+export_create(struct exportent *xep)
+{
+ nfs_client *clp;
+ nfs_export *exp;
+
+ if (!(clp = client_lookup(xep->e_hostname))) {
+ /* bad export entry; complaint already logged */
+ return NULL;
+ }
+ exp = (nfs_export *) xmalloc(sizeof(*exp));
+ export_init(exp, clp, xep);
+ export_add(exp);
+
+ return exp;
+}
+
+static void
+export_init(nfs_export *exp, nfs_client *clp, struct exportent *nep)
+{
+ struct exportent *e = &exp->m_export;
+
+ dupexportent(e, nep);
+
+ exp->m_exported = 0;
+ exp->m_xtabent = 0;
+ exp->m_mayexport = 0;
+ exp->m_changed = 0;
+ exp->m_client = clp;
+ clp->m_count++;
+}
+
+/*
+ * Duplicate exports data. The in-core export struct retains the
+ * original hostname from /etc/exports, while the in-core client struct
+ * gets the newly found FQDN.
+ */
+nfs_export *
+export_dup(nfs_export *exp, struct hostent *hp)
+{
+ nfs_export *new;
+ nfs_client *clp;
+
+ new = (nfs_export *) xmalloc(sizeof(*new));
+ memcpy(new, exp, sizeof(*new));
+ dupexportent(&new->m_export, &exp->m_export);
+ clp = client_dup(exp->m_client, hp);
+ clp->m_count++;
+ new->m_client = clp;
+ new->m_mayexport = exp->m_mayexport;
+ new->m_exported = 0;
+ new->m_xtabent = 0;
+ new->m_changed = 0;
+ export_add(new);
+
+ return new;
+}
+
+void
+export_add(nfs_export *exp)
+{
+ nfs_export **epp;
+ int type = exp->m_client->m_type;
+ int slen = strlen(exp->m_export.e_path);
+
+ if (type < 0 || type >= MCL_MAXTYPES)
+ xlog(L_FATAL, "unknown client type in export_add");
+
+ epp = exportlist + type;
+ while (*epp && slen < strlen((*epp)->m_export.e_path))
+ epp = &((*epp)->m_next);
+ exp->m_next = *epp;
+ *epp = exp;
+}
+
+nfs_export *
+export_find(struct hostent *hp, char *path)
+{
+ nfs_export *exp;
+ int i;
+
+ for (i = 0; i < MCL_MAXTYPES; i++) {
+ for (exp = exportlist[i]; exp; exp = exp->m_next) {
+ if (!export_check(exp, hp, path))
+ continue;
+ if (exp->m_client->m_type == MCL_FQDN)
+ return exp;
+ return export_dup(exp, hp);
+ }
+ }
+
+ return NULL;
+}
+
+static nfs_export *
+export_allowed_internal (struct hostent *hp, char *path)
+{
+ nfs_export *exp;
+ int i;
+
+ for (i = 0; i < MCL_MAXTYPES; i++) {
+ for (exp = exportlist[i]; exp; exp = exp->m_next) {
+ if (!exp->m_mayexport ||
+ !export_check(exp, hp, path))
+ continue;
+ return exp;
+ }
+ }
+
+ return NULL;
+}
+
+struct exportent *
+export_allowed(struct hostent *hp, char *path)
+{
+ static struct exportent ee;
+ nfs_export *exp;
+ char epath[MAXPATHLEN+1];
+ char *p = NULL;
+
+ if (path [0] != '/') return NULL;
+
+ strncpy(epath, path, sizeof (epath) - 1);
+ epath[sizeof (epath) - 1] = '\0';
+
+ /* Try the longest matching exported pathname. */
+ while (1) {
+ exp = export_allowed_internal (hp, epath);
+ if (exp) {
+ dupexportent(&ee, &exp->m_export);
+ return &ee;
+ }
+ /* We have to treat the root, "/", specially. */
+ if (p == &epath[1]) break;
+ p = strrchr(epath, '/');
+ if (p == epath) p++;
+ *p = '\0';
+ }
+
+ return NULL;
+}
+
+nfs_export *
+export_lookup(char *hname, char *path)
+{
+ nfs_client *clp;
+ nfs_export *exp;
+
+ if (!(clp = client_lookup(hname)))
+ return NULL;
+ for (exp = exportlist[clp->m_type]; exp; exp = exp->m_next)
+ if (exp->m_client == clp && !strcmp(exp->m_export.e_path, path))
+ return exp;
+ return NULL;
+}
+
+static int
+export_check(nfs_export *exp, struct hostent *hp, char *path)
+{
+ if (strcmp(path, exp->m_export.e_path))
+ return 0;
+
+ return client_check(exp->m_client, hp);
+}
+
+void
+export_freeall(void)
+{
+ nfs_export *exp, *nxt;
+ int i;
+
+ for (i = 0; i < MCL_MAXTYPES; i++) {
+ for (exp = exportlist[i]; exp; exp = nxt) {
+ nxt = exp->m_next;
+ client_release(exp->m_client);
+ if (exp->m_export.e_squids)
+ xfree(exp->m_export.e_squids);
+ if (exp->m_export.e_sqgids)
+ xfree(exp->m_export.e_sqgids);
+ xfree(exp);
+ }
+ exportlist[i] = NULL;
+ }
+ client_freeall();
+}
+
+void
+export_reset(nfs_export *exp)
+{
+ if (!exp)
+ return;
+
+ /* Restore m_path. */
+ strncpy(exp->m_export.m_path, exp->m_export.e_path,
+ sizeof (exp->m_export.m_path) - 1);
+ exp->m_export.m_path[sizeof (exp->m_export.m_path) - 1] = '\0';
+}