/*
 * support/export/export.c
 *
 * Maintain list of exported file systems.
 *
 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#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"

exp_hash_table exportlist[MCL_MAXTYPES] = {{NULL, {{NULL,NULL}, }}, }; 
static int export_hash(char *);

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);

static void warn_duplicated_exports(nfs_export *exp, struct exportent *eep)
{
	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);
	}
}

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
			warn_duplicated_exports(exp, eep);
	}
	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);
	if (nep->e_hostname)
		e->e_hostname = xstrdup(nep->e_hostname);

	exp->m_exported = 0;
	exp->m_xtabent = 0;
	exp->m_mayexport = 0;
	exp->m_changed = 0;
	exp->m_warned = 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);
	if (exp->m_export.e_hostname)
		new->m_export.e_hostname = xstrdup(exp->m_export.e_hostname);
	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;
	new->m_warned = 0;
	export_add(new);

	return new;
}
/*
 * Add export entry to hash table
 */
void 
export_add(nfs_export *exp)
{
	exp_hash_table *p_tbl;
	exp_hash_entry *p_hen;
	nfs_export *p_next;

	int type = exp->m_client->m_type;
	int pos;

	pos = export_hash(exp->m_export.e_path);
	p_tbl = &(exportlist[type]); /* pointer to hash table */
	p_hen = &(p_tbl->entries[pos]); /* pointer to hash table entry */

	if (!(p_hen->p_first)) { /* hash table entry is empty */ 
 		p_hen->p_first = exp;
 		p_hen->p_last  = exp;

 		exp->m_next = p_tbl->p_head;
 		p_tbl->p_head = exp;
	} else { /* hash table entry is NOT empty */
		p_next = p_hen->p_last->m_next;
		p_hen->p_last->m_next = exp;
		exp->m_next = p_next;
		p_hen->p_last = 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].p_head; 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].p_head; 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;
}

/*
 * Search hash table for export entry. 
 */  
nfs_export *
export_lookup(char *hname, char *path, int canonical) 
{
	nfs_client *clp;
	nfs_export *exp;
	exp_hash_entry *p_hen;

	int pos;

	clp = client_lookup(hname, canonical);
	if(clp == NULL)
		return NULL;

	pos = export_hash(path);
	p_hen = &(exportlist[clp->m_type].entries[pos]); 
	for(exp = p_hen->p_first; exp && (exp != p_hen->p_last->m_next); 
  			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, j;

	for (i = 0; i < MCL_MAXTYPES; i++) {
		for (exp = exportlist[i].p_head; 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);
			if (exp->m_export.e_fslocdata)
				xfree(exp->m_export.e_fslocdata);
			xfree(exp->m_export.e_hostname);
			xfree(exp);
		}
      for(j = 0; j < HASH_TABLE_SIZE; j++) {
        exportlist[i].entries[j].p_first = NULL;
        exportlist[i].entries[j].p_last = NULL;
      }
      exportlist[i].p_head = NULL;
	}
	client_freeall();
}

/*
 * Compute and returns integer from string. 
 * Note: Its understood the smae integers can be same for 
 *       different strings, but it should not matter.
 */
static unsigned int 
strtoint(char *str)
{
	int i = 0;
	unsigned int n = 0;

	while ( str[i] != '\0') {
		n+=((int)str[i])*i;
		i++;
	}
	return n;
}

/*
 * Hash function
 */
static int 
export_hash(char *str)
{
	int num = strtoint(str);

	return num % HASH_TABLE_SIZE;
}
