/*
   fakefs - Astonishingly Slow File System

   Copyright (C) 2001 Zygo Blaxell

   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.

*/

/*
   fakevfs:  top-level interface for the VFS layer.

   This subsystem handles directory and inode operations
   (lstat, readdir, rename, unlink, link, mkdir, rmdir, chown, chmod, and others).

   Most users will interact with fakevfs through this interface.

 */

#ifndef _FAKEVFS_H_
#define _FAKEVFS_H_

#ifdef HAVE_DB_H
#include <db.h>
#else
#error You do not have db.h
#endif

#if SIZEOF_INT == 4
#ifndef Fake_I32
#define Fake_I32 int
#endif
#endif

#if SIZEOF_INT == 8
#ifndef Fake_I64
#define Fake_I64 int
#endif
#endif

#if SIZEOF_LONG == 4
#ifndef Fake_I32
#define Fake_I32 int
#endif
#endif

#if SIZEOF_LONG == 8
#ifndef Fake_I64
#define Fake_I64 long
#endif
#endif

#if SIZEOF_LONG_LONG == 8
#ifndef Fake_I64
#define Fake_I64 long long
#endif
#endif

#ifndef Fake_I32
#error No Fake_I32 type defined
#endif

#ifndef Fake_I64
#error No Fake_I64 type defined
#endif

typedef Fake_I64 Fake_Inode;

typedef enum {
	FAKEVFS_OK,		/* All is well - MUST be 0 */
	FAKEVFS_ERROR,		/* Attempted operation failed, try something else */
	FAKEVFS_RETRY,		/* Attempted operation failed, try again */
	FAKEVFS_ABORT		/* Attempted operation failed, don't try anything else, we are FUBAR */
} Fake_Status;

typedef struct fake_cursor {
	void			*magic;				/* For sanity checking */
	DBC			*dbcursor;			/* The cursor that has to be closed */
	struct fake_cursor	*next;				/* The next one */
} Fake_Cursor;

typedef struct fake_env {
	void		*magic;				/* For sanity checking */
	char		*excuse;			/* Last error excuse */
	DB_ENV 		*dbenv;				/* Berkeley db environment */
	DB_TXN 		*dbtxn;				/* Current Berkeley db transaction */
	int		cursor_flags;			/* In case we ever use CDB mode */
	DB		*free_inodes_db;		/* Table listing free inode ranges */
	char 		*env_name;			/* Environment name (usually a directory) */

	Fake_Cursor	*cursor_list_head;		/* Head of list of open cursors */
} Fake_Env;

typedef const char *Fake_Excuse;

/* A Fake_Env * on success, 0 (and errno) on failure */
Fake_Env *fakevfs_env_create(void);

/*
   Most operations return a Fake_Status.  If Fake_Status is not
   FAKEVFS_OK, then fakevfs_env_excuse may give a human-oriented error
   message.

   The exception is fakevfs_env_close, which destroys the Fake_Env
   which would otherwise be used to obtain an excuse; therefore, we
   give the excuse if there was an error and NULL if not.
*/

/* Bind Fake_Env to an environment */
Fake_Status fakevfs_env_open(Fake_Env *fe, const char *env_name);

/* Create a new inode (get an unused number) */
Fake_Status fakevfs_ino_new(Fake_Env *fe, Fake_Inode *ino);

/* Bind a name to an inode number */
Fake_Status fakevfs_ino_bind(Fake_Env *fe, Fake_Inode ino, const char *name);

/* Unbind a name */
Fake_Status fakevfs_ino_unbind(Fake_Env *fe, const char *name);

/* Get an inode given a name */
Fake_Status fakevfs_ino_get_by_name(Fake_Env *fe, const char *name, Fake_Inode *ino);

/* 0 on success, an excuse on failure */
Fake_Excuse fakevfs_env_close(Fake_Env *fe);

/* Diagnostic excuse */
Fake_Excuse fakevfs_env_excuse(Fake_Env *fe);

/* Transaction stuff (Tcl interface needs this for testing) */
Fake_Status fakevfs_txn_begin(Fake_Env *fe, int db_flags);
Fake_Status fakevfs_txn_abort(Fake_Env *fe);
Fake_Status fakevfs_txn_commit(Fake_Env *fe, int db_flags);

#endif

