xref: /csrg-svn/old/arff/arff.c (revision 33133)
122483Sdist /*
222483Sdist  * Copyright (c) 1980 Regents of the University of California.
322483Sdist  * All rights reserved.  The Berkeley software License Agreement
422483Sdist  * specifies the terms and conditions for redistribution.
522483Sdist  */
622483Sdist 
79877Ssam #ifndef lint
822483Sdist char copyright[] =
922483Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\
1022483Sdist  All rights reserved.\n";
1122483Sdist #endif not lint
124879Ssam 
1322483Sdist #ifndef lint
14*33133Sbostic static char sccsid[] = "@(#)arff.c	5.6 (Berkeley) 12/26/87";
1522483Sdist #endif not lint
1622483Sdist 
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 */
3830238Sbostic 	u_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 */
4130238Sbostic 	u_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
4930238Sbostic #define RT_PFILE	(0200|RT_FILE)	/* protected file */
504879Ssam #define RT_ESEG		8
514879Ssam 
524879Ssam #define RT_BLOCK	512	/* block size */
534879Ssam #define RT_DIRSIZE	31	/* max # of directory segments */
544879Ssam 
55954Sbill struct rt_head {
564879Ssam 	short	rt_numseg;	/* # of segments available */
574879Ssam 	short	rt_nxtseg;	/* # of next logical segment */
584879Ssam 	short	rt_lstseg;	/* highest seg currently open */
594879Ssam 	u_short	rt_entpad;	/* extra words/directory entry */
604879Ssam 	short	rt_stfile;	/* block # where files begin */
61954Sbill };
624879Ssam 
63954Sbill struct	rt_dir {
64954Sbill 	struct rt_head	rt_axhead;
65954Sbill 	struct rt_ent	rt_ents[72];
664879Ssam 	char		_dirpad[6];
67954Sbill };
684879Ssam 
6926131Sbloom #define rd_numseg rt_axhead.rt_numseg
7026131Sbloom #define rd_nxtseg rt_axhead.rt_nxtseg
7126131Sbloom #define rd_lstseg rt_axhead.rt_lstseg
7226131Sbloom #define rd_entpad rt_axhead.rt_entpad
7326131Sbloom #define rd_stfile rt_axhead.rt_stfile
7426131Sbloom 
75954Sbill typedef struct fldope {
76954Sbill 	int	startad;
77954Sbill 	int	count;
78954Sbill struct	rt_ent	*rtdope;
79954Sbill } FLDOPE;
804879Ssam 
81954Sbill FLDOPE *lookup();
824879Ssam 
839877Ssam #define	rt(p)	((struct rt_ent *) p )
849877Ssam #define	Ain1	03100
859877Ssam #define	Ain2	050
869877Ssam #define	flag(c)	(flg[('c') - 'a'])
87954Sbill 
889877Ssam char	*man = "rxtd";
899877Ssam char	zeroes[512];
90954Sbill 
91954Sbill extern char *val;
92954Sbill extern char table[256];
934879Ssam struct rt_dir rt_dir[RT_DIRSIZE] = {
94*33133Sbostic 	{
959877Ssam 	{ 4, 0, 1, 0, 14 },
9626131Sbloom 	{ { 0, RT_NULL, { 0, 0, 0 }, 486, 0 },
979877Ssam 	  { 0, RT_ESEG } }
98*33133Sbostic 	}
994879Ssam };
100954Sbill 
10126131Sbloom struct rt_dir rt_nulldir = {
10226131Sbloom 	{ 0, 0, 0, 0, 0 },
10326131Sbloom 	{ { 0, RT_NULL, { 0, 0, 0 }, 0, 0 },
10426131Sbloom 	  { 0, RT_ESEG } }
10526131Sbloom };
10626131Sbloom 
1074879Ssam int	rt_entsiz;
1084879Ssam int	rt_nleft;
1094879Ssam struct rt_ent *rt_curend[RT_DIRSIZE];
1104879Ssam int	floppydes;
1114879Ssam int	dirdirty;
1124879Ssam char	*rt_last;
1134879Ssam char	*defdev = "/dev/floppy";
114954Sbill 
11526131Sbloom char *opt = "vfbcm";
1164879Ssam 
1174879Ssam extern long lseek();
1184879Ssam int	rcmd(), dcmd(), xcmd(), tcmd();
1194879Ssam 
120954Sbill int	(*comfun)();
121954Sbill char	flg[26];
122954Sbill char	**namv;
123954Sbill int	namc;
124954Sbill 
125954Sbill main(argc, argv)
1264879Ssam 	char *argv[];
127954Sbill {
128954Sbill 	register char *cp;
129954Sbill 
1304879Ssam 	if (argc < 2)
131954Sbill 		usage();
1324879Ssam 	for (cp = argv[1]; *cp; cp++)
1334879Ssam 		switch (*cp) {
134954Sbill 
1354879Ssam 		case 'm':
1364879Ssam 		case 'v':
1374879Ssam 		case 'u':
1384879Ssam 		case 'w':
13926131Sbloom 		case 'b':
1404879Ssam 			flg[*cp-'a']++;
1414879Ssam 			continue;
1424879Ssam 		case 'c':
14313910Ssam 			flag(c)++;
1444879Ssam 			dirdirty++;
1454879Ssam 			continue;
146954Sbill 
1474879Ssam 		case 'r':
1484879Ssam 			setcom(rcmd);
1494879Ssam 			flag(r)++;
1504879Ssam 			continue;
151954Sbill 
1524879Ssam 		case 'd':
1534879Ssam 			setcom(dcmd);
1544879Ssam 			flag(d)++;
1554879Ssam 			continue;
156954Sbill 
1574879Ssam 		case 'x':
1584879Ssam 			setcom(xcmd);
1594879Ssam 			continue;
160954Sbill 
1614879Ssam 		case 't':
1624879Ssam 			setcom(tcmd);
1634879Ssam 			continue;
164954Sbill 
1654879Ssam 		case 'f':
1664879Ssam 			defdev = argv[2];
1674879Ssam 			argv++;
1684879Ssam 			argc--;
1694879Ssam 			continue;
1704879Ssam 
1714879Ssam 		default:
1724879Ssam 			fprintf(stderr, "arff: bad option `%c'\n", *cp);
1734879Ssam 			exit(1);
1744879Ssam 		}
1754879Ssam 
176954Sbill 	namv = argv+2;
177954Sbill 	namc = argc-2;
1784879Ssam 	if (comfun == 0) {
1794879Ssam 		if (flag(u) == 0) {
1804879Ssam 			fprintf(stderr, "arff: one of [%s] must be specified\n",
1814879Ssam 				man);
182954Sbill 			exit(1);
183954Sbill 		}
184954Sbill 		setcom(rcmd);
185954Sbill 	}
186954Sbill 	(*comfun)();
187954Sbill 	exit(notfound());
188954Sbill }
189954Sbill 
190954Sbill setcom(fun)
1914879Ssam 	int (*fun)();
192954Sbill {
1934879Ssam 	if (comfun != 0) {
194954Sbill 		fprintf(stderr, "arff: only one of [%s] allowed\n", man);
195954Sbill 		exit(1);
196954Sbill 	}
197954Sbill 	comfun = fun;
198954Sbill }
199954Sbill 
200954Sbill usage()
201954Sbill {
2023356Swnj 	fprintf(stderr, "usage: ar [%s][%s] archive files ...\n", opt, man);
203954Sbill 	exit(1);
204954Sbill }
205954Sbill 
206954Sbill notfound()
207954Sbill {
2084879Ssam 	register i, n = 0;
209954Sbill 
2104879Ssam 	for (i = 0; i < namc; i++)
2114879Ssam 		if (namv[i]) {
212954Sbill 			fprintf(stderr, "arff: %s not found\n", namv[i]);
213954Sbill 			n++;
214954Sbill 		}
2159877Ssam 	return (n);
216954Sbill }
217954Sbill 
218954Sbill tcmd()
219954Sbill {
2204879Ssam 	register char *de, *last;
221954Sbill 	FLDOPE *lookup(), *dope;
2224879Ssam 	int segnum, nleft;
2234879Ssam 	register i;
224954Sbill 	register struct rt_ent *rde;
225954Sbill 
226954Sbill 	rt_init();
2279877Ssam 	if (namc != 0) {
2284879Ssam 		for (i = 0; i < namc; i++)
2294879Ssam 			if (dope = lookup(namv[i])) {
230954Sbill 				rde = dope->rtdope;
23126131Sbloom 				(void) rtls(rde);
232954Sbill 				namv[i] = 0;
233954Sbill 			}
2349877Ssam 		return;
2359877Ssam 	}
2369877Ssam 	for (segnum = 0; segnum != -1;
23726131Sbloom 	  segnum = rt_dir[segnum].rd_nxtseg - 1) {
2389877Ssam 		last = rt_last + segnum*2*RT_BLOCK;
2399877Ssam 		for (de = ((char *)&rt_dir[segnum])+10; de <= last;
2409877Ssam 		    de += rt_entsiz)
2419877Ssam 			if (rtls(rt(de))) {
2429877Ssam 				nleft = (last-de)/rt_entsiz;
2439877Ssam #define ENTRIES "\n%d entries remaining in directory segment %d.\n"
2449877Ssam 				printf(ENTRIES, nleft, segnum+1);
2459877Ssam 				break;
2469877Ssam 			}
2479877Ssam 	}
248954Sbill }
2494879Ssam 
250954Sbill rtls(de)
2514879Ssam 	register struct rt_ent *de;
252954Sbill {
2534879Ssam 	int month, day, year;
254954Sbill 	char name[12], ext[4];
255954Sbill 
2564879Ssam 	switch (de->rt_stat) {
2574879Ssam 
2584879Ssam 	case RT_TEMP:
2594879Ssam 		if (flag(v))
260954Sbill 			printf("Tempfile:\n");
2614879Ssam 		/* fall thru...*/
262954Sbill 
2634879Ssam 	case RT_FILE:
26430238Sbostic 	case RT_PFILE:
2654879Ssam 		if (!flag(v)) {
2664879Ssam 			sunrad50(name, de->rt_name);
2674879Ssam 			printf("%s\n", name);
268954Sbill 			break;
269954Sbill 		}
2704879Ssam 		unrad50(2, de->rt_name, name);
2714879Ssam 		unrad50(1, &(de->rt_name[2]), ext);
2724879Ssam 		day = de->rt_date.rt_dy;
2734879Ssam 		year = de->rt_date.rt_yr+72;
2744879Ssam 		month = de->rt_date.rt_mo;
2754879Ssam 		printf("%6.6s  %3.3s	%02d/%02d/%02d	%d\n",name,
2764879Ssam 			ext, month, day, year, de->rt_len);
2774879Ssam 		break;
278954Sbill 
2794879Ssam 	case RT_NULL:
2804879Ssam 		printf("%-25.9s	%d\n","<UNUSED>", de->rt_len);
2814879Ssam 		break;
282954Sbill 
2834879Ssam 	case RT_ESEG:
2849877Ssam 		return (1);
285954Sbill 	}
2869877Ssam 	return (0);
287954Sbill }
2884879Ssam 
289954Sbill xcmd()
290954Sbill {
2914879Ssam 	register char *de, *last;
2923346Swnj 	int segnum;
293954Sbill 	char name[12];
294954Sbill 	register int i;
295954Sbill 
296954Sbill 	rt_init();
2979877Ssam 	if (namc != 0) {
2984879Ssam 		for (i = 0; i < namc; i++)
2994879Ssam 			if (rtx(namv[i]) == 0)
3004879Ssam 				namv[i] = 0;
3019877Ssam 		return;
3029877Ssam 	}
3039877Ssam 	for (segnum = 0; segnum != -1;
30426131Sbloom 	     segnum = rt_dir[segnum].rd_nxtseg-1)
3059877Ssam 		for (last = rt_last+(segnum*2*RT_BLOCK),
3069877Ssam 		     de = ((char *)&rt_dir[segnum])+10; de <= last;
30715553Sralph 		     de += rt_entsiz) {
3089877Ssam 			switch (rt(de)->rt_stat) {
3099877Ssam 
3109877Ssam 			case RT_ESEG:
31115553Sralph 				break;	/* exit loop and try next segment */
3129877Ssam 
3139877Ssam 			case RT_TEMP:
3149877Ssam 			case RT_FILE:
31530238Sbostic 			case RT_PFILE:
3169877Ssam 				sunrad50(name,rt(de)->rt_name);
31726131Sbloom 				(void) rtx(name);
3189877Ssam 
3199877Ssam 			case RT_NULL:
32015553Sralph 			default:
32115553Sralph 				continue;
3229877Ssam 			}
32315553Sralph 			break;
32415553Sralph 		}
325954Sbill }
3264879Ssam 
327954Sbill rtx(name)
3284879Ssam 	char *name;
329954Sbill {
330954Sbill 	register FLDOPE *dope;
331954Sbill 	FLDOPE *lookup();
332954Sbill 	register startad, count;
3334879Ssam 	int file;
3344879Ssam 	char buff[512];
335954Sbill 
336954Sbill 
3374879Ssam 	if (dope = lookup(name)) {
3384879Ssam 		if (flag(v))
33926131Sbloom 			(void) rtls(dope->rtdope);
340954Sbill 		else
341954Sbill 			printf("x - %s\n",name);
342954Sbill 
3434879Ssam 		if ((file = creat(name, 0666)) < 0)
3449877Ssam 			return (1);
345954Sbill 		count = dope->count;
346954Sbill 		startad = dope->startad;
347954Sbill 		for( ; count > 0 ; count -= 512) {
34829823Skarels 			(void) lread(startad, 512, buff);
34926131Sbloom 			(void) write(file, buff, 512);
350954Sbill 			startad += 512;
351954Sbill 		}
35226131Sbloom 		(void) close(file);
3539877Ssam 		return (0);
354954Sbill 	}
3559877Ssam 	return (1);
356954Sbill }
3574879Ssam 
358954Sbill rt_init()
359954Sbill {
360954Sbill 	static initized = 0;
3614879Ssam 	register char *de, *last;
3623346Swnj 	register i;
3633799Shickman 	int dirnum;
3643799Shickman 	char *mode;
3653799Shickman 	FILE *temp_floppydes;
366954Sbill 
3674879Ssam 	if (initized)
3684879Ssam 		return;
369954Sbill 	initized = 1;
37013910Ssam 	if (flag(c)) {
37113910Ssam 		struct stat sb;
37213910Ssam 		char response[128];
37313910Ssam 		int tty;
37413910Ssam 
37513910Ssam 		if (stat(defdev, &sb) >= 0 && (sb.st_mode & S_IFMT) == S_IFREG)
37613910Ssam 			goto ignore;
37713910Ssam 		tty = open("/dev/tty", O_RDWR);
37813910Ssam #define SURE	"Are you sure you want to clobber the floppy? "
37926131Sbloom 		(void) write(tty, SURE, sizeof (SURE));
38026131Sbloom 		(void) read(tty, response, sizeof (response));
38113910Ssam 		if (*response != 'y')
38213910Ssam 			exit(50);
38326131Sbloom 		(void) close(tty);
38413910Ssam ignore:
38513910Ssam 		;
38613910Ssam 	}
3874879Ssam 	if (flag(c) || flag(d) || flag(r))
3883799Shickman 		mode = "r+";
389954Sbill 	else
3903799Shickman 		mode = "r";
3914879Ssam 	if ((temp_floppydes = fopen(defdev, mode)) == NULL) {
3923799Shickman 		perror(defdev);
3933356Swnj 		exit(1);
3943799Shickman 	} else
3953799Shickman 		floppydes = fileno(temp_floppydes);
3964879Ssam 	if (!flag(c)) {
39729823Skarels 		if (lread(6*RT_BLOCK, 2*RT_BLOCK, (char *)&rt_dir[0]))
39829823Skarels 			exit(2);
39926131Sbloom 		dirnum = rt_dir[0].rd_numseg;
40012012Shelge 		/* check for blank/uninitialized diskette */
40112012Shelge 		if (dirnum <= 0) {
40212012Shelge 			fprintf(stderr,"arff: bad directory format\n");
40312012Shelge 			exit(1);
40412012Shelge 		}
4053346Swnj 		if (dirnum > RT_DIRSIZE) {
4064879Ssam 			fprintf(stderr,"arff: too many directory segments\n");
4074879Ssam 			exit(1);
4083346Swnj 		}
4094879Ssam 		for (i = 1; i < dirnum; i++)
41029823Skarels 		    if (lread((6+2*i)*RT_BLOCK, 2*RT_BLOCK, (char *)&rt_dir[i]))
41129823Skarels 			exit(1);
41226131Sbloom 	} else {
4133489Sroot 		dirnum = 1;
41426131Sbloom 		if (flag(b)) {
41526131Sbloom 			rt_dir[0].rd_numseg = 31;
41626131Sbloom 			rt_dir[0].rd_stfile = 68;
41726131Sbloom 			rt_dir[0].rt_ents[0].rt_len = 20480 - 68;
41826131Sbloom 		}
41926131Sbloom 	}
420954Sbill 
42126131Sbloom 	rt_entsiz = 2*rt_dir[0].rd_entpad + 14;
42226131Sbloom 	/*
42326131Sbloom 	 * We assume that the directory entries have no padding.  This
42426131Sbloom 	 * may not be a valid assumption, but there are numerous point
42526131Sbloom 	 * in the code where it assumes it is an rt_ent structure and
42626131Sbloom 	 * not an rt_entsiz sized structure.
42726131Sbloom 	 */
42826131Sbloom 	rt_entsiz = 14;
4293346Swnj 	rt_last = ((char *) &rt_dir[0]) + 10 + 1014/rt_entsiz*rt_entsiz;
4303346Swnj 	rt_nleft = 0;
4313346Swnj 
4324879Ssam 	for (i = 0; i < dirnum; i++) {
4334879Ssam 		last = rt_last + i*2*RT_BLOCK;
4344879Ssam 		for (de = ((char *)&rt_dir[i])+10; de <= last; de += rt_entsiz)
4354879Ssam 			if (rt(de)->rt_stat == RT_ESEG)
4364879Ssam 				break;
4374879Ssam 		rt_curend[i] = rt(de);
4384879Ssam 		rt_nleft += (last-de)/rt_entsiz;
439954Sbill 	}
440954Sbill }
441954Sbill 
442954Sbill static FLDOPE result;
4434879Ssam 
444954Sbill FLDOPE *
445954Sbill lookup(name)
4464879Ssam 	char *name;
447954Sbill {
448954Sbill 	unsigned short rname[3];
44926131Sbloom 	register char *de;
4503346Swnj 	int segnum;
451954Sbill 	register index;
452954Sbill 
453954Sbill 	srad50(name,rname);
454954Sbill 
4553356Swnj 	/*
456954Sbill 	 *  Search for name, accumulate blocks in index
457954Sbill 	 */
458954Sbill 	rt_init();
4594879Ssam 	for (segnum = 0; segnum != -1;
46026131Sbloom 	     segnum = rt_dir[segnum].rd_nxtseg - 1)
4614879Ssam 	{
4624879Ssam 		index = 0;
4634879Ssam 		for (de=((char *)&rt_dir[segnum])+10;
4644879Ssam 		     rt(de)->rt_stat != RT_ESEG; de += rt_entsiz)
4654879Ssam 			switch(rt(de)->rt_stat) {
4664879Ssam 
4674879Ssam 			case RT_FILE:
46830238Sbostic 			case RT_PFILE:
4694879Ssam 			case RT_TEMP:
4704879Ssam 				if(samename(rname,rt(de)->rt_name)) {
4714879Ssam 					result.count = rt(de)->rt_len * 512;
4724879Ssam 					result.startad = 512*
47326131Sbloom 					    (rt_dir[segnum].rd_stfile + index);
4744879Ssam 					result.rtdope = (struct rt_ent *) de;
4759877Ssam 					return (&result);
4764879Ssam 				}
4774879Ssam 
4784879Ssam 			case RT_NULL:
4794879Ssam 				index += rt(de)->rt_len;
4804879Ssam 			}
4813346Swnj         }
4829877Ssam 	return ((FLDOPE *) 0);
4834879Ssam 
484954Sbill }
4854879Ssam 
486954Sbill static
4874879Ssam samename(a, b)
4884879Ssam 	u_short a[], b[];
489954Sbill {
4909877Ssam 	return (*a == *b && a[1] == b[1] && a[2] == b[2] );
491954Sbill }
492954Sbill 
4934879Ssam rad50(cp, out)
4944879Ssam 	register u_char *cp;
4954879Ssam 	u_short *out;
496954Sbill {
4974879Ssam 	register index, temp;
498954Sbill 
4994879Ssam 	for (index = 0; *cp; index++) {
500954Sbill 		temp = Ain1 * table[*cp++];
5014879Ssam 		if (*cp!=0) {
502954Sbill 			temp += Ain2 * table[*cp++];
503954Sbill 			if(*cp!=0)
504954Sbill 				temp += table[*cp++];
505954Sbill 		}
506954Sbill 		out[index] = temp;
507954Sbill 	}
508954Sbill }
509954Sbill 
5104879Ssam #define reduce(x, p, q) (x = v[p/q], p %= q);
5114879Ssam 
5124879Ssam unrad50(count, in, cp)
5134879Ssam 	u_short *in;
5144879Ssam 	register char *cp;
515954Sbill {
5164879Ssam 	register i, temp;
5174879Ssam 	register u_char *v = (u_char *) val;
518954Sbill 
5194879Ssam 	for (i = 0; i < count; i++) {
520954Sbill 		temp = in[i];
5214879Ssam 		reduce(*cp++, temp, Ain1);
5224879Ssam 		reduce(*cp++, temp, Ain2);
5234879Ssam 		reduce(*cp++, temp, 1);
524954Sbill 	}
525954Sbill 	*cp=0;
526954Sbill }
527954Sbill 
5284879Ssam srad50(name, rname)
5294879Ssam 	register char *name;
5304879Ssam 	register u_short *rname;
531954Sbill {
5324879Ssam 	register index;
5334879Ssam 	register char *cp;
5344879Ssam 	char file[7], ext[4];
5354879Ssam 
5363356Swnj 	/*
537954Sbill 	 * Find end of pathname
538954Sbill 	 */
5394879Ssam 	for (cp = name; *cp++; )
5404879Ssam 		;
5414879Ssam 	while (cp >= name && *--cp != '/')
5424879Ssam 		;
543954Sbill 	cp++;
5443356Swnj 	/*
545954Sbill 	 * Change to rad50
546954Sbill 	 */
5474879Ssam 	for (index = 0; *cp; ) {
548954Sbill 		file[index++] = *cp++;
5494879Ssam 		if (*cp == '.') {
550954Sbill 			cp++;
551954Sbill 			break;
552954Sbill 		}
5534879Ssam 		if (index >= 6) {
554954Sbill 			break;
555954Sbill 		}
556954Sbill 	}
557954Sbill 	file[index] = 0;
5584879Ssam 	for (index = 0; *cp; ) {
559954Sbill 		ext[index++] = *cp++;
5604879Ssam 		if (*cp == '.' || index >= 3)
561954Sbill 			break;
562954Sbill 	}
563954Sbill 	ext[index]=0;
5644879Ssam 	rname[0] = rname[1] = rname[2] = 0;
5654879Ssam 	rad50((u_char *)file, rname);
5664879Ssam 	rad50((u_char *)ext, rname+2);
567954Sbill }
5684879Ssam 
5694879Ssam sunrad50(name, rname)
5704879Ssam 	u_short rname[];
5714879Ssam 	register char *name;
572954Sbill {
573954Sbill 	register char *cp, *cp2;
574954Sbill 	char ext[4];
575954Sbill 
5764879Ssam 	unrad50(2, rname, name);
5774879Ssam 	unrad50(1, rname + 2, ext);
5784879Ssam 	/*
5794879Ssam 	 * Jam name and extension together with a dot
5804879Ssam 	 * deleting white space
5814879Ssam 	 */
5824879Ssam 	for (cp = name; *cp++;)
5834879Ssam 		;
5844879Ssam 	--cp;
5854879Ssam 	while (*--cp == ' ' && cp >= name)
5864879Ssam 		;
5874879Ssam 	*++cp = '.';
5884879Ssam 	cp++;
5894879Ssam 	for (cp2 = ext; *cp2 != ' ' && cp2 < ext+3;)
590954Sbill 		*cp++ = *cp2++;
591954Sbill 	*cp=0;
5924879Ssam 	if (cp[-1] == '.')
5934879Ssam 		cp[-1] = 0;
594954Sbill }
595954Sbill 
596954Sbill static char *val = " abcdefghijklmnopqrstuvwxyz$.@0123456789";
5974879Ssam 
598954Sbill static char table[256] = {
599954Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
600954Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
601954Sbill 0, 29, 29, 29, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 29,
602954Sbill 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 29, 29, 29, 29, 29, 29,
603954Sbill 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
604954Sbill 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
605954Sbill 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
606954Sbill 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
607954Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
608954Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
609954Sbill 0, 29, 29, 29, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 29,
610954Sbill 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 29, 29, 29, 29, 29, 29,
611954Sbill 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
612954Sbill 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
613954Sbill 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
614954Sbill 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29 };
615954Sbill 
6164879Ssam /*
6174879Ssam  * Logical to physical adress translation
6184879Ssam  */
6194879Ssam long
6204879Ssam trans(logical)
6214879Ssam 	register int logical;
622954Sbill {
623954Sbill 	register int sector, bytes, track;
624954Sbill 
6254879Ssam 	logical += 26*128;
6264879Ssam 	bytes = (logical&127);
627954Sbill 	logical >>= 7;
6284879Ssam 	sector = logical%26;
629954Sbill 	if(sector >= 13)
6304879Ssam 		sector = sector*2+1;
631954Sbill 	else
632954Sbill 		sector *= 2;
6334879Ssam 	sector += 26 + ((track = (logical/26))-1)*6;
634954Sbill 	sector %= 26;
6359877Ssam 	return ((((track*26)+sector) << 7) + bytes);
636954Sbill }
6374879Ssam 
6384879Ssam lread(startad, count, obuff)
6394879Ssam 	register startad, count;
6404879Ssam 	register char *obuff;
641954Sbill {
642954Sbill 	long trans();
643954Sbill 	extern floppydes;
6444879Ssam 	register int size = flag(m) ? 512 : 128;
64529823Skarels 	int error = 0;
64629823Skarels 	extern int errno;
6474879Ssam 
648954Sbill 	rt_init();
6494879Ssam 	while ((count -= size) >= 0) {
65026131Sbloom 		(void) lseek(floppydes, flag(m) ?
6514879Ssam 			(long)startad : trans(startad), 0);
65229823Skarels 		if (read(floppydes, obuff, size) != size) {
65329823Skarels 			error = errno;
65429823Skarels 			fprintf(stderr, "arff: read error block %d: ",
6554879Ssam 				startad/size);
65629823Skarels 			errno = error;
65729823Skarels 			perror("");
65829823Skarels 		}
6594879Ssam 		obuff += size;
6604879Ssam 		startad += size;
6614879Ssam 	}
66229823Skarels 	return (error);
663954Sbill }
6644879Ssam 
6654879Ssam lwrite(startad, count, obuff)
6664879Ssam 	register startad, count;
6674879Ssam 	register char *obuff;
668954Sbill {
669954Sbill 	long trans();
670954Sbill 	extern floppydes;
6714879Ssam 	register int size = flag(m) ? 512 : 128;
6724879Ssam 
673954Sbill 	rt_init();
6744879Ssam 	while ((count -= size) >= 0) {
67526131Sbloom 		(void) lseek(floppydes, flag(m) ?
6764879Ssam 			(long)startad : trans(startad), 0);
6774879Ssam 		if (write(floppydes, obuff, size) != size)
6784879Ssam 			fprintf(stderr, "arff: write error block %d\n",
6794879Ssam 				startad/size);
6804879Ssam 		obuff += size;
6814879Ssam 		startad += size;
6824879Ssam 	}
683954Sbill }
684954Sbill 
685954Sbill rcmd()
686954Sbill {
687954Sbill 	register int i;
688954Sbill 
689954Sbill 	rt_init();
6904879Ssam 	if (namc > 0)
6914879Ssam 		for (i = 0; i < namc; i++)
6924879Ssam 			if (rtr(namv[i]) == 0)
6934879Ssam 				namv[i] = 0;
694954Sbill }
695954Sbill 
696954Sbill rtr(name)
6974879Ssam 	char *name;
698954Sbill {
6994879Ssam 	register FLDOPE *dope;
7004879Ssam 	register struct rt_ent *de;
7014879Ssam 	struct stat buf;
7024879Ssam 	register struct stat *bufp = &buf;
7033346Swnj 	int segnum;
70426131Sbloom 	char type;
705954Sbill 
7064879Ssam 	if (stat(name, bufp) < 0) {
7073489Sroot 		perror(name);
7089877Ssam 		return (-1);
7093489Sroot 	}
71026131Sbloom 	type = 'a';
7114879Ssam 	if (dope = lookup(name)) {
712954Sbill 		/* can replace, no problem */
713954Sbill 		de = dope->rtdope;
71426131Sbloom 		if (bufp->st_size <= (de->rt_len * 512)) {
71526131Sbloom 			printf("r - %s\n",name);
7164879Ssam 			toflop(name, bufp->st_size, dope);
71726131Sbloom 			goto found;
71826131Sbloom 		} else {
71926131Sbloom 			de = dope->rtdope;
72026131Sbloom 			type = 'r';
72126131Sbloom 			de->rt_stat = RT_NULL;
72226131Sbloom 			de->rt_name[0] = 0;
72326131Sbloom 			de->rt_name[1] = 0;
72426131Sbloom 			de->rt_name[2] = 0;
72526131Sbloom 			*((u_short *)&(de->rt_date)) = 0;
72626131Sbloom 			scrunch();
727954Sbill 		}
7289877Ssam 	}
7299877Ssam 	/*
7309877Ssam 	 * Search for vacant spot
7319877Ssam 	 */
7329877Ssam 	for (segnum = 0; segnum != -1;
73326131Sbloom 	     segnum = rt_dir[segnum].rd_nxtseg - 1)
7349877Ssam 	{
7359877Ssam 		for (de = rt_dir[segnum].rt_ents;
7369877Ssam 		    rt(de)->rt_stat != RT_ESEG; de++)
7379877Ssam 			if ((de)->rt_stat == RT_NULL) {
7389877Ssam 				if (bufp->st_size <= (de->rt_len*512)) {
73926131Sbloom 					printf("%c - %s\n", type, name),
7409877Ssam 					mkent(de, segnum, bufp,name);
7419877Ssam 					goto found;
742954Sbill 				}
7439877Ssam 				continue;
7449877Ssam 			}
745954Sbill 	}
74630998Sbostic 	if (type == 'r')
74726131Sbloom 		printf("%s: no slot for file, file deleted\n",name);
74826131Sbloom 	else
74926131Sbloom 		printf("%s: no slot for file\n", name);
7509877Ssam 	return (-1);
7514879Ssam 
7524879Ssam found:
7534879Ssam 	if (dope = lookup(name)) {
7544879Ssam 		toflop(name, bufp->st_size, dope);
7553489Sroot 		return (0);
756954Sbill 	}
7573489Sroot 	printf("%s: internal error, added then not found\n", name);
7583489Sroot 	return (-1);
7594879Ssam }
760954Sbill 
7614879Ssam mkent(de, segnum, bufp, name)
7624879Ssam 	register struct rt_ent *de;
7634879Ssam 	int segnum;
7644879Ssam 	register struct stat *bufp;
7654879Ssam 	char *name;
766954Sbill {
7674879Ssam 	struct tm *localtime();
7684879Ssam 	register struct tm *timp;
7694879Ssam 	register struct rt_ent *workp;
7704879Ssam 	int count;
771954Sbill 
772954Sbill 	count = (((bufp->st_size -1) >>9) + 1);
7734879Ssam 	/* make sure there is room */
7744879Ssam 	if (de->rt_len == count)
775954Sbill 		goto overwrite;
7764879Ssam 	if ((char *)rt_curend[segnum] == (rt_last + (segnum*2*RT_BLOCK))) {
77726131Sbloom 		/* no entries left on segment, trying adding new segment */
77826131Sbloom 		if (rt_dir[0].rd_numseg > rt_dir[0].rd_lstseg) {
77926131Sbloom 			short newseg;
78026131Sbloom 			register int i;
78126131Sbloom 			int maxseg;
78226131Sbloom 			short size;
78326131Sbloom 
78426131Sbloom 			newseg = rt_dir[0].rd_lstseg++;
78526131Sbloom 			rt_dir[newseg] = rt_nulldir;
78626131Sbloom 			rt_dir[newseg].rd_nxtseg = rt_dir[segnum].rd_nxtseg;
78726131Sbloom 			rt_dir[segnum].rd_nxtseg = newseg + 1;
78826131Sbloom 			rt_dir[newseg].rd_entpad = rt_dir[0].rd_entpad;
78926131Sbloom 			rt_dir[newseg].rd_numseg = rt_dir[0].rd_numseg;
79026131Sbloom 			size = 0;
79126131Sbloom 			maxseg = 0;
79226131Sbloom 			for(i = newseg - 1; i >= 0; i--) {
79326131Sbloom 				workp = rt_curend[i] - 1;
79426131Sbloom 				if (workp->rt_stat != RT_NULL)
79526131Sbloom 					continue;
79626131Sbloom 				if (workp->rt_len < size)
79726131Sbloom 					continue;
79826131Sbloom 				size = workp->rt_len;
79926131Sbloom 				maxseg = i;
80026131Sbloom 			}
80126131Sbloom 			size = 0;
80226131Sbloom 			for (workp = &rt_dir[maxseg].rt_ents[0];
80326131Sbloom 			    workp->rt_stat != RT_ESEG; workp++) {
80426131Sbloom 				size += workp->rt_len;
80526131Sbloom 			}
80626131Sbloom 			workp--;
80726131Sbloom 			rt_dir[newseg].rt_ents[0].rt_len = workp->rt_len;
80826131Sbloom 			rt_dir[newseg].rd_stfile =
80926131Sbloom 			    rt_dir[maxseg].rd_stfile + size - workp->rt_len;
81026131Sbloom 			workp->rt_len = 0;
81126131Sbloom 			rt_curend[newseg] = &rt_dir[newseg].rt_ents[1];
81226131Sbloom 			lwrite(6*RT_BLOCK, 2*RT_BLOCK, (char *)&rt_dir[0]);
81326131Sbloom 			if (segnum != 0)
81426131Sbloom 				lwrite((6+segnum*2)*RT_BLOCK, 2*RT_BLOCK,
81526131Sbloom 				    (char *)&rt_dir[segnum]);
81626131Sbloom 			lwrite((6+newseg*2)*RT_BLOCK, 2*RT_BLOCK,
81726131Sbloom 			    (char *)&rt_dir[newseg]);
81826131Sbloom 			segnum = newseg;
81926131Sbloom 			de = &rt_dir[newseg].rt_ents[0];
82026131Sbloom 		} else {
82126131Sbloom 			fprintf(stderr, "All directory segments full on  %s\n",
82226131Sbloom 				defdev);
82326131Sbloom 			exit(1);
82426131Sbloom 		}
825954Sbill 	}
8264879Ssam 	/* copy directory entries up */
8274879Ssam 	for (workp = rt_curend[segnum]+1; workp > de; workp--)
828954Sbill 		*workp = workp[-1];
829954Sbill 	de[1].rt_len -= count;
830954Sbill 	de->rt_len = count;
8313346Swnj 	rt_curend[segnum]++;
832954Sbill 	rt_nleft--;
8334879Ssam 
834954Sbill overwrite:
835954Sbill 	srad50(name,de->rt_name);
836954Sbill 	timp = localtime(&bufp->st_mtime);
8377320Swnj 	de->rt_date.rt_dy = timp->tm_mday;
838954Sbill 	de->rt_date.rt_mo = timp->tm_mon + 1;
839954Sbill 	de->rt_date.rt_yr = timp->tm_year - 72;
840954Sbill 	de->rt_stat = RT_FILE;
841954Sbill 	de->rt_pad = 0;
842954Sbill 	de->rt_chan = 0;
843954Sbill 	de->rt_job = 0;
8444879Ssam 	lwrite((6+segnum*2)*RT_BLOCK, 2*RT_BLOCK, (char *)&rt_dir[segnum]);
845954Sbill }
846954Sbill 
8474879Ssam toflop(name, ocount, dope)
8484879Ssam 	char *name;
8494879Ssam 	register FLDOPE *dope;
8504879Ssam 	long ocount;
851954Sbill {
852954Sbill 	register file, n, startad = dope->startad, count = ocount;
853954Sbill 	char buff[512];
854954Sbill 
8554879Ssam 	file = open(name, 0);
8564879Ssam 	if (file < 0) {
8574879Ssam 		fprintf(stderr, "arff: couldn't open %s\n",name);
8584879Ssam 		exit(1);
8594879Ssam 	}
860954Sbill 	for( ; count >= 512; count -= 512) {
86126131Sbloom 		(void) read(file, buff, 512);
8624879Ssam 		lwrite(startad, 512, buff);
863954Sbill 		startad += 512;
864954Sbill 	}
86526131Sbloom 	(void) read(file, buff, count);
86626131Sbloom 	(void) close(file);
8674879Ssam 	if (count <= 0)
8684879Ssam 		return;
8694879Ssam 	for (n = count; n < 512; n ++)
8704879Ssam 		buff[n] = 0;
8714879Ssam 	lwrite(startad, 512, buff);
8724879Ssam 	count = (dope->rtdope->rt_len*512-ocount)/512 ;
8734879Ssam 	if (count <= 0)
8744879Ssam 		return;
8754879Ssam 	for ( ; count > 0 ; count--) {
876954Sbill 		startad += 512;
8774879Ssam 		lwrite(startad, 512, zeroes);
878954Sbill 	}
8794879Ssam }
880954Sbill 
881954Sbill dcmd()
882954Sbill {
883954Sbill 	register int i;
884954Sbill 
885954Sbill 	rt_init();
8864879Ssam 	if (namc)
8874879Ssam 		for (i = 0; i < namc; i++)
8884879Ssam 			if (rtk(namv[i])==0)
8894879Ssam 				namv[i]=0;
8904879Ssam 	if (dirdirty)
891954Sbill 		scrunch();
892954Sbill }
8934879Ssam 
894954Sbill rtk(name)
8954879Ssam 	char *name;
896954Sbill {
897954Sbill 	register FLDOPE *dope;
898954Sbill 	register struct rt_ent *de;
899954Sbill 	FLDOPE *lookup();
900954Sbill 
9014879Ssam 	if (dope = lookup(name)) {
902954Sbill 		printf("d - %s\n",name);
903954Sbill 		de = dope->rtdope;
904954Sbill 		de->rt_stat = RT_NULL;
905954Sbill 		de->rt_name[0] = 0;
906954Sbill 		de->rt_name[1] = 0;
907954Sbill 		de->rt_name[2] = 0;
9089877Ssam 		*((u_short *)&(de->rt_date)) = 0;
909954Sbill 		dirdirty = 1;
9109877Ssam 		return (0);
911954Sbill 	}
9129877Ssam 	return (1);
913954Sbill }
9144879Ssam 
9154879Ssam scrunch()
9164879Ssam {
9173346Swnj 	register struct rt_ent *de , *workp;
9183346Swnj 	register segnum;
9194879Ssam 
9204879Ssam 	for (segnum = 0; segnum != -1;
92126131Sbloom 	     segnum = rt_dir[segnum].rd_nxtseg - 1) {
9224879Ssam 		for (de = rt_dir[segnum].rt_ents; de <= rt_curend[segnum]; de++)
9239877Ssam 			if (de->rt_stat == RT_NULL &&
92412012Shelge 			    (de+1)->rt_stat == RT_NULL) {
9254879Ssam 				(de+1)->rt_len += de->rt_len;
92612012Shelge 				for (workp=de; workp<rt_curend[segnum]; workp++)
9274879Ssam 					*workp = workp[1];
9284879Ssam 				de--;
9294879Ssam 				rt_curend[segnum]--;
9304879Ssam 				rt_nleft++;
9314879Ssam 			}
93212012Shelge 		lwrite((6+segnum*2)*RT_BLOCK, 2*RT_BLOCK,
93312012Shelge 			(char *)&rt_dir[segnum]);
934954Sbill 	}
93512012Shelge 	dirdirty = 0;
936954Sbill }
937