diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/tapefs/v6fs.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/tapefs/v6fs.c')
-rwxr-xr-x | sys/src/cmd/tapefs/v6fs.c | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/sys/src/cmd/tapefs/v6fs.c b/sys/src/cmd/tapefs/v6fs.c new file mode 100755 index 000000000..a10d0f9c8 --- /dev/null +++ b/sys/src/cmd/tapefs/v6fs.c @@ -0,0 +1,213 @@ +/* + * old (V6 and before) PDP-11 Unix filesystem + */ +#include <u.h> +#include <libc.h> +#include <auth.h> +#include <fcall.h> +#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; i<r->ndata; 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; +} |