xref: /csrg-svn/old/arff/arff.c (revision 13910)
19877Ssam #ifndef lint
2*13910Ssam static	char sccsid[] = "@(#)arff.c	4.16 (Berkeley) 83/07/10";
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>
10*13910Ssam #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':
117*13910Ssam 			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;
2879877Ssam 		     de += rt_entsiz)
2889877Ssam 			switch (rt(de)->rt_stat) {
2899877Ssam 
2909877Ssam 			case RT_ESEG:
2919877Ssam 				return;
2929877Ssam 
2939877Ssam 			case RT_TEMP:
2949877Ssam 			case RT_FILE:
2959877Ssam 				sunrad50(name,rt(de)->rt_name);
2969877Ssam 				rtx(name);
2979877Ssam 
2989877Ssam 			case RT_NULL:
2999877Ssam 				break;
3009877Ssam 			}
301954Sbill }
3024879Ssam 
303954Sbill rtx(name)
3044879Ssam 	char *name;
305954Sbill {
306954Sbill 	register FLDOPE *dope;
307954Sbill 	FLDOPE *lookup();
308954Sbill 	register startad, count;
3094879Ssam 	int file;
3104879Ssam 	char buff[512];
311954Sbill 
312954Sbill 
3134879Ssam 	if (dope = lookup(name)) {
3144879Ssam 		if (flag(v))
315954Sbill 			rtls(dope->rtdope);
316954Sbill 		else
317954Sbill 			printf("x - %s\n",name);
318954Sbill 
3194879Ssam 		if ((file = creat(name, 0666)) < 0)
3209877Ssam 			return (1);
321954Sbill 		count = dope->count;
322954Sbill 		startad = dope->startad;
323954Sbill 		for( ; count > 0 ; count -= 512) {
3244879Ssam 			lread(startad, 512, buff);
3254879Ssam 			write(file, buff, 512);
326954Sbill 			startad += 512;
327954Sbill 		}
328954Sbill 		close(file);
3299877Ssam 		return (0);
330954Sbill 	}
3319877Ssam 	return (1);
332954Sbill }
3334879Ssam 
334954Sbill rt_init()
335954Sbill {
336954Sbill 	static initized = 0;
3374879Ssam 	register char *de, *last;
3383346Swnj 	register i;
3393799Shickman 	int dirnum;
3403799Shickman 	char *mode;
3413799Shickman 	FILE *temp_floppydes;
342954Sbill 
3434879Ssam 	if (initized)
3444879Ssam 		return;
345954Sbill 	initized = 1;
346*13910Ssam 	if (flag(c)) {
347*13910Ssam 		struct stat sb;
348*13910Ssam 		char response[128];
349*13910Ssam 		int tty;
350*13910Ssam 
351*13910Ssam 		if (stat(defdev, &sb) >= 0 && (sb.st_mode & S_IFMT) == S_IFREG)
352*13910Ssam 			goto ignore;
353*13910Ssam 		tty = open("/dev/tty", O_RDWR);
354*13910Ssam #define SURE	"Are you sure you want to clobber the floppy? "
355*13910Ssam 		write(tty, SURE, sizeof (SURE));
356*13910Ssam 		read(tty, response, sizeof (response));
357*13910Ssam 		if (*response != 'y')
358*13910Ssam 			exit(50);
359*13910Ssam 		close(tty);
360*13910Ssam ignore:
361*13910Ssam 		;
362*13910Ssam 	}
3634879Ssam 	if (flag(c) || flag(d) || flag(r))
3643799Shickman 		mode = "r+";
365954Sbill 	else
3663799Shickman 		mode = "r";
3674879Ssam 	if ((temp_floppydes = fopen(defdev, mode)) == NULL) {
3683799Shickman 		perror(defdev);
3693356Swnj 		exit(1);
3703799Shickman 	} else
3713799Shickman 		floppydes = fileno(temp_floppydes);
3724879Ssam 	if (!flag(c)) {
3734879Ssam 		lread(6*RT_BLOCK, 2*RT_BLOCK, (char *)&rt_dir[0]);
3743346Swnj 		dirnum = rt_dir[0].rt_axhead.rt_numseg;
37512012Shelge 		/* check for blank/uninitialized diskette */
37612012Shelge 		if (dirnum <= 0) {
37712012Shelge 			fprintf(stderr,"arff: bad directory format\n");
37812012Shelge 			exit(1);
37912012Shelge 		}
3803346Swnj 		if (dirnum > RT_DIRSIZE) {
3814879Ssam 			fprintf(stderr,"arff: too many directory segments\n");
3824879Ssam 			exit(1);
3833346Swnj 		}
3844879Ssam 		for (i = 1; i < dirnum; i++)
3854879Ssam 			lread((6+2*i)*RT_BLOCK, 2*RT_BLOCK, (char *)&rt_dir[i]);
3863489Sroot 	} else
3873489Sroot 		dirnum = 1;
388954Sbill 
3893346Swnj 	rt_entsiz = 2*rt_dir[0].rt_axhead.rt_entpad + 14;
3903346Swnj 	rt_entsiz = 14;			/* assume rt_entpad = 0 ??? */
3913346Swnj 	rt_last = ((char *) &rt_dir[0]) + 10 + 1014/rt_entsiz*rt_entsiz;
3923346Swnj 	rt_nleft = 0;
3933346Swnj 
3944879Ssam 	for (i = 0; i < dirnum; i++) {
3954879Ssam 		last = rt_last + i*2*RT_BLOCK;
3964879Ssam 		for (de = ((char *)&rt_dir[i])+10; de <= last; de += rt_entsiz)
3974879Ssam 			if (rt(de)->rt_stat == RT_ESEG)
3984879Ssam 				break;
3994879Ssam 		rt_curend[i] = rt(de);
4004879Ssam 		rt_nleft += (last-de)/rt_entsiz;
401954Sbill 	}
402954Sbill }
403954Sbill 
404954Sbill static FLDOPE result;
4054879Ssam 
406954Sbill FLDOPE *
407954Sbill lookup(name)
4084879Ssam 	char *name;
409954Sbill {
410954Sbill 	unsigned short rname[3];
4114879Ssam 	register char *de, *last;
4123346Swnj 	int segnum;
413954Sbill 	register index;
414954Sbill 
415954Sbill 	srad50(name,rname);
416954Sbill 
4173356Swnj 	/*
418954Sbill 	 *  Search for name, accumulate blocks in index
419954Sbill 	 */
420954Sbill 	rt_init();
4214879Ssam 	for (segnum = 0; segnum != -1;
4224879Ssam 	     segnum = rt_dir[segnum].rt_axhead.rt_nxtseg - 1)
4234879Ssam 	{
4244879Ssam 		index = 0;
4254879Ssam 		last = rt_last + segnum*2*RT_BLOCK;
4264879Ssam 		for (de=((char *)&rt_dir[segnum])+10;
4274879Ssam 		     rt(de)->rt_stat != RT_ESEG; de += rt_entsiz)
4284879Ssam 			switch(rt(de)->rt_stat) {
4294879Ssam 
4304879Ssam 			case RT_FILE:
4314879Ssam 			case RT_TEMP:
4324879Ssam 				if(samename(rname,rt(de)->rt_name)) {
4334879Ssam 					result.count = rt(de)->rt_len * 512;
4344879Ssam 					result.startad = 512*
4354879Ssam 						(rt_dir[segnum].rt_axhead.rt_stfile + index);
4364879Ssam 					result.rtdope = (struct rt_ent *) de;
4379877Ssam 					return (&result);
4384879Ssam 				}
4394879Ssam 
4404879Ssam 			case RT_NULL:
4414879Ssam 				index += rt(de)->rt_len;
4424879Ssam 			}
4433346Swnj         }
4449877Ssam 	return ((FLDOPE *) 0);
4454879Ssam 
446954Sbill }
4474879Ssam 
448954Sbill static
4494879Ssam samename(a, b)
4504879Ssam 	u_short a[], b[];
451954Sbill {
4529877Ssam 	return (*a == *b && a[1] == b[1] && a[2] == b[2] );
453954Sbill }
454954Sbill 
4554879Ssam rad50(cp, out)
4564879Ssam 	register u_char *cp;
4574879Ssam 	u_short *out;
458954Sbill {
4594879Ssam 	register index, temp;
460954Sbill 
4614879Ssam 	for (index = 0; *cp; index++) {
462954Sbill 		temp = Ain1 * table[*cp++];
4634879Ssam 		if (*cp!=0) {
464954Sbill 			temp += Ain2 * table[*cp++];
465954Sbill 			if(*cp!=0)
466954Sbill 				temp += table[*cp++];
467954Sbill 		}
468954Sbill 		out[index] = temp;
469954Sbill 	}
470954Sbill }
471954Sbill 
4724879Ssam #define reduce(x, p, q) (x = v[p/q], p %= q);
4734879Ssam 
4744879Ssam unrad50(count, in, cp)
4754879Ssam 	u_short *in;
4764879Ssam 	register char *cp;
477954Sbill {
4784879Ssam 	register i, temp;
4794879Ssam 	register u_char *v = (u_char *) val;
480954Sbill 
4814879Ssam 	for (i = 0; i < count; i++) {
482954Sbill 		temp = in[i];
4834879Ssam 		reduce(*cp++, temp, Ain1);
4844879Ssam 		reduce(*cp++, temp, Ain2);
4854879Ssam 		reduce(*cp++, temp, 1);
486954Sbill 	}
487954Sbill 	*cp=0;
488954Sbill }
489954Sbill 
4904879Ssam srad50(name, rname)
4914879Ssam 	register char *name;
4924879Ssam 	register u_short *rname;
493954Sbill {
4944879Ssam 	register index;
4954879Ssam 	register char *cp;
4964879Ssam 	char file[7], ext[4];
4974879Ssam 
4983356Swnj 	/*
499954Sbill 	 * Find end of pathname
500954Sbill 	 */
5014879Ssam 	for (cp = name; *cp++; )
5024879Ssam 		;
5034879Ssam 	while (cp >= name && *--cp != '/')
5044879Ssam 		;
505954Sbill 	cp++;
5063356Swnj 	/*
507954Sbill 	 * Change to rad50
508954Sbill 	 */
5094879Ssam 	for (index = 0; *cp; ) {
510954Sbill 		file[index++] = *cp++;
5114879Ssam 		if (*cp == '.') {
512954Sbill 			cp++;
513954Sbill 			break;
514954Sbill 		}
5154879Ssam 		if (index >= 6) {
516954Sbill 			break;
517954Sbill 		}
518954Sbill 	}
519954Sbill 	file[index] = 0;
5204879Ssam 	for (index = 0; *cp; ) {
521954Sbill 		ext[index++] = *cp++;
5224879Ssam 		if (*cp == '.' || index >= 3)
523954Sbill 			break;
524954Sbill 	}
525954Sbill 	ext[index]=0;
5264879Ssam 	rname[0] = rname[1] = rname[2] = 0;
5274879Ssam 	rad50((u_char *)file, rname);
5284879Ssam 	rad50((u_char *)ext, rname+2);
529954Sbill }
5304879Ssam 
5314879Ssam sunrad50(name, rname)
5324879Ssam 	u_short rname[];
5334879Ssam 	register char *name;
534954Sbill {
535954Sbill 	register char *cp, *cp2;
536954Sbill 	char ext[4];
537954Sbill 
5384879Ssam 	unrad50(2, rname, name);
5394879Ssam 	unrad50(1, rname + 2, ext);
5404879Ssam 	/*
5414879Ssam 	 * Jam name and extension together with a dot
5424879Ssam 	 * deleting white space
5434879Ssam 	 */
5444879Ssam 	for (cp = name; *cp++;)
5454879Ssam 		;
5464879Ssam 	--cp;
5474879Ssam 	while (*--cp == ' ' && cp >= name)
5484879Ssam 		;
5494879Ssam 	*++cp = '.';
5504879Ssam 	cp++;
5514879Ssam 	for (cp2 = ext; *cp2 != ' ' && cp2 < ext+3;)
552954Sbill 		*cp++ = *cp2++;
553954Sbill 	*cp=0;
5544879Ssam 	if (cp[-1] == '.')
5554879Ssam 		cp[-1] = 0;
556954Sbill }
557954Sbill 
558954Sbill static char *oval = " ABCDEFGHIJKLMNOPQRSTUVWXYZ$.@0123456789";
559954Sbill static char *val = " abcdefghijklmnopqrstuvwxyz$.@0123456789";
5604879Ssam 
561954Sbill static char table[256] = {
562954Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
563954Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
564954Sbill 0, 29, 29, 29, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 29,
565954Sbill 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 29, 29, 29, 29, 29, 29,
566954Sbill 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
567954Sbill 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 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, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
571954Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
572954Sbill 0, 29, 29, 29, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 29,
573954Sbill 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 29, 29, 29, 29, 29, 29,
574954Sbill 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
575954Sbill 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
576954Sbill 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
577954Sbill 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29 };
578954Sbill 
5794879Ssam /*
5804879Ssam  * Logical to physical adress translation
5814879Ssam  */
5824879Ssam long
5834879Ssam trans(logical)
5844879Ssam 	register int logical;
585954Sbill {
586954Sbill 	register int sector, bytes, track;
587954Sbill 
5884879Ssam 	logical += 26*128;
5894879Ssam 	bytes = (logical&127);
590954Sbill 	logical >>= 7;
5914879Ssam 	sector = logical%26;
592954Sbill 	if(sector >= 13)
5934879Ssam 		sector = sector*2+1;
594954Sbill 	else
595954Sbill 		sector *= 2;
5964879Ssam 	sector += 26 + ((track = (logical/26))-1)*6;
597954Sbill 	sector %= 26;
5989877Ssam 	return ((((track*26)+sector) << 7) + bytes);
599954Sbill }
6004879Ssam 
6014879Ssam lread(startad, count, obuff)
6024879Ssam 	register startad, count;
6034879Ssam 	register char *obuff;
604954Sbill {
605954Sbill 	long trans();
606954Sbill 	extern floppydes;
6074879Ssam 	register int size = flag(m) ? 512 : 128;
6084879Ssam 
609954Sbill 	rt_init();
6104879Ssam 	while ((count -= size) >= 0) {
6114879Ssam 		lseek(floppydes, flag(m) ?
6124879Ssam 			(long)startad : trans(startad), 0);
6134879Ssam 		if (read(floppydes, obuff, size) != size)
6144879Ssam 			fprintf(stderr, "arff: read error block %d\n",
6154879Ssam 				startad/size);
6164879Ssam 		obuff += size;
6174879Ssam 		startad += size;
6184879Ssam 	}
619954Sbill }
6204879Ssam 
6214879Ssam lwrite(startad, count, obuff)
6224879Ssam 	register startad, count;
6234879Ssam 	register char *obuff;
624954Sbill {
625954Sbill 	long trans();
626954Sbill 	extern floppydes;
6274879Ssam 	register int size = flag(m) ? 512 : 128;
6284879Ssam 
629954Sbill 	rt_init();
6304879Ssam 	while ((count -= size) >= 0) {
6314879Ssam 		lseek(floppydes, flag(m) ?
6324879Ssam 			(long)startad : trans(startad), 0);
6334879Ssam 		if (write(floppydes, obuff, size) != size)
6344879Ssam 			fprintf(stderr, "arff: write error block %d\n",
6354879Ssam 				startad/size);
6364879Ssam 		obuff += size;
6374879Ssam 		startad += size;
6384879Ssam 	}
639954Sbill }
640954Sbill 
641954Sbill rcmd()
642954Sbill {
643954Sbill 	register int i;
644954Sbill 
645954Sbill 	rt_init();
6464879Ssam 	if (namc > 0)
6474879Ssam 		for (i = 0; i < namc; i++)
6484879Ssam 			if (rtr(namv[i]) == 0)
6494879Ssam 				namv[i] = 0;
650954Sbill }
651954Sbill 
652954Sbill rtr(name)
6534879Ssam 	char *name;
654954Sbill {
6554879Ssam 	register FLDOPE *dope;
6564879Ssam 	register struct rt_ent *de;
6574879Ssam 	struct stat buf;
6584879Ssam 	register struct stat *bufp = &buf;
6593346Swnj 	int segnum;
6603346Swnj 	register char *last;
661954Sbill 
6624879Ssam 	if (stat(name, bufp) < 0) {
6633489Sroot 		perror(name);
6649877Ssam 		return (-1);
6653489Sroot 	}
6664879Ssam 	if (dope = lookup(name)) {
667954Sbill 		/* can replace, no problem */
668954Sbill 		de = dope->rtdope;
6694879Ssam 		if (bufp->st_size <= (de->rt_len * 512))
670954Sbill 			printf("r - %s\n",name),
6714879Ssam 			toflop(name, bufp->st_size, dope);
672954Sbill 		else {
6739877Ssam 			fprintf(stderr,
6749877Ssam 			  "%s will not fit in currently used file on floppy\n",
6759877Ssam 			  name);
6769877Ssam 			return (-1);
677954Sbill 		}
6789877Ssam 		goto found;
6799877Ssam 	}
6809877Ssam 	/*
6819877Ssam 	 * Search for vacant spot
6829877Ssam 	 */
6839877Ssam 	for (segnum = 0; segnum != -1;
6849877Ssam 	     segnum = rt_dir[segnum].rt_axhead.rt_nxtseg - 1)
6859877Ssam 	{
6869877Ssam 		last = rt_last + segnum*2*RT_BLOCK;
6879877Ssam 		for (de = rt_dir[segnum].rt_ents;
6889877Ssam 		    rt(de)->rt_stat != RT_ESEG; de++)
6899877Ssam 			if ((de)->rt_stat == RT_NULL) {
6909877Ssam 				if (bufp->st_size <= (de->rt_len*512)) {
6919877Ssam 					printf("a - %s\n",name),
6929877Ssam 					mkent(de, segnum, bufp,name);
6939877Ssam 					goto found;
694954Sbill 				}
6959877Ssam 				continue;
6969877Ssam 			}
697954Sbill 	}
6989877Ssam 	printf("%s: no slot for file\n", name);
6999877Ssam 	return (-1);
7004879Ssam 
7014879Ssam found:
7024879Ssam 	if (dope = lookup(name)) {
7034879Ssam 		toflop(name, bufp->st_size, dope);
7043489Sroot 		return (0);
705954Sbill 	}
7063489Sroot 	printf("%s: internal error, added then not found\n", name);
7073489Sroot 	return (-1);
7084879Ssam }
709954Sbill 
7104879Ssam mkent(de, segnum, bufp, name)
7114879Ssam 	register struct rt_ent *de;
7124879Ssam 	int segnum;
7134879Ssam 	register struct stat *bufp;
7144879Ssam 	char *name;
715954Sbill {
7164879Ssam 	struct tm *localtime();
7174879Ssam 	register struct tm *timp;
7184879Ssam 	register struct rt_ent *workp;
7194879Ssam 	int count;
720954Sbill 
721954Sbill 	count = (((bufp->st_size -1) >>9) + 1);
7224879Ssam 	/* make sure there is room */
7234879Ssam 	if (de->rt_len == count)
724954Sbill 		goto overwrite;
7254879Ssam 	if ((char *)rt_curend[segnum] == (rt_last + (segnum*2*RT_BLOCK))) {
7264879Ssam 		/* no entries left on segment */
7274879Ssam 		if (flag(o))
728954Sbill 			goto overwrite;
7299877Ssam 		fprintf(stderr, "Directory segment #%d full on  %s\n",
7309877Ssam 			segnum+1, defdev);
731954Sbill 		exit(1);
732954Sbill 	}
7334879Ssam 	/* copy directory entries up */
7344879Ssam 	for (workp = rt_curend[segnum]+1; workp > de; workp--)
735954Sbill 		*workp = workp[-1];
736954Sbill 	de[1].rt_len -= count;
737954Sbill 	de->rt_len = count;
7383346Swnj 	rt_curend[segnum]++;
739954Sbill 	rt_nleft--;
7404879Ssam 
741954Sbill overwrite:
742954Sbill 	srad50(name,de->rt_name);
743954Sbill 	timp = localtime(&bufp->st_mtime);
7447320Swnj 	de->rt_date.rt_dy = timp->tm_mday;
745954Sbill 	de->rt_date.rt_mo = timp->tm_mon + 1;
746954Sbill 	de->rt_date.rt_yr = timp->tm_year - 72;
747954Sbill 	de->rt_stat = RT_FILE;
748954Sbill 	de->rt_pad = 0;
749954Sbill 	de->rt_chan = 0;
750954Sbill 	de->rt_job = 0;
7514879Ssam 	lwrite((6+segnum*2)*RT_BLOCK, 2*RT_BLOCK, (char *)&rt_dir[segnum]);
752954Sbill }
753954Sbill 
7544879Ssam toflop(name, ocount, dope)
7554879Ssam 	char *name;
7564879Ssam 	register FLDOPE *dope;
7574879Ssam 	long ocount;
758954Sbill {
759954Sbill 	register file, n, startad = dope->startad, count = ocount;
760954Sbill 	char buff[512];
761954Sbill 
7624879Ssam 	file = open(name, 0);
7634879Ssam 	if (file < 0) {
7644879Ssam 		fprintf(stderr, "arff: couldn't open %s\n",name);
7654879Ssam 		exit(1);
7664879Ssam 	}
767954Sbill 	for( ; count >= 512; count -= 512) {
7684879Ssam 		read(file, buff, 512);
7694879Ssam 		lwrite(startad, 512, buff);
770954Sbill 		startad += 512;
771954Sbill 	}
7724879Ssam 	read(file, buff, count);
773954Sbill 	close(file);
7744879Ssam 	if (count <= 0)
7754879Ssam 		return;
7764879Ssam 	for (n = count; n < 512; n ++)
7774879Ssam 		buff[n] = 0;
7784879Ssam 	lwrite(startad, 512, buff);
7794879Ssam 	count = (dope->rtdope->rt_len*512-ocount)/512 ;
7804879Ssam 	if (count <= 0)
7814879Ssam 		return;
7824879Ssam 	for ( ; count > 0 ; count--) {
783954Sbill 		startad += 512;
7844879Ssam 		lwrite(startad, 512, zeroes);
785954Sbill 	}
7864879Ssam }
787954Sbill 
788954Sbill dcmd()
789954Sbill {
790954Sbill 	register int i;
791954Sbill 
792954Sbill 	rt_init();
7934879Ssam 	if (namc)
7944879Ssam 		for (i = 0; i < namc; i++)
7954879Ssam 			if (rtk(namv[i])==0)
7964879Ssam 				namv[i]=0;
7974879Ssam 	if (dirdirty)
798954Sbill 		scrunch();
799954Sbill }
8004879Ssam 
801954Sbill rtk(name)
8024879Ssam 	char *name;
803954Sbill {
804954Sbill 	register FLDOPE *dope;
805954Sbill 	register struct rt_ent *de;
806954Sbill 	FLDOPE *lookup();
807954Sbill 
8084879Ssam 	if (dope = lookup(name)) {
809954Sbill 		printf("d - %s\n",name);
810954Sbill 		de = dope->rtdope;
811954Sbill 		de->rt_stat = RT_NULL;
812954Sbill 		de->rt_name[0] = 0;
813954Sbill 		de->rt_name[1] = 0;
814954Sbill 		de->rt_name[2] = 0;
8159877Ssam 		*((u_short *)&(de->rt_date)) = 0;
816954Sbill 		dirdirty = 1;
8179877Ssam 		return (0);
818954Sbill 	}
8199877Ssam 	return (1);
820954Sbill }
8214879Ssam 
8224879Ssam scrunch()
8234879Ssam {
8243346Swnj 	register struct rt_ent *de , *workp;
8253346Swnj 	register segnum;
8264879Ssam 
8274879Ssam 	for (segnum = 0; segnum != -1;
8283346Swnj 	     segnum = rt_dir[segnum].rt_axhead.rt_nxtseg - 1) {
8294879Ssam 		for (de = rt_dir[segnum].rt_ents; de <= rt_curend[segnum]; de++)
8309877Ssam 			if (de->rt_stat == RT_NULL &&
83112012Shelge 			    (de+1)->rt_stat == RT_NULL) {
8324879Ssam 				(de+1)->rt_len += de->rt_len;
83312012Shelge 				for (workp=de; workp<rt_curend[segnum]; workp++)
8344879Ssam 					*workp = workp[1];
8354879Ssam 				de--;
8364879Ssam 				rt_curend[segnum]--;
8374879Ssam 				rt_nleft++;
8384879Ssam 			}
83912012Shelge 		lwrite((6+segnum*2)*RT_BLOCK, 2*RT_BLOCK,
84012012Shelge 			(char *)&rt_dir[segnum]);
841954Sbill 	}
84212012Shelge 	dirdirty = 0;
843954Sbill }
844