summaryrefslogtreecommitdiff
path: root/sys/src/cmd/tapefs/v6fs.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /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-xsys/src/cmd/tapefs/v6fs.c213
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;
+}