plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

v10fs.c (3799B)


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