xref: /plan9/sys/src/cmd/tapefs/fs.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1bd389b36SDavid du Colombier #include <u.h>
2bd389b36SDavid du Colombier #include <libc.h>
3*219b2ee8SDavid du Colombier #include <auth.h>
4bd389b36SDavid du Colombier #include <fcall.h>
5bd389b36SDavid du Colombier #include <tapefs.h>
6bd389b36SDavid du Colombier 
7bd389b36SDavid du Colombier Fid	*fids;
8bd389b36SDavid du Colombier Ram	*ram;
9bd389b36SDavid du Colombier int	mfd[2];
10bd389b36SDavid du Colombier char	user[NAMELEN];
11bd389b36SDavid du Colombier char	mdata[MAXMSG+MAXFDATA];
12bd389b36SDavid du Colombier Fcall	rhdr;
13bd389b36SDavid du Colombier Fcall	thdr;
14bd389b36SDavid du Colombier ulong	path;
15bd389b36SDavid du Colombier Idmap	*uidmap;
16bd389b36SDavid du Colombier Idmap	*gidmap;
17bd389b36SDavid du Colombier int	replete;
18bd389b36SDavid du Colombier 
19bd389b36SDavid du Colombier Fid *	newfid(int);
20bd389b36SDavid du Colombier void	ramstat(Ram*, char*);
21bd389b36SDavid du Colombier void	io(void);
22bd389b36SDavid du Colombier void	usage(void);
23bd389b36SDavid du Colombier int	perm(Fid*, Ram*, int);
24bd389b36SDavid du Colombier 
25bd389b36SDavid du Colombier char	*rflush(Fid*), *rnop(Fid*), *rsession(Fid*),
26bd389b36SDavid du Colombier 	*rattach(Fid*), *rclone(Fid*), *rwalk(Fid*),
27bd389b36SDavid du Colombier 	*rclwalk(Fid*), *ropen(Fid*), *rcreate(Fid*),
28bd389b36SDavid du Colombier 	*rread(Fid*), *rwrite(Fid*), *rclunk(Fid*),
29bd389b36SDavid du Colombier 	*rremove(Fid*), *rstat(Fid*), *rwstat(Fid*),
30bd389b36SDavid du Colombier 	*rauth(Fid*);
31bd389b36SDavid du Colombier 
32bd389b36SDavid du Colombier char 	*(*fcalls[])(Fid*) = {
33bd389b36SDavid du Colombier 	[Tflush]	rflush,
34bd389b36SDavid du Colombier 	[Tsession]	rsession,
35bd389b36SDavid du Colombier 	[Tnop]		rnop,
36bd389b36SDavid du Colombier 	[Tattach]	rattach,
37bd389b36SDavid du Colombier 	[Tclone]	rclone,
38bd389b36SDavid du Colombier 	[Twalk]		rwalk,
39bd389b36SDavid du Colombier 	[Tclwalk]	rclwalk,
40bd389b36SDavid du Colombier 	[Topen]		ropen,
41bd389b36SDavid du Colombier 	[Tcreate]	rcreate,
42bd389b36SDavid du Colombier 	[Tread]		rread,
43bd389b36SDavid du Colombier 	[Twrite]	rwrite,
44bd389b36SDavid du Colombier 	[Tclunk]	rclunk,
45bd389b36SDavid du Colombier 	[Tremove]	rremove,
46bd389b36SDavid du Colombier 	[Tstat]		rstat,
47bd389b36SDavid du Colombier 	[Twstat]	rwstat,
48bd389b36SDavid du Colombier };
49bd389b36SDavid du Colombier 
50bd389b36SDavid du Colombier char	Eperm[] =	"permission denied";
51bd389b36SDavid du Colombier char	Enotdir[] =	"not a directory";
52bd389b36SDavid du Colombier char	Enoauth[] =	"no authentication in ramfs";
53bd389b36SDavid du Colombier char	Enotexist[] =	"file does not exist";
54bd389b36SDavid du Colombier char	Einuse[] =	"file in use";
55bd389b36SDavid du Colombier char	Eexist[] =	"file exists";
56bd389b36SDavid du Colombier char	Enotowner[] =	"not owner";
57bd389b36SDavid du Colombier char	Eisopen[] = 	"file already open for I/O";
58bd389b36SDavid du Colombier char	Excl[] = 	"exclusive use file already open";
59bd389b36SDavid du Colombier char	Ename[] = 	"illegal name";
60bd389b36SDavid du Colombier 
61bd389b36SDavid du Colombier void
62bd389b36SDavid du Colombier notifyf(void *a, char *s)
63bd389b36SDavid du Colombier {
64bd389b36SDavid du Colombier 	USED(a);
65bd389b36SDavid du Colombier 	if(strncmp(s, "interrupt", 9) == 0)
66bd389b36SDavid du Colombier 		noted(NCONT);
67bd389b36SDavid du Colombier 	noted(NDFLT);
68bd389b36SDavid du Colombier }
69bd389b36SDavid du Colombier 
70bd389b36SDavid du Colombier void
71bd389b36SDavid du Colombier main(int argc, char *argv[])
72bd389b36SDavid du Colombier {
73bd389b36SDavid du Colombier 	Ram *r;
74bd389b36SDavid du Colombier 	char *defmnt;
75bd389b36SDavid du Colombier 	int p[2];
76bd389b36SDavid du Colombier 
77*219b2ee8SDavid du Colombier 	defmnt = "/n/tapefs";
78bd389b36SDavid du Colombier 	ARGBEGIN{
79bd389b36SDavid du Colombier 	case 'm':
80bd389b36SDavid du Colombier 		defmnt = ARGF();
81bd389b36SDavid du Colombier 		break;
82bd389b36SDavid du Colombier 	case 'p':			/* password file */
83bd389b36SDavid du Colombier 		uidmap = getpass(ARGF());
84bd389b36SDavid du Colombier 		break;
85bd389b36SDavid du Colombier 	case 'g':			/* group file */
86bd389b36SDavid du Colombier 		gidmap = getpass(ARGF());
87bd389b36SDavid du Colombier 		break;
88bd389b36SDavid du Colombier 	default:
89bd389b36SDavid du Colombier 		usage();
90bd389b36SDavid du Colombier 	}ARGEND
91bd389b36SDavid du Colombier 
92bd389b36SDavid du Colombier 	if (argc==0)
93bd389b36SDavid du Colombier 		error("no file to mount");
94bd389b36SDavid du Colombier 	ram = r = (Ram *)emalloc(sizeof(Ram));
95bd389b36SDavid du Colombier 	r->busy = 1;
96bd389b36SDavid du Colombier 	r->data = 0;
97bd389b36SDavid du Colombier 	r->ndata = 0;
98bd389b36SDavid du Colombier 	r->perm = CHDIR | 0775;
99bd389b36SDavid du Colombier 	r->qid.path = CHDIR;
100bd389b36SDavid du Colombier 	r->qid.vers = 0;
101bd389b36SDavid du Colombier 	r->parent = 0;
102bd389b36SDavid du Colombier 	r->child = 0;
103bd389b36SDavid du Colombier 	r->next = 0;
104bd389b36SDavid du Colombier 	r->user = user;
105bd389b36SDavid du Colombier 	r->group = user;
106bd389b36SDavid du Colombier 	r->atime = time(0);
107bd389b36SDavid du Colombier 	r->mtime = r->atime;
108bd389b36SDavid du Colombier 	r->replete = 0;
109bd389b36SDavid du Colombier 	strcpy(r->name, ".");
110bd389b36SDavid du Colombier 	strcpy(user, getuser());
111bd389b36SDavid du Colombier 	populate(argv[0]);
112bd389b36SDavid du Colombier 	r->replete |= replete;
113bd389b36SDavid du Colombier 	if(pipe(p) < 0)
114bd389b36SDavid du Colombier 		error("pipe failed");
115bd389b36SDavid du Colombier 	mfd[0] = mfd[1] = p[0];
116bd389b36SDavid du Colombier 	notify(notifyf);
117bd389b36SDavid du Colombier 
118bd389b36SDavid du Colombier 	switch(rfork(RFFDG|RFPROC|RFNAMEG|RFNOTEG)){
119bd389b36SDavid du Colombier 	case -1:
120bd389b36SDavid du Colombier 		error("fork");
121bd389b36SDavid du Colombier 	case 0:
122bd389b36SDavid du Colombier 		close(p[1]);
123bd389b36SDavid du Colombier 		notify(notifyf);
124bd389b36SDavid du Colombier 		io();
125bd389b36SDavid du Colombier 		break;
126bd389b36SDavid du Colombier 	default:
127bd389b36SDavid du Colombier 		close(p[0]);	/* don't deadlock if child fails */
128*219b2ee8SDavid du Colombier 		if(mount(p[1], defmnt, MREPL|MCREATE, "") < 0) {
129*219b2ee8SDavid du Colombier 			char buf[256];
130*219b2ee8SDavid du Colombier 			sprint(buf, "mount on `%s' failed", defmnt);
131*219b2ee8SDavid du Colombier 			error(buf);
132*219b2ee8SDavid du Colombier 		}
133bd389b36SDavid du Colombier 	}
134bd389b36SDavid du Colombier 	exits(0);
135bd389b36SDavid du Colombier }
136bd389b36SDavid du Colombier 
137bd389b36SDavid du Colombier char*
138bd389b36SDavid du Colombier rnop(Fid *f)
139bd389b36SDavid du Colombier {
140bd389b36SDavid du Colombier 	USED(f);
141bd389b36SDavid du Colombier 	return 0;
142bd389b36SDavid du Colombier }
143bd389b36SDavid du Colombier 
144bd389b36SDavid du Colombier char*
145bd389b36SDavid du Colombier rsession(Fid *unused)
146bd389b36SDavid du Colombier {
147bd389b36SDavid du Colombier 	Fid *f;
148bd389b36SDavid du Colombier 
149bd389b36SDavid du Colombier 	USED(unused);
150bd389b36SDavid du Colombier 
151*219b2ee8SDavid du Colombier 	memset(thdr.authid, 0, sizeof(thdr.authid));
152*219b2ee8SDavid du Colombier 	memset(thdr.authdom, 0, sizeof(thdr.authdom));
153*219b2ee8SDavid du Colombier 	memset(thdr.chal, 0, sizeof(thdr.chal));
154bd389b36SDavid du Colombier 	for(f = fids; f; f = f->next)
155bd389b36SDavid du Colombier 		if(f->busy)
156bd389b36SDavid du Colombier 			rclunk(f);
157bd389b36SDavid du Colombier 	return 0;
158bd389b36SDavid du Colombier }
159bd389b36SDavid du Colombier 
160bd389b36SDavid du Colombier char*
161bd389b36SDavid du Colombier rflush(Fid *f)
162bd389b36SDavid du Colombier {
163bd389b36SDavid du Colombier 	USED(f);
164bd389b36SDavid du Colombier 	return 0;
165bd389b36SDavid du Colombier }
166bd389b36SDavid du Colombier 
167bd389b36SDavid du Colombier char*
168bd389b36SDavid du Colombier rattach(Fid *f)
169bd389b36SDavid du Colombier {
170bd389b36SDavid du Colombier 	/* no authentication! */
171bd389b36SDavid du Colombier 	f->busy = 1;
172bd389b36SDavid du Colombier 	f->rclose = 0;
173bd389b36SDavid du Colombier 	f->ram = ram;
174bd389b36SDavid du Colombier 	thdr.qid = f->ram->qid;
175bd389b36SDavid du Colombier 	if(rhdr.uname[0])
176bd389b36SDavid du Colombier 		f->user = strdup(rhdr.uname);
177bd389b36SDavid du Colombier 	else
178bd389b36SDavid du Colombier 		f->user = "none";
179bd389b36SDavid du Colombier 	return 0;
180bd389b36SDavid du Colombier }
181bd389b36SDavid du Colombier 
182bd389b36SDavid du Colombier char*
183bd389b36SDavid du Colombier rclone(Fid *f)
184bd389b36SDavid du Colombier {
185bd389b36SDavid du Colombier 	Fid *nf;
186bd389b36SDavid du Colombier 
187bd389b36SDavid du Colombier 	if(f->open)
188bd389b36SDavid du Colombier 		return Eisopen;
189bd389b36SDavid du Colombier 	if(f->ram->busy == 0)
190bd389b36SDavid du Colombier 		return Enotexist;
191bd389b36SDavid du Colombier 	nf = newfid(rhdr.newfid);
192bd389b36SDavid du Colombier 	nf->busy = 1;
193bd389b36SDavid du Colombier 	nf->open = 0;
194bd389b36SDavid du Colombier 	nf->rclose = 0;
195bd389b36SDavid du Colombier 	nf->ram = f->ram;
196bd389b36SDavid du Colombier 	nf->user = f->user;	/* no ref count; the leakage is minor */
197bd389b36SDavid du Colombier 	return 0;
198bd389b36SDavid du Colombier }
199bd389b36SDavid du Colombier 
200bd389b36SDavid du Colombier char*
201bd389b36SDavid du Colombier rwalk(Fid *f)
202bd389b36SDavid du Colombier {
203bd389b36SDavid du Colombier 	Ram *r;
204bd389b36SDavid du Colombier 	char *name;
205bd389b36SDavid du Colombier 	Ram *dir;
206bd389b36SDavid du Colombier 
207bd389b36SDavid du Colombier 	if((f->ram->qid.path & CHDIR) == 0)
208bd389b36SDavid du Colombier 		return Enotdir;
209bd389b36SDavid du Colombier 	if(f->ram->busy == 0)
210bd389b36SDavid du Colombier 		return Enotexist;
211bd389b36SDavid du Colombier 	f->ram->atime = time(0);
212bd389b36SDavid du Colombier 	name = rhdr.name;
213bd389b36SDavid du Colombier 	if(strcmp(name, ".") == 0){
214bd389b36SDavid du Colombier 		thdr.qid = f->ram->qid;
215bd389b36SDavid du Colombier 		return 0;
216bd389b36SDavid du Colombier 	}
217bd389b36SDavid du Colombier 	dir = f->ram;
218bd389b36SDavid du Colombier 	if(!dir || !perm(f, dir, Pexec))
219bd389b36SDavid du Colombier 		return Eperm;
220bd389b36SDavid du Colombier 	if(strcmp(name, "..") == 0){
221bd389b36SDavid du Colombier 		f->ram = dir->parent;
222bd389b36SDavid du Colombier 		thdr.qid = f->ram->qid;
223bd389b36SDavid du Colombier 		return 0;
224bd389b36SDavid du Colombier 	}
225bd389b36SDavid du Colombier 	if (!dir->replete)
226bd389b36SDavid du Colombier 		popdir(dir);
227bd389b36SDavid du Colombier 	for(r=dir->child; r; r=r->next)
228bd389b36SDavid du Colombier 		if(r->busy && strcmp(name, r->name)==0){
229bd389b36SDavid du Colombier 			thdr.qid = r->qid;
230bd389b36SDavid du Colombier 			f->ram = r;
231bd389b36SDavid du Colombier 			return 0;
232bd389b36SDavid du Colombier 		}
233bd389b36SDavid du Colombier 	return Enotexist;
234bd389b36SDavid du Colombier }
235bd389b36SDavid du Colombier 
236bd389b36SDavid du Colombier char *
237bd389b36SDavid du Colombier rclwalk(Fid *f)
238bd389b36SDavid du Colombier {
239bd389b36SDavid du Colombier 	Fid *nf;
240bd389b36SDavid du Colombier 	char *err;
241bd389b36SDavid du Colombier 
242bd389b36SDavid du Colombier 	nf = newfid(rhdr.newfid);
243bd389b36SDavid du Colombier 	nf->busy = 1;
244bd389b36SDavid du Colombier 	nf->rclose = 0;
245bd389b36SDavid du Colombier 	nf->ram = f->ram;
246bd389b36SDavid du Colombier 	nf->user = f->user;
247bd389b36SDavid du Colombier 	if(err = rwalk(nf))
248bd389b36SDavid du Colombier 		rclunk(nf);
249bd389b36SDavid du Colombier 	return err;
250bd389b36SDavid du Colombier }
251bd389b36SDavid du Colombier 
252bd389b36SDavid du Colombier char *
253bd389b36SDavid du Colombier ropen(Fid *f)
254bd389b36SDavid du Colombier {
255bd389b36SDavid du Colombier 	Ram *r;
256bd389b36SDavid du Colombier 	int mode, trunc;
257bd389b36SDavid du Colombier 
258bd389b36SDavid du Colombier 	if(f->open)
259bd389b36SDavid du Colombier 		return Eisopen;
260bd389b36SDavid du Colombier 	r = f->ram;
261bd389b36SDavid du Colombier 	if(r->busy == 0)
262bd389b36SDavid du Colombier 		return Enotexist;
263bd389b36SDavid du Colombier 	if(r->perm & CHEXCL)
264bd389b36SDavid du Colombier 		if(r->open)
265bd389b36SDavid du Colombier 			return Excl;
266bd389b36SDavid du Colombier 	mode = rhdr.mode;
267bd389b36SDavid du Colombier 	if(r->qid.path & CHDIR){
268bd389b36SDavid du Colombier 		if(mode != OREAD)
269bd389b36SDavid du Colombier 			return Eperm;
270bd389b36SDavid du Colombier 		thdr.qid = r->qid;
271bd389b36SDavid du Colombier 		return 0;
272bd389b36SDavid du Colombier 	}
273bd389b36SDavid du Colombier 	if(mode & ORCLOSE)
274bd389b36SDavid du Colombier 		return Eperm;
275bd389b36SDavid du Colombier 	trunc = mode & OTRUNC;
276bd389b36SDavid du Colombier 	mode &= OPERM;
277bd389b36SDavid du Colombier 	if(mode==OWRITE || mode==ORDWR || trunc)
278bd389b36SDavid du Colombier 		if(!perm(f, r, Pwrite))
279bd389b36SDavid du Colombier 			return Eperm;
280bd389b36SDavid du Colombier 	if(mode==OREAD || mode==ORDWR)
281bd389b36SDavid du Colombier 		if(!perm(f, r, Pread))
282bd389b36SDavid du Colombier 			return Eperm;
283bd389b36SDavid du Colombier 	if(mode==OEXEC)
284bd389b36SDavid du Colombier 		if(!perm(f, r, Pexec))
285bd389b36SDavid du Colombier 			return Eperm;
286bd389b36SDavid du Colombier 	if(trunc && (r->perm&CHAPPEND)==0){
287bd389b36SDavid du Colombier 		r->ndata = 0;
288bd389b36SDavid du Colombier 		dotrunc(r);
289bd389b36SDavid du Colombier 		r->qid.vers++;
290bd389b36SDavid du Colombier 	}
291bd389b36SDavid du Colombier 	thdr.qid = r->qid;
292bd389b36SDavid du Colombier 	f->open = 1;
293bd389b36SDavid du Colombier 	r->open++;
294bd389b36SDavid du Colombier 	return 0;
295bd389b36SDavid du Colombier }
296bd389b36SDavid du Colombier 
297bd389b36SDavid du Colombier char *
298bd389b36SDavid du Colombier rcreate(Fid *f)
299bd389b36SDavid du Colombier {
300bd389b36SDavid du Colombier 	USED(f);
301bd389b36SDavid du Colombier 
302bd389b36SDavid du Colombier 	return Eperm;
303bd389b36SDavid du Colombier }
304bd389b36SDavid du Colombier 
305bd389b36SDavid du Colombier char*
306bd389b36SDavid du Colombier rread(Fid *f)
307bd389b36SDavid du Colombier {
308bd389b36SDavid du Colombier 	Ram *r;
309bd389b36SDavid du Colombier 	char *buf;
310bd389b36SDavid du Colombier 	long off;
311bd389b36SDavid du Colombier 	int n, cnt;
312bd389b36SDavid du Colombier 
313bd389b36SDavid du Colombier 	if(f->ram->busy == 0)
314bd389b36SDavid du Colombier 		return Enotexist;
315bd389b36SDavid du Colombier 	n = 0;
316bd389b36SDavid du Colombier 	thdr.count = 0;
317bd389b36SDavid du Colombier 	off = rhdr.offset;
318bd389b36SDavid du Colombier 	cnt = rhdr.count;
319bd389b36SDavid du Colombier 	buf = thdr.data;
320bd389b36SDavid du Colombier 	if(f->ram->qid.path & CHDIR){
321bd389b36SDavid du Colombier 		if (!f->ram->replete)
322bd389b36SDavid du Colombier 			popdir(f->ram);
323bd389b36SDavid du Colombier 		if(off%DIRLEN || cnt%DIRLEN)
324bd389b36SDavid du Colombier 			return "i/o error";
325bd389b36SDavid du Colombier 		for(r=f->ram->child; off; r=r->next){
326bd389b36SDavid du Colombier 			if (r==0)
327bd389b36SDavid du Colombier 				return 0;
328bd389b36SDavid du Colombier 			if(r->busy)
329bd389b36SDavid du Colombier 				off -= DIRLEN;
330bd389b36SDavid du Colombier 		}
331bd389b36SDavid du Colombier 		for(; r && n < cnt; r=r->next){
332bd389b36SDavid du Colombier 			if(!r->busy)
333bd389b36SDavid du Colombier 				continue;
334bd389b36SDavid du Colombier 			ramstat(r, buf+n);
335bd389b36SDavid du Colombier 			n += DIRLEN;
336bd389b36SDavid du Colombier 		}
337bd389b36SDavid du Colombier 		thdr.count = n;
338bd389b36SDavid du Colombier 		return 0;
339bd389b36SDavid du Colombier 	}
340bd389b36SDavid du Colombier 	r = f->ram;
341bd389b36SDavid du Colombier 	if(off >= r->ndata)
342bd389b36SDavid du Colombier 		return 0;
343bd389b36SDavid du Colombier 	r->atime = time(0);
344bd389b36SDavid du Colombier 	n = cnt;
345bd389b36SDavid du Colombier 	if(off+n > r->ndata)
346bd389b36SDavid du Colombier 		n = r->ndata - off;
347bd389b36SDavid du Colombier 	thdr.data = doread(r, off, n);
348bd389b36SDavid du Colombier 	thdr.count = n;
349bd389b36SDavid du Colombier 	return 0;
350bd389b36SDavid du Colombier }
351bd389b36SDavid du Colombier 
352bd389b36SDavid du Colombier char*
353bd389b36SDavid du Colombier rwrite(Fid *f)
354bd389b36SDavid du Colombier {
355bd389b36SDavid du Colombier 	Ram *r;
356bd389b36SDavid du Colombier 	ulong off;
357bd389b36SDavid du Colombier 	int cnt;
358bd389b36SDavid du Colombier 
359bd389b36SDavid du Colombier 	r = f->ram;
360bd389b36SDavid du Colombier 	if (dopermw(f->ram)==0)
361bd389b36SDavid du Colombier 		return Eperm;
362bd389b36SDavid du Colombier 	if(r->busy == 0)
363bd389b36SDavid du Colombier 		return Enotexist;
364bd389b36SDavid du Colombier 	off = rhdr.offset;
365bd389b36SDavid du Colombier 	if(r->perm & CHAPPEND)
366bd389b36SDavid du Colombier 		off = r->ndata;
367bd389b36SDavid du Colombier 	cnt = rhdr.count;
368bd389b36SDavid du Colombier 	if(r->qid.path & CHDIR)
369bd389b36SDavid du Colombier 		return "file is a directory";
370bd389b36SDavid du Colombier 	if(off > 100*1024*1024)		/* sanity check */
371bd389b36SDavid du Colombier 		return "write too big";
372bd389b36SDavid du Colombier 	dowrite(r, rhdr.data, off, cnt);
373bd389b36SDavid du Colombier 	r->qid.vers++;
374bd389b36SDavid du Colombier 	r->mtime = time(0);
375bd389b36SDavid du Colombier 	thdr.count = cnt;
376bd389b36SDavid du Colombier 	return 0;
377bd389b36SDavid du Colombier }
378bd389b36SDavid du Colombier 
379bd389b36SDavid du Colombier char *
380bd389b36SDavid du Colombier rclunk(Fid *f)
381bd389b36SDavid du Colombier {
382bd389b36SDavid du Colombier 	if(f->open)
383bd389b36SDavid du Colombier 		f->ram->open--;
384bd389b36SDavid du Colombier 	f->busy = 0;
385bd389b36SDavid du Colombier 	f->open = 0;
386bd389b36SDavid du Colombier 	f->ram = 0;
387bd389b36SDavid du Colombier 	return 0;
388bd389b36SDavid du Colombier }
389bd389b36SDavid du Colombier 
390bd389b36SDavid du Colombier char *
391bd389b36SDavid du Colombier rremove(Fid *f)
392bd389b36SDavid du Colombier {
393bd389b36SDavid du Colombier 	USED(f);
394bd389b36SDavid du Colombier 	return Eperm;
395bd389b36SDavid du Colombier }
396bd389b36SDavid du Colombier 
397bd389b36SDavid du Colombier char *
398bd389b36SDavid du Colombier rstat(Fid *f)
399bd389b36SDavid du Colombier {
400bd389b36SDavid du Colombier 	if(f->ram->busy == 0)
401bd389b36SDavid du Colombier 		return Enotexist;
402bd389b36SDavid du Colombier 	ramstat(f->ram, thdr.stat);
403bd389b36SDavid du Colombier 	return 0;
404bd389b36SDavid du Colombier }
405bd389b36SDavid du Colombier 
406bd389b36SDavid du Colombier char *
407bd389b36SDavid du Colombier rwstat(Fid *f)
408bd389b36SDavid du Colombier {
409bd389b36SDavid du Colombier 	if(f->ram->busy == 0)
410bd389b36SDavid du Colombier 		return Enotexist;
411bd389b36SDavid du Colombier 	return Eperm;
412bd389b36SDavid du Colombier }
413bd389b36SDavid du Colombier 
414bd389b36SDavid du Colombier void
415bd389b36SDavid du Colombier ramstat(Ram *r, char *buf)
416bd389b36SDavid du Colombier {
417bd389b36SDavid du Colombier 	Dir dir;
418bd389b36SDavid du Colombier 
419bd389b36SDavid du Colombier 	memmove(dir.name, r->name, NAMELEN);
420bd389b36SDavid du Colombier 	dir.qid = r->qid;
421bd389b36SDavid du Colombier 	dir.mode = r->perm;
422bd389b36SDavid du Colombier 	dir.length = r->ndata;
423bd389b36SDavid du Colombier 	dir.hlength = 0;
424bd389b36SDavid du Colombier 	strcpy(dir.uid, r->user);
425bd389b36SDavid du Colombier 	strcpy(dir.gid, r->group);
426bd389b36SDavid du Colombier 	dir.atime = r->atime;
427bd389b36SDavid du Colombier 	dir.mtime = r->mtime;
428bd389b36SDavid du Colombier 	convD2M(&dir, buf);
429bd389b36SDavid du Colombier }
430bd389b36SDavid du Colombier 
431bd389b36SDavid du Colombier Fid *
432bd389b36SDavid du Colombier newfid(int fid)
433bd389b36SDavid du Colombier {
434bd389b36SDavid du Colombier 	Fid *f, *ff;
435bd389b36SDavid du Colombier 
436bd389b36SDavid du Colombier 	ff = 0;
437bd389b36SDavid du Colombier 	for(f = fids; f; f = f->next)
438bd389b36SDavid du Colombier 		if(f->fid == fid)
439bd389b36SDavid du Colombier 			return f;
440bd389b36SDavid du Colombier 		else if(!ff && !f->busy)
441bd389b36SDavid du Colombier 			ff = f;
442bd389b36SDavid du Colombier 	if(ff){
443bd389b36SDavid du Colombier 		ff->fid = fid;
444bd389b36SDavid du Colombier 		ff->open = 0;
445bd389b36SDavid du Colombier 		ff->busy = 1;
446bd389b36SDavid du Colombier 	}
447bd389b36SDavid du Colombier 	f = emalloc(sizeof *f);
448bd389b36SDavid du Colombier 	f->ram = 0;
449bd389b36SDavid du Colombier 	f->fid = fid;
450bd389b36SDavid du Colombier 	f->busy = 1;
451bd389b36SDavid du Colombier 	f->open = 0;
452bd389b36SDavid du Colombier 	f->next = fids;
453bd389b36SDavid du Colombier 	fids = f;
454bd389b36SDavid du Colombier 	return f;
455bd389b36SDavid du Colombier }
456bd389b36SDavid du Colombier 
457bd389b36SDavid du Colombier void
458bd389b36SDavid du Colombier io(void)
459bd389b36SDavid du Colombier {
460bd389b36SDavid du Colombier 	char *err;
461bd389b36SDavid du Colombier 	int n, nerr;
462bd389b36SDavid du Colombier 	char buf[ERRLEN];
463bd389b36SDavid du Colombier 
464bd389b36SDavid du Colombier 	errstr(buf);
465bd389b36SDavid du Colombier 	for(nerr=0, buf[0]='\0'; nerr<100; nerr++){
466bd389b36SDavid du Colombier 		/*
467bd389b36SDavid du Colombier 		 * reading from a pipe or a network device
468bd389b36SDavid du Colombier 		 * will give an error after a few eof reads
469bd389b36SDavid du Colombier 		 * however, we cannot tell the difference
470bd389b36SDavid du Colombier 		 * between a zero-length read and an interrupt
471bd389b36SDavid du Colombier 		 * on the processes writing to us,
472bd389b36SDavid du Colombier 		 * so we wait for the error
473bd389b36SDavid du Colombier 		 */
474bd389b36SDavid du Colombier 		n = read(mfd[0], mdata, sizeof mdata);
475bd389b36SDavid du Colombier 		if (n==0)
476bd389b36SDavid du Colombier 			continue;
477bd389b36SDavid du Colombier 		if(n < 0){
478bd389b36SDavid du Colombier 			if (buf[0]=='\0')
479bd389b36SDavid du Colombier 				errstr(buf);
480bd389b36SDavid du Colombier 			continue;
481bd389b36SDavid du Colombier 		}
482bd389b36SDavid du Colombier 		nerr = 0;
483bd389b36SDavid du Colombier 		buf[0] = '\0';
484bd389b36SDavid du Colombier 		if(convM2S(mdata, &rhdr, n) == 0)
485bd389b36SDavid du Colombier 			continue;
486bd389b36SDavid du Colombier 
487bd389b36SDavid du Colombier /*		fprint(2, "ramfs:%F\n", &rhdr);/**/
488bd389b36SDavid du Colombier 
489bd389b36SDavid du Colombier 		thdr.data = mdata + MAXMSG;
490bd389b36SDavid du Colombier 		if(!fcalls[rhdr.type])
491bd389b36SDavid du Colombier 			err = "bad fcall type";
492bd389b36SDavid du Colombier 		else
493bd389b36SDavid du Colombier 			err = (*fcalls[rhdr.type])(newfid(rhdr.fid));
494bd389b36SDavid du Colombier 		if(err){
495bd389b36SDavid du Colombier 			thdr.type = Rerror;
496bd389b36SDavid du Colombier 			strncpy(thdr.ename, err, ERRLEN);
497bd389b36SDavid du Colombier 		}else{
498bd389b36SDavid du Colombier 			thdr.type = rhdr.type + 1;
499bd389b36SDavid du Colombier 			thdr.fid = rhdr.fid;
500bd389b36SDavid du Colombier 		}
501bd389b36SDavid du Colombier 		thdr.tag = rhdr.tag;
502bd389b36SDavid du Colombier 		n = convS2M(&thdr, mdata);
503bd389b36SDavid du Colombier 		if(write(mfd[1], mdata, n) != n)
504bd389b36SDavid du Colombier 			error("mount write");
505bd389b36SDavid du Colombier 	}
506bd389b36SDavid du Colombier 	if (buf[0]=='\0' || strncmp(buf, "write to hung", 13)==0)
507bd389b36SDavid du Colombier 		exits("");
508bd389b36SDavid du Colombier 	fprint(2, "%s: mount read: %s\n", argv0, buf);
509bd389b36SDavid du Colombier 	exits(buf);
510bd389b36SDavid du Colombier }
511bd389b36SDavid du Colombier 
512bd389b36SDavid du Colombier int
513bd389b36SDavid du Colombier perm(Fid *f, Ram *r, int p)
514bd389b36SDavid du Colombier {
515bd389b36SDavid du Colombier 	if (p==Pwrite && dopermw(r)==0)
516bd389b36SDavid du Colombier 		return 0;
517bd389b36SDavid du Colombier 	if((p*Pother) & r->perm)
518bd389b36SDavid du Colombier 		return 1;
519bd389b36SDavid du Colombier 	if(strcmp(f->user, r->group)==0 && ((p*Pgroup) & r->perm))
520bd389b36SDavid du Colombier 		return 1;
521bd389b36SDavid du Colombier 	if(strcmp(f->user, r->user)==0 && ((p*Powner) & r->perm))
522bd389b36SDavid du Colombier 		return 1;
523bd389b36SDavid du Colombier 	return 0;
524bd389b36SDavid du Colombier }
525bd389b36SDavid du Colombier 
526bd389b36SDavid du Colombier void
527bd389b36SDavid du Colombier error(char *s)
528bd389b36SDavid du Colombier {
529bd389b36SDavid du Colombier 	fprint(2, "%s: %s: ", argv0, s);
530bd389b36SDavid du Colombier 	perror("");
531bd389b36SDavid du Colombier 	exits(s);
532bd389b36SDavid du Colombier }
533bd389b36SDavid du Colombier 
534bd389b36SDavid du Colombier void *
535bd389b36SDavid du Colombier emalloc(ulong n)
536bd389b36SDavid du Colombier {
537bd389b36SDavid du Colombier 	void *p;
538bd389b36SDavid du Colombier 	p = malloc(n);
539bd389b36SDavid du Colombier 	if(!p)
540bd389b36SDavid du Colombier 		error("out of memory");
541bd389b36SDavid du Colombier 	return p;
542bd389b36SDavid du Colombier }
543bd389b36SDavid du Colombier 
544bd389b36SDavid du Colombier void *
545bd389b36SDavid du Colombier erealloc(void *p, ulong n)
546bd389b36SDavid du Colombier {
547bd389b36SDavid du Colombier 	p = realloc(p, n);
548bd389b36SDavid du Colombier 	if(!p)
549bd389b36SDavid du Colombier 		error("out of memory");
550bd389b36SDavid du Colombier 	return p;
551bd389b36SDavid du Colombier }
552bd389b36SDavid du Colombier 
553bd389b36SDavid du Colombier void
554bd389b36SDavid du Colombier usage(void)
555bd389b36SDavid du Colombier {
556bd389b36SDavid du Colombier 	fprint(2, "usage: %s [-s] [-m mountpoint]\n", argv0);
557bd389b36SDavid du Colombier 	exits("usage");
558bd389b36SDavid du Colombier }
559