134e04225SDavid du Colombier /* Copyright © 2003 Russ Cox, MIT; see /sys/src/libsunrpc/COPYING */
234e04225SDavid du Colombier #include <u.h>
334e04225SDavid du Colombier #include <libc.h>
434e04225SDavid du Colombier #include <bio.h>
534e04225SDavid du Colombier #include <fcall.h>
634e04225SDavid du Colombier #include <thread.h>
734e04225SDavid du Colombier #include <9p.h>
834e04225SDavid du Colombier #include <sunrpc.h>
934e04225SDavid du Colombier #include <nfs3.h>
1034e04225SDavid du Colombier
1134e04225SDavid du Colombier SunClient *nfscli;
1234e04225SDavid du Colombier SunClient *mntcli;
1334e04225SDavid du Colombier char *defaultpath = "/";
1434e04225SDavid du Colombier Channel *fschan;
1534e04225SDavid du Colombier char *sys;
1634e04225SDavid du Colombier int verbose;
1734e04225SDavid du Colombier int readplus = 0;
1834e04225SDavid du Colombier
1934e04225SDavid du Colombier
2034e04225SDavid du Colombier typedef struct Auth Auth;
2134e04225SDavid du Colombier struct Auth
2234e04225SDavid du Colombier {
2334e04225SDavid du Colombier int ref;
2434e04225SDavid du Colombier uchar *data;
2534e04225SDavid du Colombier int ndata;
2634e04225SDavid du Colombier };
2734e04225SDavid du Colombier
2834e04225SDavid du Colombier typedef struct FidAux FidAux;
2934e04225SDavid du Colombier struct FidAux
3034e04225SDavid du Colombier {
3134e04225SDavid du Colombier Nfs3Handle handle;
3234e04225SDavid du Colombier
3334e04225SDavid du Colombier u64int cookie; /* for continuing directory reads */
3434e04225SDavid du Colombier char *name; /* botch: for remove and rename */
3534e04225SDavid du Colombier Nfs3Handle parent; /* botch: for remove and rename */
3634e04225SDavid du Colombier char err[ERRMAX]; /* for walk1 */
3734e04225SDavid du Colombier Auth *auth;
3834e04225SDavid du Colombier };
3934e04225SDavid du Colombier
4034e04225SDavid du Colombier /*
4134e04225SDavid du Colombier * various RPCs. here is where we'd insert support for NFS v2
4234e04225SDavid du Colombier */
4334e04225SDavid du Colombier
4434e04225SDavid du Colombier void
portCall(SunCall * c,PortCallType type)4534e04225SDavid du Colombier portCall(SunCall *c, PortCallType type)
4634e04225SDavid du Colombier {
4734e04225SDavid du Colombier c->rpc.prog = PortProgram;
4834e04225SDavid du Colombier c->rpc.vers = PortVersion;
4934e04225SDavid du Colombier c->rpc.proc = type>>1;
5034e04225SDavid du Colombier c->rpc.iscall = !(type&1);
5134e04225SDavid du Colombier c->type = type;
5234e04225SDavid du Colombier }
5334e04225SDavid du Colombier
5434e04225SDavid du Colombier int
getport(SunClient * client,uint prog,uint vers,uint prot,uint * port)5534e04225SDavid du Colombier getport(SunClient *client, uint prog, uint vers, uint prot, uint *port)
5634e04225SDavid du Colombier {
5734e04225SDavid du Colombier PortTGetport tx;
5834e04225SDavid du Colombier PortRGetport rx;
5934e04225SDavid du Colombier
6034e04225SDavid du Colombier memset(&tx, 0, sizeof tx);
6134e04225SDavid du Colombier portCall(&tx.call, PortCallTGetport);
6234e04225SDavid du Colombier tx.map.prog = prog;
6334e04225SDavid du Colombier tx.map.vers = vers;
6434e04225SDavid du Colombier tx.map.prot = prot;
6534e04225SDavid du Colombier
6634e04225SDavid du Colombier memset(&rx, 0, sizeof rx);
6734e04225SDavid du Colombier portCall(&rx.call, PortCallRGetport);
6834e04225SDavid du Colombier
6934e04225SDavid du Colombier if(sunClientRpc(client, 0, &tx.call, &rx.call, nil) < 0)
7034e04225SDavid du Colombier return -1;
7134e04225SDavid du Colombier *port = rx.port;
7234e04225SDavid du Colombier return 0;
7334e04225SDavid du Colombier }
7434e04225SDavid du Colombier
7534e04225SDavid du Colombier void
mountCall(Auth * a,SunCall * c,NfsMount3CallType type)7634e04225SDavid du Colombier mountCall(Auth *a, SunCall *c, NfsMount3CallType type)
7734e04225SDavid du Colombier {
7834e04225SDavid du Colombier c->rpc.iscall = !(type&1);
7934e04225SDavid du Colombier c->rpc.proc = type>>1;
8034e04225SDavid du Colombier c->rpc.prog = NfsMount3Program;
8134e04225SDavid du Colombier c->rpc.vers = NfsMount3Version;
8234e04225SDavid du Colombier if(c->rpc.iscall && a){
8334e04225SDavid du Colombier c->rpc.cred.flavor = SunAuthSys;
8434e04225SDavid du Colombier c->rpc.cred.data = a->data;
8534e04225SDavid du Colombier c->rpc.cred.ndata = a->ndata;
8634e04225SDavid du Colombier }
8734e04225SDavid du Colombier c->type = type;
8834e04225SDavid du Colombier }
8934e04225SDavid du Colombier
9034e04225SDavid du Colombier int
mountNull(ulong tag)9134e04225SDavid du Colombier mountNull(ulong tag)
9234e04225SDavid du Colombier {
9334e04225SDavid du Colombier NfsMount3TNull tx;
9434e04225SDavid du Colombier NfsMount3RNull rx;
9534e04225SDavid du Colombier
9634e04225SDavid du Colombier memset(&tx, 0, sizeof tx);
9734e04225SDavid du Colombier mountCall(nil, &tx.call, NfsMount3CallTNull);
9834e04225SDavid du Colombier
9934e04225SDavid du Colombier memset(&rx, 0, sizeof rx);
10034e04225SDavid du Colombier mountCall(nil, &rx.call, NfsMount3CallTNull);
10134e04225SDavid du Colombier
10234e04225SDavid du Colombier return sunClientRpc(mntcli, tag, &tx.call, &rx.call, nil);
10334e04225SDavid du Colombier }
10434e04225SDavid du Colombier
10534e04225SDavid du Colombier int
mountMnt(Auth * a,ulong tag,char * path,Nfs3Handle * h)10634e04225SDavid du Colombier mountMnt(Auth *a, ulong tag, char *path, Nfs3Handle *h)
10734e04225SDavid du Colombier {
10834e04225SDavid du Colombier uchar *freeme;
10934e04225SDavid du Colombier NfsMount3TMnt tx;
11034e04225SDavid du Colombier NfsMount3RMnt rx;
11134e04225SDavid du Colombier
11234e04225SDavid du Colombier memset(&tx, 0, sizeof tx);
11334e04225SDavid du Colombier mountCall(a, &tx.call, NfsMount3CallTMnt);
11434e04225SDavid du Colombier tx.path = path;
11534e04225SDavid du Colombier
11634e04225SDavid du Colombier memset(&rx, 0, sizeof rx);
11734e04225SDavid du Colombier mountCall(a, &rx.call, NfsMount3CallRMnt);
11834e04225SDavid du Colombier if(sunClientRpc(mntcli, tag, &tx.call, &rx.call, &freeme) < 0)
11934e04225SDavid du Colombier return -1;
12034e04225SDavid du Colombier if(rx.status != Nfs3Ok){
12134e04225SDavid du Colombier nfs3Errstr(rx.status);
12234e04225SDavid du Colombier return -1;
12334e04225SDavid du Colombier }
12434e04225SDavid du Colombier if(verbose)print("handle %.*H\n", rx.len, rx.handle);
12534e04225SDavid du Colombier if(rx.len >= Nfs3MaxHandleSize){
12634e04225SDavid du Colombier free(freeme);
12734e04225SDavid du Colombier werrstr("server-returned handle too long");
12834e04225SDavid du Colombier return -1;
12934e04225SDavid du Colombier }
13034e04225SDavid du Colombier memmove(h->h, rx.handle, rx.len);
13134e04225SDavid du Colombier h->len = rx.len;
13234e04225SDavid du Colombier free(freeme);
13334e04225SDavid du Colombier return 0;
13434e04225SDavid du Colombier }
13534e04225SDavid du Colombier
13634e04225SDavid du Colombier void
nfs3Call(Auth * a,SunCall * c,Nfs3CallType type)13734e04225SDavid du Colombier nfs3Call(Auth *a, SunCall *c, Nfs3CallType type)
13834e04225SDavid du Colombier {
13934e04225SDavid du Colombier c->rpc.iscall = !(type&1);
14034e04225SDavid du Colombier c->rpc.proc = type>>1;
14134e04225SDavid du Colombier c->rpc.prog = Nfs3Program;
14234e04225SDavid du Colombier c->rpc.vers = Nfs3Version;
14334e04225SDavid du Colombier if(c->rpc.iscall && a){
14434e04225SDavid du Colombier c->rpc.cred.flavor = SunAuthSys;
14534e04225SDavid du Colombier c->rpc.cred.data = a->data;
14634e04225SDavid du Colombier c->rpc.cred.ndata = a->ndata;
14734e04225SDavid du Colombier }
14834e04225SDavid du Colombier c->type = type;
14934e04225SDavid du Colombier }
15034e04225SDavid du Colombier
15134e04225SDavid du Colombier int
nfsNull(ulong tag)15234e04225SDavid du Colombier nfsNull(ulong tag)
15334e04225SDavid du Colombier {
15434e04225SDavid du Colombier Nfs3TNull tx;
15534e04225SDavid du Colombier Nfs3RNull rx;
15634e04225SDavid du Colombier
15734e04225SDavid du Colombier memset(&tx, 0, sizeof tx);
15834e04225SDavid du Colombier nfs3Call(nil, &tx.call, Nfs3CallTNull);
15934e04225SDavid du Colombier
16034e04225SDavid du Colombier memset(&rx, 0, sizeof rx);
16134e04225SDavid du Colombier nfs3Call(nil, &rx.call, Nfs3CallTNull);
16234e04225SDavid du Colombier
16334e04225SDavid du Colombier return sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil);
16434e04225SDavid du Colombier }
16534e04225SDavid du Colombier
16634e04225SDavid du Colombier int
nfsGetattr(Auth * a,ulong tag,Nfs3Handle * h,Nfs3Attr * attr)16734e04225SDavid du Colombier nfsGetattr(Auth *a, ulong tag, Nfs3Handle *h, Nfs3Attr *attr)
16834e04225SDavid du Colombier {
16934e04225SDavid du Colombier Nfs3TGetattr tx;
17034e04225SDavid du Colombier Nfs3RGetattr rx;
17134e04225SDavid du Colombier
17234e04225SDavid du Colombier memset(&tx, 0, sizeof tx);
17334e04225SDavid du Colombier nfs3Call(a, &tx.call, Nfs3CallTGetattr);
17434e04225SDavid du Colombier tx.handle = *h;
17534e04225SDavid du Colombier
17634e04225SDavid du Colombier memset(&rx, 0, sizeof rx);
17734e04225SDavid du Colombier nfs3Call(a, &rx.call, Nfs3CallRGetattr);
17834e04225SDavid du Colombier
17934e04225SDavid du Colombier if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0)
18034e04225SDavid du Colombier return -1;
18134e04225SDavid du Colombier if(rx.status != Nfs3Ok){
18234e04225SDavid du Colombier nfs3Errstr(rx.status);
18334e04225SDavid du Colombier return -1;
18434e04225SDavid du Colombier }
18534e04225SDavid du Colombier
18634e04225SDavid du Colombier *attr = rx.attr;
18734e04225SDavid du Colombier return 0;
18834e04225SDavid du Colombier }
18934e04225SDavid du Colombier
19034e04225SDavid du Colombier int
nfsAccess(Auth * a,ulong tag,Nfs3Handle * h,ulong want,ulong * got,u1int * have,Nfs3Attr * attr)19134e04225SDavid du Colombier nfsAccess(Auth *a, ulong tag, Nfs3Handle *h, ulong want, ulong *got, u1int *have, Nfs3Attr *attr)
19234e04225SDavid du Colombier {
19334e04225SDavid du Colombier Nfs3TAccess tx;
19434e04225SDavid du Colombier Nfs3RAccess rx;
19534e04225SDavid du Colombier
19634e04225SDavid du Colombier memset(&tx, 0, sizeof tx);
19734e04225SDavid du Colombier nfs3Call(a, &tx.call, Nfs3CallTAccess);
19834e04225SDavid du Colombier tx.handle = *h;
19934e04225SDavid du Colombier tx.access = want;
20034e04225SDavid du Colombier
20134e04225SDavid du Colombier memset(&rx, 0, sizeof rx);
20234e04225SDavid du Colombier nfs3Call(a, &rx.call, Nfs3CallRAccess);
20334e04225SDavid du Colombier
20434e04225SDavid du Colombier if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0)
20534e04225SDavid du Colombier return -1;
20634e04225SDavid du Colombier if(rx.status != Nfs3Ok){
20734e04225SDavid du Colombier nfs3Errstr(rx.status);
20834e04225SDavid du Colombier return -1;
20934e04225SDavid du Colombier }
21034e04225SDavid du Colombier
21134e04225SDavid du Colombier *got = rx.access;
21234e04225SDavid du Colombier
21334e04225SDavid du Colombier *have = rx.haveAttr;
21434e04225SDavid du Colombier if(rx.haveAttr)
21534e04225SDavid du Colombier *attr = rx.attr;
21634e04225SDavid du Colombier return 0;
21734e04225SDavid du Colombier }
21834e04225SDavid du Colombier
21934e04225SDavid du Colombier int
nfsMkdir(Auth * a,ulong tag,Nfs3Handle * h,char * name,Nfs3Handle * nh,ulong mode,uint gid,u1int * have,Nfs3Attr * attr)22034e04225SDavid du Colombier nfsMkdir(Auth *a, ulong tag, Nfs3Handle *h, char *name, Nfs3Handle *nh, ulong mode, uint gid,
22134e04225SDavid du Colombier u1int *have, Nfs3Attr *attr)
22234e04225SDavid du Colombier {
22334e04225SDavid du Colombier Nfs3TMkdir tx;
22434e04225SDavid du Colombier Nfs3RMkdir rx;
22534e04225SDavid du Colombier
22634e04225SDavid du Colombier memset(&tx, 0, sizeof tx);
22734e04225SDavid du Colombier nfs3Call(a, &tx.call, Nfs3CallTMkdir);
22834e04225SDavid du Colombier tx.handle = *h;
22934e04225SDavid du Colombier tx.name = name;
23034e04225SDavid du Colombier tx.attr.setMode = 1;
23134e04225SDavid du Colombier tx.attr.mode = mode;
23234e04225SDavid du Colombier tx.attr.setGid = 1;
23334e04225SDavid du Colombier tx.attr.gid = gid;
23434e04225SDavid du Colombier
23534e04225SDavid du Colombier memset(&rx, 0, sizeof rx);
23634e04225SDavid du Colombier nfs3Call(a, &rx.call, Nfs3CallRMkdir);
23734e04225SDavid du Colombier
23834e04225SDavid du Colombier if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0)
23934e04225SDavid du Colombier return -1;
24034e04225SDavid du Colombier if(rx.status != Nfs3Ok){
24134e04225SDavid du Colombier nfs3Errstr(rx.status);
24234e04225SDavid du Colombier return -1;
24334e04225SDavid du Colombier }
24434e04225SDavid du Colombier
24534e04225SDavid du Colombier if(!rx.haveHandle){
24634e04225SDavid du Colombier werrstr("nfs mkdir did not return handle");
24734e04225SDavid du Colombier return -1;
24834e04225SDavid du Colombier }
24934e04225SDavid du Colombier *nh = rx.handle;
25034e04225SDavid du Colombier
25134e04225SDavid du Colombier *have = rx.haveAttr;
25234e04225SDavid du Colombier if(rx.haveAttr)
25334e04225SDavid du Colombier *attr = rx.attr;
25434e04225SDavid du Colombier return 0;
25534e04225SDavid du Colombier }
25634e04225SDavid du Colombier
25734e04225SDavid du Colombier int
nfsCreate(Auth * a,ulong tag,Nfs3Handle * h,char * name,Nfs3Handle * nh,ulong mode,uint gid,u1int * have,Nfs3Attr * attr)25834e04225SDavid du Colombier nfsCreate(Auth *a, ulong tag, Nfs3Handle *h, char *name, Nfs3Handle *nh, ulong mode, uint gid,
25934e04225SDavid du Colombier u1int *have, Nfs3Attr *attr)
26034e04225SDavid du Colombier {
26134e04225SDavid du Colombier Nfs3TCreate tx;
26234e04225SDavid du Colombier Nfs3RCreate rx;
26334e04225SDavid du Colombier
26434e04225SDavid du Colombier memset(&tx, 0, sizeof tx);
26534e04225SDavid du Colombier nfs3Call(a, &tx.call, Nfs3CallTCreate);
26634e04225SDavid du Colombier tx.handle = *h;
26734e04225SDavid du Colombier tx.name = name;
26834e04225SDavid du Colombier tx.attr.setMode = 1;
26934e04225SDavid du Colombier tx.attr.mode = mode;
27034e04225SDavid du Colombier tx.attr.setGid = 1;
27134e04225SDavid du Colombier tx.attr.gid = gid;
27234e04225SDavid du Colombier
27334e04225SDavid du Colombier memset(&rx, 0, sizeof rx);
27434e04225SDavid du Colombier nfs3Call(a, &rx.call, Nfs3CallRCreate);
27534e04225SDavid du Colombier
27634e04225SDavid du Colombier if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0)
27734e04225SDavid du Colombier return -1;
27834e04225SDavid du Colombier if(rx.status != Nfs3Ok){
27934e04225SDavid du Colombier nfs3Errstr(rx.status);
28034e04225SDavid du Colombier return -1;
28134e04225SDavid du Colombier }
28234e04225SDavid du Colombier
28334e04225SDavid du Colombier if(!rx.haveHandle){
28434e04225SDavid du Colombier werrstr("nfs create did not return handle");
28534e04225SDavid du Colombier return -1;
28634e04225SDavid du Colombier }
28734e04225SDavid du Colombier *nh = rx.handle;
28834e04225SDavid du Colombier
28934e04225SDavid du Colombier *have = rx.haveAttr;
29034e04225SDavid du Colombier if(rx.haveAttr)
29134e04225SDavid du Colombier *attr = rx.attr;
29234e04225SDavid du Colombier return 0;
29334e04225SDavid du Colombier }
29434e04225SDavid du Colombier
29534e04225SDavid du Colombier int
nfsRead(Auth * a,ulong tag,Nfs3Handle * h,u32int count,u64int offset,uchar ** pp,u32int * pcount,uchar ** pfreeme)29634e04225SDavid du Colombier nfsRead(Auth *a, ulong tag, Nfs3Handle *h, u32int count, u64int offset,
29734e04225SDavid du Colombier uchar **pp, u32int *pcount, uchar **pfreeme)
29834e04225SDavid du Colombier {
29934e04225SDavid du Colombier uchar *freeme;
30034e04225SDavid du Colombier Nfs3TRead tx;
30134e04225SDavid du Colombier Nfs3RRead rx;
30234e04225SDavid du Colombier
30334e04225SDavid du Colombier memset(&tx, 0, sizeof tx);
30434e04225SDavid du Colombier nfs3Call(a, &tx.call, Nfs3CallTRead);
30534e04225SDavid du Colombier tx.handle = *h;
30634e04225SDavid du Colombier tx.count = count;
30734e04225SDavid du Colombier tx.offset = offset;
30834e04225SDavid du Colombier
30934e04225SDavid du Colombier memset(&rx, 0, sizeof rx);
31034e04225SDavid du Colombier nfs3Call(a, &rx.call, Nfs3CallRRead);
31134e04225SDavid du Colombier
31234e04225SDavid du Colombier if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, &freeme) < 0)
31334e04225SDavid du Colombier return -1;
31434e04225SDavid du Colombier if(rx.status != Nfs3Ok){
31534e04225SDavid du Colombier nfs3Errstr(rx.status);
31634e04225SDavid du Colombier return -1;
31734e04225SDavid du Colombier }
31834e04225SDavid du Colombier if(rx.count != rx.ndata){
31934e04225SDavid du Colombier werrstr("nfs read returned count=%ud ndata=%ud", (uint)rx.count, (uint)rx.ndata);
32034e04225SDavid du Colombier free(freeme);
32134e04225SDavid du Colombier return -1;
32234e04225SDavid du Colombier }
32334e04225SDavid du Colombier *pfreeme = freeme;
32434e04225SDavid du Colombier *pcount = rx.count;
32534e04225SDavid du Colombier *pp = rx.data;
32634e04225SDavid du Colombier return 0;
32734e04225SDavid du Colombier }
32834e04225SDavid du Colombier
32934e04225SDavid du Colombier int
nfsWrite(Auth * a,ulong tag,Nfs3Handle * h,uchar * data,u32int count,u64int offset,u32int * pcount)33034e04225SDavid du Colombier nfsWrite(Auth *a, ulong tag, Nfs3Handle *h, uchar *data, u32int count, u64int offset, u32int *pcount)
33134e04225SDavid du Colombier {
33234e04225SDavid du Colombier Nfs3TWrite tx;
33334e04225SDavid du Colombier Nfs3RWrite rx;
33434e04225SDavid du Colombier
33534e04225SDavid du Colombier memset(&tx, 0, sizeof tx);
33634e04225SDavid du Colombier nfs3Call(a, &tx.call, Nfs3CallTWrite);
33734e04225SDavid du Colombier tx.handle = *h;
33834e04225SDavid du Colombier tx.count = count;
33934e04225SDavid du Colombier tx.offset = offset;
34034e04225SDavid du Colombier tx.data = data;
3416ff5e913SDavid du Colombier tx.ndata = count;
34234e04225SDavid du Colombier
34334e04225SDavid du Colombier memset(&rx, 0, sizeof rx);
34434e04225SDavid du Colombier nfs3Call(a, &rx.call, Nfs3CallRWrite);
34534e04225SDavid du Colombier
34634e04225SDavid du Colombier if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0)
34734e04225SDavid du Colombier return -1;
34834e04225SDavid du Colombier if(rx.status != Nfs3Ok){
34934e04225SDavid du Colombier nfs3Errstr(rx.status);
35034e04225SDavid du Colombier return -1;
35134e04225SDavid du Colombier }
35234e04225SDavid du Colombier
35334e04225SDavid du Colombier *pcount = rx.count;
35434e04225SDavid du Colombier return 0;
35534e04225SDavid du Colombier }
35634e04225SDavid du Colombier
35734e04225SDavid du Colombier int
nfsRmdir(Auth * a,ulong tag,Nfs3Handle * h,char * name)35834e04225SDavid du Colombier nfsRmdir(Auth *a, ulong tag, Nfs3Handle *h, char *name)
35934e04225SDavid du Colombier {
36034e04225SDavid du Colombier Nfs3TRmdir tx;
36134e04225SDavid du Colombier Nfs3RRmdir rx;
36234e04225SDavid du Colombier
36334e04225SDavid du Colombier memset(&tx, 0, sizeof tx);
36434e04225SDavid du Colombier nfs3Call(a, &tx.call, Nfs3CallTRmdir);
36534e04225SDavid du Colombier tx.handle = *h;
36634e04225SDavid du Colombier tx.name = name;
36734e04225SDavid du Colombier
36834e04225SDavid du Colombier memset(&rx, 0, sizeof rx);
36934e04225SDavid du Colombier nfs3Call(a, &rx.call, Nfs3CallRRmdir);
37034e04225SDavid du Colombier
37134e04225SDavid du Colombier if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0)
37234e04225SDavid du Colombier return -1;
37334e04225SDavid du Colombier if(rx.status != Nfs3Ok){
37434e04225SDavid du Colombier nfs3Errstr(rx.status);
37534e04225SDavid du Colombier return -1;
37634e04225SDavid du Colombier }
37734e04225SDavid du Colombier return 0;
37834e04225SDavid du Colombier }
37934e04225SDavid du Colombier
38034e04225SDavid du Colombier int
nfsRemove(Auth * a,ulong tag,Nfs3Handle * h,char * name)38134e04225SDavid du Colombier nfsRemove(Auth *a, ulong tag, Nfs3Handle *h, char *name)
38234e04225SDavid du Colombier {
38334e04225SDavid du Colombier Nfs3TRemove tx;
38434e04225SDavid du Colombier Nfs3RRemove rx;
38534e04225SDavid du Colombier
38634e04225SDavid du Colombier memset(&tx, 0, sizeof tx);
38734e04225SDavid du Colombier nfs3Call(a, &tx.call, Nfs3CallTRemove);
38834e04225SDavid du Colombier tx.handle = *h;
38934e04225SDavid du Colombier tx.name = name;
39034e04225SDavid du Colombier
39134e04225SDavid du Colombier memset(&rx, 0, sizeof rx);
39234e04225SDavid du Colombier nfs3Call(a, &rx.call, Nfs3CallRRemove);
39334e04225SDavid du Colombier
39434e04225SDavid du Colombier if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0)
39534e04225SDavid du Colombier return -1;
39634e04225SDavid du Colombier if(rx.status != Nfs3Ok){
39734e04225SDavid du Colombier nfs3Errstr(rx.status);
39834e04225SDavid du Colombier return -1;
39934e04225SDavid du Colombier }
40034e04225SDavid du Colombier return 0;
40134e04225SDavid du Colombier }
40234e04225SDavid du Colombier
40334e04225SDavid du Colombier int
nfsRename(Auth * a,ulong tag,Nfs3Handle * h,char * name,Nfs3Handle * th,char * tname)40434e04225SDavid du Colombier nfsRename(Auth *a, ulong tag, Nfs3Handle *h, char *name, Nfs3Handle *th, char *tname)
40534e04225SDavid du Colombier {
40634e04225SDavid du Colombier Nfs3TRename tx;
40734e04225SDavid du Colombier Nfs3RRename rx;
40834e04225SDavid du Colombier
40934e04225SDavid du Colombier memset(&tx, 0, sizeof tx);
41034e04225SDavid du Colombier nfs3Call(a, &tx.call, Nfs3CallTRename);
41134e04225SDavid du Colombier tx.from.handle = *h;
41234e04225SDavid du Colombier tx.from.name = name;
41334e04225SDavid du Colombier tx.to.handle = *th;
41434e04225SDavid du Colombier tx.to.name = tname;
41534e04225SDavid du Colombier
41634e04225SDavid du Colombier memset(&rx, 0, sizeof rx);
41734e04225SDavid du Colombier nfs3Call(a, &rx.call, Nfs3CallRRename);
41834e04225SDavid du Colombier
41934e04225SDavid du Colombier if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0)
42034e04225SDavid du Colombier return -1;
42134e04225SDavid du Colombier if(rx.status != Nfs3Ok){
42234e04225SDavid du Colombier nfs3Errstr(rx.status);
42334e04225SDavid du Colombier return -1;
42434e04225SDavid du Colombier }
42534e04225SDavid du Colombier return 0;
42634e04225SDavid du Colombier }
42734e04225SDavid du Colombier
42834e04225SDavid du Colombier int
nfsSetattr(Auth * a,ulong tag,Nfs3Handle * h,Nfs3SetAttr * attr)42934e04225SDavid du Colombier nfsSetattr(Auth *a, ulong tag, Nfs3Handle *h, Nfs3SetAttr *attr)
43034e04225SDavid du Colombier {
43134e04225SDavid du Colombier Nfs3TSetattr tx;
43234e04225SDavid du Colombier Nfs3RSetattr rx;
43334e04225SDavid du Colombier
43434e04225SDavid du Colombier memset(&tx, 0, sizeof tx);
43534e04225SDavid du Colombier nfs3Call(a, &tx.call, Nfs3CallTSetattr);
43634e04225SDavid du Colombier tx.handle = *h;
43734e04225SDavid du Colombier tx.attr = *attr;
43834e04225SDavid du Colombier
43934e04225SDavid du Colombier memset(&rx, 0, sizeof rx);
44034e04225SDavid du Colombier nfs3Call(a, &rx.call, Nfs3CallRSetattr);
44134e04225SDavid du Colombier
44234e04225SDavid du Colombier if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0)
44334e04225SDavid du Colombier return -1;
44434e04225SDavid du Colombier if(rx.status != Nfs3Ok){
44534e04225SDavid du Colombier nfs3Errstr(rx.status);
44634e04225SDavid du Colombier return -1;
44734e04225SDavid du Colombier }
44834e04225SDavid du Colombier return 0;
44934e04225SDavid du Colombier }
45034e04225SDavid du Colombier
45134e04225SDavid du Colombier int
nfsCommit(Auth * a,ulong tag,Nfs3Handle * h)45234e04225SDavid du Colombier nfsCommit(Auth *a, ulong tag, Nfs3Handle *h)
45334e04225SDavid du Colombier {
45434e04225SDavid du Colombier Nfs3TCommit tx;
45534e04225SDavid du Colombier Nfs3RCommit rx;
45634e04225SDavid du Colombier
45734e04225SDavid du Colombier memset(&tx, 0, sizeof tx);
45834e04225SDavid du Colombier nfs3Call(a, &tx.call, Nfs3CallTCommit);
45934e04225SDavid du Colombier tx.handle = *h;
46034e04225SDavid du Colombier
46134e04225SDavid du Colombier memset(&rx, 0, sizeof rx);
46234e04225SDavid du Colombier nfs3Call(a, &rx.call, Nfs3CallRCommit);
46334e04225SDavid du Colombier
46434e04225SDavid du Colombier if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0)
46534e04225SDavid du Colombier return -1;
46634e04225SDavid du Colombier
46734e04225SDavid du Colombier if(rx.status != Nfs3Ok){
46834e04225SDavid du Colombier nfs3Errstr(rx.status);
46934e04225SDavid du Colombier return -1;
47034e04225SDavid du Colombier }
47134e04225SDavid du Colombier return 0;
47234e04225SDavid du Colombier }
47334e04225SDavid du Colombier
47434e04225SDavid du Colombier int
nfsLookup(Auth * a,ulong tag,Nfs3Handle * h,char * name,Nfs3Handle * nh,u1int * have,Nfs3Attr * attr)47534e04225SDavid du Colombier nfsLookup(Auth *a, ulong tag, Nfs3Handle *h, char *name, Nfs3Handle *nh, u1int *have, Nfs3Attr *attr)
47634e04225SDavid du Colombier {
47734e04225SDavid du Colombier Nfs3TLookup tx;
47834e04225SDavid du Colombier Nfs3RLookup rx;
47934e04225SDavid du Colombier
48034e04225SDavid du Colombier memset(&tx, 0, sizeof tx);
48134e04225SDavid du Colombier nfs3Call(a, &tx.call, Nfs3CallTLookup);
48234e04225SDavid du Colombier tx.handle = *h;
48334e04225SDavid du Colombier tx.name = name;
48434e04225SDavid du Colombier
48534e04225SDavid du Colombier memset(&rx, 0, sizeof rx);
48634e04225SDavid du Colombier nfs3Call(a, &rx.call, Nfs3CallRLookup);
48734e04225SDavid du Colombier
48834e04225SDavid du Colombier if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0)
48934e04225SDavid du Colombier return -1;
49034e04225SDavid du Colombier
49134e04225SDavid du Colombier if(rx.status != Nfs3Ok){
49234e04225SDavid du Colombier nfs3Errstr(rx.status);
49334e04225SDavid du Colombier return -1;
49434e04225SDavid du Colombier }
49534e04225SDavid du Colombier *nh = rx.handle;
49634e04225SDavid du Colombier *have = rx.haveAttr;
49734e04225SDavid du Colombier if(rx.haveAttr)
49834e04225SDavid du Colombier *attr = rx.attr;
49934e04225SDavid du Colombier return 0;
50034e04225SDavid du Colombier }
50134e04225SDavid du Colombier
50234e04225SDavid du Colombier int
nfsReadDirPlus(Auth * a,ulong tag,Nfs3Handle * h,u32int count,u64int cookie,uchar ** pp,u32int * pcount,int (** unpack)(uchar *,uchar *,uchar **,Nfs3Entry *),uchar ** pfreeme)50334e04225SDavid du Colombier nfsReadDirPlus(Auth *a, ulong tag, Nfs3Handle *h, u32int count, u64int cookie, uchar **pp,
50434e04225SDavid du Colombier u32int *pcount, int (**unpack)(uchar*, uchar*, uchar**, Nfs3Entry*), uchar **pfreeme)
50534e04225SDavid du Colombier {
50634e04225SDavid du Colombier Nfs3TReadDirPlus tx;
50734e04225SDavid du Colombier Nfs3RReadDirPlus rx;
50834e04225SDavid du Colombier
50934e04225SDavid du Colombier memset(&tx, 0, sizeof tx);
51034e04225SDavid du Colombier nfs3Call(a, &tx.call, Nfs3CallTReadDirPlus);
51134e04225SDavid du Colombier tx.handle = *h;
51234e04225SDavid du Colombier tx.maxCount = count;
51334e04225SDavid du Colombier tx.dirCount = 1000;
51434e04225SDavid du Colombier tx.cookie = cookie;
51534e04225SDavid du Colombier
51634e04225SDavid du Colombier memset(&rx, 0, sizeof rx);
51734e04225SDavid du Colombier nfs3Call(a, &rx.call, Nfs3CallRReadDirPlus);
51834e04225SDavid du Colombier
51934e04225SDavid du Colombier if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, pfreeme) < 0)
52034e04225SDavid du Colombier return -1;
52134e04225SDavid du Colombier if(rx.status != Nfs3Ok){
52234e04225SDavid du Colombier free(*pfreeme);
52334e04225SDavid du Colombier *pfreeme = 0;
52434e04225SDavid du Colombier nfs3Errstr(rx.status);
52534e04225SDavid du Colombier return -1;
52634e04225SDavid du Colombier }
52734e04225SDavid du Colombier
52834e04225SDavid du Colombier *unpack = nfs3EntryPlusUnpack;
52934e04225SDavid du Colombier *pcount = rx.count;
53034e04225SDavid du Colombier *pp = rx.data;
53134e04225SDavid du Colombier return 0;
53234e04225SDavid du Colombier }
53334e04225SDavid du Colombier
53434e04225SDavid du Colombier int
nfsReadDir(Auth * a,ulong tag,Nfs3Handle * h,u32int count,u64int cookie,uchar ** pp,u32int * pcount,int (** unpack)(uchar *,uchar *,uchar **,Nfs3Entry *),uchar ** pfreeme)53534e04225SDavid du Colombier nfsReadDir(Auth *a, ulong tag, Nfs3Handle *h, u32int count, u64int cookie, uchar **pp,
53634e04225SDavid du Colombier u32int *pcount, int (**unpack)(uchar*, uchar*, uchar**, Nfs3Entry*), uchar **pfreeme)
53734e04225SDavid du Colombier {
53834e04225SDavid du Colombier /* BUG: try readdirplus */
53934e04225SDavid du Colombier char e[ERRMAX];
54034e04225SDavid du Colombier Nfs3TReadDir tx;
54134e04225SDavid du Colombier Nfs3RReadDir rx;
54234e04225SDavid du Colombier
54334e04225SDavid du Colombier if(readplus!=-1){
54434e04225SDavid du Colombier if(nfsReadDirPlus(a, tag, h, count, cookie, pp, pcount, unpack, pfreeme) == 0){
54534e04225SDavid du Colombier readplus = 1;
54634e04225SDavid du Colombier return 0;
54734e04225SDavid du Colombier }
54834e04225SDavid du Colombier if(readplus == 0){
54934e04225SDavid du Colombier rerrstr(e, sizeof e);
550fb7f0c93SDavid du Colombier if(strstr(e, "procedure unavailable") || strstr(e, "not supported"))
55134e04225SDavid du Colombier readplus = -1;
55234e04225SDavid du Colombier }
5536ff5e913SDavid du Colombier if(readplus == 0)
5546ff5e913SDavid du Colombier fprint(2, "readdirplus: %r\n");
55534e04225SDavid du Colombier }
55634e04225SDavid du Colombier if(readplus == 1)
55734e04225SDavid du Colombier return -1;
55834e04225SDavid du Colombier
55934e04225SDavid du Colombier memset(&tx, 0, sizeof tx);
56034e04225SDavid du Colombier nfs3Call(a, &tx.call, Nfs3CallTReadDir);
56134e04225SDavid du Colombier tx.handle = *h;
56234e04225SDavid du Colombier tx.count = count;
56334e04225SDavid du Colombier tx.cookie = cookie;
56434e04225SDavid du Colombier
56534e04225SDavid du Colombier memset(&rx, 0, sizeof rx);
56634e04225SDavid du Colombier nfs3Call(a, &rx.call, Nfs3CallRReadDir);
56734e04225SDavid du Colombier
56834e04225SDavid du Colombier if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, pfreeme) < 0)
56934e04225SDavid du Colombier return -1;
57034e04225SDavid du Colombier if(rx.status != Nfs3Ok){
57134e04225SDavid du Colombier free(*pfreeme);
57234e04225SDavid du Colombier *pfreeme = 0;
57334e04225SDavid du Colombier nfs3Errstr(rx.status);
57434e04225SDavid du Colombier return -1;
57534e04225SDavid du Colombier }
57634e04225SDavid du Colombier
57734e04225SDavid du Colombier /* readplus failed but read succeeded */
57834e04225SDavid du Colombier readplus = -1;
57934e04225SDavid du Colombier
58034e04225SDavid du Colombier *unpack = nfs3EntryUnpack;
58134e04225SDavid du Colombier *pcount = rx.count;
58234e04225SDavid du Colombier *pp = rx.data;
58334e04225SDavid du Colombier return 0;
58434e04225SDavid du Colombier }
58534e04225SDavid du Colombier
58634e04225SDavid du Colombier /*
58734e04225SDavid du Colombier * name <-> int translation
58834e04225SDavid du Colombier */
58934e04225SDavid du Colombier typedef struct Map Map;
59034e04225SDavid du Colombier typedef struct User User;
59134e04225SDavid du Colombier typedef struct Group Group;
59234e04225SDavid du Colombier
59334e04225SDavid du Colombier Map *map;
59434e04225SDavid du Colombier Map emptymap;
59534e04225SDavid du Colombier
59634e04225SDavid du Colombier struct User
59734e04225SDavid du Colombier {
59834e04225SDavid du Colombier char *name;
59934e04225SDavid du Colombier uint uid;
60034e04225SDavid du Colombier uint gid;
60134e04225SDavid du Colombier uint g[16];
60234e04225SDavid du Colombier uint ng;
60334e04225SDavid du Colombier uchar *auth;
60434e04225SDavid du Colombier int nauth;
60534e04225SDavid du Colombier };
60634e04225SDavid du Colombier
60734e04225SDavid du Colombier struct Group
60834e04225SDavid du Colombier {
60934e04225SDavid du Colombier char *name; /* same pos as in User struct */
61034e04225SDavid du Colombier uint gid; /* same pos as in User struct */
61134e04225SDavid du Colombier };
61234e04225SDavid du Colombier
61334e04225SDavid du Colombier struct Map
61434e04225SDavid du Colombier {
61534e04225SDavid du Colombier int nuser;
61634e04225SDavid du Colombier int ngroup;
61734e04225SDavid du Colombier User *user;
61834e04225SDavid du Colombier User **ubyname;
61934e04225SDavid du Colombier User **ubyid;
62034e04225SDavid du Colombier Group *group;
62134e04225SDavid du Colombier Group **gbyname;
62234e04225SDavid du Colombier Group **gbyid;
62334e04225SDavid du Colombier };
62434e04225SDavid du Colombier
62534e04225SDavid du Colombier User*
finduser(User ** u,int nu,char * s)62634e04225SDavid du Colombier finduser(User **u, int nu, char *s)
62734e04225SDavid du Colombier {
62834e04225SDavid du Colombier int lo, hi, mid, n;
62934e04225SDavid du Colombier
63034e04225SDavid du Colombier hi = nu;
63134e04225SDavid du Colombier lo = 0;
63234e04225SDavid du Colombier while(hi > lo){
63334e04225SDavid du Colombier mid = (lo+hi)/2;
63434e04225SDavid du Colombier n = strcmp(u[mid]->name, s);
63534e04225SDavid du Colombier if(n == 0)
63634e04225SDavid du Colombier return u[mid];
63734e04225SDavid du Colombier if(n < 0)
63834e04225SDavid du Colombier lo = mid+1;
63934e04225SDavid du Colombier else
64034e04225SDavid du Colombier hi = mid;
64134e04225SDavid du Colombier }
64234e04225SDavid du Colombier return nil;
64334e04225SDavid du Colombier }
64434e04225SDavid du Colombier
64534e04225SDavid du Colombier int
strtoid(User ** u,int nu,char * s,u32int * id)64634e04225SDavid du Colombier strtoid(User **u, int nu, char *s, u32int *id)
64734e04225SDavid du Colombier {
64834e04225SDavid du Colombier u32int x;
64934e04225SDavid du Colombier char *p;
65034e04225SDavid du Colombier User *uu;
65134e04225SDavid du Colombier
65234e04225SDavid du Colombier x = strtoul(s, &p, 10);
65334e04225SDavid du Colombier if(*s != 0 && *p == 0){
65434e04225SDavid du Colombier *id = x;
65534e04225SDavid du Colombier return 0;
65634e04225SDavid du Colombier }
65734e04225SDavid du Colombier
65834e04225SDavid du Colombier uu = finduser(u, nu, s);
65934e04225SDavid du Colombier if(uu == nil)
66034e04225SDavid du Colombier return -1;
66134e04225SDavid du Colombier *id = uu->uid;
66234e04225SDavid du Colombier return 0;
66334e04225SDavid du Colombier }
66434e04225SDavid du Colombier
66534e04225SDavid du Colombier char*
idtostr(User ** u,int nu,u32int id)66634e04225SDavid du Colombier idtostr(User **u, int nu, u32int id)
66734e04225SDavid du Colombier {
66834e04225SDavid du Colombier char buf[32];
66934e04225SDavid du Colombier int lo, hi, mid;
67034e04225SDavid du Colombier
67134e04225SDavid du Colombier hi = nu;
67234e04225SDavid du Colombier lo = 0;
67334e04225SDavid du Colombier while(hi > lo){
67434e04225SDavid du Colombier mid = (lo+hi)/2;
67534e04225SDavid du Colombier if(u[mid]->uid == id)
67634e04225SDavid du Colombier return estrdup9p(u[mid]->name);
67734e04225SDavid du Colombier if(u[mid]->uid < id)
67834e04225SDavid du Colombier lo = mid+1;
67934e04225SDavid du Colombier else
68034e04225SDavid du Colombier hi = mid;
68134e04225SDavid du Colombier }
68234e04225SDavid du Colombier snprint(buf, sizeof buf, "%ud", id);
68334e04225SDavid du Colombier return estrdup9p(buf);
68434e04225SDavid du Colombier }
68534e04225SDavid du Colombier char*
uidtostr(u32int uid)68634e04225SDavid du Colombier uidtostr(u32int uid)
68734e04225SDavid du Colombier {
68834e04225SDavid du Colombier return idtostr(map->ubyid, map->nuser, uid);
68934e04225SDavid du Colombier }
69034e04225SDavid du Colombier
69134e04225SDavid du Colombier char*
gidtostr(u32int gid)69234e04225SDavid du Colombier gidtostr(u32int gid)
69334e04225SDavid du Colombier {
69434e04225SDavid du Colombier return idtostr((User**)map->gbyid, map->ngroup, gid);
69534e04225SDavid du Colombier }
69634e04225SDavid du Colombier
69734e04225SDavid du Colombier int
strtouid(char * s,u32int * id)69834e04225SDavid du Colombier strtouid(char *s, u32int *id)
69934e04225SDavid du Colombier {
70034e04225SDavid du Colombier return strtoid(map->ubyname, map->nuser, s, id);
70134e04225SDavid du Colombier }
70234e04225SDavid du Colombier
70334e04225SDavid du Colombier int
strtogid(char * s,u32int * id)70434e04225SDavid du Colombier strtogid(char *s, u32int *id)
70534e04225SDavid du Colombier {
70634e04225SDavid du Colombier return strtoid((User**)map->gbyid, map->ngroup, s, id);
70734e04225SDavid du Colombier }
70834e04225SDavid du Colombier
70934e04225SDavid du Colombier
71034e04225SDavid du Colombier int
idcmp(const void * va,const void * vb)71134e04225SDavid du Colombier idcmp(const void *va, const void *vb)
71234e04225SDavid du Colombier {
71334e04225SDavid du Colombier User **a, **b;
71434e04225SDavid du Colombier
71534e04225SDavid du Colombier a = (User**)va;
71634e04225SDavid du Colombier b = (User**)vb;
71734e04225SDavid du Colombier return (*a)->uid - (*b)->uid;
71834e04225SDavid du Colombier }
71934e04225SDavid du Colombier
72034e04225SDavid du Colombier int
namecmp(const void * va,const void * vb)72134e04225SDavid du Colombier namecmp(const void *va, const void *vb)
72234e04225SDavid du Colombier {
72334e04225SDavid du Colombier User **a, **b;
72434e04225SDavid du Colombier
72534e04225SDavid du Colombier a = (User**)va;
72634e04225SDavid du Colombier b = (User**)vb;
72734e04225SDavid du Colombier return strcmp((*a)->name, (*b)->name);
72834e04225SDavid du Colombier }
72934e04225SDavid du Colombier
73034e04225SDavid du Colombier void
closemap(Map * m)73134e04225SDavid du Colombier closemap(Map *m)
73234e04225SDavid du Colombier {
73334e04225SDavid du Colombier int i;
73434e04225SDavid du Colombier
73534e04225SDavid du Colombier for(i=0; i<m->nuser; i++){
73634e04225SDavid du Colombier free(m->user[i].name);
73734e04225SDavid du Colombier free(m->user[i].auth);
73834e04225SDavid du Colombier }
73934e04225SDavid du Colombier for(i=0; i<m->ngroup; i++)
74034e04225SDavid du Colombier free(m->group[i].name);
74134e04225SDavid du Colombier free(m->user);
74234e04225SDavid du Colombier free(m->group);
74334e04225SDavid du Colombier free(m->ubyid);
74434e04225SDavid du Colombier free(m->ubyname);
74534e04225SDavid du Colombier free(m->gbyid);
74634e04225SDavid du Colombier free(m->gbyname);
74734e04225SDavid du Colombier free(m);
74834e04225SDavid du Colombier }
74934e04225SDavid du Colombier
75034e04225SDavid du Colombier Map*
readmap(char * passwd,char * group)75134e04225SDavid du Colombier readmap(char *passwd, char *group)
75234e04225SDavid du Colombier {
75334e04225SDavid du Colombier char *s, *f[10], *p, *nextp, *name;
75434e04225SDavid du Colombier uchar *q, *eq;
75534e04225SDavid du Colombier int i, n, nf, line, uid, gid;
75634e04225SDavid du Colombier Biobuf *b;
75734e04225SDavid du Colombier Map *m;
75834e04225SDavid du Colombier User *u;
75934e04225SDavid du Colombier Group *g;
76034e04225SDavid du Colombier SunAuthUnix au;
76134e04225SDavid du Colombier
76234e04225SDavid du Colombier m = emalloc(sizeof(Map));
76334e04225SDavid du Colombier
76434e04225SDavid du Colombier if((b = Bopen(passwd, OREAD)) == nil){
76534e04225SDavid du Colombier free(m);
76634e04225SDavid du Colombier return nil;
76734e04225SDavid du Colombier }
76834e04225SDavid du Colombier line = 0;
76934e04225SDavid du Colombier for(; (s = Brdstr(b, '\n', 1)) != nil; free(s)){
77034e04225SDavid du Colombier line++;
77134e04225SDavid du Colombier if(s[0] == '#')
77234e04225SDavid du Colombier continue;
77334e04225SDavid du Colombier nf = getfields(s, f, nelem(f), 0, ":");
77434e04225SDavid du Colombier if(nf < 4)
77534e04225SDavid du Colombier continue;
77634e04225SDavid du Colombier name = f[0];
77734e04225SDavid du Colombier uid = strtol(f[2], &p, 10);
77834e04225SDavid du Colombier if(f[2][0] == 0 || *p != 0){
77934e04225SDavid du Colombier fprint(2, "%s:%d: non-numeric id in third field\n", passwd, line);
78034e04225SDavid du Colombier continue;
78134e04225SDavid du Colombier }
78234e04225SDavid du Colombier gid = strtol(f[3], &p, 10);
78334e04225SDavid du Colombier if(f[3][0] == 0 || *p != 0){
78434e04225SDavid du Colombier fprint(2, "%s:%d: non-numeric id in fourth field\n", passwd, line);
78534e04225SDavid du Colombier continue;
78634e04225SDavid du Colombier }
78734e04225SDavid du Colombier if(m->nuser%32 == 0)
78834e04225SDavid du Colombier m->user = erealloc(m->user, (m->nuser+32)*sizeof(m->user[0]));
78934e04225SDavid du Colombier u = &m->user[m->nuser++];
79034e04225SDavid du Colombier u->name = estrdup9p(name);
79134e04225SDavid du Colombier u->uid = uid;
79234e04225SDavid du Colombier u->gid = gid;
79334e04225SDavid du Colombier u->ng = 0;
79434e04225SDavid du Colombier u->auth = 0;
79534e04225SDavid du Colombier u->nauth = 0;
79634e04225SDavid du Colombier }
79734e04225SDavid du Colombier Bterm(b);
79834e04225SDavid du Colombier m->ubyname = emalloc(m->nuser*sizeof(User*));
79934e04225SDavid du Colombier m->ubyid = emalloc(m->nuser*sizeof(User*));
80034e04225SDavid du Colombier for(i=0; i<m->nuser; i++){
80134e04225SDavid du Colombier m->ubyname[i] = &m->user[i];
80234e04225SDavid du Colombier m->ubyid[i] = &m->user[i];
80334e04225SDavid du Colombier }
80434e04225SDavid du Colombier qsort(m->ubyname, m->nuser, sizeof(m->ubyname[0]), namecmp);
80534e04225SDavid du Colombier qsort(m->ubyid, m->nuser, sizeof(m->ubyid[0]), idcmp);
80634e04225SDavid du Colombier
80734e04225SDavid du Colombier if((b = Bopen(group, OREAD)) == nil){
80834e04225SDavid du Colombier closemap(m);
80934e04225SDavid du Colombier return nil;
81034e04225SDavid du Colombier }
81134e04225SDavid du Colombier line = 0;
81234e04225SDavid du Colombier for(; (s = Brdstr(b, '\n', 1)) != nil; free(s)){
81334e04225SDavid du Colombier line++;
81434e04225SDavid du Colombier if(s[0] == '#')
81534e04225SDavid du Colombier continue;
81634e04225SDavid du Colombier nf = getfields(s, f, nelem(f), 0, ":");
81734e04225SDavid du Colombier if(nf < 4)
81834e04225SDavid du Colombier continue;
81934e04225SDavid du Colombier name = f[0];
82034e04225SDavid du Colombier gid = strtol(f[2], &p, 10);
82134e04225SDavid du Colombier if(f[2][0] == 0 || *p != 0){
82234e04225SDavid du Colombier fprint(2, "%s:%d: non-numeric id in third field\n", group, line);
82334e04225SDavid du Colombier continue;
82434e04225SDavid du Colombier }
82534e04225SDavid du Colombier if(m->ngroup%32 == 0)
82634e04225SDavid du Colombier m->group = erealloc(m->group, (m->ngroup+32)*sizeof(m->group[0]));
82734e04225SDavid du Colombier g = &m->group[m->ngroup++];
82834e04225SDavid du Colombier g->name = estrdup9p(name);
82934e04225SDavid du Colombier g->gid = gid;
83034e04225SDavid du Colombier
83134e04225SDavid du Colombier for(p=f[3]; *p; p=nextp){
83234e04225SDavid du Colombier if((nextp = strchr(p, ',')) != nil)
83334e04225SDavid du Colombier *nextp++ = 0;
83434e04225SDavid du Colombier else
83534e04225SDavid du Colombier nextp = p+strlen(p);
83634e04225SDavid du Colombier u = finduser(m->ubyname, m->nuser, p);
83734e04225SDavid du Colombier if(u == nil){
83834e04225SDavid du Colombier if(verbose)
83934e04225SDavid du Colombier fprint(2, "%s:%d: unknown user %s\n", group, line, p);
84034e04225SDavid du Colombier continue;
84134e04225SDavid du Colombier }
84234e04225SDavid du Colombier if(u->ng >= nelem(u->g)){
84334e04225SDavid du Colombier fprint(2, "%s:%d: user %s is in too many groups; ignoring %s\n", group, line, p, name);
84434e04225SDavid du Colombier continue;
84534e04225SDavid du Colombier }
84634e04225SDavid du Colombier u->g[u->ng++] = gid;
84734e04225SDavid du Colombier }
84834e04225SDavid du Colombier }
84934e04225SDavid du Colombier Bterm(b);
85034e04225SDavid du Colombier m->gbyname = emalloc(m->ngroup*sizeof(Group*));
85134e04225SDavid du Colombier m->gbyid = emalloc(m->ngroup*sizeof(Group*));
85234e04225SDavid du Colombier for(i=0; i<m->ngroup; i++){
85334e04225SDavid du Colombier m->gbyname[i] = &m->group[i];
85434e04225SDavid du Colombier m->gbyid[i] = &m->group[i];
85534e04225SDavid du Colombier }
85634e04225SDavid du Colombier qsort(m->gbyname, m->ngroup, sizeof(m->gbyname[0]), namecmp);
85734e04225SDavid du Colombier qsort(m->gbyid, m->ngroup, sizeof(m->gbyid[0]), idcmp);
85834e04225SDavid du Colombier
85934e04225SDavid du Colombier for(i=0; i<m->nuser; i++){
86034e04225SDavid du Colombier au.stamp = 0;
86134e04225SDavid du Colombier au.sysname = sys;
86234e04225SDavid du Colombier au.uid = m->user[i].uid;
86334e04225SDavid du Colombier au.gid = m->user[i].gid;
86434e04225SDavid du Colombier memmove(au.g, m->user[i].g, sizeof au.g);
86534e04225SDavid du Colombier au.ng = m->user[i].ng;
86634e04225SDavid du Colombier n = sunAuthUnixSize(&au);
86734e04225SDavid du Colombier q = emalloc(n);
86834e04225SDavid du Colombier eq = q+n;
86934e04225SDavid du Colombier m->user[i].auth = q;
87034e04225SDavid du Colombier m->user[i].nauth = n;
87134e04225SDavid du Colombier if(sunAuthUnixPack(q, eq, &q, &au) < 0 || q != eq){
87234e04225SDavid du Colombier fprint(2, "sunAuthUnixPack failed for %s\n", m->user[i].name);
87334e04225SDavid du Colombier free(m->user[i].auth);
87434e04225SDavid du Colombier m->user[i].auth = 0;
87534e04225SDavid du Colombier m->user[i].nauth = 0;
87634e04225SDavid du Colombier }
87734e04225SDavid du Colombier }
87834e04225SDavid du Colombier
87934e04225SDavid du Colombier return m;
88034e04225SDavid du Colombier }
88134e04225SDavid du Colombier
88234e04225SDavid du Colombier Auth*
mkauth(char * user)88334e04225SDavid du Colombier mkauth(char *user)
88434e04225SDavid du Colombier {
88534e04225SDavid du Colombier Auth *a;
88634e04225SDavid du Colombier uchar *p;
88734e04225SDavid du Colombier int n;
88834e04225SDavid du Colombier SunAuthUnix au;
88934e04225SDavid du Colombier User *u;
89034e04225SDavid du Colombier
89134e04225SDavid du Colombier u = finduser(map->ubyname, map->nuser, user);
89234e04225SDavid du Colombier if(u == nil || u->nauth == 0){
89334e04225SDavid du Colombier /* nobody */
89434e04225SDavid du Colombier au.stamp = 0;
89534e04225SDavid du Colombier au.uid = -1;
89634e04225SDavid du Colombier au.gid = -1;
89734e04225SDavid du Colombier au.ng = 0;
89834e04225SDavid du Colombier au.sysname = sys;
89934e04225SDavid du Colombier n = sunAuthUnixSize(&au);
90034e04225SDavid du Colombier a = emalloc(sizeof(Auth)+n);
90134e04225SDavid du Colombier a->data = (uchar*)&a[1];
90234e04225SDavid du Colombier a->ndata = n;
90334e04225SDavid du Colombier if(sunAuthUnixPack(a->data, a->data+a->ndata, &p, &au) < 0
90434e04225SDavid du Colombier || p != a->data+a->ndata){
90534e04225SDavid du Colombier free(a);
90634e04225SDavid du Colombier return nil;
90734e04225SDavid du Colombier }
90834e04225SDavid du Colombier a->ref = 1;
90934e04225SDavid du Colombier if(verbose)print("creds for %s: %.*H\n", user, a->ndata, a->data);
91034e04225SDavid du Colombier return a;
91134e04225SDavid du Colombier }
91234e04225SDavid du Colombier
91334e04225SDavid du Colombier a = emalloc(sizeof(Auth)+u->nauth);
91434e04225SDavid du Colombier a->data = (uchar*)&a[1];
91534e04225SDavid du Colombier a->ndata = u->nauth;
91634e04225SDavid du Colombier memmove(a->data, u->auth, a->ndata);
91734e04225SDavid du Colombier a->ref = 1;
91834e04225SDavid du Colombier if(verbose)print("creds for %s: %.*H\n", user, a->ndata, a->data);
91934e04225SDavid du Colombier return a;
92034e04225SDavid du Colombier }
92134e04225SDavid du Colombier
92234e04225SDavid du Colombier void
freeauth(Auth * a)92334e04225SDavid du Colombier freeauth(Auth *a)
92434e04225SDavid du Colombier {
92534e04225SDavid du Colombier if(--a->ref > 0)
92634e04225SDavid du Colombier return;
92734e04225SDavid du Colombier free(a);
92834e04225SDavid du Colombier }
92934e04225SDavid du Colombier
93034e04225SDavid du Colombier /*
93134e04225SDavid du Colombier * 9P server
93234e04225SDavid du Colombier */
93334e04225SDavid du Colombier void
responderrstr(Req * r)93434e04225SDavid du Colombier responderrstr(Req *r)
93534e04225SDavid du Colombier {
93634e04225SDavid du Colombier char e[ERRMAX];
93734e04225SDavid du Colombier
93834e04225SDavid du Colombier rerrstr(e, sizeof e);
93934e04225SDavid du Colombier respond(r, e);
94034e04225SDavid du Colombier }
94134e04225SDavid du Colombier
94234e04225SDavid du Colombier void
fsdestroyfid(Fid * fid)94334e04225SDavid du Colombier fsdestroyfid(Fid *fid)
94434e04225SDavid du Colombier {
94534e04225SDavid du Colombier FidAux *aux;
94634e04225SDavid du Colombier
94734e04225SDavid du Colombier aux = fid->aux;
94834e04225SDavid du Colombier if(aux == nil)
94934e04225SDavid du Colombier return;
95034e04225SDavid du Colombier freeauth(aux->auth);
95134e04225SDavid du Colombier free(aux->name);
95234e04225SDavid du Colombier free(aux);
95334e04225SDavid du Colombier }
95434e04225SDavid du Colombier
95534e04225SDavid du Colombier void
attrToQid(Nfs3Attr * attr,Qid * qid)95634e04225SDavid du Colombier attrToQid(Nfs3Attr *attr, Qid *qid)
95734e04225SDavid du Colombier {
95834e04225SDavid du Colombier qid->path = attr->fileid;
95934e04225SDavid du Colombier qid->vers = attr->mtime.sec;
96034e04225SDavid du Colombier qid->type = 0;
96134e04225SDavid du Colombier if(attr->type == Nfs3FileDir)
96234e04225SDavid du Colombier qid->type |= QTDIR;
96334e04225SDavid du Colombier }
96434e04225SDavid du Colombier
96534e04225SDavid du Colombier void
attrToDir(Nfs3Attr * attr,Dir * d)96634e04225SDavid du Colombier attrToDir(Nfs3Attr *attr, Dir *d)
96734e04225SDavid du Colombier {
96834e04225SDavid du Colombier d->mode = attr->mode & 0777;
96934e04225SDavid du Colombier if(attr->type == Nfs3FileDir)
97034e04225SDavid du Colombier d->mode |= DMDIR;
97134e04225SDavid du Colombier d->uid = uidtostr(attr->uid);
97234e04225SDavid du Colombier d->gid = gidtostr(attr->gid);
97334e04225SDavid du Colombier d->length = attr->size;
97434e04225SDavid du Colombier attrToQid(attr, &d->qid);
97534e04225SDavid du Colombier d->mtime = attr->mtime.sec;
97634e04225SDavid du Colombier d->atime = attr->atime.sec;
97734e04225SDavid du Colombier d->muid = nil;
97834e04225SDavid du Colombier }
97934e04225SDavid du Colombier
98034e04225SDavid du Colombier void
fsattach(Req * r)98134e04225SDavid du Colombier fsattach(Req *r)
98234e04225SDavid du Colombier {
98334e04225SDavid du Colombier char *path;
98434e04225SDavid du Colombier Auth *auth;
98534e04225SDavid du Colombier FidAux *aux;
98634e04225SDavid du Colombier Nfs3Attr attr;
98734e04225SDavid du Colombier Nfs3Handle h;
98834e04225SDavid du Colombier
98934e04225SDavid du Colombier path = r->ifcall.aname;
99034e04225SDavid du Colombier if(path==nil || path[0]==0)
99134e04225SDavid du Colombier path = defaultpath;
99234e04225SDavid du Colombier
99334e04225SDavid du Colombier auth = mkauth(r->ifcall.uname);
99434e04225SDavid du Colombier
99534e04225SDavid du Colombier if(mountMnt(auth, r->tag, path, &h) < 0
99634e04225SDavid du Colombier || nfsGetattr(auth, r->tag, &h, &attr) < 0){
99734e04225SDavid du Colombier freeauth(auth);
99834e04225SDavid du Colombier responderrstr(r);
99934e04225SDavid du Colombier return;
100034e04225SDavid du Colombier }
100134e04225SDavid du Colombier
100234e04225SDavid du Colombier aux = emalloc(sizeof(FidAux));
100334e04225SDavid du Colombier aux->auth = auth;
100434e04225SDavid du Colombier aux->handle = h;
100534e04225SDavid du Colombier aux->cookie = 0;
100634e04225SDavid du Colombier aux->name = nil;
100734e04225SDavid du Colombier memset(&aux->parent, 0, sizeof aux->parent);
100834e04225SDavid du Colombier r->fid->aux = aux;
100934e04225SDavid du Colombier attrToQid(&attr, &r->fid->qid);
101034e04225SDavid du Colombier r->ofcall.qid = r->fid->qid;
101134e04225SDavid du Colombier respond(r, nil);
101234e04225SDavid du Colombier }
101334e04225SDavid du Colombier
101434e04225SDavid du Colombier void
fsopen(Req * r)101534e04225SDavid du Colombier fsopen(Req *r)
101634e04225SDavid du Colombier {
101734e04225SDavid du Colombier FidAux *aux;
101834e04225SDavid du Colombier Nfs3Attr attr;
10192b5f567bSDavid du Colombier Nfs3SetAttr sa;
102034e04225SDavid du Colombier u1int have;
102134e04225SDavid du Colombier ulong a, b;
102234e04225SDavid du Colombier
102334e04225SDavid du Colombier aux = r->fid->aux;
102434e04225SDavid du Colombier a = 0;
102534e04225SDavid du Colombier switch(r->ifcall.mode&OMASK){
102634e04225SDavid du Colombier case OREAD:
10272b5f567bSDavid du Colombier a = 0x0001;
102834e04225SDavid du Colombier break;
102934e04225SDavid du Colombier case OWRITE:
10302b5f567bSDavid du Colombier a = 0x0004;
103134e04225SDavid du Colombier break;
103234e04225SDavid du Colombier case ORDWR:
10332b5f567bSDavid du Colombier a = 0x0001|0x0004;
103434e04225SDavid du Colombier break;
103534e04225SDavid du Colombier case OEXEC:
103634e04225SDavid du Colombier a = 0x20;
103734e04225SDavid du Colombier break;
103834e04225SDavid du Colombier }
103934e04225SDavid du Colombier if(r->ifcall.mode&OTRUNC)
10402b5f567bSDavid du Colombier a |= 0x0004;
104134e04225SDavid du Colombier
104234e04225SDavid du Colombier if(nfsAccess(aux->auth, r->tag, &aux->handle, a, &b, &have, &attr) < 0
104334e04225SDavid du Colombier || (!have && nfsGetattr(aux->auth, r->tag, &aux->handle, &attr) < 0)){
10442b5f567bSDavid du Colombier Error:
104534e04225SDavid du Colombier responderrstr(r);
104634e04225SDavid du Colombier return;
104734e04225SDavid du Colombier }
1048*f314cdf7SDavid du Colombier if(a != b){
1049*f314cdf7SDavid du Colombier respond(r, "permission denied");
1050*f314cdf7SDavid du Colombier return;
1051*f314cdf7SDavid du Colombier }
10522b5f567bSDavid du Colombier if(r->ifcall.mode&OTRUNC){
10532b5f567bSDavid du Colombier memset(&sa, 0, sizeof sa);
10542b5f567bSDavid du Colombier sa.setSize = 1;
10552b5f567bSDavid du Colombier if(nfsSetattr(aux->auth, r->tag, &aux->handle, &sa) < 0)
10562b5f567bSDavid du Colombier goto Error;
10572b5f567bSDavid du Colombier }
105834e04225SDavid du Colombier attrToQid(&attr, &r->fid->qid);
105934e04225SDavid du Colombier r->ofcall.qid = r->fid->qid;
106034e04225SDavid du Colombier respond(r, nil);
106134e04225SDavid du Colombier }
106234e04225SDavid du Colombier
106334e04225SDavid du Colombier void
fscreate(Req * r)106434e04225SDavid du Colombier fscreate(Req *r)
106534e04225SDavid du Colombier {
106634e04225SDavid du Colombier FidAux *aux;
106734e04225SDavid du Colombier u1int have;
106834e04225SDavid du Colombier Nfs3Attr attr;
106934e04225SDavid du Colombier Nfs3Handle h;
107034e04225SDavid du Colombier ulong mode;
107134e04225SDavid du Colombier uint gid;
107234e04225SDavid du Colombier int (*mk)(Auth*, ulong, Nfs3Handle*, char*, Nfs3Handle*, ulong, uint, u1int*, Nfs3Attr*);
107334e04225SDavid du Colombier
107434e04225SDavid du Colombier aux = r->fid->aux;
107534e04225SDavid du Colombier
107634e04225SDavid du Colombier /*
107734e04225SDavid du Colombier * Plan 9 has no umask, so let's use the
107834e04225SDavid du Colombier * parent directory bits like Plan 9 does.
107934e04225SDavid du Colombier * What the heck, let's inherit the group too.
108034e04225SDavid du Colombier * (Unix will let us set the group to anything
108134e04225SDavid du Colombier * since we're the owner!)
108234e04225SDavid du Colombier */
108334e04225SDavid du Colombier if(nfsGetattr(aux->auth, r->tag, &aux->handle, &attr) < 0){
108434e04225SDavid du Colombier responderrstr(r);
108534e04225SDavid du Colombier return;
108634e04225SDavid du Colombier }
108734e04225SDavid du Colombier mode = r->ifcall.perm&0777;
108834e04225SDavid du Colombier if(r->ifcall.perm&DMDIR)
108934e04225SDavid du Colombier mode &= (attr.mode&0666) | ~0666;
109034e04225SDavid du Colombier else
109134e04225SDavid du Colombier mode &= (attr.mode&0777) | ~0777;
109234e04225SDavid du Colombier gid = attr.gid;
109334e04225SDavid du Colombier
109434e04225SDavid du Colombier if(r->ifcall.perm&DMDIR)
109534e04225SDavid du Colombier mk = nfsMkdir;
109634e04225SDavid du Colombier else
109734e04225SDavid du Colombier mk = nfsCreate;
109834e04225SDavid du Colombier
109934e04225SDavid du Colombier if((*mk)(aux->auth, r->tag, &aux->handle, r->ifcall.name, &h, mode, gid, &have, &attr) < 0
110034e04225SDavid du Colombier || (!have && nfsGetattr(aux->auth, r->tag, &h, &attr) < 0)){
110134e04225SDavid du Colombier responderrstr(r);
110234e04225SDavid du Colombier return;
110334e04225SDavid du Colombier }
110434e04225SDavid du Colombier attrToQid(&attr, &r->fid->qid);
110534e04225SDavid du Colombier aux->parent = aux->handle;
110634e04225SDavid du Colombier aux->handle = h;
110734e04225SDavid du Colombier free(aux->name);
110834e04225SDavid du Colombier aux->name = estrdup9p(r->ifcall.name);
110934e04225SDavid du Colombier r->ofcall.qid = r->fid->qid;
111034e04225SDavid du Colombier respond(r, nil);
111134e04225SDavid du Colombier }
111234e04225SDavid du Colombier
111334e04225SDavid du Colombier void
fsreaddir(Req * r)111434e04225SDavid du Colombier fsreaddir(Req *r)
111534e04225SDavid du Colombier {
111634e04225SDavid du Colombier FidAux *aux;
111734e04225SDavid du Colombier uchar *p, *freeme, *ep, *p9, *ep9;
1118fb7f0c93SDavid du Colombier char *s;
111934e04225SDavid du Colombier uint count;
112034e04225SDavid du Colombier int n, (*unpack)(uchar*, uchar*, uchar**, Nfs3Entry*);
112134e04225SDavid du Colombier Nfs3Entry e;
112234e04225SDavid du Colombier u64int cookie;
112334e04225SDavid du Colombier Dir d;
112434e04225SDavid du Colombier
112534e04225SDavid du Colombier aux = r->fid->aux;
112634e04225SDavid du Colombier /*
112734e04225SDavid du Colombier * r->ifcall.count seems a reasonable estimate to
112834e04225SDavid du Colombier * how much NFS entry data we want. is it?
112934e04225SDavid du Colombier */
113034e04225SDavid du Colombier if(r->ifcall.offset)
113134e04225SDavid du Colombier cookie = aux->cookie;
113234e04225SDavid du Colombier else
113334e04225SDavid du Colombier cookie = 0;
113434e04225SDavid du Colombier if(nfsReadDir(aux->auth, r->tag, &aux->handle, r->ifcall.count, cookie,
113534e04225SDavid du Colombier &p, &count, &unpack, &freeme) < 0){
113634e04225SDavid du Colombier responderrstr(r);
113734e04225SDavid du Colombier return;
113834e04225SDavid du Colombier }
113934e04225SDavid du Colombier ep = p+count;
114034e04225SDavid du Colombier
114134e04225SDavid du Colombier p9 = (uchar*)r->ofcall.data;
114234e04225SDavid du Colombier ep9 = p9+r->ifcall.count;
114334e04225SDavid du Colombier
114434e04225SDavid du Colombier /*
114534e04225SDavid du Colombier * BUG: Issue all of the stat requests in parallel.
114634e04225SDavid du Colombier */
114734e04225SDavid du Colombier while(p < ep && p9 < ep9){
114834e04225SDavid du Colombier if((*unpack)(p, ep, &p, &e) < 0)
114934e04225SDavid du Colombier break;
115034e04225SDavid du Colombier aux->cookie = e.cookie;
115134e04225SDavid du Colombier if(strcmp(e.name, ".") == 0 || strcmp(e.name, "..") == 0)
115234e04225SDavid du Colombier continue;
1153fb7f0c93SDavid du Colombier for(s=e.name; (uchar)*s >= ' '; s++)
1154fb7f0c93SDavid du Colombier ;
1155fb7f0c93SDavid du Colombier if(*s != 0) /* bad character in name */
1156fb7f0c93SDavid du Colombier continue;
115734e04225SDavid du Colombier if(!e.haveAttr && !e.haveHandle)
115834e04225SDavid du Colombier if(nfsLookup(aux->auth, r->tag, &aux->handle, e.name, &e.handle, &e.haveAttr, &e.attr) < 0)
115934e04225SDavid du Colombier continue;
116034e04225SDavid du Colombier if(!e.haveAttr)
116134e04225SDavid du Colombier if(nfsGetattr(aux->auth, r->tag, &e.handle, &e.attr) < 0)
116234e04225SDavid du Colombier continue;
116334e04225SDavid du Colombier memset(&d, 0, sizeof d);
116434e04225SDavid du Colombier attrToDir(&e.attr, &d);
116534e04225SDavid du Colombier d.name = e.name;
116634e04225SDavid du Colombier if((n = convD2M(&d, p9, ep9-p9)) <= BIT16SZ)
116734e04225SDavid du Colombier break;
116834e04225SDavid du Colombier p9 += n;
116934e04225SDavid du Colombier }
117034e04225SDavid du Colombier free(freeme);
117134e04225SDavid du Colombier r->ofcall.count = p9 - (uchar*)r->ofcall.data;
117234e04225SDavid du Colombier respond(r, nil);
117334e04225SDavid du Colombier }
117434e04225SDavid du Colombier
117534e04225SDavid du Colombier void
fsread(Req * r)117634e04225SDavid du Colombier fsread(Req *r)
117734e04225SDavid du Colombier {
117834e04225SDavid du Colombier uchar *p, *freeme;
117934e04225SDavid du Colombier uint count;
118034e04225SDavid du Colombier FidAux *aux;
118134e04225SDavid du Colombier
118234e04225SDavid du Colombier if(r->fid->qid.type&QTDIR){
118334e04225SDavid du Colombier fsreaddir(r);
118434e04225SDavid du Colombier return;
118534e04225SDavid du Colombier }
118634e04225SDavid du Colombier
118734e04225SDavid du Colombier aux = r->fid->aux;
118834e04225SDavid du Colombier if(nfsRead(aux->auth, r->tag, &aux->handle, r->ifcall.count, r->ifcall.offset, &p, &count, &freeme) < 0){
118934e04225SDavid du Colombier responderrstr(r);
119034e04225SDavid du Colombier return;
119134e04225SDavid du Colombier }
119234e04225SDavid du Colombier r->ofcall.data = (char*)p;
119334e04225SDavid du Colombier r->ofcall.count = count;
119434e04225SDavid du Colombier respond(r, nil);
119534e04225SDavid du Colombier free(freeme);
119634e04225SDavid du Colombier }
119734e04225SDavid du Colombier
119834e04225SDavid du Colombier void
fswrite(Req * r)119934e04225SDavid du Colombier fswrite(Req *r)
120034e04225SDavid du Colombier {
120134e04225SDavid du Colombier uint count;
120234e04225SDavid du Colombier FidAux *aux;
120334e04225SDavid du Colombier
120434e04225SDavid du Colombier aux = r->fid->aux;
120534e04225SDavid du Colombier if(nfsWrite(aux->auth, r->tag, &aux->handle, (uchar*)r->ifcall.data, r->ifcall.count, r->ifcall.offset, &count) < 0){
120634e04225SDavid du Colombier responderrstr(r);
120734e04225SDavid du Colombier return;
120834e04225SDavid du Colombier }
120934e04225SDavid du Colombier r->ofcall.count = count;
121034e04225SDavid du Colombier respond(r, nil);
121134e04225SDavid du Colombier }
121234e04225SDavid du Colombier
121334e04225SDavid du Colombier void
fsremove(Req * r)121434e04225SDavid du Colombier fsremove(Req *r)
121534e04225SDavid du Colombier {
121634e04225SDavid du Colombier int n;
121734e04225SDavid du Colombier FidAux *aux;
121834e04225SDavid du Colombier
121934e04225SDavid du Colombier aux = r->fid->aux;
122034e04225SDavid du Colombier if(aux->name == nil){
122134e04225SDavid du Colombier respond(r, "nfs3client botch -- don't know parent handle in remove");
122234e04225SDavid du Colombier return;
122334e04225SDavid du Colombier }
122434e04225SDavid du Colombier if(r->fid->qid.type&QTDIR)
122534e04225SDavid du Colombier n = nfsRmdir(aux->auth, r->tag, &aux->parent, aux->name);
122634e04225SDavid du Colombier else
122734e04225SDavid du Colombier n = nfsRemove(aux->auth, r->tag, &aux->parent, aux->name);
122834e04225SDavid du Colombier if(n < 0){
122934e04225SDavid du Colombier responderrstr(r);
123034e04225SDavid du Colombier return;
123134e04225SDavid du Colombier }
123234e04225SDavid du Colombier respond(r, nil);
123334e04225SDavid du Colombier }
123434e04225SDavid du Colombier
123534e04225SDavid du Colombier void
fsstat(Req * r)123634e04225SDavid du Colombier fsstat(Req *r)
123734e04225SDavid du Colombier {
123834e04225SDavid du Colombier FidAux *aux;
123934e04225SDavid du Colombier Nfs3Attr attr;
124034e04225SDavid du Colombier
124134e04225SDavid du Colombier aux = r->fid->aux;
124234e04225SDavid du Colombier if(nfsGetattr(aux->auth, r->tag, &aux->handle, &attr) < 0){
124334e04225SDavid du Colombier responderrstr(r);
124434e04225SDavid du Colombier return;
124534e04225SDavid du Colombier }
124634e04225SDavid du Colombier memset(&r->d, 0, sizeof r->d);
124734e04225SDavid du Colombier attrToDir(&attr, &r->d);
124834e04225SDavid du Colombier r->d.name = estrdup9p(aux->name ? aux->name : "???");
124934e04225SDavid du Colombier respond(r, nil);
125034e04225SDavid du Colombier }
125134e04225SDavid du Colombier
125234e04225SDavid du Colombier void
fswstat(Req * r)125334e04225SDavid du Colombier fswstat(Req *r)
125434e04225SDavid du Colombier {
125534e04225SDavid du Colombier int op, sync;
125634e04225SDavid du Colombier FidAux *aux;
125734e04225SDavid du Colombier Nfs3SetAttr attr;
125834e04225SDavid du Colombier
1259fb7f0c93SDavid du Colombier memset(&attr, 0, sizeof attr);
126034e04225SDavid du Colombier aux = r->fid->aux;
126134e04225SDavid du Colombier
126234e04225SDavid du Colombier /* Fill out stat first to catch errors */
126334e04225SDavid du Colombier op = 0;
126434e04225SDavid du Colombier sync = 1;
126534e04225SDavid du Colombier if(~r->d.mode){
126634e04225SDavid du Colombier if(r->d.mode&(DMAPPEND|DMEXCL)){
126734e04225SDavid du Colombier respond(r, "wstat -- DMAPPEND and DMEXCL bits not supported");
126834e04225SDavid du Colombier return;
126934e04225SDavid du Colombier }
127034e04225SDavid du Colombier op = 1;
127134e04225SDavid du Colombier sync = 0;
127234e04225SDavid du Colombier attr.setMode = 1;
127334e04225SDavid du Colombier attr.mode = r->d.mode & 0777;
127434e04225SDavid du Colombier }
127534e04225SDavid du Colombier if(r->d.uid && r->d.uid[0]){
127634e04225SDavid du Colombier attr.setUid = 1;
127734e04225SDavid du Colombier if(strtouid(r->d.uid, &attr.uid) < 0){
127834e04225SDavid du Colombier respond(r, "wstat -- unknown uid");
127934e04225SDavid du Colombier return;
128034e04225SDavid du Colombier }
128134e04225SDavid du Colombier op = 1;
128234e04225SDavid du Colombier sync = 0;
128334e04225SDavid du Colombier }
128434e04225SDavid du Colombier if(r->d.gid && r->d.gid[0]){
128534e04225SDavid du Colombier attr.setGid = 1;
128634e04225SDavid du Colombier if(strtogid(r->d.gid, &attr.gid) < 0){
128734e04225SDavid du Colombier respond(r, "wstat -- unknown gid");
128834e04225SDavid du Colombier return;
128934e04225SDavid du Colombier }
129034e04225SDavid du Colombier op = 1;
129134e04225SDavid du Colombier sync = 0;
129234e04225SDavid du Colombier }
129334e04225SDavid du Colombier if(~r->d.length){
129434e04225SDavid du Colombier attr.setSize = 1;
129534e04225SDavid du Colombier attr.size = r->d.length;
1296fb7f0c93SDavid du Colombier op = 1;
1297fb7f0c93SDavid du Colombier sync = 0;
129834e04225SDavid du Colombier }
129934e04225SDavid du Colombier if(~r->d.mtime){
1300fb7f0c93SDavid du Colombier attr.setMtime = Nfs3SetTimeClient;
130134e04225SDavid du Colombier attr.mtime.sec = r->d.mtime;
1302fb7f0c93SDavid du Colombier op = 1;
1303fb7f0c93SDavid du Colombier sync = 0;
1304fb7f0c93SDavid du Colombier }
1305fb7f0c93SDavid du Colombier if(~r->d.atime){
1306fb7f0c93SDavid du Colombier attr.setAtime = Nfs3SetTimeClient;
1307fb7f0c93SDavid du Colombier attr.atime.sec = r->d.atime;
1308fb7f0c93SDavid du Colombier op = 1;
1309fb7f0c93SDavid du Colombier sync = 0;
131034e04225SDavid du Colombier }
131134e04225SDavid du Colombier
131234e04225SDavid du Colombier /* Try rename first because it's more likely to fail (?) */
131334e04225SDavid du Colombier if(r->d.name && r->d.name[0]){
131434e04225SDavid du Colombier if(aux->name == nil){
131534e04225SDavid du Colombier respond(r, "nfsclient botch -- don't know parent handle in rename");
131634e04225SDavid du Colombier return;
131734e04225SDavid du Colombier }
131834e04225SDavid du Colombier if(nfsRename(aux->auth, r->tag, &aux->parent, aux->name, &aux->parent, r->d.name) < 0){
131934e04225SDavid du Colombier responderrstr(r);
132034e04225SDavid du Colombier return;
132134e04225SDavid du Colombier }
132234e04225SDavid du Colombier free(aux->name);
132334e04225SDavid du Colombier aux->name = estrdup9p(r->d.name);
132434e04225SDavid du Colombier sync = 0;
132534e04225SDavid du Colombier }
132634e04225SDavid du Colombier
132734e04225SDavid du Colombier /*
132834e04225SDavid du Colombier * Now we have a problem. The rename succeeded
132934e04225SDavid du Colombier * but the setattr could fail. Sic transit atomicity.
133034e04225SDavid du Colombier */
133134e04225SDavid du Colombier if(op){
133234e04225SDavid du Colombier if(nfsSetattr(aux->auth, r->tag, &aux->handle, &attr) < 0){
133334e04225SDavid du Colombier responderrstr(r);
133434e04225SDavid du Colombier return;
133534e04225SDavid du Colombier }
133634e04225SDavid du Colombier }
133734e04225SDavid du Colombier
133834e04225SDavid du Colombier if(sync){
133934e04225SDavid du Colombier /* NFS commit */
134034e04225SDavid du Colombier if(nfsCommit(aux->auth, r->tag, &aux->handle) < 0){
134134e04225SDavid du Colombier responderrstr(r);
134234e04225SDavid du Colombier return;
134334e04225SDavid du Colombier }
134434e04225SDavid du Colombier }
134534e04225SDavid du Colombier
134634e04225SDavid du Colombier respond(r, nil);
134734e04225SDavid du Colombier }
134834e04225SDavid du Colombier
134934e04225SDavid du Colombier char*
fswalk1(Fid * fid,char * name,void * v)135034e04225SDavid du Colombier fswalk1(Fid *fid, char *name, void *v)
135134e04225SDavid du Colombier {
135234e04225SDavid du Colombier u1int have;
135334e04225SDavid du Colombier ulong tag;
135434e04225SDavid du Colombier FidAux *aux;
135534e04225SDavid du Colombier Nfs3Attr attr;
135634e04225SDavid du Colombier Nfs3Handle h;
135734e04225SDavid du Colombier
135834e04225SDavid du Colombier tag = *(ulong*)v;
135934e04225SDavid du Colombier aux = fid->aux;
136034e04225SDavid du Colombier
136134e04225SDavid du Colombier if(nfsLookup(aux->auth, tag, &aux->handle, name, &h, &have, &attr) < 0
136234e04225SDavid du Colombier || (!have && nfsGetattr(aux->auth, tag, &h, &attr) < 0)){
136334e04225SDavid du Colombier rerrstr(aux->err, sizeof aux->err);
136434e04225SDavid du Colombier return aux->err;
136534e04225SDavid du Colombier }
136634e04225SDavid du Colombier
136734e04225SDavid du Colombier aux->parent = aux->handle;
136834e04225SDavid du Colombier aux->handle = h;
136934e04225SDavid du Colombier free(aux->name);
137034e04225SDavid du Colombier if(strcmp(name, "..") == 0)
137134e04225SDavid du Colombier aux->name = nil;
137234e04225SDavid du Colombier else
137334e04225SDavid du Colombier aux->name = estrdup9p(name);
137434e04225SDavid du Colombier attrToQid(&attr, &fid->qid);
137534e04225SDavid du Colombier return nil;
137634e04225SDavid du Colombier }
137734e04225SDavid du Colombier
137834e04225SDavid du Colombier char*
fsclone(Fid * fid,Fid * newfid,void *)137934e04225SDavid du Colombier fsclone(Fid *fid, Fid *newfid, void*)
138034e04225SDavid du Colombier {
138134e04225SDavid du Colombier FidAux *a, *na;
138234e04225SDavid du Colombier
138334e04225SDavid du Colombier a = fid->aux;
138434e04225SDavid du Colombier na = emalloc9p(sizeof(FidAux));
138534e04225SDavid du Colombier *na = *a;
138634e04225SDavid du Colombier if(na->name)
138734e04225SDavid du Colombier na->name = estrdup9p(na->name);
138834e04225SDavid du Colombier newfid->aux = na;
138934e04225SDavid du Colombier if(na->auth)
139034e04225SDavid du Colombier na->auth->ref++;
139134e04225SDavid du Colombier return nil;
139234e04225SDavid du Colombier }
139334e04225SDavid du Colombier
139434e04225SDavid du Colombier void
fswalk(Req * r)139534e04225SDavid du Colombier fswalk(Req *r)
139634e04225SDavid du Colombier {
139734e04225SDavid du Colombier walkandclone(r, fswalk1, fsclone, &r->tag);
139834e04225SDavid du Colombier }
139934e04225SDavid du Colombier
140034e04225SDavid du Colombier void
fsflush(Req * r)140134e04225SDavid du Colombier fsflush(Req *r)
140234e04225SDavid du Colombier {
140334e04225SDavid du Colombier Req *or;
140434e04225SDavid du Colombier
140534e04225SDavid du Colombier /*
140634e04225SDavid du Colombier * Send on the flush channel(s).
140734e04225SDavid du Colombier * The library will make sure the response
140834e04225SDavid du Colombier * is delayed as necessary.
140934e04225SDavid du Colombier */
141034e04225SDavid du Colombier or = r->oldreq;
141134e04225SDavid du Colombier if(nfscli)
141234e04225SDavid du Colombier sendul(nfscli->flushchan, (ulong)or->tag);
141334e04225SDavid du Colombier if(mntcli)
141434e04225SDavid du Colombier sendul(mntcli->flushchan, (ulong)or->tag);
141534e04225SDavid du Colombier respond(r, nil);
141634e04225SDavid du Colombier }
141734e04225SDavid du Colombier
141834e04225SDavid du Colombier void
fsdispatch(void * v)141934e04225SDavid du Colombier fsdispatch(void *v)
142034e04225SDavid du Colombier {
142134e04225SDavid du Colombier Req *r;
142234e04225SDavid du Colombier
142334e04225SDavid du Colombier r = v;
142434e04225SDavid du Colombier switch(r->ifcall.type){
142534e04225SDavid du Colombier default: respond(r, "unknown type"); break;
142634e04225SDavid du Colombier case Tattach: fsattach(r); break;
142734e04225SDavid du Colombier case Topen: fsopen(r); break;
142834e04225SDavid du Colombier case Tcreate: fscreate(r); break;
142934e04225SDavid du Colombier case Tread: fsread(r); break;
143034e04225SDavid du Colombier case Twrite: fswrite(r); break;
143134e04225SDavid du Colombier case Tremove: fsremove(r); break;
143234e04225SDavid du Colombier case Tflush: fsflush(r); break;
143334e04225SDavid du Colombier case Tstat: fsstat(r); break;
143434e04225SDavid du Colombier case Twstat: fswstat(r); break;
143534e04225SDavid du Colombier case Twalk: fswalk(r); break;
143634e04225SDavid du Colombier }
143734e04225SDavid du Colombier }
143834e04225SDavid du Colombier
143934e04225SDavid du Colombier void
fsthread(void *)144034e04225SDavid du Colombier fsthread(void*)
144134e04225SDavid du Colombier {
144234e04225SDavid du Colombier Req *r;
144334e04225SDavid du Colombier
144434e04225SDavid du Colombier while((r = recvp(fschan)) != nil)
144534e04225SDavid du Colombier threadcreate(fsdispatch, r, SunStackSize);
144634e04225SDavid du Colombier }
144734e04225SDavid du Colombier
144834e04225SDavid du Colombier void
fssend(Req * r)144934e04225SDavid du Colombier fssend(Req *r)
145034e04225SDavid du Colombier {
145134e04225SDavid du Colombier sendp(fschan, r);
145234e04225SDavid du Colombier }
145334e04225SDavid du Colombier
145434e04225SDavid du Colombier void
fsdie(Srv *)145534e04225SDavid du Colombier fsdie(Srv*)
145634e04225SDavid du Colombier {
145734e04225SDavid du Colombier threadexitsall(nil);
145834e04225SDavid du Colombier }
145934e04225SDavid du Colombier
146034e04225SDavid du Colombier Srv fs =
146134e04225SDavid du Colombier {
146234e04225SDavid du Colombier .destroyfid = fsdestroyfid,
146334e04225SDavid du Colombier .attach= fssend,
146434e04225SDavid du Colombier .open= fssend,
146534e04225SDavid du Colombier .create= fssend,
146634e04225SDavid du Colombier .read= fssend,
146734e04225SDavid du Colombier .write= fssend,
146834e04225SDavid du Colombier .remove= fssend,
146934e04225SDavid du Colombier .flush= fssend,
147034e04225SDavid du Colombier .stat= fssend,
147134e04225SDavid du Colombier .wstat= fssend,
147234e04225SDavid du Colombier .walk= fssend,
147334e04225SDavid du Colombier .end= fsdie
147434e04225SDavid du Colombier };
147534e04225SDavid du Colombier
147634e04225SDavid du Colombier void
usage(void)147734e04225SDavid du Colombier usage(void)
147834e04225SDavid du Colombier {
147934e04225SDavid du Colombier fprint(2, "usage: nfs [-DRv] [-p perm] [-s srvname] [-u passwd group] addr [addr]\n");
148034e04225SDavid du Colombier fprint(2, "\taddr - address of portmapper server\n");
148134e04225SDavid du Colombier fprint(2, "\taddr addr - addresses of mount server and nfs server\n");
148234e04225SDavid du Colombier exits("usage");
148334e04225SDavid du Colombier }
148434e04225SDavid du Colombier
148534e04225SDavid du Colombier char*
netchangeport(char * addr,uint port,char * buf,uint nbuf)148634e04225SDavid du Colombier netchangeport(char *addr, uint port, char *buf, uint nbuf)
148734e04225SDavid du Colombier {
148834e04225SDavid du Colombier char *r;
148934e04225SDavid du Colombier
149034e04225SDavid du Colombier strecpy(buf, buf+nbuf, addr);
149134e04225SDavid du Colombier r = strrchr(buf, '!');
149234e04225SDavid du Colombier if(r == nil)
149334e04225SDavid du Colombier return nil;
149434e04225SDavid du Colombier r++;
149534e04225SDavid du Colombier seprint(r, buf+nbuf, "%ud", port);
149634e04225SDavid du Colombier return buf;
149734e04225SDavid du Colombier }
149834e04225SDavid du Colombier
149934e04225SDavid du Colombier char mbuf[256], nbuf[256];
150034e04225SDavid du Colombier char *mountaddr, *nfsaddr;
150134e04225SDavid du Colombier Channel *csync;
150234e04225SDavid du Colombier int chattyrpc;
150334e04225SDavid du Colombier void dialproc(void*);
150434e04225SDavid du Colombier
150534e04225SDavid du Colombier void
threadmain(int argc,char ** argv)150634e04225SDavid du Colombier threadmain(int argc, char **argv)
150734e04225SDavid du Colombier {
150834e04225SDavid du Colombier char *srvname, *passwd, *group, *addr, *p;
150934e04225SDavid du Colombier SunClient *cli;
151034e04225SDavid du Colombier int proto;
151134e04225SDavid du Colombier uint mport, nport;
151234e04225SDavid du Colombier ulong perm;
151334e04225SDavid du Colombier Dir d;
151434e04225SDavid du Colombier
151534e04225SDavid du Colombier perm = 0600;
151634e04225SDavid du Colombier passwd = nil;
151734e04225SDavid du Colombier group = nil;
151834e04225SDavid du Colombier srvname = nil;
151934e04225SDavid du Colombier sys = sysname();
152034e04225SDavid du Colombier if(sys == nil)
152134e04225SDavid du Colombier sys = "plan9";
152234e04225SDavid du Colombier ARGBEGIN{
152334e04225SDavid du Colombier default:
152434e04225SDavid du Colombier usage();
152534e04225SDavid du Colombier case 'D':
152634e04225SDavid du Colombier chatty9p++;
152734e04225SDavid du Colombier break;
152834e04225SDavid du Colombier case 'R':
152934e04225SDavid du Colombier chattyrpc++;
153034e04225SDavid du Colombier break;
153134e04225SDavid du Colombier case 'p':
153234e04225SDavid du Colombier perm = strtol(EARGF(usage()), &p, 8);
153334e04225SDavid du Colombier if(perm==0 || *p != 0)
153434e04225SDavid du Colombier usage();
153534e04225SDavid du Colombier break;
153634e04225SDavid du Colombier case 's':
153734e04225SDavid du Colombier srvname = EARGF(usage());
153834e04225SDavid du Colombier break;
153934e04225SDavid du Colombier case 'u':
154034e04225SDavid du Colombier passwd = EARGF(usage());
154134e04225SDavid du Colombier group = EARGF(usage());
154234e04225SDavid du Colombier break;
154334e04225SDavid du Colombier case 'v':
154434e04225SDavid du Colombier verbose++;
154534e04225SDavid du Colombier break;
154634e04225SDavid du Colombier }ARGEND
154734e04225SDavid du Colombier
154834e04225SDavid du Colombier if(argc != 1 && argc != 2)
154934e04225SDavid du Colombier usage();
155034e04225SDavid du Colombier
155134e04225SDavid du Colombier if(srvname == nil)
155234e04225SDavid du Colombier srvname = argv[0];
155334e04225SDavid du Colombier
155434e04225SDavid du Colombier fmtinstall('B', sunRpcFmt);
155534e04225SDavid du Colombier fmtinstall('C', sunCallFmt);
155634e04225SDavid du Colombier fmtinstall('H', encodefmt);
155734e04225SDavid du Colombier sunFmtInstall(&portProg);
155834e04225SDavid du Colombier sunFmtInstall(&nfs3Prog);
155934e04225SDavid du Colombier sunFmtInstall(&nfsMount3Prog);
156034e04225SDavid du Colombier
156134e04225SDavid du Colombier if(passwd && (map = readmap(passwd, group)) == nil)
156234e04225SDavid du Colombier fprint(2, "warning: reading %s and %s: %r\n", passwd, group);
156334e04225SDavid du Colombier
156434e04225SDavid du Colombier if(map == nil)
156534e04225SDavid du Colombier map = &emptymap;
156634e04225SDavid du Colombier
156734e04225SDavid du Colombier if(argc == 1){
156834e04225SDavid du Colombier addr = netmkaddr(argv[0], "udp", "portmap");
156934e04225SDavid du Colombier if((cli = sunDial(addr)) == nil)
157034e04225SDavid du Colombier sysfatal("dial %s: %r", addr);
157134e04225SDavid du Colombier cli->chatty = chattyrpc;
157234e04225SDavid du Colombier sunClientProg(cli, &portProg);
157334e04225SDavid du Colombier if(strstr(addr, "udp!"))
157434e04225SDavid du Colombier proto = PortProtoUdp;
157534e04225SDavid du Colombier else
157634e04225SDavid du Colombier proto = PortProtoTcp;
157734e04225SDavid du Colombier if(getport(cli, NfsMount3Program, NfsMount3Version, proto, &mport) < 0)
157834e04225SDavid du Colombier sysfatal("lookup mount program port: %r");
157934e04225SDavid du Colombier if(getport(cli, Nfs3Program, Nfs3Version, proto, &nport) < 0)
158034e04225SDavid du Colombier sysfatal("lookup nfs program port: %r");
158134e04225SDavid du Colombier sunClientClose(cli);
158234e04225SDavid du Colombier mountaddr = netchangeport(addr, mport, mbuf, sizeof mbuf);
158334e04225SDavid du Colombier nfsaddr = netchangeport(addr, nport, nbuf, sizeof nbuf);
158434e04225SDavid du Colombier strcat(mountaddr, "!r");
158534e04225SDavid du Colombier strcat(nfsaddr, "!r");
158634e04225SDavid du Colombier if(verbose)
158734e04225SDavid du Colombier fprint(2, "nfs %s %s\n", mountaddr, nfsaddr);
158834e04225SDavid du Colombier }else{
158934e04225SDavid du Colombier mountaddr = argv[0];
159034e04225SDavid du Colombier nfsaddr = argv[1];
159134e04225SDavid du Colombier }
159234e04225SDavid du Colombier
159334e04225SDavid du Colombier /* have to dial in another proc because it creates threads */
159434e04225SDavid du Colombier csync = chancreate(sizeof(void*), 0);
159534e04225SDavid du Colombier proccreate(dialproc, nil, SunStackSize);
159634e04225SDavid du Colombier recvp(csync);
159734e04225SDavid du Colombier
159834e04225SDavid du Colombier threadpostmountsrv(&fs, srvname, nil, 0);
159934e04225SDavid du Colombier if(perm != 0600){
160034e04225SDavid du Colombier p = smprint("/srv/%s", srvname);
160134e04225SDavid du Colombier if(p){
160234e04225SDavid du Colombier nulldir(&d);
160334e04225SDavid du Colombier d.mode = perm;
160434e04225SDavid du Colombier dirwstat(p, &d);
160534e04225SDavid du Colombier }
160634e04225SDavid du Colombier }
160734e04225SDavid du Colombier threadexits(nil);
160834e04225SDavid du Colombier }
160934e04225SDavid du Colombier
161034e04225SDavid du Colombier void
dialproc(void *)161134e04225SDavid du Colombier dialproc(void*)
161234e04225SDavid du Colombier {
161334e04225SDavid du Colombier rfork(RFNAMEG);
161434e04225SDavid du Colombier rfork(RFNOTEG);
161534e04225SDavid du Colombier if((mntcli = sunDial(mountaddr)) == nil)
161634e04225SDavid du Colombier sysfatal("dial mount program at %s: %r", mountaddr);
161734e04225SDavid du Colombier mntcli->chatty = chattyrpc;
161834e04225SDavid du Colombier sunClientProg(mntcli, &nfsMount3Prog);
161934e04225SDavid du Colombier if(mountNull(0) < 0)
162034e04225SDavid du Colombier sysfatal("execute nop with mnt server at %s: %r", mountaddr);
162134e04225SDavid du Colombier
162234e04225SDavid du Colombier if((nfscli = sunDial(nfsaddr)) == nil)
162334e04225SDavid du Colombier sysfatal("dial nfs program at %s: %r", nfsaddr);
162434e04225SDavid du Colombier nfscli->chatty = chattyrpc;
162534e04225SDavid du Colombier sunClientProg(nfscli, &nfs3Prog);
162634e04225SDavid du Colombier if(nfsNull(0) < 0)
162734e04225SDavid du Colombier sysfatal("execute nop with nfs server at %s: %r", nfsaddr);
162834e04225SDavid du Colombier
162934e04225SDavid du Colombier fschan = chancreate(sizeof(Req*), 0);
163034e04225SDavid du Colombier threadcreate(fsthread, nil, SunStackSize);
163134e04225SDavid du Colombier sendp(csync, 0);
163234e04225SDavid du Colombier }
1633