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

/* Object: dbase_file_t (File)
 * Extends: dbase_llist_t (Linked List) 
 * Implements: dbase_t (Database)
 */

struct dbase_file;
typedef struct dbase_file dbase_t;
#define DBASE_DEFINED

#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <stdio_ext.h>
#include "debug.h"
#include "handle.h"
#include "parse_utils.h"
#include "database_file.h"
#include "database_llist.h"
#include "semanage_store.h"

/* FILE dbase */
struct dbase_file {

	/* Parent object - must always be 
	 * the first field - here we are using
	 * a linked list to store the records */
	dbase_llist_t llist;

	/* Backing path for read-only[0] and transaction[1] */
	const char *path[2];

	/* FILE extension */
	record_file_table_t *rftable;
};

static int dbase_file_cache(semanage_handle_t * handle, dbase_file_t * dbase)
{

	record_table_t *rtable = dbase_llist_get_rtable(&dbase->llist);
	record_file_table_t *rftable = dbase->rftable;

	record_t *process_record = NULL;
	int pstatus = STATUS_SUCCESS;

	parse_info_t *parse_info = NULL;
	const char *fname = NULL;

	/* Already cached */
	if (!dbase_llist_needs_resync(handle, &dbase->llist))
		return STATUS_SUCCESS;

	/* Update cache serial */
	dbase_llist_cache_init(&dbase->llist);
	if (dbase_llist_set_serial(handle, &dbase->llist) < 0)
		goto err;

	fname = dbase->path[handle->is_in_transaction];

	if (parse_init(handle, fname, NULL, &parse_info) < 0)
		goto err;

	if (parse_open(handle, parse_info) < 0)
		goto err;

	/* Main processing loop */
	do {

		/* Create record */
		if (rtable->create(handle, &process_record) < 0)
			goto err;

		/* Parse record */
		pstatus = rftable->parse(handle, parse_info, process_record);

		/* Parse error */
		if (pstatus < 0)
			goto err;

		/* End of file */
		else if (pstatus == STATUS_NODATA)
			break;

		/* Prepend to cache */
		if (dbase_llist_cache_prepend(handle, &dbase->llist,
					      process_record) < 0)
			goto err;

		rtable->free(process_record);
		process_record = NULL;

	} while (pstatus != STATUS_NODATA);

	rtable->free(process_record);
	parse_close(parse_info);
	parse_release(parse_info);
	return STATUS_SUCCESS;

      err:
	ERR(handle, "could not cache file database");
	rtable->free(process_record);
	if (parse_info) {
		parse_close(parse_info);
		parse_release(parse_info);
	}
	dbase_llist_drop_cache(&dbase->llist);
	return STATUS_ERR;
}

/* Flush database to file */
static int dbase_file_flush(semanage_handle_t * handle, dbase_file_t * dbase)
{

	record_file_table_t *rftable = dbase->rftable;

	cache_entry_t *ptr;
	const char *fname = NULL;
	FILE *str = NULL;

	if (!dbase_llist_is_modified(&dbase->llist))
		return STATUS_SUCCESS;

	fname = dbase->path[handle->is_in_transaction];

	str = fopen(fname, "w");
	if (!str) {
		ERR(handle, "could not open %s for writing: %s",
		    fname, strerror(errno));
		goto err;
	}
	__fsetlocking(str, FSETLOCKING_BYCALLER);

	if (fprintf(str, "# This file is auto-generated by libsemanage\n"
		    "# Do not edit directly.\n\n") < 0) {

		ERR(handle, "could not write file header for %s", fname);
		goto err;
	}

	for (ptr = dbase->llist.cache_tail; ptr != NULL; ptr = ptr->prev) {
		if (rftable->print(handle, ptr->data, str) < 0)
			goto err;
	}

	dbase_llist_set_modified(&dbase->llist, 0);
	fclose(str);
	return STATUS_SUCCESS;

      err:
	if (str != NULL)
		fclose(str);

	ERR(handle, "could not flush database to file");
	return STATUS_ERR;
}

int dbase_file_init(semanage_handle_t * handle,
		    const char *path_ro,
		    const char *path_rw,
		    record_table_t * rtable,
		    record_file_table_t * rftable, dbase_file_t ** dbase)
{

	dbase_file_t *tmp_dbase = (dbase_file_t *) malloc(sizeof(dbase_file_t));

	if (!tmp_dbase)
		goto omem;

	tmp_dbase->path[0] = path_ro;
	tmp_dbase->path[1] = path_rw;
	tmp_dbase->rftable = rftable;
	dbase_llist_init(&tmp_dbase->llist, rtable, &SEMANAGE_FILE_DTABLE);

	*dbase = tmp_dbase;

	return STATUS_SUCCESS;

      omem:
	ERR(handle, "out of memory, could not initialize file database");
	free(tmp_dbase);
	return STATUS_ERR;
}

/* Release dbase resources */
void dbase_file_release(dbase_file_t * dbase)
{

	dbase_llist_drop_cache(&dbase->llist);
	free(dbase);
}

/* FILE dbase - method table implementation */
dbase_table_t SEMANAGE_FILE_DTABLE = {

	/* Cache/Transactions */
	.cache = dbase_file_cache,
	.drop_cache = (void *)dbase_llist_drop_cache,
	.flush = dbase_file_flush,
	.is_modified = (void *)dbase_llist_is_modified,

	/* Database API */
	.iterate = (void *)dbase_llist_iterate,
	.exists = (void *)dbase_llist_exists,
	.list = (void *)dbase_llist_list,
	.add = (void *)dbase_llist_add,
	.set = (void *)dbase_llist_set,
	.del = (void *)dbase_llist_del,
	.clear = (void *)dbase_llist_clear,
	.modify = (void *)dbase_llist_modify,
	.query = (void *)dbase_llist_query,
	.count = (void *)dbase_llist_count,

	/* Polymorphism */
	.get_rtable = (void *)dbase_llist_get_rtable
};
