AUSAM/source/S/dcopy.c
#
#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');
}