V10/cmd/arff.c

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

static	char *sccsid = "@(#)arff.c	4.7 (Berkeley) 81/07/08";
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <signal.h>
#include <stdio.h>
#define dbprintf printf
struct rt_dat {
unsigned short	int	rt_yr:5;	/* Year - 1972 */
unsigned short	int	rt_dy:5;	/* day */
unsigned short	int	rt_mo:5;	/* month */
};
struct	rt_axent {
	char	rt_sent[14];
};

struct rt_ent {
	char  rt_pad;			/* unusued */
	char  rt_stat;			/* Type of entry, or end of seg */
	unsigned short rt_name[3];	/* Name, 3 words in rad50 form */
	short rt_len;			/* Length of file */
	char  rt_chan;			/* Only used in temporary files */
	char  rt_job;			/* Only used in temporary files */
	struct rt_dat rt_date;		/* Creation Date */
};
#define RT_TEMP 1
#define RT_NULL 2
#define RT_FILE 4
#define RT_ESEG 8
#define RT_BLOCK 512
#define RT_DIRSIZE 31			/* max # of directory segments */
struct rt_head {
	short	rt_numseg;		/* number of segments available */
	short	rt_nxtseg;		/* segment no of next log. seg */
	short	rt_lstseg;		/* highest seg currenltly open */
	unsigned short	rt_entpad;	/* extra words/dir. entry      */
	short	rt_stfile;		/* block no where files begin  */
};
struct	rt_dir {
	struct rt_head	rt_axhead;
	struct rt_ent	rt_ents[72];
	char	_dirpad[6];
};
extern struct rt_dir	rt_dir[RT_DIRSIZE];
extern int		rt_entsiz;
extern int		floppydes;
extern char		*rt_last;
typedef struct fldope {
	int	startad;
	int	count;
struct	rt_ent	*rtdope;
} FLDOPE;
#define	FL_BLOCK 128
FLDOPE *lookup();
#define rt(p) ((struct rt_ent *) p )
#define Ain1 03100
#define Ain2 050
#define flag(c) (flg[(c) - 'a'])

char	*man	=	{ "rxtd" };

char zeroes[512];
extern char *val;
extern char table[256];
struct rt_dir	
   rt_dir[RT_DIRSIZE] = {{{4,0,1,0,14},{0,RT_NULL,{0,0,0},494,0}, {0,RT_ESEG}}};
int		rt_entsiz;
int		rt_nleft;
struct rt_ent	*rt_curend[RT_DIRSIZE];
int		floppydes;
int		dirdirty;
char		*rt_last;
char		*defdev = "/dev/floppy";

char	*opt	=	{ "vf" };

int	signum[] = {SIGHUP, SIGINT, SIGQUIT, 0};
long	lseek();
int	rcmd();
int	dcmd();
int	xcmd();
int	tcmd();
int	(*comfun)();
char	flg[26];
char	**namv;
int	namc;
int	file;


main(argc, argv)
char *argv[];
{
	register char *cp;

	/* register i;
	for(i=0; signum[i]; i++)
		if(signal(signum[i], SIG_IGN) != SIG_IGN)
			signal(signum[i], sigdone); */
	if(argc < 2)
		usage();
	cp = argv[1];
	for(cp = argv[1]; *cp; cp++)
	switch(*cp) {
	case 'm':
	case 'v':
	case 'u':
	case 'w':
		flg[*cp - 'a']++;
		continue;
	case 'c':
		{
#define SURE	"Are you sure you want to clobber the floppy?\n"
			int tty;
			char response[128];
			tty = open("/dev/tty",2);
			write(tty,SURE,sizeof(SURE));
			read(tty,response,sizeof(response));
			if(*response!='y')
				exit(50);
			flag('c')++;
			close(tty);
		}
		dirdirty++;
		continue;

	case 'r':
		setcom(rcmd);
		flag('r')++;
		continue;

	case 'd':
		setcom(dcmd);
		flag('d')++;
		continue;

	case 'x':
		setcom(xcmd);
		continue;

	case 't':
		setcom(tcmd);
		continue;

	case 'f':
		defdev = argv[2];
		argv++;
		argc--;
		continue;


	default:
		fprintf(stderr, "arff: bad option `%c'\n", *cp);
		exit(1);
	}
	namv = argv+2;
	namc = argc-2;
	if(comfun == 0) {
		if(flag('u') == 0) {
			fprintf(stderr, "arff: one of [%s] must be specified\n", man);
			exit(1);
		}
		setcom(rcmd);
	}
	(*comfun)();
	exit(notfound());
}

setcom(fun)
int (*fun)();
{

	if(comfun != 0) {
		fprintf(stderr, "arff: only one of [%s] allowed\n", man);
		exit(1);
	}
	comfun = fun;
}

usage()
{

	fprintf(stderr, "usage: arff [%s][%s] archive files ...\n", opt, man);
	exit(1);
}

notfound()
{
	register i, n;

	n = 0;
	for(i=0; i<namc; i++)
		if(namv[i]) {
			fprintf(stderr, "arff: %s not found\n", namv[i]);
			n++;
		}
	return(n);
}

phserr()
{

	fprintf(stderr, "arff: phase error on %s\n", file);
}

mesg(c, name)
char *name;
{

	if(flag('v'))
		if(c != 'c' || flag('v') > 1)
			printf("%c - %s\n", c, name);
}

tcmd()
{
	register char *de;
	int segnum;
	register char *last;
	FLDOPE *lookup(), *dope;
	int nleft; register i;
	register struct rt_ent *rde;

	rt_init();
	if(namc==0)
	    for (segnum=0; segnum >= 0;    /* for all dir. segments */
		 segnum = rt_dir[segnum].rt_axhead.rt_nxtseg - 1) {
		last = rt_last + segnum*2*RT_BLOCK;
		for(de=((char *)&rt_dir[segnum])+10; de <= last; 
		    de += rt_entsiz) {
			if(rtls(rt(de))) {
				nleft = (last - de) / rt_entsiz;
				printf("\n%d entries remaining",nleft);
				printf(" in directory segment %d.\n",segnum+1);
				break;
			}
		}
	    }
	else
		for(i = 0; i < namc; i++) {
			if(dope = lookup(namv[i])) {
				rde = dope->rtdope;
				rtls(rde);
				namv[i] = 0;
			}
		}
}

rtls(de)
register struct rt_ent *de;
{
	int month,day,year;
	char name[12], ext[4];

	if(flag('v'))
		switch(de->rt_stat) {
		case RT_TEMP:
			printf("Tempfile:\n");
		case RT_FILE:
			unrad50(2,de->rt_name,name);
			unrad50(1,&(de->rt_name[2]),ext);
			day = de->rt_date.rt_dy;
			year = de->rt_date.rt_yr + 72;
			month = de->rt_date.rt_mo;
			printf("%6.6s  %3.3s	%02d/%02d/%02d	%d\n",name,
				ext,month,day,year,de->rt_len);
			break;

		case RT_NULL:
			printf("%-25.9s	%d\n","<UNUSED>",de->rt_len);
			break;

		case RT_ESEG:
			return(1);
		}
	else {
		switch(de->rt_stat) {
		case RT_TEMP:
		case RT_FILE:
			sunrad50(name,de->rt_name);
			printf(name);putchar('\n');
			break;

		case RT_ESEG:
			return(1);

		case RT_NULL:
			break;
		}
	}
	return(0);
}
xcmd()
{
	register char *de;
	int segnum;
	register char *last;
	char name[12];
	register int i;

	rt_init();
	if(namc==0)
	    for (segnum=0; segnum >= 0;    /* for all dir. segments */
		 segnum = rt_dir[segnum].rt_axhead.rt_nxtseg - 1) {
		last = rt_last + segnum*2*RT_BLOCK;
		for(de=((char *)&rt_dir[segnum])+10; de <= last; 
		    de += rt_entsiz) {
			sunrad50(name,rt(de)->rt_name);
			rtx(name);
		}
	    }
	else
		for(i = 0; i < namc; i++)
		if(rtx(namv[i])==0) namv[i] = 0;
}
rtx(name)
char *name;
{
	register FLDOPE *dope;
	FLDOPE *lookup();
	register startad, count;
	int file; char buff[RT_BLOCK];


	if(dope = lookup(name)) {
		mesg('x', name);
		file = creat(name, 0666);
		if(file < 0) return(1);
		count = dope->count;
		startad = dope->startad;
		for( ; count > 0 ; count -= RT_BLOCK) {
			lread(startad,RT_BLOCK,buff);
			write(file,buff,RT_BLOCK);
			startad += RT_BLOCK;
		}
		close(file);
		return(0);
	}
	return(1);
}
rt_init()
{
	static initized = 0;
	register char *de;
	register i;
	int dirnum;
	char *mode;
	register char *last;
	FILE *temp_floppydes;

	if(initized) return;
	initized = 1;
	if(flag('c') || flag('d') || flag('r'))
		mode = "r+";
	else
		mode = "r";
	if((temp_floppydes = fopen(defdev, mode)) == NULL) {
		perror(defdev);
		exit(1);
	}
	floppydes = fileno(temp_floppydes);
	if(flag('c')==0) {
		lread(6*RT_BLOCK,2*RT_BLOCK,(char *)&rt_dir[0]);
		dirnum = rt_dir[0].rt_axhead.rt_numseg;
		if (dirnum > RT_DIRSIZE) {
		   fprintf(stderr,"arff: too many directory segments\n");
		   exit(1);
		}
		for (i=1; i<dirnum; i++)
		   lread((6+2*i)*RT_BLOCK,2*RT_BLOCK,(char *)&rt_dir[i]);
	} else
		dirnum = 1;

	rt_entsiz = 2*rt_dir[0].rt_axhead.rt_entpad + 14;
	rt_entsiz = 14;			/* assume rt_entpad = 0 ??? */
	rt_last = ((char *) &rt_dir[0]) + 10 + 1014/rt_entsiz*rt_entsiz; 
	rt_nleft = 0;
	
	for (i=0; i<dirnum; i++) {
	    if (rt_dir[i].rt_axhead.rt_nxtseg >= RT_DIRSIZE
	    ||  rt_dir[i].rt_axhead.rt_lstseg >= RT_DIRSIZE) {
		fprintf(stderr, "arff: awful directory linkage\n");
		exit(1);
	    }
  	    last = rt_last + i*2*RT_BLOCK;
	    for(de=((char *)&rt_dir[i])+10; de <= last; de += rt_entsiz) {
		if(rt(de)->rt_stat==RT_ESEG) break;
	    }
	    rt_curend[i] = rt(de);
	    rt_nleft += (last - de) / rt_entsiz;
	}
}

static FLDOPE result;
FLDOPE *
lookup(name)
char * name;
{
	unsigned short rname[3];
	register char *de;
	int segnum;
	register char *last;
	register index;

	srad50(name,rname);

	/* 
	 *  Search for name, accumulate blocks in index
	 */
	rt_init();
	for (segnum=0; segnum >= 0;    /* for all dir. segments */
             segnum = rt_dir[segnum].rt_axhead.rt_nxtseg - 1) {
	    index = 0;
	    last = rt_last + segnum*2*RT_BLOCK;
	    for(de=((char *)&rt_dir[segnum])+10; 
		rt(de)->rt_stat != RT_ESEG; de += rt_entsiz) {
		switch(rt(de)->rt_stat) {
		case RT_FILE:
		case RT_TEMP:
		if(samename(rname,rt(de)->rt_name))
			goto found;
		case RT_NULL:
			index += rt(de)->rt_len;
		}
	    }
        }
	return((FLDOPE *) 0);
found:	result.count = rt(de)->rt_len * RT_BLOCK;
	result.startad = RT_BLOCK * (rt_dir[segnum].rt_axhead.rt_stfile + index);
	result.rtdope = (struct rt_ent *) de;
	return(&result);
}
static
samename(a,b)
unsigned short a[3],b[3];
{
	return( a[0]==b[0] && a[1]==b[1] && a[2]==b[2] );
}


rad50(cp,out)
register unsigned char *cp;
unsigned short *out;
{
	register index;
	register temp;

	for(index = 0;*cp; index++) {

		temp = Ain1 * table[*cp++];
		if(*cp!=0) {
			temp += Ain2 * table[*cp++];

			if(*cp!=0) 
				temp += table[*cp++];
		}

		out[index] = temp;
	}
}
#define reduce(x,p,q) \
	(x = v[p/q], p %= q);

unrad50(count,in,cp)
unsigned short *in;
register char *cp;
{
	register i, temp; register unsigned char *v = (unsigned char *) val;
	
	for(i = 0; i < count; i++) {
		temp = in[i];

		reduce (*cp++,temp,Ain1);
		reduce (*cp++,temp,Ain2);
		reduce (*cp++,temp,1);
	}
	*cp=0;
}

srad50(name,rname)
register char * name;
register unsigned short *rname;
{
	register index; register char *cp;
	char file[7],ext[4];
	/* 
	 * Find end of pathname
	 */
	for(cp = name; *cp++; );
	while(cp >= name && *--cp != '/');
	cp++;
	/* 
	 * Change to rad50
	 *
	 */
	for(index = 0; *cp; ){
		file[index++] = *cp++;
		if(*cp=='.') {
			cp++;
			break;
		}
		if(index>=6) {
			break;
		}
	}
	file[index] = 0;
	for(index = 0; *cp; ){
		ext[index++] = *cp++;
		if(*cp=='.' || index>=3) {
			break;
		}
	}
	ext[index]=0;
	rname[0] = 0;
	rname[1] = 0;
	rname[2] = 0;
	rad50((unsigned char *)file,rname);
	rad50((unsigned char *)ext,rname+2);
}
sunrad50(name,rname)
unsigned short rname[3];
register char *name;
{
	register char *cp, *cp2;
	char ext[4];

	unrad50(2,rname,name);
	unrad50(1,rname + 2,ext);
	/* Jam name and extension together with a dot
	   deleting white space */
	for(cp = name; *cp++;);--cp;  while(*--cp==' ' && cp>=name);
	*++cp = '.';cp++;
	for(cp2=ext; *cp2!=' ' && cp2 < ext + 3;) {
		*cp++ = *cp2++;
	}
	*cp=0;
	if(cp[-1]=='.') cp[-1] = 0;
}

static char *oval = " ABCDEFGHIJKLMNOPQRSTUVWXYZ$.@0123456789";
static char *val = " abcdefghijklmnopqrstuvwxyz$.@0123456789";
static char table[256] = {
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 
0, 29, 29, 29, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 29, 
30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 29, 29, 29, 29, 29, 29, 
29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29, 
29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29, 
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 
0, 29, 29, 29, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 29, 
30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 29, 29, 29, 29, 29, 29, 
29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29, 
29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29 };
		
long
trans(logical)
register int logical;
{
	/*  Logical to physical adress translation */
	register int sector, bytes, track;

	logical += 26 * 128;
	bytes = (logical & 127);
	logical >>= 7;
	sector = logical % 26;
	if(sector >= 13)
		sector = sector *2 +1;
	else
		sector *= 2;
	sector += 26 + ((track = (logical / 26)) - 1) * 6;
	sector %= 26;
	return( (((track *26) + sector) << 7) + bytes);
}
lread(startad,count,obuff)
register startad, count;
register char * obuff;
{
	long trans();
	extern floppydes;
	int chunk;

	rt_init();
	if(flag('m')==0)
		chunk = FL_BLOCK;
	else
		chunk = RT_BLOCK;
	for (; count > 0; count -= chunk, obuff += chunk, startad += chunk) {
		lseek(floppydes,
		    (long) (flag('m') ? startad : trans(startad)), 0);
		if (read(floppydes, obuff, chunk) != chunk)
			fprintf(stderr, "arff: read error, block %d\n", startad / RT_BLOCK);
	}
}

lwrite(startad,count,obuff)
register startad, count;
register char * obuff;
{
	long trans();
	extern floppydes;
	int chunk;

	rt_init();
	if(flag('m')==0)
		chunk = FL_BLOCK;
	else
		chunk = RT_BLOCK;
	for (; count > 0; count -= chunk, obuff += chunk, startad += chunk) {
		lseek(floppydes,
		    (long) (flag('m') ? startad : trans(startad)), 0);
		if (write(floppydes, obuff, chunk) != chunk)
			fprintf(stderr, "arff: write error, block %d\n", startad / RT_BLOCK);
	}
}

rcmd()
{
	register int i;

	rt_init();
	if (namc>0)
		for(i = 0; i < namc; i++)
			if(rtr(namv[i])==0) namv[i]=0;
}

rtr(name)
char *name;
{
	register FLDOPE *dope;
	struct stat buf;
	FLDOPE *flcreat();

	if(stat(name,&buf)<0) {
		perror(name);
		return (-1);
	}
	if ((dope = flcreat(name, buf.st_size, buf.st_mtime)) == NULL)
		return (-1);
	mesg('r', name);
	toflop(name, buf.st_size, dope);
	return (0);
}

FLDOPE *
flcreat(name, size, mtime)
char *name;
long size;
time_t mtime;
{
	register FLDOPE *dope;
	register struct rt_ent *de;
	int segnum;

	if ((dope = lookup(name)) != NULL
	&&  size <= dope->rtdope->rt_len * RT_BLOCK)
		return (dope);
	for (segnum=0; segnum != -1; segnum = rt_dir[segnum].rt_axhead.rt_nxtseg - 1) {
		for(de = rt_dir[segnum].rt_ents; de->rt_stat != RT_ESEG; de++)
			if (de->rt_stat == RT_NULL
			&&  size <= de->rt_len * RT_BLOCK) {
				if (dope)
					delete(dope);
				mkent(de, segnum, size, name, mtime);
				goto found;
			}
	}
	printf("%s: no slot or no space for file\n", name);
	return (NULL);
found:
	if (dope = lookup(name))
		return (dope);
	fprintf(stderr, "%s: internal error, added then not found\n", name);
	return (NULL);
}

mkent(de,segnum,size,name,mtime)
register struct rt_ent *de;
int segnum;
long size;
char *name;
time_t mtime;
{
	struct tm *localtime(); register struct tm *timp;
	register struct rt_ent *workp; int count;
	
	count = (((size - 1)/RT_BLOCK) + 1);
						/* Make sure there is room */
	if(de->rt_len==count)
		goto overwrite;
	if(rt_curend[segnum] == (rt_last + (segnum*2*RT_BLOCK))) {
						/* no entries left on segment */
		if(flag('o'))
			goto overwrite;
		fprintf(stderr,"Directory segment #%d full on  %s\n",segnum+1,
                    defdev);
		exit(1);
	}	
					/* copy directory entries up */
	for(workp = rt_curend[segnum]+1; workp > de; workp--)
		*workp = workp[-1];
	de[1].rt_len -= count;
	de->rt_len = count;
	rt_curend[segnum]++;
	rt_nleft--;
overwrite:
	srad50(name,de->rt_name);
	timp = localtime(&mtime);
	de->rt_date.rt_dy = timp->tm_mday + 1;
	de->rt_date.rt_mo = timp->tm_mon + 1;
	de->rt_date.rt_yr = timp->tm_year - 72;
	de->rt_stat = RT_FILE;
	de->rt_pad = 0;
	de->rt_chan = 0;
	de->rt_job = 0;
	lwrite((6+segnum*2)*RT_BLOCK,2*RT_BLOCK,(char *)&rt_dir[segnum]);
}

toflop(name,ocount,dope)
char *name;
register FLDOPE *dope;
long ocount;
{
	register file, n, startad = dope->startad, count = ocount;
	char buff[RT_BLOCK];
	
	file = open(name,0);
	if(file < 0) {
		fprintf(stderr, "arff: couldn't open %s\n",name);exit(1);}
	for( ; count >= RT_BLOCK; count -= RT_BLOCK) {
		read(file,buff,RT_BLOCK);
		lwrite(startad,RT_BLOCK,buff);
		startad += RT_BLOCK;
	}
	read(file,buff,count);
	close(file);
	if(count <= 0) return;
	for(n = count; n < RT_BLOCK; n ++) buff[n] = 0;
	lwrite(startad,RT_BLOCK,buff);
	count = (dope->rtdope->rt_len * RT_BLOCK - ocount) / RT_BLOCK ;
	if(count <= 0) return;
	for( ; count > 0 ; count--) {
		startad += RT_BLOCK;
		lwrite(startad,RT_BLOCK,zeroes);
	}
}
dcmd()
{
	register int i;

	rt_init();
	if(namc)
		for(i = 0; i < namc; i++)
			if(rtk(namv[i])==0) namv[i]=0;
	if(dirdirty)
		scrunch();
	
}
rtk(name)
char *name;
{
	FLDOPE *dope;
	register struct rt_ent *de;
	FLDOPE *lookup();

	if(dope = lookup(name)) {
		mesg('d', name);
		delete(dope);
		return(0);
	}
	return(1);
}

delete(dope)
FLDOPE *dope;
{
	register struct rt_ent *de;

	de = dope->rtdope;
	de->rt_stat = RT_NULL;
	de->rt_name[0] = 0;
	de->rt_name[1] = 0;
	de->rt_name[2] = 0;
	* ((unsigned short *) & (de->rt_date)) = 0;
	dirdirty = 1;
}

scrunch() {
	register struct rt_ent *de , *workp;
	register segnum;
	for (segnum=0; segnum != -1;    /* for all dir. segments */
	     segnum = rt_dir[segnum].rt_axhead.rt_nxtseg - 1) {
	    dirdirty = 0;
	    for(de = rt_dir[segnum].rt_ents; de <= rt_curend[segnum]; de++) {
		if(de->rt_stat==RT_NULL && de[1].rt_stat==RT_NULL) {
			(de+1)->rt_len += de->rt_len;
			for(workp = de; workp < rt_curend[segnum]; workp++)
				*workp = workp[1];
			de--;
			rt_curend[segnum]--;
			rt_nleft++;
			dirdirty = 1;
		}
	    }
	    if (dirdirty)
	    lwrite((6+segnum*2)*RT_BLOCK,2*RT_BLOCK,(char *)&rt_dir[segnum]);
	}
}