xref: /plan9-contrib/sys/src/cmd/tapefs/32vfs.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1 /*
2  * Vax 32V Unix filesystem (same as pre-FFS Berkeley)
3  */
4 #include <u.h>
5 #include <libc.h>
6 #include <auth.h>
7 #include <fcall.h>
8 #include "tapefs.h"
9 
10 /*
11  * v32 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	512
24 #define	LINOPB	(BLSIZE/sizeof(struct v32dinode))
25 #define	LNINDIR	(BLSIZE/sizeof(unsigned long))
26 
27 struct v32dinode {
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	v32dir {
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->data = f.addr;
62 	ram->ndata = f.size;
63 }
64 
65 void
66 popdir(Ram *r)
67 {
68 	int i, ino;
69 	char *cp;
70 	struct v32dir *dp;
71 	Fileinf f;
72 	char name[VNAMELEN+1];
73 
74 	for (i=0; i<r->ndata; i+=sizeof(struct v32dir)) {
75 		if (i%BLSIZE==0)
76 			cp = doread(r, i, BLSIZE);
77 		dp = (struct v32dir *)(cp+i%BLSIZE);
78 		ino = g2byte(dp->ino);
79 		if (strcmp(dp->name, ".")==0 || strcmp(dp->name, "..")==0)
80 			continue;
81 		if (ino==0)
82 			continue;
83 		f = iget(ino);
84 		strncpy(name, dp->name, VNAMELEN);
85 		name[VNAMELEN+1] = '\0';
86 		f.name = name;
87 		popfile(r, f);
88 	}
89 	r->replete = 1;
90 }
91 
92 void
93 dotrunc(Ram *r)
94 {
95 	USED(r);
96 }
97 
98 void
99 docreate(Ram *r)
100 {
101 	USED(r);
102 }
103 
104 char *
105 doread(Ram *r, long off, long cnt)
106 {
107 	static char buf[MAXFDATA+BLSIZE];
108 	int bno, i;
109 
110 	bno = off/BLSIZE;
111 	off -= bno*BLSIZE;
112 	if (cnt>MAXFDATA)
113 		error("count too large");
114 	if (off)
115 		cnt += BLSIZE-off;
116 	i = 0;
117 	while (cnt>0) {
118 		getblk(r, bno, &buf[i*BLSIZE]);
119 		cnt -= BLSIZE;
120 		bno++;
121 		i++;
122 	}
123 	return buf;
124 }
125 
126 void
127 dowrite(Ram *r, char *buf, long off, long cnt)
128 {
129 	USED(r); USED(buf); USED(off); USED(cnt);
130 }
131 
132 int
133 dopermw(Ram *r)
134 {
135 	USED(r);
136 	return 0;
137 }
138 
139 /*
140  * fetch an i-node
141  * -- no sanity check for now
142  * -- magic inode-to-disk-block stuff here
143  */
144 
145 Fileinf
146 iget(int ino)
147 {
148 	char buf[BLSIZE];
149 	struct v32dinode *dp;
150 	long flags, i;
151 	Fileinf f;
152 
153 	seek(tapefile, BLSIZE*((ino-1)/LINOPB + VSUPERB + 1), 0);
154 	if (read(tapefile, buf, BLSIZE) != BLSIZE)
155 		error("Can't read inode");
156 	dp = ((struct v32dinode *)buf) + ((ino-1)%LINOPB);
157 	flags = g2byte(dp->flags);
158 	f.size = g4byte(dp->size);
159 	if ((flags&VFMT)==VIFCHR || (flags&VFMT)==VIFBLK)
160 		f.size = 0;
161 	f.addr = emalloc(VNADDR*sizeof(long));
162 	for (i = 0; i < VNADDR; i++)
163 		((long*)f.addr)[i] = g3byte(dp->addr+3*i);
164 	f.mode = flags & VMODE;
165 	if ((flags&VFMT)==VIFDIR)
166 		f.mode |= CHDIR;
167 	f.uid = g2byte(dp->uid);
168 	f.gid = g2byte(dp->gid);
169 	f.mdate = g4byte(dp->mtime);
170 	return f;
171 }
172 
173 void
174 getblk(Ram *r, long bno, char *buf)
175 {
176 	long dbno;
177 
178 	if ((dbno = bmap(r, bno)) == 0) {
179 		memset(buf, 0, BLSIZE);
180 		return;
181 	}
182 	seek(tapefile, dbno*BLSIZE, 0);
183 	if (read(tapefile, buf, BLSIZE) != BLSIZE)
184 		error("bad read");
185 }
186 
187 /*
188  * logical to physical block
189  * only singly-indirect files for now
190  */
191 
192 long
193 bmap(Ram *r, long bno)
194 {
195 	unsigned char indbuf[LNINDIR][sizeof(long)];
196 
197 	if (bno < VNADDR-3)
198 		return ((long*)r->data)[bno];
199 	if (bno < VNADDR*LNINDIR) {
200 		seek(tapefile, ((long *)r->data)[(bno-(VNADDR-3))/LNINDIR]*BLSIZE, 0);
201 		if (read(tapefile, (char *)indbuf, BLSIZE) != BLSIZE)
202 			return 0;
203 		return ((indbuf[bno%LNINDIR][1]<<8) + indbuf[bno%LNINDIR][0]);
204 	}
205 	return 0;
206 }
207