xref: /csrg-svn/old/arff/arff.c (revision 22483)
1*22483Sdist /*
2*22483Sdist  * Copyright (c) 1980 Regents of the University of California.
3*22483Sdist  * All rights reserved.  The Berkeley software License Agreement
4*22483Sdist  * specifies the terms and conditions for redistribution.
5*22483Sdist  */
6*22483Sdist 
79877Ssam #ifndef lint
8*22483Sdist char copyright[] =
9*22483Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\
10*22483Sdist  All rights reserved.\n";
11*22483Sdist #endif not lint
124879Ssam 
13*22483Sdist #ifndef lint
14*22483Sdist static char sccsid[] = "@(#)arff.c	5.1 (Berkeley) 06/06/85";
15*22483Sdist #endif not lint
16*22483Sdist 
17954Sbill #include <sys/types.h>
18954Sbill #include <sys/stat.h>
1913605Ssam #include <sys/time.h>
20954Sbill #include <signal.h>
21954Sbill #include <stdio.h>
2213910Ssam #include <sys/file.h>
234879Ssam 
24954Sbill #define dbprintf printf
254879Ssam 
26954Sbill struct rt_dat {
274879Ssam 	u_short	rt_yr:5;	/* year-1972 */
284879Ssam 	u_short	rt_dy:5;	/* day */
294879Ssam 	u_short	rt_mo:5;	/* month */
30954Sbill };
314879Ssam 
32954Sbill struct	rt_axent {
33954Sbill 	char	rt_sent[14];
34954Sbill };
35954Sbill 
36954Sbill struct rt_ent {
374879Ssam 	char	rt_pad;		/* unusued */
384879Ssam 	char	rt_stat;	/* type of entry, or end of seg */
394879Ssam 	u_short	rt_name[3];	/* name, 3 words in rad50 form */
407319Swnj 	u_short	rt_len;		/* length of file */
414879Ssam 	char	rt_chan;	/* only used in temporary files */
424879Ssam 	char	rt_job;		/* only used in temporary files */
439877Ssam 	struct	rt_dat rt_date;	/* creation date */
44954Sbill };
454879Ssam 
464879Ssam #define RT_TEMP		1
474879Ssam #define RT_NULL		2
484879Ssam #define RT_FILE		4
494879Ssam #define RT_ESEG		8
504879Ssam 
514879Ssam #define RT_BLOCK	512	/* block size */
524879Ssam #define RT_DIRSIZE	31	/* max # of directory segments */
534879Ssam 
54954Sbill struct rt_head {
554879Ssam 	short	rt_numseg;	/* # of segments available */
564879Ssam 	short	rt_nxtseg;	/* # of next logical segment */
574879Ssam 	short	rt_lstseg;	/* highest seg currently open */
584879Ssam 	u_short	rt_entpad;	/* extra words/directory entry */
594879Ssam 	short	rt_stfile;	/* block # where files begin */
60954Sbill };
614879Ssam 
62954Sbill struct	rt_dir {
63954Sbill 	struct rt_head	rt_axhead;
64954Sbill 	struct rt_ent	rt_ents[72];
654879Ssam 	char		_dirpad[6];
66954Sbill };
674879Ssam 
68954Sbill typedef struct fldope {
69954Sbill 	int	startad;
70954Sbill 	int	count;
71954Sbill struct	rt_ent	*rtdope;
72954Sbill } FLDOPE;
734879Ssam 
74954Sbill FLDOPE *lookup();
754879Ssam 
769877Ssam #define	rt(p)	((struct rt_ent *) p )
779877Ssam #define	Ain1	03100
789877Ssam #define	Ain2	050
799877Ssam #define	flag(c)	(flg[('c') - 'a'])
80954Sbill 
819877Ssam char	*man = "rxtd";
829877Ssam char	zeroes[512];
83954Sbill 
84954Sbill extern char *val;
85954Sbill extern char table[256];
864879Ssam struct rt_dir rt_dir[RT_DIRSIZE] = {
879877Ssam 	{ 4, 0, 1, 0, 14 },
889877Ssam 	{ { 0, RT_NULL, { 0, 0, 0 }, 494, 0 },
899877Ssam 	  { 0, RT_ESEG } }
904879Ssam };
91954Sbill 
924879Ssam int	rt_entsiz;
934879Ssam int	rt_nleft;
944879Ssam struct rt_ent *rt_curend[RT_DIRSIZE];
954879Ssam int	floppydes;
964879Ssam int	dirdirty;
974879Ssam char	*rt_last;
984879Ssam char	*defdev = "/dev/floppy";
99954Sbill 
1004879Ssam char *opt = "vf";
1014879Ssam 
102954Sbill int	signum[] = {SIGHUP, SIGINT, SIGQUIT, 0};
1034879Ssam extern long lseek();
1044879Ssam int	rcmd(), dcmd(), xcmd(), tcmd();
1054879Ssam 
106954Sbill int	(*comfun)();
107954Sbill char	flg[26];
108954Sbill char	**namv;
109954Sbill int	namc;
110954Sbill int	file;
111954Sbill 
112954Sbill main(argc, argv)
1134879Ssam 	char *argv[];
114954Sbill {
115954Sbill 	register char *cp;
116954Sbill 
1174879Ssam 	if (argc < 2)
118954Sbill 		usage();
1194879Ssam 	for (cp = argv[1]; *cp; cp++)
1204879Ssam 		switch (*cp) {
121954Sbill 
1224879Ssam 		case 'm':
1234879Ssam 		case 'v':
1244879Ssam 		case 'u':
1254879Ssam 		case 'w':
1264879Ssam 			flg[*cp-'a']++;
1274879Ssam 			continue;
1284879Ssam 		case 'c':
12913910Ssam 			flag(c)++;
1304879Ssam 			dirdirty++;
1314879Ssam 			continue;
132954Sbill 
1334879Ssam 		case 'r':
1344879Ssam 			setcom(rcmd);
1354879Ssam 			flag(r)++;
1364879Ssam 			continue;
137954Sbill 
1384879Ssam 		case 'd':
1394879Ssam 			setcom(dcmd);
1404879Ssam 			flag(d)++;
1414879Ssam 			continue;
142954Sbill 
1434879Ssam 		case 'x':
1444879Ssam 			setcom(xcmd);
1454879Ssam 			continue;
146954Sbill 
1474879Ssam 		case 't':
1484879Ssam 			setcom(tcmd);
1494879Ssam 			continue;
150954Sbill 
1514879Ssam 		case 'f':
1524879Ssam 			defdev = argv[2];
1534879Ssam 			argv++;
1544879Ssam 			argc--;
1554879Ssam 			continue;
1564879Ssam 
1574879Ssam 		default:
1584879Ssam 			fprintf(stderr, "arff: bad option `%c'\n", *cp);
1594879Ssam 			exit(1);
1604879Ssam 		}
1614879Ssam 
162954Sbill 	namv = argv+2;
163954Sbill 	namc = argc-2;
1644879Ssam 	if (comfun == 0) {
1654879Ssam 		if (flag(u) == 0) {
1664879Ssam 			fprintf(stderr, "arff: one of [%s] must be specified\n",
1674879Ssam 				man);
168954Sbill 			exit(1);
169954Sbill 		}
170954Sbill 		setcom(rcmd);
171954Sbill 	}
172954Sbill 	(*comfun)();
173954Sbill 	exit(notfound());
174954Sbill }
175954Sbill 
176954Sbill setcom(fun)
1774879Ssam 	int (*fun)();
178954Sbill {
1794879Ssam 	if (comfun != 0) {
180954Sbill 		fprintf(stderr, "arff: only one of [%s] allowed\n", man);
181954Sbill 		exit(1);
182954Sbill 	}
183954Sbill 	comfun = fun;
184954Sbill }
185954Sbill 
186954Sbill usage()
187954Sbill {
1883356Swnj 	fprintf(stderr, "usage: ar [%s][%s] archive files ...\n", opt, man);
189954Sbill 	exit(1);
190954Sbill }
191954Sbill 
192954Sbill notfound()
193954Sbill {
1944879Ssam 	register i, n = 0;
195954Sbill 
1964879Ssam 	for (i = 0; i < namc; i++)
1974879Ssam 		if (namv[i]) {
198954Sbill 			fprintf(stderr, "arff: %s not found\n", namv[i]);
199954Sbill 			n++;
200954Sbill 		}
2019877Ssam 	return (n);
202954Sbill }
203954Sbill 
204954Sbill mesg(c)
205954Sbill {
2064879Ssam 	if (flag(v))
2074879Ssam 		if (c != 'c' || flag(v) > 1)
208954Sbill 			printf("%c - %s\n", c, file);
209954Sbill }
210954Sbill 
211954Sbill tcmd()
212954Sbill {
2134879Ssam 	register char *de, *last;
214954Sbill 	FLDOPE *lookup(), *dope;
2154879Ssam 	int segnum, nleft;
2164879Ssam 	register i;
217954Sbill 	register struct rt_ent *rde;
218954Sbill 
219954Sbill 	rt_init();
2209877Ssam 	if (namc != 0) {
2214879Ssam 		for (i = 0; i < namc; i++)
2224879Ssam 			if (dope = lookup(namv[i])) {
223954Sbill 				rde = dope->rtdope;
224954Sbill 				rtls(rde);
225954Sbill 				namv[i] = 0;
226954Sbill 			}
2279877Ssam 		return;
2289877Ssam 	}
2299877Ssam 	for (segnum = 0; segnum != -1;
2309877Ssam 	  segnum = rt_dir[segnum].rt_axhead.rt_nxtseg - 1) {
2319877Ssam 		last = rt_last + segnum*2*RT_BLOCK;
2329877Ssam 		for (de = ((char *)&rt_dir[segnum])+10; de <= last;
2339877Ssam 		    de += rt_entsiz)
2349877Ssam 			if (rtls(rt(de))) {
2359877Ssam 				nleft = (last-de)/rt_entsiz;
2369877Ssam #define ENTRIES "\n%d entries remaining in directory segment %d.\n"
2379877Ssam 				printf(ENTRIES, nleft, segnum+1);
2389877Ssam 				break;
2399877Ssam 			}
2409877Ssam 	}
241954Sbill }
2424879Ssam 
243954Sbill rtls(de)
2444879Ssam 	register struct rt_ent *de;
245954Sbill {
2464879Ssam 	int month, day, year;
247954Sbill 	char name[12], ext[4];
248954Sbill 
2494879Ssam 	switch (de->rt_stat) {
2504879Ssam 
2514879Ssam 	case RT_TEMP:
2524879Ssam 		if (flag(v))
253954Sbill 			printf("Tempfile:\n");
2544879Ssam 		/* fall thru...*/
255954Sbill 
2564879Ssam 	case RT_FILE:
2574879Ssam 		if (!flag(v)) {
2584879Ssam 			sunrad50(name, de->rt_name);
2594879Ssam 			printf("%s\n", name);
260954Sbill 			break;
261954Sbill 		}
2624879Ssam 		unrad50(2, de->rt_name, name);
2634879Ssam 		unrad50(1, &(de->rt_name[2]), ext);
2644879Ssam 		day = de->rt_date.rt_dy;
2654879Ssam 		year = de->rt_date.rt_yr+72;
2664879Ssam 		month = de->rt_date.rt_mo;
2674879Ssam 		printf("%6.6s  %3.3s	%02d/%02d/%02d	%d\n",name,
2684879Ssam 			ext, month, day, year, de->rt_len);
2694879Ssam 		break;
270954Sbill 
2714879Ssam 	case RT_NULL:
2724879Ssam 		printf("%-25.9s	%d\n","<UNUSED>", de->rt_len);
2734879Ssam 		break;
274954Sbill 
2754879Ssam 	case RT_ESEG:
2769877Ssam 		return (1);
277954Sbill 	}
2789877Ssam 	return (0);
279954Sbill }
2804879Ssam 
281954Sbill xcmd()
282954Sbill {
2834879Ssam 	register char *de, *last;
2843346Swnj 	int segnum;
285954Sbill 	char name[12];
286954Sbill 	register int i;
287954Sbill 
288954Sbill 	rt_init();
2899877Ssam 	if (namc != 0) {
2904879Ssam 		for (i = 0; i < namc; i++)
2914879Ssam 			if (rtx(namv[i]) == 0)
2924879Ssam 				namv[i] = 0;
2939877Ssam 		return;
2949877Ssam 	}
2959877Ssam 	for (segnum = 0; segnum != -1;
2969877Ssam 	     segnum = rt_dir[segnum].rt_axhead.rt_nxtseg-1)
2979877Ssam 		for (last = rt_last+(segnum*2*RT_BLOCK),
2989877Ssam 		     de = ((char *)&rt_dir[segnum])+10; de <= last;
29915553Sralph 		     de += rt_entsiz) {
3009877Ssam 			switch (rt(de)->rt_stat) {
3019877Ssam 
3029877Ssam 			case RT_ESEG:
30315553Sralph 				break;	/* exit loop and try next segment */
3049877Ssam 
3059877Ssam 			case RT_TEMP:
3069877Ssam 			case RT_FILE:
3079877Ssam 				sunrad50(name,rt(de)->rt_name);
3089877Ssam 				rtx(name);
3099877Ssam 
3109877Ssam 			case RT_NULL:
31115553Sralph 			default:
31215553Sralph 				continue;
3139877Ssam 			}
31415553Sralph 			break;
31515553Sralph 		}
316954Sbill }
3174879Ssam 
318954Sbill rtx(name)
3194879Ssam 	char *name;
320954Sbill {
321954Sbill 	register FLDOPE *dope;
322954Sbill 	FLDOPE *lookup();
323954Sbill 	register startad, count;
3244879Ssam 	int file;
3254879Ssam 	char buff[512];
326954Sbill 
327954Sbill 
3284879Ssam 	if (dope = lookup(name)) {
3294879Ssam 		if (flag(v))
330954Sbill 			rtls(dope->rtdope);
331954Sbill 		else
332954Sbill 			printf("x - %s\n",name);
333954Sbill 
3344879Ssam 		if ((file = creat(name, 0666)) < 0)
3359877Ssam 			return (1);
336954Sbill 		count = dope->count;
337954Sbill 		startad = dope->startad;
338954Sbill 		for( ; count > 0 ; count -= 512) {
3394879Ssam 			lread(startad, 512, buff);
3404879Ssam 			write(file, buff, 512);
341954Sbill 			startad += 512;
342954Sbill 		}
343954Sbill 		close(file);
3449877Ssam 		return (0);
345954Sbill 	}
3469877Ssam 	return (1);
347954Sbill }
3484879Ssam 
349954Sbill rt_init()
350954Sbill {
351954Sbill 	static initized = 0;
3524879Ssam 	register char *de, *last;
3533346Swnj 	register i;
3543799Shickman 	int dirnum;
3553799Shickman 	char *mode;
3563799Shickman 	FILE *temp_floppydes;
357954Sbill 
3584879Ssam 	if (initized)
3594879Ssam 		return;
360954Sbill 	initized = 1;
36113910Ssam 	if (flag(c)) {
36213910Ssam 		struct stat sb;
36313910Ssam 		char response[128];
36413910Ssam 		int tty;
36513910Ssam 
36613910Ssam 		if (stat(defdev, &sb) >= 0 && (sb.st_mode & S_IFMT) == S_IFREG)
36713910Ssam 			goto ignore;
36813910Ssam 		tty = open("/dev/tty", O_RDWR);
36913910Ssam #define SURE	"Are you sure you want to clobber the floppy? "
37013910Ssam 		write(tty, SURE, sizeof (SURE));
37113910Ssam 		read(tty, response, sizeof (response));
37213910Ssam 		if (*response != 'y')
37313910Ssam 			exit(50);
37413910Ssam 		close(tty);
37513910Ssam ignore:
37613910Ssam 		;
37713910Ssam 	}
3784879Ssam 	if (flag(c) || flag(d) || flag(r))
3793799Shickman 		mode = "r+";
380954Sbill 	else
3813799Shickman 		mode = "r";
3824879Ssam 	if ((temp_floppydes = fopen(defdev, mode)) == NULL) {
3833799Shickman 		perror(defdev);
3843356Swnj 		exit(1);
3853799Shickman 	} else
3863799Shickman 		floppydes = fileno(temp_floppydes);
3874879Ssam 	if (!flag(c)) {
3884879Ssam 		lread(6*RT_BLOCK, 2*RT_BLOCK, (char *)&rt_dir[0]);
3893346Swnj 		dirnum = rt_dir[0].rt_axhead.rt_numseg;
39012012Shelge 		/* check for blank/uninitialized diskette */
39112012Shelge 		if (dirnum <= 0) {
39212012Shelge 			fprintf(stderr,"arff: bad directory format\n");
39312012Shelge 			exit(1);
39412012Shelge 		}
3953346Swnj 		if (dirnum > RT_DIRSIZE) {
3964879Ssam 			fprintf(stderr,"arff: too many directory segments\n");
3974879Ssam 			exit(1);
3983346Swnj 		}
3994879Ssam 		for (i = 1; i < dirnum; i++)
4004879Ssam 			lread((6+2*i)*RT_BLOCK, 2*RT_BLOCK, (char *)&rt_dir[i]);
4013489Sroot 	} else
4023489Sroot 		dirnum = 1;
403954Sbill 
4043346Swnj 	rt_entsiz = 2*rt_dir[0].rt_axhead.rt_entpad + 14;
4053346Swnj 	rt_entsiz = 14;			/* assume rt_entpad = 0 ??? */
4063346Swnj 	rt_last = ((char *) &rt_dir[0]) + 10 + 1014/rt_entsiz*rt_entsiz;
4073346Swnj 	rt_nleft = 0;
4083346Swnj 
4094879Ssam 	for (i = 0; i < dirnum; i++) {
4104879Ssam 		last = rt_last + i*2*RT_BLOCK;
4114879Ssam 		for (de = ((char *)&rt_dir[i])+10; de <= last; de += rt_entsiz)
4124879Ssam 			if (rt(de)->rt_stat == RT_ESEG)
4134879Ssam 				break;
4144879Ssam 		rt_curend[i] = rt(de);
4154879Ssam 		rt_nleft += (last-de)/rt_entsiz;
416954Sbill 	}
417954Sbill }
418954Sbill 
419954Sbill static FLDOPE result;
4204879Ssam 
421954Sbill FLDOPE *
422954Sbill lookup(name)
4234879Ssam 	char *name;
424954Sbill {
425954Sbill 	unsigned short rname[3];
4264879Ssam 	register char *de, *last;
4273346Swnj 	int segnum;
428954Sbill 	register index;
429954Sbill 
430954Sbill 	srad50(name,rname);
431954Sbill 
4323356Swnj 	/*
433954Sbill 	 *  Search for name, accumulate blocks in index
434954Sbill 	 */
435954Sbill 	rt_init();
4364879Ssam 	for (segnum = 0; segnum != -1;
4374879Ssam 	     segnum = rt_dir[segnum].rt_axhead.rt_nxtseg - 1)
4384879Ssam 	{
4394879Ssam 		index = 0;
4404879Ssam 		last = rt_last + segnum*2*RT_BLOCK;
4414879Ssam 		for (de=((char *)&rt_dir[segnum])+10;
4424879Ssam 		     rt(de)->rt_stat != RT_ESEG; de += rt_entsiz)
4434879Ssam 			switch(rt(de)->rt_stat) {
4444879Ssam 
4454879Ssam 			case RT_FILE:
4464879Ssam 			case RT_TEMP:
4474879Ssam 				if(samename(rname,rt(de)->rt_name)) {
4484879Ssam 					result.count = rt(de)->rt_len * 512;
4494879Ssam 					result.startad = 512*
4504879Ssam 						(rt_dir[segnum].rt_axhead.rt_stfile + index);
4514879Ssam 					result.rtdope = (struct rt_ent *) de;
4529877Ssam 					return (&result);
4534879Ssam 				}
4544879Ssam 
4554879Ssam 			case RT_NULL:
4564879Ssam 				index += rt(de)->rt_len;
4574879Ssam 			}
4583346Swnj         }
4599877Ssam 	return ((FLDOPE *) 0);
4604879Ssam 
461954Sbill }
4624879Ssam 
463954Sbill static
4644879Ssam samename(a, b)
4654879Ssam 	u_short a[], b[];
466954Sbill {
4679877Ssam 	return (*a == *b && a[1] == b[1] && a[2] == b[2] );
468954Sbill }
469954Sbill 
4704879Ssam rad50(cp, out)
4714879Ssam 	register u_char *cp;
4724879Ssam 	u_short *out;
473954Sbill {
4744879Ssam 	register index, temp;
475954Sbill 
4764879Ssam 	for (index = 0; *cp; index++) {
477954Sbill 		temp = Ain1 * table[*cp++];
4784879Ssam 		if (*cp!=0) {
479954Sbill 			temp += Ain2 * table[*cp++];
480954Sbill 			if(*cp!=0)
481954Sbill 				temp += table[*cp++];
482954Sbill 		}
483954Sbill 		out[index] = temp;
484954Sbill 	}
485954Sbill }
486954Sbill 
4874879Ssam #define reduce(x, p, q) (x = v[p/q], p %= q);
4884879Ssam 
4894879Ssam unrad50(count, in, cp)
4904879Ssam 	u_short *in;
4914879Ssam 	register char *cp;
492954Sbill {
4934879Ssam 	register i, temp;
4944879Ssam 	register u_char *v = (u_char *) val;
495954Sbill 
4964879Ssam 	for (i = 0; i < count; i++) {
497954Sbill 		temp = in[i];
4984879Ssam 		reduce(*cp++, temp, Ain1);
4994879Ssam 		reduce(*cp++, temp, Ain2);
5004879Ssam 		reduce(*cp++, temp, 1);
501954Sbill 	}
502954Sbill 	*cp=0;
503954Sbill }
504954Sbill 
5054879Ssam srad50(name, rname)
5064879Ssam 	register char *name;
5074879Ssam 	register u_short *rname;
508954Sbill {
5094879Ssam 	register index;
5104879Ssam 	register char *cp;
5114879Ssam 	char file[7], ext[4];
5124879Ssam 
5133356Swnj 	/*
514954Sbill 	 * Find end of pathname
515954Sbill 	 */
5164879Ssam 	for (cp = name; *cp++; )
5174879Ssam 		;
5184879Ssam 	while (cp >= name && *--cp != '/')
5194879Ssam 		;
520954Sbill 	cp++;
5213356Swnj 	/*
522954Sbill 	 * Change to rad50
523954Sbill 	 */
5244879Ssam 	for (index = 0; *cp; ) {
525954Sbill 		file[index++] = *cp++;
5264879Ssam 		if (*cp == '.') {
527954Sbill 			cp++;
528954Sbill 			break;
529954Sbill 		}
5304879Ssam 		if (index >= 6) {
531954Sbill 			break;
532954Sbill 		}
533954Sbill 	}
534954Sbill 	file[index] = 0;
5354879Ssam 	for (index = 0; *cp; ) {
536954Sbill 		ext[index++] = *cp++;
5374879Ssam 		if (*cp == '.' || index >= 3)
538954Sbill 			break;
539954Sbill 	}
540954Sbill 	ext[index]=0;
5414879Ssam 	rname[0] = rname[1] = rname[2] = 0;
5424879Ssam 	rad50((u_char *)file, rname);
5434879Ssam 	rad50((u_char *)ext, rname+2);
544954Sbill }
5454879Ssam 
5464879Ssam sunrad50(name, rname)
5474879Ssam 	u_short rname[];
5484879Ssam 	register char *name;
549954Sbill {
550954Sbill 	register char *cp, *cp2;
551954Sbill 	char ext[4];
552954Sbill 
5534879Ssam 	unrad50(2, rname, name);
5544879Ssam 	unrad50(1, rname + 2, ext);
5554879Ssam 	/*
5564879Ssam 	 * Jam name and extension together with a dot
5574879Ssam 	 * deleting white space
5584879Ssam 	 */
5594879Ssam 	for (cp = name; *cp++;)
5604879Ssam 		;
5614879Ssam 	--cp;
5624879Ssam 	while (*--cp == ' ' && cp >= name)
5634879Ssam 		;
5644879Ssam 	*++cp = '.';
5654879Ssam 	cp++;
5664879Ssam 	for (cp2 = ext; *cp2 != ' ' && cp2 < ext+3;)
567954Sbill 		*cp++ = *cp2++;
568954Sbill 	*cp=0;
5694879Ssam 	if (cp[-1] == '.')
5704879Ssam 		cp[-1] = 0;
571954Sbill }
572954Sbill 
573954Sbill static char *oval = " ABCDEFGHIJKLMNOPQRSTUVWXYZ$.@0123456789";
574954Sbill static char *val = " abcdefghijklmnopqrstuvwxyz$.@0123456789";
5754879Ssam 
576954Sbill static char table[256] = {
577954Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
578954Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
579954Sbill 0, 29, 29, 29, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 29,
580954Sbill 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 29, 29, 29, 29, 29, 29,
581954Sbill 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
582954Sbill 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
583954Sbill 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
584954Sbill 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
585954Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
586954Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
587954Sbill 0, 29, 29, 29, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 29,
588954Sbill 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 29, 29, 29, 29, 29, 29,
589954Sbill 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
590954Sbill 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
591954Sbill 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
592954Sbill 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29 };
593954Sbill 
5944879Ssam /*
5954879Ssam  * Logical to physical adress translation
5964879Ssam  */
5974879Ssam long
5984879Ssam trans(logical)
5994879Ssam 	register int logical;
600954Sbill {
601954Sbill 	register int sector, bytes, track;
602954Sbill 
6034879Ssam 	logical += 26*128;
6044879Ssam 	bytes = (logical&127);
605954Sbill 	logical >>= 7;
6064879Ssam 	sector = logical%26;
607954Sbill 	if(sector >= 13)
6084879Ssam 		sector = sector*2+1;
609954Sbill 	else
610954Sbill 		sector *= 2;
6114879Ssam 	sector += 26 + ((track = (logical/26))-1)*6;
612954Sbill 	sector %= 26;
6139877Ssam 	return ((((track*26)+sector) << 7) + bytes);
614954Sbill }
6154879Ssam 
6164879Ssam lread(startad, count, obuff)
6174879Ssam 	register startad, count;
6184879Ssam 	register char *obuff;
619954Sbill {
620954Sbill 	long trans();
621954Sbill 	extern floppydes;
6224879Ssam 	register int size = flag(m) ? 512 : 128;
6234879Ssam 
624954Sbill 	rt_init();
6254879Ssam 	while ((count -= size) >= 0) {
6264879Ssam 		lseek(floppydes, flag(m) ?
6274879Ssam 			(long)startad : trans(startad), 0);
6284879Ssam 		if (read(floppydes, obuff, size) != size)
6294879Ssam 			fprintf(stderr, "arff: read error block %d\n",
6304879Ssam 				startad/size);
6314879Ssam 		obuff += size;
6324879Ssam 		startad += size;
6334879Ssam 	}
634954Sbill }
6354879Ssam 
6364879Ssam lwrite(startad, count, obuff)
6374879Ssam 	register startad, count;
6384879Ssam 	register char *obuff;
639954Sbill {
640954Sbill 	long trans();
641954Sbill 	extern floppydes;
6424879Ssam 	register int size = flag(m) ? 512 : 128;
6434879Ssam 
644954Sbill 	rt_init();
6454879Ssam 	while ((count -= size) >= 0) {
6464879Ssam 		lseek(floppydes, flag(m) ?
6474879Ssam 			(long)startad : trans(startad), 0);
6484879Ssam 		if (write(floppydes, obuff, size) != size)
6494879Ssam 			fprintf(stderr, "arff: write error block %d\n",
6504879Ssam 				startad/size);
6514879Ssam 		obuff += size;
6524879Ssam 		startad += size;
6534879Ssam 	}
654954Sbill }
655954Sbill 
656954Sbill rcmd()
657954Sbill {
658954Sbill 	register int i;
659954Sbill 
660954Sbill 	rt_init();
6614879Ssam 	if (namc > 0)
6624879Ssam 		for (i = 0; i < namc; i++)
6634879Ssam 			if (rtr(namv[i]) == 0)
6644879Ssam 				namv[i] = 0;
665954Sbill }
666954Sbill 
667954Sbill rtr(name)
6684879Ssam 	char *name;
669954Sbill {
6704879Ssam 	register FLDOPE *dope;
6714879Ssam 	register struct rt_ent *de;
6724879Ssam 	struct stat buf;
6734879Ssam 	register struct stat *bufp = &buf;
6743346Swnj 	int segnum;
6753346Swnj 	register char *last;
676954Sbill 
6774879Ssam 	if (stat(name, bufp) < 0) {
6783489Sroot 		perror(name);
6799877Ssam 		return (-1);
6803489Sroot 	}
6814879Ssam 	if (dope = lookup(name)) {
682954Sbill 		/* can replace, no problem */
683954Sbill 		de = dope->rtdope;
6844879Ssam 		if (bufp->st_size <= (de->rt_len * 512))
685954Sbill 			printf("r - %s\n",name),
6864879Ssam 			toflop(name, bufp->st_size, dope);
687954Sbill 		else {
6889877Ssam 			fprintf(stderr,
6899877Ssam 			  "%s will not fit in currently used file on floppy\n",
6909877Ssam 			  name);
6919877Ssam 			return (-1);
692954Sbill 		}
6939877Ssam 		goto found;
6949877Ssam 	}
6959877Ssam 	/*
6969877Ssam 	 * Search for vacant spot
6979877Ssam 	 */
6989877Ssam 	for (segnum = 0; segnum != -1;
6999877Ssam 	     segnum = rt_dir[segnum].rt_axhead.rt_nxtseg - 1)
7009877Ssam 	{
7019877Ssam 		last = rt_last + segnum*2*RT_BLOCK;
7029877Ssam 		for (de = rt_dir[segnum].rt_ents;
7039877Ssam 		    rt(de)->rt_stat != RT_ESEG; de++)
7049877Ssam 			if ((de)->rt_stat == RT_NULL) {
7059877Ssam 				if (bufp->st_size <= (de->rt_len*512)) {
7069877Ssam 					printf("a - %s\n",name),
7079877Ssam 					mkent(de, segnum, bufp,name);
7089877Ssam 					goto found;
709954Sbill 				}
7109877Ssam 				continue;
7119877Ssam 			}
712954Sbill 	}
7139877Ssam 	printf("%s: no slot for file\n", name);
7149877Ssam 	return (-1);
7154879Ssam 
7164879Ssam found:
7174879Ssam 	if (dope = lookup(name)) {
7184879Ssam 		toflop(name, bufp->st_size, dope);
7193489Sroot 		return (0);
720954Sbill 	}
7213489Sroot 	printf("%s: internal error, added then not found\n", name);
7223489Sroot 	return (-1);
7234879Ssam }
724954Sbill 
7254879Ssam mkent(de, segnum, bufp, name)
7264879Ssam 	register struct rt_ent *de;
7274879Ssam 	int segnum;
7284879Ssam 	register struct stat *bufp;
7294879Ssam 	char *name;
730954Sbill {
7314879Ssam 	struct tm *localtime();
7324879Ssam 	register struct tm *timp;
7334879Ssam 	register struct rt_ent *workp;
7344879Ssam 	int count;
735954Sbill 
736954Sbill 	count = (((bufp->st_size -1) >>9) + 1);
7374879Ssam 	/* make sure there is room */
7384879Ssam 	if (de->rt_len == count)
739954Sbill 		goto overwrite;
7404879Ssam 	if ((char *)rt_curend[segnum] == (rt_last + (segnum*2*RT_BLOCK))) {
7414879Ssam 		/* no entries left on segment */
7424879Ssam 		if (flag(o))
743954Sbill 			goto overwrite;
7449877Ssam 		fprintf(stderr, "Directory segment #%d full on  %s\n",
7459877Ssam 			segnum+1, defdev);
746954Sbill 		exit(1);
747954Sbill 	}
7484879Ssam 	/* copy directory entries up */
7494879Ssam 	for (workp = rt_curend[segnum]+1; workp > de; workp--)
750954Sbill 		*workp = workp[-1];
751954Sbill 	de[1].rt_len -= count;
752954Sbill 	de->rt_len = count;
7533346Swnj 	rt_curend[segnum]++;
754954Sbill 	rt_nleft--;
7554879Ssam 
756954Sbill overwrite:
757954Sbill 	srad50(name,de->rt_name);
758954Sbill 	timp = localtime(&bufp->st_mtime);
7597320Swnj 	de->rt_date.rt_dy = timp->tm_mday;
760954Sbill 	de->rt_date.rt_mo = timp->tm_mon + 1;
761954Sbill 	de->rt_date.rt_yr = timp->tm_year - 72;
762954Sbill 	de->rt_stat = RT_FILE;
763954Sbill 	de->rt_pad = 0;
764954Sbill 	de->rt_chan = 0;
765954Sbill 	de->rt_job = 0;
7664879Ssam 	lwrite((6+segnum*2)*RT_BLOCK, 2*RT_BLOCK, (char *)&rt_dir[segnum]);
767954Sbill }
768954Sbill 
7694879Ssam toflop(name, ocount, dope)
7704879Ssam 	char *name;
7714879Ssam 	register FLDOPE *dope;
7724879Ssam 	long ocount;
773954Sbill {
774954Sbill 	register file, n, startad = dope->startad, count = ocount;
775954Sbill 	char buff[512];
776954Sbill 
7774879Ssam 	file = open(name, 0);
7784879Ssam 	if (file < 0) {
7794879Ssam 		fprintf(stderr, "arff: couldn't open %s\n",name);
7804879Ssam 		exit(1);
7814879Ssam 	}
782954Sbill 	for( ; count >= 512; count -= 512) {
7834879Ssam 		read(file, buff, 512);
7844879Ssam 		lwrite(startad, 512, buff);
785954Sbill 		startad += 512;
786954Sbill 	}
7874879Ssam 	read(file, buff, count);
788954Sbill 	close(file);
7894879Ssam 	if (count <= 0)
7904879Ssam 		return;
7914879Ssam 	for (n = count; n < 512; n ++)
7924879Ssam 		buff[n] = 0;
7934879Ssam 	lwrite(startad, 512, buff);
7944879Ssam 	count = (dope->rtdope->rt_len*512-ocount)/512 ;
7954879Ssam 	if (count <= 0)
7964879Ssam 		return;
7974879Ssam 	for ( ; count > 0 ; count--) {
798954Sbill 		startad += 512;
7994879Ssam 		lwrite(startad, 512, zeroes);
800954Sbill 	}
8014879Ssam }
802954Sbill 
803954Sbill dcmd()
804954Sbill {
805954Sbill 	register int i;
806954Sbill 
807954Sbill 	rt_init();
8084879Ssam 	if (namc)
8094879Ssam 		for (i = 0; i < namc; i++)
8104879Ssam 			if (rtk(namv[i])==0)
8114879Ssam 				namv[i]=0;
8124879Ssam 	if (dirdirty)
813954Sbill 		scrunch();
814954Sbill }
8154879Ssam 
816954Sbill rtk(name)
8174879Ssam 	char *name;
818954Sbill {
819954Sbill 	register FLDOPE *dope;
820954Sbill 	register struct rt_ent *de;
821954Sbill 	FLDOPE *lookup();
822954Sbill 
8234879Ssam 	if (dope = lookup(name)) {
824954Sbill 		printf("d - %s\n",name);
825954Sbill 		de = dope->rtdope;
826954Sbill 		de->rt_stat = RT_NULL;
827954Sbill 		de->rt_name[0] = 0;
828954Sbill 		de->rt_name[1] = 0;
829954Sbill 		de->rt_name[2] = 0;
8309877Ssam 		*((u_short *)&(de->rt_date)) = 0;
831954Sbill 		dirdirty = 1;
8329877Ssam 		return (0);
833954Sbill 	}
8349877Ssam 	return (1);
835954Sbill }
8364879Ssam 
8374879Ssam scrunch()
8384879Ssam {
8393346Swnj 	register struct rt_ent *de , *workp;
8403346Swnj 	register segnum;
8414879Ssam 
8424879Ssam 	for (segnum = 0; segnum != -1;
8433346Swnj 	     segnum = rt_dir[segnum].rt_axhead.rt_nxtseg - 1) {
8444879Ssam 		for (de = rt_dir[segnum].rt_ents; de <= rt_curend[segnum]; de++)
8459877Ssam 			if (de->rt_stat == RT_NULL &&
84612012Shelge 			    (de+1)->rt_stat == RT_NULL) {
8474879Ssam 				(de+1)->rt_len += de->rt_len;
84812012Shelge 				for (workp=de; workp<rt_curend[segnum]; workp++)
8494879Ssam 					*workp = workp[1];
8504879Ssam 				de--;
8514879Ssam 				rt_curend[segnum]--;
8524879Ssam 				rt_nleft++;
8534879Ssam 			}
85412012Shelge 		lwrite((6+segnum*2)*RT_BLOCK, 2*RT_BLOCK,
85512012Shelge 			(char *)&rt_dir[segnum]);
856954Sbill 	}
85712012Shelge 	dirdirty = 0;
858954Sbill }
859