123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222 |
- /*
- * 10th edition 4K file system
- */
- #include <u.h>
- #include <libc.h>
- #include <auth.h>
- #include <fcall.h>
- #include "tapefs.h"
- /*
- * v10 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 4096
- #define LINOPB (BLSIZE/sizeof(struct v10dinode))
- #define LNINDIR (BLSIZE/sizeof(unsigned long))
- struct v10dinode {
- 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 v10dir {
- uchar ino[2];
- char name[VNAMELEN];
- };
- int tapefile;
- vlong tapelen;
- Fileinf iget(int ino);
- long bmap(Ram *r, long bno);
- void getblk(Ram *r, long bno, char *buf);
- void
- populate(char *name)
- {
- Fileinf f;
- Dir *d;
- replete = 0;
- tapefile = open(name, OREAD);
- if (tapefile<0)
- error("Can't open argument file");
- if ((d=dirfstat(tapefile)) == nil)
- error("dirfstat");
- tapelen = d->length;
- free(d);
- 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 v10dir *dp;
- Fileinf f;
- char name[VNAMELEN+1];
- cp = 0;
- for (i=0; i<r->ndata; i+=sizeof(struct v10dir)) {
- if (i%BLSIZE==0)
- cp = doread(r, i, BLSIZE);
- dp = (struct v10dir *)(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] = '\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+off;
- }
- 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 v10dinode *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 v10dinode *)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;
- }
- if ((vlong)(dbno+1)*BLSIZE > tapelen) {
- fprint(2, "read past end of tape: %lld\n", (vlong)dbno*BLSIZE);
- memset(buf, 0, BLSIZE);
- return;
- }
- seek(tapefile, dbno*BLSIZE, 0);
- if (readn(tapefile, buf, BLSIZE) != BLSIZE){
- fprint(2, "readn at %lld: %r\n", (vlong)dbno*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+(VNADDR-3)]*BLSIZE, 0);
- if (read(tapefile, (char *)indbuf, BLSIZE) != BLSIZE)
- return 0;
- return ((indbuf[(bno-(VNADDR-3))%LNINDIR][2]<<16) + (indbuf[(bno-(VNADDR-3))%LNINDIR][1]<<8)
- + indbuf[(bno-(VNADDR-3))%LNINDIR][0]);
- }
- return 0;
- }
|