xref: /csrg-svn/old/arff/arff.c (revision 4879)
1*4879Ssam static	char *sccsid = "@(#)arff.c	4.8 (Berkeley) 81/11/13";
2*4879Ssam 
3954Sbill #include <sys/types.h>
4954Sbill #include <sys/stat.h>
5954Sbill #include <time.h>
6954Sbill #include <signal.h>
7954Sbill #include <stdio.h>
8*4879Ssam 
9954Sbill #define dbprintf printf
10*4879Ssam 
11954Sbill struct rt_dat {
12*4879Ssam 	u_short	rt_yr:5;	/* year-1972 */
13*4879Ssam 	u_short	rt_dy:5;	/* day */
14*4879Ssam 	u_short	rt_mo:5;	/* month */
15954Sbill };
16*4879Ssam 
17954Sbill struct	rt_axent {
18954Sbill 	char	rt_sent[14];
19954Sbill };
20954Sbill 
21954Sbill struct rt_ent {
22*4879Ssam 	char	rt_pad;		/* unusued */
23*4879Ssam 	char	rt_stat;	/* type of entry, or end of seg */
24*4879Ssam 	u_short	rt_name[3];	/* name, 3 words in rad50 form */
25*4879Ssam 	short	rt_len;		/* length of file */
26*4879Ssam 	char	rt_chan;	/* only used in temporary files */
27*4879Ssam 	char	rt_job;		/* only used in temporary files */
28*4879Ssam 	struct rt_dat rt_date;	/* creation date */
29954Sbill };
30*4879Ssam 
31*4879Ssam #define RT_TEMP		1
32*4879Ssam #define RT_NULL		2
33*4879Ssam #define RT_FILE		4
34*4879Ssam #define RT_ESEG		8
35*4879Ssam 
36*4879Ssam #define RT_BLOCK	512	/* block size */
37*4879Ssam #define RT_DIRSIZE	31	/* max # of directory segments */
38*4879Ssam 
39954Sbill struct rt_head {
40*4879Ssam 	short	rt_numseg;	/* # of segments available */
41*4879Ssam 	short	rt_nxtseg;	/* # of next logical segment */
42*4879Ssam 	short	rt_lstseg;	/* highest seg currently open */
43*4879Ssam 	u_short	rt_entpad;	/* extra words/directory entry */
44*4879Ssam 	short	rt_stfile;	/* block # where files begin */
45954Sbill };
46*4879Ssam 
47954Sbill struct	rt_dir {
48954Sbill 	struct rt_head	rt_axhead;
49954Sbill 	struct rt_ent	rt_ents[72];
50*4879Ssam 	char		_dirpad[6];
51954Sbill };
52*4879Ssam 
533346Swnj extern struct rt_dir	rt_dir[RT_DIRSIZE];
54954Sbill extern int		rt_entsiz;
55954Sbill extern int		floppydes;
56954Sbill extern char		*rt_last;
57*4879Ssam 
58954Sbill typedef struct fldope {
59954Sbill 	int	startad;
60954Sbill 	int	count;
61954Sbill struct	rt_ent	*rtdope;
62954Sbill } FLDOPE;
63*4879Ssam 
64954Sbill FLDOPE *lookup();
65*4879Ssam 
66954Sbill #define rt(p) ((struct rt_ent *) p )
67954Sbill #define Ain1 03100
68954Sbill #define Ain2 050
69*4879Ssam #define flag(c) (flg[('c') - 'a'])
70954Sbill 
71*4879Ssam char *man = "rxtd";
72*4879Ssam char zeroes[512];
73954Sbill 
74954Sbill extern char *val;
75954Sbill extern char table[256];
76*4879Ssam struct rt_dir rt_dir[RT_DIRSIZE] = {
77*4879Ssam 	{4, 0, 1, 0, 14},
78*4879Ssam 	{ {0, RT_NULL, {0, 0, 0}, 494, 0}, {0, RT_ESEG} }
79*4879Ssam };
80954Sbill 
81*4879Ssam int	rt_entsiz;
82*4879Ssam int	rt_nleft;
83*4879Ssam struct rt_ent *rt_curend[RT_DIRSIZE];
84*4879Ssam int	floppydes;
85*4879Ssam int	dirdirty;
86*4879Ssam char	*rt_last;
87*4879Ssam char	*defdev = "/dev/floppy";
88954Sbill 
89*4879Ssam char *opt = "vf";
90*4879Ssam 
91954Sbill int	signum[] = {SIGHUP, SIGINT, SIGQUIT, 0};
92*4879Ssam extern long lseek();
93*4879Ssam int	rcmd(), dcmd(), xcmd(), tcmd();
94*4879Ssam 
95954Sbill int	(*comfun)();
96954Sbill char	flg[26];
97954Sbill char	**namv;
98954Sbill int	namc;
99954Sbill int	file;
100954Sbill 
101954Sbill main(argc, argv)
102*4879Ssam 	char *argv[];
103954Sbill {
104954Sbill 	register char *cp;
105954Sbill 
106*4879Ssam 	if (argc < 2)
107954Sbill 		usage();
108954Sbill 	cp = argv[1];
109*4879Ssam 	for (cp = argv[1]; *cp; cp++)
110*4879Ssam 		switch (*cp) {
111954Sbill 
112*4879Ssam 		case 'm':
113*4879Ssam 		case 'v':
114*4879Ssam 		case 'u':
115*4879Ssam 		case 'w':
116*4879Ssam 			flg[*cp-'a']++;
117*4879Ssam 			continue;
118*4879Ssam 		case 'c':
119*4879Ssam 			{
120*4879Ssam #define SURE	"Last chance before clobbering floppy?"
121*4879Ssam 				int tty;
122*4879Ssam 				char response[128];
123954Sbill 
124*4879Ssam 				tty = open("/dev/tty", 2);
125*4879Ssam 				write(tty, SURE, sizeof(SURE));
126*4879Ssam 				read(tty, response, sizeof(response));
127*4879Ssam 				if (*response != 'y')
128*4879Ssam 					exit(50);
129*4879Ssam 				flag(c)++;
130*4879Ssam 				close(tty);
131*4879Ssam 			}
132*4879Ssam 			dirdirty++;
133*4879Ssam 			continue;
134954Sbill 
135*4879Ssam 		case 'r':
136*4879Ssam 			setcom(rcmd);
137*4879Ssam 			flag(r)++;
138*4879Ssam 			continue;
139954Sbill 
140*4879Ssam 		case 'd':
141*4879Ssam 			setcom(dcmd);
142*4879Ssam 			flag(d)++;
143*4879Ssam 			continue;
144954Sbill 
145*4879Ssam 		case 'x':
146*4879Ssam 			setcom(xcmd);
147*4879Ssam 			continue;
148954Sbill 
149*4879Ssam 		case 't':
150*4879Ssam 			setcom(tcmd);
151*4879Ssam 			continue;
152954Sbill 
153*4879Ssam 		case 'f':
154*4879Ssam 			defdev = argv[2];
155*4879Ssam 			argv++;
156*4879Ssam 			argc--;
157*4879Ssam 			continue;
158*4879Ssam 
159*4879Ssam 		default:
160*4879Ssam 			fprintf(stderr, "arff: bad option `%c'\n", *cp);
161*4879Ssam 			exit(1);
162*4879Ssam 		}
163*4879Ssam 
164954Sbill 	namv = argv+2;
165954Sbill 	namc = argc-2;
166*4879Ssam 	if (comfun == 0) {
167*4879Ssam 		if (flag(u) == 0) {
168*4879Ssam 			fprintf(stderr, "arff: one of [%s] must be specified\n",
169*4879Ssam 				man);
170954Sbill 			exit(1);
171954Sbill 		}
172954Sbill 		setcom(rcmd);
173954Sbill 	}
174954Sbill 	(*comfun)();
175954Sbill 	exit(notfound());
176954Sbill }
177954Sbill 
178954Sbill setcom(fun)
179*4879Ssam 	int (*fun)();
180954Sbill {
181*4879Ssam 	if (comfun != 0) {
182954Sbill 		fprintf(stderr, "arff: only one of [%s] allowed\n", man);
183954Sbill 		exit(1);
184954Sbill 	}
185954Sbill 	comfun = fun;
186954Sbill }
187954Sbill 
188954Sbill usage()
189954Sbill {
1903356Swnj 	fprintf(stderr, "usage: ar [%s][%s] archive files ...\n", opt, man);
191954Sbill 	exit(1);
192954Sbill }
193954Sbill 
194954Sbill notfound()
195954Sbill {
196*4879Ssam 	register i, n = 0;
197954Sbill 
198*4879Ssam 	for (i = 0; i < namc; i++)
199*4879Ssam 		if (namv[i]) {
200954Sbill 			fprintf(stderr, "arff: %s not found\n", namv[i]);
201954Sbill 			n++;
202954Sbill 		}
203954Sbill 	return(n);
204954Sbill }
205954Sbill 
206954Sbill mesg(c)
207954Sbill {
208*4879Ssam 	if (flag(v))
209*4879Ssam 		if (c != 'c' || flag(v) > 1)
210954Sbill 			printf("%c - %s\n", c, file);
211954Sbill }
212954Sbill 
213954Sbill tcmd()
214954Sbill {
215*4879Ssam 	register char *de, *last;
216954Sbill 	FLDOPE *lookup(), *dope;
217*4879Ssam 	int segnum, nleft;
218*4879Ssam 	register i;
219954Sbill 	register struct rt_ent *rde;
220954Sbill 
221954Sbill 	rt_init();
222*4879Ssam 	if (namc == 0)
223*4879Ssam 		for (segnum = 0; segnum != -1;
224*4879Ssam 		     segnum = rt_dir[segnum].rt_axhead.rt_nxtseg - 1)
225*4879Ssam 		{
226*4879Ssam 			last = rt_last + segnum*2*RT_BLOCK;
227*4879Ssam 			for (de = ((char *)&rt_dir[segnum])+10; de <= last;
228*4879Ssam 			    de += rt_entsiz)
229*4879Ssam 				if (rtls(rt(de))) {
230*4879Ssam 					nleft = (last-de)/rt_entsiz;
231*4879Ssam #define ENTRIES "\n%d entries remaining in directory segment %d.\n"
232*4879Ssam 					printf(ENTRIES, nleft, segnum+1);
233*4879Ssam 					break;
234*4879Ssam 				}
235954Sbill 		}
236954Sbill 	else
237*4879Ssam 		for (i = 0; i < namc; i++)
238*4879Ssam 			if (dope = lookup(namv[i])) {
239954Sbill 				rde = dope->rtdope;
240954Sbill 				rtls(rde);
241954Sbill 				namv[i] = 0;
242954Sbill 			}
243954Sbill }
244*4879Ssam 
245954Sbill rtls(de)
246*4879Ssam 	register struct rt_ent *de;
247954Sbill {
248*4879Ssam 	int month, day, year;
249954Sbill 	char name[12], ext[4];
250954Sbill 
251*4879Ssam 	switch (de->rt_stat) {
252*4879Ssam 
253*4879Ssam 	case RT_TEMP:
254*4879Ssam 		if (flag(v))
255954Sbill 			printf("Tempfile:\n");
256*4879Ssam 		/* fall thru...*/
257954Sbill 
258*4879Ssam 	case RT_FILE:
259*4879Ssam 		if (!flag(v)) {
260*4879Ssam 			sunrad50(name, de->rt_name);
261*4879Ssam 			printf("%s\n", name);
262954Sbill 			break;
263954Sbill 		}
264*4879Ssam 		unrad50(2, de->rt_name, name);
265*4879Ssam 		unrad50(1, &(de->rt_name[2]), ext);
266*4879Ssam 		day = de->rt_date.rt_dy;
267*4879Ssam 		year = de->rt_date.rt_yr+72;
268*4879Ssam 		month = de->rt_date.rt_mo;
269*4879Ssam 		printf("%6.6s  %3.3s	%02d/%02d/%02d	%d\n",name,
270*4879Ssam 			ext, month, day, year, de->rt_len);
271*4879Ssam 		break;
272954Sbill 
273*4879Ssam 	case RT_NULL:
274*4879Ssam 		printf("%-25.9s	%d\n","<UNUSED>", de->rt_len);
275*4879Ssam 		break;
276954Sbill 
277*4879Ssam 	case RT_ESEG:
278*4879Ssam 		return(1);
279954Sbill 	}
280954Sbill 	return(0);
281954Sbill }
282*4879Ssam 
283954Sbill xcmd()
284954Sbill {
285*4879Ssam 	register char *de, *last;
2863346Swnj 	int segnum;
287954Sbill 	char name[12];
288954Sbill 	register int i;
289954Sbill 
290954Sbill 	rt_init();
291*4879Ssam 	if (namc == 0)
292*4879Ssam 		for (segnum = 0; segnum != -1;
293*4879Ssam 		     segnum = rt_dir[segnum].rt_axhead.rt_nxtseg-1)
294*4879Ssam 			for (last = rt_last+(segnum*2*RT_BLOCK),
295*4879Ssam 			     de = ((char *)&rt_dir[segnum])+10; de <= last;
296*4879Ssam 			     de += rt_entsiz)
297*4879Ssam 				sunrad50(name, rt(de)->rt_name), rtx(name);
298954Sbill 	else
299*4879Ssam 		for (i = 0; i < namc; i++)
300*4879Ssam 			if (rtx(namv[i]) == 0)
301*4879Ssam 				namv[i] = 0;
302954Sbill }
303*4879Ssam 
304954Sbill rtx(name)
305*4879Ssam 	char *name;
306954Sbill {
307954Sbill 	register FLDOPE *dope;
308954Sbill 	FLDOPE *lookup();
309954Sbill 	register startad, count;
310*4879Ssam 	int file;
311*4879Ssam 	char buff[512];
312954Sbill 
313954Sbill 
314*4879Ssam 	if (dope = lookup(name)) {
315*4879Ssam 		if (flag(v))
316954Sbill 			rtls(dope->rtdope);
317954Sbill 		else
318954Sbill 			printf("x - %s\n",name);
319954Sbill 
320*4879Ssam 		if ((file = creat(name, 0666)) < 0)
321*4879Ssam 			return(1);
322954Sbill 		count = dope->count;
323954Sbill 		startad = dope->startad;
324954Sbill 		for( ; count > 0 ; count -= 512) {
325*4879Ssam 			lread(startad, 512, buff);
326*4879Ssam 			write(file, buff, 512);
327954Sbill 			startad += 512;
328954Sbill 		}
329954Sbill 		close(file);
330954Sbill 		return(0);
331954Sbill 	}
332954Sbill 	return(1);
333954Sbill }
334*4879Ssam 
335954Sbill rt_init()
336954Sbill {
337954Sbill 	static initized = 0;
338*4879Ssam 	register char *de, *last;
3393346Swnj 	register i;
3403799Shickman 	int dirnum;
3413799Shickman 	char *mode;
3423799Shickman 	FILE *temp_floppydes;
343954Sbill 
344*4879Ssam 	if (initized)
345*4879Ssam 		return;
346954Sbill 	initized = 1;
347*4879Ssam 	if (flag(c) || flag(d) || flag(r))
3483799Shickman 		mode = "r+";
349954Sbill 	else
3503799Shickman 		mode = "r";
351*4879Ssam 	if ((temp_floppydes = fopen(defdev, mode)) == NULL) {
3523799Shickman 		perror(defdev);
3533356Swnj 		exit(1);
3543799Shickman 	} else
3553799Shickman 		floppydes = fileno(temp_floppydes);
356*4879Ssam 	if (!flag(c)) {
357*4879Ssam 		lread(6*RT_BLOCK, 2*RT_BLOCK, (char *)&rt_dir[0]);
3583346Swnj 		dirnum = rt_dir[0].rt_axhead.rt_numseg;
3593346Swnj 		if (dirnum > RT_DIRSIZE) {
360*4879Ssam 			fprintf(stderr,"arff: too many directory segments\n");
361*4879Ssam 			exit(1);
3623346Swnj 		}
363*4879Ssam 		for (i = 1; i < dirnum; i++)
364*4879Ssam 			lread((6+2*i)*RT_BLOCK, 2*RT_BLOCK, (char *)&rt_dir[i]);
3653489Sroot 	} else
3663489Sroot 		dirnum = 1;
367954Sbill 
3683346Swnj 	rt_entsiz = 2*rt_dir[0].rt_axhead.rt_entpad + 14;
3693346Swnj 	rt_entsiz = 14;			/* assume rt_entpad = 0 ??? */
3703346Swnj 	rt_last = ((char *) &rt_dir[0]) + 10 + 1014/rt_entsiz*rt_entsiz;
3713346Swnj 	rt_nleft = 0;
3723346Swnj 
373*4879Ssam 	for (i = 0; i < dirnum; i++) {
374*4879Ssam 		last = rt_last + i*2*RT_BLOCK;
375*4879Ssam 		for (de = ((char *)&rt_dir[i])+10; de <= last; de += rt_entsiz)
376*4879Ssam 			if (rt(de)->rt_stat == RT_ESEG)
377*4879Ssam 				break;
378*4879Ssam 		rt_curend[i] = rt(de);
379*4879Ssam 		rt_nleft += (last-de)/rt_entsiz;
380954Sbill 	}
381954Sbill }
382954Sbill 
383954Sbill static FLDOPE result;
384*4879Ssam 
385954Sbill FLDOPE *
386954Sbill lookup(name)
387*4879Ssam 	char *name;
388954Sbill {
389954Sbill 	unsigned short rname[3];
390*4879Ssam 	register char *de, *last;
3913346Swnj 	int segnum;
392954Sbill 	register index;
393954Sbill 
394954Sbill 	srad50(name,rname);
395954Sbill 
3963356Swnj 	/*
397954Sbill 	 *  Search for name, accumulate blocks in index
398954Sbill 	 */
399954Sbill 	rt_init();
400*4879Ssam 	for (segnum = 0; segnum != -1;
401*4879Ssam 	     segnum = rt_dir[segnum].rt_axhead.rt_nxtseg - 1)
402*4879Ssam 	{
403*4879Ssam 		index = 0;
404*4879Ssam 		last = rt_last + segnum*2*RT_BLOCK;
405*4879Ssam 		for (de=((char *)&rt_dir[segnum])+10;
406*4879Ssam 		     rt(de)->rt_stat != RT_ESEG; de += rt_entsiz)
407*4879Ssam 			switch(rt(de)->rt_stat) {
408*4879Ssam 
409*4879Ssam 			case RT_FILE:
410*4879Ssam 			case RT_TEMP:
411*4879Ssam 				if(samename(rname,rt(de)->rt_name)) {
412*4879Ssam 					result.count = rt(de)->rt_len * 512;
413*4879Ssam 					result.startad = 512*
414*4879Ssam 						(rt_dir[segnum].rt_axhead.rt_stfile + index);
415*4879Ssam 					result.rtdope = (struct rt_ent *) de;
416*4879Ssam 					return(&result);
417*4879Ssam 				}
418*4879Ssam 
419*4879Ssam 			case RT_NULL:
420*4879Ssam 				index += rt(de)->rt_len;
421*4879Ssam 			}
4223346Swnj         }
423954Sbill 	return((FLDOPE *) 0);
424*4879Ssam 
425954Sbill }
426*4879Ssam 
427954Sbill static
428*4879Ssam samename(a, b)
429*4879Ssam 	u_short a[], b[];
430954Sbill {
431*4879Ssam 	return(*a == *b && a[1] == b[1] && a[2] == b[2] );
432954Sbill }
433954Sbill 
434*4879Ssam rad50(cp, out)
435*4879Ssam 	register u_char *cp;
436*4879Ssam 	u_short *out;
437954Sbill {
438*4879Ssam 	register index, temp;
439954Sbill 
440*4879Ssam 	for (index = 0; *cp; index++) {
441954Sbill 		temp = Ain1 * table[*cp++];
442*4879Ssam 		if (*cp!=0) {
443954Sbill 			temp += Ain2 * table[*cp++];
444954Sbill 			if(*cp!=0)
445954Sbill 				temp += table[*cp++];
446954Sbill 		}
447954Sbill 		out[index] = temp;
448954Sbill 	}
449954Sbill }
450954Sbill 
451*4879Ssam #define reduce(x, p, q) (x = v[p/q], p %= q);
452*4879Ssam 
453*4879Ssam unrad50(count, in, cp)
454*4879Ssam 	u_short *in;
455*4879Ssam 	register char *cp;
456954Sbill {
457*4879Ssam 	register i, temp;
458*4879Ssam 	register u_char *v = (u_char *) val;
459954Sbill 
460*4879Ssam 	for (i = 0; i < count; i++) {
461954Sbill 		temp = in[i];
462*4879Ssam 		reduce(*cp++, temp, Ain1);
463*4879Ssam 		reduce(*cp++, temp, Ain2);
464*4879Ssam 		reduce(*cp++, temp, 1);
465954Sbill 	}
466954Sbill 	*cp=0;
467954Sbill }
468954Sbill 
469*4879Ssam srad50(name, rname)
470*4879Ssam 	register char *name;
471*4879Ssam 	register u_short *rname;
472954Sbill {
473*4879Ssam 	register index;
474*4879Ssam 	register char *cp;
475*4879Ssam 	char file[7], ext[4];
476*4879Ssam 
4773356Swnj 	/*
478954Sbill 	 * Find end of pathname
479954Sbill 	 */
480*4879Ssam 	for (cp = name; *cp++; )
481*4879Ssam 		;
482*4879Ssam 	while (cp >= name && *--cp != '/')
483*4879Ssam 		;
484954Sbill 	cp++;
4853356Swnj 	/*
486954Sbill 	 * Change to rad50
487954Sbill 	 */
488*4879Ssam 	for (index = 0; *cp; ) {
489954Sbill 		file[index++] = *cp++;
490*4879Ssam 		if (*cp == '.') {
491954Sbill 			cp++;
492954Sbill 			break;
493954Sbill 		}
494*4879Ssam 		if (index >= 6) {
495954Sbill 			break;
496954Sbill 		}
497954Sbill 	}
498954Sbill 	file[index] = 0;
499*4879Ssam 	for (index = 0; *cp; ) {
500954Sbill 		ext[index++] = *cp++;
501*4879Ssam 		if (*cp == '.' || index >= 3)
502954Sbill 			break;
503954Sbill 	}
504954Sbill 	ext[index]=0;
505*4879Ssam 	rname[0] = rname[1] = rname[2] = 0;
506*4879Ssam 	rad50((u_char *)file, rname);
507*4879Ssam 	rad50((u_char *)ext, rname+2);
508954Sbill }
509*4879Ssam 
510*4879Ssam sunrad50(name, rname)
511*4879Ssam 	u_short rname[];
512*4879Ssam 	register char *name;
513954Sbill {
514954Sbill 	register char *cp, *cp2;
515954Sbill 	char ext[4];
516954Sbill 
517*4879Ssam 	unrad50(2, rname, name);
518*4879Ssam 	unrad50(1, rname + 2, ext);
519*4879Ssam 	/*
520*4879Ssam 	 * Jam name and extension together with a dot
521*4879Ssam 	 * deleting white space
522*4879Ssam 	 */
523*4879Ssam 	for (cp = name; *cp++;)
524*4879Ssam 		;
525*4879Ssam 	--cp;
526*4879Ssam 	while (*--cp == ' ' && cp >= name)
527*4879Ssam 		;
528*4879Ssam 	*++cp = '.';
529*4879Ssam 	cp++;
530*4879Ssam 	for (cp2 = ext; *cp2 != ' ' && cp2 < ext+3;)
531954Sbill 		*cp++ = *cp2++;
532954Sbill 	*cp=0;
533*4879Ssam 	if (cp[-1] == '.')
534*4879Ssam 		cp[-1] = 0;
535954Sbill }
536954Sbill 
537954Sbill static char *oval = " ABCDEFGHIJKLMNOPQRSTUVWXYZ$.@0123456789";
538954Sbill static char *val = " abcdefghijklmnopqrstuvwxyz$.@0123456789";
539*4879Ssam 
540954Sbill static char table[256] = {
541954Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
542954Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
543954Sbill 0, 29, 29, 29, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 29,
544954Sbill 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 29, 29, 29, 29, 29, 29,
545954Sbill 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
546954Sbill 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
547954Sbill 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
548954Sbill 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
549954Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
550954Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
551954Sbill 0, 29, 29, 29, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 29,
552954Sbill 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 29, 29, 29, 29, 29, 29,
553954Sbill 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
554954Sbill 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
555954Sbill 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
556954Sbill 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29 };
557954Sbill 
558*4879Ssam /*
559*4879Ssam  * Logical to physical adress translation
560*4879Ssam  */
561*4879Ssam long
562*4879Ssam trans(logical)
563*4879Ssam 	register int logical;
564954Sbill {
565954Sbill 	register int sector, bytes, track;
566954Sbill 
567*4879Ssam 	logical += 26*128;
568*4879Ssam 	bytes = (logical&127);
569954Sbill 	logical >>= 7;
570*4879Ssam 	sector = logical%26;
571954Sbill 	if(sector >= 13)
572*4879Ssam 		sector = sector*2+1;
573954Sbill 	else
574954Sbill 		sector *= 2;
575*4879Ssam 	sector += 26 + ((track = (logical/26))-1)*6;
576954Sbill 	sector %= 26;
577*4879Ssam 	return((((track*26)+sector) << 7) + bytes);
578954Sbill }
579*4879Ssam 
580*4879Ssam lread(startad, count, obuff)
581*4879Ssam 	register startad, count;
582*4879Ssam 	register char *obuff;
583954Sbill {
584954Sbill 	long trans();
585954Sbill 	extern floppydes;
586*4879Ssam 	register int size = flag(m) ? 512 : 128;
587*4879Ssam 
588954Sbill 	rt_init();
589*4879Ssam 	while ((count -= size) >= 0) {
590*4879Ssam 		lseek(floppydes, flag(m) ?
591*4879Ssam 			(long)startad : trans(startad), 0);
592*4879Ssam 		if (read(floppydes, obuff, size) != size)
593*4879Ssam 			fprintf(stderr, "arff: read error block %d\n",
594*4879Ssam 				startad/size);
595*4879Ssam 		obuff += size;
596*4879Ssam 		startad += size;
597*4879Ssam 	}
598954Sbill }
599*4879Ssam 
600*4879Ssam lwrite(startad, count, obuff)
601*4879Ssam 	register startad, count;
602*4879Ssam 	register char *obuff;
603954Sbill {
604954Sbill 	long trans();
605954Sbill 	extern floppydes;
606*4879Ssam 	register int size = flag(m) ? 512 : 128;
607*4879Ssam 
608954Sbill 	rt_init();
609*4879Ssam 	while ((count -= size) >= 0) {
610*4879Ssam 		lseek(floppydes, flag(m) ?
611*4879Ssam 			(long)startad : trans(startad), 0);
612*4879Ssam 		if (write(floppydes, obuff, size) != size)
613*4879Ssam 			fprintf(stderr, "arff: write error block %d\n",
614*4879Ssam 				startad/size);
615*4879Ssam 		obuff += size;
616*4879Ssam 		startad += size;
617*4879Ssam 	}
618954Sbill }
619954Sbill 
620954Sbill rcmd()
621954Sbill {
622954Sbill 	register int i;
623954Sbill 
624954Sbill 	rt_init();
625*4879Ssam 	if (namc > 0)
626*4879Ssam 		for (i = 0; i < namc; i++)
627*4879Ssam 			if (rtr(namv[i]) == 0)
628*4879Ssam 				namv[i] = 0;
629954Sbill }
630954Sbill 
631954Sbill rtr(name)
632*4879Ssam 	char *name;
633954Sbill {
634*4879Ssam 	register FLDOPE *dope;
635*4879Ssam 	register struct rt_ent *de;
636*4879Ssam 	struct stat buf;
637*4879Ssam 	register struct stat *bufp = &buf;
6383346Swnj 	int segnum;
6393346Swnj 	register char *last;
640954Sbill 
641*4879Ssam 	if (stat(name, bufp) < 0) {
6423489Sroot 		perror(name);
6433489Sroot 		return(-1);
6443489Sroot 	}
645*4879Ssam 	if (dope = lookup(name)) {
646954Sbill 		/* can replace, no problem */
647954Sbill 		de = dope->rtdope;
648*4879Ssam 		if (bufp->st_size <= (de->rt_len * 512))
649954Sbill 			printf("r - %s\n",name),
650*4879Ssam 			toflop(name, bufp->st_size, dope);
651954Sbill 		else {
6523356Swnj 			fprintf(stderr, "%s will not fit in currently used file on floppy\n",name);
6533489Sroot 			return(-1);
654954Sbill 		}
655954Sbill 	} else {
656*4879Ssam 		/* Search for vacant spot */
657*4879Ssam 		for (segnum = 0; segnum != -1;
658*4879Ssam 		     segnum = rt_dir[segnum].rt_axhead.rt_nxtseg - 1)
659*4879Ssam 		{
660*4879Ssam 			last = rt_last + segnum*2*RT_BLOCK;
661*4879Ssam 			for (de = rt_dir[segnum].rt_ents;
662*4879Ssam 			    rt(de)->rt_stat != RT_ESEG; de++)
663*4879Ssam 				if ((de)->rt_stat == RT_NULL) {
664*4879Ssam 					if (bufp->st_size <= (de->rt_len*512)) {
665*4879Ssam 						printf("a - %s\n",name),
666*4879Ssam 						mkent(de, segnum, bufp,name);
667*4879Ssam 						goto found;
668*4879Ssam 					}
669*4879Ssam 					continue;
670954Sbill 				}
6713346Swnj 	    }
6723489Sroot 	    printf("%s: no slot for file\n", name);
6733489Sroot 	    return (-1);
674954Sbill 	}
675*4879Ssam 
676*4879Ssam found:
677*4879Ssam 	if (dope = lookup(name)) {
678*4879Ssam 		toflop(name, bufp->st_size, dope);
6793489Sroot 		return (0);
680954Sbill 	}
6813489Sroot 	printf("%s: internal error, added then not found\n", name);
6823489Sroot 	return (-1);
683*4879Ssam }
684954Sbill 
685*4879Ssam mkent(de, segnum, bufp, name)
686*4879Ssam 	register struct rt_ent *de;
687*4879Ssam 	int segnum;
688*4879Ssam 	register struct stat *bufp;
689*4879Ssam 	char *name;
690954Sbill {
691*4879Ssam 	struct tm *localtime();
692*4879Ssam 	register struct tm *timp;
693*4879Ssam 	register struct rt_ent *workp;
694*4879Ssam 	int count;
695954Sbill 
696954Sbill 	count = (((bufp->st_size -1) >>9) + 1);
697*4879Ssam 	/* make sure there is room */
698*4879Ssam 	if (de->rt_len == count)
699954Sbill 		goto overwrite;
700*4879Ssam 	if ((char *)rt_curend[segnum] == (rt_last + (segnum*2*RT_BLOCK))) {
701*4879Ssam 		/* no entries left on segment */
702*4879Ssam 		if (flag(o))
703954Sbill 			goto overwrite;
7043346Swnj 		fprintf(stderr,"Directory segment #%d full on  %s\n",segnum+1,
705*4879Ssam 			defdev);
706954Sbill 		exit(1);
707954Sbill 	}
708*4879Ssam 	/* copy directory entries up */
709*4879Ssam 	for (workp = rt_curend[segnum]+1; workp > de; workp--)
710954Sbill 		*workp = workp[-1];
711954Sbill 	de[1].rt_len -= count;
712954Sbill 	de->rt_len = count;
7133346Swnj 	rt_curend[segnum]++;
714954Sbill 	rt_nleft--;
715*4879Ssam 
716954Sbill overwrite:
717954Sbill 	srad50(name,de->rt_name);
718954Sbill 	timp = localtime(&bufp->st_mtime);
719954Sbill 	de->rt_date.rt_dy = timp->tm_mday + 1;
720954Sbill 	de->rt_date.rt_mo = timp->tm_mon + 1;
721954Sbill 	de->rt_date.rt_yr = timp->tm_year - 72;
722954Sbill 	de->rt_stat = RT_FILE;
723954Sbill 	de->rt_pad = 0;
724954Sbill 	de->rt_chan = 0;
725954Sbill 	de->rt_job = 0;
726*4879Ssam 	lwrite((6+segnum*2)*RT_BLOCK, 2*RT_BLOCK, (char *)&rt_dir[segnum]);
727954Sbill }
728954Sbill 
729*4879Ssam toflop(name, ocount, dope)
730*4879Ssam 	char *name;
731*4879Ssam 	register FLDOPE *dope;
732*4879Ssam 	long ocount;
733954Sbill {
734954Sbill 	register file, n, startad = dope->startad, count = ocount;
735954Sbill 	char buff[512];
736954Sbill 
737*4879Ssam 	file = open(name, 0);
738*4879Ssam 	if (file < 0) {
739*4879Ssam 		fprintf(stderr, "arff: couldn't open %s\n",name);
740*4879Ssam 		exit(1);
741*4879Ssam 	}
742954Sbill 	for( ; count >= 512; count -= 512) {
743*4879Ssam 		read(file, buff, 512);
744*4879Ssam 		lwrite(startad, 512, buff);
745954Sbill 		startad += 512;
746954Sbill 	}
747*4879Ssam 	read(file, buff, count);
748954Sbill 	close(file);
749*4879Ssam 	if (count <= 0)
750*4879Ssam 		return;
751*4879Ssam 	for (n = count; n < 512; n ++)
752*4879Ssam 		buff[n] = 0;
753*4879Ssam 	lwrite(startad, 512, buff);
754*4879Ssam 	count = (dope->rtdope->rt_len*512-ocount)/512 ;
755*4879Ssam 	if (count <= 0)
756*4879Ssam 		return;
757*4879Ssam 	for ( ; count > 0 ; count--) {
758954Sbill 		startad += 512;
759*4879Ssam 		lwrite(startad, 512, zeroes);
760954Sbill 	}
761*4879Ssam }
762954Sbill 
763954Sbill dcmd()
764954Sbill {
765954Sbill 	register int i;
766954Sbill 
767954Sbill 	rt_init();
768*4879Ssam 	if (namc)
769*4879Ssam 		for (i = 0; i < namc; i++)
770*4879Ssam 			if (rtk(namv[i])==0)
771*4879Ssam 				namv[i]=0;
772*4879Ssam 	if (dirdirty)
773954Sbill 		scrunch();
774954Sbill }
775*4879Ssam 
776954Sbill rtk(name)
777*4879Ssam 	char *name;
778954Sbill {
779954Sbill 	register FLDOPE *dope;
780954Sbill 	register struct rt_ent *de;
781954Sbill 	FLDOPE *lookup();
782954Sbill 
783*4879Ssam 	if (dope = lookup(name)) {
784954Sbill 		printf("d - %s\n",name);
785954Sbill 		de = dope->rtdope;
786954Sbill 		de->rt_stat = RT_NULL;
787954Sbill 		de->rt_name[0] = 0;
788954Sbill 		de->rt_name[1] = 0;
789954Sbill 		de->rt_name[2] = 0;
790*4879Ssam 		* ((u_short *)&(de->rt_date)) = 0;
791954Sbill 		dirdirty = 1;
792954Sbill 		return(0);
793954Sbill 	}
794954Sbill 	return(1);
795954Sbill }
796*4879Ssam 
797*4879Ssam scrunch()
798*4879Ssam {
7993346Swnj 	register struct rt_ent *de , *workp;
8003346Swnj 	register segnum;
801*4879Ssam 
802*4879Ssam 	for (segnum = 0; segnum != -1;
8033346Swnj 	     segnum = rt_dir[segnum].rt_axhead.rt_nxtseg - 1) {
804*4879Ssam 		dirdirty = 0;
805*4879Ssam 		for (de = rt_dir[segnum].rt_ents; de <= rt_curend[segnum]; de++)
806*4879Ssam 			if (de->rt_stat == RT_NULL && de[1].rt_stat == RT_NULL) {
807*4879Ssam 				(de+1)->rt_len += de->rt_len;
808*4879Ssam 				for (workp = de; workp < rt_curend[segnum]; workp++)
809*4879Ssam 					*workp = workp[1];
810*4879Ssam 				de--;
811*4879Ssam 				rt_curend[segnum]--;
812*4879Ssam 				rt_nleft++;
813*4879Ssam 				dirdirty = 1;
814*4879Ssam 			}
815*4879Ssam 		if (dirdirty)
816*4879Ssam 			lwrite((6+segnum*2)*RT_BLOCK, 2*RT_BLOCK,
817*4879Ssam 				(char *)&rt_dir[segnum]);
818954Sbill 	}
819954Sbill }
820