xref: /csrg-svn/old/arff/arff.c (revision 29823)
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*29823Skarels static char sccsid[] = "@(#)arff.c	5.3 (Berkeley) 09/03/86";
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 */
384879Ssam 	char	rt_stat;	/* type of entry, or end of seg */
394879Ssam 	u_short	rt_name[3];	/* name, 3 words in rad50 form */
407319Swnj 	u_short	rt_len;		/* length of file */
414879Ssam 	char	rt_chan;	/* only used in temporary files */
424879Ssam 	char	rt_job;		/* only used in temporary files */
439877Ssam 	struct	rt_dat rt_date;	/* creation date */
44954Sbill };
454879Ssam 
464879Ssam #define RT_TEMP		1
474879Ssam #define RT_NULL		2
484879Ssam #define RT_FILE		4
494879Ssam #define RT_ESEG		8
504879Ssam 
514879Ssam #define RT_BLOCK	512	/* block size */
524879Ssam #define RT_DIRSIZE	31	/* max # of directory segments */
534879Ssam 
54954Sbill struct rt_head {
554879Ssam 	short	rt_numseg;	/* # of segments available */
564879Ssam 	short	rt_nxtseg;	/* # of next logical segment */
574879Ssam 	short	rt_lstseg;	/* highest seg currently open */
584879Ssam 	u_short	rt_entpad;	/* extra words/directory entry */
594879Ssam 	short	rt_stfile;	/* block # where files begin */
60954Sbill };
614879Ssam 
62954Sbill struct	rt_dir {
63954Sbill 	struct rt_head	rt_axhead;
64954Sbill 	struct rt_ent	rt_ents[72];
654879Ssam 	char		_dirpad[6];
66954Sbill };
674879Ssam 
6826131Sbloom #define rd_numseg rt_axhead.rt_numseg
6926131Sbloom #define rd_nxtseg rt_axhead.rt_nxtseg
7026131Sbloom #define rd_lstseg rt_axhead.rt_lstseg
7126131Sbloom #define rd_entpad rt_axhead.rt_entpad
7226131Sbloom #define rd_stfile rt_axhead.rt_stfile
7326131Sbloom 
74954Sbill typedef struct fldope {
75954Sbill 	int	startad;
76954Sbill 	int	count;
77954Sbill struct	rt_ent	*rtdope;
78954Sbill } FLDOPE;
794879Ssam 
80954Sbill FLDOPE *lookup();
814879Ssam 
829877Ssam #define	rt(p)	((struct rt_ent *) p )
839877Ssam #define	Ain1	03100
849877Ssam #define	Ain2	050
859877Ssam #define	flag(c)	(flg[('c') - 'a'])
86954Sbill 
879877Ssam char	*man = "rxtd";
889877Ssam char	zeroes[512];
89954Sbill 
90954Sbill extern char *val;
91954Sbill extern char table[256];
924879Ssam struct rt_dir rt_dir[RT_DIRSIZE] = {
939877Ssam 	{ 4, 0, 1, 0, 14 },
9426131Sbloom 	{ { 0, RT_NULL, { 0, 0, 0 }, 486, 0 },
959877Ssam 	  { 0, RT_ESEG } }
964879Ssam };
97954Sbill 
9826131Sbloom struct rt_dir rt_nulldir = {
9926131Sbloom 	{ 0, 0, 0, 0, 0 },
10026131Sbloom 	{ { 0, RT_NULL, { 0, 0, 0 }, 0, 0 },
10126131Sbloom 	  { 0, RT_ESEG } }
10226131Sbloom };
10326131Sbloom 
1044879Ssam int	rt_entsiz;
1054879Ssam int	rt_nleft;
1064879Ssam struct rt_ent *rt_curend[RT_DIRSIZE];
1074879Ssam int	floppydes;
1084879Ssam int	dirdirty;
1094879Ssam char	*rt_last;
1104879Ssam char	*defdev = "/dev/floppy";
111954Sbill 
11226131Sbloom char *opt = "vfbcm";
1134879Ssam 
1144879Ssam extern long lseek();
1154879Ssam int	rcmd(), dcmd(), xcmd(), tcmd();
1164879Ssam 
117954Sbill int	(*comfun)();
118954Sbill char	flg[26];
119954Sbill char	**namv;
120954Sbill int	namc;
121954Sbill 
122954Sbill main(argc, argv)
1234879Ssam 	char *argv[];
124954Sbill {
125954Sbill 	register char *cp;
126954Sbill 
1274879Ssam 	if (argc < 2)
128954Sbill 		usage();
1294879Ssam 	for (cp = argv[1]; *cp; cp++)
1304879Ssam 		switch (*cp) {
131954Sbill 
1324879Ssam 		case 'm':
1334879Ssam 		case 'v':
1344879Ssam 		case 'u':
1354879Ssam 		case 'w':
13626131Sbloom 		case 'b':
1374879Ssam 			flg[*cp-'a']++;
1384879Ssam 			continue;
1394879Ssam 		case 'c':
14013910Ssam 			flag(c)++;
1414879Ssam 			dirdirty++;
1424879Ssam 			continue;
143954Sbill 
1444879Ssam 		case 'r':
1454879Ssam 			setcom(rcmd);
1464879Ssam 			flag(r)++;
1474879Ssam 			continue;
148954Sbill 
1494879Ssam 		case 'd':
1504879Ssam 			setcom(dcmd);
1514879Ssam 			flag(d)++;
1524879Ssam 			continue;
153954Sbill 
1544879Ssam 		case 'x':
1554879Ssam 			setcom(xcmd);
1564879Ssam 			continue;
157954Sbill 
1584879Ssam 		case 't':
1594879Ssam 			setcom(tcmd);
1604879Ssam 			continue;
161954Sbill 
1624879Ssam 		case 'f':
1634879Ssam 			defdev = argv[2];
1644879Ssam 			argv++;
1654879Ssam 			argc--;
1664879Ssam 			continue;
1674879Ssam 
1684879Ssam 		default:
1694879Ssam 			fprintf(stderr, "arff: bad option `%c'\n", *cp);
1704879Ssam 			exit(1);
1714879Ssam 		}
1724879Ssam 
173954Sbill 	namv = argv+2;
174954Sbill 	namc = argc-2;
1754879Ssam 	if (comfun == 0) {
1764879Ssam 		if (flag(u) == 0) {
1774879Ssam 			fprintf(stderr, "arff: one of [%s] must be specified\n",
1784879Ssam 				man);
179954Sbill 			exit(1);
180954Sbill 		}
181954Sbill 		setcom(rcmd);
182954Sbill 	}
183954Sbill 	(*comfun)();
184954Sbill 	exit(notfound());
185954Sbill }
186954Sbill 
187954Sbill setcom(fun)
1884879Ssam 	int (*fun)();
189954Sbill {
1904879Ssam 	if (comfun != 0) {
191954Sbill 		fprintf(stderr, "arff: only one of [%s] allowed\n", man);
192954Sbill 		exit(1);
193954Sbill 	}
194954Sbill 	comfun = fun;
195954Sbill }
196954Sbill 
197954Sbill usage()
198954Sbill {
1993356Swnj 	fprintf(stderr, "usage: ar [%s][%s] archive files ...\n", opt, man);
200954Sbill 	exit(1);
201954Sbill }
202954Sbill 
203954Sbill notfound()
204954Sbill {
2054879Ssam 	register i, n = 0;
206954Sbill 
2074879Ssam 	for (i = 0; i < namc; i++)
2084879Ssam 		if (namv[i]) {
209954Sbill 			fprintf(stderr, "arff: %s not found\n", namv[i]);
210954Sbill 			n++;
211954Sbill 		}
2129877Ssam 	return (n);
213954Sbill }
214954Sbill 
215954Sbill tcmd()
216954Sbill {
2174879Ssam 	register char *de, *last;
218954Sbill 	FLDOPE *lookup(), *dope;
2194879Ssam 	int segnum, nleft;
2204879Ssam 	register i;
221954Sbill 	register struct rt_ent *rde;
222954Sbill 
223954Sbill 	rt_init();
2249877Ssam 	if (namc != 0) {
2254879Ssam 		for (i = 0; i < namc; i++)
2264879Ssam 			if (dope = lookup(namv[i])) {
227954Sbill 				rde = dope->rtdope;
22826131Sbloom 				(void) rtls(rde);
229954Sbill 				namv[i] = 0;
230954Sbill 			}
2319877Ssam 		return;
2329877Ssam 	}
2339877Ssam 	for (segnum = 0; segnum != -1;
23426131Sbloom 	  segnum = rt_dir[segnum].rd_nxtseg - 1) {
2359877Ssam 		last = rt_last + segnum*2*RT_BLOCK;
2369877Ssam 		for (de = ((char *)&rt_dir[segnum])+10; de <= last;
2379877Ssam 		    de += rt_entsiz)
2389877Ssam 			if (rtls(rt(de))) {
2399877Ssam 				nleft = (last-de)/rt_entsiz;
2409877Ssam #define ENTRIES "\n%d entries remaining in directory segment %d.\n"
2419877Ssam 				printf(ENTRIES, nleft, segnum+1);
2429877Ssam 				break;
2439877Ssam 			}
2449877Ssam 	}
245954Sbill }
2464879Ssam 
247954Sbill rtls(de)
2484879Ssam 	register struct rt_ent *de;
249954Sbill {
2504879Ssam 	int month, day, year;
251954Sbill 	char name[12], ext[4];
252954Sbill 
2534879Ssam 	switch (de->rt_stat) {
2544879Ssam 
2554879Ssam 	case RT_TEMP:
2564879Ssam 		if (flag(v))
257954Sbill 			printf("Tempfile:\n");
2584879Ssam 		/* fall thru...*/
259954Sbill 
2604879Ssam 	case RT_FILE:
2614879Ssam 		if (!flag(v)) {
2624879Ssam 			sunrad50(name, de->rt_name);
2634879Ssam 			printf("%s\n", name);
264954Sbill 			break;
265954Sbill 		}
2664879Ssam 		unrad50(2, de->rt_name, name);
2674879Ssam 		unrad50(1, &(de->rt_name[2]), ext);
2684879Ssam 		day = de->rt_date.rt_dy;
2694879Ssam 		year = de->rt_date.rt_yr+72;
2704879Ssam 		month = de->rt_date.rt_mo;
2714879Ssam 		printf("%6.6s  %3.3s	%02d/%02d/%02d	%d\n",name,
2724879Ssam 			ext, month, day, year, de->rt_len);
2734879Ssam 		break;
274954Sbill 
2754879Ssam 	case RT_NULL:
2764879Ssam 		printf("%-25.9s	%d\n","<UNUSED>", de->rt_len);
2774879Ssam 		break;
278954Sbill 
2794879Ssam 	case RT_ESEG:
2809877Ssam 		return (1);
281954Sbill 	}
2829877Ssam 	return (0);
283954Sbill }
2844879Ssam 
285954Sbill xcmd()
286954Sbill {
2874879Ssam 	register char *de, *last;
2883346Swnj 	int segnum;
289954Sbill 	char name[12];
290954Sbill 	register int i;
291954Sbill 
292954Sbill 	rt_init();
2939877Ssam 	if (namc != 0) {
2944879Ssam 		for (i = 0; i < namc; i++)
2954879Ssam 			if (rtx(namv[i]) == 0)
2964879Ssam 				namv[i] = 0;
2979877Ssam 		return;
2989877Ssam 	}
2999877Ssam 	for (segnum = 0; segnum != -1;
30026131Sbloom 	     segnum = rt_dir[segnum].rd_nxtseg-1)
3019877Ssam 		for (last = rt_last+(segnum*2*RT_BLOCK),
3029877Ssam 		     de = ((char *)&rt_dir[segnum])+10; de <= last;
30315553Sralph 		     de += rt_entsiz) {
3049877Ssam 			switch (rt(de)->rt_stat) {
3059877Ssam 
3069877Ssam 			case RT_ESEG:
30715553Sralph 				break;	/* exit loop and try next segment */
3089877Ssam 
3099877Ssam 			case RT_TEMP:
3109877Ssam 			case RT_FILE:
3119877Ssam 				sunrad50(name,rt(de)->rt_name);
31226131Sbloom 				(void) rtx(name);
3139877Ssam 
3149877Ssam 			case RT_NULL:
31515553Sralph 			default:
31615553Sralph 				continue;
3179877Ssam 			}
31815553Sralph 			break;
31915553Sralph 		}
320954Sbill }
3214879Ssam 
322954Sbill rtx(name)
3234879Ssam 	char *name;
324954Sbill {
325954Sbill 	register FLDOPE *dope;
326954Sbill 	FLDOPE *lookup();
327954Sbill 	register startad, count;
3284879Ssam 	int file;
3294879Ssam 	char buff[512];
330954Sbill 
331954Sbill 
3324879Ssam 	if (dope = lookup(name)) {
3334879Ssam 		if (flag(v))
33426131Sbloom 			(void) rtls(dope->rtdope);
335954Sbill 		else
336954Sbill 			printf("x - %s\n",name);
337954Sbill 
3384879Ssam 		if ((file = creat(name, 0666)) < 0)
3399877Ssam 			return (1);
340954Sbill 		count = dope->count;
341954Sbill 		startad = dope->startad;
342954Sbill 		for( ; count > 0 ; count -= 512) {
343*29823Skarels 			(void) lread(startad, 512, buff);
34426131Sbloom 			(void) write(file, buff, 512);
345954Sbill 			startad += 512;
346954Sbill 		}
34726131Sbloom 		(void) close(file);
3489877Ssam 		return (0);
349954Sbill 	}
3509877Ssam 	return (1);
351954Sbill }
3524879Ssam 
353954Sbill rt_init()
354954Sbill {
355954Sbill 	static initized = 0;
3564879Ssam 	register char *de, *last;
3573346Swnj 	register i;
3583799Shickman 	int dirnum;
3593799Shickman 	char *mode;
3603799Shickman 	FILE *temp_floppydes;
361954Sbill 
3624879Ssam 	if (initized)
3634879Ssam 		return;
364954Sbill 	initized = 1;
36513910Ssam 	if (flag(c)) {
36613910Ssam 		struct stat sb;
36713910Ssam 		char response[128];
36813910Ssam 		int tty;
36913910Ssam 
37013910Ssam 		if (stat(defdev, &sb) >= 0 && (sb.st_mode & S_IFMT) == S_IFREG)
37113910Ssam 			goto ignore;
37213910Ssam 		tty = open("/dev/tty", O_RDWR);
37313910Ssam #define SURE	"Are you sure you want to clobber the floppy? "
37426131Sbloom 		(void) write(tty, SURE, sizeof (SURE));
37526131Sbloom 		(void) read(tty, response, sizeof (response));
37613910Ssam 		if (*response != 'y')
37713910Ssam 			exit(50);
37826131Sbloom 		(void) close(tty);
37913910Ssam ignore:
38013910Ssam 		;
38113910Ssam 	}
3824879Ssam 	if (flag(c) || flag(d) || flag(r))
3833799Shickman 		mode = "r+";
384954Sbill 	else
3853799Shickman 		mode = "r";
3864879Ssam 	if ((temp_floppydes = fopen(defdev, mode)) == NULL) {
3873799Shickman 		perror(defdev);
3883356Swnj 		exit(1);
3893799Shickman 	} else
3903799Shickman 		floppydes = fileno(temp_floppydes);
3914879Ssam 	if (!flag(c)) {
392*29823Skarels 		if (lread(6*RT_BLOCK, 2*RT_BLOCK, (char *)&rt_dir[0]))
393*29823Skarels 			exit(2);
39426131Sbloom 		dirnum = rt_dir[0].rd_numseg;
39512012Shelge 		/* check for blank/uninitialized diskette */
39612012Shelge 		if (dirnum <= 0) {
39712012Shelge 			fprintf(stderr,"arff: bad directory format\n");
39812012Shelge 			exit(1);
39912012Shelge 		}
4003346Swnj 		if (dirnum > RT_DIRSIZE) {
4014879Ssam 			fprintf(stderr,"arff: too many directory segments\n");
4024879Ssam 			exit(1);
4033346Swnj 		}
4044879Ssam 		for (i = 1; i < dirnum; i++)
405*29823Skarels 		    if (lread((6+2*i)*RT_BLOCK, 2*RT_BLOCK, (char *)&rt_dir[i]))
406*29823Skarels 			exit(1);
40726131Sbloom 	} else {
4083489Sroot 		dirnum = 1;
40926131Sbloom 		if (flag(b)) {
41026131Sbloom 			rt_dir[0].rd_numseg = 31;
41126131Sbloom 			rt_dir[0].rd_stfile = 68;
41226131Sbloom 			rt_dir[0].rt_ents[0].rt_len = 20480 - 68;
41326131Sbloom 		}
41426131Sbloom 	}
415954Sbill 
41626131Sbloom 	rt_entsiz = 2*rt_dir[0].rd_entpad + 14;
41726131Sbloom 	/*
41826131Sbloom 	 * We assume that the directory entries have no padding.  This
41926131Sbloom 	 * may not be a valid assumption, but there are numerous point
42026131Sbloom 	 * in the code where it assumes it is an rt_ent structure and
42126131Sbloom 	 * not an rt_entsiz sized structure.
42226131Sbloom 	 */
42326131Sbloom 	rt_entsiz = 14;
4243346Swnj 	rt_last = ((char *) &rt_dir[0]) + 10 + 1014/rt_entsiz*rt_entsiz;
4253346Swnj 	rt_nleft = 0;
4263346Swnj 
4274879Ssam 	for (i = 0; i < dirnum; i++) {
4284879Ssam 		last = rt_last + i*2*RT_BLOCK;
4294879Ssam 		for (de = ((char *)&rt_dir[i])+10; de <= last; de += rt_entsiz)
4304879Ssam 			if (rt(de)->rt_stat == RT_ESEG)
4314879Ssam 				break;
4324879Ssam 		rt_curend[i] = rt(de);
4334879Ssam 		rt_nleft += (last-de)/rt_entsiz;
434954Sbill 	}
435954Sbill }
436954Sbill 
437954Sbill static FLDOPE result;
4384879Ssam 
439954Sbill FLDOPE *
440954Sbill lookup(name)
4414879Ssam 	char *name;
442954Sbill {
443954Sbill 	unsigned short rname[3];
44426131Sbloom 	register char *de;
4453346Swnj 	int segnum;
446954Sbill 	register index;
447954Sbill 
448954Sbill 	srad50(name,rname);
449954Sbill 
4503356Swnj 	/*
451954Sbill 	 *  Search for name, accumulate blocks in index
452954Sbill 	 */
453954Sbill 	rt_init();
4544879Ssam 	for (segnum = 0; segnum != -1;
45526131Sbloom 	     segnum = rt_dir[segnum].rd_nxtseg - 1)
4564879Ssam 	{
4574879Ssam 		index = 0;
4584879Ssam 		for (de=((char *)&rt_dir[segnum])+10;
4594879Ssam 		     rt(de)->rt_stat != RT_ESEG; de += rt_entsiz)
4604879Ssam 			switch(rt(de)->rt_stat) {
4614879Ssam 
4624879Ssam 			case RT_FILE:
4634879Ssam 			case RT_TEMP:
4644879Ssam 				if(samename(rname,rt(de)->rt_name)) {
4654879Ssam 					result.count = rt(de)->rt_len * 512;
4664879Ssam 					result.startad = 512*
46726131Sbloom 					    (rt_dir[segnum].rd_stfile + index);
4684879Ssam 					result.rtdope = (struct rt_ent *) de;
4699877Ssam 					return (&result);
4704879Ssam 				}
4714879Ssam 
4724879Ssam 			case RT_NULL:
4734879Ssam 				index += rt(de)->rt_len;
4744879Ssam 			}
4753346Swnj         }
4769877Ssam 	return ((FLDOPE *) 0);
4774879Ssam 
478954Sbill }
4794879Ssam 
480954Sbill static
4814879Ssam samename(a, b)
4824879Ssam 	u_short a[], b[];
483954Sbill {
4849877Ssam 	return (*a == *b && a[1] == b[1] && a[2] == b[2] );
485954Sbill }
486954Sbill 
4874879Ssam rad50(cp, out)
4884879Ssam 	register u_char *cp;
4894879Ssam 	u_short *out;
490954Sbill {
4914879Ssam 	register index, temp;
492954Sbill 
4934879Ssam 	for (index = 0; *cp; index++) {
494954Sbill 		temp = Ain1 * table[*cp++];
4954879Ssam 		if (*cp!=0) {
496954Sbill 			temp += Ain2 * table[*cp++];
497954Sbill 			if(*cp!=0)
498954Sbill 				temp += table[*cp++];
499954Sbill 		}
500954Sbill 		out[index] = temp;
501954Sbill 	}
502954Sbill }
503954Sbill 
5044879Ssam #define reduce(x, p, q) (x = v[p/q], p %= q);
5054879Ssam 
5064879Ssam unrad50(count, in, cp)
5074879Ssam 	u_short *in;
5084879Ssam 	register char *cp;
509954Sbill {
5104879Ssam 	register i, temp;
5114879Ssam 	register u_char *v = (u_char *) val;
512954Sbill 
5134879Ssam 	for (i = 0; i < count; i++) {
514954Sbill 		temp = in[i];
5154879Ssam 		reduce(*cp++, temp, Ain1);
5164879Ssam 		reduce(*cp++, temp, Ain2);
5174879Ssam 		reduce(*cp++, temp, 1);
518954Sbill 	}
519954Sbill 	*cp=0;
520954Sbill }
521954Sbill 
5224879Ssam srad50(name, rname)
5234879Ssam 	register char *name;
5244879Ssam 	register u_short *rname;
525954Sbill {
5264879Ssam 	register index;
5274879Ssam 	register char *cp;
5284879Ssam 	char file[7], ext[4];
5294879Ssam 
5303356Swnj 	/*
531954Sbill 	 * Find end of pathname
532954Sbill 	 */
5334879Ssam 	for (cp = name; *cp++; )
5344879Ssam 		;
5354879Ssam 	while (cp >= name && *--cp != '/')
5364879Ssam 		;
537954Sbill 	cp++;
5383356Swnj 	/*
539954Sbill 	 * Change to rad50
540954Sbill 	 */
5414879Ssam 	for (index = 0; *cp; ) {
542954Sbill 		file[index++] = *cp++;
5434879Ssam 		if (*cp == '.') {
544954Sbill 			cp++;
545954Sbill 			break;
546954Sbill 		}
5474879Ssam 		if (index >= 6) {
548954Sbill 			break;
549954Sbill 		}
550954Sbill 	}
551954Sbill 	file[index] = 0;
5524879Ssam 	for (index = 0; *cp; ) {
553954Sbill 		ext[index++] = *cp++;
5544879Ssam 		if (*cp == '.' || index >= 3)
555954Sbill 			break;
556954Sbill 	}
557954Sbill 	ext[index]=0;
5584879Ssam 	rname[0] = rname[1] = rname[2] = 0;
5594879Ssam 	rad50((u_char *)file, rname);
5604879Ssam 	rad50((u_char *)ext, rname+2);
561954Sbill }
5624879Ssam 
5634879Ssam sunrad50(name, rname)
5644879Ssam 	u_short rname[];
5654879Ssam 	register char *name;
566954Sbill {
567954Sbill 	register char *cp, *cp2;
568954Sbill 	char ext[4];
569954Sbill 
5704879Ssam 	unrad50(2, rname, name);
5714879Ssam 	unrad50(1, rname + 2, ext);
5724879Ssam 	/*
5734879Ssam 	 * Jam name and extension together with a dot
5744879Ssam 	 * deleting white space
5754879Ssam 	 */
5764879Ssam 	for (cp = name; *cp++;)
5774879Ssam 		;
5784879Ssam 	--cp;
5794879Ssam 	while (*--cp == ' ' && cp >= name)
5804879Ssam 		;
5814879Ssam 	*++cp = '.';
5824879Ssam 	cp++;
5834879Ssam 	for (cp2 = ext; *cp2 != ' ' && cp2 < ext+3;)
584954Sbill 		*cp++ = *cp2++;
585954Sbill 	*cp=0;
5864879Ssam 	if (cp[-1] == '.')
5874879Ssam 		cp[-1] = 0;
588954Sbill }
589954Sbill 
590954Sbill static char *val = " abcdefghijklmnopqrstuvwxyz$.@0123456789";
5914879Ssam 
592954Sbill static char table[256] = {
593954Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
594954Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
595954Sbill 0, 29, 29, 29, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 29,
596954Sbill 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 29, 29, 29, 29, 29, 29,
597954Sbill 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
598954Sbill 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
599954Sbill 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
600954Sbill 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
601954Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
602954Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
603954Sbill 0, 29, 29, 29, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 29,
604954Sbill 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 29, 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, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
608954Sbill 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29 };
609954Sbill 
6104879Ssam /*
6114879Ssam  * Logical to physical adress translation
6124879Ssam  */
6134879Ssam long
6144879Ssam trans(logical)
6154879Ssam 	register int logical;
616954Sbill {
617954Sbill 	register int sector, bytes, track;
618954Sbill 
6194879Ssam 	logical += 26*128;
6204879Ssam 	bytes = (logical&127);
621954Sbill 	logical >>= 7;
6224879Ssam 	sector = logical%26;
623954Sbill 	if(sector >= 13)
6244879Ssam 		sector = sector*2+1;
625954Sbill 	else
626954Sbill 		sector *= 2;
6274879Ssam 	sector += 26 + ((track = (logical/26))-1)*6;
628954Sbill 	sector %= 26;
6299877Ssam 	return ((((track*26)+sector) << 7) + bytes);
630954Sbill }
6314879Ssam 
6324879Ssam lread(startad, count, obuff)
6334879Ssam 	register startad, count;
6344879Ssam 	register char *obuff;
635954Sbill {
636954Sbill 	long trans();
637954Sbill 	extern floppydes;
6384879Ssam 	register int size = flag(m) ? 512 : 128;
639*29823Skarels 	int error = 0;
640*29823Skarels 	extern int errno;
6414879Ssam 
642954Sbill 	rt_init();
6434879Ssam 	while ((count -= size) >= 0) {
64426131Sbloom 		(void) lseek(floppydes, flag(m) ?
6454879Ssam 			(long)startad : trans(startad), 0);
646*29823Skarels 		if (read(floppydes, obuff, size) != size) {
647*29823Skarels 			error = errno;
648*29823Skarels 			fprintf(stderr, "arff: read error block %d: ",
6494879Ssam 				startad/size);
650*29823Skarels 			errno = error;
651*29823Skarels 			perror("");
652*29823Skarels 		}
6534879Ssam 		obuff += size;
6544879Ssam 		startad += size;
6554879Ssam 	}
656*29823Skarels 	return (error);
657954Sbill }
6584879Ssam 
6594879Ssam lwrite(startad, count, obuff)
6604879Ssam 	register startad, count;
6614879Ssam 	register char *obuff;
662954Sbill {
663954Sbill 	long trans();
664954Sbill 	extern floppydes;
6654879Ssam 	register int size = flag(m) ? 512 : 128;
6664879Ssam 
667954Sbill 	rt_init();
6684879Ssam 	while ((count -= size) >= 0) {
66926131Sbloom 		(void) lseek(floppydes, flag(m) ?
6704879Ssam 			(long)startad : trans(startad), 0);
6714879Ssam 		if (write(floppydes, obuff, size) != size)
6724879Ssam 			fprintf(stderr, "arff: write error block %d\n",
6734879Ssam 				startad/size);
6744879Ssam 		obuff += size;
6754879Ssam 		startad += size;
6764879Ssam 	}
677954Sbill }
678954Sbill 
679954Sbill rcmd()
680954Sbill {
681954Sbill 	register int i;
682954Sbill 
683954Sbill 	rt_init();
6844879Ssam 	if (namc > 0)
6854879Ssam 		for (i = 0; i < namc; i++)
6864879Ssam 			if (rtr(namv[i]) == 0)
6874879Ssam 				namv[i] = 0;
688954Sbill }
689954Sbill 
690954Sbill rtr(name)
6914879Ssam 	char *name;
692954Sbill {
6934879Ssam 	register FLDOPE *dope;
6944879Ssam 	register struct rt_ent *de;
6954879Ssam 	struct stat buf;
6964879Ssam 	register struct stat *bufp = &buf;
6973346Swnj 	int segnum;
69826131Sbloom 	char type;
699954Sbill 
7004879Ssam 	if (stat(name, bufp) < 0) {
7013489Sroot 		perror(name);
7029877Ssam 		return (-1);
7033489Sroot 	}
70426131Sbloom 	type = 'a';
7054879Ssam 	if (dope = lookup(name)) {
706954Sbill 		/* can replace, no problem */
707954Sbill 		de = dope->rtdope;
70826131Sbloom 		if (bufp->st_size <= (de->rt_len * 512)) {
70926131Sbloom 			printf("r - %s\n",name);
7104879Ssam 			toflop(name, bufp->st_size, dope);
71126131Sbloom 			goto found;
71226131Sbloom 		} else {
71326131Sbloom 			de = dope->rtdope;
71426131Sbloom 			type = 'r';
71526131Sbloom 			de->rt_stat = RT_NULL;
71626131Sbloom 			de->rt_name[0] = 0;
71726131Sbloom 			de->rt_name[1] = 0;
71826131Sbloom 			de->rt_name[2] = 0;
71926131Sbloom 			*((u_short *)&(de->rt_date)) = 0;
72026131Sbloom 			scrunch();
721954Sbill 		}
7229877Ssam 	}
7239877Ssam 	/*
7249877Ssam 	 * Search for vacant spot
7259877Ssam 	 */
7269877Ssam 	for (segnum = 0; segnum != -1;
72726131Sbloom 	     segnum = rt_dir[segnum].rd_nxtseg - 1)
7289877Ssam 	{
7299877Ssam 		for (de = rt_dir[segnum].rt_ents;
7309877Ssam 		    rt(de)->rt_stat != RT_ESEG; de++)
7319877Ssam 			if ((de)->rt_stat == RT_NULL) {
7329877Ssam 				if (bufp->st_size <= (de->rt_len*512)) {
73326131Sbloom 					printf("%c - %s\n", type, name),
7349877Ssam 					mkent(de, segnum, bufp,name);
7359877Ssam 					goto found;
736954Sbill 				}
7379877Ssam 				continue;
7389877Ssam 			}
739954Sbill 	}
74026131Sbloom 	if (type = 'r')
74126131Sbloom 		printf("%s: no slot for file, file deleted\n",name);
74226131Sbloom 	else
74326131Sbloom 		printf("%s: no slot for file\n", name);
7449877Ssam 	return (-1);
7454879Ssam 
7464879Ssam found:
7474879Ssam 	if (dope = lookup(name)) {
7484879Ssam 		toflop(name, bufp->st_size, dope);
7493489Sroot 		return (0);
750954Sbill 	}
7513489Sroot 	printf("%s: internal error, added then not found\n", name);
7523489Sroot 	return (-1);
7534879Ssam }
754954Sbill 
7554879Ssam mkent(de, segnum, bufp, name)
7564879Ssam 	register struct rt_ent *de;
7574879Ssam 	int segnum;
7584879Ssam 	register struct stat *bufp;
7594879Ssam 	char *name;
760954Sbill {
7614879Ssam 	struct tm *localtime();
7624879Ssam 	register struct tm *timp;
7634879Ssam 	register struct rt_ent *workp;
7644879Ssam 	int count;
765954Sbill 
766954Sbill 	count = (((bufp->st_size -1) >>9) + 1);
7674879Ssam 	/* make sure there is room */
7684879Ssam 	if (de->rt_len == count)
769954Sbill 		goto overwrite;
7704879Ssam 	if ((char *)rt_curend[segnum] == (rt_last + (segnum*2*RT_BLOCK))) {
77126131Sbloom 		/* no entries left on segment, trying adding new segment */
77226131Sbloom 		if (rt_dir[0].rd_numseg > rt_dir[0].rd_lstseg) {
77326131Sbloom 			short newseg;
77426131Sbloom 			register int i;
77526131Sbloom 			int maxseg;
77626131Sbloom 			short size;
77726131Sbloom 
77826131Sbloom 			newseg = rt_dir[0].rd_lstseg++;
77926131Sbloom 			rt_dir[newseg] = rt_nulldir;
78026131Sbloom 			rt_dir[newseg].rd_nxtseg = rt_dir[segnum].rd_nxtseg;
78126131Sbloom 			rt_dir[segnum].rd_nxtseg = newseg + 1;
78226131Sbloom 			rt_dir[newseg].rd_entpad = rt_dir[0].rd_entpad;
78326131Sbloom 			rt_dir[newseg].rd_numseg = rt_dir[0].rd_numseg;
78426131Sbloom 			size = 0;
78526131Sbloom 			maxseg = 0;
78626131Sbloom 			for(i = newseg - 1; i >= 0; i--) {
78726131Sbloom 				workp = rt_curend[i] - 1;
78826131Sbloom 				if (workp->rt_stat != RT_NULL)
78926131Sbloom 					continue;
79026131Sbloom 				if (workp->rt_len < size)
79126131Sbloom 					continue;
79226131Sbloom 				size = workp->rt_len;
79326131Sbloom 				maxseg = i;
79426131Sbloom 			}
79526131Sbloom 			size = 0;
79626131Sbloom 			for (workp = &rt_dir[maxseg].rt_ents[0];
79726131Sbloom 			    workp->rt_stat != RT_ESEG; workp++) {
79826131Sbloom 				size += workp->rt_len;
79926131Sbloom 			}
80026131Sbloom 			workp--;
80126131Sbloom 			rt_dir[newseg].rt_ents[0].rt_len = workp->rt_len;
80226131Sbloom 			rt_dir[newseg].rd_stfile =
80326131Sbloom 			    rt_dir[maxseg].rd_stfile + size - workp->rt_len;
80426131Sbloom 			workp->rt_len = 0;
80526131Sbloom 			rt_curend[newseg] = &rt_dir[newseg].rt_ents[1];
80626131Sbloom 			lwrite(6*RT_BLOCK, 2*RT_BLOCK, (char *)&rt_dir[0]);
80726131Sbloom 			if (segnum != 0)
80826131Sbloom 				lwrite((6+segnum*2)*RT_BLOCK, 2*RT_BLOCK,
80926131Sbloom 				    (char *)&rt_dir[segnum]);
81026131Sbloom 			lwrite((6+newseg*2)*RT_BLOCK, 2*RT_BLOCK,
81126131Sbloom 			    (char *)&rt_dir[newseg]);
81226131Sbloom 			segnum = newseg;
81326131Sbloom 			de = &rt_dir[newseg].rt_ents[0];
81426131Sbloom 		} else {
81526131Sbloom 			fprintf(stderr, "All directory segments full on  %s\n",
81626131Sbloom 				defdev);
81726131Sbloom 			exit(1);
81826131Sbloom 		}
819954Sbill 	}
8204879Ssam 	/* copy directory entries up */
8214879Ssam 	for (workp = rt_curend[segnum]+1; workp > de; workp--)
822954Sbill 		*workp = workp[-1];
823954Sbill 	de[1].rt_len -= count;
824954Sbill 	de->rt_len = count;
8253346Swnj 	rt_curend[segnum]++;
826954Sbill 	rt_nleft--;
8274879Ssam 
828954Sbill overwrite:
829954Sbill 	srad50(name,de->rt_name);
830954Sbill 	timp = localtime(&bufp->st_mtime);
8317320Swnj 	de->rt_date.rt_dy = timp->tm_mday;
832954Sbill 	de->rt_date.rt_mo = timp->tm_mon + 1;
833954Sbill 	de->rt_date.rt_yr = timp->tm_year - 72;
834954Sbill 	de->rt_stat = RT_FILE;
835954Sbill 	de->rt_pad = 0;
836954Sbill 	de->rt_chan = 0;
837954Sbill 	de->rt_job = 0;
8384879Ssam 	lwrite((6+segnum*2)*RT_BLOCK, 2*RT_BLOCK, (char *)&rt_dir[segnum]);
839954Sbill }
840954Sbill 
8414879Ssam toflop(name, ocount, dope)
8424879Ssam 	char *name;
8434879Ssam 	register FLDOPE *dope;
8444879Ssam 	long ocount;
845954Sbill {
846954Sbill 	register file, n, startad = dope->startad, count = ocount;
847954Sbill 	char buff[512];
848954Sbill 
8494879Ssam 	file = open(name, 0);
8504879Ssam 	if (file < 0) {
8514879Ssam 		fprintf(stderr, "arff: couldn't open %s\n",name);
8524879Ssam 		exit(1);
8534879Ssam 	}
854954Sbill 	for( ; count >= 512; count -= 512) {
85526131Sbloom 		(void) read(file, buff, 512);
8564879Ssam 		lwrite(startad, 512, buff);
857954Sbill 		startad += 512;
858954Sbill 	}
85926131Sbloom 	(void) read(file, buff, count);
86026131Sbloom 	(void) close(file);
8614879Ssam 	if (count <= 0)
8624879Ssam 		return;
8634879Ssam 	for (n = count; n < 512; n ++)
8644879Ssam 		buff[n] = 0;
8654879Ssam 	lwrite(startad, 512, buff);
8664879Ssam 	count = (dope->rtdope->rt_len*512-ocount)/512 ;
8674879Ssam 	if (count <= 0)
8684879Ssam 		return;
8694879Ssam 	for ( ; count > 0 ; count--) {
870954Sbill 		startad += 512;
8714879Ssam 		lwrite(startad, 512, zeroes);
872954Sbill 	}
8734879Ssam }
874954Sbill 
875954Sbill dcmd()
876954Sbill {
877954Sbill 	register int i;
878954Sbill 
879954Sbill 	rt_init();
8804879Ssam 	if (namc)
8814879Ssam 		for (i = 0; i < namc; i++)
8824879Ssam 			if (rtk(namv[i])==0)
8834879Ssam 				namv[i]=0;
8844879Ssam 	if (dirdirty)
885954Sbill 		scrunch();
886954Sbill }
8874879Ssam 
888954Sbill rtk(name)
8894879Ssam 	char *name;
890954Sbill {
891954Sbill 	register FLDOPE *dope;
892954Sbill 	register struct rt_ent *de;
893954Sbill 	FLDOPE *lookup();
894954Sbill 
8954879Ssam 	if (dope = lookup(name)) {
896954Sbill 		printf("d - %s\n",name);
897954Sbill 		de = dope->rtdope;
898954Sbill 		de->rt_stat = RT_NULL;
899954Sbill 		de->rt_name[0] = 0;
900954Sbill 		de->rt_name[1] = 0;
901954Sbill 		de->rt_name[2] = 0;
9029877Ssam 		*((u_short *)&(de->rt_date)) = 0;
903954Sbill 		dirdirty = 1;
9049877Ssam 		return (0);
905954Sbill 	}
9069877Ssam 	return (1);
907954Sbill }
9084879Ssam 
9094879Ssam scrunch()
9104879Ssam {
9113346Swnj 	register struct rt_ent *de , *workp;
9123346Swnj 	register segnum;
9134879Ssam 
9144879Ssam 	for (segnum = 0; segnum != -1;
91526131Sbloom 	     segnum = rt_dir[segnum].rd_nxtseg - 1) {
9164879Ssam 		for (de = rt_dir[segnum].rt_ents; de <= rt_curend[segnum]; de++)
9179877Ssam 			if (de->rt_stat == RT_NULL &&
91812012Shelge 			    (de+1)->rt_stat == RT_NULL) {
9194879Ssam 				(de+1)->rt_len += de->rt_len;
92012012Shelge 				for (workp=de; workp<rt_curend[segnum]; workp++)
9214879Ssam 					*workp = workp[1];
9224879Ssam 				de--;
9234879Ssam 				rt_curend[segnum]--;
9244879Ssam 				rt_nleft++;
9254879Ssam 			}
92612012Shelge 		lwrite((6+segnum*2)*RT_BLOCK, 2*RT_BLOCK,
92712012Shelge 			(char *)&rt_dir[segnum]);
928954Sbill 	}
92912012Shelge 	dirdirty = 0;
930954Sbill }
931