xref: /csrg-svn/old/arff/arff.c (revision 15553)
19877Ssam #ifndef lint
2*15553Sralph static	char sccsid[] = "@(#)arff.c	4.17 (Berkeley) 83/11/18";
39877Ssam #endif
44879Ssam 
5954Sbill #include <sys/types.h>
6954Sbill #include <sys/stat.h>
713605Ssam #include <sys/time.h>
8954Sbill #include <signal.h>
9954Sbill #include <stdio.h>
1013910Ssam #include <sys/file.h>
114879Ssam 
12954Sbill #define dbprintf printf
134879Ssam 
14954Sbill struct rt_dat {
154879Ssam 	u_short	rt_yr:5;	/* year-1972 */
164879Ssam 	u_short	rt_dy:5;	/* day */
174879Ssam 	u_short	rt_mo:5;	/* month */
18954Sbill };
194879Ssam 
20954Sbill struct	rt_axent {
21954Sbill 	char	rt_sent[14];
22954Sbill };
23954Sbill 
24954Sbill struct rt_ent {
254879Ssam 	char	rt_pad;		/* unusued */
264879Ssam 	char	rt_stat;	/* type of entry, or end of seg */
274879Ssam 	u_short	rt_name[3];	/* name, 3 words in rad50 form */
287319Swnj 	u_short	rt_len;		/* length of file */
294879Ssam 	char	rt_chan;	/* only used in temporary files */
304879Ssam 	char	rt_job;		/* only used in temporary files */
319877Ssam 	struct	rt_dat rt_date;	/* creation date */
32954Sbill };
334879Ssam 
344879Ssam #define RT_TEMP		1
354879Ssam #define RT_NULL		2
364879Ssam #define RT_FILE		4
374879Ssam #define RT_ESEG		8
384879Ssam 
394879Ssam #define RT_BLOCK	512	/* block size */
404879Ssam #define RT_DIRSIZE	31	/* max # of directory segments */
414879Ssam 
42954Sbill struct rt_head {
434879Ssam 	short	rt_numseg;	/* # of segments available */
444879Ssam 	short	rt_nxtseg;	/* # of next logical segment */
454879Ssam 	short	rt_lstseg;	/* highest seg currently open */
464879Ssam 	u_short	rt_entpad;	/* extra words/directory entry */
474879Ssam 	short	rt_stfile;	/* block # where files begin */
48954Sbill };
494879Ssam 
50954Sbill struct	rt_dir {
51954Sbill 	struct rt_head	rt_axhead;
52954Sbill 	struct rt_ent	rt_ents[72];
534879Ssam 	char		_dirpad[6];
54954Sbill };
554879Ssam 
56954Sbill typedef struct fldope {
57954Sbill 	int	startad;
58954Sbill 	int	count;
59954Sbill struct	rt_ent	*rtdope;
60954Sbill } FLDOPE;
614879Ssam 
62954Sbill FLDOPE *lookup();
634879Ssam 
649877Ssam #define	rt(p)	((struct rt_ent *) p )
659877Ssam #define	Ain1	03100
669877Ssam #define	Ain2	050
679877Ssam #define	flag(c)	(flg[('c') - 'a'])
68954Sbill 
699877Ssam char	*man = "rxtd";
709877Ssam char	zeroes[512];
71954Sbill 
72954Sbill extern char *val;
73954Sbill extern char table[256];
744879Ssam struct rt_dir rt_dir[RT_DIRSIZE] = {
759877Ssam 	{ 4, 0, 1, 0, 14 },
769877Ssam 	{ { 0, RT_NULL, { 0, 0, 0 }, 494, 0 },
779877Ssam 	  { 0, RT_ESEG } }
784879Ssam };
79954Sbill 
804879Ssam int	rt_entsiz;
814879Ssam int	rt_nleft;
824879Ssam struct rt_ent *rt_curend[RT_DIRSIZE];
834879Ssam int	floppydes;
844879Ssam int	dirdirty;
854879Ssam char	*rt_last;
864879Ssam char	*defdev = "/dev/floppy";
87954Sbill 
884879Ssam char *opt = "vf";
894879Ssam 
90954Sbill int	signum[] = {SIGHUP, SIGINT, SIGQUIT, 0};
914879Ssam extern long lseek();
924879Ssam int	rcmd(), dcmd(), xcmd(), tcmd();
934879Ssam 
94954Sbill int	(*comfun)();
95954Sbill char	flg[26];
96954Sbill char	**namv;
97954Sbill int	namc;
98954Sbill int	file;
99954Sbill 
100954Sbill main(argc, argv)
1014879Ssam 	char *argv[];
102954Sbill {
103954Sbill 	register char *cp;
104954Sbill 
1054879Ssam 	if (argc < 2)
106954Sbill 		usage();
1074879Ssam 	for (cp = argv[1]; *cp; cp++)
1084879Ssam 		switch (*cp) {
109954Sbill 
1104879Ssam 		case 'm':
1114879Ssam 		case 'v':
1124879Ssam 		case 'u':
1134879Ssam 		case 'w':
1144879Ssam 			flg[*cp-'a']++;
1154879Ssam 			continue;
1164879Ssam 		case 'c':
11713910Ssam 			flag(c)++;
1184879Ssam 			dirdirty++;
1194879Ssam 			continue;
120954Sbill 
1214879Ssam 		case 'r':
1224879Ssam 			setcom(rcmd);
1234879Ssam 			flag(r)++;
1244879Ssam 			continue;
125954Sbill 
1264879Ssam 		case 'd':
1274879Ssam 			setcom(dcmd);
1284879Ssam 			flag(d)++;
1294879Ssam 			continue;
130954Sbill 
1314879Ssam 		case 'x':
1324879Ssam 			setcom(xcmd);
1334879Ssam 			continue;
134954Sbill 
1354879Ssam 		case 't':
1364879Ssam 			setcom(tcmd);
1374879Ssam 			continue;
138954Sbill 
1394879Ssam 		case 'f':
1404879Ssam 			defdev = argv[2];
1414879Ssam 			argv++;
1424879Ssam 			argc--;
1434879Ssam 			continue;
1444879Ssam 
1454879Ssam 		default:
1464879Ssam 			fprintf(stderr, "arff: bad option `%c'\n", *cp);
1474879Ssam 			exit(1);
1484879Ssam 		}
1494879Ssam 
150954Sbill 	namv = argv+2;
151954Sbill 	namc = argc-2;
1524879Ssam 	if (comfun == 0) {
1534879Ssam 		if (flag(u) == 0) {
1544879Ssam 			fprintf(stderr, "arff: one of [%s] must be specified\n",
1554879Ssam 				man);
156954Sbill 			exit(1);
157954Sbill 		}
158954Sbill 		setcom(rcmd);
159954Sbill 	}
160954Sbill 	(*comfun)();
161954Sbill 	exit(notfound());
162954Sbill }
163954Sbill 
164954Sbill setcom(fun)
1654879Ssam 	int (*fun)();
166954Sbill {
1674879Ssam 	if (comfun != 0) {
168954Sbill 		fprintf(stderr, "arff: only one of [%s] allowed\n", man);
169954Sbill 		exit(1);
170954Sbill 	}
171954Sbill 	comfun = fun;
172954Sbill }
173954Sbill 
174954Sbill usage()
175954Sbill {
1763356Swnj 	fprintf(stderr, "usage: ar [%s][%s] archive files ...\n", opt, man);
177954Sbill 	exit(1);
178954Sbill }
179954Sbill 
180954Sbill notfound()
181954Sbill {
1824879Ssam 	register i, n = 0;
183954Sbill 
1844879Ssam 	for (i = 0; i < namc; i++)
1854879Ssam 		if (namv[i]) {
186954Sbill 			fprintf(stderr, "arff: %s not found\n", namv[i]);
187954Sbill 			n++;
188954Sbill 		}
1899877Ssam 	return (n);
190954Sbill }
191954Sbill 
192954Sbill mesg(c)
193954Sbill {
1944879Ssam 	if (flag(v))
1954879Ssam 		if (c != 'c' || flag(v) > 1)
196954Sbill 			printf("%c - %s\n", c, file);
197954Sbill }
198954Sbill 
199954Sbill tcmd()
200954Sbill {
2014879Ssam 	register char *de, *last;
202954Sbill 	FLDOPE *lookup(), *dope;
2034879Ssam 	int segnum, nleft;
2044879Ssam 	register i;
205954Sbill 	register struct rt_ent *rde;
206954Sbill 
207954Sbill 	rt_init();
2089877Ssam 	if (namc != 0) {
2094879Ssam 		for (i = 0; i < namc; i++)
2104879Ssam 			if (dope = lookup(namv[i])) {
211954Sbill 				rde = dope->rtdope;
212954Sbill 				rtls(rde);
213954Sbill 				namv[i] = 0;
214954Sbill 			}
2159877Ssam 		return;
2169877Ssam 	}
2179877Ssam 	for (segnum = 0; segnum != -1;
2189877Ssam 	  segnum = rt_dir[segnum].rt_axhead.rt_nxtseg - 1) {
2199877Ssam 		last = rt_last + segnum*2*RT_BLOCK;
2209877Ssam 		for (de = ((char *)&rt_dir[segnum])+10; de <= last;
2219877Ssam 		    de += rt_entsiz)
2229877Ssam 			if (rtls(rt(de))) {
2239877Ssam 				nleft = (last-de)/rt_entsiz;
2249877Ssam #define ENTRIES "\n%d entries remaining in directory segment %d.\n"
2259877Ssam 				printf(ENTRIES, nleft, segnum+1);
2269877Ssam 				break;
2279877Ssam 			}
2289877Ssam 	}
229954Sbill }
2304879Ssam 
231954Sbill rtls(de)
2324879Ssam 	register struct rt_ent *de;
233954Sbill {
2344879Ssam 	int month, day, year;
235954Sbill 	char name[12], ext[4];
236954Sbill 
2374879Ssam 	switch (de->rt_stat) {
2384879Ssam 
2394879Ssam 	case RT_TEMP:
2404879Ssam 		if (flag(v))
241954Sbill 			printf("Tempfile:\n");
2424879Ssam 		/* fall thru...*/
243954Sbill 
2444879Ssam 	case RT_FILE:
2454879Ssam 		if (!flag(v)) {
2464879Ssam 			sunrad50(name, de->rt_name);
2474879Ssam 			printf("%s\n", name);
248954Sbill 			break;
249954Sbill 		}
2504879Ssam 		unrad50(2, de->rt_name, name);
2514879Ssam 		unrad50(1, &(de->rt_name[2]), ext);
2524879Ssam 		day = de->rt_date.rt_dy;
2534879Ssam 		year = de->rt_date.rt_yr+72;
2544879Ssam 		month = de->rt_date.rt_mo;
2554879Ssam 		printf("%6.6s  %3.3s	%02d/%02d/%02d	%d\n",name,
2564879Ssam 			ext, month, day, year, de->rt_len);
2574879Ssam 		break;
258954Sbill 
2594879Ssam 	case RT_NULL:
2604879Ssam 		printf("%-25.9s	%d\n","<UNUSED>", de->rt_len);
2614879Ssam 		break;
262954Sbill 
2634879Ssam 	case RT_ESEG:
2649877Ssam 		return (1);
265954Sbill 	}
2669877Ssam 	return (0);
267954Sbill }
2684879Ssam 
269954Sbill xcmd()
270954Sbill {
2714879Ssam 	register char *de, *last;
2723346Swnj 	int segnum;
273954Sbill 	char name[12];
274954Sbill 	register int i;
275954Sbill 
276954Sbill 	rt_init();
2779877Ssam 	if (namc != 0) {
2784879Ssam 		for (i = 0; i < namc; i++)
2794879Ssam 			if (rtx(namv[i]) == 0)
2804879Ssam 				namv[i] = 0;
2819877Ssam 		return;
2829877Ssam 	}
2839877Ssam 	for (segnum = 0; segnum != -1;
2849877Ssam 	     segnum = rt_dir[segnum].rt_axhead.rt_nxtseg-1)
2859877Ssam 		for (last = rt_last+(segnum*2*RT_BLOCK),
2869877Ssam 		     de = ((char *)&rt_dir[segnum])+10; de <= last;
287*15553Sralph 		     de += rt_entsiz) {
2889877Ssam 			switch (rt(de)->rt_stat) {
2899877Ssam 
2909877Ssam 			case RT_ESEG:
291*15553Sralph 				break;	/* exit loop and try next segment */
2929877Ssam 
2939877Ssam 			case RT_TEMP:
2949877Ssam 			case RT_FILE:
2959877Ssam 				sunrad50(name,rt(de)->rt_name);
2969877Ssam 				rtx(name);
2979877Ssam 
2989877Ssam 			case RT_NULL:
299*15553Sralph 			default:
300*15553Sralph 				continue;
3019877Ssam 			}
302*15553Sralph 			break;
303*15553Sralph 		}
304954Sbill }
3054879Ssam 
306954Sbill rtx(name)
3074879Ssam 	char *name;
308954Sbill {
309954Sbill 	register FLDOPE *dope;
310954Sbill 	FLDOPE *lookup();
311954Sbill 	register startad, count;
3124879Ssam 	int file;
3134879Ssam 	char buff[512];
314954Sbill 
315954Sbill 
3164879Ssam 	if (dope = lookup(name)) {
3174879Ssam 		if (flag(v))
318954Sbill 			rtls(dope->rtdope);
319954Sbill 		else
320954Sbill 			printf("x - %s\n",name);
321954Sbill 
3224879Ssam 		if ((file = creat(name, 0666)) < 0)
3239877Ssam 			return (1);
324954Sbill 		count = dope->count;
325954Sbill 		startad = dope->startad;
326954Sbill 		for( ; count > 0 ; count -= 512) {
3274879Ssam 			lread(startad, 512, buff);
3284879Ssam 			write(file, buff, 512);
329954Sbill 			startad += 512;
330954Sbill 		}
331954Sbill 		close(file);
3329877Ssam 		return (0);
333954Sbill 	}
3349877Ssam 	return (1);
335954Sbill }
3364879Ssam 
337954Sbill rt_init()
338954Sbill {
339954Sbill 	static initized = 0;
3404879Ssam 	register char *de, *last;
3413346Swnj 	register i;
3423799Shickman 	int dirnum;
3433799Shickman 	char *mode;
3443799Shickman 	FILE *temp_floppydes;
345954Sbill 
3464879Ssam 	if (initized)
3474879Ssam 		return;
348954Sbill 	initized = 1;
34913910Ssam 	if (flag(c)) {
35013910Ssam 		struct stat sb;
35113910Ssam 		char response[128];
35213910Ssam 		int tty;
35313910Ssam 
35413910Ssam 		if (stat(defdev, &sb) >= 0 && (sb.st_mode & S_IFMT) == S_IFREG)
35513910Ssam 			goto ignore;
35613910Ssam 		tty = open("/dev/tty", O_RDWR);
35713910Ssam #define SURE	"Are you sure you want to clobber the floppy? "
35813910Ssam 		write(tty, SURE, sizeof (SURE));
35913910Ssam 		read(tty, response, sizeof (response));
36013910Ssam 		if (*response != 'y')
36113910Ssam 			exit(50);
36213910Ssam 		close(tty);
36313910Ssam ignore:
36413910Ssam 		;
36513910Ssam 	}
3664879Ssam 	if (flag(c) || flag(d) || flag(r))
3673799Shickman 		mode = "r+";
368954Sbill 	else
3693799Shickman 		mode = "r";
3704879Ssam 	if ((temp_floppydes = fopen(defdev, mode)) == NULL) {
3713799Shickman 		perror(defdev);
3723356Swnj 		exit(1);
3733799Shickman 	} else
3743799Shickman 		floppydes = fileno(temp_floppydes);
3754879Ssam 	if (!flag(c)) {
3764879Ssam 		lread(6*RT_BLOCK, 2*RT_BLOCK, (char *)&rt_dir[0]);
3773346Swnj 		dirnum = rt_dir[0].rt_axhead.rt_numseg;
37812012Shelge 		/* check for blank/uninitialized diskette */
37912012Shelge 		if (dirnum <= 0) {
38012012Shelge 			fprintf(stderr,"arff: bad directory format\n");
38112012Shelge 			exit(1);
38212012Shelge 		}
3833346Swnj 		if (dirnum > RT_DIRSIZE) {
3844879Ssam 			fprintf(stderr,"arff: too many directory segments\n");
3854879Ssam 			exit(1);
3863346Swnj 		}
3874879Ssam 		for (i = 1; i < dirnum; i++)
3884879Ssam 			lread((6+2*i)*RT_BLOCK, 2*RT_BLOCK, (char *)&rt_dir[i]);
3893489Sroot 	} else
3903489Sroot 		dirnum = 1;
391954Sbill 
3923346Swnj 	rt_entsiz = 2*rt_dir[0].rt_axhead.rt_entpad + 14;
3933346Swnj 	rt_entsiz = 14;			/* assume rt_entpad = 0 ??? */
3943346Swnj 	rt_last = ((char *) &rt_dir[0]) + 10 + 1014/rt_entsiz*rt_entsiz;
3953346Swnj 	rt_nleft = 0;
3963346Swnj 
3974879Ssam 	for (i = 0; i < dirnum; i++) {
3984879Ssam 		last = rt_last + i*2*RT_BLOCK;
3994879Ssam 		for (de = ((char *)&rt_dir[i])+10; de <= last; de += rt_entsiz)
4004879Ssam 			if (rt(de)->rt_stat == RT_ESEG)
4014879Ssam 				break;
4024879Ssam 		rt_curend[i] = rt(de);
4034879Ssam 		rt_nleft += (last-de)/rt_entsiz;
404954Sbill 	}
405954Sbill }
406954Sbill 
407954Sbill static FLDOPE result;
4084879Ssam 
409954Sbill FLDOPE *
410954Sbill lookup(name)
4114879Ssam 	char *name;
412954Sbill {
413954Sbill 	unsigned short rname[3];
4144879Ssam 	register char *de, *last;
4153346Swnj 	int segnum;
416954Sbill 	register index;
417954Sbill 
418954Sbill 	srad50(name,rname);
419954Sbill 
4203356Swnj 	/*
421954Sbill 	 *  Search for name, accumulate blocks in index
422954Sbill 	 */
423954Sbill 	rt_init();
4244879Ssam 	for (segnum = 0; segnum != -1;
4254879Ssam 	     segnum = rt_dir[segnum].rt_axhead.rt_nxtseg - 1)
4264879Ssam 	{
4274879Ssam 		index = 0;
4284879Ssam 		last = rt_last + segnum*2*RT_BLOCK;
4294879Ssam 		for (de=((char *)&rt_dir[segnum])+10;
4304879Ssam 		     rt(de)->rt_stat != RT_ESEG; de += rt_entsiz)
4314879Ssam 			switch(rt(de)->rt_stat) {
4324879Ssam 
4334879Ssam 			case RT_FILE:
4344879Ssam 			case RT_TEMP:
4354879Ssam 				if(samename(rname,rt(de)->rt_name)) {
4364879Ssam 					result.count = rt(de)->rt_len * 512;
4374879Ssam 					result.startad = 512*
4384879Ssam 						(rt_dir[segnum].rt_axhead.rt_stfile + index);
4394879Ssam 					result.rtdope = (struct rt_ent *) de;
4409877Ssam 					return (&result);
4414879Ssam 				}
4424879Ssam 
4434879Ssam 			case RT_NULL:
4444879Ssam 				index += rt(de)->rt_len;
4454879Ssam 			}
4463346Swnj         }
4479877Ssam 	return ((FLDOPE *) 0);
4484879Ssam 
449954Sbill }
4504879Ssam 
451954Sbill static
4524879Ssam samename(a, b)
4534879Ssam 	u_short a[], b[];
454954Sbill {
4559877Ssam 	return (*a == *b && a[1] == b[1] && a[2] == b[2] );
456954Sbill }
457954Sbill 
4584879Ssam rad50(cp, out)
4594879Ssam 	register u_char *cp;
4604879Ssam 	u_short *out;
461954Sbill {
4624879Ssam 	register index, temp;
463954Sbill 
4644879Ssam 	for (index = 0; *cp; index++) {
465954Sbill 		temp = Ain1 * table[*cp++];
4664879Ssam 		if (*cp!=0) {
467954Sbill 			temp += Ain2 * table[*cp++];
468954Sbill 			if(*cp!=0)
469954Sbill 				temp += table[*cp++];
470954Sbill 		}
471954Sbill 		out[index] = temp;
472954Sbill 	}
473954Sbill }
474954Sbill 
4754879Ssam #define reduce(x, p, q) (x = v[p/q], p %= q);
4764879Ssam 
4774879Ssam unrad50(count, in, cp)
4784879Ssam 	u_short *in;
4794879Ssam 	register char *cp;
480954Sbill {
4814879Ssam 	register i, temp;
4824879Ssam 	register u_char *v = (u_char *) val;
483954Sbill 
4844879Ssam 	for (i = 0; i < count; i++) {
485954Sbill 		temp = in[i];
4864879Ssam 		reduce(*cp++, temp, Ain1);
4874879Ssam 		reduce(*cp++, temp, Ain2);
4884879Ssam 		reduce(*cp++, temp, 1);
489954Sbill 	}
490954Sbill 	*cp=0;
491954Sbill }
492954Sbill 
4934879Ssam srad50(name, rname)
4944879Ssam 	register char *name;
4954879Ssam 	register u_short *rname;
496954Sbill {
4974879Ssam 	register index;
4984879Ssam 	register char *cp;
4994879Ssam 	char file[7], ext[4];
5004879Ssam 
5013356Swnj 	/*
502954Sbill 	 * Find end of pathname
503954Sbill 	 */
5044879Ssam 	for (cp = name; *cp++; )
5054879Ssam 		;
5064879Ssam 	while (cp >= name && *--cp != '/')
5074879Ssam 		;
508954Sbill 	cp++;
5093356Swnj 	/*
510954Sbill 	 * Change to rad50
511954Sbill 	 */
5124879Ssam 	for (index = 0; *cp; ) {
513954Sbill 		file[index++] = *cp++;
5144879Ssam 		if (*cp == '.') {
515954Sbill 			cp++;
516954Sbill 			break;
517954Sbill 		}
5184879Ssam 		if (index >= 6) {
519954Sbill 			break;
520954Sbill 		}
521954Sbill 	}
522954Sbill 	file[index] = 0;
5234879Ssam 	for (index = 0; *cp; ) {
524954Sbill 		ext[index++] = *cp++;
5254879Ssam 		if (*cp == '.' || index >= 3)
526954Sbill 			break;
527954Sbill 	}
528954Sbill 	ext[index]=0;
5294879Ssam 	rname[0] = rname[1] = rname[2] = 0;
5304879Ssam 	rad50((u_char *)file, rname);
5314879Ssam 	rad50((u_char *)ext, rname+2);
532954Sbill }
5334879Ssam 
5344879Ssam sunrad50(name, rname)
5354879Ssam 	u_short rname[];
5364879Ssam 	register char *name;
537954Sbill {
538954Sbill 	register char *cp, *cp2;
539954Sbill 	char ext[4];
540954Sbill 
5414879Ssam 	unrad50(2, rname, name);
5424879Ssam 	unrad50(1, rname + 2, ext);
5434879Ssam 	/*
5444879Ssam 	 * Jam name and extension together with a dot
5454879Ssam 	 * deleting white space
5464879Ssam 	 */
5474879Ssam 	for (cp = name; *cp++;)
5484879Ssam 		;
5494879Ssam 	--cp;
5504879Ssam 	while (*--cp == ' ' && cp >= name)
5514879Ssam 		;
5524879Ssam 	*++cp = '.';
5534879Ssam 	cp++;
5544879Ssam 	for (cp2 = ext; *cp2 != ' ' && cp2 < ext+3;)
555954Sbill 		*cp++ = *cp2++;
556954Sbill 	*cp=0;
5574879Ssam 	if (cp[-1] == '.')
5584879Ssam 		cp[-1] = 0;
559954Sbill }
560954Sbill 
561954Sbill static char *oval = " ABCDEFGHIJKLMNOPQRSTUVWXYZ$.@0123456789";
562954Sbill static char *val = " abcdefghijklmnopqrstuvwxyz$.@0123456789";
5634879Ssam 
564954Sbill static char table[256] = {
565954Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
566954Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
567954Sbill 0, 29, 29, 29, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 29,
568954Sbill 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 29, 29, 29, 29, 29, 29,
569954Sbill 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
570954Sbill 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
571954Sbill 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
572954Sbill 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
573954Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
574954Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
575954Sbill 0, 29, 29, 29, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 29,
576954Sbill 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 29, 29, 29, 29, 29, 29,
577954Sbill 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
578954Sbill 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
579954Sbill 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
580954Sbill 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29 };
581954Sbill 
5824879Ssam /*
5834879Ssam  * Logical to physical adress translation
5844879Ssam  */
5854879Ssam long
5864879Ssam trans(logical)
5874879Ssam 	register int logical;
588954Sbill {
589954Sbill 	register int sector, bytes, track;
590954Sbill 
5914879Ssam 	logical += 26*128;
5924879Ssam 	bytes = (logical&127);
593954Sbill 	logical >>= 7;
5944879Ssam 	sector = logical%26;
595954Sbill 	if(sector >= 13)
5964879Ssam 		sector = sector*2+1;
597954Sbill 	else
598954Sbill 		sector *= 2;
5994879Ssam 	sector += 26 + ((track = (logical/26))-1)*6;
600954Sbill 	sector %= 26;
6019877Ssam 	return ((((track*26)+sector) << 7) + bytes);
602954Sbill }
6034879Ssam 
6044879Ssam lread(startad, count, obuff)
6054879Ssam 	register startad, count;
6064879Ssam 	register char *obuff;
607954Sbill {
608954Sbill 	long trans();
609954Sbill 	extern floppydes;
6104879Ssam 	register int size = flag(m) ? 512 : 128;
6114879Ssam 
612954Sbill 	rt_init();
6134879Ssam 	while ((count -= size) >= 0) {
6144879Ssam 		lseek(floppydes, flag(m) ?
6154879Ssam 			(long)startad : trans(startad), 0);
6164879Ssam 		if (read(floppydes, obuff, size) != size)
6174879Ssam 			fprintf(stderr, "arff: read error block %d\n",
6184879Ssam 				startad/size);
6194879Ssam 		obuff += size;
6204879Ssam 		startad += size;
6214879Ssam 	}
622954Sbill }
6234879Ssam 
6244879Ssam lwrite(startad, count, obuff)
6254879Ssam 	register startad, count;
6264879Ssam 	register char *obuff;
627954Sbill {
628954Sbill 	long trans();
629954Sbill 	extern floppydes;
6304879Ssam 	register int size = flag(m) ? 512 : 128;
6314879Ssam 
632954Sbill 	rt_init();
6334879Ssam 	while ((count -= size) >= 0) {
6344879Ssam 		lseek(floppydes, flag(m) ?
6354879Ssam 			(long)startad : trans(startad), 0);
6364879Ssam 		if (write(floppydes, obuff, size) != size)
6374879Ssam 			fprintf(stderr, "arff: write error block %d\n",
6384879Ssam 				startad/size);
6394879Ssam 		obuff += size;
6404879Ssam 		startad += size;
6414879Ssam 	}
642954Sbill }
643954Sbill 
644954Sbill rcmd()
645954Sbill {
646954Sbill 	register int i;
647954Sbill 
648954Sbill 	rt_init();
6494879Ssam 	if (namc > 0)
6504879Ssam 		for (i = 0; i < namc; i++)
6514879Ssam 			if (rtr(namv[i]) == 0)
6524879Ssam 				namv[i] = 0;
653954Sbill }
654954Sbill 
655954Sbill rtr(name)
6564879Ssam 	char *name;
657954Sbill {
6584879Ssam 	register FLDOPE *dope;
6594879Ssam 	register struct rt_ent *de;
6604879Ssam 	struct stat buf;
6614879Ssam 	register struct stat *bufp = &buf;
6623346Swnj 	int segnum;
6633346Swnj 	register char *last;
664954Sbill 
6654879Ssam 	if (stat(name, bufp) < 0) {
6663489Sroot 		perror(name);
6679877Ssam 		return (-1);
6683489Sroot 	}
6694879Ssam 	if (dope = lookup(name)) {
670954Sbill 		/* can replace, no problem */
671954Sbill 		de = dope->rtdope;
6724879Ssam 		if (bufp->st_size <= (de->rt_len * 512))
673954Sbill 			printf("r - %s\n",name),
6744879Ssam 			toflop(name, bufp->st_size, dope);
675954Sbill 		else {
6769877Ssam 			fprintf(stderr,
6779877Ssam 			  "%s will not fit in currently used file on floppy\n",
6789877Ssam 			  name);
6799877Ssam 			return (-1);
680954Sbill 		}
6819877Ssam 		goto found;
6829877Ssam 	}
6839877Ssam 	/*
6849877Ssam 	 * Search for vacant spot
6859877Ssam 	 */
6869877Ssam 	for (segnum = 0; segnum != -1;
6879877Ssam 	     segnum = rt_dir[segnum].rt_axhead.rt_nxtseg - 1)
6889877Ssam 	{
6899877Ssam 		last = rt_last + segnum*2*RT_BLOCK;
6909877Ssam 		for (de = rt_dir[segnum].rt_ents;
6919877Ssam 		    rt(de)->rt_stat != RT_ESEG; de++)
6929877Ssam 			if ((de)->rt_stat == RT_NULL) {
6939877Ssam 				if (bufp->st_size <= (de->rt_len*512)) {
6949877Ssam 					printf("a - %s\n",name),
6959877Ssam 					mkent(de, segnum, bufp,name);
6969877Ssam 					goto found;
697954Sbill 				}
6989877Ssam 				continue;
6999877Ssam 			}
700954Sbill 	}
7019877Ssam 	printf("%s: no slot for file\n", name);
7029877Ssam 	return (-1);
7034879Ssam 
7044879Ssam found:
7054879Ssam 	if (dope = lookup(name)) {
7064879Ssam 		toflop(name, bufp->st_size, dope);
7073489Sroot 		return (0);
708954Sbill 	}
7093489Sroot 	printf("%s: internal error, added then not found\n", name);
7103489Sroot 	return (-1);
7114879Ssam }
712954Sbill 
7134879Ssam mkent(de, segnum, bufp, name)
7144879Ssam 	register struct rt_ent *de;
7154879Ssam 	int segnum;
7164879Ssam 	register struct stat *bufp;
7174879Ssam 	char *name;
718954Sbill {
7194879Ssam 	struct tm *localtime();
7204879Ssam 	register struct tm *timp;
7214879Ssam 	register struct rt_ent *workp;
7224879Ssam 	int count;
723954Sbill 
724954Sbill 	count = (((bufp->st_size -1) >>9) + 1);
7254879Ssam 	/* make sure there is room */
7264879Ssam 	if (de->rt_len == count)
727954Sbill 		goto overwrite;
7284879Ssam 	if ((char *)rt_curend[segnum] == (rt_last + (segnum*2*RT_BLOCK))) {
7294879Ssam 		/* no entries left on segment */
7304879Ssam 		if (flag(o))
731954Sbill 			goto overwrite;
7329877Ssam 		fprintf(stderr, "Directory segment #%d full on  %s\n",
7339877Ssam 			segnum+1, defdev);
734954Sbill 		exit(1);
735954Sbill 	}
7364879Ssam 	/* copy directory entries up */
7374879Ssam 	for (workp = rt_curend[segnum]+1; workp > de; workp--)
738954Sbill 		*workp = workp[-1];
739954Sbill 	de[1].rt_len -= count;
740954Sbill 	de->rt_len = count;
7413346Swnj 	rt_curend[segnum]++;
742954Sbill 	rt_nleft--;
7434879Ssam 
744954Sbill overwrite:
745954Sbill 	srad50(name,de->rt_name);
746954Sbill 	timp = localtime(&bufp->st_mtime);
7477320Swnj 	de->rt_date.rt_dy = timp->tm_mday;
748954Sbill 	de->rt_date.rt_mo = timp->tm_mon + 1;
749954Sbill 	de->rt_date.rt_yr = timp->tm_year - 72;
750954Sbill 	de->rt_stat = RT_FILE;
751954Sbill 	de->rt_pad = 0;
752954Sbill 	de->rt_chan = 0;
753954Sbill 	de->rt_job = 0;
7544879Ssam 	lwrite((6+segnum*2)*RT_BLOCK, 2*RT_BLOCK, (char *)&rt_dir[segnum]);
755954Sbill }
756954Sbill 
7574879Ssam toflop(name, ocount, dope)
7584879Ssam 	char *name;
7594879Ssam 	register FLDOPE *dope;
7604879Ssam 	long ocount;
761954Sbill {
762954Sbill 	register file, n, startad = dope->startad, count = ocount;
763954Sbill 	char buff[512];
764954Sbill 
7654879Ssam 	file = open(name, 0);
7664879Ssam 	if (file < 0) {
7674879Ssam 		fprintf(stderr, "arff: couldn't open %s\n",name);
7684879Ssam 		exit(1);
7694879Ssam 	}
770954Sbill 	for( ; count >= 512; count -= 512) {
7714879Ssam 		read(file, buff, 512);
7724879Ssam 		lwrite(startad, 512, buff);
773954Sbill 		startad += 512;
774954Sbill 	}
7754879Ssam 	read(file, buff, count);
776954Sbill 	close(file);
7774879Ssam 	if (count <= 0)
7784879Ssam 		return;
7794879Ssam 	for (n = count; n < 512; n ++)
7804879Ssam 		buff[n] = 0;
7814879Ssam 	lwrite(startad, 512, buff);
7824879Ssam 	count = (dope->rtdope->rt_len*512-ocount)/512 ;
7834879Ssam 	if (count <= 0)
7844879Ssam 		return;
7854879Ssam 	for ( ; count > 0 ; count--) {
786954Sbill 		startad += 512;
7874879Ssam 		lwrite(startad, 512, zeroes);
788954Sbill 	}
7894879Ssam }
790954Sbill 
791954Sbill dcmd()
792954Sbill {
793954Sbill 	register int i;
794954Sbill 
795954Sbill 	rt_init();
7964879Ssam 	if (namc)
7974879Ssam 		for (i = 0; i < namc; i++)
7984879Ssam 			if (rtk(namv[i])==0)
7994879Ssam 				namv[i]=0;
8004879Ssam 	if (dirdirty)
801954Sbill 		scrunch();
802954Sbill }
8034879Ssam 
804954Sbill rtk(name)
8054879Ssam 	char *name;
806954Sbill {
807954Sbill 	register FLDOPE *dope;
808954Sbill 	register struct rt_ent *de;
809954Sbill 	FLDOPE *lookup();
810954Sbill 
8114879Ssam 	if (dope = lookup(name)) {
812954Sbill 		printf("d - %s\n",name);
813954Sbill 		de = dope->rtdope;
814954Sbill 		de->rt_stat = RT_NULL;
815954Sbill 		de->rt_name[0] = 0;
816954Sbill 		de->rt_name[1] = 0;
817954Sbill 		de->rt_name[2] = 0;
8189877Ssam 		*((u_short *)&(de->rt_date)) = 0;
819954Sbill 		dirdirty = 1;
8209877Ssam 		return (0);
821954Sbill 	}
8229877Ssam 	return (1);
823954Sbill }
8244879Ssam 
8254879Ssam scrunch()
8264879Ssam {
8273346Swnj 	register struct rt_ent *de , *workp;
8283346Swnj 	register segnum;
8294879Ssam 
8304879Ssam 	for (segnum = 0; segnum != -1;
8313346Swnj 	     segnum = rt_dir[segnum].rt_axhead.rt_nxtseg - 1) {
8324879Ssam 		for (de = rt_dir[segnum].rt_ents; de <= rt_curend[segnum]; de++)
8339877Ssam 			if (de->rt_stat == RT_NULL &&
83412012Shelge 			    (de+1)->rt_stat == RT_NULL) {
8354879Ssam 				(de+1)->rt_len += de->rt_len;
83612012Shelge 				for (workp=de; workp<rt_curend[segnum]; workp++)
8374879Ssam 					*workp = workp[1];
8384879Ssam 				de--;
8394879Ssam 				rt_curend[segnum]--;
8404879Ssam 				rt_nleft++;
8414879Ssam 			}
84212012Shelge 		lwrite((6+segnum*2)*RT_BLOCK, 2*RT_BLOCK,
84312012Shelge 			(char *)&rt_dir[segnum]);
844954Sbill 	}
84512012Shelge 	dirdirty = 0;
846954Sbill }
847