/*
 * Note: this routine requires header files that are currently missing.
 * Also some routines that aren't present in the library.  It seems
 * to examine the disk directory.
 */

#include <stdio.h>
#include <rsx.h>
#include "f11.h"

FILE	*ifp;
FILE	*bfp;
int	ihbase;
int	nfile;
int	bibb;
int	bbdirty;
int	bixb;
int	bmap[256];
int	xmap[256];
char	dev[20];
struct	home	bhome;
struct	header	bheader;

main(argc, argv)
char *argv[];
{
	register char *cp1, *cp2;
	register fn;
	char b[40];

	printf("Device? ");
	gets(dev);
	concat(b, dev, "[0,0]indexf.sys", NULL);
	if ((ifp = fopen(b, "wu")) == NULL) {
		printf("%s: cannot open.\n", b);
		exit(1);
	}
	concat(b, dev, "[0,0]bitmap.sys", NULL);
	if ((bfp = fopen(b, "wu")) == NULL) {
		printf("%s: cannot open.\n", b);
		exit(1);
	}
	bread(&bhome, HOMEB, ifp);
	cp1 = &bhome.h_vnam[12];
	while (cp1 > &bhome.h_vnam[0] && cp1[-1] == 0)
		--cp1;
	printf("Volume id `");
	cp2 = &bhome.h_vnam[0];
	while (cp2 < cp1)
		putchar(*cp2++);
	printf("', proceed? ");
	gets(b);
	if (b[0] == 'y') {
		init();
		for (fn=0; fn<nfile; ++fn) {
			bread(&bheader, ihbase+fn, ifp);
			if (bheader.h_fnum==0 && bheader.h_fseq!=0) {
				display(fn);
				overlap();
				printf("Do it? ");
				gets(b);
				if (b[0] == 'y') {
					fixheader(fn);
					alxheader(fn);
					aldblocks();
				}
			}
		}
	}
}

init()
{
	register i;

	ihbase = IMAPB + bhome.h_ibsz;
	bread(&bheader, ihbase, ifp);  /* Index file */
	if (bheader.m_ctsz!=1 || bheader.m_lbsz!=3) {
		printf("Not a [1,3] volume!\n");
		exit(1);
	}
	nfile = -(ihbase-1);
	i = 0;
	while (i < bheader.m_use) {
		nfile += ((bheader.m_map[i]>>8)&0377) + 1;
		i += 2;
	}
	if (nfile > bhome.h_fmax)
		nfile = bhome.h_fmax;
}

display(fn)
{
	register char *cp1, *cp2;
	char b[20];

	printf("File id (%o,%o) name `", fn+1, bheader.h_fseq);
	r50toa(b, bheader.i_fnam, 3);
	cp1 = &b[9];
	while (cp1 > &b[0] && cp1[-1] == ' ')
		--cp1;
	cp2 = &b[0];
	while (cp2 < cp1)
		putchar(*cp2++);
	if (bheader.i_ftyp[0] != 0) {
		r50toa(b, bheader.i_ftyp, 1);
		cp1 = &b[3];
		while (cp1 > &b[0] && cp1[-1] == ' ')
			--cp1;
		if (cp1 != &b[0]) {
			putchar('.');
			cp2 = &b[0];
			while (cp2 < cp1)
				putchar(*cp2++);
		}
	}
	if (bheader.i_fver != 0)
		printf(";%o", bheader.i_fver);
	printf("'\n");
}

overlap()
{
	register i, len;
	long lbn;

	i = 0;
	while (i < bheader.m_use) {
		len = ((bheader.m_map[i]>>8)&0377) + 1;
		lbn = ((bheader.m_map[i]&0377)<<16) | bheader.m_map[i+1];
		check(len, lbn);
		i += 2;
	}
}

check(len, lbn)
long lbn;
{
	register bn, mm, *mp;

	bn = (lbn >> 12) + 2;  /* Vbn 1 is not used !! */
	if (bn != bibb) {
		bbclear();
		bibb = bn;
		bread(bmap, bn, bfp);
	}
	mp = &bmap[(lbn>>4)&0377];
	mm = 1<<(lbn&017);
	while (len--) {
		if (mm == 0) {
			mm = 01;
			if (++mp == &bmap[256]) {
				mp = &bmap[0];
				bread(bmap, ++bibb, bfp);
			}
		}
		if ((*mp&mm) == 0)
			printf("Lbn %lo is allocated!\n", lbn);
		++lbn;
		mm <<= 1;
	}
}

fixheader(fn)
{
	register n, *p, s;

	bheader.h_fnum = fn+1;
	bheader.h_scha &= ~SC_MDL;
	s = 0;
	p = &bheader;
	n = 255;
	do {
		s += *p++;
	} while (--n);
	bheader.h_cksm = s;
	bwrite(&bheader, ihbase+fn, ifp);
}

alxheader(fn)
register fn;
{
	register bn;

	bn = (fn >> 12) + IMAPB;
	if (bn != bixb) {
		bixb = bn;
		bread(xmap, bn, ifp);
	}
	xmap[(fn>>4)&0377] |= 1 << (fn&017);
	bwrite(xmap, bn, ifp);
}

aldblocks()
{
	register i, len;
	long lbn;

	i = 0;
	while (i < bheader.m_use) {
		len = ((bheader.m_map[i]>>8)&0377) + 1;
		lbn = ((bheader.m_map[i]&0377)<<16) | bheader.m_map[i+1];
		allocate(len, lbn);
		i += 2;
	}
	bbclear();
}

allocate(len, lbn)
long lbn;
{
	register bn, mm, *mp;

	bn = (lbn >> 12) + 2;  /* Vbn 1 is not used !! */
	if (bn != bibb) {
		bbclear();
		bibb = bn;
		bread(bmap, bn, bfp);
	}
	mp = &bmap[(lbn>>4)&0377];
	mm = 1<<(lbn&017);
	while (len--) {
		if (mm == 0) {
			mm = 01;
			if (++mp == &bmap[256]) {
				mp = &bmap[0];
				bbclear();
				bread(bmap, ++bibb, bfp);
			}
		}
		*mp &= ~mm;
		bbdirty = 1;
		++lbn;
		mm <<= 1;
	}
}

bbclear()
{
	if (bbdirty) {
		bwrite(bmap, bibb, bfp);
		bbdirty = 0;
	}
}

bread(bp, bn, fp)
char *bp;
FILE *fp;
{
	register s;
	int iosb[2];

	qio(IO_RVB, flun(fp), 1, iosb, NULL, bp, 512, 0, 0, bn, 0);
	wtse(1);
	s = iosb[0] & 0377;
	if (s != IS_SUC) {
		printf("Bread: I/O error, status %03o!\n", s);
		exit(1);
	}
}

bwrite(bp, bn, fp)
char *bp;
FILE *fp;
{
	register s;
	int iosb[2];

	qio(IO_WVB, flun(fp), 1, iosb, NULL, bp, 512, 0, 0, bn, 0);
	wtse(1);
	s = iosb[0] & 0377;
	if (s != IS_SUC) {
		printf("bwrite: I/O error, status %03o!\n", s);
		exit(1);
	}
}
