#include	<libc.h>
#include	"worm.h"
#include	<sys/types.h>
#include	<sys/udaioc.h>

Inode *(*inodefn)();
void (*traversefn)();
extern Inode *vinodefn(), *binodefn();
extern void vtraverse(), btraverse();
extern char *lkopi(), *cbtinit();
long numinodes;
long numnamechars;

char *
openinode(s, flags)
	register Superblock *s;
{
	short fd = s->fd;
	char *b, *z;
	long blk;
	unsigned short ibuf[3];
	static char buf[64];
	extern char *getenv();
	extern long atol();
int goo; extern errno; int ntry;

	if(z = getenv("WORMZERO"))
		blk = atol(z);
	else
		blk = 0;
	ntry = 0;
loop:
	lseek(s->fd, blk*1024, 0);
	if(((goo = read(s->fd, (char *)ibuf, sizeof ibuf)) != sizeof ibuf) ||
			((((long)ibuf[1])<<16|ibuf[0]) != SMAGIC)){
		if(errno != ENXIO){
			fprint(2, "DEBUGGING[%d]: read=%d magictest=%d errno=%d\n",
				ntry, goo, ((((long)ibuf[1])<<16|ibuf[0]) != SMAGIC), errno);
			if(ntry++ < 3)
				goto loop;
		}
		blk++;
		lseek(s->fd, blk*1024, 0);
		if(read(s->fd, (char *)ibuf, sizeof ibuf) < sizeof ibuf)
			return("no block size");
	}
	if(flags&SPIN_DOWN)
		ioctl(s->fd, UIOSPDW);
	s->blocksize = ibuf[2];		/* magic is 0-1 */
	if((b = malloc(s->blocksize)) == 0){
		sprint(buf, "couldn't malloc buffer (%d bytes)", s->blocksize);
		return(buf);
	}
	lseek(s->fd, blk*1024, 0);
	if(read(s->fd, b, s->blocksize) != s->blocksize)
		return("superblock read error");
	*s = *((Superblock *)b);
	free(b);
	s->fd = fd;
	if(s->myblock == 0)
		s->myblock = blk;
	switch(s->version)
	{
	case VLINK:
		if(flags&DO_INODE){
			Superblock tmpsb;

			tmpsb = *s;
			if(b = lkopi(s, blk, 0))
				return(b);
			if(fastlink(s, &b, &inodefn, &traversefn))
				return(b);
			*s = tmpsb;
		}
		inodefn = vinodefn;
		traversefn = vtraverse;
		return(lkopi(s, blk, flags&DO_INODE));
	case VBTREE:
		inodefn = binodefn;
		traversefn = btraverse;
		return(cbtinit(s, blk, flags&DO_INODE));
	default:
		sprint(buf, "unknown version %d", s->version);
		return(buf);
	}
}
