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

struct semanage_fcontext;
struct semanage_fcontext_key;
typedef struct semanage_fcontext_key record_key_t;
typedef struct semanage_fcontext record_t;
#define DBASE_RECORD_DEFINED

#include <stdlib.h>
#include <sepol/policydb.h>
#include <sepol/context.h>
#include "fcontext_internal.h"
#include "context_internal.h"
#include "debug.h"
#include "handle.h"
#include "database.h"

int semanage_fcontext_modify_local(semanage_handle_t * handle,
				   const semanage_fcontext_key_t * key,
				   const semanage_fcontext_t * data)
{

	dbase_config_t *dconfig = semanage_fcontext_dbase_local(handle);
	return dbase_modify(handle, dconfig, key, data);
}

int semanage_fcontext_del_local(semanage_handle_t * handle,
				const semanage_fcontext_key_t * key)
{

	dbase_config_t *dconfig = semanage_fcontext_dbase_local(handle);
	return dbase_del(handle, dconfig, key);
}

int semanage_fcontext_query_local(semanage_handle_t * handle,
				  const semanage_fcontext_key_t * key,
				  semanage_fcontext_t ** response)
{

	dbase_config_t *dconfig = semanage_fcontext_dbase_local(handle);
	return dbase_query(handle, dconfig, key, response);
}

int semanage_fcontext_exists_local(semanage_handle_t * handle,
				   const semanage_fcontext_key_t * key,
				   int *response)
{

	dbase_config_t *dconfig = semanage_fcontext_dbase_local(handle);
	return dbase_exists(handle, dconfig, key, response);
}

int semanage_fcontext_count_local(semanage_handle_t * handle,
				  unsigned int *response)
{

	dbase_config_t *dconfig = semanage_fcontext_dbase_local(handle);
	return dbase_count(handle, dconfig, response);
}

int semanage_fcontext_iterate_local(semanage_handle_t * handle,
				    int (*handler) (const semanage_fcontext_t *
						    record, void *varg),
				    void *handler_arg)
{

	dbase_config_t *dconfig = semanage_fcontext_dbase_local(handle);
	return dbase_iterate(handle, dconfig, handler, handler_arg);
}

hidden_def(semanage_fcontext_iterate_local)

int semanage_fcontext_list_local(semanage_handle_t * handle,
				 semanage_fcontext_t *** records,
				 unsigned int *count)
{

	dbase_config_t *dconfig = semanage_fcontext_dbase_local(handle);
	return dbase_list(handle, dconfig, records, count);
}

struct validate_handler_arg {
	semanage_handle_t *handle;
	const sepol_policydb_t *policydb;
};

static int validate_handler(const semanage_fcontext_t * fcon, void *varg)
{

	char *str;

	/* Unpack varg */
	struct validate_handler_arg *arg = (struct validate_handler_arg *)varg;
	semanage_handle_t *handle = arg->handle;
	const sepol_policydb_t *policydb = arg->policydb;

	/* Unpack fcontext */
	const char *expr = semanage_fcontext_get_expr(fcon);
	int type = semanage_fcontext_get_type(fcon);
	const char *type_str = semanage_fcontext_get_type_str(type);
	semanage_context_t *con = semanage_fcontext_get_con(fcon);

	if (con
	    && sepol_context_check(handle->sepolh, policydb,
				   (sepol_context_t *) con) < 0)
		goto invalid;

	return 0;

      invalid:
	if (semanage_context_to_string(handle, con, &str) >= 0) {
		ERR(handle, "invalid context %s specified for %s [%s]",
		    str, expr, type_str);
		free(str);
	} else
		ERR(handle, "invalid context specified for %s [%s]",
		    expr, type_str);
	return -1;
}

int hidden semanage_fcontext_validate_local(semanage_handle_t * handle,
					    const sepol_policydb_t * policydb)
{

	struct validate_handler_arg arg;
	arg.handle = handle;
	arg.policydb = policydb;
	return semanage_fcontext_iterate_local(handle, validate_handler, &arg);
}