#ident "$Header: nodes.c 1.9 90/05/01 $"

/*
 * $Copyright:	$
 * Copyright (c) 1984, 1985, 1986, 1987, 1988, 1989, 1990 
 * Sequent Computer Systems, Inc.   All rights reserved.
 *  
 * This software is furnished under a license and may be used
 * only in accordance with the terms of that license and with the
 * inclusion of the above copyright notice.   This software may not
 * be provided or otherwise made available to, or used by, any
 * other person.  No title to or ownership of the software is
 * hereby transferred.
 */

/*
 * $Log:	nodes.c,v $
 */

#include "crash.h"
#include <sys/types.h>
#ifdef CROSS
#include "/usr/include/time.h"
#else
#include <time.h>
#endif /* CROSS */
#include <sys/vnode.h>
#define INKERNEL
#include <sys/ufsinode.h>
#undef INKERNEL
#include <sys/snode.h>
#include <sys/sysmacros.h>

#define INKERNEL
#include <sys/var.h>

struct inode *readinode(), *inode, *inodeNINODE;
int ninode;
struct snode *readsnode();

struct	vnode *readvnode(), *rootdir;
struct	vnodeops *ufs_vnode, *specfs_vnode, *fifo_vnode;
int	stablesize;
struct	snode **stable;

/*
 * vnode_init() must be called before inode_init().
 * vnode_init() need be called only once; it reads static information.
 * inode_init() may be repeatedly called; it reads dynamic information.
 */

inode_init()
{
	struct var *vaddr;
	struct var v;

	readv(search("inode"), &inode, sizeof inode);
	readv(search("v"), &v, sizeof v);
	inodeNINODE = v.ve_inode;
	ninode = v.v_inode;
	readv(search("stable"), stable, stablesize * sizeof(struct snode *));
}

vnode_init()
{

	readv(search("rootdir"), &rootdir, sizeof rootdir);
	ufs_vnode    = (struct vnodeops *)search("ufs_vnodeops");
	specfs_vnode = (struct vnodeops *)search("spec_vnodeops");
	fifo_vnode = (struct vnodeops *)search("fifo_vnodeops");
	readv(search("stablesize"), &stablesize, sizeof stablesize);
	stable = (struct snode **)calloc(stablesize, sizeof(struct snode *));

}

Inode()
{

	struct inode *ii, *i = inode;
	register int j;
	char *arg;
	int count, slt;

	if (live)
		inode_init();

	printf("SLT   ADDR     VNODE   DEVVP    INUMB  LINK UID  GID   MODE  FLAGS\n");
						
	if ((arg = token()) == NULL) {		/* print the works */
		for (j = ninode; j > 0; i++, j--) {
			printf("%-3d", ninode - j);
			prinode(i);
		}
	} else if (memcmp("0x", arg, 2) == 0) {/* inode address supplied */
		printf("%-3d",
		      (((struct inode *)atox(arg+2) - inode) / sizeof (struct inode))); 
		prinode((struct inode *)atox(arg+2));
	 } else {				/* selective print */
		slt = atoi(arg);
		i +=  slt;
		count = atoi(token());
		if (!count) count = 1;
		count = ((count + slt) > ninode ) ? (ninode - slt) : count;
		for (j = count; j > 0; i++, j--, slt++) {
			printf("%-3d", slt);
			prinode(i);
		}
	}	

}

Vnode()
{
	
	struct inode *ii, *i = inode;
	register int j;
	char *arg;
	int count, slt;

	if (live)
		inode_init();

	printf("SLT  VNODE    NODE    CNT TYP FS   DEVVP    SNODE    DEV     FLAGS\n");

	if ((arg = token()) == NULL) {		/* print the works */
		for (j = ninode; j > 0; i++, j--) {
			printf("%-3d", ninode - j);
			prvnode(&i->i_vnode);
		}
	} else if (memcmp("0x", arg, 2) == 0) {/* vnode address supplied */
		printf("   ");
		prvnode(atoi(arg));
	} else {
		slt = atoi(arg);
		i +=  slt;
		count = atoi(token());
		if (!count) count = 1;
		for (j = count; j > 0; i++, j--, slt++) {
			printf("%-3d", slt);
			prvnode(&i->i_vnode);
		}
	}	
	
}	

Snode()
{
	struct inode *ii, *i = inode;
	register int j;
	char *arg;
	int count, slt;
	char *title = "SNODE      VNODE      REALVP     BDEVVP   TYP DEV    SPTR       NEXT\n";

	if (live)
		inode_init();

	if ((arg = token()) == NULL) {		/* print the works */
		printf("ISLT  %s", title);
		for (j = ninode; j > 0; i++, j--) {
			if ((ii = readinode(i)) == NULL)
				continue;
			if (ii->i_vnode.v_snode == 0)
				continue;
			printf("%3d", ninode - j);
			prsnode(ii->i_vnode.v_snode);
		}
	} else if (memcmp("-b", arg, 2) == 0) {/* print "common" VBLK snodes */
		struct snode *p;

		printf("HSLT  %s", title);
		for (j = 0; j < stablesize; j++) {
			for (p = stable[j]; p != NULL; p = p->s_next) {
				printf("%2d ", j);
				prsnode(p);
				p = readsnode(p);
			}
		}
	} else if (memcmp("0x", arg, 2) == 0) {/* vnode address supplied */
		printf("      %s", title);
		printf("   ");
		prsnode(atoi(arg));
	} else {
		printf("ISLT  %s", title);
		slt = atoi(arg);
		i +=  slt;
		count = atoi(token());
		if (!count) count = 1;
		count = ((count + slt) > ninode ) ? (ninode - slt) : count;
		for (j = count; j > 0; i++, j--, slt++) {
			if ((ii = readinode(i)) == NULL)
				continue;
			if (ii->i_vnode.v_snode == 0)
				continue;
			printf("%3d", slt);
			prsnode(ii->i_vnode.v_snode);
		}
	}	
	
}	

prinode(ii)
register struct inode *ii;
{

	register struct inode	*i;
	register char	ch;

	if ((i = readinode(ii)) == NULL)
		return;

	printf(" %#6x %#6x %#6x %-7u %-4d %4-d %-4d",
		ii, &ii->i_vnode, i->i_devvp,
	        i->i_number, i->i_nlink, i->i_uid, i->i_gid);

	printf("%s%s%s%3o",
	i->i_mode & ISUID ? "u" : "-",
	i->i_mode & ISGID ? "g" : "-",
	i->i_mode & ISVTX ? "v" : "-",
	i->i_mode & 0777);

	switch(i->i_mode & IFMT) {
	case IFDIR: 
		ch = 'd'; 
		break;
	case IFCHR: 
		ch = 'c'; 
		break;
	case IFBLK: 
		ch = 'b'; 
		break;
	case IFREG: 
		ch = 'f'; 
		break;
	case IFIFO: 
		ch = 'p'; 
		break;
	case IFSOCK: 
		ch = 'S'; 
		break;
	case IFLNK: 
		ch = 'l'; 
		break;
	default:    
		ch = '-'; 
		break;
	}
	printf(" %c", ch);

	printf("%s%s%s%s\n",
	i->i_flag & IUPD ? " upd" : "",
	i->i_flag & IACC ? " acc" : "",
	i->i_flag & ICHG ? " chg" : "",
	i->i_flag & IFREE ? " free": "");

	return;

}

prvnode(vv)
register struct vnode *vv;
{

	register struct vnode *v;
	register char	ch;

	if ((v = readvnode(vv)) == NULL)
		return;

	printf(" %#6x %#6x  %-2u ",
		vv, v->v_data, v->v_count);

	switch (v->v_type) {
	case VNON:
		ch = 'n';
		break;
	case VREG:
		ch = 'r';
		break;
	case VDIR:
		ch = 'd';
		break;
	case VBLK:
		ch = 'b';
		break;
	case VCHR:
		ch = 'c';
		break;
	case VFIFO:
		ch = 'p';
		break;
	case VLNK:
		ch = 'l';
		break;
	case VSOCK:
		ch = 's';
		break;
	case VBAD:
		ch = 'b';
		break;
	default:
		ch = '-';
		break;
	}

	printf(" %c ", ch);

	if (v->v_op == ufs_vnode)
		printf(" ufs");
	else if (v->v_op == fifo_vnode)
		printf(" fifo");
	else if (v->v_op == specfs_vnode)
		printf(" specfs");
	else
		printf(" vfs");

	printf(" 0x%06x 0x%06x %d,%d", v->v_devvp, v->v_snode,
			major(v->v_rdev), minor(v->v_rdev));

	printf(" %s%s%s%s%s%s\n",
	v->v_flag & VROOT ? " root" : "",
	v->v_flag & VMOUNTING ? " mntg" : "",
	v->v_flag & VTEXT ? " txt" : "",
	v->v_flag & VMNDLCK ? " mndl" : "",
	v->v_flag & VMAPPED ? " map": "",
	v->v_flag & VMAPSYNC ? " mapsy": "");
	
}	

prsnode(ss)
register struct snode *ss;
{

	register struct snode *s;
	register struct vnode *v;
	register char	ch;

	if ((s = readsnode(ss)) == NULL)
		return;
	
	printf(" 0x%08x 0x%08x 0x%08x 0x%08x ",
		ss, &ss->s_vnode, s->s_realvp, s->s_bdevvp);

	v = &s->s_vnode;

	switch (v->v_type) {
	case VNON:
		ch = 'n';
		break;
	case VREG:
		ch = 'r';
		break;
	case VDIR:
		ch = 'd';
		break;
	case VBLK:
		ch = 'b';
		break;
	case VCHR:
		ch = 'c';
		break;
	case VFIFO:
		ch = 'p';
		break;
	case VLNK:
		ch = 'l';
		break;
	case VSOCK:
		ch = 's';
		break;
	case VBAD:
		ch = 'b';
		break;
	default:
		ch = '-';
		break;
	}

	printf(" %c ", ch);

	printf("%2d,%2d", major(s->s_dev), minor(s->s_dev));
	printf(" 0x%08x 0x%08x ", s->s_sptr, s->s_next);

	if (v->v_op == ufs_vnode) {
		printf("INCORRECT VOPS: ufs");
	} else if (v->v_op == fifo_vnode) {
		if (v->v_type != VFIFO)
			printf("INCORRECT VOPS: fifo");
	} else if (v->v_op == specfs_vnode) {
		if ((v->v_type != VCHR) && (v->v_type != VBLK))
			printf("INCORRECT VOPS: specfs");
	} else {
		printf("INCORRECT VOPS: unknown");
	}

	printf("\n");
	
}	

struct inode *
readinode(ii)
struct inode *ii;
{

	static struct inode inodebuf;

	if (readv(ii, &inodebuf, sizeof inodebuf) != sizeof inodebuf) {
		printf("read error on inode table\n");
		return NULL;
	}
	return &inodebuf;

}

struct snode *
readsnode(ss)
struct snode *ss;
{

	static struct snode snodebuf;

	if (readv(ss, &snodebuf, sizeof snodebuf) != sizeof snodebuf) {
		printf("read error on snode\n");
		return NULL;
	}
	return &snodebuf;

}


struct vnode *
readvnode(vv)
struct vnode *vv;
{

	static struct vnode vnodebuf;

	if (readv(vv, &vnodebuf, sizeof vnodebuf) != sizeof vnodebuf) {
		printf("read error on vnode\n");
		return NULL;
	}
	return &vnodebuf;

}

atox(p)
	register char *p;
{
	register int n = 0;

	for(; *p != '\0'; p++) {
		n <<= 4;
		if (*p >= 'a' && *p <= 'f') {
			n += (*p - 'a' + 0xa);
		} else if (*p >= 'A' && *p <= 'F') {
			n += (*p - 'A' + 0xa);
		} else {
			n += (*p - '0');
		}
	}
	return(n);
}

