/* Copyright (c) 1999 Thorsten Kukuk
   Author: Thorsten Kukuk <kukuk@suse.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, or (at your option)
   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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <errno.h>
#include <unistd.h>

#include "nis_db.h"
#include "db_private.h"

/* We could get problems with this function, if closing a file
   handle twice is a real error. xdr_destroy could close the file handle,
   and we do it with fclose, too. */
db_status
__load_entries (table_t *tobj)
{
  XDR xdrs;
  FILE *fp;
  int free_header = 0, free_header_log = 0;
  xdb_header header, header_log;
  db_status retval = DB_SUCCESS;

  /* If we have a data file, load the header and entries */
  if (access (tobj->name, R_OK|W_OK) >= 0)
    {
      fp = fopen (tobj->path, "rb+");
      if (fp == NULL)
	return DB_INTERNAL_ERROR;
      __close_on_exit (&fp);

      memset (&header, 0, sizeof (xdb_header));
      xdrstdio_create (&xdrs, fp, XDR_DECODE);
      if (!xdr_xdb_header (&xdrs, &header))
	{
	  xdr_destroy (&xdrs);
	  fclose (fp);
	  return DB_INTERNAL_ERROR;
	}

      free_header = 1;

      if (header.vers != XDB_VERSION ||
	  strncmp (header.identifier, XDB_VER_STRING,
		   strlen (XDB_VER_STRING)) != 0 || header.type != XDB_FILE)
	{
	  xdr_destroy (&xdrs);
	  retval = DB_INTERNAL_ERROR;
	  goto bailout2;
	}

      /* XXX Read all the entries here */

      xdr_destroy (&xdrs);
    }
  else
    {
      if (errno != ENOENT)
	return DB_INTERNAL_ERROR; /* Seems we don't have permissions
				     to access it */
      else
	header.log_present = TRUE; /* We must have an log file */
    }

  if (header.log_present)
    { /* We have a log file flag */
      tobj->fp_log = fopen (tobj->path_log, "rb+");
      if (tobj->fp_log == NULL)
	return DB_INTERNAL_ERROR;
      __close_on_exit (&tobj->fp_log);

      /* Read the header of the log file */
      memset (&header_log, 0, sizeof (xdb_header));
      xdrstdio_create (&xdrs, tobj->fp_log, XDR_DECODE);
      if (!xdr_xdb_header (&xdrs, &header_log))
	{
	  xdr_destroy (&xdrs);
	  fclose (tobj->fp_log);
	  tobj->fp_log = NULL;
	  retval = DB_INTERNAL_ERROR;
	  goto bailout2;
	}

      free_header_log = 1;

      if (header_log.vers != XDB_VERSION ||
	  strncmp (header_log.identifier, XDB_VER_STRING,
		   strlen (XDB_VER_STRING)) != 0 ||
	  header_log.type != XDB_LOG)
	{
	  xdr_destroy (&xdrs);
	  fclose (tobj->fp_log);
	  tobj->fp_log = NULL;
	  retval = DB_INTERNAL_ERROR;
	  goto bailout;
	}

      while (!feof (tobj->fp_log))
	{ /* Read the logfile here */
	  xdb_logaction action;

	  memset (&action, 0, sizeof (xdb_logaction));
	  if (!xdr_xdb_logaction (&xdrs, &action))
	    {
	      if (feof (tobj->fp_log))
		break;
	      fclose (tobj->fp_log);
	      tobj->fp_log = NULL;
	      xdr_destroy (&xdrs);
	      retval = DB_INTERNAL_ERROR;
	      goto bailout;
	    }

	  switch (action)
	    {
	    case LOG_ADD:
	      break;
	    case LOG_DELETE:
	      break;
	    case LOG_IGNORE:
	      break;
	    default:
	      /* Logfile is broken. Maybe need external tool for
		 repairing it ? */
	      xdr_destroy (&xdrs);
	      fclose (tobj->fp_log);
	      tobj->fp_log = NULL;
	      retval = DB_INTERNAL_ERROR;
	      goto bailout;
	    }
	  xdr_free ((xdrproc_t) xdr_xdb_logaction, (caddr_t) &action);
	}
      xdr_destroy (&xdrs);
    }


 bailout:
  if (free_header_log)
    xdr_free ((xdrproc_t) xdr_xdb_header, (caddr_t) &header_log);
 bailout2:
  if (free_header)
    xdr_free ((xdrproc_t) xdr_xdb_header, (caddr_t) &header);

  return retval;
}
