aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/tapefs/32vfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/tapefs/32vfs.c')
-rw-r--r--src/cmd/tapefs/32vfs.c208
1 files changed, 208 insertions, 0 deletions
diff --git a/src/cmd/tapefs/32vfs.c b/src/cmd/tapefs/32vfs.c
new file mode 100644
index 00000000..55d5dbe0
--- /dev/null
+++ b/src/cmd/tapefs/32vfs.c
@@ -0,0 +1,208 @@
+/*
+ * Vax 32V Unix filesystem (same as pre-FFS Berkeley)
+ */
+#include <u.h>
+#include <libc.h>
+#include <auth.h>
+#include <fcall.h>
+#include "tapefs.h"
+
+/*
+ * v32 disk inode
+ */
+#define VNADDR 13
+#define VFMT 0160000
+#define VIFREG 0100000
+#define VIFDIR 0040000
+#define VIFCHR 0120000
+#define VIFBLK 0160000
+#define VMODE 0777
+#define VSUPERB 1
+#define VROOT 2 /* root inode */
+#define VNAMELEN 14
+#define BLSIZE 512
+#define LINOPB (BLSIZE/sizeof(struct v32dinode))
+#define LNINDIR (BLSIZE/sizeof(unsigned long))
+
+struct v32dinode {
+ unsigned char flags[2];
+ unsigned char nlinks[2];
+ unsigned char uid[2];
+ unsigned char gid[2];
+ unsigned char size[4];
+ unsigned char addr[40];
+ unsigned char atime[4];
+ unsigned char mtime[4];
+ unsigned char ctime[4];
+};
+
+struct v32dir {
+ uchar ino[2];
+ char name[VNAMELEN];
+};
+
+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(VROOT);
+ 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 v32dir *dp;
+ Fileinf f;
+ char name[VNAMELEN+1];
+
+ cp = 0;
+ for (i=0; i<r->ndata; i+=sizeof(struct v32dir)) {
+ if (i%BLSIZE==0)
+ cp = doread(r, i, BLSIZE);
+ dp = (struct v32dir *)(cp+i%BLSIZE);
+ ino = g2byte(dp->ino);
+ if (strcmp(dp->name, ".")==0 || strcmp(dp->name, "..")==0)
+ continue;
+ if (ino==0)
+ continue;
+ f = iget(ino);
+ strncpy(name, dp->name, VNAMELEN);
+ name[VNAMELEN+1] = '\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 v32dinode *dp;
+ long flags, i;
+ Fileinf f;
+
+ seek(tapefile, BLSIZE*((ino-1)/LINOPB + VSUPERB + 1), 0);
+ if (read(tapefile, buf, BLSIZE) != BLSIZE)
+ error("Can't read inode");
+ dp = ((struct v32dinode *)buf) + ((ino-1)%LINOPB);
+ flags = g2byte(dp->flags);
+ f.size = g4byte(dp->size);
+ if ((flags&VFMT)==VIFCHR || (flags&VFMT)==VIFBLK)
+ f.size = 0;
+ f.data = emalloc(VNADDR*sizeof(long));
+ for (i = 0; i < VNADDR; i++)
+ ((long*)f.data)[i] = g3byte(dp->addr+3*i);
+ f.mode = flags & VMODE;
+ if ((flags&VFMT)==VIFDIR)
+ f.mode |= DMDIR;
+ f.uid = g2byte(dp->uid);
+ f.gid = g2byte(dp->gid);
+ f.mdate = g4byte(dp->mtime);
+ 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][sizeof(long)];
+
+ if (bno < VNADDR-3)
+ return ((long*)r->data)[bno];
+ if (bno < VNADDR*LNINDIR) {
+ seek(tapefile, ((long *)r->data)[(bno-(VNADDR-3))/LNINDIR]*BLSIZE, 0);
+ if (read(tapefile, (char *)indbuf, BLSIZE) != BLSIZE)
+ return 0;
+ return ((indbuf[bno%LNINDIR][1]<<8) + indbuf[bno%LNINDIR][0]);
+ }
+ return 0;
+}