#ifndef	_LOCAL_FSLIB_H
#define	_LOCAL_FSLIB_H
#include <sys/types.h>
#include <linux/vfs.h>
#include "basic.h"
#include "linux/userfs_types.h"

typedef struct {
	time_t	bsize;
	time_t	blocks;
	time_t	bfree;
	time_t	bavail;
	time_t	files;
	time_t	ffree;
	fsid_t	fsid;
	time_t	namelen;
}	FS_Status;

typedef up_inode Inode;

typedef struct {
	ushort	uid;
	ushort	euid;
	ushort	suid;
	ushort	gid;
	ushort	egid;
	ushort	sgid;
	ushort	umask;
	ulong	gcnt;
	long	*groups;
}	Permission;

typedef struct {
	ulong	size;
	unchar	*ptr;
}	TBuffer;

typedef struct {
	ulong	handle;
	off_t	off;
	const char *fname;
}	Directory;

typedef struct {

  /* every error that occurs is send to this function */
  void     (*errorlog) (const char *str);

  /* initialization routine with optional parameters */
  Status   (*init) (int ac, char **av);

  /* deinitialization */
  Status   (*deinit) (void);

  /* on file creation */
  ulong    (*ufs_create) (ulong dir, long mode,
                          long rdev, Permission *p, char *fname);

  /* lookup for an inode */
  ulong    (*ufs_lookup) (ulong dir, char *fname);

  /* on every close on a file */
  Status   (*ufs_close) (ulong handle, ulong ctok);

  /* on every read request */
  TBuffer *(*ufs_read) (ulong handle, off_t off, off_t size, ulong ctok);

  /* on write requests */
  off_t    (*ufs_write) (ulong handle, off_t off, TBuffer *tb, ulong ctok);

  /* shorten a file */
  Status   (*ufs_truncate) (ulong handle, off_t size);

  /* physical sync data */
  Status   (*ufs_fsync) (void);

  /* read a directory entry */
  Directory *(*ufs_readdir) (ulong dir, off_t off, ulong ctok);

  /* link two files together */
  Status   (*ufs_link) (ulong oldhandle, ulong dir, char *fname);

  /* unlink a file */
  Status   (*ufs_unlink) (ulong dir, char *fname);

  /* create a symbolic link */
  Status   (*ufs_symlink) (ulong dir, char *name, char *symname,
                           Permission *p);

  /* read the symbolic link information */
  char    *(*ufs_readlink) (ulong handle);

  /* follow a symbolic link */
  char    *(*ufs_followlink) (ulong dir, ulong handle,
                              long flag, long mode);

  /* called on mounting to request the inode of the root directory */
  ulong    (*ufs_mount) (void);

  /* when filesystem will be unmounted */
  Status   (*ufs_umount) (void);

  /* if a read request for an inode is send */
  Inode   *(*ufs_iread) (ulong handle);

  /* write an inode back to the fs */
  Status   (*ufs_iwrite) (ulong handle, Inode *ino);

  /* get statistics over the filesystem */
  FS_Status *(*ufs_statfs) (void);

  /* write an inode back */
  Status   (*ufs_iput) (ulong handle);

  /* called on every open */
  ulong    (*ufs_open) (ulong handle, Permission *p);

  /* permission check */
  Status   (*ufs_permission) (ulong handle, long mask, Permission *p);

  /* rename a file */
  Status   (*ufs_rename) (ulong odir, char *oname,
                          ulong ndir, char *nname);

  /* read more directory entries with one call */
  Directory *(*ufs_multireaddir) (ulong dir, off_t off,
                                  ulong ctok, ulong *count);

  /* notify of inode change */
  Status   (*ufs_notify_change) (ulong handle, up_iattr *iattr);
}	fscalls;

extern int	userfs (int argc, char **argv, fscalls *fc);

/*
 *	this is for a filesystem sceleton to do some basic work
 */
# define	DATABUF_MAGIC	((ulong) 0x1abe4)

#ifndef USERFS_MAX_XFER
#define USERFS_MAX_XFER	(4080)
#endif

/*
 *	On default action the user process can be informed of several
 *	actions. Each action passes a pointer to inform_user.
 */
typedef enum {
	UI_Create,		/* filenam */
	UI_Lookup,		/* filenam */
	UI_Close,		/* finode */
	UI_Read,		/* ui_io */
	UI_Write,		/* ui_io */
	UI_Truncate,		/* ui_io */
	UI_Fsync,		/* NULL */
	UI_Readdir,		/* filenam */
	UI_Link,		/* filenam */
	UI_Unlink,		/* filenam */
	UI_Symlink,		/* filenam */
	UI_Readlink,		/* finode */
	UI_Followlink,		/* finode */
	UI_Iread,		/* finode */
	UI_Iwrite,		/* finode */
	UI_Statfs,		/* FS_Status */
	UI_Iput,		/* ulong */
	UI_Open,		/* finode */
	UI_Permission,		/* ??? */
	UI_Rename,		/* ??? */
	UI_Multireaddir,	/* filenam */
	UI_Notify_Change	/* ??? */
}	UserInfo;

typedef struct _finode	finode;

typedef struct _filenam {
	char	*fname;		/* the filename itself			*/
	ulong	i;		/* attached inode			*/
	struct _filenam
		*next;
}	filenam;

struct _finode {
	ulong	nr;		/* the inode number			*/
	ulong	linked;		/* how often is this file open?		*/
	Inode	ino;		/* the inode data itself		*/
	void	*priv;		/* for FS depended data			*/
	char	*slink;		/* the symbolic link name		*/
	filenam	*dir;		/* the linked directory filename	*/
};

typedef struct _databuf {
	ulong	magic;		/* an unreliable method to prevent inter-
				   preting other priv data		*/
	unchar	*ptr;		/* the data itself			*/
	ulong	cnt;		/* # of bytes in ptr			*/
	ulong	siz;		/* allocated memory for the data	*/
}	databuf;

typedef struct {
	off_t	off;		/* offset to read from			*/
	off_t	size;		/* # of bytes to read			*/
	finode	*i;		/* inode to read from			*/
}	ui_io;

extern void	set_fsdata (ulong blk, ulong nam);
extern filenam	*alloc_filenam (char *name, ulong use, Bool isdir, void *priv);
extern void	set_filesize (ulong ino, ulong size);
extern void	free_filenam (filenam *f);
extern finode	*get_finode (int inr);
extern filenam	*make_directory (char *fname, ulong up, void *priv);
extern filenam	*add_fullpath (filenam *root, char *path, Bool isdir);
extern void	dump_filesystem (filenam *root);

extern void	inform_user (UserInfo what, void *ptr);
/*
 *	Some useful default actions
 */
extern void	def_errorlog (char *str);
extern ulong	def_lookup (ulong dir, char *fname);
extern TBuffer	*def_read (ulong handle, off_t off, off_t size, ulong ctok);
extern off_t	def_write (ulong handle, off_t off, TBuffer *tb, ulong ctok);
extern Status	def_truncate (ulong handle, off_t size);
extern Status	def_fsync (void);
extern ulong	def_create (ulong dir, long mode, long rdev,
                            Permission *p, char *fname);
extern Status	def_close (ulong handle, ulong ctok);
extern Directory
		*def_readdir (ulong dir, off_t off, ulong ctok);
extern Status	def_link (ulong ohandle, ulong dir, char *fname);
extern Status	def_unlink (ulong dir, char *fname);
extern Status	def_symlink (ulong dir, char *name,
                             char *symname, Permission *p);
extern char	*def_readlink (ulong handle);
extern char	*def_followlink (ulong dir, ulong handle,
                                 long flag, long mode);
extern Inode	*def_iread (ulong handle);
extern Status	def_iwrite (ulong handle, Inode *ino);
extern FS_Status
		*def_statfs (void);
extern Status	def_iput (ulong handle);
extern ulong	def_open (ulong handle, Permission *perm);
extern Status	def_permission (ulong handle, long mask, Permission *perm);
extern Status	def_rename (ulong odir, char *oname, ulong ndir, char *nname);
extern Directory
		*def_multireaddir (ulong dir, off_t off,
                                   ulong ctok, ulong *count);
extern Status	def_notify_change (ulong hanlde, Inode *ino, long flags);
# endif		/* _LOCAL_FSLIB_H */
