xref: /plan9/sys/src/cmd/9nfs/nfs.c (revision 4de34a7edde43207e841ec91ecd12e6cf5f5ebe7)
1 #include "all.h"
2 
3 extern uchar buf[];
4 
5 Xfid *
rpc2xfid(Rpccall * cmd,Dir * dp)6 rpc2xfid(Rpccall *cmd, Dir *dp)
7 {
8 	char *argptr = cmd->args;
9 	Xfile *xp;
10 	Xfid *xf;
11 	Session *s;
12 	char *service;
13 	Authunix au;
14 	Qid qid;
15 	char client[256], *user;
16 	Unixidmap *m;
17 	int i;
18 	uvlong x1, x2;
19 
20 	chat("rpc2xfid %.8lux %.8lux %p %p\n", *((ulong*)argptr), *((ulong*)argptr+1), buf, argptr);
21 	if(argptr[0] == 0 && argptr[1] == 0){	/* root */
22 		chat("root...");
23 		xp = xfroot(&argptr[2], 0);
24 		s = xp ? xp->s : 0;
25 	}else{
26 		ulong ul;
27 		chat("noroot %.8lux...", *((ulong*)argptr));
28 		if((ul=GLONG()) != starttime){
29 			chat("bad tag %lux %lux...", ul, starttime);
30 			return 0;
31 		}
32 		s = (Session *)GLONG();
33 		x1 = GLONG();
34 		x2 = GLONG();
35 		qid.path = x1 | (x2<<32);
36 		qid.vers = 0;
37 		qid.type = GBYTE();
38 		xp = xfile(&qid, s, 0);
39 	}
40 	if(xp == 0){
41 		chat("no xfile...");
42 		return 0;
43 	}
44 	if(auth2unix(&cmd->cred, &au) != 0){
45 		chat("auth flavor=%ld, count=%ld\n",
46 			cmd->cred.flavor, cmd->cred.count);
47 		for(i=0; i<cmd->cred.count; i++)
48 			chat(" %.2ux", ((uchar *)cmd->cred.data)[i]);
49 		chat("...");
50 		return 0;
51 	}else{
52 /*		chat("auth: %d %.*s u=%d g=%d",
53  *			au.stamp, utfnlen(au.mach.s, au.mach.n), au.mach.s, au.uid, au.gid);
54  *		for(i=0; i<au.gidlen; i++)
55  *			chat(", %d", au.gids[i]);
56  *		chat("...");
57  */
58 		char *p = memchr(au.mach.s, '.', au.mach.n);
59 		chat("%ld@%.*s...", au.uid, utfnlen(au.mach.s, (p ? p-au.mach.s : au.mach.n)), au.mach.s);
60 	}
61 	if(au.mach.n >= sizeof client){
62 		chat("client name too long...");
63 		return 0;
64 	}
65 	memcpy(client, au.mach.s, au.mach.n);
66 	client[au.mach.n] = 0;
67 	service = xp->parent->s->service;
68 	cmd->up = m = pair2idmap(service, cmd->host);
69 	if(m == 0){
70 		chat("no map for pair (%s,%s)...", service, client);
71 		/*chat("getdom %d.%d.%d.%d", cmd->host&0xFF, (cmd->host>>8)&0xFF,
72 			(cmd->host>>16)&0xFF, (cmd->host>>24)&0xFF);/**/
73 		/*if(getdom(cmd->host, client, sizeof(client))<0)
74 			return 0;/**/
75 		return 0;
76 	}
77 	/*chat("map=(%s,%s)...", m->server, m->client);/**/
78 	cmd->user = user = id2name(&m->u.ids, au.uid);
79 	if(user == 0){
80 		chat("no user for id %ld...", au.uid);
81 		return 0;
82 	}
83 	chat("user=%s...", user);/**/
84 	xf = 0;
85 	if(s == xp->parent->s){
86 		if(!s->noauth)
87 			xf = setuser(xp, user);
88 		if(xf == 0)
89 			xf = setuser(xp, "none");
90 		if(xf == 0)
91 			chat("can't set user none...");
92 	}else
93 		xf = xp->users;
94 	if(xf)
95 		chat("uid=%s...", xf->uid);
96 	if(xf && dp && xfstat(xf, dp) < 0){
97 		chat("can't stat %s...", xp->name);
98 		return 0;
99 	}
100 	return xf;
101 }
102 
103 Xfid *
setuser(Xfile * xp,char * user)104 setuser(Xfile *xp, char *user)
105 {
106 	Xfid *xf, *xpf;
107 	Session *s;
108 
109 	xf = xfid(user, xp, 1);
110 	if(xf->urfid)
111 		return xf;
112 	if(xp->parent==xp || !(xpf = setuser(xp->parent, user))) /* assign = */
113 		return xfid(user, xp, -1);
114 	s = xp->s;
115 	xf->urfid = newfid(s);
116 	xf->urfid->owner = &xf->urfid;
117 	setfid(s, xpf->urfid);
118 	s->f.newfid = xf->urfid - s->fids;
119 	s->f.nwname = 1;
120 	s->f.wname[0] = xp->name;
121 	if(xmesg(s, Twalk) || s->f.nwqid != 1)
122 		return xfid(user, xp, -1);
123 	return xf;
124 }
125 
126 int
xfstat(Xfid * xf,Dir * dp)127 xfstat(Xfid *xf, Dir *dp)
128 {
129 	Xfile *xp;
130 	Session *s;
131 	char buf[128];
132 
133 	xp = xf->xp;
134 	s = xp->s;
135 	if(s != xp->parent->s){
136 		seprint(buf, buf+sizeof buf, "#%s", xf->uid);
137 		dp->name = strstore(buf);
138 		dp->uid = xf->uid;
139 		dp->gid = xf->uid;
140 		dp->muid = xf->uid;
141 		dp->qid.path = (uvlong)xf->uid;
142 		dp->qid.type = QTFILE;
143 		dp->qid.vers = 0;
144 		dp->mode = 0666;
145 		dp->atime = time(0);
146 		dp->mtime = dp->atime;
147 		dp->length = NETCHLEN;
148 		dp->type = 0;
149 		dp->type = 0;
150 		return 0;
151 	}
152 	setfid(s, xf->urfid);
153 	if(xmesg(s, Tstat) == 0){
154 		convM2D(s->f.stat, s->f.nstat, dp, (char*)s->statbuf);
155 		if(xp->qid.path == dp->qid.path){
156 			xp->name = strstore(dp->name);
157 			return 0;
158 		}
159 		/* not reached ? */
160 		chat("xp->qid.path=0x%.16llux, dp->qid.path=0x%.16llux name=%s...",
161 			xp->qid.path, dp->qid.path, dp->name);
162 	}
163 	if(xp != xp->parent)
164 		xpclear(xp);
165 	else
166 		clog("can't stat root: %s",
167 			s->f.type == Rerror ? s->f.ename : "??");
168 	return -1;
169 }
170 
171 int
xfwstat(Xfid * xf,Dir * dp)172 xfwstat(Xfid *xf, Dir *dp)
173 {
174 	Xfile *xp;
175 	Session *s;
176 
177 	xp = xf->xp;
178 	s = xp->s;
179 
180 	/*
181 	 * xf->urfid can be zero because some DOS NFS clients
182 	 * try to do wstat on the #user authentication files on close.
183 	 */
184 	if(s == 0 || xf->urfid == 0)
185 		return -1;
186 	setfid(s, xf->urfid);
187 	s->f.stat = s->statbuf;
188 	convD2M(dp, s->f.stat, Maxstatdata);
189 	if(xmesg(s, Twstat))
190 		return -1;
191 	xp->name = strstore(dp->name);
192 	return 0;
193 }
194 
195 int
xfopen(Xfid * xf,int flag)196 xfopen(Xfid *xf, int flag)
197 {
198 	static int modes[] = {
199 		[Oread] OREAD, [Owrite] OWRITE, [Oread|Owrite] ORDWR,
200 	};
201 	Xfile *xp;
202 	Session *s;
203 	Fid *opfid;
204 	int omode;
205 
206 	if(xf->opfid && (xf->mode & flag & Open) == flag)
207 		return 0;
208 	omode = modes[(xf->mode|flag) & Open];
209 	if(flag & Trunc)
210 		omode |= OTRUNC;
211 	xp = xf->xp;
212 	chat("open(\"%s\", %d)...", xp->name, omode);
213 	s = xp->s;
214 	opfid = newfid(s);
215 	setfid(s, xf->urfid);
216 	s->f.newfid = opfid - s->fids;
217 	s->f.nwname = 0;
218 	if(xmesg(s, Twalk)){
219 		putfid(s, opfid);
220 		return -1;
221 	}
222 	setfid(s, opfid);
223 	s->f.mode = omode;
224 	if(xmesg(s, Topen)){
225 		clunkfid(s, opfid);
226 		return -1;
227 	}
228 	if(xf->opfid)
229 		clunkfid(s, xf->opfid);
230 	xf->mode |= flag & Open;
231 	xf->opfid = opfid;
232 	opfid->owner = &xf->opfid;
233 	xf->offset = 0;
234 	return 0;
235 }
236 
237 void
xfclose(Xfid * xf)238 xfclose(Xfid *xf)
239 {
240 	Xfile *xp;
241 
242 	if(xf->mode & Open){
243 		xp = xf->xp;
244 		chat("close(\"%s\")...", xp->name);
245 		if(xf->opfid)
246 			clunkfid(xp->s, xf->opfid);
247 		xf->mode &= ~Open;
248 		xf->opfid = 0;
249 	}
250 }
251 
252 void
xfclear(Xfid * xf)253 xfclear(Xfid *xf)
254 {
255 	Xfile *xp = xf->xp;
256 
257 	if(xf->opfid){
258 		clunkfid(xp->s, xf->opfid);
259 		xf->opfid = 0;
260 	}
261 	if(xf->urfid){
262 		clunkfid(xp->s, xf->urfid);
263 		xf->urfid = 0;
264 	}
265 	xfid(xf->uid, xp, -1);
266 }
267 
268 Xfid *
xfwalkcr(int type,Xfid * xf,String * elem,long perm)269 xfwalkcr(int type, Xfid *xf, String *elem, long perm)
270 {
271 	Session *s;
272 	Xfile *xp, *newxp;
273 	Xfid *newxf;
274 	Fid *nfid;
275 
276 	chat("xf%s(\"%s\")...", type==Tcreate ? "create" : "walk", elem->s);
277 	xp = xf->xp;
278 	s = xp->s;
279 	nfid = newfid(s);
280 	setfid(s, xf->urfid);
281 	s->f.newfid = nfid - s->fids;
282 	if(type == Tcreate){
283 		s->f.nwname = 0;
284 		if(xmesg(s, Twalk)){
285 			putfid(s, nfid);
286 			return 0;
287 		}
288 		s->f.fid = nfid - s->fids;
289 	}
290 	if(type == Tcreate){
291 		s->f.name = elem->s;
292 		s->f.perm = perm;
293 		s->f.mode = (perm&DMDIR) ? OREAD : ORDWR;
294 		if(xmesg(s, type)){
295 			clunkfid(s, nfid);
296 			return 0;
297 		}
298 	}else{	/* Twalk */
299 		s->f.nwname = 1;
300 		s->f.wname[0] = elem->s;
301 		if(xmesg(s, type) || s->f.nwqid!=1){
302 			putfid(s, nfid);
303 			return 0;
304 		}
305 		s->f.qid = s->f.wqid[0];	/* only one element */
306 	}
307 	chat("fid=%d,qid=0x%llux,%ld,%.2ux...", s->f.fid, s->f.qid.path, s->f.qid.vers, s->f.qid.type);
308 	newxp = xfile(&s->f.qid, s, 1);
309 	if(newxp->parent == 0){
310 		chat("new xfile...");
311 		newxp->parent = xp;
312 		newxp->sib = xp->child;
313 		xp->child = newxp;
314 	}
315 	newxf = xfid(xf->uid, newxp, 1);
316 	if(type == Tcreate){
317 		newxf->mode = (perm&DMDIR) ? Oread : (Oread|Owrite);
318 		newxf->opfid = nfid;
319 		nfid->owner = &newxf->opfid;
320 		nfid = newfid(s);
321 		setfid(s, xf->urfid);
322 		s->f.newfid = nfid - s->fids;
323 		s->f.nwname = 1;
324 		s->f.wname[0] = elem->s;
325 		if(xmesg(s, Twalk) || s->f.nwqid!=1){
326 			putfid(s, nfid);
327 			xpclear(newxp);
328 			return 0;
329 		}
330 		newxf->urfid = nfid;
331 		nfid->owner = &newxf->urfid;
332 	}else if(newxf->urfid){
333 		chat("old xfid %ld...", newxf->urfid-s->fids);
334 		clunkfid(s, nfid);
335 	}else{
336 		newxf->urfid = nfid;
337 		nfid->owner = &newxf->urfid;
338 	}
339 	newxp->name = strstore(elem->s);
340 	return newxf;
341 }
342 
343 void
xpclear(Xfile * xp)344 xpclear(Xfile *xp)
345 {
346 	Session *s;
347 	Xfid *xf;
348 	Xfile *xnp;
349 
350 	s = xp->s;
351 	while(xf = xp->users)	/* assign = */
352 		xfclear(xf);
353 	while(xnp = xp->child){	/* assign = */
354 		xp->child = xnp->sib;
355 		xnp->parent = 0;
356 		xpclear(xnp);
357 		xfile(&xnp->qid, s, -1);
358 	}
359 	if(xnp = xp->parent){	/* assign = */
360 		if(xnp->child == xp)
361 			xnp->child = xp->sib;
362 		else{
363 			xnp = xnp->child;
364 			while(xnp->sib != xp)
365 				xnp = xnp->sib;
366 			xnp->sib = xp->sib;
367 		}
368 		xfile(&xp->qid, s, -1);
369 	}
370 }
371 
372 int
xp2fhandle(Xfile * xp,Fhandle fh)373 xp2fhandle(Xfile *xp, Fhandle fh)
374 {
375 	uchar *dataptr = fh;
376 	ulong x;
377 	int n;
378 
379 	memset(fh, 0, FHSIZE);
380 	if(xp == xp->parent){	/* root */
381 		dataptr[0] = 0;
382 		dataptr[1] = 0;
383 		n = strlen(xp->s->service);
384 		if(n > FHSIZE-3)
385 			n = FHSIZE-3;
386 		memmove(&dataptr[2], xp->s->service, n);
387 		dataptr[2+n] = 0;
388 	}else{
389 		PLONG(starttime);
390 		PLONG((u32int)(uintptr)xp->s);
391 		x = xp->qid.path;
392 		PLONG(x);
393 		x = xp->qid.path>>32;
394 		PLONG(x);
395 		PBYTE(xp->qid.type);
396 		USED(dataptr);
397 	}
398 	return FHSIZE;
399 }
400 
401 int
dir2fattr(Unixidmap * up,Dir * dp,void * mp)402 dir2fattr(Unixidmap *up, Dir *dp, void *mp)
403 {
404 	uchar *dataptr = mp;
405 	long length;
406 	int r;
407 
408 	r = dp->mode & 0777;
409 	if (dp->mode & DMDIR)
410 		length = 1024;
411 	else
412 		length = dp->length;
413 	if((dp->mode & DMDIR) && dp->type == '/' && dp->dev == 0)
414 		r |= 0555;
415 	if(dp->mode & DMDIR){
416 		PLONG(NFDIR);	/* type */
417 		r |= S_IFDIR;
418 		PLONG(r);	/* mode */
419 		PLONG(3);	/* nlink */
420 	}else{
421 		PLONG(NFREG);	/* type */
422 		r |= S_IFREG;
423 		PLONG(r);	/* mode */
424 		PLONG(1);	/* nlink */
425 	}
426 	r = name2id(&up->u.ids, dp->uid);
427 	if(r < 0){
428 		r = name2id(&up->u.ids, "daemon");
429 		if(r < 0)
430 			r = 1;
431 	}
432 	PLONG(r);		/* uid */
433 	r = name2id(&up->g.ids, dp->gid);
434 	if(r < 0){
435 		r = name2id(&up->g.ids, "user");
436 		if(r < 0)
437 			r = 1;
438 	}
439 	PLONG(r);		/* gid */
440 	PLONG(length);		/* size */
441 	PLONG(2048);		/* blocksize */
442 	PLONG(0);		/* rdev */
443 	r = (length+2047)/2048;
444 	PLONG(r);		/* blocks */
445 	r = (dp->type<<16) | dp->dev;
446 	PLONG(r);		/* fsid */
447 	PLONG(dp->qid.path);	/* fileid */
448 	PLONG(dp->atime);	/* atime */
449 	PLONG(0);
450 	PLONG(dp->mtime);	/* mtime */
451 	PLONG(0);
452 	PLONG(dp->mtime);	/* ctime */
453 	PLONG(0);
454 	return dataptr - (uchar *)mp;
455 }
456 
457 int
convM2sattr(void * mp,Sattr * sp)458 convM2sattr(void *mp, Sattr *sp)
459 {
460 	uchar *argptr = mp;
461 
462 	sp->mode = GLONG();
463 	sp->uid = GLONG();
464 	sp->gid = GLONG();
465 	sp->size = GLONG();
466 	sp->atime = GLONG();
467 	sp->ausec = GLONG();
468 	sp->mtime = GLONG();
469 	sp->musec = GLONG();
470 	return argptr - (uchar *)mp;
471 }
472