xref: /plan9/sys/src/cmd/tapefs/v10fs.c (revision 9f2726c34299ea5a81cda1b22133dd5a4b421e04)
1219b2ee8SDavid du Colombier /*
2219b2ee8SDavid du Colombier  * 10th edition 4K file system
3219b2ee8SDavid du Colombier  */
4219b2ee8SDavid du Colombier #include <u.h>
5219b2ee8SDavid du Colombier #include <libc.h>
6219b2ee8SDavid du Colombier #include <auth.h>
7219b2ee8SDavid du Colombier #include <fcall.h>
8219b2ee8SDavid du Colombier #include "tapefs.h"
9219b2ee8SDavid du Colombier 
10219b2ee8SDavid du Colombier /*
11219b2ee8SDavid du Colombier  * v10 disk inode
12219b2ee8SDavid du Colombier  */
13219b2ee8SDavid du Colombier #define	VNADDR	13
14219b2ee8SDavid du Colombier #define	VFMT	0160000
15219b2ee8SDavid du Colombier #define	VIFREG	0100000
16219b2ee8SDavid du Colombier #define	VIFDIR	0040000
17219b2ee8SDavid du Colombier #define	VIFCHR	0120000
18219b2ee8SDavid du Colombier #define	VIFBLK	0160000
19219b2ee8SDavid du Colombier #define	VMODE	0777
20219b2ee8SDavid du Colombier #define	VSUPERB	1
21219b2ee8SDavid du Colombier #define	VROOT		2	/* root inode */
22219b2ee8SDavid du Colombier #define	VNAMELEN	14
23219b2ee8SDavid du Colombier #define	BLSIZE	4096
24219b2ee8SDavid du Colombier #define	LINOPB	(BLSIZE/sizeof(struct v10dinode))
25219b2ee8SDavid du Colombier #define	LNINDIR	(BLSIZE/sizeof(unsigned long))
26219b2ee8SDavid du Colombier 
27219b2ee8SDavid du Colombier struct v10dinode {
28219b2ee8SDavid du Colombier 	unsigned char flags[2];
29219b2ee8SDavid du Colombier 	unsigned char nlinks[2];
30219b2ee8SDavid du Colombier 	unsigned char uid[2];
31219b2ee8SDavid du Colombier 	unsigned char gid[2];
32219b2ee8SDavid du Colombier 	unsigned char size[4];
33219b2ee8SDavid du Colombier 	unsigned char addr[40];
34219b2ee8SDavid du Colombier 	unsigned char atime[4];
35219b2ee8SDavid du Colombier 	unsigned char mtime[4];
36219b2ee8SDavid du Colombier 	unsigned char ctime[4];
37219b2ee8SDavid du Colombier };
38219b2ee8SDavid du Colombier 
39219b2ee8SDavid du Colombier struct	v10dir {
40219b2ee8SDavid du Colombier 	uchar	ino[2];
41219b2ee8SDavid du Colombier 	char	name[VNAMELEN];
42219b2ee8SDavid du Colombier };
43219b2ee8SDavid du Colombier 
44219b2ee8SDavid du Colombier int	tapefile;
4529b83c63SDavid du Colombier vlong	tapelen;
46219b2ee8SDavid du Colombier Fileinf	iget(int ino);
47219b2ee8SDavid du Colombier long	bmap(Ram *r, long bno);
48219b2ee8SDavid du Colombier void	getblk(Ram *r, long bno, char *buf);
49219b2ee8SDavid du Colombier 
50219b2ee8SDavid du Colombier void
populate(char * name)51219b2ee8SDavid du Colombier populate(char *name)
52219b2ee8SDavid du Colombier {
53219b2ee8SDavid du Colombier 	Fileinf f;
5429b83c63SDavid du Colombier 	Dir *d;
55219b2ee8SDavid du Colombier 
56219b2ee8SDavid du Colombier 	replete = 0;
57219b2ee8SDavid du Colombier 	tapefile = open(name, OREAD);
58219b2ee8SDavid du Colombier 	if (tapefile<0)
59219b2ee8SDavid du Colombier 		error("Can't open argument file");
6029b83c63SDavid du Colombier 	if ((d=dirfstat(tapefile)) == nil)
6129b83c63SDavid du Colombier 		error("dirfstat");
6229b83c63SDavid du Colombier 	tapelen = d->length;
6329b83c63SDavid du Colombier 	free(d);
64219b2ee8SDavid du Colombier 	f = iget(VROOT);
65219b2ee8SDavid du Colombier 	ram->perm = f.mode;
66219b2ee8SDavid du Colombier 	ram->mtime = f.mdate;
6741fe996aSDavid du Colombier 	ram->addr = f.addr;
6841fe996aSDavid du Colombier 	ram->data = f.data;
69219b2ee8SDavid du Colombier 	ram->ndata = f.size;
70219b2ee8SDavid du Colombier }
71219b2ee8SDavid du Colombier 
72219b2ee8SDavid du Colombier void
popdir(Ram * r)73219b2ee8SDavid du Colombier popdir(Ram *r)
74219b2ee8SDavid du Colombier {
75219b2ee8SDavid du Colombier 	int i, ino;
76219b2ee8SDavid du Colombier 	char *cp;
77219b2ee8SDavid du Colombier 	struct v10dir *dp;
78219b2ee8SDavid du Colombier 	Fileinf f;
79219b2ee8SDavid du Colombier 	char name[VNAMELEN+1];
80219b2ee8SDavid du Colombier 
817dd7cddfSDavid du Colombier 	cp = 0;
82219b2ee8SDavid du Colombier 	for (i=0; i<r->ndata; i+=sizeof(struct v10dir)) {
83219b2ee8SDavid du Colombier 		if (i%BLSIZE==0)
84219b2ee8SDavid du Colombier 			cp = doread(r, i, BLSIZE);
85219b2ee8SDavid du Colombier 		dp = (struct v10dir *)(cp+i%BLSIZE);
86219b2ee8SDavid du Colombier 		ino = g2byte(dp->ino);
87219b2ee8SDavid du Colombier 		if (strcmp(dp->name, ".")==0 || strcmp(dp->name, "..")==0)
88219b2ee8SDavid du Colombier 			continue;
89219b2ee8SDavid du Colombier 		if (ino==0)
90219b2ee8SDavid du Colombier 			continue;
91219b2ee8SDavid du Colombier 		f = iget(ino);
92219b2ee8SDavid du Colombier 		strncpy(name, dp->name, VNAMELEN);
93*9f2726c3SDavid du Colombier 		name[VNAMELEN] = '\0';
94219b2ee8SDavid du Colombier 		f.name = name;
95219b2ee8SDavid du Colombier 		popfile(r, f);
96219b2ee8SDavid du Colombier 	}
97219b2ee8SDavid du Colombier 	r->replete = 1;
98219b2ee8SDavid du Colombier }
99219b2ee8SDavid du Colombier 
100219b2ee8SDavid du Colombier void
dotrunc(Ram * r)101219b2ee8SDavid du Colombier dotrunc(Ram *r)
102219b2ee8SDavid du Colombier {
103219b2ee8SDavid du Colombier 	USED(r);
104219b2ee8SDavid du Colombier }
105219b2ee8SDavid du Colombier 
106219b2ee8SDavid du Colombier void
docreate(Ram * r)107219b2ee8SDavid du Colombier docreate(Ram *r)
108219b2ee8SDavid du Colombier {
109219b2ee8SDavid du Colombier 	USED(r);
110219b2ee8SDavid du Colombier }
111219b2ee8SDavid du Colombier 
112219b2ee8SDavid du Colombier char *
doread(Ram * r,vlong off,long cnt)11341fe996aSDavid du Colombier doread(Ram *r, vlong off, long cnt)
114219b2ee8SDavid du Colombier {
1159a747e4fSDavid du Colombier 	static char buf[Maxbuf+BLSIZE];
116219b2ee8SDavid du Colombier 	int bno, i;
117219b2ee8SDavid du Colombier 
118219b2ee8SDavid du Colombier 	bno = off/BLSIZE;
119219b2ee8SDavid du Colombier 	off -= bno*BLSIZE;
1209a747e4fSDavid du Colombier 	if (cnt>Maxbuf)
121219b2ee8SDavid du Colombier 		error("count too large");
122219b2ee8SDavid du Colombier 	if (off)
1237dd7cddfSDavid du Colombier 		cnt += off;
124219b2ee8SDavid du Colombier 	i = 0;
125219b2ee8SDavid du Colombier 	while (cnt>0) {
126219b2ee8SDavid du Colombier 		getblk(r, bno, &buf[i*BLSIZE]);
127219b2ee8SDavid du Colombier 		cnt -= BLSIZE;
128219b2ee8SDavid du Colombier 		bno++;
129219b2ee8SDavid du Colombier 		i++;
130219b2ee8SDavid du Colombier 	}
131219b2ee8SDavid du Colombier 	return buf+off;
132219b2ee8SDavid du Colombier }
133219b2ee8SDavid du Colombier 
134219b2ee8SDavid du Colombier void
dowrite(Ram * r,char * buf,long off,long cnt)135219b2ee8SDavid du Colombier dowrite(Ram *r, char *buf, long off, long cnt)
136219b2ee8SDavid du Colombier {
137219b2ee8SDavid du Colombier 	USED(r); USED(buf); USED(off); USED(cnt);
138219b2ee8SDavid du Colombier }
139219b2ee8SDavid du Colombier 
140219b2ee8SDavid du Colombier int
dopermw(Ram * r)141219b2ee8SDavid du Colombier dopermw(Ram *r)
142219b2ee8SDavid du Colombier {
143219b2ee8SDavid du Colombier 	USED(r);
144219b2ee8SDavid du Colombier 	return 0;
145219b2ee8SDavid du Colombier }
146219b2ee8SDavid du Colombier 
147219b2ee8SDavid du Colombier /*
148219b2ee8SDavid du Colombier  * fetch an i-node
149219b2ee8SDavid du Colombier  * -- no sanity check for now
150219b2ee8SDavid du Colombier  * -- magic inode-to-disk-block stuff here
151219b2ee8SDavid du Colombier  */
152219b2ee8SDavid du Colombier 
153219b2ee8SDavid du Colombier Fileinf
iget(int ino)154219b2ee8SDavid du Colombier iget(int ino)
155219b2ee8SDavid du Colombier {
156219b2ee8SDavid du Colombier 	char buf[BLSIZE];
157219b2ee8SDavid du Colombier 	struct v10dinode *dp;
158219b2ee8SDavid du Colombier 	long flags, i;
159219b2ee8SDavid du Colombier 	Fileinf f;
160219b2ee8SDavid du Colombier 
161219b2ee8SDavid du Colombier 	seek(tapefile, BLSIZE*((ino-1)/LINOPB + VSUPERB + 1), 0);
162219b2ee8SDavid du Colombier 	if (read(tapefile, buf, BLSIZE) != BLSIZE)
163219b2ee8SDavid du Colombier 		error("Can't read inode");
164219b2ee8SDavid du Colombier 	dp = ((struct v10dinode *)buf) + ((ino-1)%LINOPB);
165219b2ee8SDavid du Colombier 	flags = g2byte(dp->flags);
166219b2ee8SDavid du Colombier 	f.size = g4byte(dp->size);
167219b2ee8SDavid du Colombier 	if ((flags&VFMT)==VIFCHR || (flags&VFMT)==VIFBLK)
168219b2ee8SDavid du Colombier 		f.size = 0;
16941fe996aSDavid du Colombier 	f.data = emalloc(VNADDR*sizeof(long));
170219b2ee8SDavid du Colombier 	for (i = 0; i < VNADDR; i++)
17141fe996aSDavid du Colombier 		((long*)f.data)[i] = g3byte(dp->addr+3*i);
172219b2ee8SDavid du Colombier 	f.mode = flags & VMODE;
173219b2ee8SDavid du Colombier 	if ((flags&VFMT)==VIFDIR)
1749a747e4fSDavid du Colombier 		f.mode |= DMDIR;
175219b2ee8SDavid du Colombier 	f.uid = g2byte(dp->uid);
176219b2ee8SDavid du Colombier 	f.gid = g2byte(dp->gid);
177219b2ee8SDavid du Colombier 	f.mdate = g4byte(dp->mtime);
178219b2ee8SDavid du Colombier 	return f;
179219b2ee8SDavid du Colombier }
180219b2ee8SDavid du Colombier 
181219b2ee8SDavid du Colombier void
getblk(Ram * r,long bno,char * buf)182219b2ee8SDavid du Colombier getblk(Ram *r, long bno, char *buf)
183219b2ee8SDavid du Colombier {
184219b2ee8SDavid du Colombier 	long dbno;
185219b2ee8SDavid du Colombier 
186219b2ee8SDavid du Colombier 	if ((dbno = bmap(r, bno)) == 0) {
187219b2ee8SDavid du Colombier 		memset(buf, 0, BLSIZE);
188219b2ee8SDavid du Colombier 		return;
189219b2ee8SDavid du Colombier 	}
19029b83c63SDavid du Colombier 	if ((vlong)(dbno+1)*BLSIZE > tapelen) {
19129b83c63SDavid du Colombier 		fprint(2, "read past end of tape: %lld\n", (vlong)dbno*BLSIZE);
19229b83c63SDavid du Colombier 		memset(buf, 0, BLSIZE);
19329b83c63SDavid du Colombier 		return;
19429b83c63SDavid du Colombier 	}
195219b2ee8SDavid du Colombier 	seek(tapefile, dbno*BLSIZE, 0);
19629b83c63SDavid du Colombier 	if (readn(tapefile, buf, BLSIZE) != BLSIZE){
19729b83c63SDavid du Colombier 		fprint(2, "readn at %lld: %r\n", (vlong)dbno*BLSIZE);
198219b2ee8SDavid du Colombier 		error("bad read");
199219b2ee8SDavid du Colombier 	}
20029b83c63SDavid du Colombier }
201219b2ee8SDavid du Colombier 
202219b2ee8SDavid du Colombier /*
203219b2ee8SDavid du Colombier  * logical to physical block
204219b2ee8SDavid du Colombier  * only singly-indirect files for now
205219b2ee8SDavid du Colombier  */
206219b2ee8SDavid du Colombier 
207219b2ee8SDavid du Colombier long
bmap(Ram * r,long bno)208219b2ee8SDavid du Colombier bmap(Ram *r, long bno)
209219b2ee8SDavid du Colombier {
210219b2ee8SDavid du Colombier 	unsigned char indbuf[LNINDIR][sizeof(long)];
211219b2ee8SDavid du Colombier 
212219b2ee8SDavid du Colombier 	if (bno < VNADDR-3)
213219b2ee8SDavid du Colombier 		return ((long*)r->data)[bno];
214219b2ee8SDavid du Colombier 	if (bno < VNADDR*LNINDIR) {
215219b2ee8SDavid du Colombier 		seek(tapefile, ((long *)r->data)[(bno-(VNADDR-3))/LNINDIR+(VNADDR-3)]*BLSIZE, 0);
216219b2ee8SDavid du Colombier 		if (read(tapefile, (char *)indbuf, BLSIZE) != BLSIZE)
217219b2ee8SDavid du Colombier 			return 0;
218219b2ee8SDavid du Colombier 		return ((indbuf[(bno-(VNADDR-3))%LNINDIR][2]<<16) + (indbuf[(bno-(VNADDR-3))%LNINDIR][1]<<8)
219219b2ee8SDavid du Colombier 			+ indbuf[(bno-(VNADDR-3))%LNINDIR][0]);
220219b2ee8SDavid du Colombier 	}
221219b2ee8SDavid du Colombier 	return 0;
222219b2ee8SDavid du Colombier }
223