xref: /csrg-svn/old/arff/arff.c (revision 37979)
122483Sdist /*
222483Sdist  * Copyright (c) 1980 Regents of the University of California.
322483Sdist  * All rights reserved.  The Berkeley software License Agreement
422483Sdist  * specifies the terms and conditions for redistribution.
522483Sdist  */
622483Sdist 
79877Ssam #ifndef lint
822483Sdist char copyright[] =
922483Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\
1022483Sdist  All rights reserved.\n";
1122483Sdist #endif not lint
124879Ssam 
1322483Sdist #ifndef lint
14*37979Sbostic static char sccsid[] = "@(#)arff.c	5.7 (Berkeley) 05/11/89";
1522483Sdist #endif not lint
1622483Sdist 
17954Sbill #include <sys/types.h>
18954Sbill #include <sys/stat.h>
1913605Ssam #include <sys/time.h>
20*37979Sbostic #include <sys/signal.h>
21*37979Sbostic #include <sys/file.h>
22954Sbill #include <stdio.h>
23*37979Sbostic #include "pathnames.h"
244879Ssam 
25954Sbill #define dbprintf printf
264879Ssam 
27954Sbill struct rt_dat {
284879Ssam 	u_short	rt_yr:5;	/* year-1972 */
294879Ssam 	u_short	rt_dy:5;	/* day */
304879Ssam 	u_short	rt_mo:5;	/* month */
31954Sbill };
324879Ssam 
33954Sbill struct	rt_axent {
34954Sbill 	char	rt_sent[14];
35954Sbill };
36954Sbill 
37954Sbill struct rt_ent {
384879Ssam 	char	rt_pad;		/* unusued */
3930238Sbostic 	u_char	rt_stat;	/* type of entry, or end of seg */
404879Ssam 	u_short	rt_name[3];	/* name, 3 words in rad50 form */
417319Swnj 	u_short	rt_len;		/* length of file */
4230238Sbostic 	u_char	rt_chan;	/* only used in temporary files */
434879Ssam 	char	rt_job;		/* only used in temporary files */
449877Ssam 	struct	rt_dat rt_date;	/* creation date */
45954Sbill };
464879Ssam 
474879Ssam #define RT_TEMP		1
484879Ssam #define RT_NULL		2
494879Ssam #define RT_FILE		4
5030238Sbostic #define RT_PFILE	(0200|RT_FILE)	/* protected file */
514879Ssam #define RT_ESEG		8
524879Ssam 
534879Ssam #define RT_BLOCK	512	/* block size */
544879Ssam #define RT_DIRSIZE	31	/* max # of directory segments */
554879Ssam 
56954Sbill struct rt_head {
574879Ssam 	short	rt_numseg;	/* # of segments available */
584879Ssam 	short	rt_nxtseg;	/* # of next logical segment */
594879Ssam 	short	rt_lstseg;	/* highest seg currently open */
604879Ssam 	u_short	rt_entpad;	/* extra words/directory entry */
614879Ssam 	short	rt_stfile;	/* block # where files begin */
62954Sbill };
634879Ssam 
64954Sbill struct	rt_dir {
65954Sbill 	struct rt_head	rt_axhead;
66954Sbill 	struct rt_ent	rt_ents[72];
674879Ssam 	char		_dirpad[6];
68954Sbill };
694879Ssam 
7026131Sbloom #define rd_numseg rt_axhead.rt_numseg
7126131Sbloom #define rd_nxtseg rt_axhead.rt_nxtseg
7226131Sbloom #define rd_lstseg rt_axhead.rt_lstseg
7326131Sbloom #define rd_entpad rt_axhead.rt_entpad
7426131Sbloom #define rd_stfile rt_axhead.rt_stfile
7526131Sbloom 
76954Sbill typedef struct fldope {
77954Sbill 	int	startad;
78954Sbill 	int	count;
79954Sbill struct	rt_ent	*rtdope;
80954Sbill } FLDOPE;
814879Ssam 
82954Sbill FLDOPE *lookup();
834879Ssam 
849877Ssam #define	rt(p)	((struct rt_ent *) p )
859877Ssam #define	Ain1	03100
869877Ssam #define	Ain2	050
879877Ssam #define	flag(c)	(flg[('c') - 'a'])
88954Sbill 
899877Ssam char	*man = "rxtd";
909877Ssam char	zeroes[512];
91954Sbill 
92954Sbill extern char *val;
93954Sbill extern char table[256];
944879Ssam struct rt_dir rt_dir[RT_DIRSIZE] = {
9533133Sbostic 	{
969877Ssam 	{ 4, 0, 1, 0, 14 },
9726131Sbloom 	{ { 0, RT_NULL, { 0, 0, 0 }, 486, 0 },
989877Ssam 	  { 0, RT_ESEG } }
9933133Sbostic 	}
1004879Ssam };
101954Sbill 
10226131Sbloom struct rt_dir rt_nulldir = {
10326131Sbloom 	{ 0, 0, 0, 0, 0 },
10426131Sbloom 	{ { 0, RT_NULL, { 0, 0, 0 }, 0, 0 },
10526131Sbloom 	  { 0, RT_ESEG } }
10626131Sbloom };
10726131Sbloom 
1084879Ssam int	rt_entsiz;
1094879Ssam int	rt_nleft;
1104879Ssam struct rt_ent *rt_curend[RT_DIRSIZE];
1114879Ssam int	floppydes;
1124879Ssam int	dirdirty;
1134879Ssam char	*rt_last;
114*37979Sbostic char	*defdev = _PATH_FLOPPY;
115954Sbill 
11626131Sbloom char *opt = "vfbcm";
1174879Ssam 
1184879Ssam extern long lseek();
1194879Ssam int	rcmd(), dcmd(), xcmd(), tcmd();
1204879Ssam 
121954Sbill int	(*comfun)();
122954Sbill char	flg[26];
123954Sbill char	**namv;
124954Sbill int	namc;
125954Sbill 
126954Sbill main(argc, argv)
1274879Ssam 	char *argv[];
128954Sbill {
129954Sbill 	register char *cp;
130954Sbill 
1314879Ssam 	if (argc < 2)
132954Sbill 		usage();
1334879Ssam 	for (cp = argv[1]; *cp; cp++)
1344879Ssam 		switch (*cp) {
135954Sbill 
1364879Ssam 		case 'm':
1374879Ssam 		case 'v':
1384879Ssam 		case 'u':
1394879Ssam 		case 'w':
14026131Sbloom 		case 'b':
1414879Ssam 			flg[*cp-'a']++;
1424879Ssam 			continue;
1434879Ssam 		case 'c':
14413910Ssam 			flag(c)++;
1454879Ssam 			dirdirty++;
1464879Ssam 			continue;
147954Sbill 
1484879Ssam 		case 'r':
1494879Ssam 			setcom(rcmd);
1504879Ssam 			flag(r)++;
1514879Ssam 			continue;
152954Sbill 
1534879Ssam 		case 'd':
1544879Ssam 			setcom(dcmd);
1554879Ssam 			flag(d)++;
1564879Ssam 			continue;
157954Sbill 
1584879Ssam 		case 'x':
1594879Ssam 			setcom(xcmd);
1604879Ssam 			continue;
161954Sbill 
1624879Ssam 		case 't':
1634879Ssam 			setcom(tcmd);
1644879Ssam 			continue;
165954Sbill 
1664879Ssam 		case 'f':
1674879Ssam 			defdev = argv[2];
1684879Ssam 			argv++;
1694879Ssam 			argc--;
1704879Ssam 			continue;
1714879Ssam 
1724879Ssam 		default:
1734879Ssam 			fprintf(stderr, "arff: bad option `%c'\n", *cp);
1744879Ssam 			exit(1);
1754879Ssam 		}
1764879Ssam 
177954Sbill 	namv = argv+2;
178954Sbill 	namc = argc-2;
1794879Ssam 	if (comfun == 0) {
1804879Ssam 		if (flag(u) == 0) {
1814879Ssam 			fprintf(stderr, "arff: one of [%s] must be specified\n",
1824879Ssam 				man);
183954Sbill 			exit(1);
184954Sbill 		}
185954Sbill 		setcom(rcmd);
186954Sbill 	}
187954Sbill 	(*comfun)();
188954Sbill 	exit(notfound());
189954Sbill }
190954Sbill 
191954Sbill setcom(fun)
1924879Ssam 	int (*fun)();
193954Sbill {
1944879Ssam 	if (comfun != 0) {
195954Sbill 		fprintf(stderr, "arff: only one of [%s] allowed\n", man);
196954Sbill 		exit(1);
197954Sbill 	}
198954Sbill 	comfun = fun;
199954Sbill }
200954Sbill 
201954Sbill usage()
202954Sbill {
2033356Swnj 	fprintf(stderr, "usage: ar [%s][%s] archive files ...\n", opt, man);
204954Sbill 	exit(1);
205954Sbill }
206954Sbill 
207954Sbill notfound()
208954Sbill {
2094879Ssam 	register i, n = 0;
210954Sbill 
2114879Ssam 	for (i = 0; i < namc; i++)
2124879Ssam 		if (namv[i]) {
213954Sbill 			fprintf(stderr, "arff: %s not found\n", namv[i]);
214954Sbill 			n++;
215954Sbill 		}
2169877Ssam 	return (n);
217954Sbill }
218954Sbill 
219954Sbill tcmd()
220954Sbill {
2214879Ssam 	register char *de, *last;
222954Sbill 	FLDOPE *lookup(), *dope;
2234879Ssam 	int segnum, nleft;
2244879Ssam 	register i;
225954Sbill 	register struct rt_ent *rde;
226954Sbill 
227954Sbill 	rt_init();
2289877Ssam 	if (namc != 0) {
2294879Ssam 		for (i = 0; i < namc; i++)
2304879Ssam 			if (dope = lookup(namv[i])) {
231954Sbill 				rde = dope->rtdope;
23226131Sbloom 				(void) rtls(rde);
233954Sbill 				namv[i] = 0;
234954Sbill 			}
2359877Ssam 		return;
2369877Ssam 	}
2379877Ssam 	for (segnum = 0; segnum != -1;
23826131Sbloom 	  segnum = rt_dir[segnum].rd_nxtseg - 1) {
2399877Ssam 		last = rt_last + segnum*2*RT_BLOCK;
2409877Ssam 		for (de = ((char *)&rt_dir[segnum])+10; de <= last;
2419877Ssam 		    de += rt_entsiz)
2429877Ssam 			if (rtls(rt(de))) {
2439877Ssam 				nleft = (last-de)/rt_entsiz;
2449877Ssam #define ENTRIES "\n%d entries remaining in directory segment %d.\n"
2459877Ssam 				printf(ENTRIES, nleft, segnum+1);
2469877Ssam 				break;
2479877Ssam 			}
2489877Ssam 	}
249954Sbill }
2504879Ssam 
251954Sbill rtls(de)
2524879Ssam 	register struct rt_ent *de;
253954Sbill {
2544879Ssam 	int month, day, year;
255954Sbill 	char name[12], ext[4];
256954Sbill 
2574879Ssam 	switch (de->rt_stat) {
2584879Ssam 
2594879Ssam 	case RT_TEMP:
2604879Ssam 		if (flag(v))
261954Sbill 			printf("Tempfile:\n");
2624879Ssam 		/* fall thru...*/
263954Sbill 
2644879Ssam 	case RT_FILE:
26530238Sbostic 	case RT_PFILE:
2664879Ssam 		if (!flag(v)) {
2674879Ssam 			sunrad50(name, de->rt_name);
2684879Ssam 			printf("%s\n", name);
269954Sbill 			break;
270954Sbill 		}
2714879Ssam 		unrad50(2, de->rt_name, name);
2724879Ssam 		unrad50(1, &(de->rt_name[2]), ext);
2734879Ssam 		day = de->rt_date.rt_dy;
2744879Ssam 		year = de->rt_date.rt_yr+72;
2754879Ssam 		month = de->rt_date.rt_mo;
2764879Ssam 		printf("%6.6s  %3.3s	%02d/%02d/%02d	%d\n",name,
2774879Ssam 			ext, month, day, year, de->rt_len);
2784879Ssam 		break;
279954Sbill 
2804879Ssam 	case RT_NULL:
2814879Ssam 		printf("%-25.9s	%d\n","<UNUSED>", de->rt_len);
2824879Ssam 		break;
283954Sbill 
2844879Ssam 	case RT_ESEG:
2859877Ssam 		return (1);
286954Sbill 	}
2879877Ssam 	return (0);
288954Sbill }
2894879Ssam 
290954Sbill xcmd()
291954Sbill {
2924879Ssam 	register char *de, *last;
2933346Swnj 	int segnum;
294954Sbill 	char name[12];
295954Sbill 	register int i;
296954Sbill 
297954Sbill 	rt_init();
2989877Ssam 	if (namc != 0) {
2994879Ssam 		for (i = 0; i < namc; i++)
3004879Ssam 			if (rtx(namv[i]) == 0)
3014879Ssam 				namv[i] = 0;
3029877Ssam 		return;
3039877Ssam 	}
3049877Ssam 	for (segnum = 0; segnum != -1;
30526131Sbloom 	     segnum = rt_dir[segnum].rd_nxtseg-1)
3069877Ssam 		for (last = rt_last+(segnum*2*RT_BLOCK),
3079877Ssam 		     de = ((char *)&rt_dir[segnum])+10; de <= last;
30815553Sralph 		     de += rt_entsiz) {
3099877Ssam 			switch (rt(de)->rt_stat) {
3109877Ssam 
3119877Ssam 			case RT_ESEG:
31215553Sralph 				break;	/* exit loop and try next segment */
3139877Ssam 
3149877Ssam 			case RT_TEMP:
3159877Ssam 			case RT_FILE:
31630238Sbostic 			case RT_PFILE:
3179877Ssam 				sunrad50(name,rt(de)->rt_name);
31826131Sbloom 				(void) rtx(name);
3199877Ssam 
3209877Ssam 			case RT_NULL:
32115553Sralph 			default:
32215553Sralph 				continue;
3239877Ssam 			}
32415553Sralph 			break;
32515553Sralph 		}
326954Sbill }
3274879Ssam 
328954Sbill rtx(name)
3294879Ssam 	char *name;
330954Sbill {
331954Sbill 	register FLDOPE *dope;
332954Sbill 	FLDOPE *lookup();
333954Sbill 	register startad, count;
3344879Ssam 	int file;
3354879Ssam 	char buff[512];
336954Sbill 
337954Sbill 
3384879Ssam 	if (dope = lookup(name)) {
3394879Ssam 		if (flag(v))
34026131Sbloom 			(void) rtls(dope->rtdope);
341954Sbill 		else
342954Sbill 			printf("x - %s\n",name);
343954Sbill 
3444879Ssam 		if ((file = creat(name, 0666)) < 0)
3459877Ssam 			return (1);
346954Sbill 		count = dope->count;
347954Sbill 		startad = dope->startad;
348954Sbill 		for( ; count > 0 ; count -= 512) {
34929823Skarels 			(void) lread(startad, 512, buff);
35026131Sbloom 			(void) write(file, buff, 512);
351954Sbill 			startad += 512;
352954Sbill 		}
35326131Sbloom 		(void) close(file);
3549877Ssam 		return (0);
355954Sbill 	}
3569877Ssam 	return (1);
357954Sbill }
3584879Ssam 
359954Sbill rt_init()
360954Sbill {
361954Sbill 	static initized = 0;
3624879Ssam 	register char *de, *last;
3633346Swnj 	register i;
3643799Shickman 	int dirnum;
3653799Shickman 	char *mode;
3663799Shickman 	FILE *temp_floppydes;
367954Sbill 
3684879Ssam 	if (initized)
3694879Ssam 		return;
370954Sbill 	initized = 1;
37113910Ssam 	if (flag(c)) {
37213910Ssam 		struct stat sb;
37313910Ssam 		char response[128];
37413910Ssam 		int tty;
37513910Ssam 
37613910Ssam 		if (stat(defdev, &sb) >= 0 && (sb.st_mode & S_IFMT) == S_IFREG)
37713910Ssam 			goto ignore;
378*37979Sbostic 		tty = open(_PATH_TTY, O_RDWR);
37913910Ssam #define SURE	"Are you sure you want to clobber the floppy? "
38026131Sbloom 		(void) write(tty, SURE, sizeof (SURE));
38126131Sbloom 		(void) read(tty, response, sizeof (response));
38213910Ssam 		if (*response != 'y')
38313910Ssam 			exit(50);
38426131Sbloom 		(void) close(tty);
38513910Ssam ignore:
38613910Ssam 		;
38713910Ssam 	}
3884879Ssam 	if (flag(c) || flag(d) || flag(r))
3893799Shickman 		mode = "r+";
390954Sbill 	else
3913799Shickman 		mode = "r";
3924879Ssam 	if ((temp_floppydes = fopen(defdev, mode)) == NULL) {
3933799Shickman 		perror(defdev);
3943356Swnj 		exit(1);
3953799Shickman 	} else
3963799Shickman 		floppydes = fileno(temp_floppydes);
3974879Ssam 	if (!flag(c)) {
39829823Skarels 		if (lread(6*RT_BLOCK, 2*RT_BLOCK, (char *)&rt_dir[0]))
39929823Skarels 			exit(2);
40026131Sbloom 		dirnum = rt_dir[0].rd_numseg;
40112012Shelge 		/* check for blank/uninitialized diskette */
40212012Shelge 		if (dirnum <= 0) {
40312012Shelge 			fprintf(stderr,"arff: bad directory format\n");
40412012Shelge 			exit(1);
40512012Shelge 		}
4063346Swnj 		if (dirnum > RT_DIRSIZE) {
4074879Ssam 			fprintf(stderr,"arff: too many directory segments\n");
4084879Ssam 			exit(1);
4093346Swnj 		}
4104879Ssam 		for (i = 1; i < dirnum; i++)
41129823Skarels 		    if (lread((6+2*i)*RT_BLOCK, 2*RT_BLOCK, (char *)&rt_dir[i]))
41229823Skarels 			exit(1);
41326131Sbloom 	} else {
4143489Sroot 		dirnum = 1;
41526131Sbloom 		if (flag(b)) {
41626131Sbloom 			rt_dir[0].rd_numseg = 31;
41726131Sbloom 			rt_dir[0].rd_stfile = 68;
41826131Sbloom 			rt_dir[0].rt_ents[0].rt_len = 20480 - 68;
41926131Sbloom 		}
42026131Sbloom 	}
421954Sbill 
42226131Sbloom 	rt_entsiz = 2*rt_dir[0].rd_entpad + 14;
42326131Sbloom 	/*
42426131Sbloom 	 * We assume that the directory entries have no padding.  This
42526131Sbloom 	 * may not be a valid assumption, but there are numerous point
42626131Sbloom 	 * in the code where it assumes it is an rt_ent structure and
42726131Sbloom 	 * not an rt_entsiz sized structure.
42826131Sbloom 	 */
42926131Sbloom 	rt_entsiz = 14;
4303346Swnj 	rt_last = ((char *) &rt_dir[0]) + 10 + 1014/rt_entsiz*rt_entsiz;
4313346Swnj 	rt_nleft = 0;
4323346Swnj 
4334879Ssam 	for (i = 0; i < dirnum; i++) {
4344879Ssam 		last = rt_last + i*2*RT_BLOCK;
4354879Ssam 		for (de = ((char *)&rt_dir[i])+10; de <= last; de += rt_entsiz)
4364879Ssam 			if (rt(de)->rt_stat == RT_ESEG)
4374879Ssam 				break;
4384879Ssam 		rt_curend[i] = rt(de);
4394879Ssam 		rt_nleft += (last-de)/rt_entsiz;
440954Sbill 	}
441954Sbill }
442954Sbill 
443954Sbill static FLDOPE result;
4444879Ssam 
445954Sbill FLDOPE *
446954Sbill lookup(name)
4474879Ssam 	char *name;
448954Sbill {
449954Sbill 	unsigned short rname[3];
45026131Sbloom 	register char *de;
4513346Swnj 	int segnum;
452954Sbill 	register index;
453954Sbill 
454954Sbill 	srad50(name,rname);
455954Sbill 
4563356Swnj 	/*
457954Sbill 	 *  Search for name, accumulate blocks in index
458954Sbill 	 */
459954Sbill 	rt_init();
4604879Ssam 	for (segnum = 0; segnum != -1;
46126131Sbloom 	     segnum = rt_dir[segnum].rd_nxtseg - 1)
4624879Ssam 	{
4634879Ssam 		index = 0;
4644879Ssam 		for (de=((char *)&rt_dir[segnum])+10;
4654879Ssam 		     rt(de)->rt_stat != RT_ESEG; de += rt_entsiz)
4664879Ssam 			switch(rt(de)->rt_stat) {
4674879Ssam 
4684879Ssam 			case RT_FILE:
46930238Sbostic 			case RT_PFILE:
4704879Ssam 			case RT_TEMP:
4714879Ssam 				if(samename(rname,rt(de)->rt_name)) {
4724879Ssam 					result.count = rt(de)->rt_len * 512;
4734879Ssam 					result.startad = 512*
47426131Sbloom 					    (rt_dir[segnum].rd_stfile + index);
4754879Ssam 					result.rtdope = (struct rt_ent *) de;
4769877Ssam 					return (&result);
4774879Ssam 				}
4784879Ssam 
4794879Ssam 			case RT_NULL:
4804879Ssam 				index += rt(de)->rt_len;
4814879Ssam 			}
4823346Swnj         }
4839877Ssam 	return ((FLDOPE *) 0);
4844879Ssam 
485954Sbill }
4864879Ssam 
487954Sbill static
4884879Ssam samename(a, b)
4894879Ssam 	u_short a[], b[];
490954Sbill {
4919877Ssam 	return (*a == *b && a[1] == b[1] && a[2] == b[2] );
492954Sbill }
493954Sbill 
4944879Ssam rad50(cp, out)
4954879Ssam 	register u_char *cp;
4964879Ssam 	u_short *out;
497954Sbill {
4984879Ssam 	register index, temp;
499954Sbill 
5004879Ssam 	for (index = 0; *cp; index++) {
501954Sbill 		temp = Ain1 * table[*cp++];
5024879Ssam 		if (*cp!=0) {
503954Sbill 			temp += Ain2 * table[*cp++];
504954Sbill 			if(*cp!=0)
505954Sbill 				temp += table[*cp++];
506954Sbill 		}
507954Sbill 		out[index] = temp;
508954Sbill 	}
509954Sbill }
510954Sbill 
5114879Ssam #define reduce(x, p, q) (x = v[p/q], p %= q);
5124879Ssam 
5134879Ssam unrad50(count, in, cp)
5144879Ssam 	u_short *in;
5154879Ssam 	register char *cp;
516954Sbill {
5174879Ssam 	register i, temp;
5184879Ssam 	register u_char *v = (u_char *) val;
519954Sbill 
5204879Ssam 	for (i = 0; i < count; i++) {
521954Sbill 		temp = in[i];
5224879Ssam 		reduce(*cp++, temp, Ain1);
5234879Ssam 		reduce(*cp++, temp, Ain2);
5244879Ssam 		reduce(*cp++, temp, 1);
525954Sbill 	}
526954Sbill 	*cp=0;
527954Sbill }
528954Sbill 
5294879Ssam srad50(name, rname)
5304879Ssam 	register char *name;
5314879Ssam 	register u_short *rname;
532954Sbill {
5334879Ssam 	register index;
5344879Ssam 	register char *cp;
5354879Ssam 	char file[7], ext[4];
5364879Ssam 
5373356Swnj 	/*
538954Sbill 	 * Find end of pathname
539954Sbill 	 */
5404879Ssam 	for (cp = name; *cp++; )
5414879Ssam 		;
5424879Ssam 	while (cp >= name && *--cp != '/')
5434879Ssam 		;
544954Sbill 	cp++;
5453356Swnj 	/*
546954Sbill 	 * Change to rad50
547954Sbill 	 */
5484879Ssam 	for (index = 0; *cp; ) {
549954Sbill 		file[index++] = *cp++;
5504879Ssam 		if (*cp == '.') {
551954Sbill 			cp++;
552954Sbill 			break;
553954Sbill 		}
5544879Ssam 		if (index >= 6) {
555954Sbill 			break;
556954Sbill 		}
557954Sbill 	}
558954Sbill 	file[index] = 0;
5594879Ssam 	for (index = 0; *cp; ) {
560954Sbill 		ext[index++] = *cp++;
5614879Ssam 		if (*cp == '.' || index >= 3)
562954Sbill 			break;
563954Sbill 	}
564954Sbill 	ext[index]=0;
5654879Ssam 	rname[0] = rname[1] = rname[2] = 0;
5664879Ssam 	rad50((u_char *)file, rname);
5674879Ssam 	rad50((u_char *)ext, rname+2);
568954Sbill }
5694879Ssam 
5704879Ssam sunrad50(name, rname)
5714879Ssam 	u_short rname[];
5724879Ssam 	register char *name;
573954Sbill {
574954Sbill 	register char *cp, *cp2;
575954Sbill 	char ext[4];
576954Sbill 
5774879Ssam 	unrad50(2, rname, name);
5784879Ssam 	unrad50(1, rname + 2, ext);
5794879Ssam 	/*
5804879Ssam 	 * Jam name and extension together with a dot
5814879Ssam 	 * deleting white space
5824879Ssam 	 */
5834879Ssam 	for (cp = name; *cp++;)
5844879Ssam 		;
5854879Ssam 	--cp;
5864879Ssam 	while (*--cp == ' ' && cp >= name)
5874879Ssam 		;
5884879Ssam 	*++cp = '.';
5894879Ssam 	cp++;
5904879Ssam 	for (cp2 = ext; *cp2 != ' ' && cp2 < ext+3;)
591954Sbill 		*cp++ = *cp2++;
592954Sbill 	*cp=0;
5934879Ssam 	if (cp[-1] == '.')
5944879Ssam 		cp[-1] = 0;
595954Sbill }
596954Sbill 
597954Sbill static char *val = " abcdefghijklmnopqrstuvwxyz$.@0123456789";
5984879Ssam 
599954Sbill static char table[256] = {
600954Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
601954Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
602954Sbill 0, 29, 29, 29, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 29,
603954Sbill 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 29, 29, 29, 29, 29, 29,
604954Sbill 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
605954Sbill 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
606954Sbill 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
607954Sbill 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
608954Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
609954Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
610954Sbill 0, 29, 29, 29, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 29,
611954Sbill 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 29, 29, 29, 29, 29, 29,
612954Sbill 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
613954Sbill 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
614954Sbill 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
615954Sbill 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29 };
616954Sbill 
6174879Ssam /*
6184879Ssam  * Logical to physical adress translation
6194879Ssam  */
6204879Ssam long
6214879Ssam trans(logical)
6224879Ssam 	register int logical;
623954Sbill {
624954Sbill 	register int sector, bytes, track;
625954Sbill 
6264879Ssam 	logical += 26*128;
6274879Ssam 	bytes = (logical&127);
628954Sbill 	logical >>= 7;
6294879Ssam 	sector = logical%26;
630954Sbill 	if(sector >= 13)
6314879Ssam 		sector = sector*2+1;
632954Sbill 	else
633954Sbill 		sector *= 2;
6344879Ssam 	sector += 26 + ((track = (logical/26))-1)*6;
635954Sbill 	sector %= 26;
6369877Ssam 	return ((((track*26)+sector) << 7) + bytes);
637954Sbill }
6384879Ssam 
6394879Ssam lread(startad, count, obuff)
6404879Ssam 	register startad, count;
6414879Ssam 	register char *obuff;
642954Sbill {
643954Sbill 	long trans();
644954Sbill 	extern floppydes;
6454879Ssam 	register int size = flag(m) ? 512 : 128;
64629823Skarels 	int error = 0;
64729823Skarels 	extern int errno;
6484879Ssam 
649954Sbill 	rt_init();
6504879Ssam 	while ((count -= size) >= 0) {
65126131Sbloom 		(void) lseek(floppydes, flag(m) ?
6524879Ssam 			(long)startad : trans(startad), 0);
65329823Skarels 		if (read(floppydes, obuff, size) != size) {
65429823Skarels 			error = errno;
65529823Skarels 			fprintf(stderr, "arff: read error block %d: ",
6564879Ssam 				startad/size);
65729823Skarels 			errno = error;
65829823Skarels 			perror("");
65929823Skarels 		}
6604879Ssam 		obuff += size;
6614879Ssam 		startad += size;
6624879Ssam 	}
66329823Skarels 	return (error);
664954Sbill }
6654879Ssam 
6664879Ssam lwrite(startad, count, obuff)
6674879Ssam 	register startad, count;
6684879Ssam 	register char *obuff;
669954Sbill {
670954Sbill 	long trans();
671954Sbill 	extern floppydes;
6724879Ssam 	register int size = flag(m) ? 512 : 128;
6734879Ssam 
674954Sbill 	rt_init();
6754879Ssam 	while ((count -= size) >= 0) {
67626131Sbloom 		(void) lseek(floppydes, flag(m) ?
6774879Ssam 			(long)startad : trans(startad), 0);
6784879Ssam 		if (write(floppydes, obuff, size) != size)
6794879Ssam 			fprintf(stderr, "arff: write error block %d\n",
6804879Ssam 				startad/size);
6814879Ssam 		obuff += size;
6824879Ssam 		startad += size;
6834879Ssam 	}
684954Sbill }
685954Sbill 
686954Sbill rcmd()
687954Sbill {
688954Sbill 	register int i;
689954Sbill 
690954Sbill 	rt_init();
6914879Ssam 	if (namc > 0)
6924879Ssam 		for (i = 0; i < namc; i++)
6934879Ssam 			if (rtr(namv[i]) == 0)
6944879Ssam 				namv[i] = 0;
695954Sbill }
696954Sbill 
697954Sbill rtr(name)
6984879Ssam 	char *name;
699954Sbill {
7004879Ssam 	register FLDOPE *dope;
7014879Ssam 	register struct rt_ent *de;
7024879Ssam 	struct stat buf;
7034879Ssam 	register struct stat *bufp = &buf;
7043346Swnj 	int segnum;
70526131Sbloom 	char type;
706954Sbill 
7074879Ssam 	if (stat(name, bufp) < 0) {
7083489Sroot 		perror(name);
7099877Ssam 		return (-1);
7103489Sroot 	}
71126131Sbloom 	type = 'a';
7124879Ssam 	if (dope = lookup(name)) {
713954Sbill 		/* can replace, no problem */
714954Sbill 		de = dope->rtdope;
71526131Sbloom 		if (bufp->st_size <= (de->rt_len * 512)) {
71626131Sbloom 			printf("r - %s\n",name);
7174879Ssam 			toflop(name, bufp->st_size, dope);
71826131Sbloom 			goto found;
71926131Sbloom 		} else {
72026131Sbloom 			de = dope->rtdope;
72126131Sbloom 			type = 'r';
72226131Sbloom 			de->rt_stat = RT_NULL;
72326131Sbloom 			de->rt_name[0] = 0;
72426131Sbloom 			de->rt_name[1] = 0;
72526131Sbloom 			de->rt_name[2] = 0;
72626131Sbloom 			*((u_short *)&(de->rt_date)) = 0;
72726131Sbloom 			scrunch();
728954Sbill 		}
7299877Ssam 	}
7309877Ssam 	/*
7319877Ssam 	 * Search for vacant spot
7329877Ssam 	 */
7339877Ssam 	for (segnum = 0; segnum != -1;
73426131Sbloom 	     segnum = rt_dir[segnum].rd_nxtseg - 1)
7359877Ssam 	{
7369877Ssam 		for (de = rt_dir[segnum].rt_ents;
7379877Ssam 		    rt(de)->rt_stat != RT_ESEG; de++)
7389877Ssam 			if ((de)->rt_stat == RT_NULL) {
7399877Ssam 				if (bufp->st_size <= (de->rt_len*512)) {
74026131Sbloom 					printf("%c - %s\n", type, name),
7419877Ssam 					mkent(de, segnum, bufp,name);
7429877Ssam 					goto found;
743954Sbill 				}
7449877Ssam 				continue;
7459877Ssam 			}
746954Sbill 	}
74730998Sbostic 	if (type == 'r')
74826131Sbloom 		printf("%s: no slot for file, file deleted\n",name);
74926131Sbloom 	else
75026131Sbloom 		printf("%s: no slot for file\n", name);
7519877Ssam 	return (-1);
7524879Ssam 
7534879Ssam found:
7544879Ssam 	if (dope = lookup(name)) {
7554879Ssam 		toflop(name, bufp->st_size, dope);
7563489Sroot 		return (0);
757954Sbill 	}
7583489Sroot 	printf("%s: internal error, added then not found\n", name);
7593489Sroot 	return (-1);
7604879Ssam }
761954Sbill 
7624879Ssam mkent(de, segnum, bufp, name)
7634879Ssam 	register struct rt_ent *de;
7644879Ssam 	int segnum;
7654879Ssam 	register struct stat *bufp;
7664879Ssam 	char *name;
767954Sbill {
7684879Ssam 	struct tm *localtime();
7694879Ssam 	register struct tm *timp;
7704879Ssam 	register struct rt_ent *workp;
7714879Ssam 	int count;
772954Sbill 
773954Sbill 	count = (((bufp->st_size -1) >>9) + 1);
7744879Ssam 	/* make sure there is room */
7754879Ssam 	if (de->rt_len == count)
776954Sbill 		goto overwrite;
7774879Ssam 	if ((char *)rt_curend[segnum] == (rt_last + (segnum*2*RT_BLOCK))) {
77826131Sbloom 		/* no entries left on segment, trying adding new segment */
77926131Sbloom 		if (rt_dir[0].rd_numseg > rt_dir[0].rd_lstseg) {
78026131Sbloom 			short newseg;
78126131Sbloom 			register int i;
78226131Sbloom 			int maxseg;
78326131Sbloom 			short size;
78426131Sbloom 
78526131Sbloom 			newseg = rt_dir[0].rd_lstseg++;
78626131Sbloom 			rt_dir[newseg] = rt_nulldir;
78726131Sbloom 			rt_dir[newseg].rd_nxtseg = rt_dir[segnum].rd_nxtseg;
78826131Sbloom 			rt_dir[segnum].rd_nxtseg = newseg + 1;
78926131Sbloom 			rt_dir[newseg].rd_entpad = rt_dir[0].rd_entpad;
79026131Sbloom 			rt_dir[newseg].rd_numseg = rt_dir[0].rd_numseg;
79126131Sbloom 			size = 0;
79226131Sbloom 			maxseg = 0;
79326131Sbloom 			for(i = newseg - 1; i >= 0; i--) {
79426131Sbloom 				workp = rt_curend[i] - 1;
79526131Sbloom 				if (workp->rt_stat != RT_NULL)
79626131Sbloom 					continue;
79726131Sbloom 				if (workp->rt_len < size)
79826131Sbloom 					continue;
79926131Sbloom 				size = workp->rt_len;
80026131Sbloom 				maxseg = i;
80126131Sbloom 			}
80226131Sbloom 			size = 0;
80326131Sbloom 			for (workp = &rt_dir[maxseg].rt_ents[0];
80426131Sbloom 			    workp->rt_stat != RT_ESEG; workp++) {
80526131Sbloom 				size += workp->rt_len;
80626131Sbloom 			}
80726131Sbloom 			workp--;
80826131Sbloom 			rt_dir[newseg].rt_ents[0].rt_len = workp->rt_len;
80926131Sbloom 			rt_dir[newseg].rd_stfile =
81026131Sbloom 			    rt_dir[maxseg].rd_stfile + size - workp->rt_len;
81126131Sbloom 			workp->rt_len = 0;
81226131Sbloom 			rt_curend[newseg] = &rt_dir[newseg].rt_ents[1];
81326131Sbloom 			lwrite(6*RT_BLOCK, 2*RT_BLOCK, (char *)&rt_dir[0]);
81426131Sbloom 			if (segnum != 0)
81526131Sbloom 				lwrite((6+segnum*2)*RT_BLOCK, 2*RT_BLOCK,
81626131Sbloom 				    (char *)&rt_dir[segnum]);
81726131Sbloom 			lwrite((6+newseg*2)*RT_BLOCK, 2*RT_BLOCK,
81826131Sbloom 			    (char *)&rt_dir[newseg]);
81926131Sbloom 			segnum = newseg;
82026131Sbloom 			de = &rt_dir[newseg].rt_ents[0];
82126131Sbloom 		} else {
82226131Sbloom 			fprintf(stderr, "All directory segments full on  %s\n",
82326131Sbloom 				defdev);
82426131Sbloom 			exit(1);
82526131Sbloom 		}
826954Sbill 	}
8274879Ssam 	/* copy directory entries up */
8284879Ssam 	for (workp = rt_curend[segnum]+1; workp > de; workp--)
829954Sbill 		*workp = workp[-1];
830954Sbill 	de[1].rt_len -= count;
831954Sbill 	de->rt_len = count;
8323346Swnj 	rt_curend[segnum]++;
833954Sbill 	rt_nleft--;
8344879Ssam 
835954Sbill overwrite:
836954Sbill 	srad50(name,de->rt_name);
837954Sbill 	timp = localtime(&bufp->st_mtime);
8387320Swnj 	de->rt_date.rt_dy = timp->tm_mday;
839954Sbill 	de->rt_date.rt_mo = timp->tm_mon + 1;
840954Sbill 	de->rt_date.rt_yr = timp->tm_year - 72;
841954Sbill 	de->rt_stat = RT_FILE;
842954Sbill 	de->rt_pad = 0;
843954Sbill 	de->rt_chan = 0;
844954Sbill 	de->rt_job = 0;
8454879Ssam 	lwrite((6+segnum*2)*RT_BLOCK, 2*RT_BLOCK, (char *)&rt_dir[segnum]);
846954Sbill }
847954Sbill 
8484879Ssam toflop(name, ocount, dope)
8494879Ssam 	char *name;
8504879Ssam 	register FLDOPE *dope;
8514879Ssam 	long ocount;
852954Sbill {
853954Sbill 	register file, n, startad = dope->startad, count = ocount;
854954Sbill 	char buff[512];
855954Sbill 
8564879Ssam 	file = open(name, 0);
8574879Ssam 	if (file < 0) {
8584879Ssam 		fprintf(stderr, "arff: couldn't open %s\n",name);
8594879Ssam 		exit(1);
8604879Ssam 	}
861954Sbill 	for( ; count >= 512; count -= 512) {
86226131Sbloom 		(void) read(file, buff, 512);
8634879Ssam 		lwrite(startad, 512, buff);
864954Sbill 		startad += 512;
865954Sbill 	}
86626131Sbloom 	(void) read(file, buff, count);
86726131Sbloom 	(void) close(file);
8684879Ssam 	if (count <= 0)
8694879Ssam 		return;
8704879Ssam 	for (n = count; n < 512; n ++)
8714879Ssam 		buff[n] = 0;
8724879Ssam 	lwrite(startad, 512, buff);
8734879Ssam 	count = (dope->rtdope->rt_len*512-ocount)/512 ;
8744879Ssam 	if (count <= 0)
8754879Ssam 		return;
8764879Ssam 	for ( ; count > 0 ; count--) {
877954Sbill 		startad += 512;
8784879Ssam 		lwrite(startad, 512, zeroes);
879954Sbill 	}
8804879Ssam }
881954Sbill 
882954Sbill dcmd()
883954Sbill {
884954Sbill 	register int i;
885954Sbill 
886954Sbill 	rt_init();
8874879Ssam 	if (namc)
8884879Ssam 		for (i = 0; i < namc; i++)
8894879Ssam 			if (rtk(namv[i])==0)
8904879Ssam 				namv[i]=0;
8914879Ssam 	if (dirdirty)
892954Sbill 		scrunch();
893954Sbill }
8944879Ssam 
895954Sbill rtk(name)
8964879Ssam 	char *name;
897954Sbill {
898954Sbill 	register FLDOPE *dope;
899954Sbill 	register struct rt_ent *de;
900954Sbill 	FLDOPE *lookup();
901954Sbill 
9024879Ssam 	if (dope = lookup(name)) {
903954Sbill 		printf("d - %s\n",name);
904954Sbill 		de = dope->rtdope;
905954Sbill 		de->rt_stat = RT_NULL;
906954Sbill 		de->rt_name[0] = 0;
907954Sbill 		de->rt_name[1] = 0;
908954Sbill 		de->rt_name[2] = 0;
9099877Ssam 		*((u_short *)&(de->rt_date)) = 0;
910954Sbill 		dirdirty = 1;
9119877Ssam 		return (0);
912954Sbill 	}
9139877Ssam 	return (1);
914954Sbill }
9154879Ssam 
9164879Ssam scrunch()
9174879Ssam {
9183346Swnj 	register struct rt_ent *de , *workp;
9193346Swnj 	register segnum;
9204879Ssam 
9214879Ssam 	for (segnum = 0; segnum != -1;
92226131Sbloom 	     segnum = rt_dir[segnum].rd_nxtseg - 1) {
9234879Ssam 		for (de = rt_dir[segnum].rt_ents; de <= rt_curend[segnum]; de++)
9249877Ssam 			if (de->rt_stat == RT_NULL &&
92512012Shelge 			    (de+1)->rt_stat == RT_NULL) {
9264879Ssam 				(de+1)->rt_len += de->rt_len;
92712012Shelge 				for (workp=de; workp<rt_curend[segnum]; workp++)
9284879Ssam 					*workp = workp[1];
9294879Ssam 				de--;
9304879Ssam 				rt_curend[segnum]--;
9314879Ssam 				rt_nleft++;
9324879Ssam 			}
93312012Shelge 		lwrite((6+segnum*2)*RT_BLOCK, 2*RT_BLOCK,
93412012Shelge 			(char *)&rt_dir[segnum]);
935954Sbill 	}
93612012Shelge 	dirdirty = 0;
937954Sbill }
938