+static char *sccsid = "@(#)arff.c 4.1 (Berkeley) %G%";
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <signal.h>
+#include <stdio.h>
+#define dbprintf printf
+struct rt_dat {
+unsigned short int rt_yr:5; /*Year - 1972 */
+unsigned short int rt_dy:5; /*day */
+unsigned short int rt_mo:5; /*month */
+};
+struct rt_axent {
+ char rt_sent[14];
+};
+
+struct rt_ent {
+ char rt_pad; /*unusued */
+ char rt_stat; /*Type of entry, or end of seg*/
+ unsigned short rt_name[3]; /*Name, 3 words in rad50 form */
+ short rt_len; /*Length of file */
+ char rt_chan; /*Only used in temporary files*/
+ char rt_job; /*Only used in temporary files*/
+ struct rt_dat rt_date; /*Creation Date */
+};
+#define RT_TEMP 1
+#define RT_NULL 2
+#define RT_FILE 4
+#define RT_ESEG 8
+#define RT_BLOCK 512
+struct rt_head {
+ short rt_numseg; /*number of segments available*/
+ short rt_nxtseg; /*segment no of next log. seg */
+ short rt_lstseg; /*highest seg currenltly open */
+ unsigned short rt_entpad; /*extra words/dir. entry */
+ short rt_stfile; /*block no where files begin */
+};
+struct rt_dir {
+ struct rt_head rt_axhead;
+ struct rt_ent rt_ents[72];
+ char _dirpad[6];
+};
+extern struct rt_dir rt_dir;
+extern int rt_entsiz;
+extern int floppydes;
+extern char *rt_last;
+typedef struct fldope {
+ int startad;
+ int count;
+struct rt_ent *rtdope;
+} FLDOPE;
+FLDOPE *lookup();
+#define rt(p) ((struct rt_ent *) p )
+#define Ain1 03100
+#define Ain2 050
+#define flag(c) (flg[(c) - 'a'])
+
+char *man = { "rxtd" };
+
+char zeroes[512];
+extern char *val;
+extern char table[256];
+struct rt_dir rt_dir = {{4,0,1,0,14},{0,RT_NULL,{0,0,0},494,0}, {0,RT_ESEG}};
+int rt_entsiz;
+int rt_nleft;
+struct rt_ent *rt_curend;
+int floppydes;
+int dirdirty;
+char *rt_last;
+char *defdev = "/dev/floppy";
+
+char *opt = { "vf" };
+
+int signum[] = {SIGHUP, SIGINT, SIGQUIT, 0};
+long lseek();
+int rcmd();
+int dcmd();
+int xcmd();
+int tcmd();
+int (*comfun)();
+char flg[26];
+char **namv;
+int namc;
+int file;
+
+
+main(argc, argv)
+char *argv[];
+{
+ register char *cp;
+
+ /*register i;
+ for(i=0; signum[i]; i++)
+ if(signal(signum[i], SIG_IGN) != SIG_IGN)
+ signal(signum[i], sigdone);*/
+ if(argc < 2)
+ usage();
+ cp = argv[1];
+ for(cp = argv[1]; *cp; cp++)
+ switch(*cp) {
+ case 'm':
+ case 'v':
+ case 'u':
+ case 'w':
+ flg[*cp - 'a']++;
+ continue;
+ case 'c':
+ {
+#define SURE "Are you sure you want to clobber the floppy?\n"
+ int tty;
+ char response[2];
+ tty = open("/dev/tty",2);
+ write(tty,SURE,sizeof(SURE));
+ read(tty,response,2);
+ if(*response!='y')
+ exit(50);
+ flag('c')++;
+ close(tty);
+ }
+ dirdirty++;
+ continue;
+
+ case 'r':
+ setcom(rcmd);
+ flag('r')++;
+ continue;
+
+ case 'd':
+ setcom(dcmd);
+ flag('d')++;
+ continue;
+
+ case 'x':
+ setcom(xcmd);
+ continue;
+
+ case 't':
+ setcom(tcmd);
+ continue;
+
+ case 'f':
+ defdev = argv[2];
+ argv++;
+ argc--;
+ continue;
+
+
+ default:
+ fprintf(stderr, "arff: bad option `%c'\n", *cp);
+ exit(1);
+ }
+ namv = argv+2;
+ namc = argc-2;
+ if(comfun == 0) {
+ if(flg['u'-'a'] == 0) {
+ fprintf(stderr, "arff: one of [%s] must be specified\n", man);
+ exit(1);
+ }
+ setcom(rcmd);
+ }
+ (*comfun)();
+ exit(notfound());
+}
+
+setcom(fun)
+int (*fun)();
+{
+
+ if(comfun != 0) {
+ fprintf(stderr, "arff: only one of [%s] allowed\n", man);
+ exit(1);
+ }
+ comfun = fun;
+}
+
+
+
+
+
+
+
+
+usage()
+{
+ printf("usage: ar [%s][%s] archive files ...\n", opt, man);
+ exit(1);
+}
+
+
+
+notfound()
+{
+ register i, n;
+
+ n = 0;
+ for(i=0; i<namc; i++)
+ if(namv[i]) {
+ fprintf(stderr, "arff: %s not found\n", namv[i]);
+ n++;
+ }
+ return(n);
+}
+
+
+
+phserr()
+{
+
+ fprintf(stderr, "arff: phase error on %s\n", file);
+}
+
+mesg(c)
+{
+
+ if(flg['v'-'a'])
+ if(c != 'c' || flg['v'-'a'] > 1)
+ printf("%c - %s\n", c, file);
+}
+
+tcmd()
+{
+ register char *de;
+ FLDOPE *lookup(), *dope;
+ int nleft; register i;
+ register struct rt_ent *rde;
+
+ rt_init();
+ if(namc==0)
+ for(de=((char *)&rt_dir)+10; de <= rt_last; de += rt_entsiz) {
+ if(rtls(rt(de))) {
+ nleft = (rt_last - de) / rt_entsiz;
+ printf("\n\n%d entries remaining.\n",nleft);
+ break;
+ }
+ }
+ else
+ for(i = 0; i < namc; i++) {
+ if(dope = lookup(namv[i])) {
+ rde = dope->rtdope;
+ rtls(rde);
+ namv[i] = 0;
+ }
+ }
+}
+rtls(de)
+register struct rt_ent *de;
+{
+ int month,day,year;
+ char name[12], ext[4];
+
+ if(flg['v'-'a'])
+ switch(de->rt_stat) {
+ case RT_TEMP:
+ printf("Tempfile:\n");
+ case RT_FILE:
+ unrad50(2,de->rt_name,name);
+ unrad50(1,&(de->rt_name[2]),ext);
+ day = de->rt_date.rt_dy;
+ year = de->rt_date.rt_yr + 72;
+ month = de->rt_date.rt_mo;
+ printf("%6.6s %3.3s %02d/%02d/%02d %d\n",name,
+ ext,month,day,year,de->rt_len);
+ break;
+
+ case RT_NULL:
+ printf("%-25.9s %d\n","<UNUSED>",de->rt_len);
+ break;
+
+ case RT_ESEG:
+ return(1);
+ }
+ else {
+ switch(de->rt_stat) {
+ case RT_TEMP:
+ case RT_FILE:
+ sunrad50(name,de->rt_name);
+ printf(name);putchar('\n');
+ break;
+
+ case RT_ESEG:
+ return(1);
+
+ case RT_NULL:
+ ;
+ }
+ }
+ return(0);
+}
+xcmd()
+{
+ register char *de;
+ char name[12];
+ register int i;
+
+ rt_init();
+ if(namc==0)
+ for(de=((char *)&rt_dir)+10; de <= rt_last; de += rt_entsiz) {
+ sunrad50(name,rt(de)->rt_name);
+ rtx(name);
+ }
+
+ else
+ for(i = 0; i < namc; i++)
+ if(rtx(namv[i])==0) namv[i] = 0;
+}
+rtx(name)
+char *name;
+{
+ register FLDOPE *dope;
+ FLDOPE *lookup();
+ register startad, count;
+ int file; char buff[512];
+
+
+ if(dope = lookup(name)) {
+ if(flg['v' - 'a'])
+ rtls(dope->rtdope);
+ else
+ printf("x - %s\n",name);
+
+ file = creat(name, 0666);
+ if(file < 0) return(1);
+ count = dope->count;
+ startad = dope->startad;
+ for( ; count > 0 ; count -= 512) {
+ lread(startad,512,buff);
+ write(file,buff,512);
+ startad += 512;
+ }
+ close(file);
+ return(0);
+ }
+ return(1);
+}
+rt_init()
+{
+ static initized = 0;
+ register char *de;
+ int mode;
+
+ if(initized) return;
+ initized = 1;
+ if(flag('c') || flag('d') || flag('r'))
+ mode = 2;
+ else
+ mode = 0;
+ if((floppydes = open(defdev,mode)) < 0)
+ dbprintf("Floppy open failed\n");
+ if(flag('c')==0)
+ lread(6*RT_BLOCK,2*RT_BLOCK,(char *)&rt_dir);
+
+ rt_entsiz = 2*rt_dir.rt_axhead.rt_entpad + 14;
+ rt_entsiz = 14;
+ rt_last = ((char *) &rt_dir) + 10 + 1014/rt_entsiz*rt_entsiz;
+ for(de=((char *)&rt_dir)+10; de <= rt_last; de += rt_entsiz) {
+ if(rt(de)->rt_stat==RT_ESEG) break;
+ }
+ rt_curend = rt(de);
+ rt_nleft = (rt_last - de) / rt_entsiz;
+}
+
+static FLDOPE result;
+FLDOPE *
+lookup(name)
+char * name;
+{
+ unsigned short rname[3];
+ register char *de;
+ register index;
+
+ srad50(name,rname);
+
+ /*
+ * Search for name, accumulate blocks in index
+ */
+ rt_init();
+ index = 0;
+ for(de = ((char *) &rt_dir) + 10; de <= rt_last; de += rt_entsiz) {
+ switch(rt(de)->rt_stat) {
+ case RT_ESEG:
+ return((FLDOPE *) 0);
+ case RT_FILE:
+ case RT_TEMP:
+ if(samename(rname,rt(de)->rt_name))
+ goto found;
+ case RT_NULL:
+ index += rt(de)->rt_len;
+ }
+ }
+ return((FLDOPE *) 0);
+found: result.count = rt(de)->rt_len * 512;
+ result.startad = 512 * (rt_dir.rt_axhead.rt_stfile + index);
+ result.rtdope = (struct rt_ent *) de;
+ return(&result);
+}
+static
+samename(a,b)
+unsigned short a[3],b[3];
+{
+ return( a[0]==b[0] && a[1]==b[1] && a[2]==b[2] );
+}
+
+
+rad50(cp,out)
+register unsigned char *cp;
+unsigned short *out;
+{
+ register index;
+ register temp;
+
+ for(index = 0;*cp; index++) {
+
+ temp = Ain1 * table[*cp++];
+ if(*cp!=0) {
+ temp += Ain2 * table[*cp++];
+
+ if(*cp!=0)
+ temp += table[*cp++];
+ }
+
+ out[index] = temp;
+ }
+}
+#define reduce(x,p,q) \
+ (x = v[p/q], p %= q);
+
+unrad50(count,in,cp)
+unsigned short *in;
+register char *cp;
+{
+ register i, temp; register unsigned char *v = (unsigned char *) val;
+
+ for(i = 0; i < count; i++) {
+ temp = in[i];
+
+ reduce (*cp++,temp,Ain1);
+ reduce (*cp++,temp,Ain2);
+ reduce (*cp++,temp,1);
+ }
+ *cp=0;
+}
+
+srad50(name,rname)
+register char * name;
+register unsigned short *rname;
+{
+ register index; register char *cp;
+ char file[7],ext[4];
+ /*
+ * Find end of pathname
+ */
+ for(cp = name; *cp++; );
+ while(cp >= name && *--cp != '/');
+ cp++;
+ /*
+ * Change to rad50
+ *
+ */
+ for(index = 0; *cp; ){
+ file[index++] = *cp++;
+ if(*cp=='.') {
+ cp++;
+ break;
+ }
+ if(index>=6) {
+ break;
+ }
+ }
+ file[index] = 0;
+ for(index = 0; *cp; ){
+ ext[index++] = *cp++;
+ if(*cp=='.' || index>=3) {
+ break;
+ }
+ }
+ ext[index]=0;
+ rname[0] = 0;
+ rname[1] = 0;
+ rname[2] = 0;
+ rad50((unsigned char *)file,rname);
+ rad50((unsigned char *)ext,rname+2);
+}
+sunrad50(name,rname)
+unsigned short rname[3];
+register char *name;
+{
+ register char *cp, *cp2;
+ char ext[4];
+
+ unrad50(2,rname,name);
+ unrad50(1,rname + 2,ext);
+ /* Jam name and extension together with a dot
+ deleting white space */
+ for(cp = name; *cp++;);--cp; while(*--cp==' ' && cp>=name);
+ *++cp = '.';cp++;
+ for(cp2=ext; *cp2!=' ' && cp2 < ext + 3;) {
+ *cp++ = *cp2++;
+ }
+ *cp=0;
+ if(cp[-1]=='.') cp[-1] = 0;
+}
+
+static char *oval = " ABCDEFGHIJKLMNOPQRSTUVWXYZ$.@0123456789";
+static char *val = " abcdefghijklmnopqrstuvwxyz$.@0123456789";
+static char table[256] = {
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+0, 29, 29, 29, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 29,
+30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 29, 29, 29, 29, 29, 29,
+29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
+29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+0, 29, 29, 29, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 29,
+30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 29, 29, 29, 29, 29, 29,
+29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
+29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29 };
+
+long trans(logical)
+register int logical;
+{
+ /* Logical to physical adress translation */
+ register int sector, bytes, track;
+
+ logical += 26 * 128;
+ bytes = (logical & 127);
+ logical >>= 7;
+ sector = logical % 26;
+ if(sector >= 13)
+ sector = sector *2 +1;
+ else
+ sector *= 2;
+ sector += 26 + ((track = (logical / 26)) - 1) * 6;
+ sector %= 26;
+ return( (((track *26) + sector) << 7) + bytes);
+}
+lread(startad,count,obuff)
+register startad, count;
+register char * obuff;
+{
+ long trans();
+ extern floppydes;
+ rt_init();
+ if(flg['m'-'a']==0)
+ while( (count -= 128) >= 0) {
+ lseek(floppydes, trans(startad), 0);
+ read(floppydes,obuff,128);
+ obuff += 128;
+ startad += 128;
+ }
+ else
+ while( (count -= 512) >= 0) {
+ lseek(floppydes,(long) (startad), 0);
+ read(floppydes,obuff,512);
+ obuff += 512;
+ startad += 512;
+ }
+}
+lwrite(startad,count,obuff)
+register startad, count;
+register char * obuff;
+{
+ long trans();
+ extern floppydes;
+ rt_init();
+ if(flg['m'-'a']==0)
+ while( (count -= 128) >= 0) {
+ lseek(floppydes, trans(startad), 0);
+ write(floppydes,obuff,128);
+ obuff += 128;
+ startad += 128;
+ }
+ else
+ while( (count -= 512) >= 0) {
+ lseek(floppydes,(long) (startad), 0);
+ write(floppydes,obuff,512);
+ obuff += 512;
+ startad += 512;
+ }
+}
+
+rcmd()
+{
+ register int i;
+
+ rt_init();
+ if(namc>0)
+ for(i = 0; i < namc; i++)
+ if(rtr(namv[i])==0) namv[i]=0;
+
+
+}
+
+rtr(name)
+char *name;
+{
+ register FLDOPE *dope; register struct rt_ent *de;
+ struct stat buf; register struct stat *bufp = &buf;
+
+ if(stat(name,bufp)<0) return(1);
+ if(dope = lookup(name)) {
+ /* can replace, no problem */
+ de = dope->rtdope;
+ if(bufp->st_size <= (de->rt_len * 512))
+ printf("r - %s\n",name),
+ toflop(name,bufp->st_size,dope);
+ else {
+ printf("%s will not fit in currently used file on floppy\n",name);
+ return(1);
+ }
+ } else {
+ /* Search for vacant spot */
+ for(de = rt_dir.rt_ents; (char *) de <= rt_last; de++) {
+ switch((de)->rt_stat) {
+ case RT_NULL:
+ if(bufp->st_size <= (de->rt_len * 512)) {
+ printf("a - %s\n",name),
+ mkent(de,bufp,name);
+ goto found;
+ }
+ continue;
+ case RT_ESEG:
+ return(3);
+ }
+ }
+ return(5);
+ }
+found: if(dope=lookup(name)) {
+ toflop(name,bufp->st_size,dope);
+ return(0);
+ }
+ return(7);
+
+}
+mkent(de,bufp,name)
+register struct rt_ent *de;
+register struct stat *bufp;
+char *name;
+{
+ struct tm *localtime(); register struct tm *timp;
+ register struct rt_ent *workp; int count;
+
+ count = (((bufp->st_size -1) >>9) + 1);
+ /* Make sure there is room */
+ if(de->rt_len==count)
+ goto overwrite;
+ if(rt_nleft==0) {
+ if(flg['o'-'a'])
+ goto overwrite;
+ fprintf(stderr,"Directory full on %s\n",defdev);
+ exit(1);
+ }
+ /* copy directory entries up */
+ for(workp = rt_curend+1; workp > de; workp--)
+ *workp = workp[-1];
+ de[1].rt_len -= count;
+ de->rt_len = count;
+ rt_curend++;
+ rt_nleft--;
+overwrite:
+ srad50(name,de->rt_name);
+ timp = localtime(&bufp->st_mtime);
+ de->rt_date.rt_dy = timp->tm_mday + 1;
+ de->rt_date.rt_mo = timp->tm_mon + 1;
+ de->rt_date.rt_yr = timp->tm_year - 72;
+ de->rt_stat = RT_FILE;
+ de->rt_pad = 0;
+ de->rt_chan = 0;
+ de->rt_job = 0;
+ lwrite(6*RT_BLOCK,2*RT_BLOCK,(char *)&rt_dir);
+
+}
+
+toflop(name,ocount,dope)
+char *name;
+register FLDOPE *dope;
+long ocount;
+{
+ register file, n, startad = dope->startad, count = ocount;
+ char buff[512];
+
+ file = open(name,0);
+ if(file < 0) {
+ printf("arff: couldn't open %s\n",name);exit(1);}
+ for( ; count >= 512; count -= 512) {
+ read(file,buff,512);
+ lwrite(startad,512,buff);
+ startad += 512;
+ }
+ read(file,buff,count);
+ close(file);
+ if(count <= 0) return;
+ for(n = count; n < 512; n ++) buff[n] = 0;
+ lwrite(startad,512,buff);
+ count = (dope->rtdope->rt_len * 512 - ocount) / 512 ;
+ if(count <= 0) return;
+ for( ; count > 0 ; count--) {
+ startad += 512;
+ lwrite(startad,512,zeroes);
+ }
+
+}
+dcmd()
+{
+ register int i;
+
+ rt_init();
+ if(namc)
+ for(i = 0; i < namc; i++)
+ if(rtk(namv[i])==0) namv[i]=0;
+ if(dirdirty)
+ scrunch();
+
+}
+rtk(name)
+char *name;
+{
+ register FLDOPE *dope;
+ register struct rt_ent *de;
+ FLDOPE *lookup();
+
+ if(dope = lookup(name)) {
+ printf("d - %s\n",name);
+ de = dope->rtdope;
+ de->rt_stat = RT_NULL;
+ de->rt_name[0] = 0;
+ de->rt_name[1] = 0;
+ de->rt_name[2] = 0;
+ * ((unsigned short *) & (de->rt_date)) = 0;
+ dirdirty = 1;
+ return(0);
+ }
+ return(1);
+}
+scrunch() {
+ register struct rt_ent *de = rt_dir.rt_ents, *workp;
+ for(de = rt_dir.rt_ents; de <= rt_curend; de++) {
+ if(de->rt_stat==RT_NULL && de[1].rt_stat==RT_NULL) {
+ (de+1)->rt_len += de->rt_len;
+ for(workp = de; workp < rt_curend; workp++)
+ *workp = workp[1];
+ de--;
+ rt_curend--;
+ rt_nleft++;
+ }
+ }
+ lwrite(6*RT_BLOCK,2*RT_BLOCK,(char *)&rt_dir);
+}