/* 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.  */

#ifndef __DB_PRIVATE_H__
#define __DB_PRIVATE_H__

#include <unistd.h>
#include <fcntl.h>
#include "nis_db.h"
#include "nisdb_priv.h"
#include "xdb.h"

struct entry_t {
  entry_obj *object;
  uint32_t *hashes;
  uint32_t hashes_len;
  struct entry_t *next;
};
typedef struct entry_t entry_t;

struct table_t {
  uint32_t hashkey;
  char *name;
  char *path;
  char *path_log;
  table_obj *object;
  struct table_t *next;
  xdb_header header;
  struct entry_t *entry;
  FILE *fp_log; /* We only need the log_handle, all other will not be cached */
};
typedef struct table_t table_t;

static inline void __close_on_exit (FILE **fp)
{
  /* We have to make sure the file is  `closed on exec'.  */
  int result, flags;

  if (fp != NULL && *fp != NULL)
    {
      result = flags = fcntl (fileno (*fp), F_GETFD, 0);
      if (result >= 0)
	{
	  flags |= FD_CLOEXEC;
	  result = fcntl (fileno (*fp), F_SETFD, flags);
	}
      if (result < 0)
	{
	  /* Something went wrong.  Close the stream and return a
	     failure.  */
	  fclose (*fp);
	  *fp = NULL;
	}
    }
}

static inline db_status __open_log (table_t *tobj)
{
  XDR xdrs;

  if (tobj->fp_log == NULL)
    {
      if (tobj->header.log_present)     /* We are in standby. */
        {
          tobj->fp_log = fopen (tobj->path_log, "a+");
          if (tobj->fp_log == NULL)
            return DB_INTERNAL_ERROR;
          __close_on_exit (&tobj->fp_log);
        }
      else
        /* There is no log file yet, create one. */
        {
          FILE *fp;

          tobj->header.type = XDB_LOG;
          tobj->fp_log = fopen (tobj->path_log, "w+");
          if (tobj->fp_log == NULL)
            return DB_INTERNAL_ERROR;
          __close_on_exit (&tobj->fp_log);

          xdrstdio_create (&xdrs, tobj->fp_log, XDR_ENCODE);
          if (!xdr_xdb_header (&xdrs, &tobj->header))
            {
              xdr_destroy (&xdrs);
              fclose (tobj->fp_log);
              unlink (tobj->path_log);
              return DB_INTERNAL_ERROR;
            }
          xdr_destroy (&xdrs);

          fp = fopen (tobj->name, "r+");
          xdb_set_log_present (fp, &tobj->header);
          fclose (fp);
        }
    }

  return DB_SUCCESS;
}

extern table_t *__get_table __P ((__const char *name));
extern table_t *__destroy_table __P ((__const char *name));
extern db_status __add_table __P ((table_t *t_entry));
extern db_status __load_entries __P ((table_t *));
extern db_status calc_entry_hash __P ((table_t *tobj, entry_t *eobj));
extern db_result *__remove_entry __P ((const char *table_name, u_int numattrs,
				      const nis_attr *attrs, bool_t writelog));

extern entry_obj *__clone_entry __P ((const entry_obj *src));
extern table_obj *__clone_table __P ((const table_obj *src));

extern bool_t __nisdb_xdr_table_obj __P ((XDR *xdrs, table_obj *objp));
extern bool_t __nisdb_xdr_entry_obj __P ((XDR *xdrs, entry_obj *objp));
extern bool_t __nisdb_xdr_attr __P ((XDR *xdr, nis_attr *attrs));

#endif /* __DB_PRIVATE_H__ */
