1 /* Copyright © 2003 Russ Cox, MIT; see /sys/src/libsunrpc/COPYING */
13 char *defaultpath = "/";
20 typedef struct Auth Auth;
28 typedef struct FidAux FidAux;
33 u64int cookie; /* for continuing directory reads */
34 char *name; /* botch: for remove and rename */
35 Nfs3Handle parent; /* botch: for remove and rename */
36 char err[ERRMAX]; /* for walk1 */
41 * various RPCs. here is where we'd insert support for NFS v2
45 portCall(SunCall *c, PortCallType type)
47 c->rpc.prog = PortProgram;
48 c->rpc.vers = PortVersion;
49 c->rpc.proc = type>>1;
50 c->rpc.iscall = !(type&1);
55 getport(SunClient *client, uint prog, uint vers, uint prot, uint *port)
60 memset(&tx, 0, sizeof tx);
61 portCall(&tx.call, PortCallTGetport);
66 memset(&rx, 0, sizeof rx);
67 portCall(&rx.call, PortCallRGetport);
69 if(sunClientRpc(client, 0, &tx.call, &rx.call, nil) < 0)
76 mountCall(Auth *a, SunCall *c, NfsMount3CallType type)
78 c->rpc.iscall = !(type&1);
79 c->rpc.proc = type>>1;
80 c->rpc.prog = NfsMount3Program;
81 c->rpc.vers = NfsMount3Version;
82 if(c->rpc.iscall && a){
83 c->rpc.cred.flavor = SunAuthSys;
84 c->rpc.cred.data = a->data;
85 c->rpc.cred.ndata = a->ndata;
96 memset(&tx, 0, sizeof tx);
97 mountCall(nil, &tx.call, NfsMount3CallTNull);
99 memset(&rx, 0, sizeof rx);
100 mountCall(nil, &rx.call, NfsMount3CallTNull);
102 return sunClientRpc(mntcli, tag, &tx.call, &rx.call, nil);
106 mountMnt(Auth *a, ulong tag, char *path, Nfs3Handle *h)
112 memset(&tx, 0, sizeof tx);
113 mountCall(a, &tx.call, NfsMount3CallTMnt);
116 memset(&rx, 0, sizeof rx);
117 mountCall(a, &rx.call, NfsMount3CallRMnt);
118 if(sunClientRpc(mntcli, tag, &tx.call, &rx.call, &freeme) < 0)
120 if(rx.status != Nfs3Ok){
121 nfs3Errstr(rx.status);
124 if(verbose)print("handle %.*H\n", rx.len, rx.handle);
125 if(rx.len >= Nfs3MaxHandleSize){
127 werrstr("server-returned handle too long");
130 memmove(h->h, rx.handle, rx.len);
137 nfs3Call(Auth *a, SunCall *c, Nfs3CallType type)
139 c->rpc.iscall = !(type&1);
140 c->rpc.proc = type>>1;
141 c->rpc.prog = Nfs3Program;
142 c->rpc.vers = Nfs3Version;
143 if(c->rpc.iscall && a){
144 c->rpc.cred.flavor = SunAuthSys;
145 c->rpc.cred.data = a->data;
146 c->rpc.cred.ndata = a->ndata;
157 memset(&tx, 0, sizeof tx);
158 nfs3Call(nil, &tx.call, Nfs3CallTNull);
160 memset(&rx, 0, sizeof rx);
161 nfs3Call(nil, &rx.call, Nfs3CallTNull);
163 return sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil);
167 nfsGetattr(Auth *a, ulong tag, Nfs3Handle *h, Nfs3Attr *attr)
172 memset(&tx, 0, sizeof tx);
173 nfs3Call(a, &tx.call, Nfs3CallTGetattr);
176 memset(&rx, 0, sizeof rx);
177 nfs3Call(a, &rx.call, Nfs3CallRGetattr);
179 if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0)
181 if(rx.status != Nfs3Ok){
182 nfs3Errstr(rx.status);
191 nfsAccess(Auth *a, ulong tag, Nfs3Handle *h, ulong want, ulong *got, u1int *have, Nfs3Attr *attr)
196 memset(&tx, 0, sizeof tx);
197 nfs3Call(a, &tx.call, Nfs3CallTAccess);
201 memset(&rx, 0, sizeof rx);
202 nfs3Call(a, &rx.call, Nfs3CallRAccess);
204 if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0)
206 if(rx.status != Nfs3Ok){
207 nfs3Errstr(rx.status);
220 nfsMkdir(Auth *a, ulong tag, Nfs3Handle *h, char *name, Nfs3Handle *nh, ulong mode, uint gid,
221 u1int *have, Nfs3Attr *attr)
226 memset(&tx, 0, sizeof tx);
227 nfs3Call(a, &tx.call, Nfs3CallTMkdir);
235 memset(&rx, 0, sizeof rx);
236 nfs3Call(a, &rx.call, Nfs3CallRMkdir);
238 if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0)
240 if(rx.status != Nfs3Ok){
241 nfs3Errstr(rx.status);
246 werrstr("nfs mkdir did not return handle");
258 nfsCreate(Auth *a, ulong tag, Nfs3Handle *h, char *name, Nfs3Handle *nh, ulong mode, uint gid,
259 u1int *have, Nfs3Attr *attr)
264 memset(&tx, 0, sizeof tx);
265 nfs3Call(a, &tx.call, Nfs3CallTCreate);
273 memset(&rx, 0, sizeof rx);
274 nfs3Call(a, &rx.call, Nfs3CallRCreate);
276 if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0)
278 if(rx.status != Nfs3Ok){
279 nfs3Errstr(rx.status);
284 werrstr("nfs create did not return handle");
296 nfsRead(Auth *a, ulong tag, Nfs3Handle *h, u32int count, u64int offset,
297 uchar **pp, u32int *pcount, uchar **pfreeme)
303 memset(&tx, 0, sizeof tx);
304 nfs3Call(a, &tx.call, Nfs3CallTRead);
309 memset(&rx, 0, sizeof rx);
310 nfs3Call(a, &rx.call, Nfs3CallRRead);
312 if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, &freeme) < 0)
314 if(rx.status != Nfs3Ok){
315 nfs3Errstr(rx.status);
318 if(rx.count != rx.ndata){
319 werrstr("nfs read returned count=%ud ndata=%ud", (uint)rx.count, (uint)rx.ndata);
330 nfsWrite(Auth *a, ulong tag, Nfs3Handle *h, uchar *data, u32int count, u64int offset, u32int *pcount)
335 memset(&tx, 0, sizeof tx);
336 nfs3Call(a, &tx.call, Nfs3CallTWrite);
343 memset(&rx, 0, sizeof rx);
344 nfs3Call(a, &rx.call, Nfs3CallRWrite);
346 if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0)
348 if(rx.status != Nfs3Ok){
349 nfs3Errstr(rx.status);
358 nfsRmdir(Auth *a, ulong tag, Nfs3Handle *h, char *name)
363 memset(&tx, 0, sizeof tx);
364 nfs3Call(a, &tx.call, Nfs3CallTRmdir);
368 memset(&rx, 0, sizeof rx);
369 nfs3Call(a, &rx.call, Nfs3CallRRmdir);
371 if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0)
373 if(rx.status != Nfs3Ok){
374 nfs3Errstr(rx.status);
381 nfsRemove(Auth *a, ulong tag, Nfs3Handle *h, char *name)
386 memset(&tx, 0, sizeof tx);
387 nfs3Call(a, &tx.call, Nfs3CallTRemove);
391 memset(&rx, 0, sizeof rx);
392 nfs3Call(a, &rx.call, Nfs3CallRRemove);
394 if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0)
396 if(rx.status != Nfs3Ok){
397 nfs3Errstr(rx.status);
404 nfsRename(Auth *a, ulong tag, Nfs3Handle *h, char *name, Nfs3Handle *th, char *tname)
409 memset(&tx, 0, sizeof tx);
410 nfs3Call(a, &tx.call, Nfs3CallTRename);
416 memset(&rx, 0, sizeof rx);
417 nfs3Call(a, &rx.call, Nfs3CallRRename);
419 if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0)
421 if(rx.status != Nfs3Ok){
422 nfs3Errstr(rx.status);
429 nfsSetattr(Auth *a, ulong tag, Nfs3Handle *h, Nfs3SetAttr *attr)
434 memset(&tx, 0, sizeof tx);
435 nfs3Call(a, &tx.call, Nfs3CallTSetattr);
439 memset(&rx, 0, sizeof rx);
440 nfs3Call(a, &rx.call, Nfs3CallRSetattr);
442 if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0)
444 if(rx.status != Nfs3Ok){
445 nfs3Errstr(rx.status);
452 nfsCommit(Auth *a, ulong tag, Nfs3Handle *h)
457 memset(&tx, 0, sizeof tx);
458 nfs3Call(a, &tx.call, Nfs3CallTCommit);
461 memset(&rx, 0, sizeof rx);
462 nfs3Call(a, &rx.call, Nfs3CallRCommit);
464 if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0)
467 if(rx.status != Nfs3Ok){
468 nfs3Errstr(rx.status);
475 nfsLookup(Auth *a, ulong tag, Nfs3Handle *h, char *name, Nfs3Handle *nh, u1int *have, Nfs3Attr *attr)
480 memset(&tx, 0, sizeof tx);
481 nfs3Call(a, &tx.call, Nfs3CallTLookup);
485 memset(&rx, 0, sizeof rx);
486 nfs3Call(a, &rx.call, Nfs3CallRLookup);
488 if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0)
491 if(rx.status != Nfs3Ok){
492 nfs3Errstr(rx.status);
503 nfsReadDirPlus(Auth *a, ulong tag, Nfs3Handle *h, u32int count, u64int cookie, uchar **pp,
504 u32int *pcount, int (**unpack)(uchar*, uchar*, uchar**, Nfs3Entry*), uchar **pfreeme)
509 memset(&tx, 0, sizeof tx);
510 nfs3Call(a, &tx.call, Nfs3CallTReadDirPlus);
516 memset(&rx, 0, sizeof rx);
517 nfs3Call(a, &rx.call, Nfs3CallRReadDirPlus);
519 if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, pfreeme) < 0)
521 if(rx.status != Nfs3Ok){
524 nfs3Errstr(rx.status);
528 *unpack = nfs3EntryPlusUnpack;
535 nfsReadDir(Auth *a, ulong tag, Nfs3Handle *h, u32int count, u64int cookie, uchar **pp,
536 u32int *pcount, int (**unpack)(uchar*, uchar*, uchar**, Nfs3Entry*), uchar **pfreeme)
538 /* BUG: try readdirplus */
544 if(nfsReadDirPlus(a, tag, h, count, cookie, pp, pcount, unpack, pfreeme) == 0){
549 rerrstr(e, sizeof e);
550 if(strstr(e, "procedure unavailable") || strstr(e, "not supported"))
554 fprint(2, "readdirplus: %r\n");
559 memset(&tx, 0, sizeof tx);
560 nfs3Call(a, &tx.call, Nfs3CallTReadDir);
565 memset(&rx, 0, sizeof rx);
566 nfs3Call(a, &rx.call, Nfs3CallRReadDir);
568 if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, pfreeme) < 0)
570 if(rx.status != Nfs3Ok){
573 nfs3Errstr(rx.status);
577 /* readplus failed but read succeeded */
580 *unpack = nfs3EntryUnpack;
587 * name <-> int translation
589 typedef struct Map Map;
590 typedef struct User User;
591 typedef struct Group Group;
609 char *name; /* same pos as in User struct */
610 uint gid; /* same pos as in User struct */
626 finduser(User **u, int nu, char *s)
634 n = strcmp(u[mid]->name, s);
646 strtoid(User **u, int nu, char *s, u32int *id)
652 x = strtoul(s, &p, 10);
653 if(*s != 0 && *p == 0){
658 uu = finduser(u, nu, s);
666 idtostr(User **u, int nu, u32int id)
675 if(u[mid]->uid == id)
676 return estrdup9p(u[mid]->name);
682 snprint(buf, sizeof buf, "%ud", id);
683 return estrdup9p(buf);
688 return idtostr(map->ubyid, map->nuser, uid);
694 return idtostr((User**)map->gbyid, map->ngroup, gid);
698 strtouid(char *s, u32int *id)
700 return strtoid(map->ubyname, map->nuser, s, id);
704 strtogid(char *s, u32int *id)
706 return strtoid((User**)map->gbyid, map->ngroup, s, id);
711 idcmp(const void *va, const void *vb)
717 return (*a)->uid - (*b)->uid;
721 namecmp(const void *va, const void *vb)
727 return strcmp((*a)->name, (*b)->name);
735 for(i=0; i<m->nuser; i++){
736 free(m->user[i].name);
737 free(m->user[i].auth);
739 for(i=0; i<m->ngroup; i++)
740 free(m->group[i].name);
751 readmap(char *passwd, char *group)
753 char *s, *f[10], *p, *nextp, *name;
755 int i, n, nf, line, uid, gid;
762 m = emalloc(sizeof(Map));
764 if((b = Bopen(passwd, OREAD)) == nil){
769 for(; (s = Brdstr(b, '\n', 1)) != nil; free(s)){
773 nf = getfields(s, f, nelem(f), 0, ":");
777 uid = strtol(f[2], &p, 10);
778 if(f[2][0] == 0 || *p != 0){
779 fprint(2, "%s:%d: non-numeric id in third field\n", passwd, line);
782 gid = strtol(f[3], &p, 10);
783 if(f[3][0] == 0 || *p != 0){
784 fprint(2, "%s:%d: non-numeric id in fourth field\n", passwd, line);
788 m->user = erealloc(m->user, (m->nuser+32)*sizeof(m->user[0]));
789 u = &m->user[m->nuser++];
790 u->name = estrdup9p(name);
798 m->ubyname = emalloc(m->nuser*sizeof(User*));
799 m->ubyid = emalloc(m->nuser*sizeof(User*));
800 for(i=0; i<m->nuser; i++){
801 m->ubyname[i] = &m->user[i];
802 m->ubyid[i] = &m->user[i];
804 qsort(m->ubyname, m->nuser, sizeof(m->ubyname[0]), namecmp);
805 qsort(m->ubyid, m->nuser, sizeof(m->ubyid[0]), idcmp);
807 if((b = Bopen(group, OREAD)) == nil){
812 for(; (s = Brdstr(b, '\n', 1)) != nil; free(s)){
816 nf = getfields(s, f, nelem(f), 0, ":");
820 gid = strtol(f[2], &p, 10);
821 if(f[2][0] == 0 || *p != 0){
822 fprint(2, "%s:%d: non-numeric id in third field\n", group, line);
825 if(m->ngroup%32 == 0)
826 m->group = erealloc(m->group, (m->ngroup+32)*sizeof(m->group[0]));
827 g = &m->group[m->ngroup++];
828 g->name = estrdup9p(name);
831 for(p=f[3]; *p; p=nextp){
832 if((nextp = strchr(p, ',')) != nil)
836 u = finduser(m->ubyname, m->nuser, p);
839 fprint(2, "%s:%d: unknown user %s\n", group, line, p);
842 if(u->ng >= nelem(u->g)){
843 fprint(2, "%s:%d: user %s is in too many groups; ignoring %s\n", group, line, p, name);
850 m->gbyname = emalloc(m->ngroup*sizeof(Group*));
851 m->gbyid = emalloc(m->ngroup*sizeof(Group*));
852 for(i=0; i<m->ngroup; i++){
853 m->gbyname[i] = &m->group[i];
854 m->gbyid[i] = &m->group[i];
856 qsort(m->gbyname, m->ngroup, sizeof(m->gbyname[0]), namecmp);
857 qsort(m->gbyid, m->ngroup, sizeof(m->gbyid[0]), idcmp);
859 for(i=0; i<m->nuser; i++){
862 au.uid = m->user[i].uid;
863 au.gid = m->user[i].gid;
864 memmove(au.g, m->user[i].g, sizeof au.g);
865 au.ng = m->user[i].ng;
866 n = sunAuthUnixSize(&au);
870 m->user[i].nauth = n;
871 if(sunAuthUnixPack(q, eq, &q, &au) < 0 || q != eq){
872 fprint(2, "sunAuthUnixPack failed for %s\n", m->user[i].name);
873 free(m->user[i].auth);
875 m->user[i].nauth = 0;
891 u = finduser(map->ubyname, map->nuser, user);
892 if(u == nil || u->nauth == 0){
899 n = sunAuthUnixSize(&au);
900 a = emalloc(sizeof(Auth)+n);
901 a->data = (uchar*)&a[1];
903 if(sunAuthUnixPack(a->data, a->data+a->ndata, &p, &au) < 0
904 || p != a->data+a->ndata){
909 if(verbose)print("creds for %s: %.*H\n", user, a->ndata, a->data);
913 a = emalloc(sizeof(Auth)+u->nauth);
914 a->data = (uchar*)&a[1];
916 memmove(a->data, u->auth, a->ndata);
918 if(verbose)print("creds for %s: %.*H\n", user, a->ndata, a->data);
934 responderrstr(Req *r)
938 rerrstr(e, sizeof e);
943 fsdestroyfid(Fid *fid)
956 attrToQid(Nfs3Attr *attr, Qid *qid)
958 qid->path = attr->fileid;
959 qid->vers = attr->mtime.sec;
961 if(attr->type == Nfs3FileDir)
966 attrToDir(Nfs3Attr *attr, Dir *d)
968 d->mode = attr->mode & 0777;
969 if(attr->type == Nfs3FileDir)
971 d->uid = uidtostr(attr->uid);
972 d->gid = gidtostr(attr->gid);
973 d->length = attr->size;
974 attrToQid(attr, &d->qid);
975 d->mtime = attr->mtime.sec;
976 d->atime = attr->atime.sec;
989 path = r->ifcall.aname;
990 if(path==nil || path[0]==0)
993 auth = mkauth(r->ifcall.uname);
995 if(mountMnt(auth, r->tag, path, &h) < 0
996 || nfsGetattr(auth, r->tag, &h, &attr) < 0){
1002 aux = emalloc(sizeof(FidAux));
1007 memset(&aux->parent, 0, sizeof aux->parent);
1009 attrToQid(&attr, &r->fid->qid);
1010 r->ofcall.qid = r->fid->qid;
1025 switch(r->ifcall.mode&OMASK){
1039 if(r->ifcall.mode&OTRUNC)
1042 if(nfsAccess(aux->auth, r->tag, &aux->handle, a, &b, &have, &attr) < 0
1043 || (!have && nfsGetattr(aux->auth, r->tag, &aux->handle, &attr) < 0)){
1049 respond(r, "permission denied");
1052 if(r->ifcall.mode&OTRUNC){
1053 memset(&sa, 0, sizeof sa);
1055 if(nfsSetattr(aux->auth, r->tag, &aux->handle, &sa) < 0)
1058 attrToQid(&attr, &r->fid->qid);
1059 r->ofcall.qid = r->fid->qid;
1072 int (*mk)(Auth*, ulong, Nfs3Handle*, char*, Nfs3Handle*, ulong, uint, u1int*, Nfs3Attr*);
1077 * Plan 9 has no umask, so let's use the
1078 * parent directory bits like Plan 9 does.
1079 * What the heck, let's inherit the group too.
1080 * (Unix will let us set the group to anything
1081 * since we're the owner!)
1083 if(nfsGetattr(aux->auth, r->tag, &aux->handle, &attr) < 0){
1087 mode = r->ifcall.perm&0777;
1088 if(r->ifcall.perm&DMDIR)
1089 mode &= (attr.mode&0666) | ~0666;
1091 mode &= (attr.mode&0777) | ~0777;
1094 if(r->ifcall.perm&DMDIR)
1099 if((*mk)(aux->auth, r->tag, &aux->handle, r->ifcall.name, &h, mode, gid, &have, &attr) < 0
1100 || (!have && nfsGetattr(aux->auth, r->tag, &h, &attr) < 0)){
1104 attrToQid(&attr, &r->fid->qid);
1105 aux->parent = aux->handle;
1108 aux->name = estrdup9p(r->ifcall.name);
1109 r->ofcall.qid = r->fid->qid;
1117 uchar *p, *freeme, *ep, *p9, *ep9;
1120 int n, (*unpack)(uchar*, uchar*, uchar**, Nfs3Entry*);
1127 * r->ifcall.count seems a reasonable estimate to
1128 * how much NFS entry data we want. is it?
1130 if(r->ifcall.offset)
1131 cookie = aux->cookie;
1134 if(nfsReadDir(aux->auth, r->tag, &aux->handle, r->ifcall.count, cookie,
1135 &p, &count, &unpack, &freeme) < 0){
1141 p9 = (uchar*)r->ofcall.data;
1142 ep9 = p9+r->ifcall.count;
1145 * BUG: Issue all of the stat requests in parallel.
1147 while(p < ep && p9 < ep9){
1148 if((*unpack)(p, ep, &p, &e) < 0)
1150 aux->cookie = e.cookie;
1151 if(strcmp(e.name, ".") == 0 || strcmp(e.name, "..") == 0)
1153 for(s=e.name; (uchar)*s >= ' '; s++)
1155 if(*s != 0) /* bad character in name */
1157 if(!e.haveAttr && !e.haveHandle)
1158 if(nfsLookup(aux->auth, r->tag, &aux->handle, e.name, &e.handle, &e.haveAttr, &e.attr) < 0)
1161 if(nfsGetattr(aux->auth, r->tag, &e.handle, &e.attr) < 0)
1163 memset(&d, 0, sizeof d);
1164 attrToDir(&e.attr, &d);
1166 if((n = convD2M(&d, p9, ep9-p9)) <= BIT16SZ)
1171 r->ofcall.count = p9 - (uchar*)r->ofcall.data;
1182 if(r->fid->qid.type&QTDIR){
1188 if(nfsRead(aux->auth, r->tag, &aux->handle, r->ifcall.count, r->ifcall.offset, &p, &count, &freeme) < 0){
1192 r->ofcall.data = (char*)p;
1193 r->ofcall.count = count;
1205 if(nfsWrite(aux->auth, r->tag, &aux->handle, (uchar*)r->ifcall.data, r->ifcall.count, r->ifcall.offset, &count) < 0){
1209 r->ofcall.count = count;
1220 if(aux->name == nil){
1221 respond(r, "nfs3client botch -- don't know parent handle in remove");
1224 if(r->fid->qid.type&QTDIR)
1225 n = nfsRmdir(aux->auth, r->tag, &aux->parent, aux->name);
1227 n = nfsRemove(aux->auth, r->tag, &aux->parent, aux->name);
1242 if(nfsGetattr(aux->auth, r->tag, &aux->handle, &attr) < 0){
1246 memset(&r->d, 0, sizeof r->d);
1247 attrToDir(&attr, &r->d);
1248 r->d.name = estrdup9p(aux->name ? aux->name : "???");
1259 memset(&attr, 0, sizeof attr);
1262 /* Fill out stat first to catch errors */
1266 if(r->d.mode&(DMAPPEND|DMEXCL)){
1267 respond(r, "wstat -- DMAPPEND and DMEXCL bits not supported");
1273 attr.mode = r->d.mode & 0777;
1275 if(r->d.uid && r->d.uid[0]){
1277 if(strtouid(r->d.uid, &attr.uid) < 0){
1278 respond(r, "wstat -- unknown uid");
1284 if(r->d.gid && r->d.gid[0]){
1286 if(strtogid(r->d.gid, &attr.gid) < 0){
1287 respond(r, "wstat -- unknown gid");
1295 attr.size = r->d.length;
1300 attr.setMtime = Nfs3SetTimeClient;
1301 attr.mtime.sec = r->d.mtime;
1306 attr.setAtime = Nfs3SetTimeClient;
1307 attr.atime.sec = r->d.atime;
1312 /* Try rename first because it's more likely to fail (?) */
1313 if(r->d.name && r->d.name[0]){
1314 if(aux->name == nil){
1315 respond(r, "nfsclient botch -- don't know parent handle in rename");
1318 if(nfsRename(aux->auth, r->tag, &aux->parent, aux->name, &aux->parent, r->d.name) < 0){
1323 aux->name = estrdup9p(r->d.name);
1328 * Now we have a problem. The rename succeeded
1329 * but the setattr could fail. Sic transit atomicity.
1332 if(nfsSetattr(aux->auth, r->tag, &aux->handle, &attr) < 0){
1340 if(nfsCommit(aux->auth, r->tag, &aux->handle) < 0){
1350 fswalk1(Fid *fid, char *name, void *v)
1361 if(nfsLookup(aux->auth, tag, &aux->handle, name, &h, &have, &attr) < 0
1362 || (!have && nfsGetattr(aux->auth, tag, &h, &attr) < 0)){
1363 rerrstr(aux->err, sizeof aux->err);
1367 aux->parent = aux->handle;
1370 if(strcmp(name, "..") == 0)
1373 aux->name = estrdup9p(name);
1374 attrToQid(&attr, &fid->qid);
1379 fsclone(Fid *fid, Fid *newfid, void*)
1384 na = emalloc9p(sizeof(FidAux));
1387 na->name = estrdup9p(na->name);
1397 walkandclone(r, fswalk1, fsclone, &r->tag);
1406 * Send on the flush channel(s).
1407 * The library will make sure the response
1408 * is delayed as necessary.
1412 sendul(nfscli->flushchan, (ulong)or->tag);
1414 sendul(mntcli->flushchan, (ulong)or->tag);
1424 switch(r->ifcall.type){
1425 default: respond(r, "unknown type"); break;
1426 case Tattach: fsattach(r); break;
1427 case Topen: fsopen(r); break;
1428 case Tcreate: fscreate(r); break;
1429 case Tread: fsread(r); break;
1430 case Twrite: fswrite(r); break;
1431 case Tremove: fsremove(r); break;
1432 case Tflush: fsflush(r); break;
1433 case Tstat: fsstat(r); break;
1434 case Twstat: fswstat(r); break;
1435 case Twalk: fswalk(r); break;
1444 while((r = recvp(fschan)) != nil)
1445 threadcreate(fsdispatch, r, SunStackSize);
1457 threadexitsall(nil);
1462 .destroyfid = fsdestroyfid,
1479 fprint(2, "usage: nfs [-DRv] [-p perm] [-s srvname] [-u passwd group] addr [addr]\n");
1480 fprint(2, "\taddr - address of portmapper server\n");
1481 fprint(2, "\taddr addr - addresses of mount server and nfs server\n");
1486 netchangeport(char *addr, uint port, char *buf, uint nbuf)
1490 strecpy(buf, buf+nbuf, addr);
1491 r = strrchr(buf, '!');
1495 seprint(r, buf+nbuf, "%ud", port);
1499 char mbuf[256], nbuf[256];
1500 char *mountaddr, *nfsaddr;
1503 void dialproc(void*);
1506 threadmain(int argc, char **argv)
1508 char *srvname, *passwd, *group, *addr, *p;
1532 perm = strtol(EARGF(usage()), &p, 8);
1533 if(perm==0 || *p != 0)
1537 srvname = EARGF(usage());
1540 passwd = EARGF(usage());
1541 group = EARGF(usage());
1548 if(argc != 1 && argc != 2)
1554 fmtinstall('B', sunRpcFmt);
1555 fmtinstall('C', sunCallFmt);
1556 fmtinstall('H', encodefmt);
1557 sunFmtInstall(&portProg);
1558 sunFmtInstall(&nfs3Prog);
1559 sunFmtInstall(&nfsMount3Prog);
1561 if(passwd && (map = readmap(passwd, group)) == nil)
1562 fprint(2, "warning: reading %s and %s: %r\n", passwd, group);
1568 addr = netmkaddr(argv[0], "udp", "portmap");
1569 if((cli = sunDial(addr)) == nil)
1570 sysfatal("dial %s: %r", addr);
1571 cli->chatty = chattyrpc;
1572 sunClientProg(cli, &portProg);
1573 if(strstr(addr, "udp!"))
1574 proto = PortProtoUdp;
1576 proto = PortProtoTcp;
1577 if(getport(cli, NfsMount3Program, NfsMount3Version, proto, &mport) < 0)
1578 sysfatal("lookup mount program port: %r");
1579 if(getport(cli, Nfs3Program, Nfs3Version, proto, &nport) < 0)
1580 sysfatal("lookup nfs program port: %r");
1581 sunClientClose(cli);
1582 mountaddr = netchangeport(addr, mport, mbuf, sizeof mbuf);
1583 nfsaddr = netchangeport(addr, nport, nbuf, sizeof nbuf);
1584 strcat(mountaddr, "!r");
1585 strcat(nfsaddr, "!r");
1587 fprint(2, "nfs %s %s\n", mountaddr, nfsaddr);
1589 mountaddr = argv[0];
1593 /* have to dial in another proc because it creates threads */
1594 csync = chancreate(sizeof(void*), 0);
1595 proccreate(dialproc, nil, SunStackSize);
1598 threadpostmountsrv(&fs, srvname, nil, 0);
1600 p = smprint("/srv/%s", srvname);
1615 if((mntcli = sunDial(mountaddr)) == nil)
1616 sysfatal("dial mount program at %s: %r", mountaddr);
1617 mntcli->chatty = chattyrpc;
1618 sunClientProg(mntcli, &nfsMount3Prog);
1619 if(mountNull(0) < 0)
1620 sysfatal("execute nop with mnt server at %s: %r", mountaddr);
1622 if((nfscli = sunDial(nfsaddr)) == nil)
1623 sysfatal("dial nfs program at %s: %r", nfsaddr);
1624 nfscli->chatty = chattyrpc;
1625 sunClientProg(nfscli, &nfs3Prog);
1627 sysfatal("execute nop with nfs server at %s: %r", nfsaddr);
1629 fschan = chancreate(sizeof(Req*), 0);
1630 threadcreate(fsthread, nil, SunStackSize);