]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/9nfs/nfs.c
upas/fs: remove imap lastread debounding
[plan9front.git] / sys / src / cmd / 9nfs / nfs.c
1 #include "all.h"
2
3 extern uchar buf[];
4
5 Xfid *
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 *
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
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
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
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
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
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 *
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 %zd...", 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
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
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
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
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 }