1*219b2ee8SDavid du Colombier /* 2*219b2ee8SDavid du Colombier * 10th edition 4K file system 3*219b2ee8SDavid du Colombier */ 4*219b2ee8SDavid du Colombier #include <u.h> 5*219b2ee8SDavid du Colombier #include <libc.h> 6*219b2ee8SDavid du Colombier #include <auth.h> 7*219b2ee8SDavid du Colombier #include <fcall.h> 8*219b2ee8SDavid du Colombier #include "tapefs.h" 9*219b2ee8SDavid du Colombier 10*219b2ee8SDavid du Colombier /* 11*219b2ee8SDavid du Colombier * v10 disk inode 12*219b2ee8SDavid du Colombier */ 13*219b2ee8SDavid du Colombier #define VNADDR 13 14*219b2ee8SDavid du Colombier #define VFMT 0160000 15*219b2ee8SDavid du Colombier #define VIFREG 0100000 16*219b2ee8SDavid du Colombier #define VIFDIR 0040000 17*219b2ee8SDavid du Colombier #define VIFCHR 0120000 18*219b2ee8SDavid du Colombier #define VIFBLK 0160000 19*219b2ee8SDavid du Colombier #define VMODE 0777 20*219b2ee8SDavid du Colombier #define VSUPERB 1 21*219b2ee8SDavid du Colombier #define VROOT 2 /* root inode */ 22*219b2ee8SDavid du Colombier #define VNAMELEN 14 23*219b2ee8SDavid du Colombier #define BLSIZE 4096 24*219b2ee8SDavid du Colombier #define LINOPB (BLSIZE/sizeof(struct v10dinode)) 25*219b2ee8SDavid du Colombier #define LNINDIR (BLSIZE/sizeof(unsigned long)) 26*219b2ee8SDavid du Colombier 27*219b2ee8SDavid du Colombier struct v10dinode { 28*219b2ee8SDavid du Colombier unsigned char flags[2]; 29*219b2ee8SDavid du Colombier unsigned char nlinks[2]; 30*219b2ee8SDavid du Colombier unsigned char uid[2]; 31*219b2ee8SDavid du Colombier unsigned char gid[2]; 32*219b2ee8SDavid du Colombier unsigned char size[4]; 33*219b2ee8SDavid du Colombier unsigned char addr[40]; 34*219b2ee8SDavid du Colombier unsigned char atime[4]; 35*219b2ee8SDavid du Colombier unsigned char mtime[4]; 36*219b2ee8SDavid du Colombier unsigned char ctime[4]; 37*219b2ee8SDavid du Colombier }; 38*219b2ee8SDavid du Colombier 39*219b2ee8SDavid du Colombier struct v10dir { 40*219b2ee8SDavid du Colombier uchar ino[2]; 41*219b2ee8SDavid du Colombier char name[VNAMELEN]; 42*219b2ee8SDavid du Colombier }; 43*219b2ee8SDavid du Colombier 44*219b2ee8SDavid du Colombier int tapefile; 45*219b2ee8SDavid du Colombier Fileinf iget(int ino); 46*219b2ee8SDavid du Colombier long bmap(Ram *r, long bno); 47*219b2ee8SDavid du Colombier void getblk(Ram *r, long bno, char *buf); 48*219b2ee8SDavid du Colombier 49*219b2ee8SDavid du Colombier void 50*219b2ee8SDavid du Colombier populate(char *name) 51*219b2ee8SDavid du Colombier { 52*219b2ee8SDavid du Colombier Fileinf f; 53*219b2ee8SDavid du Colombier 54*219b2ee8SDavid du Colombier replete = 0; 55*219b2ee8SDavid du Colombier tapefile = open(name, OREAD); 56*219b2ee8SDavid du Colombier if (tapefile<0) 57*219b2ee8SDavid du Colombier error("Can't open argument file"); 58*219b2ee8SDavid du Colombier f = iget(VROOT); 59*219b2ee8SDavid du Colombier ram->perm = f.mode; 60*219b2ee8SDavid du Colombier ram->mtime = f.mdate; 61*219b2ee8SDavid du Colombier ram->data = f.addr; 62*219b2ee8SDavid du Colombier ram->ndata = f.size; 63*219b2ee8SDavid du Colombier } 64*219b2ee8SDavid du Colombier 65*219b2ee8SDavid du Colombier void 66*219b2ee8SDavid du Colombier popdir(Ram *r) 67*219b2ee8SDavid du Colombier { 68*219b2ee8SDavid du Colombier int i, ino; 69*219b2ee8SDavid du Colombier char *cp; 70*219b2ee8SDavid du Colombier struct v10dir *dp; 71*219b2ee8SDavid du Colombier Fileinf f; 72*219b2ee8SDavid du Colombier char name[VNAMELEN+1]; 73*219b2ee8SDavid du Colombier 74*219b2ee8SDavid du Colombier for (i=0; i<r->ndata; i+=sizeof(struct v10dir)) { 75*219b2ee8SDavid du Colombier if (i%BLSIZE==0) 76*219b2ee8SDavid du Colombier cp = doread(r, i, BLSIZE); 77*219b2ee8SDavid du Colombier dp = (struct v10dir *)(cp+i%BLSIZE); 78*219b2ee8SDavid du Colombier ino = g2byte(dp->ino); 79*219b2ee8SDavid du Colombier if (strcmp(dp->name, ".")==0 || strcmp(dp->name, "..")==0) 80*219b2ee8SDavid du Colombier continue; 81*219b2ee8SDavid du Colombier if (ino==0) 82*219b2ee8SDavid du Colombier continue; 83*219b2ee8SDavid du Colombier f = iget(ino); 84*219b2ee8SDavid du Colombier strncpy(name, dp->name, VNAMELEN); 85*219b2ee8SDavid du Colombier name[VNAMELEN+1] = '\0'; 86*219b2ee8SDavid du Colombier f.name = name; 87*219b2ee8SDavid du Colombier popfile(r, f); 88*219b2ee8SDavid du Colombier } 89*219b2ee8SDavid du Colombier r->replete = 1; 90*219b2ee8SDavid du Colombier } 91*219b2ee8SDavid du Colombier 92*219b2ee8SDavid du Colombier void 93*219b2ee8SDavid du Colombier dotrunc(Ram *r) 94*219b2ee8SDavid du Colombier { 95*219b2ee8SDavid du Colombier USED(r); 96*219b2ee8SDavid du Colombier } 97*219b2ee8SDavid du Colombier 98*219b2ee8SDavid du Colombier void 99*219b2ee8SDavid du Colombier docreate(Ram *r) 100*219b2ee8SDavid du Colombier { 101*219b2ee8SDavid du Colombier USED(r); 102*219b2ee8SDavid du Colombier } 103*219b2ee8SDavid du Colombier 104*219b2ee8SDavid du Colombier char * 105*219b2ee8SDavid du Colombier doread(Ram *r, long off, long cnt) 106*219b2ee8SDavid du Colombier { 107*219b2ee8SDavid du Colombier static char buf[MAXFDATA+BLSIZE]; 108*219b2ee8SDavid du Colombier int bno, i; 109*219b2ee8SDavid du Colombier 110*219b2ee8SDavid du Colombier bno = off/BLSIZE; 111*219b2ee8SDavid du Colombier off -= bno*BLSIZE; 112*219b2ee8SDavid du Colombier if (cnt>MAXFDATA) 113*219b2ee8SDavid du Colombier error("count too large"); 114*219b2ee8SDavid du Colombier if (off) 115*219b2ee8SDavid du Colombier cnt += BLSIZE-off; 116*219b2ee8SDavid du Colombier i = 0; 117*219b2ee8SDavid du Colombier while (cnt>0) { 118*219b2ee8SDavid du Colombier getblk(r, bno, &buf[i*BLSIZE]); 119*219b2ee8SDavid du Colombier cnt -= BLSIZE; 120*219b2ee8SDavid du Colombier bno++; 121*219b2ee8SDavid du Colombier i++; 122*219b2ee8SDavid du Colombier } 123*219b2ee8SDavid du Colombier return buf+off; 124*219b2ee8SDavid du Colombier } 125*219b2ee8SDavid du Colombier 126*219b2ee8SDavid du Colombier void 127*219b2ee8SDavid du Colombier dowrite(Ram *r, char *buf, long off, long cnt) 128*219b2ee8SDavid du Colombier { 129*219b2ee8SDavid du Colombier USED(r); USED(buf); USED(off); USED(cnt); 130*219b2ee8SDavid du Colombier } 131*219b2ee8SDavid du Colombier 132*219b2ee8SDavid du Colombier int 133*219b2ee8SDavid du Colombier dopermw(Ram *r) 134*219b2ee8SDavid du Colombier { 135*219b2ee8SDavid du Colombier USED(r); 136*219b2ee8SDavid du Colombier return 0; 137*219b2ee8SDavid du Colombier } 138*219b2ee8SDavid du Colombier 139*219b2ee8SDavid du Colombier /* 140*219b2ee8SDavid du Colombier * fetch an i-node 141*219b2ee8SDavid du Colombier * -- no sanity check for now 142*219b2ee8SDavid du Colombier * -- magic inode-to-disk-block stuff here 143*219b2ee8SDavid du Colombier */ 144*219b2ee8SDavid du Colombier 145*219b2ee8SDavid du Colombier Fileinf 146*219b2ee8SDavid du Colombier iget(int ino) 147*219b2ee8SDavid du Colombier { 148*219b2ee8SDavid du Colombier char buf[BLSIZE]; 149*219b2ee8SDavid du Colombier struct v10dinode *dp; 150*219b2ee8SDavid du Colombier long flags, i; 151*219b2ee8SDavid du Colombier Fileinf f; 152*219b2ee8SDavid du Colombier 153*219b2ee8SDavid du Colombier seek(tapefile, BLSIZE*((ino-1)/LINOPB + VSUPERB + 1), 0); 154*219b2ee8SDavid du Colombier if (read(tapefile, buf, BLSIZE) != BLSIZE) 155*219b2ee8SDavid du Colombier error("Can't read inode"); 156*219b2ee8SDavid du Colombier dp = ((struct v10dinode *)buf) + ((ino-1)%LINOPB); 157*219b2ee8SDavid du Colombier flags = g2byte(dp->flags); 158*219b2ee8SDavid du Colombier f.size = g4byte(dp->size); 159*219b2ee8SDavid du Colombier if ((flags&VFMT)==VIFCHR || (flags&VFMT)==VIFBLK) 160*219b2ee8SDavid du Colombier f.size = 0; 161*219b2ee8SDavid du Colombier f.addr = emalloc(VNADDR*sizeof(long)); 162*219b2ee8SDavid du Colombier for (i = 0; i < VNADDR; i++) 163*219b2ee8SDavid du Colombier ((long*)f.addr)[i] = g3byte(dp->addr+3*i); 164*219b2ee8SDavid du Colombier f.mode = flags & VMODE; 165*219b2ee8SDavid du Colombier if ((flags&VFMT)==VIFDIR) 166*219b2ee8SDavid du Colombier f.mode |= CHDIR; 167*219b2ee8SDavid du Colombier f.uid = g2byte(dp->uid); 168*219b2ee8SDavid du Colombier f.gid = g2byte(dp->gid); 169*219b2ee8SDavid du Colombier f.mdate = g4byte(dp->mtime); 170*219b2ee8SDavid du Colombier return f; 171*219b2ee8SDavid du Colombier } 172*219b2ee8SDavid du Colombier 173*219b2ee8SDavid du Colombier void 174*219b2ee8SDavid du Colombier getblk(Ram *r, long bno, char *buf) 175*219b2ee8SDavid du Colombier { 176*219b2ee8SDavid du Colombier long dbno; 177*219b2ee8SDavid du Colombier 178*219b2ee8SDavid du Colombier if ((dbno = bmap(r, bno)) == 0) { 179*219b2ee8SDavid du Colombier memset(buf, 0, BLSIZE); 180*219b2ee8SDavid du Colombier return; 181*219b2ee8SDavid du Colombier } 182*219b2ee8SDavid du Colombier seek(tapefile, dbno*BLSIZE, 0); 183*219b2ee8SDavid du Colombier if (read(tapefile, buf, BLSIZE) != BLSIZE) 184*219b2ee8SDavid du Colombier error("bad read"); 185*219b2ee8SDavid du Colombier } 186*219b2ee8SDavid du Colombier 187*219b2ee8SDavid du Colombier /* 188*219b2ee8SDavid du Colombier * logical to physical block 189*219b2ee8SDavid du Colombier * only singly-indirect files for now 190*219b2ee8SDavid du Colombier */ 191*219b2ee8SDavid du Colombier 192*219b2ee8SDavid du Colombier long 193*219b2ee8SDavid du Colombier bmap(Ram *r, long bno) 194*219b2ee8SDavid du Colombier { 195*219b2ee8SDavid du Colombier unsigned char indbuf[LNINDIR][sizeof(long)]; 196*219b2ee8SDavid du Colombier 197*219b2ee8SDavid du Colombier if (bno < VNADDR-3) 198*219b2ee8SDavid du Colombier return ((long*)r->data)[bno]; 199*219b2ee8SDavid du Colombier if (bno < VNADDR*LNINDIR) { 200*219b2ee8SDavid du Colombier seek(tapefile, ((long *)r->data)[(bno-(VNADDR-3))/LNINDIR+(VNADDR-3)]*BLSIZE, 0); 201*219b2ee8SDavid du Colombier if (read(tapefile, (char *)indbuf, BLSIZE) != BLSIZE) 202*219b2ee8SDavid du Colombier return 0; 203*219b2ee8SDavid du Colombier return ((indbuf[(bno-(VNADDR-3))%LNINDIR][2]<<16) + (indbuf[(bno-(VNADDR-3))%LNINDIR][1]<<8) 204*219b2ee8SDavid du Colombier + indbuf[(bno-(VNADDR-3))%LNINDIR][0]); 205*219b2ee8SDavid du Colombier } 206*219b2ee8SDavid du Colombier return 0; 207*219b2ee8SDavid du Colombier } 208