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 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 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 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 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 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 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 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 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 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 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 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 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 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; 341*6ff5e913SDavid 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 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 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 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 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 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 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 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 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); 55034e04225SDavid du Colombier if(strstr(e, "procedure unavailable")) 55134e04225SDavid du Colombier readplus = -1; 55234e04225SDavid du Colombier } 553*6ff5e913SDavid du Colombier if(readplus == 0) 554*6ff5e913SDavid 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* 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 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* 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* 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* 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 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 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 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 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 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* 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* 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 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 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 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 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 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 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 101534e04225SDavid du Colombier fsopen(Req *r) 101634e04225SDavid du Colombier { 101734e04225SDavid du Colombier FidAux *aux; 101834e04225SDavid du Colombier Nfs3Attr attr; 101934e04225SDavid du Colombier u1int have; 102034e04225SDavid du Colombier ulong a, b; 102134e04225SDavid du Colombier 102234e04225SDavid du Colombier aux = r->fid->aux; 102334e04225SDavid du Colombier a = 0; 102434e04225SDavid du Colombier switch(r->ifcall.mode&OMASK){ 102534e04225SDavid du Colombier case OREAD: 102634e04225SDavid du Colombier a = 1; 102734e04225SDavid du Colombier break; 102834e04225SDavid du Colombier case OWRITE: 102934e04225SDavid du Colombier a = 2; 103034e04225SDavid du Colombier break; 103134e04225SDavid du Colombier case ORDWR: 103234e04225SDavid du Colombier a = 3; 103334e04225SDavid du Colombier break; 103434e04225SDavid du Colombier case OEXEC: 103534e04225SDavid du Colombier a = 0x20; 103634e04225SDavid du Colombier break; 103734e04225SDavid du Colombier } 103834e04225SDavid du Colombier if(r->ifcall.mode&OTRUNC) 103934e04225SDavid du Colombier a = 0x10; 104034e04225SDavid du Colombier 104134e04225SDavid du Colombier if(nfsAccess(aux->auth, r->tag, &aux->handle, a, &b, &have, &attr) < 0 104234e04225SDavid du Colombier || (!have && nfsGetattr(aux->auth, r->tag, &aux->handle, &attr) < 0)){ 104334e04225SDavid du Colombier responderrstr(r); 104434e04225SDavid du Colombier return; 104534e04225SDavid du Colombier } 104634e04225SDavid du Colombier attrToQid(&attr, &r->fid->qid); 104734e04225SDavid du Colombier r->ofcall.qid = r->fid->qid; 104834e04225SDavid du Colombier respond(r, nil); 104934e04225SDavid du Colombier } 105034e04225SDavid du Colombier 105134e04225SDavid du Colombier void 105234e04225SDavid du Colombier fscreate(Req *r) 105334e04225SDavid du Colombier { 105434e04225SDavid du Colombier FidAux *aux; 105534e04225SDavid du Colombier u1int have; 105634e04225SDavid du Colombier Nfs3Attr attr; 105734e04225SDavid du Colombier Nfs3Handle h; 105834e04225SDavid du Colombier ulong mode; 105934e04225SDavid du Colombier uint gid; 106034e04225SDavid du Colombier int (*mk)(Auth*, ulong, Nfs3Handle*, char*, Nfs3Handle*, ulong, uint, u1int*, Nfs3Attr*); 106134e04225SDavid du Colombier 106234e04225SDavid du Colombier aux = r->fid->aux; 106334e04225SDavid du Colombier 106434e04225SDavid du Colombier /* 106534e04225SDavid du Colombier * Plan 9 has no umask, so let's use the 106634e04225SDavid du Colombier * parent directory bits like Plan 9 does. 106734e04225SDavid du Colombier * What the heck, let's inherit the group too. 106834e04225SDavid du Colombier * (Unix will let us set the group to anything 106934e04225SDavid du Colombier * since we're the owner!) 107034e04225SDavid du Colombier */ 107134e04225SDavid du Colombier if(nfsGetattr(aux->auth, r->tag, &aux->handle, &attr) < 0){ 107234e04225SDavid du Colombier responderrstr(r); 107334e04225SDavid du Colombier return; 107434e04225SDavid du Colombier } 107534e04225SDavid du Colombier mode = r->ifcall.perm&0777; 107634e04225SDavid du Colombier if(r->ifcall.perm&DMDIR) 107734e04225SDavid du Colombier mode &= (attr.mode&0666) | ~0666; 107834e04225SDavid du Colombier else 107934e04225SDavid du Colombier mode &= (attr.mode&0777) | ~0777; 108034e04225SDavid du Colombier gid = attr.gid; 108134e04225SDavid du Colombier 108234e04225SDavid du Colombier if(r->ifcall.perm&DMDIR) 108334e04225SDavid du Colombier mk = nfsMkdir; 108434e04225SDavid du Colombier else 108534e04225SDavid du Colombier mk = nfsCreate; 108634e04225SDavid du Colombier 108734e04225SDavid du Colombier if((*mk)(aux->auth, r->tag, &aux->handle, r->ifcall.name, &h, mode, gid, &have, &attr) < 0 108834e04225SDavid du Colombier || (!have && nfsGetattr(aux->auth, r->tag, &h, &attr) < 0)){ 108934e04225SDavid du Colombier responderrstr(r); 109034e04225SDavid du Colombier return; 109134e04225SDavid du Colombier } 109234e04225SDavid du Colombier attrToQid(&attr, &r->fid->qid); 109334e04225SDavid du Colombier aux->parent = aux->handle; 109434e04225SDavid du Colombier aux->handle = h; 109534e04225SDavid du Colombier free(aux->name); 109634e04225SDavid du Colombier aux->name = estrdup9p(r->ifcall.name); 109734e04225SDavid du Colombier r->ofcall.qid = r->fid->qid; 109834e04225SDavid du Colombier respond(r, nil); 109934e04225SDavid du Colombier } 110034e04225SDavid du Colombier 110134e04225SDavid du Colombier void 110234e04225SDavid du Colombier fsreaddir(Req *r) 110334e04225SDavid du Colombier { 110434e04225SDavid du Colombier FidAux *aux; 110534e04225SDavid du Colombier uchar *p, *freeme, *ep, *p9, *ep9; 110634e04225SDavid du Colombier uint count; 110734e04225SDavid du Colombier int n, (*unpack)(uchar*, uchar*, uchar**, Nfs3Entry*); 110834e04225SDavid du Colombier Nfs3Entry e; 110934e04225SDavid du Colombier u64int cookie; 111034e04225SDavid du Colombier Dir d; 111134e04225SDavid du Colombier 111234e04225SDavid du Colombier aux = r->fid->aux; 111334e04225SDavid du Colombier /* 111434e04225SDavid du Colombier * r->ifcall.count seems a reasonable estimate to 111534e04225SDavid du Colombier * how much NFS entry data we want. is it? 111634e04225SDavid du Colombier */ 111734e04225SDavid du Colombier if(r->ifcall.offset) 111834e04225SDavid du Colombier cookie = aux->cookie; 111934e04225SDavid du Colombier else 112034e04225SDavid du Colombier cookie = 0; 112134e04225SDavid du Colombier if(nfsReadDir(aux->auth, r->tag, &aux->handle, r->ifcall.count, cookie, 112234e04225SDavid du Colombier &p, &count, &unpack, &freeme) < 0){ 112334e04225SDavid du Colombier responderrstr(r); 112434e04225SDavid du Colombier return; 112534e04225SDavid du Colombier } 112634e04225SDavid du Colombier ep = p+count; 112734e04225SDavid du Colombier 112834e04225SDavid du Colombier p9 = (uchar*)r->ofcall.data; 112934e04225SDavid du Colombier ep9 = p9+r->ifcall.count; 113034e04225SDavid du Colombier 113134e04225SDavid du Colombier /* 113234e04225SDavid du Colombier * BUG: Issue all of the stat requests in parallel. 113334e04225SDavid du Colombier */ 113434e04225SDavid du Colombier while(p < ep && p9 < ep9){ 113534e04225SDavid du Colombier if((*unpack)(p, ep, &p, &e) < 0) 113634e04225SDavid du Colombier break; 113734e04225SDavid du Colombier aux->cookie = e.cookie; 113834e04225SDavid du Colombier if(strcmp(e.name, ".") == 0 || strcmp(e.name, "..") == 0) 113934e04225SDavid du Colombier continue; 114034e04225SDavid du Colombier if(!e.haveAttr && !e.haveHandle) 114134e04225SDavid du Colombier if(nfsLookup(aux->auth, r->tag, &aux->handle, e.name, &e.handle, &e.haveAttr, &e.attr) < 0) 114234e04225SDavid du Colombier continue; 114334e04225SDavid du Colombier if(!e.haveAttr) 114434e04225SDavid du Colombier if(nfsGetattr(aux->auth, r->tag, &e.handle, &e.attr) < 0) 114534e04225SDavid du Colombier continue; 114634e04225SDavid du Colombier memset(&d, 0, sizeof d); 114734e04225SDavid du Colombier attrToDir(&e.attr, &d); 114834e04225SDavid du Colombier d.name = e.name; 114934e04225SDavid du Colombier if((n = convD2M(&d, p9, ep9-p9)) <= BIT16SZ) 115034e04225SDavid du Colombier break; 115134e04225SDavid du Colombier p9 += n; 115234e04225SDavid du Colombier } 115334e04225SDavid du Colombier free(freeme); 115434e04225SDavid du Colombier r->ofcall.count = p9 - (uchar*)r->ofcall.data; 115534e04225SDavid du Colombier respond(r, nil); 115634e04225SDavid du Colombier } 115734e04225SDavid du Colombier 115834e04225SDavid du Colombier void 115934e04225SDavid du Colombier fsread(Req *r) 116034e04225SDavid du Colombier { 116134e04225SDavid du Colombier uchar *p, *freeme; 116234e04225SDavid du Colombier uint count; 116334e04225SDavid du Colombier FidAux *aux; 116434e04225SDavid du Colombier 116534e04225SDavid du Colombier if(r->fid->qid.type&QTDIR){ 116634e04225SDavid du Colombier fsreaddir(r); 116734e04225SDavid du Colombier return; 116834e04225SDavid du Colombier } 116934e04225SDavid du Colombier 117034e04225SDavid du Colombier aux = r->fid->aux; 117134e04225SDavid du Colombier if(nfsRead(aux->auth, r->tag, &aux->handle, r->ifcall.count, r->ifcall.offset, &p, &count, &freeme) < 0){ 117234e04225SDavid du Colombier responderrstr(r); 117334e04225SDavid du Colombier return; 117434e04225SDavid du Colombier } 117534e04225SDavid du Colombier r->ofcall.data = (char*)p; 117634e04225SDavid du Colombier r->ofcall.count = count; 117734e04225SDavid du Colombier respond(r, nil); 117834e04225SDavid du Colombier free(freeme); 117934e04225SDavid du Colombier } 118034e04225SDavid du Colombier 118134e04225SDavid du Colombier void 118234e04225SDavid du Colombier fswrite(Req *r) 118334e04225SDavid du Colombier { 118434e04225SDavid du Colombier uint count; 118534e04225SDavid du Colombier FidAux *aux; 118634e04225SDavid du Colombier 118734e04225SDavid du Colombier aux = r->fid->aux; 118834e04225SDavid du Colombier if(nfsWrite(aux->auth, r->tag, &aux->handle, (uchar*)r->ifcall.data, r->ifcall.count, r->ifcall.offset, &count) < 0){ 118934e04225SDavid du Colombier responderrstr(r); 119034e04225SDavid du Colombier return; 119134e04225SDavid du Colombier } 119234e04225SDavid du Colombier r->ofcall.count = count; 119334e04225SDavid du Colombier respond(r, nil); 119434e04225SDavid du Colombier } 119534e04225SDavid du Colombier 119634e04225SDavid du Colombier void 119734e04225SDavid du Colombier fsremove(Req *r) 119834e04225SDavid du Colombier { 119934e04225SDavid du Colombier int n; 120034e04225SDavid du Colombier FidAux *aux; 120134e04225SDavid du Colombier 120234e04225SDavid du Colombier aux = r->fid->aux; 120334e04225SDavid du Colombier if(aux->name == nil){ 120434e04225SDavid du Colombier respond(r, "nfs3client botch -- don't know parent handle in remove"); 120534e04225SDavid du Colombier return; 120634e04225SDavid du Colombier } 120734e04225SDavid du Colombier if(r->fid->qid.type&QTDIR) 120834e04225SDavid du Colombier n = nfsRmdir(aux->auth, r->tag, &aux->parent, aux->name); 120934e04225SDavid du Colombier else 121034e04225SDavid du Colombier n = nfsRemove(aux->auth, r->tag, &aux->parent, aux->name); 121134e04225SDavid du Colombier if(n < 0){ 121234e04225SDavid du Colombier responderrstr(r); 121334e04225SDavid du Colombier return; 121434e04225SDavid du Colombier } 121534e04225SDavid du Colombier respond(r, nil); 121634e04225SDavid du Colombier } 121734e04225SDavid du Colombier 121834e04225SDavid du Colombier void 121934e04225SDavid du Colombier fsstat(Req *r) 122034e04225SDavid du Colombier { 122134e04225SDavid du Colombier FidAux *aux; 122234e04225SDavid du Colombier Nfs3Attr attr; 122334e04225SDavid du Colombier 122434e04225SDavid du Colombier aux = r->fid->aux; 122534e04225SDavid du Colombier if(nfsGetattr(aux->auth, r->tag, &aux->handle, &attr) < 0){ 122634e04225SDavid du Colombier responderrstr(r); 122734e04225SDavid du Colombier return; 122834e04225SDavid du Colombier } 122934e04225SDavid du Colombier memset(&r->d, 0, sizeof r->d); 123034e04225SDavid du Colombier attrToDir(&attr, &r->d); 123134e04225SDavid du Colombier r->d.name = estrdup9p(aux->name ? aux->name : "???"); 123234e04225SDavid du Colombier respond(r, nil); 123334e04225SDavid du Colombier } 123434e04225SDavid du Colombier 123534e04225SDavid du Colombier void 123634e04225SDavid du Colombier fswstat(Req *r) 123734e04225SDavid du Colombier { 123834e04225SDavid du Colombier int op, sync; 123934e04225SDavid du Colombier FidAux *aux; 124034e04225SDavid du Colombier Nfs3SetAttr attr; 124134e04225SDavid du Colombier 124234e04225SDavid du Colombier aux = r->fid->aux; 124334e04225SDavid du Colombier 124434e04225SDavid du Colombier /* Fill out stat first to catch errors */ 124534e04225SDavid du Colombier op = 0; 124634e04225SDavid du Colombier sync = 1; 124734e04225SDavid du Colombier if(~r->d.mode){ 124834e04225SDavid du Colombier if(r->d.mode&(DMAPPEND|DMEXCL)){ 124934e04225SDavid du Colombier respond(r, "wstat -- DMAPPEND and DMEXCL bits not supported"); 125034e04225SDavid du Colombier return; 125134e04225SDavid du Colombier } 125234e04225SDavid du Colombier op = 1; 125334e04225SDavid du Colombier sync = 0; 125434e04225SDavid du Colombier attr.setMode = 1; 125534e04225SDavid du Colombier attr.mode = r->d.mode & 0777; 125634e04225SDavid du Colombier } 125734e04225SDavid du Colombier if(r->d.uid && r->d.uid[0]){ 125834e04225SDavid du Colombier attr.setUid = 1; 125934e04225SDavid du Colombier if(strtouid(r->d.uid, &attr.uid) < 0){ 126034e04225SDavid du Colombier respond(r, "wstat -- unknown uid"); 126134e04225SDavid du Colombier return; 126234e04225SDavid du Colombier } 126334e04225SDavid du Colombier op = 1; 126434e04225SDavid du Colombier sync = 0; 126534e04225SDavid du Colombier } 126634e04225SDavid du Colombier if(r->d.gid && r->d.gid[0]){ 126734e04225SDavid du Colombier attr.setGid = 1; 126834e04225SDavid du Colombier if(strtogid(r->d.gid, &attr.gid) < 0){ 126934e04225SDavid du Colombier respond(r, "wstat -- unknown gid"); 127034e04225SDavid du Colombier return; 127134e04225SDavid du Colombier } 127234e04225SDavid du Colombier op = 1; 127334e04225SDavid du Colombier sync = 0; 127434e04225SDavid du Colombier } 127534e04225SDavid du Colombier if(~r->d.length){ 127634e04225SDavid du Colombier attr.setSize = 1; 127734e04225SDavid du Colombier attr.size = r->d.length; 127834e04225SDavid du Colombier } 127934e04225SDavid du Colombier if(~r->d.mtime){ 128034e04225SDavid du Colombier attr.setMtime = 1; 128134e04225SDavid du Colombier attr.mtime.sec = r->d.mtime; 128234e04225SDavid du Colombier } 128334e04225SDavid du Colombier 128434e04225SDavid du Colombier /* Try rename first because it's more likely to fail (?) */ 128534e04225SDavid du Colombier if(r->d.name && r->d.name[0]){ 128634e04225SDavid du Colombier if(aux->name == nil){ 128734e04225SDavid du Colombier respond(r, "nfsclient botch -- don't know parent handle in rename"); 128834e04225SDavid du Colombier return; 128934e04225SDavid du Colombier } 129034e04225SDavid du Colombier if(nfsRename(aux->auth, r->tag, &aux->parent, aux->name, &aux->parent, r->d.name) < 0){ 129134e04225SDavid du Colombier responderrstr(r); 129234e04225SDavid du Colombier return; 129334e04225SDavid du Colombier } 129434e04225SDavid du Colombier free(aux->name); 129534e04225SDavid du Colombier aux->name = estrdup9p(r->d.name); 129634e04225SDavid du Colombier sync = 0; 129734e04225SDavid du Colombier } 129834e04225SDavid du Colombier 129934e04225SDavid du Colombier /* 130034e04225SDavid du Colombier * Now we have a problem. The rename succeeded 130134e04225SDavid du Colombier * but the setattr could fail. Sic transit atomicity. 130234e04225SDavid du Colombier */ 130334e04225SDavid du Colombier if(op){ 130434e04225SDavid du Colombier if(nfsSetattr(aux->auth, r->tag, &aux->handle, &attr) < 0){ 130534e04225SDavid du Colombier responderrstr(r); 130634e04225SDavid du Colombier return; 130734e04225SDavid du Colombier } 130834e04225SDavid du Colombier } 130934e04225SDavid du Colombier 131034e04225SDavid du Colombier if(sync){ 131134e04225SDavid du Colombier /* NFS commit */ 131234e04225SDavid du Colombier if(nfsCommit(aux->auth, r->tag, &aux->handle) < 0){ 131334e04225SDavid du Colombier responderrstr(r); 131434e04225SDavid du Colombier return; 131534e04225SDavid du Colombier } 131634e04225SDavid du Colombier } 131734e04225SDavid du Colombier 131834e04225SDavid du Colombier respond(r, nil); 131934e04225SDavid du Colombier } 132034e04225SDavid du Colombier 132134e04225SDavid du Colombier char* 132234e04225SDavid du Colombier fswalk1(Fid *fid, char *name, void *v) 132334e04225SDavid du Colombier { 132434e04225SDavid du Colombier u1int have; 132534e04225SDavid du Colombier ulong tag; 132634e04225SDavid du Colombier FidAux *aux; 132734e04225SDavid du Colombier Nfs3Attr attr; 132834e04225SDavid du Colombier Nfs3Handle h; 132934e04225SDavid du Colombier 133034e04225SDavid du Colombier tag = *(ulong*)v; 133134e04225SDavid du Colombier aux = fid->aux; 133234e04225SDavid du Colombier 133334e04225SDavid du Colombier if(nfsLookup(aux->auth, tag, &aux->handle, name, &h, &have, &attr) < 0 133434e04225SDavid du Colombier || (!have && nfsGetattr(aux->auth, tag, &h, &attr) < 0)){ 133534e04225SDavid du Colombier rerrstr(aux->err, sizeof aux->err); 133634e04225SDavid du Colombier return aux->err; 133734e04225SDavid du Colombier } 133834e04225SDavid du Colombier 133934e04225SDavid du Colombier aux->parent = aux->handle; 134034e04225SDavid du Colombier aux->handle = h; 134134e04225SDavid du Colombier free(aux->name); 134234e04225SDavid du Colombier if(strcmp(name, "..") == 0) 134334e04225SDavid du Colombier aux->name = nil; 134434e04225SDavid du Colombier else 134534e04225SDavid du Colombier aux->name = estrdup9p(name); 134634e04225SDavid du Colombier attrToQid(&attr, &fid->qid); 134734e04225SDavid du Colombier return nil; 134834e04225SDavid du Colombier } 134934e04225SDavid du Colombier 135034e04225SDavid du Colombier char* 135134e04225SDavid du Colombier fsclone(Fid *fid, Fid *newfid, void*) 135234e04225SDavid du Colombier { 135334e04225SDavid du Colombier FidAux *a, *na; 135434e04225SDavid du Colombier 135534e04225SDavid du Colombier a = fid->aux; 135634e04225SDavid du Colombier na = emalloc9p(sizeof(FidAux)); 135734e04225SDavid du Colombier *na = *a; 135834e04225SDavid du Colombier if(na->name) 135934e04225SDavid du Colombier na->name = estrdup9p(na->name); 136034e04225SDavid du Colombier newfid->aux = na; 136134e04225SDavid du Colombier if(na->auth) 136234e04225SDavid du Colombier na->auth->ref++; 136334e04225SDavid du Colombier return nil; 136434e04225SDavid du Colombier } 136534e04225SDavid du Colombier 136634e04225SDavid du Colombier void 136734e04225SDavid du Colombier fswalk(Req *r) 136834e04225SDavid du Colombier { 136934e04225SDavid du Colombier walkandclone(r, fswalk1, fsclone, &r->tag); 137034e04225SDavid du Colombier } 137134e04225SDavid du Colombier 137234e04225SDavid du Colombier void 137334e04225SDavid du Colombier fsflush(Req *r) 137434e04225SDavid du Colombier { 137534e04225SDavid du Colombier Req *or; 137634e04225SDavid du Colombier 137734e04225SDavid du Colombier /* 137834e04225SDavid du Colombier * Send on the flush channel(s). 137934e04225SDavid du Colombier * The library will make sure the response 138034e04225SDavid du Colombier * is delayed as necessary. 138134e04225SDavid du Colombier */ 138234e04225SDavid du Colombier or = r->oldreq; 138334e04225SDavid du Colombier if(nfscli) 138434e04225SDavid du Colombier sendul(nfscli->flushchan, (ulong)or->tag); 138534e04225SDavid du Colombier if(mntcli) 138634e04225SDavid du Colombier sendul(mntcli->flushchan, (ulong)or->tag); 138734e04225SDavid du Colombier respond(r, nil); 138834e04225SDavid du Colombier } 138934e04225SDavid du Colombier 139034e04225SDavid du Colombier void 139134e04225SDavid du Colombier fsdispatch(void *v) 139234e04225SDavid du Colombier { 139334e04225SDavid du Colombier Req *r; 139434e04225SDavid du Colombier 139534e04225SDavid du Colombier r = v; 139634e04225SDavid du Colombier switch(r->ifcall.type){ 139734e04225SDavid du Colombier default: respond(r, "unknown type"); break; 139834e04225SDavid du Colombier case Tattach: fsattach(r); break; 139934e04225SDavid du Colombier case Topen: fsopen(r); break; 140034e04225SDavid du Colombier case Tcreate: fscreate(r); break; 140134e04225SDavid du Colombier case Tread: fsread(r); break; 140234e04225SDavid du Colombier case Twrite: fswrite(r); break; 140334e04225SDavid du Colombier case Tremove: fsremove(r); break; 140434e04225SDavid du Colombier case Tflush: fsflush(r); break; 140534e04225SDavid du Colombier case Tstat: fsstat(r); break; 140634e04225SDavid du Colombier case Twstat: fswstat(r); break; 140734e04225SDavid du Colombier case Twalk: fswalk(r); break; 140834e04225SDavid du Colombier } 140934e04225SDavid du Colombier } 141034e04225SDavid du Colombier 141134e04225SDavid du Colombier void 141234e04225SDavid du Colombier fsthread(void*) 141334e04225SDavid du Colombier { 141434e04225SDavid du Colombier Req *r; 141534e04225SDavid du Colombier 141634e04225SDavid du Colombier while((r = recvp(fschan)) != nil) 141734e04225SDavid du Colombier threadcreate(fsdispatch, r, SunStackSize); 141834e04225SDavid du Colombier } 141934e04225SDavid du Colombier 142034e04225SDavid du Colombier void 142134e04225SDavid du Colombier fssend(Req *r) 142234e04225SDavid du Colombier { 142334e04225SDavid du Colombier sendp(fschan, r); 142434e04225SDavid du Colombier } 142534e04225SDavid du Colombier 142634e04225SDavid du Colombier void 142734e04225SDavid du Colombier fsdie(Srv*) 142834e04225SDavid du Colombier { 142934e04225SDavid du Colombier threadexitsall(nil); 143034e04225SDavid du Colombier } 143134e04225SDavid du Colombier 143234e04225SDavid du Colombier Srv fs = 143334e04225SDavid du Colombier { 143434e04225SDavid du Colombier .destroyfid = fsdestroyfid, 143534e04225SDavid du Colombier .attach= fssend, 143634e04225SDavid du Colombier .open= fssend, 143734e04225SDavid du Colombier .create= fssend, 143834e04225SDavid du Colombier .read= fssend, 143934e04225SDavid du Colombier .write= fssend, 144034e04225SDavid du Colombier .remove= fssend, 144134e04225SDavid du Colombier .flush= fssend, 144234e04225SDavid du Colombier .stat= fssend, 144334e04225SDavid du Colombier .wstat= fssend, 144434e04225SDavid du Colombier .walk= fssend, 144534e04225SDavid du Colombier .end= fsdie 144634e04225SDavid du Colombier }; 144734e04225SDavid du Colombier 144834e04225SDavid du Colombier void 144934e04225SDavid du Colombier usage(void) 145034e04225SDavid du Colombier { 145134e04225SDavid du Colombier fprint(2, "usage: nfs [-DRv] [-p perm] [-s srvname] [-u passwd group] addr [addr]\n"); 145234e04225SDavid du Colombier fprint(2, "\taddr - address of portmapper server\n"); 145334e04225SDavid du Colombier fprint(2, "\taddr addr - addresses of mount server and nfs server\n"); 145434e04225SDavid du Colombier exits("usage"); 145534e04225SDavid du Colombier } 145634e04225SDavid du Colombier 145734e04225SDavid du Colombier char* 145834e04225SDavid du Colombier netchangeport(char *addr, uint port, char *buf, uint nbuf) 145934e04225SDavid du Colombier { 146034e04225SDavid du Colombier char *r; 146134e04225SDavid du Colombier 146234e04225SDavid du Colombier strecpy(buf, buf+nbuf, addr); 146334e04225SDavid du Colombier r = strrchr(buf, '!'); 146434e04225SDavid du Colombier if(r == nil) 146534e04225SDavid du Colombier return nil; 146634e04225SDavid du Colombier r++; 146734e04225SDavid du Colombier seprint(r, buf+nbuf, "%ud", port); 146834e04225SDavid du Colombier return buf; 146934e04225SDavid du Colombier } 147034e04225SDavid du Colombier 147134e04225SDavid du Colombier char mbuf[256], nbuf[256]; 147234e04225SDavid du Colombier char *mountaddr, *nfsaddr; 147334e04225SDavid du Colombier Channel *csync; 147434e04225SDavid du Colombier int chattyrpc; 147534e04225SDavid du Colombier void dialproc(void*); 147634e04225SDavid du Colombier 147734e04225SDavid du Colombier void 147834e04225SDavid du Colombier threadmain(int argc, char **argv) 147934e04225SDavid du Colombier { 148034e04225SDavid du Colombier char *srvname, *passwd, *group, *addr, *p; 148134e04225SDavid du Colombier SunClient *cli; 148234e04225SDavid du Colombier int proto; 148334e04225SDavid du Colombier uint mport, nport; 148434e04225SDavid du Colombier ulong perm; 148534e04225SDavid du Colombier Dir d; 148634e04225SDavid du Colombier 148734e04225SDavid du Colombier perm = 0600; 148834e04225SDavid du Colombier passwd = nil; 148934e04225SDavid du Colombier group = nil; 149034e04225SDavid du Colombier srvname = nil; 149134e04225SDavid du Colombier sys = sysname(); 149234e04225SDavid du Colombier if(sys == nil) 149334e04225SDavid du Colombier sys = "plan9"; 149434e04225SDavid du Colombier ARGBEGIN{ 149534e04225SDavid du Colombier default: 149634e04225SDavid du Colombier usage(); 149734e04225SDavid du Colombier case 'D': 149834e04225SDavid du Colombier chatty9p++; 149934e04225SDavid du Colombier break; 150034e04225SDavid du Colombier case 'R': 150134e04225SDavid du Colombier chattyrpc++; 150234e04225SDavid du Colombier break; 150334e04225SDavid du Colombier case 'p': 150434e04225SDavid du Colombier perm = strtol(EARGF(usage()), &p, 8); 150534e04225SDavid du Colombier if(perm==0 || *p != 0) 150634e04225SDavid du Colombier usage(); 150734e04225SDavid du Colombier break; 150834e04225SDavid du Colombier case 's': 150934e04225SDavid du Colombier srvname = EARGF(usage()); 151034e04225SDavid du Colombier break; 151134e04225SDavid du Colombier case 'u': 151234e04225SDavid du Colombier passwd = EARGF(usage()); 151334e04225SDavid du Colombier group = EARGF(usage()); 151434e04225SDavid du Colombier break; 151534e04225SDavid du Colombier case 'v': 151634e04225SDavid du Colombier verbose++; 151734e04225SDavid du Colombier break; 151834e04225SDavid du Colombier }ARGEND 151934e04225SDavid du Colombier 152034e04225SDavid du Colombier if(argc != 1 && argc != 2) 152134e04225SDavid du Colombier usage(); 152234e04225SDavid du Colombier 152334e04225SDavid du Colombier if(srvname == nil) 152434e04225SDavid du Colombier srvname = argv[0]; 152534e04225SDavid du Colombier 152634e04225SDavid du Colombier fmtinstall('B', sunRpcFmt); 152734e04225SDavid du Colombier fmtinstall('C', sunCallFmt); 152834e04225SDavid du Colombier fmtinstall('H', encodefmt); 152934e04225SDavid du Colombier sunFmtInstall(&portProg); 153034e04225SDavid du Colombier sunFmtInstall(&nfs3Prog); 153134e04225SDavid du Colombier sunFmtInstall(&nfsMount3Prog); 153234e04225SDavid du Colombier 153334e04225SDavid du Colombier if(passwd && (map = readmap(passwd, group)) == nil) 153434e04225SDavid du Colombier fprint(2, "warning: reading %s and %s: %r\n", passwd, group); 153534e04225SDavid du Colombier 153634e04225SDavid du Colombier if(map == nil) 153734e04225SDavid du Colombier map = &emptymap; 153834e04225SDavid du Colombier 153934e04225SDavid du Colombier if(argc == 1){ 154034e04225SDavid du Colombier addr = netmkaddr(argv[0], "udp", "portmap"); 154134e04225SDavid du Colombier if((cli = sunDial(addr)) == nil) 154234e04225SDavid du Colombier sysfatal("dial %s: %r", addr); 154334e04225SDavid du Colombier cli->chatty = chattyrpc; 154434e04225SDavid du Colombier sunClientProg(cli, &portProg); 154534e04225SDavid du Colombier if(strstr(addr, "udp!")) 154634e04225SDavid du Colombier proto = PortProtoUdp; 154734e04225SDavid du Colombier else 154834e04225SDavid du Colombier proto = PortProtoTcp; 154934e04225SDavid du Colombier if(getport(cli, NfsMount3Program, NfsMount3Version, proto, &mport) < 0) 155034e04225SDavid du Colombier sysfatal("lookup mount program port: %r"); 155134e04225SDavid du Colombier if(getport(cli, Nfs3Program, Nfs3Version, proto, &nport) < 0) 155234e04225SDavid du Colombier sysfatal("lookup nfs program port: %r"); 155334e04225SDavid du Colombier sunClientClose(cli); 155434e04225SDavid du Colombier mountaddr = netchangeport(addr, mport, mbuf, sizeof mbuf); 155534e04225SDavid du Colombier nfsaddr = netchangeport(addr, nport, nbuf, sizeof nbuf); 155634e04225SDavid du Colombier strcat(mountaddr, "!r"); 155734e04225SDavid du Colombier strcat(nfsaddr, "!r"); 155834e04225SDavid du Colombier if(verbose) 155934e04225SDavid du Colombier fprint(2, "nfs %s %s\n", mountaddr, nfsaddr); 156034e04225SDavid du Colombier }else{ 156134e04225SDavid du Colombier mountaddr = argv[0]; 156234e04225SDavid du Colombier nfsaddr = argv[1]; 156334e04225SDavid du Colombier } 156434e04225SDavid du Colombier 156534e04225SDavid du Colombier /* have to dial in another proc because it creates threads */ 156634e04225SDavid du Colombier csync = chancreate(sizeof(void*), 0); 156734e04225SDavid du Colombier proccreate(dialproc, nil, SunStackSize); 156834e04225SDavid du Colombier recvp(csync); 156934e04225SDavid du Colombier 157034e04225SDavid du Colombier threadpostmountsrv(&fs, srvname, nil, 0); 157134e04225SDavid du Colombier if(perm != 0600){ 157234e04225SDavid du Colombier p = smprint("/srv/%s", srvname); 157334e04225SDavid du Colombier if(p){ 157434e04225SDavid du Colombier nulldir(&d); 157534e04225SDavid du Colombier d.mode = perm; 157634e04225SDavid du Colombier dirwstat(p, &d); 157734e04225SDavid du Colombier } 157834e04225SDavid du Colombier } 157934e04225SDavid du Colombier threadexits(nil); 158034e04225SDavid du Colombier } 158134e04225SDavid du Colombier 158234e04225SDavid du Colombier void 158334e04225SDavid du Colombier dialproc(void*) 158434e04225SDavid du Colombier { 158534e04225SDavid du Colombier rfork(RFNAMEG); 158634e04225SDavid du Colombier rfork(RFNOTEG); 158734e04225SDavid du Colombier if((mntcli = sunDial(mountaddr)) == nil) 158834e04225SDavid du Colombier sysfatal("dial mount program at %s: %r", mountaddr); 158934e04225SDavid du Colombier mntcli->chatty = chattyrpc; 159034e04225SDavid du Colombier sunClientProg(mntcli, &nfsMount3Prog); 159134e04225SDavid du Colombier if(mountNull(0) < 0) 159234e04225SDavid du Colombier sysfatal("execute nop with mnt server at %s: %r", mountaddr); 159334e04225SDavid du Colombier 159434e04225SDavid du Colombier if((nfscli = sunDial(nfsaddr)) == nil) 159534e04225SDavid du Colombier sysfatal("dial nfs program at %s: %r", nfsaddr); 159634e04225SDavid du Colombier nfscli->chatty = chattyrpc; 159734e04225SDavid du Colombier sunClientProg(nfscli, &nfs3Prog); 159834e04225SDavid du Colombier if(nfsNull(0) < 0) 159934e04225SDavid du Colombier sysfatal("execute nop with nfs server at %s: %r", nfsaddr); 160034e04225SDavid du Colombier 160134e04225SDavid du Colombier fschan = chancreate(sizeof(Req*), 0); 160234e04225SDavid du Colombier threadcreate(fsthread, nil, SunStackSize); 160334e04225SDavid du Colombier sendp(csync, 0); 160434e04225SDavid du Colombier } 1605