/* * support/export/export.c * * Maintain list of exported file systems. * * Copyright (C) 1995, 1996 Olaf Kirch */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #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(0,1)) != NULL) { exp = export_lookup(eep->e_hostname, eep->e_path, 0); if (!exp) export_create(eep,0); else { if (exp->m_export.e_flags != eep->e_flags) { xlog(L_ERROR, "incompatible duplicated 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, "duplicated 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, int canonical) { nfs_client *clp; nfs_export *exp; if (!(clp = client_lookup(xep->e_hostname, canonical))) { /* 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; } nfs_export * export_allowed(struct hostent *hp, char *path) { 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) return exp; /* 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, int canonical) { nfs_client *clp; nfs_export *exp; if (!(clp = client_lookup(hname, canonical))) 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); if (exp->m_export.e_mountpoint) free(exp->m_export.e_mountpoint); 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'; }