diff options
Diffstat (limited to 'support/export/export.c')
-rw-r--r-- | support/export/export.c | 259 |
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 ⅇ + } + /* 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'; +} |