/* rcsid[]="$Header: inode.h,v 820.1 86/12/04 19:48:53 root Exp $" */
/* sccsid[]="%W% %Y% %Q% %G%" */

/************************************************************************
*									*
*				Copyright 1984				*
*			VALID LOGIC SYSTEMS INCORPORATED		*
*									*
*	This listing contains confidential proprietary information	*
*	which is not to be disclosed to unauthorized persons without	*
*	written consent of an officer of Valid Logic Systems 		*
*	Incorporated.							*
*									*
*	The copyright notice appearing above is included to provide	*
*	statutory protection in the event of unauthorized or 		*
*	unintentional public disclosure.				*
*									*
************************************************************************/

#ifndef	INODE_ALREADY_DEFINED
#define	INODE_ALREADY_DEFINED

/*	inode.h	6.1	83/07/29	*/

#ifdef	KERNEL
#include "../h/socket.h"
#else
#include <sys/socket.h>
#endif

/*
 * The I node is the focus of all file activity in UNIX.
 * There is a unique inode allocated for each active file,
 * each current directory, each mounted-on file, text file, and the root.
 * An inode is 'named' by its dev/inumber pair. (iget/iget.c)
 * Data in icommon is read in from permanent inode on volume.
 */

#define	NDADDR	12		/* direct addresses in inode */
#define	NIADDR	3		/* indirect addresses in inode */

#ifdef VALID_OOT
/*
 * Each inode potentially points to another
 * inode which contains information about the
 * object oriented structure of the first inode.
 *
 * BUG this is all highly subject to change
 */
typedef struct oNodeRef {
	host_t	Obj_host;	/* 0x00: host on which reference resides */
	dev_t	Obj_dev;	/* 0x08: device number on that host */
	ino_t	Obj_inumber;	/* 0x0A: inumber on that device */
} oNodeRef_t;			/* 0x0E: length */
#endif VALID_OOT

struct inode {
	struct	inode *i_chain[2];	/* must be first */
	u_short	i_flag;
	u_short	i_count;	/* reference count */
	dev_t	i_dev;		/* device where inode resides */
	u_short	i_shlockc;	/* count of shared locks on inode */
	u_short	i_exlockc;	/* count of exclusive locks on inode */
	ino_t	i_number;	/* i number, 1-to-1 with device address */
	struct	fs *i_fs;	/* file sys associated with this inode */
	struct	dquot *i_dquot;	/* quota structure controlling this file */
	union {
		daddr_t	if_lastr;	/* last read (read-ahead) */
		struct	socket *is_socket;
		struct	{
			struct inode  *if_freef;	/* free list forward */
			struct inode **if_freeb;	/* free list back */
		} i_fr;
	} i_un;
	struct 	icommon
	{
		u_short	ic_mode;	/*  0: mode and type of file */
		short	ic_nlink;	/*  2: number of links to file */
		short	ic_uid;		/*  4: owner's user id */
		short	ic_gid;		/*  6: owner's group id */
		quad	ic_size;	/*  8: number of bytes in file */
		time_t	ic_atime;	/* 16: time last accessed */
		long	ic_atspare;
		time_t	ic_mtime;	/* 24: time last modified */
		long	ic_mtspare;
		time_t	ic_ctime;	/* 32: last time inode changed */
		long	ic_ctspare;
		daddr_t	ic_db[NDADDR];	/* 40: disk block addresses */
		daddr_t	ic_ib[NIADDR];	/* 88: indirect blocks */
		long	ic_flags;	/* 100: status, currently unused */
		long	ic_blocks;	/* 104: blocks actually held */
#if	defined(VALID_DFS) && defined(VALID_OOT)
		/*
		 * Support for Valid's Object Oriented Technology
		 * This information MUST be written to disk.
		 */
		oNodeRef_t	ic_object;	/* 108: Assoc'd abstract obj */

#define i_absObj_ino	i_ic.ic_object.Obj_inumber
#define i_absObj_host	i_ic.ic_object.Obj_host
#define i_absObj_dev	i_ic.ic_object.Obj_dev

		u_short	ic_spareA[1];	/* 122: Reserved, currently unused */
		u_long	ic_spareB[1];	/* 124: Reserved, currently unused */
#else	defined(VALID_DFS) && defined(VALID_OOT)
		long	ic_spare[5];	/* 108: reserved, currently unused */
#endif	defined(VALID_DFS) && defined(VALID_OOT)
	} i_ic;
#ifdef	VALID_DFS
	/*
	 * This DFS information is transient
	 * across system shutdowns and need
	 * NOT be written to disk.
	 *
	 * Currently, just the common-portion (i_ic)
	 * is installed/updated across DFS machines,
	 * although the entire inode is actually
	 * shipped through the datalink layer.
	 *
	 * However, mbuftoinode(ip,rp) should
	 * be consulted for installation/update of COMPLETE
	 * information necessary for DFS:
	 *	E.g., i_wcount?
	 */
	struct	connection *	i_host;	    /* Connection to remote server    */
	struct	dfs_remote *	i_rmt_node; /* Chain thru local inodes	      */
	caddr_t			i_rmt_ip;   /* Remote inode address (@ server)*/
	struct	dfs_remote *	i_rmt_lock; /* Client host which has us locked*/
	u_short			i_wcount;   /* # "open for write" references  */
	u_short			i_dfsSpare0;/* DFS spare (for alignment)      */
	u_long			i_dfsSpare1;/* DFS spare (for paranoia)	      */
#endif	VALID_DFS
#if	defined(VALID_DFS) && defined(VALID_OOT)
	/*
	 * The following fields are for Valid's
	 * Object Oriented Technology.
	 *
	 * BUG all of this is subject to change
	 * BUG it is not clear that the system will run with these
	 * BUG it is not clear that DFS will work with these
	 */
	/*
	 * RAM-resident `onode' information for
	 * Valid's Object Oriented Technology.
	 * This information is placed after
	 * the nominal DFS and disk-resident information
	 * and MUST be present to
	 * permit downward DFS compatiblity.
	 *
	 * We want to transiently relate
	 * the class and method heirarchies
	 * of an incore abstract object.
	 */
	struct	inode *	i_class_ip [2];	/* ???: Up/down  "class"  ptrs */
	struct	inode *	i_method_ip[2];	/* ???: Fwd/Bkwd "method" ptrs */

/*
 * Linkages between object classes
 */
#define	i_superClass_ip		i_class_ip[0]
#define	i_subClass_ip		i_class_ip[1]

/*
 * Linkage for method inheiritency
 */
#define	i_methodFwd_ip		i_methods_ip[0]
#define	i_methodBkwd_ip		i_methods_ip[1]

/*
 * Same pointer linkages,
 * but from the viewpoint
 * of an abstract object.
 */
#define	i_objUp_ip		i_class_ip[0]
#define	i_objDown_ip		i_class_ip[1]

#define	i_objFwd_ip		i_methods_ip[0]
#define	i_objBkwd_ip		i_methods_ip[1]

#endif	defined(VALID_DFS) && defined(VALID_OOT)
};

struct dinode {
	union {
		struct	icommon di_icom;
		char	di_size[128];
	} di_un;
};

#define	i_mode		i_ic.ic_mode
#define	i_nlink		i_ic.ic_nlink
#define	i_uid		i_ic.ic_uid
#define	i_gid		i_ic.ic_gid
/* ugh! -- must be fixed */
#ifdef vax
#define	i_size		i_ic.ic_size.val[0]
#endif
#ifdef s32
#define	i_size		i_ic.ic_size.val[1]
#endif s32
#define	i_db		i_ic.ic_db
#define	i_ib		i_ic.ic_ib
#define	i_atime		i_ic.ic_atime
#define	i_mtime		i_ic.ic_mtime
#define	i_ctime		i_ic.ic_ctime
#define i_blocks	i_ic.ic_blocks
#define	i_rdev		i_ic.ic_db[0]
#define	i_lastr		i_un.if_lastr
#define	i_socket	i_un.is_socket
#define	i_forw		i_chain[0]
#define	i_back		i_chain[1]
#define	i_freef		i_un.i_fr.if_freef
#define	i_freeb		i_un.i_fr.if_freeb

#define di_ic		di_un.di_icom
#define	di_mode		di_ic.ic_mode
#define	di_nlink	di_ic.ic_nlink
#define	di_uid		di_ic.ic_uid
#define	di_gid		di_ic.ic_gid
#ifdef vax
#define	di_size		di_ic.ic_size.val[0]
#endif
#ifdef s32
#define	di_size		di_ic.ic_size.val[1]
#endif s32
#define	di_db		di_ic.ic_db
#define	di_ib		di_ic.ic_ib
#define	di_atime	di_ic.ic_atime
#define	di_mtime	di_ic.ic_mtime
#define	di_ctime	di_ic.ic_ctime
#define	di_rdev		di_ic.ic_db[0]
#define	di_blocks	di_ic.ic_blocks

#ifdef KERNEL
struct inode *inode;		/* the inode table itself */
struct inode *inodeNINODE;	/* the end of the inode table */
int	ninode;			/* number of slots in the table */

struct	inode *rootdir;			/* pointer to inode of root directory */

struct	inode *ialloc();
struct	inode *iget();
#ifdef notdef
struct	inode *ifind();
#endif
struct	inode *owner();
struct	inode *maknode();
struct	inode *namei();

ino_t	dirpref();
#endif

/* flags */
#define	ILOCKED		0x1		/* inode is locked */
#define	IUPD		0x2		/* file has been modified */
#define	IACC		0x4		/* inode access time to be updated */
#define	IMOUNT		0x8		/* inode is mounted on */
#define	IWANT		0x10		/* some process waiting on lock */
#define	ITEXT		0x20		/* inode is pure text prototype */
#define	ICHG		0x40		/* inode has been changed */
#define	ISHLOCK		0x80		/* file has shared lock */
#define	IEXLOCK		0x100		/* file has exclusive lock */
#define	ILWAIT		0x200		/* someone waiting on file lock */
#ifdef VALID_DFS
#define IOPENWRITE	0x400		/* inode opened for write */
#define IDEADSERVER	0x800		/* server for this inode is dead */
#endif VALID_DFS

/* modes */
#define	IFMT		0170000		/* type of file */
#define	IFCHR		0020000		/* character special */
#define	IFDIR		0040000		/* directory */
#define	IFBLK		0060000		/* block special */
#define	IFREG		0100000		/* regular */
#define	IFLNK		0120000		/* symbolic link */
#define	IFSOCK		0140000		/* socket */

#define	ISUID		04000		/* set user id on execution */
#define	ISGID		02000		/* set group id on execution */
#define	ISVTX		01000		/* save swapped text even after use */
#define	IREAD		0400		/* read, write, execute permissions */
#define	IWRITE		0200
#define	IEXEC		0100

#define	ILOCK(ip) { \
	while ((ip)->i_flag & ILOCKED) { \
		(ip)->i_flag |= IWANT; \
		sleep((caddr_t)(ip), PINOD); \
	} \
	(ip)->i_flag |= ILOCKED; \
}

#define	IUNLOCK(ip) { \
	(ip)->i_flag &= ~ILOCKED; \
	if ((ip)->i_flag&IWANT) { \
		(ip)->i_flag &= ~IWANT; \
		wakeup((caddr_t)(ip)); \
	} \
}

#define	IUPDAT(ip, t1, t2, waitfor) { \
	if (ip->i_flag&(IUPD|IACC|ICHG)) \
		iupdat(ip, t1, t2, waitfor); \
}
#endif	INODE_ALREADY_DEFINED
