AUSAM/source/S/dcopy.c

Compare this file to the similar file:
Show the results in this format:

#
#include <local-system>
/*
 *	disk copier and compacter
 *	J. N. Rottman
 *
 *	NOTE:
 *	1) Boostrap block is copied.
 *	2) Size of destination file system (in particular no inodes)
 *	   is used i.e it is not duplicated. An initial pass is thus
 *	   made to check if copied filesystem fits !!
 *	3) Disk errors are also copied, so dcheck and icheck aforehand.
 *	4) Will work for HP and MS disks only (agsm and eecf respectively).
 *
 *	C. H. Maltby esq.
 */

/*
 *	5) Will now work for any disk (e.g. RK).  The algorithm was
 *	   plagiarised from `icheck.c'.
 *	6) Added directory-compression feature.
 *
 *	K. F. Hill (failed)
 */

#include <param.h>
#include <filsys.h>
#include <ino.h>

#ifdef	EECF
#define	IN	10	/* magic interleave number */
#define NSEC	21	/* number of sectors per track */
#define NTRACK	19	/* number of tracks per cylinder */
#endif	EECF
#ifdef	AGSM
#define	IN	7	/* magic interleave number */
#define NSEC	22	/* number of sectors per track */
#define NTRACK	19	/* number of tracks per cylinder */
#endif	AGSM
#ifdef	EECF1140
#define	IN	3	/* magic interleave number */
#define	NSEC	12	/* number of sectors per track */
#define NTRACK	2	/* number of tracks per cylinder */
#endif	EECF1140

#ifdef	EECF & AGSM | EECF & EECF1140 | AGSM & EECF1140
more than one is defined .... this should not bee ;;
#endif

#define	NPOOL	50	/* size of output buffer pool - must be >= 8 */


struct	filsys	super0;
struct	filsys	super1;
struct	inode	node0;
struct	inode	node1;

struct	direct
{
	int	inum;
	char	name[14];
};

struct	inode	in_node[16];
struct	inode	out_node[16];

int	inum	16;
int	iblk	1;
int	onum	0;
int	oblk	2;
int	iunit;
int	*iindex;
int	fi;
int	fo;
int	lastblock;
int	inext	1;
int	in[256];
int	ind0[256];
int	ind1[256];
char	*blkno;


int dirent;		/* number of directory entries */
int diriaddr;		/* index into i_addr for new large directories */
int dirind1;		/* index into ind1 for new block numbers */
int *upto;		/* remembers where up to in new block */


struct
{
	int	bn;
	int	bb[256];
} bpl[NPOOL];

int	inpool;


char	adr[NSEC], flag[NSEC];


main(argc, argv)
char **argv;
{
	register i, *indx, icount;
	extern int *sbrk();

	if (argc != 3)
	{
		printf("Usage: dcopy fromfilesys tofilesys\n");
		return(1);
	}
	if ((fi = open(argv[1], 0)) < 0)
	{
		printf("Cannot open %s.\n", argv[1]);
		return(1);
	}
	if ((fo = open(argv[2], 2)) < 0)
	{
		printf("Cannot open %s.\n", argv[2]);
		return(1);
	}
	blkno = argv[0];
	indx = 0;
	if (gtty(0, in) == -1) indx++;		/* terminal input */
	sync();
	getblk(fi, &super0, 0);
	putblk(&super0, 0);		/* copy bootstrap */
	getblk(fi, &super0, 1);

	if (indx == 0)
	{
		printf("%s: size = %d blks (%d in use); i-list = %d blks (%d in use).\n",
			argv[1], super0.s_fsize, super0.s_fsize - (icount = countfree()), super0.s_isize, i = counti());
		for (;;)
		{
			printf("Enter size (blks) for %s file system ", argv[2]);
			if ((super1.s_fsize = getnum(super0.s_fsize)) < i)
			{
				printf("Too small\n");
				continue;
			}
			printf("Enter size (blks) of i-list (16 inodes per blk) ");
			if ((super1.s_isize = getnum(super0.s_isize)) < i || super1.s_isize >= super1.s_fsize)
			{
				printf("Illegal size\n");
				continue;
			}
			if ((super0.s_fsize - (super0.s_isize + icount)) <= (super1.s_fsize - super1.s_isize)) break;
			printf("Insufficient space for file system.\n");
		}

		if ((i = fork()) < 0)
			printf("Fork has failed!! Parent will carry on...\n");
		if (i > 0)
		{
			printf("Child continuing dcopy (pid %d)\n", i);
			return 0;
		}
		if (i == 0)
		{
			signal(2, 1);
			signal(3, 1);
		}
	}
	else
	{
		super1.s_fsize = super0.s_fsize;
		super1.s_isize = super0.s_isize;
	}

	super1.s_time = super0.s_time;
	icount = 0;
	for (i = 0; i < NSEC; i++)
	{
		while (flag[icount]) icount = (icount + 1) % NSEC;
		adr[i] = icount;
		flag[icount]++;
		icount = (icount + IN) % NSEC;
	}

	indx = i = sbrk(super0.s_isize * 2 * 16);
	if (i == -1)
	{
		printf("Dcopy: Not enough core!\n");
		return 1;
	}
	iindex = indx - 1;
	icount = 16*super0.s_isize;


	iunit = fi;

	i = icount;
	do
	{
		geti();
		if (node0.i_mode & IALLOC)
		{
			copyi();
			*indx++ = inext++;
		}
		else *indx++ = 0;
	} while (--i);

	ipurge();

	for (i=1; i < inext; i++)
	{
		geti();
		if ((node0.i_mode & IFMT) == IFDIR) reldir();
	}

	icount = 16 * super1.s_isize;
	i = inext;
	while (i <= icount && super1.s_ninode != 100)
		super1.s_inode[super1.s_ninode++] = i++;

	for (indx = &in[100]; indx != &in[256]; *indx++ = 0);
	freelist();

	putblk(&super1, 1);
	purgepool();
	sync();
	printf("\007Dcopy finished\n");
	return(0);
}

getnum(dflt)
{
	register unsigned n;
	register c;

	for (;;)
	{
		n = 0;
		if ((c = getchar()) == 0 || c == '\n') n = dflt;
		else while (c >= '0' && c <= '9')
		{
			n = n * 10 + c - '0';
			c = getchar();
		}
		if (c == 0 || c == '\n') return n;
		while ((c = getchar()) && c != '\n');
		printf("\007Illegal number - try again ");
	}
}

getblk(f, b, n)
{
	seek(f, n, 3);
	if (read(f, b, 512) != 512) printf("Input error: block %d\n", n);
}

putblk(b, n)
register int *b;
{
	register int *w;
	register int q;

	if (inpool == NPOOL) purgepool();
	bpl[inpool].bn = n;
	w = bpl[inpool++].bb;
	q = 256;
	do *w++ = *b++; while (--q);
}

grablock(n)	/* grabs the next free block from the pool */
{
	if (inpool == NPOOL) purgepool();
	bpl[inpool].bn = n;
	return(&bpl[inpool++].bb);
}

purgepool()
{
	register int i;

	for (i=0; i < inpool; i++)
	{
		seek(fo, bpl[i].bn, 3);
		if (write(fo, bpl[i].bb, 512) != 512)
			printf("Output error: block %d\n", bpl[i].bn);
	}
	inpool = 0;
}

geti()
{
	register *r, *w, q;

	if (inum == 16)
	{
		getblk(iunit, in_node, ++iblk);
		decnum(blkno, iblk);
		inum = 0;
	}
	w = &node0;
	r = &in_node[inum++];
	q = 16;
	do *w++ = *r++; while (--q);
}

decnum(s, n)
register char *s;
register int n;
{
	if (n/10 != 0) s = decnum(s, n/10);
	*s++ = n%10 + '0';
	*s = 0;
	return(s);
}

puti()
{
	register *r, *w, q;

	w = &out_node[onum];
	r = &node1;
	q = 16;
	do *w++ = *r++; while (--q);
	if (++onum == 16)
	{
		putblk(out_node, oblk++);
		onum = 0;
	}
}

ipurge()
{
	register *r, *w, q;

	if (onum)
	{
		r = &out_node[onum];
		q = 16*(16-onum);
		do *r++ = 0; while (--q);
		putblk(out_node, oblk++);
	}

	r = out_node;
	q = 256;
	do *r++ = 0; while (--q);

	while (oblk < 2 + super1.s_isize) putblk(out_node, oblk++);

	iblk = 1;
	inum = 16;
	iunit = fo;
	purgepool();
}

nxtblk()
{
	static int cyl, sector, track;
	register char *block;

	for (;;)
	{
		lastblock = block = (cyl * NTRACK + track) * NSEC + adr[sector];
		if (++sector >= NSEC)
		{
			sector = 0;
			if (++track >= NTRACK)
			{
				cyl++;
				track = 0;
			}
		}
		if (block >= 2 + super1.s_isize) return(block);
	}
}

freelist()
{
	register cyl, sector, track;
	extern int ldivr;
	char *block;

	cyl = ldiv(0, super1.s_fsize, NTRACK*NSEC);
	track = ldivr / NSEC;		/* first non-usable block */
	sector = ldivr % NSEC;
	bfree(0);			/* end-of-list sentinel */

	while (sector) bfree((cyl * NTRACK + track) * NSEC + --sector);
	for (;;)
	{
		if (sector-- == 0)
		{
			sector =+ NSEC;
			if (track-- == 0)
			{
				track =+ NTRACK;
				cyl--;
			}
		}
		block = (cyl * NTRACK + track) * NSEC + adr[sector];
		if (block == lastblock) return;
		if (block >= 2 + super1.s_isize) bfree(block);
	}
}

bfree(b)
{
	register *r, *q, w;
	if (super1.s_nfree == 100)
	{
		r = in;
		*r++ = super1.s_nfree;
		q = super1.s_free;
		w = 100;
		do *r++ = *q++; while (--w);
		putblk(in, b);
		super1.s_nfree = 0;
	}
	super1.s_free[super1.s_nfree++] = b;
}

copyi()
{
	register int w, ww;
	int *r, *q;

	r = &node0;
	q = &node1;
	w = 16;
	do *q++ = *r++; while (--w);

	if (w = node1.i_mode & IFMT)
	{
		if (w == IFDIR) copydir();
		puti();
		return;
	}

	if ((node1.i_mode&ILARG) == 0)
	{
		for (w = 0; w < 8; w++) 
			if (node1.i_addr[w])
			{
				getblk(fi, in, node1.i_addr[w]);
				node1.i_addr[w] = nxtblk();
				putblk(in, node1.i_addr[w]);
			}
		puti();
		return;
	}
	for (w = 0; w < 7; w++) 
		if (node1.i_addr[w])
		{
			getblk(fi, ind0, node1.i_addr[w]);
			node1.i_addr[w] = nxtblk();
			for (ww = 0; ww < 256; ww++)
				if (ind0[ww])
				{
					getblk(fi, in, ind0[ww]);
					ind0[ww] = nxtblk();
					putblk(in, ind0[ww]);
				}
			putblk(ind0, node1.i_addr[w]);
		}

	if (node1.i_addr[7])
	{
		getblk(fi, ind0, node1.i_addr[7]);
		node1.i_addr[7] = nxtblk();
		for (w = 0; w < 256; w++)
			if (ind0[w])
			{
				getblk(fi, ind1, ind0[w]);
				ind0[w] = nxtblk();
				for (ww = 0; ww < 256; ww++)
					if (ind1[ww])
					{
						getblk(fi, in, ind1[ww]);
						ind1[ww] = nxtblk();
						putblk(in, ind1[ww]);
					}
				putblk(ind1, ind0[w]);
			}
		putblk(ind0, node1.i_addr[7]);
	}
	puti();
}

putdir(blk)
{
	register *to, *from, cntr;
	int count;

	to = upto;
	getblk(fi, from = in, blk);
	for (count = 0; count < 32; count++)
	{
		if (! *from)		/* valid entry ? */
		{
			from =+ 8;
			continue;
		}
		if ((dirent & 037) == 0)
		{
			if (diriaddr == -1 && dirent == 256)	/* convert to large file */
			{
				node1.i_mode =| ILARG;
				node1.i_addr[diriaddr = 0] = ind1[0];
				for (cntr = 0; cntr < 7; cntr++)	/* at least 8 buffers have been guaranteed */
					bpl[inpool + cntr - 8].bn = ind1[cntr] = ind1[cntr + 1];
				bpl[inpool - 1].bn = ind1[7] = nxtblk();
			}
			else if (diriaddr != -1 && (dirent & 017777) == 0)
			{
				putblk(ind1, node1.i_addr[diriaddr]);
				node1.i_addr[++diriaddr] = nxtblk();
				dirind1 = 0;
			}
			to = grablock(ind1[dirind1++] = nxtblk());
		}
		for (cntr = 0; cntr < 8; cntr++) *to++ = *from++;	/* copy name */
		dirent++;
	}
	upto = to;
}

copydir()
{
	register w, ww;
	register *p;

	dirent = 0;
	diriaddr = -1;
	dirind1 = 0;
	if ((node1.i_mode & ILARG) == 0)
	{
		for (w = 0; w < 8; w++) if (node1.i_addr[w]) putdir(node1.i_addr[w]);
	}
	else
	{
		if (NPOOL - inpool < 8) purgepool();	/* guarantees 8 buffers - see `putdir' */
		node1.i_mode =& ~ILARG;
		for (w = 0; w < 7; w++)
			if (node1.i_addr[w])
			{
				getblk(fi, ind0, node1.i_addr[w]);
				for (ww = 0; ww < 256; ww++)
					if (ind0[ww]) putdir(ind0[ww]);
			}
		if (diriaddr != -1) while (dirind1 < 256) ind1[dirind1++] = 0;	/* clear rest of pointers */
	}
	node1.i_size0 = (dirent >> 12) & 017;
	node1.i_size1 = dirent << 4;
	if (diriaddr == -1)
	{
		w = -1;
		for (ww = 0; ww < dirind1; node1.i_addr[++w] = ind1[ww++]);
	}
	for (p = upto; p < &bpl[inpool]; *p++ = 0);	/* clear rest of directory */
	if (diriaddr != -1) putblk(ind1, node1.i_addr[w = diriaddr]);
	while (w < 7) node1.i_addr[++w] = 0;
}

reldir()
{
	register int i, j;

	if ((node0.i_mode & ILARG) == 0)
	{
		for (i=0; i < 8; i++) relx(node0.i_addr[i]);
		return;
	}
	for (i=0; i < 7; i++)
		if (node0.i_addr[i])
		{
			getblk(fo, ind0, node0.i_addr[i]);
			for (j = 0; j < 256; j++) relx(ind0[j]);
		}
}

relx(b)
{
	register struct  direct *p;
	register int i;

	if (b == 0) return;
	getblk(fo, in, b);
	p = in;
	i = 32;
	do
	{
		if (p->inum) p->inum = iindex[p->inum];
		p++;
	} while (--i);
	putblk(in, b);
}

counti()
{
	register i,j,n;

	n = 0;
	for (i = 0; i < super0.s_isize; i++)
	{
		getblk(fi, &in_node, 2+i);
		for (j = 0; j < 16; j++)
			if (in_node[j].i_mode & IALLOC) n++;
	}
	return((n + 15) / 16);
}

countfree()
{
	register n,m;

	n = super0.s_nfree;
	if (n)
	{
		m = super0.s_free[0];
		while (m)
		{
			getblk(fi, in, m);
			n =+ in[0];
			m = in[1];
		}
	}
	return(n);
}

printf(s, a)
register char *s;
{
	register c, *p;

	p = &a;
	while (c = *s++)
	{
		if (c == '%')
		{
			if ((c = *s++) == 'd')
			{
				printl(*p++);
				continue;
			}
			if (c == 's')
			{
				printf(*p++);	/* CARE !! */
				continue;
			}
			if (c == 0) return;
		}
		putchar(c);
	}
}

printl(n)
register unsigned n;
{
	register i;

	i = n % 10;
	if (n =/ 10) printl(n);
	putchar(i + '0');
}