/*
 * sysdb.c  -  System database routines for mknbi-dos
 *
 * Copyright (C) 2005-2007 Gero Kuhlmann   <gero@gkminix.han.de>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * $Id: sysdb.c,v 1.8 2007/01/06 18:31:22 gkminix Exp $
 */

#include <common.h>
#include <nblib.h>
#include "mknbi.h"
#include "headers/fat.h"

#ifndef MKNBI_H_DOS
#error Included wrong header file
#endif


static struct sysdef dbdata;		/* Buffer for database data */




/*
 **************************************************************************
 *
 *		Process keep flag string
 *
 **************************************************************************
 */

/*
 * Values for keep command line option
 */
static struct enumdef ktypes[] = {
  { "none",	KEEP_NONE },
  { "all",	KEEP_ALL },
  { "undi",	KEEP_UNDI },
  { NULL,	KEEP_MISSING }
};



/*
 * Convert a string into a ramdisk load mode
 */
char *getkeepflag __F((keepstr, sysentry),
				const char *keepstr AND
				struct sysdef *sysentry)
{
  int i, newflag = KEEP_MISSING;

  if (keepstr != NULL) {
	for (i = 0; ktypes[i].enumstr != NULL; i++)
		if (!strcmp(ktypes[i].enumstr, keepstr)) {
			newflag = ktypes[i].val;
			break;
		}
	if (newflag == KEEP_MISSING)
		return("invalid keep argument");
  }
  sysentry->keepflag = newflag;
  return(NULL);
}




/*
 **************************************************************************
 *
 *		Read a systems database entry
 *
 **************************************************************************
 */

/*
 * Parameters in each section of database file
 */
static struct paramdef dbparams[] = {
  { "volume-name",	par_string,	NULL,	{&dbdata.volumename}},
  { "outfile",	 	par_file,	NULL,	{&dbdata.outname}},
  { "ramdisk-image", 	par_file,	NULL,	{&dbdata.rdname}},
  { "ramdisk-size",	par_int,	NULL,	{&dbdata.rdsize}},
  { "no-hard-disk",	par_bool,	NULL,	{&dbdata.nohd}},
  { "no-rpl",		par_bool,	NULL,	{&dbdata.norpl}},
  { "use-int-15",	par_bool,	NULL,	{&dbdata.useint15}},
  { "single-fat",	par_bool,	NULL,	{&dbdata.singlefat}},
  { "simulate-hd",	par_bool,	NULL,	{&dbdata.usehd}},
  { "compress",		par_bool,	NULL,	{&dbdata.compress}},
  { "keep",		par_enum,	ktypes,	{&dbdata.keepflag}},
  { NULL,	 	par_null,	NULL,	{NULL}}
};



/*
 * Copy a string from the database entry into the systems entry
 */
static inline void copyentry __F((sysentry, dbentry),
				char **sysentry AND
				char **dbentry)
{
  if (*dbentry != NULL) {
	if (*sysentry == NULL && **dbentry != '\0')
		*sysentry = *dbentry;
	else
		free(*dbentry);
	*dbentry = NULL;
  }
}



/*
 * Read system database
 */
void getdb __F((name, sysentry),
				const char *name AND
				struct sysdef *sysentry)
{
  char *namebuf;

  /* Read one entry from database file */
  namebuf = (char *)nbmalloc(strlen(name) + strlen(DBSECTNAME) + 2);
  sprintf(namebuf, "%s:%s", DBSECTNAME, name);
  memzero(&dbdata, sizeof(dbdata));
  dbdata.keepflag = KEEP_MISSING;
  if (!opensysdb(TRUE))
	nbexit(-1);
  if (!readsysdb(namebuf, dbparams))
	nbexit(-1);
  closesysdb();

  /* Check that parameters are correct */
  if (dbdata.rdsize > MAX_RDSIZE) {
	prnerr("ramdisk size must be < %d kB in section <%s>",
							MAX_RDSIZE, namebuf);
	nbexit(EXIT_DB);
  }
  if ((dbdata.volumename != NULL) &&
      ((int)strlen(dbdata.volumename) > MAX_VOLNAME_LEN)) {
	prnerr("volume name too long in section <%s>", namebuf);
	nbexit(EXIT_DB);
  }
  if (dbdata.usehd && dbdata.nohd) {
	prnerr("can't use 'simulate-hd' and 'no-hard-disk' "
				"simultaneously in section <%s>", namebuf);
	nbexit(EXIT_DB);
  }
#ifndef HAVE_LZO
  if (dbdata.compress) {
	prnerr("ramdisk compression not supported - option ignored");
	dbdata.compress = FALSE;
  }
#endif

  /* Copy database data into systems entry */
  copyentry(&(sysentry->outname), &(dbdata.outname));
  copyentry(&(sysentry->rdname), &(dbdata.rdname));
  copyentry(&(sysentry->volumename), &(dbdata.volumename));
  if ((dbdata.usehd || dbdata.nohd) && !(sysentry->usehd || sysentry->nohd)) {
	sysentry->usehd = dbdata.usehd;
	sysentry->nohd = dbdata.nohd;
  }
  if (dbdata.rdsize > 0 && sysentry->rdsize == 0)
	sysentry->rdsize = dbdata.rdsize;
  if (dbdata.norpl && !sysentry->norpl)
	sysentry->norpl = dbdata.norpl;
  if (dbdata.useint15 && !sysentry->useint15)
	sysentry->useint15 = dbdata.useint15;
  if (dbdata.singlefat && !sysentry->singlefat)
	sysentry->singlefat = dbdata.singlefat;
  if (dbdata.compress && !sysentry->compress)
	sysentry->compress = dbdata.compress;
  if (dbdata.keepflag != KEEP_MISSING && sysentry->keepflag == KEEP_MISSING)
	sysentry->keepflag = dbdata.keepflag;

  /* Check for missing parameters */
  if (sysentry->rdname == NULL) {
	prnerr("need ramdisk image file or directory name in section <%s>",
								namebuf);
	nbexit(EXIT_DB);
  }
  if (sysentry->outname == NULL) {
	prnerr("need output file name in section <%s>", namebuf);
	nbexit(EXIT_DB);
  }
  free(namebuf);
}



/*
 * Write one entry into the database file
 */
void putdb __F((name, sysentry),
				const char *name AND
				struct sysdef *sysentry)
{
  char *sectname;
  int len;

  /* Check if we have something to write at all */
  if (name == NULL || (len = strlen(name)) == 0)
	return;

  /* Copy the boot definition into our own static data area */
  if (sysentry != &dbdata)
	dbdata = *sysentry;

  /* Generate section name */
  sectname = (char *)nbmalloc(len + strlen(DBSECTNAME) + 3);
  sprintf(sectname, "%s:%s", DBSECTNAME, name);

  /* Write section into database */
  if (!opensysdb(FALSE))
	nbexit(-1);
  if (!writesysdb(sectname, dbparams))
	nbexit(-1);
  closesysdb();
  free(sectname);
}

