xref: /csrg-svn/old/arff/arff.c (revision 12012)
19877Ssam #ifndef lint
2*12012Shelge static	char sccsid[] = "@(#)arff.c	4.13 (Berkeley) 83/04/22";
39877Ssam #endif
44879Ssam 
5954Sbill #include <sys/types.h>
6954Sbill #include <sys/stat.h>
7954Sbill #include <time.h>
8954Sbill #include <signal.h>
9954Sbill #include <stdio.h>
104879Ssam 
11954Sbill #define dbprintf printf
124879Ssam 
13954Sbill struct rt_dat {
144879Ssam 	u_short	rt_yr:5;	/* year-1972 */
154879Ssam 	u_short	rt_dy:5;	/* day */
164879Ssam 	u_short	rt_mo:5;	/* month */
17954Sbill };
184879Ssam 
19954Sbill struct	rt_axent {
20954Sbill 	char	rt_sent[14];
21954Sbill };
22954Sbill 
23954Sbill struct rt_ent {
244879Ssam 	char	rt_pad;		/* unusued */
254879Ssam 	char	rt_stat;	/* type of entry, or end of seg */
264879Ssam 	u_short	rt_name[3];	/* name, 3 words in rad50 form */
277319Swnj 	u_short	rt_len;		/* length of file */
284879Ssam 	char	rt_chan;	/* only used in temporary files */
294879Ssam 	char	rt_job;		/* only used in temporary files */
309877Ssam 	struct	rt_dat rt_date;	/* creation date */
31954Sbill };
324879Ssam 
334879Ssam #define RT_TEMP		1
344879Ssam #define RT_NULL		2
354879Ssam #define RT_FILE		4
364879Ssam #define RT_ESEG		8
374879Ssam 
384879Ssam #define RT_BLOCK	512	/* block size */
394879Ssam #define RT_DIRSIZE	31	/* max # of directory segments */
404879Ssam 
41954Sbill struct rt_head {
424879Ssam 	short	rt_numseg;	/* # of segments available */
434879Ssam 	short	rt_nxtseg;	/* # of next logical segment */
444879Ssam 	short	rt_lstseg;	/* highest seg currently open */
454879Ssam 	u_short	rt_entpad;	/* extra words/directory entry */
464879Ssam 	short	rt_stfile;	/* block # where files begin */
47954Sbill };
484879Ssam 
49954Sbill struct	rt_dir {
50954Sbill 	struct rt_head	rt_axhead;
51954Sbill 	struct rt_ent	rt_ents[72];
524879Ssam 	char		_dirpad[6];
53954Sbill };
544879Ssam 
55954Sbill typedef struct fldope {
56954Sbill 	int	startad;
57954Sbill 	int	count;
58954Sbill struct	rt_ent	*rtdope;
59954Sbill } FLDOPE;
604879Ssam 
61954Sbill FLDOPE *lookup();
624879Ssam 
639877Ssam #define	rt(p)	((struct rt_ent *) p )
649877Ssam #define	Ain1	03100
659877Ssam #define	Ain2	050
669877Ssam #define	flag(c)	(flg[('c') - 'a'])
67954Sbill 
689877Ssam char	*man = "rxtd";
699877Ssam char	zeroes[512];
70954Sbill 
71954Sbill extern char *val;
72954Sbill extern char table[256];
734879Ssam struct rt_dir rt_dir[RT_DIRSIZE] = {
749877Ssam 	{ 4, 0, 1, 0, 14 },
759877Ssam 	{ { 0, RT_NULL, { 0, 0, 0 }, 494, 0 },
769877Ssam 	  { 0, RT_ESEG } }
774879Ssam };
78954Sbill 
794879Ssam int	rt_entsiz;
804879Ssam int	rt_nleft;
814879Ssam struct rt_ent *rt_curend[RT_DIRSIZE];
824879Ssam int	floppydes;
834879Ssam int	dirdirty;
844879Ssam char	*rt_last;
854879Ssam char	*defdev = "/dev/floppy";
86954Sbill 
874879Ssam char *opt = "vf";
884879Ssam 
89954Sbill int	signum[] = {SIGHUP, SIGINT, SIGQUIT, 0};
904879Ssam extern long lseek();
914879Ssam int	rcmd(), dcmd(), xcmd(), tcmd();
924879Ssam 
93954Sbill int	(*comfun)();
94954Sbill char	flg[26];
95954Sbill char	**namv;
96954Sbill int	namc;
97954Sbill int	file;
98954Sbill 
99954Sbill main(argc, argv)
1004879Ssam 	char *argv[];
101954Sbill {
102954Sbill 	register char *cp;
103954Sbill 
1044879Ssam 	if (argc < 2)
105954Sbill 		usage();
1064879Ssam 	for (cp = argv[1]; *cp; cp++)
1074879Ssam 		switch (*cp) {
108954Sbill 
1094879Ssam 		case 'm':
1104879Ssam 		case 'v':
1114879Ssam 		case 'u':
1124879Ssam 		case 'w':
1134879Ssam 			flg[*cp-'a']++;
1144879Ssam 			continue;
1154879Ssam 		case 'c':
1164879Ssam 			{
1174879Ssam #define SURE	"Last chance before clobbering floppy?"
1184879Ssam 				int tty;
1194879Ssam 				char response[128];
120954Sbill 
1214879Ssam 				tty = open("/dev/tty", 2);
1224879Ssam 				write(tty, SURE, sizeof(SURE));
1234879Ssam 				read(tty, response, sizeof(response));
1244879Ssam 				if (*response != 'y')
1254879Ssam 					exit(50);
1264879Ssam 				flag(c)++;
1274879Ssam 				close(tty);
1284879Ssam 			}
1294879Ssam 			dirdirty++;
1304879Ssam 			continue;
131954Sbill 
1324879Ssam 		case 'r':
1334879Ssam 			setcom(rcmd);
1344879Ssam 			flag(r)++;
1354879Ssam 			continue;
136954Sbill 
1374879Ssam 		case 'd':
1384879Ssam 			setcom(dcmd);
1394879Ssam 			flag(d)++;
1404879Ssam 			continue;
141954Sbill 
1424879Ssam 		case 'x':
1434879Ssam 			setcom(xcmd);
1444879Ssam 			continue;
145954Sbill 
1464879Ssam 		case 't':
1474879Ssam 			setcom(tcmd);
1484879Ssam 			continue;
149954Sbill 
1504879Ssam 		case 'f':
1514879Ssam 			defdev = argv[2];
1524879Ssam 			argv++;
1534879Ssam 			argc--;
1544879Ssam 			continue;
1554879Ssam 
1564879Ssam 		default:
1574879Ssam 			fprintf(stderr, "arff: bad option `%c'\n", *cp);
1584879Ssam 			exit(1);
1594879Ssam 		}
1604879Ssam 
161954Sbill 	namv = argv+2;
162954Sbill 	namc = argc-2;
1634879Ssam 	if (comfun == 0) {
1644879Ssam 		if (flag(u) == 0) {
1654879Ssam 			fprintf(stderr, "arff: one of [%s] must be specified\n",
1664879Ssam 				man);
167954Sbill 			exit(1);
168954Sbill 		}
169954Sbill 		setcom(rcmd);
170954Sbill 	}
171954Sbill 	(*comfun)();
172954Sbill 	exit(notfound());
173954Sbill }
174954Sbill 
175954Sbill setcom(fun)
1764879Ssam 	int (*fun)();
177954Sbill {
1784879Ssam 	if (comfun != 0) {
179954Sbill 		fprintf(stderr, "arff: only one of [%s] allowed\n", man);
180954Sbill 		exit(1);
181954Sbill 	}
182954Sbill 	comfun = fun;
183954Sbill }
184954Sbill 
185954Sbill usage()
186954Sbill {
1873356Swnj 	fprintf(stderr, "usage: ar [%s][%s] archive files ...\n", opt, man);
188954Sbill 	exit(1);
189954Sbill }
190954Sbill 
191954Sbill notfound()
192954Sbill {
1934879Ssam 	register i, n = 0;
194954Sbill 
1954879Ssam 	for (i = 0; i < namc; i++)
1964879Ssam 		if (namv[i]) {
197954Sbill 			fprintf(stderr, "arff: %s not found\n", namv[i]);
198954Sbill 			n++;
199954Sbill 		}
2009877Ssam 	return (n);
201954Sbill }
202954Sbill 
203954Sbill mesg(c)
204954Sbill {
2054879Ssam 	if (flag(v))
2064879Ssam 		if (c != 'c' || flag(v) > 1)
207954Sbill 			printf("%c - %s\n", c, file);
208954Sbill }
209954Sbill 
210954Sbill tcmd()
211954Sbill {
2124879Ssam 	register char *de, *last;
213954Sbill 	FLDOPE *lookup(), *dope;
2144879Ssam 	int segnum, nleft;
2154879Ssam 	register i;
216954Sbill 	register struct rt_ent *rde;
217954Sbill 
218954Sbill 	rt_init();
2199877Ssam 	if (namc != 0) {
2204879Ssam 		for (i = 0; i < namc; i++)
2214879Ssam 			if (dope = lookup(namv[i])) {
222954Sbill 				rde = dope->rtdope;
223954Sbill 				rtls(rde);
224954Sbill 				namv[i] = 0;
225954Sbill 			}
2269877Ssam 		return;
2279877Ssam 	}
2289877Ssam 	for (segnum = 0; segnum != -1;
2299877Ssam 	  segnum = rt_dir[segnum].rt_axhead.rt_nxtseg - 1) {
2309877Ssam 		last = rt_last + segnum*2*RT_BLOCK;
2319877Ssam 		for (de = ((char *)&rt_dir[segnum])+10; de <= last;
2329877Ssam 		    de += rt_entsiz)
2339877Ssam 			if (rtls(rt(de))) {
2349877Ssam 				nleft = (last-de)/rt_entsiz;
2359877Ssam #define ENTRIES "\n%d entries remaining in directory segment %d.\n"
2369877Ssam 				printf(ENTRIES, nleft, segnum+1);
2379877Ssam 				break;
2389877Ssam 			}
2399877Ssam 	}
240954Sbill }
2414879Ssam 
242954Sbill rtls(de)
2434879Ssam 	register struct rt_ent *de;
244954Sbill {
2454879Ssam 	int month, day, year;
246954Sbill 	char name[12], ext[4];
247954Sbill 
2484879Ssam 	switch (de->rt_stat) {
2494879Ssam 
2504879Ssam 	case RT_TEMP:
2514879Ssam 		if (flag(v))
252954Sbill 			printf("Tempfile:\n");
2534879Ssam 		/* fall thru...*/
254954Sbill 
2554879Ssam 	case RT_FILE:
2564879Ssam 		if (!flag(v)) {
2574879Ssam 			sunrad50(name, de->rt_name);
2584879Ssam 			printf("%s\n", name);
259954Sbill 			break;
260954Sbill 		}
2614879Ssam 		unrad50(2, de->rt_name, name);
2624879Ssam 		unrad50(1, &(de->rt_name[2]), ext);
2634879Ssam 		day = de->rt_date.rt_dy;
2644879Ssam 		year = de->rt_date.rt_yr+72;
2654879Ssam 		month = de->rt_date.rt_mo;
2664879Ssam 		printf("%6.6s  %3.3s	%02d/%02d/%02d	%d\n",name,
2674879Ssam 			ext, month, day, year, de->rt_len);
2684879Ssam 		break;
269954Sbill 
2704879Ssam 	case RT_NULL:
2714879Ssam 		printf("%-25.9s	%d\n","<UNUSED>", de->rt_len);
2724879Ssam 		break;
273954Sbill 
2744879Ssam 	case RT_ESEG:
2759877Ssam 		return (1);
276954Sbill 	}
2779877Ssam 	return (0);
278954Sbill }
2794879Ssam 
280954Sbill xcmd()
281954Sbill {
2824879Ssam 	register char *de, *last;
2833346Swnj 	int segnum;
284954Sbill 	char name[12];
285954Sbill 	register int i;
286954Sbill 
287954Sbill 	rt_init();
2889877Ssam 	if (namc != 0) {
2894879Ssam 		for (i = 0; i < namc; i++)
2904879Ssam 			if (rtx(namv[i]) == 0)
2914879Ssam 				namv[i] = 0;
2929877Ssam 		return;
2939877Ssam 	}
2949877Ssam 	for (segnum = 0; segnum != -1;
2959877Ssam 	     segnum = rt_dir[segnum].rt_axhead.rt_nxtseg-1)
2969877Ssam 		for (last = rt_last+(segnum*2*RT_BLOCK),
2979877Ssam 		     de = ((char *)&rt_dir[segnum])+10; de <= last;
2989877Ssam 		     de += rt_entsiz)
2999877Ssam 			switch (rt(de)->rt_stat) {
3009877Ssam 
3019877Ssam 			case RT_ESEG:
3029877Ssam 				return;
3039877Ssam 
3049877Ssam 			case RT_TEMP:
3059877Ssam 			case RT_FILE:
3069877Ssam 				sunrad50(name,rt(de)->rt_name);
3079877Ssam 				rtx(name);
3089877Ssam 
3099877Ssam 			case RT_NULL:
3109877Ssam 				break;
3119877Ssam 			}
312954Sbill }
3134879Ssam 
314954Sbill rtx(name)
3154879Ssam 	char *name;
316954Sbill {
317954Sbill 	register FLDOPE *dope;
318954Sbill 	FLDOPE *lookup();
319954Sbill 	register startad, count;
3204879Ssam 	int file;
3214879Ssam 	char buff[512];
322954Sbill 
323954Sbill 
3244879Ssam 	if (dope = lookup(name)) {
3254879Ssam 		if (flag(v))
326954Sbill 			rtls(dope->rtdope);
327954Sbill 		else
328954Sbill 			printf("x - %s\n",name);
329954Sbill 
3304879Ssam 		if ((file = creat(name, 0666)) < 0)
3319877Ssam 			return (1);
332954Sbill 		count = dope->count;
333954Sbill 		startad = dope->startad;
334954Sbill 		for( ; count > 0 ; count -= 512) {
3354879Ssam 			lread(startad, 512, buff);
3364879Ssam 			write(file, buff, 512);
337954Sbill 			startad += 512;
338954Sbill 		}
339954Sbill 		close(file);
3409877Ssam 		return (0);
341954Sbill 	}
3429877Ssam 	return (1);
343954Sbill }
3444879Ssam 
345954Sbill rt_init()
346954Sbill {
347954Sbill 	static initized = 0;
3484879Ssam 	register char *de, *last;
3493346Swnj 	register i;
3503799Shickman 	int dirnum;
3513799Shickman 	char *mode;
3523799Shickman 	FILE *temp_floppydes;
353954Sbill 
3544879Ssam 	if (initized)
3554879Ssam 		return;
356954Sbill 	initized = 1;
3574879Ssam 	if (flag(c) || flag(d) || flag(r))
3583799Shickman 		mode = "r+";
359954Sbill 	else
3603799Shickman 		mode = "r";
3614879Ssam 	if ((temp_floppydes = fopen(defdev, mode)) == NULL) {
3623799Shickman 		perror(defdev);
3633356Swnj 		exit(1);
3643799Shickman 	} else
3653799Shickman 		floppydes = fileno(temp_floppydes);
3664879Ssam 	if (!flag(c)) {
3674879Ssam 		lread(6*RT_BLOCK, 2*RT_BLOCK, (char *)&rt_dir[0]);
3683346Swnj 		dirnum = rt_dir[0].rt_axhead.rt_numseg;
369*12012Shelge 		/* check for blank/uninitialized diskette */
370*12012Shelge 		if (dirnum <= 0) {
371*12012Shelge 			fprintf(stderr,"arff: bad directory format\n");
372*12012Shelge 			exit(1);
373*12012Shelge 		}
3743346Swnj 		if (dirnum > RT_DIRSIZE) {
3754879Ssam 			fprintf(stderr,"arff: too many directory segments\n");
3764879Ssam 			exit(1);
3773346Swnj 		}
3784879Ssam 		for (i = 1; i < dirnum; i++)
3794879Ssam 			lread((6+2*i)*RT_BLOCK, 2*RT_BLOCK, (char *)&rt_dir[i]);
3803489Sroot 	} else
3813489Sroot 		dirnum = 1;
382954Sbill 
3833346Swnj 	rt_entsiz = 2*rt_dir[0].rt_axhead.rt_entpad + 14;
3843346Swnj 	rt_entsiz = 14;			/* assume rt_entpad = 0 ??? */
3853346Swnj 	rt_last = ((char *) &rt_dir[0]) + 10 + 1014/rt_entsiz*rt_entsiz;
3863346Swnj 	rt_nleft = 0;
3873346Swnj 
3884879Ssam 	for (i = 0; i < dirnum; i++) {
3894879Ssam 		last = rt_last + i*2*RT_BLOCK;
3904879Ssam 		for (de = ((char *)&rt_dir[i])+10; de <= last; de += rt_entsiz)
3914879Ssam 			if (rt(de)->rt_stat == RT_ESEG)
3924879Ssam 				break;
3934879Ssam 		rt_curend[i] = rt(de);
3944879Ssam 		rt_nleft += (last-de)/rt_entsiz;
395954Sbill 	}
396954Sbill }
397954Sbill 
398954Sbill static FLDOPE result;
3994879Ssam 
400954Sbill FLDOPE *
401954Sbill lookup(name)
4024879Ssam 	char *name;
403954Sbill {
404954Sbill 	unsigned short rname[3];
4054879Ssam 	register char *de, *last;
4063346Swnj 	int segnum;
407954Sbill 	register index;
408954Sbill 
409954Sbill 	srad50(name,rname);
410954Sbill 
4113356Swnj 	/*
412954Sbill 	 *  Search for name, accumulate blocks in index
413954Sbill 	 */
414954Sbill 	rt_init();
4154879Ssam 	for (segnum = 0; segnum != -1;
4164879Ssam 	     segnum = rt_dir[segnum].rt_axhead.rt_nxtseg - 1)
4174879Ssam 	{
4184879Ssam 		index = 0;
4194879Ssam 		last = rt_last + segnum*2*RT_BLOCK;
4204879Ssam 		for (de=((char *)&rt_dir[segnum])+10;
4214879Ssam 		     rt(de)->rt_stat != RT_ESEG; de += rt_entsiz)
4224879Ssam 			switch(rt(de)->rt_stat) {
4234879Ssam 
4244879Ssam 			case RT_FILE:
4254879Ssam 			case RT_TEMP:
4264879Ssam 				if(samename(rname,rt(de)->rt_name)) {
4274879Ssam 					result.count = rt(de)->rt_len * 512;
4284879Ssam 					result.startad = 512*
4294879Ssam 						(rt_dir[segnum].rt_axhead.rt_stfile + index);
4304879Ssam 					result.rtdope = (struct rt_ent *) de;
4319877Ssam 					return (&result);
4324879Ssam 				}
4334879Ssam 
4344879Ssam 			case RT_NULL:
4354879Ssam 				index += rt(de)->rt_len;
4364879Ssam 			}
4373346Swnj         }
4389877Ssam 	return ((FLDOPE *) 0);
4394879Ssam 
440954Sbill }
4414879Ssam 
442954Sbill static
4434879Ssam samename(a, b)
4444879Ssam 	u_short a[], b[];
445954Sbill {
4469877Ssam 	return (*a == *b && a[1] == b[1] && a[2] == b[2] );
447954Sbill }
448954Sbill 
4494879Ssam rad50(cp, out)
4504879Ssam 	register u_char *cp;
4514879Ssam 	u_short *out;
452954Sbill {
4534879Ssam 	register index, temp;
454954Sbill 
4554879Ssam 	for (index = 0; *cp; index++) {
456954Sbill 		temp = Ain1 * table[*cp++];
4574879Ssam 		if (*cp!=0) {
458954Sbill 			temp += Ain2 * table[*cp++];
459954Sbill 			if(*cp!=0)
460954Sbill 				temp += table[*cp++];
461954Sbill 		}
462954Sbill 		out[index] = temp;
463954Sbill 	}
464954Sbill }
465954Sbill 
4664879Ssam #define reduce(x, p, q) (x = v[p/q], p %= q);
4674879Ssam 
4684879Ssam unrad50(count, in, cp)
4694879Ssam 	u_short *in;
4704879Ssam 	register char *cp;
471954Sbill {
4724879Ssam 	register i, temp;
4734879Ssam 	register u_char *v = (u_char *) val;
474954Sbill 
4754879Ssam 	for (i = 0; i < count; i++) {
476954Sbill 		temp = in[i];
4774879Ssam 		reduce(*cp++, temp, Ain1);
4784879Ssam 		reduce(*cp++, temp, Ain2);
4794879Ssam 		reduce(*cp++, temp, 1);
480954Sbill 	}
481954Sbill 	*cp=0;
482954Sbill }
483954Sbill 
4844879Ssam srad50(name, rname)
4854879Ssam 	register char *name;
4864879Ssam 	register u_short *rname;
487954Sbill {
4884879Ssam 	register index;
4894879Ssam 	register char *cp;
4904879Ssam 	char file[7], ext[4];
4914879Ssam 
4923356Swnj 	/*
493954Sbill 	 * Find end of pathname
494954Sbill 	 */
4954879Ssam 	for (cp = name; *cp++; )
4964879Ssam 		;
4974879Ssam 	while (cp >= name && *--cp != '/')
4984879Ssam 		;
499954Sbill 	cp++;
5003356Swnj 	/*
501954Sbill 	 * Change to rad50
502954Sbill 	 */
5034879Ssam 	for (index = 0; *cp; ) {
504954Sbill 		file[index++] = *cp++;
5054879Ssam 		if (*cp == '.') {
506954Sbill 			cp++;
507954Sbill 			break;
508954Sbill 		}
5094879Ssam 		if (index >= 6) {
510954Sbill 			break;
511954Sbill 		}
512954Sbill 	}
513954Sbill 	file[index] = 0;
5144879Ssam 	for (index = 0; *cp; ) {
515954Sbill 		ext[index++] = *cp++;
5164879Ssam 		if (*cp == '.' || index >= 3)
517954Sbill 			break;
518954Sbill 	}
519954Sbill 	ext[index]=0;
5204879Ssam 	rname[0] = rname[1] = rname[2] = 0;
5214879Ssam 	rad50((u_char *)file, rname);
5224879Ssam 	rad50((u_char *)ext, rname+2);
523954Sbill }
5244879Ssam 
5254879Ssam sunrad50(name, rname)
5264879Ssam 	u_short rname[];
5274879Ssam 	register char *name;
528954Sbill {
529954Sbill 	register char *cp, *cp2;
530954Sbill 	char ext[4];
531954Sbill 
5324879Ssam 	unrad50(2, rname, name);
5334879Ssam 	unrad50(1, rname + 2, ext);
5344879Ssam 	/*
5354879Ssam 	 * Jam name and extension together with a dot
5364879Ssam 	 * deleting white space
5374879Ssam 	 */
5384879Ssam 	for (cp = name; *cp++;)
5394879Ssam 		;
5404879Ssam 	--cp;
5414879Ssam 	while (*--cp == ' ' && cp >= name)
5424879Ssam 		;
5434879Ssam 	*++cp = '.';
5444879Ssam 	cp++;
5454879Ssam 	for (cp2 = ext; *cp2 != ' ' && cp2 < ext+3;)
546954Sbill 		*cp++ = *cp2++;
547954Sbill 	*cp=0;
5484879Ssam 	if (cp[-1] == '.')
5494879Ssam 		cp[-1] = 0;
550954Sbill }
551954Sbill 
552954Sbill static char *oval = " ABCDEFGHIJKLMNOPQRSTUVWXYZ$.@0123456789";
553954Sbill static char *val = " abcdefghijklmnopqrstuvwxyz$.@0123456789";
5544879Ssam 
555954Sbill static char table[256] = {
556954Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
557954Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
558954Sbill 0, 29, 29, 29, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 29,
559954Sbill 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 29, 29, 29, 29, 29, 29,
560954Sbill 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
561954Sbill 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
562954Sbill 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
563954Sbill 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
564954Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
565954Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
566954Sbill 0, 29, 29, 29, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 29,
567954Sbill 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 29, 29, 29, 29, 29, 29,
568954Sbill 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
569954Sbill 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
570954Sbill 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
571954Sbill 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29 };
572954Sbill 
5734879Ssam /*
5744879Ssam  * Logical to physical adress translation
5754879Ssam  */
5764879Ssam long
5774879Ssam trans(logical)
5784879Ssam 	register int logical;
579954Sbill {
580954Sbill 	register int sector, bytes, track;
581954Sbill 
5824879Ssam 	logical += 26*128;
5834879Ssam 	bytes = (logical&127);
584954Sbill 	logical >>= 7;
5854879Ssam 	sector = logical%26;
586954Sbill 	if(sector >= 13)
5874879Ssam 		sector = sector*2+1;
588954Sbill 	else
589954Sbill 		sector *= 2;
5904879Ssam 	sector += 26 + ((track = (logical/26))-1)*6;
591954Sbill 	sector %= 26;
5929877Ssam 	return ((((track*26)+sector) << 7) + bytes);
593954Sbill }
5944879Ssam 
5954879Ssam lread(startad, count, obuff)
5964879Ssam 	register startad, count;
5974879Ssam 	register char *obuff;
598954Sbill {
599954Sbill 	long trans();
600954Sbill 	extern floppydes;
6014879Ssam 	register int size = flag(m) ? 512 : 128;
6024879Ssam 
603954Sbill 	rt_init();
6044879Ssam 	while ((count -= size) >= 0) {
6054879Ssam 		lseek(floppydes, flag(m) ?
6064879Ssam 			(long)startad : trans(startad), 0);
6074879Ssam 		if (read(floppydes, obuff, size) != size)
6084879Ssam 			fprintf(stderr, "arff: read error block %d\n",
6094879Ssam 				startad/size);
6104879Ssam 		obuff += size;
6114879Ssam 		startad += size;
6124879Ssam 	}
613954Sbill }
6144879Ssam 
6154879Ssam lwrite(startad, count, obuff)
6164879Ssam 	register startad, count;
6174879Ssam 	register char *obuff;
618954Sbill {
619954Sbill 	long trans();
620954Sbill 	extern floppydes;
6214879Ssam 	register int size = flag(m) ? 512 : 128;
6224879Ssam 
623954Sbill 	rt_init();
6244879Ssam 	while ((count -= size) >= 0) {
6254879Ssam 		lseek(floppydes, flag(m) ?
6264879Ssam 			(long)startad : trans(startad), 0);
6274879Ssam 		if (write(floppydes, obuff, size) != size)
6284879Ssam 			fprintf(stderr, "arff: write error block %d\n",
6294879Ssam 				startad/size);
6304879Ssam 		obuff += size;
6314879Ssam 		startad += size;
6324879Ssam 	}
633954Sbill }
634954Sbill 
635954Sbill rcmd()
636954Sbill {
637954Sbill 	register int i;
638954Sbill 
639954Sbill 	rt_init();
6404879Ssam 	if (namc > 0)
6414879Ssam 		for (i = 0; i < namc; i++)
6424879Ssam 			if (rtr(namv[i]) == 0)
6434879Ssam 				namv[i] = 0;
644954Sbill }
645954Sbill 
646954Sbill rtr(name)
6474879Ssam 	char *name;
648954Sbill {
6494879Ssam 	register FLDOPE *dope;
6504879Ssam 	register struct rt_ent *de;
6514879Ssam 	struct stat buf;
6524879Ssam 	register struct stat *bufp = &buf;
6533346Swnj 	int segnum;
6543346Swnj 	register char *last;
655954Sbill 
6564879Ssam 	if (stat(name, bufp) < 0) {
6573489Sroot 		perror(name);
6589877Ssam 		return (-1);
6593489Sroot 	}
6604879Ssam 	if (dope = lookup(name)) {
661954Sbill 		/* can replace, no problem */
662954Sbill 		de = dope->rtdope;
6634879Ssam 		if (bufp->st_size <= (de->rt_len * 512))
664954Sbill 			printf("r - %s\n",name),
6654879Ssam 			toflop(name, bufp->st_size, dope);
666954Sbill 		else {
6679877Ssam 			fprintf(stderr,
6689877Ssam 			  "%s will not fit in currently used file on floppy\n",
6699877Ssam 			  name);
6709877Ssam 			return (-1);
671954Sbill 		}
6729877Ssam 		goto found;
6739877Ssam 	}
6749877Ssam 	/*
6759877Ssam 	 * Search for vacant spot
6769877Ssam 	 */
6779877Ssam 	for (segnum = 0; segnum != -1;
6789877Ssam 	     segnum = rt_dir[segnum].rt_axhead.rt_nxtseg - 1)
6799877Ssam 	{
6809877Ssam 		last = rt_last + segnum*2*RT_BLOCK;
6819877Ssam 		for (de = rt_dir[segnum].rt_ents;
6829877Ssam 		    rt(de)->rt_stat != RT_ESEG; de++)
6839877Ssam 			if ((de)->rt_stat == RT_NULL) {
6849877Ssam 				if (bufp->st_size <= (de->rt_len*512)) {
6859877Ssam 					printf("a - %s\n",name),
6869877Ssam 					mkent(de, segnum, bufp,name);
6879877Ssam 					goto found;
688954Sbill 				}
6899877Ssam 				continue;
6909877Ssam 			}
691954Sbill 	}
6929877Ssam 	printf("%s: no slot for file\n", name);
6939877Ssam 	return (-1);
6944879Ssam 
6954879Ssam found:
6964879Ssam 	if (dope = lookup(name)) {
6974879Ssam 		toflop(name, bufp->st_size, dope);
6983489Sroot 		return (0);
699954Sbill 	}
7003489Sroot 	printf("%s: internal error, added then not found\n", name);
7013489Sroot 	return (-1);
7024879Ssam }
703954Sbill 
7044879Ssam mkent(de, segnum, bufp, name)
7054879Ssam 	register struct rt_ent *de;
7064879Ssam 	int segnum;
7074879Ssam 	register struct stat *bufp;
7084879Ssam 	char *name;
709954Sbill {
7104879Ssam 	struct tm *localtime();
7114879Ssam 	register struct tm *timp;
7124879Ssam 	register struct rt_ent *workp;
7134879Ssam 	int count;
714954Sbill 
715954Sbill 	count = (((bufp->st_size -1) >>9) + 1);
7164879Ssam 	/* make sure there is room */
7174879Ssam 	if (de->rt_len == count)
718954Sbill 		goto overwrite;
7194879Ssam 	if ((char *)rt_curend[segnum] == (rt_last + (segnum*2*RT_BLOCK))) {
7204879Ssam 		/* no entries left on segment */
7214879Ssam 		if (flag(o))
722954Sbill 			goto overwrite;
7239877Ssam 		fprintf(stderr, "Directory segment #%d full on  %s\n",
7249877Ssam 			segnum+1, defdev);
725954Sbill 		exit(1);
726954Sbill 	}
7274879Ssam 	/* copy directory entries up */
7284879Ssam 	for (workp = rt_curend[segnum]+1; workp > de; workp--)
729954Sbill 		*workp = workp[-1];
730954Sbill 	de[1].rt_len -= count;
731954Sbill 	de->rt_len = count;
7323346Swnj 	rt_curend[segnum]++;
733954Sbill 	rt_nleft--;
7344879Ssam 
735954Sbill overwrite:
736954Sbill 	srad50(name,de->rt_name);
737954Sbill 	timp = localtime(&bufp->st_mtime);
7387320Swnj 	de->rt_date.rt_dy = timp->tm_mday;
739954Sbill 	de->rt_date.rt_mo = timp->tm_mon + 1;
740954Sbill 	de->rt_date.rt_yr = timp->tm_year - 72;
741954Sbill 	de->rt_stat = RT_FILE;
742954Sbill 	de->rt_pad = 0;
743954Sbill 	de->rt_chan = 0;
744954Sbill 	de->rt_job = 0;
7454879Ssam 	lwrite((6+segnum*2)*RT_BLOCK, 2*RT_BLOCK, (char *)&rt_dir[segnum]);
746954Sbill }
747954Sbill 
7484879Ssam toflop(name, ocount, dope)
7494879Ssam 	char *name;
7504879Ssam 	register FLDOPE *dope;
7514879Ssam 	long ocount;
752954Sbill {
753954Sbill 	register file, n, startad = dope->startad, count = ocount;
754954Sbill 	char buff[512];
755954Sbill 
7564879Ssam 	file = open(name, 0);
7574879Ssam 	if (file < 0) {
7584879Ssam 		fprintf(stderr, "arff: couldn't open %s\n",name);
7594879Ssam 		exit(1);
7604879Ssam 	}
761954Sbill 	for( ; count >= 512; count -= 512) {
7624879Ssam 		read(file, buff, 512);
7634879Ssam 		lwrite(startad, 512, buff);
764954Sbill 		startad += 512;
765954Sbill 	}
7664879Ssam 	read(file, buff, count);
767954Sbill 	close(file);
7684879Ssam 	if (count <= 0)
7694879Ssam 		return;
7704879Ssam 	for (n = count; n < 512; n ++)
7714879Ssam 		buff[n] = 0;
7724879Ssam 	lwrite(startad, 512, buff);
7734879Ssam 	count = (dope->rtdope->rt_len*512-ocount)/512 ;
7744879Ssam 	if (count <= 0)
7754879Ssam 		return;
7764879Ssam 	for ( ; count > 0 ; count--) {
777954Sbill 		startad += 512;
7784879Ssam 		lwrite(startad, 512, zeroes);
779954Sbill 	}
7804879Ssam }
781954Sbill 
782954Sbill dcmd()
783954Sbill {
784954Sbill 	register int i;
785954Sbill 
786954Sbill 	rt_init();
7874879Ssam 	if (namc)
7884879Ssam 		for (i = 0; i < namc; i++)
7894879Ssam 			if (rtk(namv[i])==0)
7904879Ssam 				namv[i]=0;
7914879Ssam 	if (dirdirty)
792954Sbill 		scrunch();
793954Sbill }
7944879Ssam 
795954Sbill rtk(name)
7964879Ssam 	char *name;
797954Sbill {
798954Sbill 	register FLDOPE *dope;
799954Sbill 	register struct rt_ent *de;
800954Sbill 	FLDOPE *lookup();
801954Sbill 
8024879Ssam 	if (dope = lookup(name)) {
803954Sbill 		printf("d - %s\n",name);
804954Sbill 		de = dope->rtdope;
805954Sbill 		de->rt_stat = RT_NULL;
806954Sbill 		de->rt_name[0] = 0;
807954Sbill 		de->rt_name[1] = 0;
808954Sbill 		de->rt_name[2] = 0;
8099877Ssam 		*((u_short *)&(de->rt_date)) = 0;
810954Sbill 		dirdirty = 1;
8119877Ssam 		return (0);
812954Sbill 	}
8139877Ssam 	return (1);
814954Sbill }
8154879Ssam 
8164879Ssam scrunch()
8174879Ssam {
8183346Swnj 	register struct rt_ent *de , *workp;
8193346Swnj 	register segnum;
8204879Ssam 
8214879Ssam 	for (segnum = 0; segnum != -1;
8223346Swnj 	     segnum = rt_dir[segnum].rt_axhead.rt_nxtseg - 1) {
8234879Ssam 		for (de = rt_dir[segnum].rt_ents; de <= rt_curend[segnum]; de++)
8249877Ssam 			if (de->rt_stat == RT_NULL &&
825*12012Shelge 			    (de+1)->rt_stat == RT_NULL) {
8264879Ssam 				(de+1)->rt_len += de->rt_len;
827*12012Shelge 				for (workp=de; workp<rt_curend[segnum]; workp++)
8284879Ssam 					*workp = workp[1];
8294879Ssam 				de--;
8304879Ssam 				rt_curend[segnum]--;
8314879Ssam 				rt_nleft++;
8324879Ssam 			}
833*12012Shelge 		lwrite((6+segnum*2)*RT_BLOCK, 2*RT_BLOCK,
834*12012Shelge 			(char *)&rt_dir[segnum]);
835954Sbill 	}
836*12012Shelge 	dirdirty = 0;
837954Sbill }
838