/* Copyright (C) 2005 Red Hat, Inc. */

#include <stdlib.h>
#include "policy.h"
#include "handle.h"
#include "database.h"
#include "modules.h"
#include "debug.h"

/* Powers of two only */
#define MODE_SET    1
#define MODE_MODIFY 2
#define MODE_SORT   4

static int clear_obsolete(semanage_handle_t * handle,
			  record_t ** records,
			  unsigned int nrecords,
			  dbase_config_t * src, dbase_config_t * dst)
{

	record_key_t *key = NULL;
	unsigned int i;

	dbase_table_t *src_dtable = src->dtable;
	dbase_table_t *dst_dtable = dst->dtable;
	record_table_t *rtable = src_dtable->get_rtable(src->dbase);

	for (i = 0; i < nrecords; i++) {
		int exists;

		if (rtable->key_extract(handle, records[i], &key) < 0)
			goto err;

		if (dst_dtable->exists(handle, dst->dbase, key, &exists) < 0)
			goto err;

		if (!exists) {
			if (src_dtable->del(handle, src->dbase, key) < 0)
				goto err;

			rtable->free(records[i]);
			records[i] = NULL;

			/* FIXME: notice to user */
			/* INFO(handle, "boolean %s is obsolete, unsetting configured value..."); */
		}

		rtable->key_free(key);
	}

	return STATUS_SUCCESS;

      err:
	/* FIXME: handle error */
	rtable->key_free(key);
	return STATUS_ERR;
}

static int load_records(semanage_handle_t * handle,
			dbase_config_t * dst,
			record_t ** records, unsigned int nrecords, int mode)
{

	unsigned int i;
	record_key_t *rkey = NULL;

	dbase_t *dbase = dst->dbase;
	dbase_table_t *dtable = dst->dtable;
	record_table_t *rtable = dtable->get_rtable(dbase);

	for (i = 0; i < nrecords; i++) {

		/* Possibly obsoleted */
		if (!records[i])
			continue;

		if (rtable->key_extract(handle, records[i], &rkey) < 0)
			goto err;

		if (mode & MODE_SET &&
		    dtable->set(handle, dbase, rkey, records[i]) < 0)
			goto err;

		else if (mode & MODE_MODIFY &&
			 dtable->modify(handle, dbase, rkey, records[i]) < 0)
			goto err;

		rtable->key_free(rkey);
	}

	return STATUS_SUCCESS;

      err:
	/* FIXME: handle error */
	rtable->key_free(rkey);
	return STATUS_ERR;
}

typedef struct load_table {
	dbase_config_t *src;
	dbase_config_t *dst;
	int mode;
} load_table_t;

/* This function must be called AFTER all modules are loaded.
 * Modules could be represented as a database, in which case
 * they should be loaded at the beginning of this function */

int semanage_base_merge_components(semanage_handle_t * handle)
{

	unsigned int i, j;
	int rc = STATUS_SUCCESS;

	/* Order is important here - change things carefully.
	 * System components first, local next. Verify runs with 
	 * mutual dependencies are ran after everything is merged */
	load_table_t components[] = {

		{semanage_user_base_dbase_local(handle),
		 semanage_user_base_dbase_policy(handle), MODE_MODIFY},

		{semanage_user_extra_dbase_local(handle),
		 semanage_user_extra_dbase_policy(handle), MODE_MODIFY},

		{semanage_port_dbase_local(handle),
		 semanage_port_dbase_policy(handle), MODE_MODIFY},

		{semanage_iface_dbase_local(handle),
		 semanage_iface_dbase_policy(handle), MODE_MODIFY},

		{semanage_bool_dbase_local(handle),
		 semanage_bool_dbase_policy(handle), MODE_SET},

		{semanage_seuser_dbase_local(handle),
		 semanage_seuser_dbase_policy(handle), MODE_MODIFY},

		{semanage_node_dbase_local(handle),
		 semanage_node_dbase_policy(handle), MODE_MODIFY | MODE_SORT},

		{semanage_ibpkey_dbase_local(handle),
		 semanage_ibpkey_dbase_policy(handle), MODE_MODIFY},

		{semanage_ibendport_dbase_local(handle),
		 semanage_ibendport_dbase_policy(handle), MODE_MODIFY},
	};
	const unsigned int CCOUNT = sizeof(components) / sizeof(components[0]);

	/* Merge components into policy (and validate) */
	for (i = 0; i < CCOUNT; i++) {
		record_t **records = NULL;
		unsigned int nrecords = 0;

		dbase_config_t *src = components[i].src;
		dbase_config_t *dst = components[i].dst;
		int mode = components[i].mode;
		record_table_t *rtable = src->dtable->get_rtable(src->dbase);

		/* Must invoke cache function first */
		if (src->dtable->cache(handle, src->dbase) < 0)
			goto err;
		if (dst->dtable->cache(handle, dst->dbase) < 0)
			goto err;

		/* List all records */
		if (src->dtable->list(handle, src->dbase,
				      &records, &nrecords) < 0)
			goto err;

		/* Sort records on MODE_SORT */
		if (mode & MODE_SORT) {
			qsort(records, nrecords, sizeof(record_t *),
			      (int (*)(const void *, const void *))rtable->
			      compare2_qsort);
		}

		/* Clear obsolete ones for MODE_SET */
		if (mode & MODE_SET &&
		    clear_obsolete(handle, records, nrecords, src, dst) < 0) {
			rc = STATUS_ERR;
			goto dbase_exit;
		}

		/* Load records */
		if (load_records(handle, dst, records, nrecords, mode) < 0) {

			rc = STATUS_ERR;
			goto dbase_exit;
		}

		/* Cleanup */
	      dbase_exit:
		for (j = 0; j < nrecords; j++)
			rtable->free(records[j]);
		free(records);

		/* Abort on error */
		if (rc < 0)
			goto err;
	}

	return rc;

      err:
	ERR(handle, "could not merge local modifications into policy");
	return STATUS_ERR;
}

int semanage_commit_components(semanage_handle_t * handle)
{

	int i;
	dbase_config_t *components[] = {
		semanage_iface_dbase_local(handle),
		semanage_bool_dbase_local(handle),
		semanage_user_base_dbase_local(handle),
		semanage_user_extra_dbase_local(handle),
		semanage_user_extra_dbase_policy(handle),
		semanage_port_dbase_local(handle),
		semanage_fcontext_dbase_local(handle),
		semanage_fcontext_dbase_policy(handle),
		semanage_seuser_dbase_local(handle),
		semanage_seuser_dbase_policy(handle),
		semanage_bool_dbase_active(handle),
		semanage_node_dbase_local(handle),
		semanage_ibpkey_dbase_local(handle),
		semanage_ibendport_dbase_local(handle),
	};
	const int CCOUNT = sizeof(components) / sizeof(components[0]);

	for (i = 0; i < CCOUNT; i++) {
		/* Flush to disk */
		if (components[i]->dtable->flush(handle, components[i]->dbase) <
		    0)
			goto err;
	}

	return STATUS_SUCCESS;

      err:
	ERR(handle, "could not commit local/active modifications");

	for (i = 0; i < CCOUNT; i++)
		components[i]->dtable->drop_cache(components[i]->dbase);
	return STATUS_ERR;
}
