/* * old (V6 and before) PDP-11 Unix filesystem */ #include #include #include #include #include "tapefs.h" /* * v6 disk inode */ #define V6NADDR 8 #define V6FMT 0160000 #define V6IFREG 0100000 #define V6IFDIR 0140000 #define V6IFCHR 0120000 #define V6IFBLK 0160000 #define V6MODE 0777 #define V6LARGE 010000 #define V6SUPERB 1 #define V6ROOT 1 /* root inode */ #define V6NAMELEN 14 #define BLSIZE 512 #define LINOPB (BLSIZE/sizeof(struct v6dinode)) #define LNINDIR (BLSIZE/sizeof(unsigned short)) struct v6dinode { unsigned char flags[2]; unsigned char nlinks; unsigned char uid; unsigned char gid; unsigned char hisize; unsigned char losize[2]; unsigned char addr[V6NADDR][2]; unsigned char atime[4]; /* pdp-11 order */ unsigned char mtime[4]; /* pdp-11 order */ }; struct v6dir { uchar ino[2]; char name[V6NAMELEN]; }; int tapefile; Fileinf iget(int ino); long bmap(Ram *r, long bno); void getblk(Ram *r, long bno, char *buf); void populate(char *name) { Fileinf f; replete = 0; tapefile = open(name, OREAD); if (tapefile<0) error("Can't open argument file"); f = iget(V6ROOT); ram->perm = f.mode; ram->mtime = f.mdate; ram->addr = f.addr; ram->data = f.data; ram->ndata = f.size; } void popdir(Ram *r) { int i, ino; char *cp; struct v6dir *dp; Fileinf f; char name[V6NAMELEN+1]; cp = 0; for (i=0; indata; i+=sizeof(struct v6dir)) { if (i%BLSIZE==0) cp = doread(r, i, BLSIZE); dp = (struct v6dir *)(cp+i%BLSIZE); ino = dp->ino[0] + (dp->ino[1]<<8); if (strcmp(dp->name, ".")==0 || strcmp(dp->name, "..")==0) continue; if (ino==0) continue; f = iget(ino); strncpy(name, dp->name, V6NAMELEN); name[V6NAMELEN] = '\0'; f.name = name; popfile(r, f); } r->replete = 1; } void dotrunc(Ram *r) { USED(r); } void docreate(Ram *r) { USED(r); } char * doread(Ram *r, vlong off, long cnt) { static char buf[Maxbuf+BLSIZE]; int bno, i; bno = off/BLSIZE; off -= bno*BLSIZE; if (cnt>Maxbuf) error("count too large"); if (off) cnt += off; i = 0; while (cnt>0) { getblk(r, bno, &buf[i*BLSIZE]); cnt -= BLSIZE; bno++; i++; } return buf; } void dowrite(Ram *r, char *buf, long off, long cnt) { USED(r); USED(buf); USED(off); USED(cnt); } int dopermw(Ram *r) { USED(r); return 0; } /* * fetch an i-node * -- no sanity check for now * -- magic inode-to-disk-block stuff here */ Fileinf iget(int ino) { char buf[BLSIZE]; struct v6dinode *dp; long flags, i; Fileinf f; seek(tapefile, BLSIZE*((ino-1)/LINOPB + V6SUPERB + 1), 0); if (read(tapefile, buf, BLSIZE) != BLSIZE) error("Can't read inode"); dp = ((struct v6dinode *)buf) + ((ino-1)%LINOPB); flags = (dp->flags[1]<<8) + dp->flags[0]; f.size = (dp->hisize << 16) + (dp->losize[1]<<8) + dp->losize[0]; if ((flags&V6FMT)==V6IFCHR || (flags&V6FMT)==V6IFBLK) f.size = 0; f.data = emalloc(V6NADDR*sizeof(ushort)); for (i = 0; i < V6NADDR; i++) ((ushort*)f.data)[i] = (dp->addr[i][1]<<8) + dp->addr[i][0]; f.mode = flags & V6MODE; if ((flags&V6FMT)==V6IFDIR) f.mode |= DMDIR; f.uid = dp->uid; f.gid = dp->gid; f.mdate = (dp->mtime[2]<<0) + (dp->mtime[3]<<8) +(dp->mtime[0]<<16) + (dp->mtime[1]<<24); return f; } void getblk(Ram *r, long bno, char *buf) { long dbno; if ((dbno = bmap(r, bno)) == 0) { memset(buf, 0, BLSIZE); return; } seek(tapefile, dbno*BLSIZE, 0); if (read(tapefile, buf, BLSIZE) != BLSIZE) error("bad read"); } /* * logical to physical block * only singly-indirect files for now */ long bmap(Ram *r, long bno) { unsigned char indbuf[LNINDIR][2]; if (r->ndata <= V6NADDR*BLSIZE) { /* assume size predicts largeness of file */ if (bno < V6NADDR) return ((ushort*)r->data)[bno]; return 0; } if (bno < V6NADDR*LNINDIR) { seek(tapefile, ((ushort *)r->data)[bno/LNINDIR]*BLSIZE, 0); if (read(tapefile, (char *)indbuf, BLSIZE) != BLSIZE) return 0; return ((indbuf[bno%LNINDIR][1]<<8) + indbuf[bno%LNINDIR][0]); } return 0; }