|
|
1.1 root 1: static char *sccsid = "@(#)arff.c 4.2 (Berkeley) 11/3/80";
2: #include <sys/types.h>
3: #include <sys/stat.h>
4: #include <time.h>
5: #include <signal.h>
6: #include <stdio.h>
7: #define dbprintf printf
8: struct rt_dat {
9: unsigned short int rt_yr:5; /*Year - 1972 */
10: unsigned short int rt_dy:5; /*day */
11: unsigned short int rt_mo:5; /*month */
12: };
13: struct rt_axent {
14: char rt_sent[14];
15: };
16:
17: struct rt_ent {
18: char rt_pad; /*unusued */
19: char rt_stat; /*Type of entry, or end of seg*/
20: unsigned short rt_name[3]; /*Name, 3 words in rad50 form */
21: short rt_len; /*Length of file */
22: char rt_chan; /*Only used in temporary files*/
23: char rt_job; /*Only used in temporary files*/
24: struct rt_dat rt_date; /*Creation Date */
25: };
26: #define RT_TEMP 1
27: #define RT_NULL 2
28: #define RT_FILE 4
29: #define RT_ESEG 8
30: #define RT_BLOCK 512
31: struct rt_head {
32: short rt_numseg; /*number of segments available*/
33: short rt_nxtseg; /*segment no of next log. seg */
34: short rt_lstseg; /*highest seg currenltly open */
35: unsigned short rt_entpad; /*extra words/dir. entry */
36: short rt_stfile; /*block no where files begin */
37: };
38: struct rt_dir {
39: struct rt_head rt_axhead;
40: struct rt_ent rt_ents[72];
41: char _dirpad[6];
42: };
43: extern struct rt_dir rt_dir;
44: extern int rt_entsiz;
45: extern int floppydes;
46: extern char *rt_last;
47: typedef struct fldope {
48: int startad;
49: int count;
50: struct rt_ent *rtdope;
51: } FLDOPE;
52: FLDOPE *lookup();
53: #define rt(p) ((struct rt_ent *) p )
54: #define Ain1 03100
55: #define Ain2 050
56: #define flag(c) (flg[(c) - 'a'])
57:
58: char *man = { "rxtd" };
59:
60: char zeroes[512];
61: extern char *val;
62: extern char table[256];
63: struct rt_dir rt_dir = {{4,0,1,0,14},{0,RT_NULL,{0,0,0},494,0}, {0,RT_ESEG}};
64: int rt_entsiz;
65: int rt_nleft;
66: struct rt_ent *rt_curend;
67: int floppydes;
68: int dirdirty;
69: char *rt_last;
70: char *defdev = "/dev/floppy";
71:
72: char *opt = { "vf" };
73:
74: int signum[] = {SIGHUP, SIGINT, SIGQUIT, 0};
75: long lseek();
76: int rcmd();
77: int dcmd();
78: int xcmd();
79: int tcmd();
80: int (*comfun)();
81: char flg[26];
82: char **namv;
83: int namc;
84: int file;
85:
86:
87: main(argc, argv)
88: char *argv[];
89: {
90: register char *cp;
91:
92: /*register i;
93: for(i=0; signum[i]; i++)
94: if(signal(signum[i], SIG_IGN) != SIG_IGN)
95: signal(signum[i], sigdone);*/
96: if(argc < 2)
97: usage();
98: cp = argv[1];
99: for(cp = argv[1]; *cp; cp++)
100: switch(*cp) {
101: case 'm':
102: case 'v':
103: case 'u':
104: case 'w':
105: flg[*cp - 'a']++;
106: continue;
107: case 'c':
108: {
109: #define SURE "Are you sure you want to clobber the floppy?\n"
110: int tty;
111: char response[128];
112: tty = open("/dev/tty",2);
113: write(tty,SURE,sizeof(SURE));
114: read(tty,response,128);
115: if(*response!='y')
116: exit(50);
117: flag('c')++;
118: close(tty);
119: }
120: dirdirty++;
121: continue;
122:
123: case 'r':
124: setcom(rcmd);
125: flag('r')++;
126: continue;
127:
128: case 'd':
129: setcom(dcmd);
130: flag('d')++;
131: continue;
132:
133: case 'x':
134: setcom(xcmd);
135: continue;
136:
137: case 't':
138: setcom(tcmd);
139: continue;
140:
141: case 'f':
142: defdev = argv[2];
143: argv++;
144: argc--;
145: continue;
146:
147:
148: default:
149: fprintf(stderr, "arff: bad option `%c'\n", *cp);
150: exit(1);
151: }
152: namv = argv+2;
153: namc = argc-2;
154: if(comfun == 0) {
155: if(flg['u'-'a'] == 0) {
156: fprintf(stderr, "arff: one of [%s] must be specified\n", man);
157: exit(1);
158: }
159: setcom(rcmd);
160: }
161: (*comfun)();
162: exit(notfound());
163: }
164:
165: setcom(fun)
166: int (*fun)();
167: {
168:
169: if(comfun != 0) {
170: fprintf(stderr, "arff: only one of [%s] allowed\n", man);
171: exit(1);
172: }
173: comfun = fun;
174: }
175:
176:
177:
178:
179:
180:
181:
182:
183: usage()
184: {
185: printf("usage: ar [%s][%s] archive files ...\n", opt, man);
186: exit(1);
187: }
188:
189:
190:
191: notfound()
192: {
193: register i, n;
194:
195: n = 0;
196: for(i=0; i<namc; i++)
197: if(namv[i]) {
198: fprintf(stderr, "arff: %s not found\n", namv[i]);
199: n++;
200: }
201: return(n);
202: }
203:
204:
205:
206: phserr()
207: {
208:
209: fprintf(stderr, "arff: phase error on %s\n", file);
210: }
211:
212: mesg(c)
213: {
214:
215: if(flg['v'-'a'])
216: if(c != 'c' || flg['v'-'a'] > 1)
217: printf("%c - %s\n", c, file);
218: }
219:
220: tcmd()
221: {
222: register char *de;
223: FLDOPE *lookup(), *dope;
224: int nleft; register i;
225: register struct rt_ent *rde;
226:
227: rt_init();
228: if(namc==0)
229: for(de=((char *)&rt_dir)+10; de <= rt_last; de += rt_entsiz) {
230: if(rtls(rt(de))) {
231: nleft = (rt_last - de) / rt_entsiz;
232: printf("\n\n%d entries remaining.\n",nleft);
233: break;
234: }
235: }
236: else
237: for(i = 0; i < namc; i++) {
238: if(dope = lookup(namv[i])) {
239: rde = dope->rtdope;
240: rtls(rde);
241: namv[i] = 0;
242: }
243: }
244: }
245: rtls(de)
246: register struct rt_ent *de;
247: {
248: int month,day,year;
249: char name[12], ext[4];
250:
251: if(flg['v'-'a'])
252: switch(de->rt_stat) {
253: case RT_TEMP:
254: printf("Tempfile:\n");
255: case RT_FILE:
256: unrad50(2,de->rt_name,name);
257: unrad50(1,&(de->rt_name[2]),ext);
258: day = de->rt_date.rt_dy;
259: year = de->rt_date.rt_yr + 72;
260: month = de->rt_date.rt_mo;
261: printf("%6.6s %3.3s %02d/%02d/%02d %d\n",name,
262: ext,month,day,year,de->rt_len);
263: break;
264:
265: case RT_NULL:
266: printf("%-25.9s %d\n","<UNUSED>",de->rt_len);
267: break;
268:
269: case RT_ESEG:
270: return(1);
271: }
272: else {
273: switch(de->rt_stat) {
274: case RT_TEMP:
275: case RT_FILE:
276: sunrad50(name,de->rt_name);
277: printf(name);putchar('\n');
278: break;
279:
280: case RT_ESEG:
281: return(1);
282:
283: case RT_NULL:
284: ;
285: }
286: }
287: return(0);
288: }
289: xcmd()
290: {
291: register char *de;
292: char name[12];
293: register int i;
294:
295: rt_init();
296: if(namc==0)
297: for(de=((char *)&rt_dir)+10; de <= rt_last; de += rt_entsiz) {
298: sunrad50(name,rt(de)->rt_name);
299: rtx(name);
300: }
301:
302: else
303: for(i = 0; i < namc; i++)
304: if(rtx(namv[i])==0) namv[i] = 0;
305: }
306: rtx(name)
307: char *name;
308: {
309: register FLDOPE *dope;
310: FLDOPE *lookup();
311: register startad, count;
312: int file; char buff[512];
313:
314:
315: if(dope = lookup(name)) {
316: if(flg['v' - 'a'])
317: rtls(dope->rtdope);
318: else
319: printf("x - %s\n",name);
320:
321: file = creat(name, 0666);
322: if(file < 0) return(1);
323: count = dope->count;
324: startad = dope->startad;
325: for( ; count > 0 ; count -= 512) {
326: lread(startad,512,buff);
327: write(file,buff,512);
328: startad += 512;
329: }
330: close(file);
331: return(0);
332: }
333: return(1);
334: }
335: rt_init()
336: {
337: static initized = 0;
338: register char *de;
339: int mode;
340:
341: if(initized) return;
342: initized = 1;
343: if(flag('c') || flag('d') || flag('r'))
344: mode = 2;
345: else
346: mode = 0;
347: if((floppydes = open(defdev,mode)) < 0)
348: dbprintf("Floppy open failed\n");
349: if(flag('c')==0)
350: lread(6*RT_BLOCK,2*RT_BLOCK,(char *)&rt_dir);
351:
352: rt_entsiz = 2*rt_dir.rt_axhead.rt_entpad + 14;
353: rt_entsiz = 14;
354: rt_last = ((char *) &rt_dir) + 10 + 1014/rt_entsiz*rt_entsiz;
355: for(de=((char *)&rt_dir)+10; de <= rt_last; de += rt_entsiz) {
356: if(rt(de)->rt_stat==RT_ESEG) break;
357: }
358: rt_curend = rt(de);
359: rt_nleft = (rt_last - de) / rt_entsiz;
360: }
361:
362: static FLDOPE result;
363: FLDOPE *
364: lookup(name)
365: char * name;
366: {
367: unsigned short rname[3];
368: register char *de;
369: register index;
370:
371: srad50(name,rname);
372:
373: /*
374: * Search for name, accumulate blocks in index
375: */
376: rt_init();
377: index = 0;
378: for(de = ((char *) &rt_dir) + 10; de <= rt_last; de += rt_entsiz) {
379: switch(rt(de)->rt_stat) {
380: case RT_ESEG:
381: return((FLDOPE *) 0);
382: case RT_FILE:
383: case RT_TEMP:
384: if(samename(rname,rt(de)->rt_name))
385: goto found;
386: case RT_NULL:
387: index += rt(de)->rt_len;
388: }
389: }
390: return((FLDOPE *) 0);
391: found: result.count = rt(de)->rt_len * 512;
392: result.startad = 512 * (rt_dir.rt_axhead.rt_stfile + index);
393: result.rtdope = (struct rt_ent *) de;
394: return(&result);
395: }
396: static
397: samename(a,b)
398: unsigned short a[3],b[3];
399: {
400: return( a[0]==b[0] && a[1]==b[1] && a[2]==b[2] );
401: }
402:
403:
404: rad50(cp,out)
405: register unsigned char *cp;
406: unsigned short *out;
407: {
408: register index;
409: register temp;
410:
411: for(index = 0;*cp; index++) {
412:
413: temp = Ain1 * table[*cp++];
414: if(*cp!=0) {
415: temp += Ain2 * table[*cp++];
416:
417: if(*cp!=0)
418: temp += table[*cp++];
419: }
420:
421: out[index] = temp;
422: }
423: }
424: #define reduce(x,p,q) \
425: (x = v[p/q], p %= q);
426:
427: unrad50(count,in,cp)
428: unsigned short *in;
429: register char *cp;
430: {
431: register i, temp; register unsigned char *v = (unsigned char *) val;
432:
433: for(i = 0; i < count; i++) {
434: temp = in[i];
435:
436: reduce (*cp++,temp,Ain1);
437: reduce (*cp++,temp,Ain2);
438: reduce (*cp++,temp,1);
439: }
440: *cp=0;
441: }
442:
443: srad50(name,rname)
444: register char * name;
445: register unsigned short *rname;
446: {
447: register index; register char *cp;
448: char file[7],ext[4];
449: /*
450: * Find end of pathname
451: */
452: for(cp = name; *cp++; );
453: while(cp >= name && *--cp != '/');
454: cp++;
455: /*
456: * Change to rad50
457: *
458: */
459: for(index = 0; *cp; ){
460: file[index++] = *cp++;
461: if(*cp=='.') {
462: cp++;
463: break;
464: }
465: if(index>=6) {
466: break;
467: }
468: }
469: file[index] = 0;
470: for(index = 0; *cp; ){
471: ext[index++] = *cp++;
472: if(*cp=='.' || index>=3) {
473: break;
474: }
475: }
476: ext[index]=0;
477: rname[0] = 0;
478: rname[1] = 0;
479: rname[2] = 0;
480: rad50((unsigned char *)file,rname);
481: rad50((unsigned char *)ext,rname+2);
482: }
483: sunrad50(name,rname)
484: unsigned short rname[3];
485: register char *name;
486: {
487: register char *cp, *cp2;
488: char ext[4];
489:
490: unrad50(2,rname,name);
491: unrad50(1,rname + 2,ext);
492: /* Jam name and extension together with a dot
493: deleting white space */
494: for(cp = name; *cp++;);--cp; while(*--cp==' ' && cp>=name);
495: *++cp = '.';cp++;
496: for(cp2=ext; *cp2!=' ' && cp2 < ext + 3;) {
497: *cp++ = *cp2++;
498: }
499: *cp=0;
500: if(cp[-1]=='.') cp[-1] = 0;
501: }
502:
503: static char *oval = " ABCDEFGHIJKLMNOPQRSTUVWXYZ$.@0123456789";
504: static char *val = " abcdefghijklmnopqrstuvwxyz$.@0123456789";
505: static char table[256] = {
506: 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
507: 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
508: 0, 29, 29, 29, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 29,
509: 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 29, 29, 29, 29, 29, 29,
510: 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
511: 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
512: 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
513: 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
514: 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
515: 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
516: 0, 29, 29, 29, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 29,
517: 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 29, 29, 29, 29, 29, 29,
518: 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
519: 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
520: 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
521: 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29 };
522:
523: long trans(logical)
524: register int logical;
525: {
526: /* Logical to physical adress translation */
527: register int sector, bytes, track;
528:
529: logical += 26 * 128;
530: bytes = (logical & 127);
531: logical >>= 7;
532: sector = logical % 26;
533: if(sector >= 13)
534: sector = sector *2 +1;
535: else
536: sector *= 2;
537: sector += 26 + ((track = (logical / 26)) - 1) * 6;
538: sector %= 26;
539: return( (((track *26) + sector) << 7) + bytes);
540: }
541: lread(startad,count,obuff)
542: register startad, count;
543: register char * obuff;
544: {
545: long trans();
546: extern floppydes;
547: rt_init();
548: if(flg['m'-'a']==0)
549: while( (count -= 128) >= 0) {
550: lseek(floppydes, trans(startad), 0);
551: read(floppydes,obuff,128);
552: obuff += 128;
553: startad += 128;
554: }
555: else
556: while( (count -= 512) >= 0) {
557: lseek(floppydes,(long) (startad), 0);
558: read(floppydes,obuff,512);
559: obuff += 512;
560: startad += 512;
561: }
562: }
563: lwrite(startad,count,obuff)
564: register startad, count;
565: register char * obuff;
566: {
567: long trans();
568: extern floppydes;
569: rt_init();
570: if(flg['m'-'a']==0)
571: while( (count -= 128) >= 0) {
572: lseek(floppydes, trans(startad), 0);
573: write(floppydes,obuff,128);
574: obuff += 128;
575: startad += 128;
576: }
577: else
578: while( (count -= 512) >= 0) {
579: lseek(floppydes,(long) (startad), 0);
580: write(floppydes,obuff,512);
581: obuff += 512;
582: startad += 512;
583: }
584: }
585:
586: rcmd()
587: {
588: register int i;
589:
590: rt_init();
591: if(namc>0)
592: for(i = 0; i < namc; i++)
593: if(rtr(namv[i])==0) namv[i]=0;
594:
595:
596: }
597:
598: rtr(name)
599: char *name;
600: {
601: register FLDOPE *dope; register struct rt_ent *de;
602: struct stat buf; register struct stat *bufp = &buf;
603:
604: if(stat(name,bufp)<0) return(1);
605: if(dope = lookup(name)) {
606: /* can replace, no problem */
607: de = dope->rtdope;
608: if(bufp->st_size <= (de->rt_len * 512))
609: printf("r - %s\n",name),
610: toflop(name,bufp->st_size,dope);
611: else {
612: printf("%s will not fit in currently used file on floppy\n",name);
613: return(1);
614: }
615: } else {
616: /* Search for vacant spot */
617: for(de = rt_dir.rt_ents; (char *) de <= rt_last; de++) {
618: switch((de)->rt_stat) {
619: case RT_NULL:
620: if(bufp->st_size <= (de->rt_len * 512)) {
621: printf("a - %s\n",name),
622: mkent(de,bufp,name);
623: goto found;
624: }
625: continue;
626: case RT_ESEG:
627: return(3);
628: }
629: }
630: return(5);
631: }
632: found: if(dope=lookup(name)) {
633: toflop(name,bufp->st_size,dope);
634: return(0);
635: }
636: return(7);
637:
638: }
639: mkent(de,bufp,name)
640: register struct rt_ent *de;
641: register struct stat *bufp;
642: char *name;
643: {
644: struct tm *localtime(); register struct tm *timp;
645: register struct rt_ent *workp; int count;
646:
647: count = (((bufp->st_size -1) >>9) + 1);
648: /* Make sure there is room */
649: if(de->rt_len==count)
650: goto overwrite;
651: if(rt_nleft==0) {
652: if(flg['o'-'a'])
653: goto overwrite;
654: fprintf(stderr,"Directory full on %s\n",defdev);
655: exit(1);
656: }
657: /* copy directory entries up */
658: for(workp = rt_curend+1; workp > de; workp--)
659: *workp = workp[-1];
660: de[1].rt_len -= count;
661: de->rt_len = count;
662: rt_curend++;
663: rt_nleft--;
664: overwrite:
665: srad50(name,de->rt_name);
666: timp = localtime(&bufp->st_mtime);
667: de->rt_date.rt_dy = timp->tm_mday + 1;
668: de->rt_date.rt_mo = timp->tm_mon + 1;
669: de->rt_date.rt_yr = timp->tm_year - 72;
670: de->rt_stat = RT_FILE;
671: de->rt_pad = 0;
672: de->rt_chan = 0;
673: de->rt_job = 0;
674: lwrite(6*RT_BLOCK,2*RT_BLOCK,(char *)&rt_dir);
675:
676: }
677:
678: toflop(name,ocount,dope)
679: char *name;
680: register FLDOPE *dope;
681: long ocount;
682: {
683: register file, n, startad = dope->startad, count = ocount;
684: char buff[512];
685:
686: file = open(name,0);
687: if(file < 0) {
688: printf("arff: couldn't open %s\n",name);exit(1);}
689: for( ; count >= 512; count -= 512) {
690: read(file,buff,512);
691: lwrite(startad,512,buff);
692: startad += 512;
693: }
694: read(file,buff,count);
695: close(file);
696: if(count <= 0) return;
697: for(n = count; n < 512; n ++) buff[n] = 0;
698: lwrite(startad,512,buff);
699: count = (dope->rtdope->rt_len * 512 - ocount) / 512 ;
700: if(count <= 0) return;
701: for( ; count > 0 ; count--) {
702: startad += 512;
703: lwrite(startad,512,zeroes);
704: }
705:
706: }
707: dcmd()
708: {
709: register int i;
710:
711: rt_init();
712: if(namc)
713: for(i = 0; i < namc; i++)
714: if(rtk(namv[i])==0) namv[i]=0;
715: if(dirdirty)
716: scrunch();
717:
718: }
719: rtk(name)
720: char *name;
721: {
722: register FLDOPE *dope;
723: register struct rt_ent *de;
724: FLDOPE *lookup();
725:
726: if(dope = lookup(name)) {
727: printf("d - %s\n",name);
728: de = dope->rtdope;
729: de->rt_stat = RT_NULL;
730: de->rt_name[0] = 0;
731: de->rt_name[1] = 0;
732: de->rt_name[2] = 0;
733: * ((unsigned short *) & (de->rt_date)) = 0;
734: dirdirty = 1;
735: return(0);
736: }
737: return(1);
738: }
739: scrunch() {
740: register struct rt_ent *de = rt_dir.rt_ents, *workp;
741: for(de = rt_dir.rt_ents; de <= rt_curend; de++) {
742: if(de->rt_stat==RT_NULL && de[1].rt_stat==RT_NULL) {
743: (de+1)->rt_len += de->rt_len;
744: for(workp = de; workp < rt_curend; workp++)
745: *workp = workp[1];
746: de--;
747: rt_curend--;
748: rt_nleft++;
749: }
750: }
751: lwrite(6*RT_BLOCK,2*RT_BLOCK,(char *)&rt_dir);
752: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.