#include "cbt.h"
#include "pr.h"

bfile		*curbf;
extern bfile	*newtran();
extern char	*malloc(), *strcpy();
extern long	lseek();

bfile *bopen(s, typ) char *s;	/* typ is 0 or 2 */
{	bfile *p;
	int n, i;

	p = alloc(bfile);
	if(p == NULL)
		goto nomem;
	n = strlen(s);
	p->fname = malloc((unsigned)n + 3);
	if(p->fname == NULL)
		goto nomem;
	(void) strcpy(p->fname, s);
	strcpy(p->fname + n, ".T");
	if((p->tfd = open(p->fname, typ)) == -1) {
		free(p->fname);
		free((char *)p);
		return(NULL);
	}
	p->rdwrt = typ;
	p->fatal = p->advnc = 0;
	p->altname = NULL;
	for(i = 0; i <= MXHT; i++) {
		p->path[i] = NULL;
		p->flag[i] = 0;
		p->loc[i] = 0;
	}
	p->path[0] = (hdr *)malloc(NDSZ);
	if(p->path[0] == NULL)
		goto nomem;
	curbf = p;
	if(ndrd(0, (ndaddr)0) == EOF)
		return(NULL);
	strcpy(p->fname + n, ".F");
	if(!treeonly(p) && (p->dfd = open(p->fname, typ)) == -1) {
		(void) close(p->tfd);
		free(p->fname);
		free((char *) p->path[0]);
		free((char *)p);
		return(NULL);
	}
	else if(treeonly(p))
		p->dfd = -1;
	p->fname[n] = 0;
	if(shared(p))
		return(newtran(p));
	else if(tranid == 0)
		tranid = getlpid();
	p->height = p->path[0]->hlev;
	for(n = 1; n <= p->height; n++)
		if((p->path[n] = (hdr *)malloc(NDSZ)) == NULL)
			goto nomem;
	if(p->height > 0)
		mvgbt((char *)p->path[p->height], (char *)p->path[0], NDSZ);
	(void) bfirst(p);
	return(p);
nomem:
	errno = BNOMEM;
	return(NULL);
}

bseek(bf, key) bfile *bf; mbuf key;
{	private m;
	int i;
	if(bf == NULL)
		return(EOF);
	if(notran(bf))
		return(EOF);
	if(!readonly(bf))
		for(i = 0; i < bf->height; i++)
			if(mustwrite(bf, i))
				if(fixpath(bf) == EOF)
					return(EOF);
	bf->rdptr.rnum = desce(bf, key, &m);
	if(bf->rdptr.rnum == EOF)
		return(EOF);
	bf->advnc = 0;
	bf->rdptr.rptr = m.d;
	if(m.match == EOF) {
		if(advance() == EOF)
			return(EOF);
		if(bf->rdptr.rptr != NULL)
			m.match = NOTFOUND;
	}
	if(m.match != EOF)
		mvgbt(bf->rdptr.rpref, key.mdata, bf->rdptr.rptr->dcom);
		/* maybe use rptr instead of m.d */
	return(m.match);
}

bfirst(bf) bfile *bf;
{	mbuf key;
	key.mlen = 0;
	return(bseek(bf, key));
}

bclose(bf) bfile *bf;
{	int i;
	if(bf == NULL)
		return;
	if(shared(bf)) {
		if(intran())
			trabort();
		rmtran(bf);
	}
	else
		bflush(bf);
	btbufdone(bf->tfd);
	free(bf->fname);
	for(i = 0; i <= MXHT; i++)
		if(bf->path[i] != NULL)
			free((char *)bf->path[i]);
	if(bf->tfd != -1)
		(void) close(bf->tfd);
	if(bf->dfd != -1)
		(void) close(bf->dfd);
	free((char *)bf);
}

bflush(bf) bfile *bf;
{	int i;
	if(bf == NULL)
		return(0);
	if(!bf->rdwrt) {
		errno = BNOWRITE;
		return(EOF);
	}
	curbf = bf;
	if(shared(bf))
		if(intran()) {
			trabort();
			return(EOF);
		}
		else return(0);
	for(i = 0; i <= bf->height; i++) {
		if(!mustwrite(bf, i))
			continue;
		if(readonly(bf) || i == bf->height)
			if(ndwrt(bf->path[i], bf->loc[i]) == EOF)
				return(EOF);
		else
			if(fixpath(bf) == EOF)
				return(EOF);
		bf->flag[i] = 0;
	}
	return(0);
}

breclen(bf) bfile *bf;
{
	if(bf == NULL)
		return(EOF);
	if(notran(bf))
		return(EOF);
	if(bf->advnc)
		if(advance() == EOF)
			return(EOF);
	if(bf->rdptr.rnum >= bf->path[0]->kcnt)
		return(EOF);
	if(treeonly(bf))
		return(0);
	return(lfadr(bf->path[0], bf->rdptr.rnum)->llen);
}

mbuf bkey(bf) bfile *bf;
{	mbuf x;
	dkey *d;
	if(bf == NULL)
		goto eof;
	if(notran(bf))
		goto eof;
	if(bf->advnc)
		if(advance() == EOF)
			goto eof;
	if(bf->rdptr.rnum >= bf->path[0]->kcnt)
		goto eof;
	d = bf->rdptr.rptr;
	x.mlen = d->dlen - DKEYSZ + d->dcom;
	mvgbt(bf->rdptr.rpref + d->dcom, d->dkey, d->dlen-DKEYSZ);
	x.mdata = bf->rdptr.rpref;
	return(x);
eof:
	x.mlen = 0;
	x.mdata = NULL;
	return(x);
}

bread(bf, key, rec) bfile *bf; mbuf *key, *rec;
{
	dkey *d;
	lfaddr *x;
	int n;
	if(bf == NULL)
		return(NULL);
	if(notran(bf))
		return(EOF);
	if(bf->advnc)
		if(advance() == EOF)
			return(EOF);
	if(bf->rdptr.rnum >= bf->path[0]->kcnt)
		return(EOF);
	if(key != NULL) {
		d = bf->rdptr.rptr;
		key->mlen = d->dlen - DKEYSZ + d->dcom;
		mvgbt(key->mdata, bf->rdptr.rpref, d->dcom);
		mvgbt(key->mdata + d->dcom, d->dkey, d->dlen - DKEYSZ);
	}
	if(rec != NULL && !treeonly(bf)) {
		x = lfadr(bf->path[0], bf->rdptr.rnum);
		rec->mlen = x->llen;
		if(rec->mlen != 0) {
			(void) lseek(bf->dfd, x->lloc, 0);
			if((n = read(bf->dfd, rec->mdata, (int)rec->mlen))
				!= rec->mlen) {
				if(n >= 0)
					errno = BRDERR;
				return(EOF);
			}
		}
	}
	bf->advnc = 1;
	return(0);
}
static struct D { struct D *a; char *b;} VER = {&VER,"\n82/10/9:bt.c\n"};
/*0001011110110101*/
