xref: /csrg-svn/old/arff/arff.c (revision 48343)
1*48343Sbostic /*-
2*48343Sbostic  * Copyright (c) 1980 The Regents of the University of California.
3*48343Sbostic  * All rights reserved.
4*48343Sbostic  *
5*48343Sbostic  * %sccs.include.proprietary.c%
622483Sdist  */
722483Sdist 
89877Ssam #ifndef lint
922483Sdist char copyright[] =
10*48343Sbostic "@(#) Copyright (c) 1980 The Regents of the University of California.\n\
1122483Sdist  All rights reserved.\n";
12*48343Sbostic #endif /* not lint */
134879Ssam 
1422483Sdist #ifndef lint
15*48343Sbostic static char sccsid[] = "@(#)arff.c	5.8 (Berkeley) 04/18/91";
16*48343Sbostic #endif /* not lint */
1722483Sdist 
18954Sbill #include <sys/types.h>
19954Sbill #include <sys/stat.h>
2013605Ssam #include <sys/time.h>
2137979Sbostic #include <sys/signal.h>
2237979Sbostic #include <sys/file.h>
23954Sbill #include <stdio.h>
2437979Sbostic #include "pathnames.h"
254879Ssam 
26954Sbill #define dbprintf printf
274879Ssam 
28954Sbill struct rt_dat {
294879Ssam 	u_short	rt_yr:5;	/* year-1972 */
304879Ssam 	u_short	rt_dy:5;	/* day */
314879Ssam 	u_short	rt_mo:5;	/* month */
32954Sbill };
334879Ssam 
34954Sbill struct	rt_axent {
35954Sbill 	char	rt_sent[14];
36954Sbill };
37954Sbill 
38954Sbill struct rt_ent {
394879Ssam 	char	rt_pad;		/* unusued */
4030238Sbostic 	u_char	rt_stat;	/* type of entry, or end of seg */
414879Ssam 	u_short	rt_name[3];	/* name, 3 words in rad50 form */
427319Swnj 	u_short	rt_len;		/* length of file */
4330238Sbostic 	u_char	rt_chan;	/* only used in temporary files */
444879Ssam 	char	rt_job;		/* only used in temporary files */
459877Ssam 	struct	rt_dat rt_date;	/* creation date */
46954Sbill };
474879Ssam 
484879Ssam #define RT_TEMP		1
494879Ssam #define RT_NULL		2
504879Ssam #define RT_FILE		4
5130238Sbostic #define RT_PFILE	(0200|RT_FILE)	/* protected file */
524879Ssam #define RT_ESEG		8
534879Ssam 
544879Ssam #define RT_BLOCK	512	/* block size */
554879Ssam #define RT_DIRSIZE	31	/* max # of directory segments */
564879Ssam 
57954Sbill struct rt_head {
584879Ssam 	short	rt_numseg;	/* # of segments available */
594879Ssam 	short	rt_nxtseg;	/* # of next logical segment */
604879Ssam 	short	rt_lstseg;	/* highest seg currently open */
614879Ssam 	u_short	rt_entpad;	/* extra words/directory entry */
624879Ssam 	short	rt_stfile;	/* block # where files begin */
63954Sbill };
644879Ssam 
65954Sbill struct	rt_dir {
66954Sbill 	struct rt_head	rt_axhead;
67954Sbill 	struct rt_ent	rt_ents[72];
684879Ssam 	char		_dirpad[6];
69954Sbill };
704879Ssam 
7126131Sbloom #define rd_numseg rt_axhead.rt_numseg
7226131Sbloom #define rd_nxtseg rt_axhead.rt_nxtseg
7326131Sbloom #define rd_lstseg rt_axhead.rt_lstseg
7426131Sbloom #define rd_entpad rt_axhead.rt_entpad
7526131Sbloom #define rd_stfile rt_axhead.rt_stfile
7626131Sbloom 
77954Sbill typedef struct fldope {
78954Sbill 	int	startad;
79954Sbill 	int	count;
80954Sbill struct	rt_ent	*rtdope;
81954Sbill } FLDOPE;
824879Ssam 
83954Sbill FLDOPE *lookup();
844879Ssam 
859877Ssam #define	rt(p)	((struct rt_ent *) p )
869877Ssam #define	Ain1	03100
879877Ssam #define	Ain2	050
889877Ssam #define	flag(c)	(flg[('c') - 'a'])
89954Sbill 
909877Ssam char	*man = "rxtd";
919877Ssam char	zeroes[512];
92954Sbill 
93954Sbill extern char *val;
94954Sbill extern char table[256];
954879Ssam struct rt_dir rt_dir[RT_DIRSIZE] = {
9633133Sbostic 	{
979877Ssam 	{ 4, 0, 1, 0, 14 },
9826131Sbloom 	{ { 0, RT_NULL, { 0, 0, 0 }, 486, 0 },
999877Ssam 	  { 0, RT_ESEG } }
10033133Sbostic 	}
1014879Ssam };
102954Sbill 
10326131Sbloom struct rt_dir rt_nulldir = {
10426131Sbloom 	{ 0, 0, 0, 0, 0 },
10526131Sbloom 	{ { 0, RT_NULL, { 0, 0, 0 }, 0, 0 },
10626131Sbloom 	  { 0, RT_ESEG } }
10726131Sbloom };
10826131Sbloom 
1094879Ssam int	rt_entsiz;
1104879Ssam int	rt_nleft;
1114879Ssam struct rt_ent *rt_curend[RT_DIRSIZE];
1124879Ssam int	floppydes;
1134879Ssam int	dirdirty;
1144879Ssam char	*rt_last;
11537979Sbostic char	*defdev = _PATH_FLOPPY;
116954Sbill 
11726131Sbloom char *opt = "vfbcm";
1184879Ssam 
1194879Ssam extern long lseek();
1204879Ssam int	rcmd(), dcmd(), xcmd(), tcmd();
1214879Ssam 
122954Sbill int	(*comfun)();
123954Sbill char	flg[26];
124954Sbill char	**namv;
125954Sbill int	namc;
126954Sbill 
main(argc,argv)127954Sbill main(argc, argv)
1284879Ssam 	char *argv[];
129954Sbill {
130954Sbill 	register char *cp;
131954Sbill 
1324879Ssam 	if (argc < 2)
133954Sbill 		usage();
1344879Ssam 	for (cp = argv[1]; *cp; cp++)
1354879Ssam 		switch (*cp) {
136954Sbill 
1374879Ssam 		case 'm':
1384879Ssam 		case 'v':
1394879Ssam 		case 'u':
1404879Ssam 		case 'w':
14126131Sbloom 		case 'b':
1424879Ssam 			flg[*cp-'a']++;
1434879Ssam 			continue;
1444879Ssam 		case 'c':
14513910Ssam 			flag(c)++;
1464879Ssam 			dirdirty++;
1474879Ssam 			continue;
148954Sbill 
1494879Ssam 		case 'r':
1504879Ssam 			setcom(rcmd);
1514879Ssam 			flag(r)++;
1524879Ssam 			continue;
153954Sbill 
1544879Ssam 		case 'd':
1554879Ssam 			setcom(dcmd);
1564879Ssam 			flag(d)++;
1574879Ssam 			continue;
158954Sbill 
1594879Ssam 		case 'x':
1604879Ssam 			setcom(xcmd);
1614879Ssam 			continue;
162954Sbill 
1634879Ssam 		case 't':
1644879Ssam 			setcom(tcmd);
1654879Ssam 			continue;
166954Sbill 
1674879Ssam 		case 'f':
1684879Ssam 			defdev = argv[2];
1694879Ssam 			argv++;
1704879Ssam 			argc--;
1714879Ssam 			continue;
1724879Ssam 
1734879Ssam 		default:
1744879Ssam 			fprintf(stderr, "arff: bad option `%c'\n", *cp);
1754879Ssam 			exit(1);
1764879Ssam 		}
1774879Ssam 
178954Sbill 	namv = argv+2;
179954Sbill 	namc = argc-2;
1804879Ssam 	if (comfun == 0) {
1814879Ssam 		if (flag(u) == 0) {
1824879Ssam 			fprintf(stderr, "arff: one of [%s] must be specified\n",
1834879Ssam 				man);
184954Sbill 			exit(1);
185954Sbill 		}
186954Sbill 		setcom(rcmd);
187954Sbill 	}
188954Sbill 	(*comfun)();
189954Sbill 	exit(notfound());
190954Sbill }
191954Sbill 
192954Sbill setcom(fun)
1934879Ssam 	int (*fun)();
194954Sbill {
1954879Ssam 	if (comfun != 0) {
196954Sbill 		fprintf(stderr, "arff: only one of [%s] allowed\n", man);
197954Sbill 		exit(1);
198954Sbill 	}
199954Sbill 	comfun = fun;
200954Sbill }
201954Sbill 
usage()202954Sbill usage()
203954Sbill {
2043356Swnj 	fprintf(stderr, "usage: ar [%s][%s] archive files ...\n", opt, man);
205954Sbill 	exit(1);
206954Sbill }
207954Sbill 
notfound()208954Sbill notfound()
209954Sbill {
2104879Ssam 	register i, n = 0;
211954Sbill 
2124879Ssam 	for (i = 0; i < namc; i++)
2134879Ssam 		if (namv[i]) {
214954Sbill 			fprintf(stderr, "arff: %s not found\n", namv[i]);
215954Sbill 			n++;
216954Sbill 		}
2179877Ssam 	return (n);
218954Sbill }
219954Sbill 
tcmd()220954Sbill tcmd()
221954Sbill {
2224879Ssam 	register char *de, *last;
223954Sbill 	FLDOPE *lookup(), *dope;
2244879Ssam 	int segnum, nleft;
2254879Ssam 	register i;
226954Sbill 	register struct rt_ent *rde;
227954Sbill 
228954Sbill 	rt_init();
2299877Ssam 	if (namc != 0) {
2304879Ssam 		for (i = 0; i < namc; i++)
2314879Ssam 			if (dope = lookup(namv[i])) {
232954Sbill 				rde = dope->rtdope;
23326131Sbloom 				(void) rtls(rde);
234954Sbill 				namv[i] = 0;
235954Sbill 			}
2369877Ssam 		return;
2379877Ssam 	}
2389877Ssam 	for (segnum = 0; segnum != -1;
23926131Sbloom 	  segnum = rt_dir[segnum].rd_nxtseg - 1) {
2409877Ssam 		last = rt_last + segnum*2*RT_BLOCK;
2419877Ssam 		for (de = ((char *)&rt_dir[segnum])+10; de <= last;
2429877Ssam 		    de += rt_entsiz)
2439877Ssam 			if (rtls(rt(de))) {
2449877Ssam 				nleft = (last-de)/rt_entsiz;
2459877Ssam #define ENTRIES "\n%d entries remaining in directory segment %d.\n"
2469877Ssam 				printf(ENTRIES, nleft, segnum+1);
2479877Ssam 				break;
2489877Ssam 			}
2499877Ssam 	}
250954Sbill }
2514879Ssam 
rtls(de)252954Sbill rtls(de)
2534879Ssam 	register struct rt_ent *de;
254954Sbill {
2554879Ssam 	int month, day, year;
256954Sbill 	char name[12], ext[4];
257954Sbill 
2584879Ssam 	switch (de->rt_stat) {
2594879Ssam 
2604879Ssam 	case RT_TEMP:
2614879Ssam 		if (flag(v))
262954Sbill 			printf("Tempfile:\n");
2634879Ssam 		/* fall thru...*/
264954Sbill 
2654879Ssam 	case RT_FILE:
26630238Sbostic 	case RT_PFILE:
2674879Ssam 		if (!flag(v)) {
2684879Ssam 			sunrad50(name, de->rt_name);
2694879Ssam 			printf("%s\n", name);
270954Sbill 			break;
271954Sbill 		}
2724879Ssam 		unrad50(2, de->rt_name, name);
2734879Ssam 		unrad50(1, &(de->rt_name[2]), ext);
2744879Ssam 		day = de->rt_date.rt_dy;
2754879Ssam 		year = de->rt_date.rt_yr+72;
2764879Ssam 		month = de->rt_date.rt_mo;
2774879Ssam 		printf("%6.6s  %3.3s	%02d/%02d/%02d	%d\n",name,
2784879Ssam 			ext, month, day, year, de->rt_len);
2794879Ssam 		break;
280954Sbill 
2814879Ssam 	case RT_NULL:
2824879Ssam 		printf("%-25.9s	%d\n","<UNUSED>", de->rt_len);
2834879Ssam 		break;
284954Sbill 
2854879Ssam 	case RT_ESEG:
2869877Ssam 		return (1);
287954Sbill 	}
2889877Ssam 	return (0);
289954Sbill }
2904879Ssam 
xcmd()291954Sbill xcmd()
292954Sbill {
2934879Ssam 	register char *de, *last;
2943346Swnj 	int segnum;
295954Sbill 	char name[12];
296954Sbill 	register int i;
297954Sbill 
298954Sbill 	rt_init();
2999877Ssam 	if (namc != 0) {
3004879Ssam 		for (i = 0; i < namc; i++)
3014879Ssam 			if (rtx(namv[i]) == 0)
3024879Ssam 				namv[i] = 0;
3039877Ssam 		return;
3049877Ssam 	}
3059877Ssam 	for (segnum = 0; segnum != -1;
30626131Sbloom 	     segnum = rt_dir[segnum].rd_nxtseg-1)
3079877Ssam 		for (last = rt_last+(segnum*2*RT_BLOCK),
3089877Ssam 		     de = ((char *)&rt_dir[segnum])+10; de <= last;
30915553Sralph 		     de += rt_entsiz) {
3109877Ssam 			switch (rt(de)->rt_stat) {
3119877Ssam 
3129877Ssam 			case RT_ESEG:
31315553Sralph 				break;	/* exit loop and try next segment */
3149877Ssam 
3159877Ssam 			case RT_TEMP:
3169877Ssam 			case RT_FILE:
31730238Sbostic 			case RT_PFILE:
3189877Ssam 				sunrad50(name,rt(de)->rt_name);
31926131Sbloom 				(void) rtx(name);
3209877Ssam 
3219877Ssam 			case RT_NULL:
32215553Sralph 			default:
32315553Sralph 				continue;
3249877Ssam 			}
32515553Sralph 			break;
32615553Sralph 		}
327954Sbill }
3284879Ssam 
rtx(name)329954Sbill rtx(name)
3304879Ssam 	char *name;
331954Sbill {
332954Sbill 	register FLDOPE *dope;
333954Sbill 	FLDOPE *lookup();
334954Sbill 	register startad, count;
3354879Ssam 	int file;
3364879Ssam 	char buff[512];
337954Sbill 
338954Sbill 
3394879Ssam 	if (dope = lookup(name)) {
3404879Ssam 		if (flag(v))
34126131Sbloom 			(void) rtls(dope->rtdope);
342954Sbill 		else
343954Sbill 			printf("x - %s\n",name);
344954Sbill 
3454879Ssam 		if ((file = creat(name, 0666)) < 0)
3469877Ssam 			return (1);
347954Sbill 		count = dope->count;
348954Sbill 		startad = dope->startad;
349954Sbill 		for( ; count > 0 ; count -= 512) {
35029823Skarels 			(void) lread(startad, 512, buff);
35126131Sbloom 			(void) write(file, buff, 512);
352954Sbill 			startad += 512;
353954Sbill 		}
35426131Sbloom 		(void) close(file);
3559877Ssam 		return (0);
356954Sbill 	}
3579877Ssam 	return (1);
358954Sbill }
3594879Ssam 
rt_init()360954Sbill rt_init()
361954Sbill {
362954Sbill 	static initized = 0;
3634879Ssam 	register char *de, *last;
3643346Swnj 	register i;
3653799Shickman 	int dirnum;
3663799Shickman 	char *mode;
3673799Shickman 	FILE *temp_floppydes;
368954Sbill 
3694879Ssam 	if (initized)
3704879Ssam 		return;
371954Sbill 	initized = 1;
37213910Ssam 	if (flag(c)) {
37313910Ssam 		struct stat sb;
37413910Ssam 		char response[128];
37513910Ssam 		int tty;
37613910Ssam 
37713910Ssam 		if (stat(defdev, &sb) >= 0 && (sb.st_mode & S_IFMT) == S_IFREG)
37813910Ssam 			goto ignore;
37937979Sbostic 		tty = open(_PATH_TTY, O_RDWR);
38013910Ssam #define SURE	"Are you sure you want to clobber the floppy? "
38126131Sbloom 		(void) write(tty, SURE, sizeof (SURE));
38226131Sbloom 		(void) read(tty, response, sizeof (response));
38313910Ssam 		if (*response != 'y')
38413910Ssam 			exit(50);
38526131Sbloom 		(void) close(tty);
38613910Ssam ignore:
38713910Ssam 		;
38813910Ssam 	}
3894879Ssam 	if (flag(c) || flag(d) || flag(r))
3903799Shickman 		mode = "r+";
391954Sbill 	else
3923799Shickman 		mode = "r";
3934879Ssam 	if ((temp_floppydes = fopen(defdev, mode)) == NULL) {
3943799Shickman 		perror(defdev);
3953356Swnj 		exit(1);
3963799Shickman 	} else
3973799Shickman 		floppydes = fileno(temp_floppydes);
3984879Ssam 	if (!flag(c)) {
39929823Skarels 		if (lread(6*RT_BLOCK, 2*RT_BLOCK, (char *)&rt_dir[0]))
40029823Skarels 			exit(2);
40126131Sbloom 		dirnum = rt_dir[0].rd_numseg;
40212012Shelge 		/* check for blank/uninitialized diskette */
40312012Shelge 		if (dirnum <= 0) {
40412012Shelge 			fprintf(stderr,"arff: bad directory format\n");
40512012Shelge 			exit(1);
40612012Shelge 		}
4073346Swnj 		if (dirnum > RT_DIRSIZE) {
4084879Ssam 			fprintf(stderr,"arff: too many directory segments\n");
4094879Ssam 			exit(1);
4103346Swnj 		}
4114879Ssam 		for (i = 1; i < dirnum; i++)
41229823Skarels 		    if (lread((6+2*i)*RT_BLOCK, 2*RT_BLOCK, (char *)&rt_dir[i]))
41329823Skarels 			exit(1);
41426131Sbloom 	} else {
4153489Sroot 		dirnum = 1;
41626131Sbloom 		if (flag(b)) {
41726131Sbloom 			rt_dir[0].rd_numseg = 31;
41826131Sbloom 			rt_dir[0].rd_stfile = 68;
41926131Sbloom 			rt_dir[0].rt_ents[0].rt_len = 20480 - 68;
42026131Sbloom 		}
42126131Sbloom 	}
422954Sbill 
42326131Sbloom 	rt_entsiz = 2*rt_dir[0].rd_entpad + 14;
42426131Sbloom 	/*
42526131Sbloom 	 * We assume that the directory entries have no padding.  This
42626131Sbloom 	 * may not be a valid assumption, but there are numerous point
42726131Sbloom 	 * in the code where it assumes it is an rt_ent structure and
42826131Sbloom 	 * not an rt_entsiz sized structure.
42926131Sbloom 	 */
43026131Sbloom 	rt_entsiz = 14;
4313346Swnj 	rt_last = ((char *) &rt_dir[0]) + 10 + 1014/rt_entsiz*rt_entsiz;
4323346Swnj 	rt_nleft = 0;
4333346Swnj 
4344879Ssam 	for (i = 0; i < dirnum; i++) {
4354879Ssam 		last = rt_last + i*2*RT_BLOCK;
4364879Ssam 		for (de = ((char *)&rt_dir[i])+10; de <= last; de += rt_entsiz)
4374879Ssam 			if (rt(de)->rt_stat == RT_ESEG)
4384879Ssam 				break;
4394879Ssam 		rt_curend[i] = rt(de);
4404879Ssam 		rt_nleft += (last-de)/rt_entsiz;
441954Sbill 	}
442954Sbill }
443954Sbill 
444954Sbill static FLDOPE result;
4454879Ssam 
446954Sbill FLDOPE *
lookup(name)447954Sbill lookup(name)
4484879Ssam 	char *name;
449954Sbill {
450954Sbill 	unsigned short rname[3];
45126131Sbloom 	register char *de;
4523346Swnj 	int segnum;
453954Sbill 	register index;
454954Sbill 
455954Sbill 	srad50(name,rname);
456954Sbill 
4573356Swnj 	/*
458954Sbill 	 *  Search for name, accumulate blocks in index
459954Sbill 	 */
460954Sbill 	rt_init();
4614879Ssam 	for (segnum = 0; segnum != -1;
46226131Sbloom 	     segnum = rt_dir[segnum].rd_nxtseg - 1)
4634879Ssam 	{
4644879Ssam 		index = 0;
4654879Ssam 		for (de=((char *)&rt_dir[segnum])+10;
4664879Ssam 		     rt(de)->rt_stat != RT_ESEG; de += rt_entsiz)
4674879Ssam 			switch(rt(de)->rt_stat) {
4684879Ssam 
4694879Ssam 			case RT_FILE:
47030238Sbostic 			case RT_PFILE:
4714879Ssam 			case RT_TEMP:
4724879Ssam 				if(samename(rname,rt(de)->rt_name)) {
4734879Ssam 					result.count = rt(de)->rt_len * 512;
4744879Ssam 					result.startad = 512*
47526131Sbloom 					    (rt_dir[segnum].rd_stfile + index);
4764879Ssam 					result.rtdope = (struct rt_ent *) de;
4779877Ssam 					return (&result);
4784879Ssam 				}
4794879Ssam 
4804879Ssam 			case RT_NULL:
4814879Ssam 				index += rt(de)->rt_len;
4824879Ssam 			}
4833346Swnj         }
4849877Ssam 	return ((FLDOPE *) 0);
4854879Ssam 
486954Sbill }
4874879Ssam 
488954Sbill static
samename(a,b)4894879Ssam samename(a, b)
4904879Ssam 	u_short a[], b[];
491954Sbill {
4929877Ssam 	return (*a == *b && a[1] == b[1] && a[2] == b[2] );
493954Sbill }
494954Sbill 
rad50(cp,out)4954879Ssam rad50(cp, out)
4964879Ssam 	register u_char *cp;
4974879Ssam 	u_short *out;
498954Sbill {
4994879Ssam 	register index, temp;
500954Sbill 
5014879Ssam 	for (index = 0; *cp; index++) {
502954Sbill 		temp = Ain1 * table[*cp++];
5034879Ssam 		if (*cp!=0) {
504954Sbill 			temp += Ain2 * table[*cp++];
505954Sbill 			if(*cp!=0)
506954Sbill 				temp += table[*cp++];
507954Sbill 		}
508954Sbill 		out[index] = temp;
509954Sbill 	}
510954Sbill }
511954Sbill 
5124879Ssam #define reduce(x, p, q) (x = v[p/q], p %= q);
5134879Ssam 
unrad50(count,in,cp)5144879Ssam unrad50(count, in, cp)
5154879Ssam 	u_short *in;
5164879Ssam 	register char *cp;
517954Sbill {
5184879Ssam 	register i, temp;
5194879Ssam 	register u_char *v = (u_char *) val;
520954Sbill 
5214879Ssam 	for (i = 0; i < count; i++) {
522954Sbill 		temp = in[i];
5234879Ssam 		reduce(*cp++, temp, Ain1);
5244879Ssam 		reduce(*cp++, temp, Ain2);
5254879Ssam 		reduce(*cp++, temp, 1);
526954Sbill 	}
527954Sbill 	*cp=0;
528954Sbill }
529954Sbill 
srad50(name,rname)5304879Ssam srad50(name, rname)
5314879Ssam 	register char *name;
5324879Ssam 	register u_short *rname;
533954Sbill {
5344879Ssam 	register index;
5354879Ssam 	register char *cp;
5364879Ssam 	char file[7], ext[4];
5374879Ssam 
5383356Swnj 	/*
539954Sbill 	 * Find end of pathname
540954Sbill 	 */
5414879Ssam 	for (cp = name; *cp++; )
5424879Ssam 		;
5434879Ssam 	while (cp >= name && *--cp != '/')
5444879Ssam 		;
545954Sbill 	cp++;
5463356Swnj 	/*
547954Sbill 	 * Change to rad50
548954Sbill 	 */
5494879Ssam 	for (index = 0; *cp; ) {
550954Sbill 		file[index++] = *cp++;
5514879Ssam 		if (*cp == '.') {
552954Sbill 			cp++;
553954Sbill 			break;
554954Sbill 		}
5554879Ssam 		if (index >= 6) {
556954Sbill 			break;
557954Sbill 		}
558954Sbill 	}
559954Sbill 	file[index] = 0;
5604879Ssam 	for (index = 0; *cp; ) {
561954Sbill 		ext[index++] = *cp++;
5624879Ssam 		if (*cp == '.' || index >= 3)
563954Sbill 			break;
564954Sbill 	}
565954Sbill 	ext[index]=0;
5664879Ssam 	rname[0] = rname[1] = rname[2] = 0;
5674879Ssam 	rad50((u_char *)file, rname);
5684879Ssam 	rad50((u_char *)ext, rname+2);
569954Sbill }
5704879Ssam 
sunrad50(name,rname)5714879Ssam sunrad50(name, rname)
5724879Ssam 	u_short rname[];
5734879Ssam 	register char *name;
574954Sbill {
575954Sbill 	register char *cp, *cp2;
576954Sbill 	char ext[4];
577954Sbill 
5784879Ssam 	unrad50(2, rname, name);
5794879Ssam 	unrad50(1, rname + 2, ext);
5804879Ssam 	/*
5814879Ssam 	 * Jam name and extension together with a dot
5824879Ssam 	 * deleting white space
5834879Ssam 	 */
5844879Ssam 	for (cp = name; *cp++;)
5854879Ssam 		;
5864879Ssam 	--cp;
5874879Ssam 	while (*--cp == ' ' && cp >= name)
5884879Ssam 		;
5894879Ssam 	*++cp = '.';
5904879Ssam 	cp++;
5914879Ssam 	for (cp2 = ext; *cp2 != ' ' && cp2 < ext+3;)
592954Sbill 		*cp++ = *cp2++;
593954Sbill 	*cp=0;
5944879Ssam 	if (cp[-1] == '.')
5954879Ssam 		cp[-1] = 0;
596954Sbill }
597954Sbill 
598954Sbill static char *val = " abcdefghijklmnopqrstuvwxyz$.@0123456789";
5994879Ssam 
600954Sbill static char table[256] = {
601954Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
602954Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
603954Sbill 0, 29, 29, 29, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 29,
604954Sbill 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 29, 29, 29, 29, 29, 29,
605954Sbill 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
606954Sbill 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
607954Sbill 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
608954Sbill 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
609954Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
610954Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
611954Sbill 0, 29, 29, 29, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 29,
612954Sbill 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 29, 29, 29, 29, 29, 29,
613954Sbill 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
614954Sbill 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
615954Sbill 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
616954Sbill 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29 };
617954Sbill 
6184879Ssam /*
6194879Ssam  * Logical to physical adress translation
6204879Ssam  */
6214879Ssam long
trans(logical)6224879Ssam trans(logical)
6234879Ssam 	register int logical;
624954Sbill {
625954Sbill 	register int sector, bytes, track;
626954Sbill 
6274879Ssam 	logical += 26*128;
6284879Ssam 	bytes = (logical&127);
629954Sbill 	logical >>= 7;
6304879Ssam 	sector = logical%26;
631954Sbill 	if(sector >= 13)
6324879Ssam 		sector = sector*2+1;
633954Sbill 	else
634954Sbill 		sector *= 2;
6354879Ssam 	sector += 26 + ((track = (logical/26))-1)*6;
636954Sbill 	sector %= 26;
6379877Ssam 	return ((((track*26)+sector) << 7) + bytes);
638954Sbill }
6394879Ssam 
lread(startad,count,obuff)6404879Ssam lread(startad, count, obuff)
6414879Ssam 	register startad, count;
6424879Ssam 	register char *obuff;
643954Sbill {
644954Sbill 	long trans();
645954Sbill 	extern floppydes;
6464879Ssam 	register int size = flag(m) ? 512 : 128;
64729823Skarels 	int error = 0;
64829823Skarels 	extern int errno;
6494879Ssam 
650954Sbill 	rt_init();
6514879Ssam 	while ((count -= size) >= 0) {
65226131Sbloom 		(void) lseek(floppydes, flag(m) ?
6534879Ssam 			(long)startad : trans(startad), 0);
65429823Skarels 		if (read(floppydes, obuff, size) != size) {
65529823Skarels 			error = errno;
65629823Skarels 			fprintf(stderr, "arff: read error block %d: ",
6574879Ssam 				startad/size);
65829823Skarels 			errno = error;
65929823Skarels 			perror("");
66029823Skarels 		}
6614879Ssam 		obuff += size;
6624879Ssam 		startad += size;
6634879Ssam 	}
66429823Skarels 	return (error);
665954Sbill }
6664879Ssam 
lwrite(startad,count,obuff)6674879Ssam lwrite(startad, count, obuff)
6684879Ssam 	register startad, count;
6694879Ssam 	register char *obuff;
670954Sbill {
671954Sbill 	long trans();
672954Sbill 	extern floppydes;
6734879Ssam 	register int size = flag(m) ? 512 : 128;
6744879Ssam 
675954Sbill 	rt_init();
6764879Ssam 	while ((count -= size) >= 0) {
67726131Sbloom 		(void) lseek(floppydes, flag(m) ?
6784879Ssam 			(long)startad : trans(startad), 0);
6794879Ssam 		if (write(floppydes, obuff, size) != size)
6804879Ssam 			fprintf(stderr, "arff: write error block %d\n",
6814879Ssam 				startad/size);
6824879Ssam 		obuff += size;
6834879Ssam 		startad += size;
6844879Ssam 	}
685954Sbill }
686954Sbill 
rcmd()687954Sbill rcmd()
688954Sbill {
689954Sbill 	register int i;
690954Sbill 
691954Sbill 	rt_init();
6924879Ssam 	if (namc > 0)
6934879Ssam 		for (i = 0; i < namc; i++)
6944879Ssam 			if (rtr(namv[i]) == 0)
6954879Ssam 				namv[i] = 0;
696954Sbill }
697954Sbill 
rtr(name)698954Sbill rtr(name)
6994879Ssam 	char *name;
700954Sbill {
7014879Ssam 	register FLDOPE *dope;
7024879Ssam 	register struct rt_ent *de;
7034879Ssam 	struct stat buf;
7044879Ssam 	register struct stat *bufp = &buf;
7053346Swnj 	int segnum;
70626131Sbloom 	char type;
707954Sbill 
7084879Ssam 	if (stat(name, bufp) < 0) {
7093489Sroot 		perror(name);
7109877Ssam 		return (-1);
7113489Sroot 	}
71226131Sbloom 	type = 'a';
7134879Ssam 	if (dope = lookup(name)) {
714954Sbill 		/* can replace, no problem */
715954Sbill 		de = dope->rtdope;
71626131Sbloom 		if (bufp->st_size <= (de->rt_len * 512)) {
71726131Sbloom 			printf("r - %s\n",name);
7184879Ssam 			toflop(name, bufp->st_size, dope);
71926131Sbloom 			goto found;
72026131Sbloom 		} else {
72126131Sbloom 			de = dope->rtdope;
72226131Sbloom 			type = 'r';
72326131Sbloom 			de->rt_stat = RT_NULL;
72426131Sbloom 			de->rt_name[0] = 0;
72526131Sbloom 			de->rt_name[1] = 0;
72626131Sbloom 			de->rt_name[2] = 0;
72726131Sbloom 			*((u_short *)&(de->rt_date)) = 0;
72826131Sbloom 			scrunch();
729954Sbill 		}
7309877Ssam 	}
7319877Ssam 	/*
7329877Ssam 	 * Search for vacant spot
7339877Ssam 	 */
7349877Ssam 	for (segnum = 0; segnum != -1;
73526131Sbloom 	     segnum = rt_dir[segnum].rd_nxtseg - 1)
7369877Ssam 	{
7379877Ssam 		for (de = rt_dir[segnum].rt_ents;
7389877Ssam 		    rt(de)->rt_stat != RT_ESEG; de++)
7399877Ssam 			if ((de)->rt_stat == RT_NULL) {
7409877Ssam 				if (bufp->st_size <= (de->rt_len*512)) {
74126131Sbloom 					printf("%c - %s\n", type, name),
7429877Ssam 					mkent(de, segnum, bufp,name);
7439877Ssam 					goto found;
744954Sbill 				}
7459877Ssam 				continue;
7469877Ssam 			}
747954Sbill 	}
74830998Sbostic 	if (type == 'r')
74926131Sbloom 		printf("%s: no slot for file, file deleted\n",name);
75026131Sbloom 	else
75126131Sbloom 		printf("%s: no slot for file\n", name);
7529877Ssam 	return (-1);
7534879Ssam 
7544879Ssam found:
7554879Ssam 	if (dope = lookup(name)) {
7564879Ssam 		toflop(name, bufp->st_size, dope);
7573489Sroot 		return (0);
758954Sbill 	}
7593489Sroot 	printf("%s: internal error, added then not found\n", name);
7603489Sroot 	return (-1);
7614879Ssam }
762954Sbill 
mkent(de,segnum,bufp,name)7634879Ssam mkent(de, segnum, bufp, name)
7644879Ssam 	register struct rt_ent *de;
7654879Ssam 	int segnum;
7664879Ssam 	register struct stat *bufp;
7674879Ssam 	char *name;
768954Sbill {
7694879Ssam 	struct tm *localtime();
7704879Ssam 	register struct tm *timp;
7714879Ssam 	register struct rt_ent *workp;
7724879Ssam 	int count;
773954Sbill 
774954Sbill 	count = (((bufp->st_size -1) >>9) + 1);
7754879Ssam 	/* make sure there is room */
7764879Ssam 	if (de->rt_len == count)
777954Sbill 		goto overwrite;
7784879Ssam 	if ((char *)rt_curend[segnum] == (rt_last + (segnum*2*RT_BLOCK))) {
77926131Sbloom 		/* no entries left on segment, trying adding new segment */
78026131Sbloom 		if (rt_dir[0].rd_numseg > rt_dir[0].rd_lstseg) {
78126131Sbloom 			short newseg;
78226131Sbloom 			register int i;
78326131Sbloom 			int maxseg;
78426131Sbloom 			short size;
78526131Sbloom 
78626131Sbloom 			newseg = rt_dir[0].rd_lstseg++;
78726131Sbloom 			rt_dir[newseg] = rt_nulldir;
78826131Sbloom 			rt_dir[newseg].rd_nxtseg = rt_dir[segnum].rd_nxtseg;
78926131Sbloom 			rt_dir[segnum].rd_nxtseg = newseg + 1;
79026131Sbloom 			rt_dir[newseg].rd_entpad = rt_dir[0].rd_entpad;
79126131Sbloom 			rt_dir[newseg].rd_numseg = rt_dir[0].rd_numseg;
79226131Sbloom 			size = 0;
79326131Sbloom 			maxseg = 0;
79426131Sbloom 			for(i = newseg - 1; i >= 0; i--) {
79526131Sbloom 				workp = rt_curend[i] - 1;
79626131Sbloom 				if (workp->rt_stat != RT_NULL)
79726131Sbloom 					continue;
79826131Sbloom 				if (workp->rt_len < size)
79926131Sbloom 					continue;
80026131Sbloom 				size = workp->rt_len;
80126131Sbloom 				maxseg = i;
80226131Sbloom 			}
80326131Sbloom 			size = 0;
80426131Sbloom 			for (workp = &rt_dir[maxseg].rt_ents[0];
80526131Sbloom 			    workp->rt_stat != RT_ESEG; workp++) {
80626131Sbloom 				size += workp->rt_len;
80726131Sbloom 			}
80826131Sbloom 			workp--;
80926131Sbloom 			rt_dir[newseg].rt_ents[0].rt_len = workp->rt_len;
81026131Sbloom 			rt_dir[newseg].rd_stfile =
81126131Sbloom 			    rt_dir[maxseg].rd_stfile + size - workp->rt_len;
81226131Sbloom 			workp->rt_len = 0;
81326131Sbloom 			rt_curend[newseg] = &rt_dir[newseg].rt_ents[1];
81426131Sbloom 			lwrite(6*RT_BLOCK, 2*RT_BLOCK, (char *)&rt_dir[0]);
81526131Sbloom 			if (segnum != 0)
81626131Sbloom 				lwrite((6+segnum*2)*RT_BLOCK, 2*RT_BLOCK,
81726131Sbloom 				    (char *)&rt_dir[segnum]);
81826131Sbloom 			lwrite((6+newseg*2)*RT_BLOCK, 2*RT_BLOCK,
81926131Sbloom 			    (char *)&rt_dir[newseg]);
82026131Sbloom 			segnum = newseg;
82126131Sbloom 			de = &rt_dir[newseg].rt_ents[0];
82226131Sbloom 		} else {
82326131Sbloom 			fprintf(stderr, "All directory segments full on  %s\n",
82426131Sbloom 				defdev);
82526131Sbloom 			exit(1);
82626131Sbloom 		}
827954Sbill 	}
8284879Ssam 	/* copy directory entries up */
8294879Ssam 	for (workp = rt_curend[segnum]+1; workp > de; workp--)
830954Sbill 		*workp = workp[-1];
831954Sbill 	de[1].rt_len -= count;
832954Sbill 	de->rt_len = count;
8333346Swnj 	rt_curend[segnum]++;
834954Sbill 	rt_nleft--;
8354879Ssam 
836954Sbill overwrite:
837954Sbill 	srad50(name,de->rt_name);
838954Sbill 	timp = localtime(&bufp->st_mtime);
8397320Swnj 	de->rt_date.rt_dy = timp->tm_mday;
840954Sbill 	de->rt_date.rt_mo = timp->tm_mon + 1;
841954Sbill 	de->rt_date.rt_yr = timp->tm_year - 72;
842954Sbill 	de->rt_stat = RT_FILE;
843954Sbill 	de->rt_pad = 0;
844954Sbill 	de->rt_chan = 0;
845954Sbill 	de->rt_job = 0;
8464879Ssam 	lwrite((6+segnum*2)*RT_BLOCK, 2*RT_BLOCK, (char *)&rt_dir[segnum]);
847954Sbill }
848954Sbill 
toflop(name,ocount,dope)8494879Ssam toflop(name, ocount, dope)
8504879Ssam 	char *name;
8514879Ssam 	register FLDOPE *dope;
8524879Ssam 	long ocount;
853954Sbill {
854954Sbill 	register file, n, startad = dope->startad, count = ocount;
855954Sbill 	char buff[512];
856954Sbill 
8574879Ssam 	file = open(name, 0);
8584879Ssam 	if (file < 0) {
8594879Ssam 		fprintf(stderr, "arff: couldn't open %s\n",name);
8604879Ssam 		exit(1);
8614879Ssam 	}
862954Sbill 	for( ; count >= 512; count -= 512) {
86326131Sbloom 		(void) read(file, buff, 512);
8644879Ssam 		lwrite(startad, 512, buff);
865954Sbill 		startad += 512;
866954Sbill 	}
86726131Sbloom 	(void) read(file, buff, count);
86826131Sbloom 	(void) close(file);
8694879Ssam 	if (count <= 0)
8704879Ssam 		return;
8714879Ssam 	for (n = count; n < 512; n ++)
8724879Ssam 		buff[n] = 0;
8734879Ssam 	lwrite(startad, 512, buff);
8744879Ssam 	count = (dope->rtdope->rt_len*512-ocount)/512 ;
8754879Ssam 	if (count <= 0)
8764879Ssam 		return;
8774879Ssam 	for ( ; count > 0 ; count--) {
878954Sbill 		startad += 512;
8794879Ssam 		lwrite(startad, 512, zeroes);
880954Sbill 	}
8814879Ssam }
882954Sbill 
dcmd()883954Sbill dcmd()
884954Sbill {
885954Sbill 	register int i;
886954Sbill 
887954Sbill 	rt_init();
8884879Ssam 	if (namc)
8894879Ssam 		for (i = 0; i < namc; i++)
8904879Ssam 			if (rtk(namv[i])==0)
8914879Ssam 				namv[i]=0;
8924879Ssam 	if (dirdirty)
893954Sbill 		scrunch();
894954Sbill }
8954879Ssam 
rtk(name)896954Sbill rtk(name)
8974879Ssam 	char *name;
898954Sbill {
899954Sbill 	register FLDOPE *dope;
900954Sbill 	register struct rt_ent *de;
901954Sbill 	FLDOPE *lookup();
902954Sbill 
9034879Ssam 	if (dope = lookup(name)) {
904954Sbill 		printf("d - %s\n",name);
905954Sbill 		de = dope->rtdope;
906954Sbill 		de->rt_stat = RT_NULL;
907954Sbill 		de->rt_name[0] = 0;
908954Sbill 		de->rt_name[1] = 0;
909954Sbill 		de->rt_name[2] = 0;
9109877Ssam 		*((u_short *)&(de->rt_date)) = 0;
911954Sbill 		dirdirty = 1;
9129877Ssam 		return (0);
913954Sbill 	}
9149877Ssam 	return (1);
915954Sbill }
9164879Ssam 
scrunch()9174879Ssam scrunch()
9184879Ssam {
9193346Swnj 	register struct rt_ent *de , *workp;
9203346Swnj 	register segnum;
9214879Ssam 
9224879Ssam 	for (segnum = 0; segnum != -1;
92326131Sbloom 	     segnum = rt_dir[segnum].rd_nxtseg - 1) {
9244879Ssam 		for (de = rt_dir[segnum].rt_ents; de <= rt_curend[segnum]; de++)
9259877Ssam 			if (de->rt_stat == RT_NULL &&
92612012Shelge 			    (de+1)->rt_stat == RT_NULL) {
9274879Ssam 				(de+1)->rt_len += de->rt_len;
92812012Shelge 				for (workp=de; workp<rt_curend[segnum]; workp++)
9294879Ssam 					*workp = workp[1];
9304879Ssam 				de--;
9314879Ssam 				rt_curend[segnum]--;
9324879Ssam 				rt_nleft++;
9334879Ssam 			}
93412012Shelge 		lwrite((6+segnum*2)*RT_BLOCK, 2*RT_BLOCK,
93512012Shelge 			(char *)&rt_dir[segnum]);
936954Sbill 	}
93712012Shelge 	dirdirty = 0;
938954Sbill }
939