/* Copyright © 2003 Russ Cox, MIT; see /sys/src/libsunrpc/COPYING */#include <u.h>#include <libc.h>#include <bio.h>#include <fcall.h>#include <thread.h>#include <9p.h>#include <sunrpc.h>#include <nfs3.h> SunClient *nfscli;SunClient *mntcli;char *defaultpath = "/";Channel *fschan;char *sys;int verbose;int readplus = 0; typedef struct Auth Auth;struct Auth{ int ref; uchar *data; int ndata;}; typedef struct FidAux FidAux;struct FidAux{ Nfs3Handle handle; u64int cookie; /* for continuing directory reads */ char *name; /* botch: for remove and rename */ Nfs3Handle parent; /* botch: for remove and rename */ char err[ERRMAX]; /* for walk1 */ Auth *auth;}; /* * various RPCs. here is where we'd insert support for NFS v2 */ voidportCall(SunCall *c, PortCallType type){ c->rpc.prog = PortProgram; c->rpc.vers = PortVersion; c->rpc.proc = type>>1; c->rpc.iscall = !(type&1); c->type = type;} intgetport(SunClient *client, uint prog, uint vers, uint prot, uint *port){ PortTGetport tx; PortRGetport rx; memset(&tx, 0, sizeof tx); portCall(&tx.call, PortCallTGetport); tx.map.prog = prog; tx.map.vers = vers; tx.map.prot = prot; memset(&rx, 0, sizeof rx); portCall(&rx.call, PortCallRGetport); if(sunClientRpc(client, 0, &tx.call, &rx.call, nil) < 0) return -1; *port = rx.port; return 0;} voidmountCall(Auth *a, SunCall *c, NfsMount3CallType type){ c->rpc.iscall = !(type&1); c->rpc.proc = type>>1; c->rpc.prog = NfsMount3Program; c->rpc.vers = NfsMount3Version; if(c->rpc.iscall && a){ c->rpc.cred.flavor = SunAuthSys; c->rpc.cred.data = a->data; c->rpc.cred.ndata = a->ndata; } c->type = type;} intmountNull(ulong tag){ NfsMount3TNull tx; NfsMount3RNull rx; memset(&tx, 0, sizeof tx); mountCall(nil, &tx.call, NfsMount3CallTNull); memset(&rx, 0, sizeof rx); mountCall(nil, &rx.call, NfsMount3CallTNull); return sunClientRpc(mntcli, tag, &tx.call, &rx.call, nil);} intmountMnt(Auth *a, ulong tag, char *path, Nfs3Handle *h){ uchar *freeme; NfsMount3TMnt tx; NfsMount3RMnt rx; memset(&tx, 0, sizeof tx); mountCall(a, &tx.call, NfsMount3CallTMnt); tx.path = path; memset(&rx, 0, sizeof rx); mountCall(a, &rx.call, NfsMount3CallRMnt); if(sunClientRpc(mntcli, tag, &tx.call, &rx.call, &freeme) < 0) return -1; if(rx.status != Nfs3Ok){ nfs3Errstr(rx.status); return -1; }if(verbose)print("handle %.*H\n", rx.len, rx.handle); if(rx.len >= Nfs3MaxHandleSize){ free(freeme); werrstr("server-returned handle too long"); return -1; } memmove(h->h, rx.handle, rx.len); h->len = rx.len; free(freeme); return 0;} voidnfs3Call(Auth *a, SunCall *c, Nfs3CallType type){ c->rpc.iscall = !(type&1); c->rpc.proc = type>>1; c->rpc.prog = Nfs3Program; c->rpc.vers = Nfs3Version; if(c->rpc.iscall && a){ c->rpc.cred.flavor = SunAuthSys; c->rpc.cred.data = a->data; c->rpc.cred.ndata = a->ndata; } c->type = type;} intnfsNull(ulong tag){ Nfs3TNull tx; Nfs3RNull rx; memset(&tx, 0, sizeof tx); nfs3Call(nil, &tx.call, Nfs3CallTNull); memset(&rx, 0, sizeof rx); nfs3Call(nil, &rx.call, Nfs3CallTNull); return sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil);} intnfsGetattr(Auth *a, ulong tag, Nfs3Handle *h, Nfs3Attr *attr){ Nfs3TGetattr tx; Nfs3RGetattr rx; memset(&tx, 0, sizeof tx); nfs3Call(a, &tx.call, Nfs3CallTGetattr); tx.handle = *h; memset(&rx, 0, sizeof rx); nfs3Call(a, &rx.call, Nfs3CallRGetattr); if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0) return -1; if(rx.status != Nfs3Ok){ nfs3Errstr(rx.status); return -1; } *attr = rx.attr; return 0;} intnfsAccess(Auth *a, ulong tag, Nfs3Handle *h, ulong want, ulong *got, u1int *have, Nfs3Attr *attr){ Nfs3TAccess tx; Nfs3RAccess rx; memset(&tx, 0, sizeof tx); nfs3Call(a, &tx.call, Nfs3CallTAccess); tx.handle = *h; tx.access = want; memset(&rx, 0, sizeof rx); nfs3Call(a, &rx.call, Nfs3CallRAccess); if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0) return -1; if(rx.status != Nfs3Ok){ nfs3Errstr(rx.status); return -1; } *got = rx.access; *have = rx.haveAttr; if(rx.haveAttr) *attr = rx.attr; return 0;} intnfsMkdir(Auth *a, ulong tag, Nfs3Handle *h, char *name, Nfs3Handle *nh, ulong mode, uint gid, u1int *have, Nfs3Attr *attr){ Nfs3TMkdir tx; Nfs3RMkdir rx; memset(&tx, 0, sizeof tx); nfs3Call(a, &tx.call, Nfs3CallTMkdir); tx.handle = *h; tx.name = name; tx.attr.setMode = 1; tx.attr.mode = mode; tx.attr.setGid = 1; tx.attr.gid = gid; memset(&rx, 0, sizeof rx); nfs3Call(a, &rx.call, Nfs3CallRMkdir); if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0) return -1; if(rx.status != Nfs3Ok){ nfs3Errstr(rx.status); return -1; } if(!rx.haveHandle){ werrstr("nfs mkdir did not return handle"); return -1; } *nh = rx.handle; *have = rx.haveAttr; if(rx.haveAttr) *attr = rx.attr; return 0;} intnfsCreate(Auth *a, ulong tag, Nfs3Handle *h, char *name, Nfs3Handle *nh, ulong mode, uint gid, u1int *have, Nfs3Attr *attr){ Nfs3TCreate tx; Nfs3RCreate rx; memset(&tx, 0, sizeof tx); nfs3Call(a, &tx.call, Nfs3CallTCreate); tx.handle = *h; tx.name = name; tx.attr.setMode = 1; tx.attr.mode = mode; tx.attr.setGid = 1; tx.attr.gid = gid; memset(&rx, 0, sizeof rx); nfs3Call(a, &rx.call, Nfs3CallRCreate); if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0) return -1; if(rx.status != Nfs3Ok){ nfs3Errstr(rx.status); return -1; } if(!rx.haveHandle){ werrstr("nfs create did not return handle"); return -1; } *nh = rx.handle; *have = rx.haveAttr; if(rx.haveAttr) *attr = rx.attr; return 0;} intnfsRead(Auth *a, ulong tag, Nfs3Handle *h, u32int count, u64int offset, uchar **pp, u32int *pcount, uchar **pfreeme){ uchar *freeme; Nfs3TRead tx; Nfs3RRead rx; memset(&tx, 0, sizeof tx); nfs3Call(a, &tx.call, Nfs3CallTRead); tx.handle = *h; tx.count = count; tx.offset = offset; memset(&rx, 0, sizeof rx); nfs3Call(a, &rx.call, Nfs3CallRRead); if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, &freeme) < 0) return -1; if(rx.status != Nfs3Ok){ nfs3Errstr(rx.status); return -1; } if(rx.count != rx.ndata){ werrstr("nfs read returned count=%ud ndata=%ud", (uint)rx.count, (uint)rx.ndata); free(freeme); return -1; } *pfreeme = freeme; *pcount = rx.count; *pp = rx.data; return 0;} intnfsWrite(Auth *a, ulong tag, Nfs3Handle *h, uchar *data, u32int count, u64int offset, u32int *pcount){ Nfs3TWrite tx; Nfs3RWrite rx; memset(&tx, 0, sizeof tx); nfs3Call(a, &tx.call, Nfs3CallTWrite); tx.handle = *h; tx.count = count; tx.offset = offset; tx.data = data; tx.ndata = count; memset(&rx, 0, sizeof rx); nfs3Call(a, &rx.call, Nfs3CallRWrite); if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0) return -1; if(rx.status != Nfs3Ok){ nfs3Errstr(rx.status); return -1; } *pcount = rx.count; return 0;} intnfsRmdir(Auth *a, ulong tag, Nfs3Handle *h, char *name){ Nfs3TRmdir tx; Nfs3RRmdir rx; memset(&tx, 0, sizeof tx); nfs3Call(a, &tx.call, Nfs3CallTRmdir); tx.handle = *h; tx.name = name; memset(&rx, 0, sizeof rx); nfs3Call(a, &rx.call, Nfs3CallRRmdir); if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0) return -1; if(rx.status != Nfs3Ok){ nfs3Errstr(rx.status); return -1; } return 0;} intnfsRemove(Auth *a, ulong tag, Nfs3Handle *h, char *name){ Nfs3TRemove tx; Nfs3RRemove rx; memset(&tx, 0, sizeof tx); nfs3Call(a, &tx.call, Nfs3CallTRemove); tx.handle = *h; tx.name = name; memset(&rx, 0, sizeof rx); nfs3Call(a, &rx.call, Nfs3CallRRemove); if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0) return -1; if(rx.status != Nfs3Ok){ nfs3Errstr(rx.status); return -1; } return 0;} intnfsRename(Auth *a, ulong tag, Nfs3Handle *h, char *name, Nfs3Handle *th, char *tname){ Nfs3TRename tx; Nfs3RRename rx; memset(&tx, 0, sizeof tx); nfs3Call(a, &tx.call, Nfs3CallTRename); tx.from.handle = *h; tx.from.name = name; tx.to.handle = *th; tx.to.name = tname; memset(&rx, 0, sizeof rx); nfs3Call(a, &rx.call, Nfs3CallRRename); if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0) return -1; if(rx.status != Nfs3Ok){ nfs3Errstr(rx.status); return -1; } return 0;} intnfsSetattr(Auth *a, ulong tag, Nfs3Handle *h, Nfs3SetAttr *attr){ Nfs3TSetattr tx; Nfs3RSetattr rx; memset(&tx, 0, sizeof tx); nfs3Call(a, &tx.call, Nfs3CallTSetattr); tx.handle = *h; tx.attr = *attr; memset(&rx, 0, sizeof rx); nfs3Call(a, &rx.call, Nfs3CallRSetattr); if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0) return -1; if(rx.status != Nfs3Ok){ nfs3Errstr(rx.status); return -1; } return 0;} intnfsCommit(Auth *a, ulong tag, Nfs3Handle *h){ Nfs3TCommit tx; Nfs3RCommit rx; memset(&tx, 0, sizeof tx); nfs3Call(a, &tx.call, Nfs3CallTCommit); tx.handle = *h; memset(&rx, 0, sizeof rx); nfs3Call(a, &rx.call, Nfs3CallRCommit); if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0) return -1; if(rx.status != Nfs3Ok){ nfs3Errstr(rx.status); return -1; } return 0;} intnfsLookup(Auth *a, ulong tag, Nfs3Handle *h, char *name, Nfs3Handle *nh, u1int *have, Nfs3Attr *attr){ Nfs3TLookup tx; Nfs3RLookup rx; memset(&tx, 0, sizeof tx); nfs3Call(a, &tx.call, Nfs3CallTLookup); tx.handle = *h; tx.name = name; memset(&rx, 0, sizeof rx); nfs3Call(a, &rx.call, Nfs3CallRLookup); if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0) return -1; if(rx.status != Nfs3Ok){ nfs3Errstr(rx.status); return -1; } *nh = rx.handle; *have = rx.haveAttr; if(rx.haveAttr) *attr = rx.attr; return 0;}Lines 1–500 of 1632. Load more
/* Copyright © 2003 Russ Cox, MIT; see /sys/src/libsunrpc/COPYING */ #include <u.h> #include <libc.h> #include <bio.h> #include <fcall.h> #include <thread.h> #include <9p.h> #include <sunrpc.h> #include <nfs3.h> SunClient *nfscli; SunClient *mntcli; char *defaultpath = "/"; Channel *fschan; char *sys; int verbose; int readplus = 0; typedef struct Auth Auth; struct Auth { int ref; uchar *data; int ndata; }; typedef struct FidAux FidAux; struct FidAux { Nfs3Handle handle; u64int cookie; /* for continuing directory reads */ char *name; /* botch: for remove and rename */ Nfs3Handle parent; /* botch: for remove and rename */ char err[ERRMAX]; /* for walk1 */ Auth *auth; }; /* * various RPCs. here is where we'd insert support for NFS v2 */ void portCall(SunCall *c, PortCallType type) { c->rpc.prog = PortProgram; c->rpc.vers = PortVersion; c->rpc.proc = type>>1; c->rpc.iscall = !(type&1); c->type = type; } int getport(SunClient *client, uint prog, uint vers, uint prot, uint *port) { PortTGetport tx; PortRGetport rx; memset(&tx, 0, sizeof tx); portCall(&tx.call, PortCallTGetport); tx.map.prog = prog; tx.map.vers = vers; tx.map.prot = prot; memset(&rx, 0, sizeof rx); portCall(&rx.call, PortCallRGetport); if(sunClientRpc(client, 0, &tx.call, &rx.call, nil) < 0) return -1; *port = rx.port; return 0; } void mountCall(Auth *a, SunCall *c, NfsMount3CallType type) { c->rpc.iscall = !(type&1); c->rpc.proc = type>>1; c->rpc.prog = NfsMount3Program; c->rpc.vers = NfsMount3Version; if(c->rpc.iscall && a){ c->rpc.cred.flavor = SunAuthSys; c->rpc.cred.data = a->data; c->rpc.cred.ndata = a->ndata; } c->type = type; } int mountNull(ulong tag) { NfsMount3TNull tx; NfsMount3RNull rx; memset(&tx, 0, sizeof tx); mountCall(nil, &tx.call, NfsMount3CallTNull); memset(&rx, 0, sizeof rx); mountCall(nil, &rx.call, NfsMount3CallTNull); return sunClientRpc(mntcli, tag, &tx.call, &rx.call, nil); } int mountMnt(Auth *a, ulong tag, char *path, Nfs3Handle *h) { uchar *freeme; NfsMount3TMnt tx; NfsMount3RMnt rx; memset(&tx, 0, sizeof tx); mountCall(a, &tx.call, NfsMount3CallTMnt); tx.path = path; memset(&rx, 0, sizeof rx); mountCall(a, &rx.call, NfsMount3CallRMnt); if(sunClientRpc(mntcli, tag, &tx.call, &rx.call, &freeme) < 0) return -1; if(rx.status != Nfs3Ok){ nfs3Errstr(rx.status); return -1; } if(verbose)print("handle %.*H\n", rx.len, rx.handle); if(rx.len >= Nfs3MaxHandleSize){ free(freeme); werrstr("server-returned handle too long"); return -1; } memmove(h->h, rx.handle, rx.len); h->len = rx.len; free(freeme); return 0; } void nfs3Call(Auth *a, SunCall *c, Nfs3CallType type) { c->rpc.iscall = !(type&1); c->rpc.proc = type>>1; c->rpc.prog = Nfs3Program; c->rpc.vers = Nfs3Version; if(c->rpc.iscall && a){ c->rpc.cred.flavor = SunAuthSys; c->rpc.cred.data = a->data; c->rpc.cred.ndata = a->ndata; } c->type = type; } int nfsNull(ulong tag) { Nfs3TNull tx; Nfs3RNull rx; memset(&tx, 0, sizeof tx); nfs3Call(nil, &tx.call, Nfs3CallTNull); memset(&rx, 0, sizeof rx); nfs3Call(nil, &rx.call, Nfs3CallTNull); return sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil); } int nfsGetattr(Auth *a, ulong tag, Nfs3Handle *h, Nfs3Attr *attr) { Nfs3TGetattr tx; Nfs3RGetattr rx; memset(&tx, 0, sizeof tx); nfs3Call(a, &tx.call, Nfs3CallTGetattr); tx.handle = *h; memset(&rx, 0, sizeof rx); nfs3Call(a, &rx.call, Nfs3CallRGetattr); if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0) return -1; if(rx.status != Nfs3Ok){ nfs3Errstr(rx.status); return -1; } *attr = rx.attr; return 0; } int nfsAccess(Auth *a, ulong tag, Nfs3Handle *h, ulong want, ulong *got, u1int *have, Nfs3Attr *attr) { Nfs3TAccess tx; Nfs3RAccess rx; memset(&tx, 0, sizeof tx); nfs3Call(a, &tx.call, Nfs3CallTAccess); tx.handle = *h; tx.access = want; memset(&rx, 0, sizeof rx); nfs3Call(a, &rx.call, Nfs3CallRAccess); if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0) return -1; if(rx.status != Nfs3Ok){ nfs3Errstr(rx.status); return -1; } *got = rx.access; *have = rx.haveAttr; if(rx.haveAttr) *attr = rx.attr; return 0; } int nfsMkdir(Auth *a, ulong tag, Nfs3Handle *h, char *name, Nfs3Handle *nh, ulong mode, uint gid, u1int *have, Nfs3Attr *attr) { Nfs3TMkdir tx; Nfs3RMkdir rx; memset(&tx, 0, sizeof tx); nfs3Call(a, &tx.call, Nfs3CallTMkdir); tx.handle = *h; tx.name = name; tx.attr.setMode = 1; tx.attr.mode = mode; tx.attr.setGid = 1; tx.attr.gid = gid; memset(&rx, 0, sizeof rx); nfs3Call(a, &rx.call, Nfs3CallRMkdir); if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0) return -1; if(rx.status != Nfs3Ok){ nfs3Errstr(rx.status); return -1; } if(!rx.haveHandle){ werrstr("nfs mkdir did not return handle"); return -1; } *nh = rx.handle; *have = rx.haveAttr; if(rx.haveAttr) *attr = rx.attr; return 0; } int nfsCreate(Auth *a, ulong tag, Nfs3Handle *h, char *name, Nfs3Handle *nh, ulong mode, uint gid, u1int *have, Nfs3Attr *attr) { Nfs3TCreate tx; Nfs3RCreate rx; memset(&tx, 0, sizeof tx); nfs3Call(a, &tx.call, Nfs3CallTCreate); tx.handle = *h; tx.name = name; tx.attr.setMode = 1; tx.attr.mode = mode; tx.attr.setGid = 1; tx.attr.gid = gid; memset(&rx, 0, sizeof rx); nfs3Call(a, &rx.call, Nfs3CallRCreate); if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0) return -1; if(rx.status != Nfs3Ok){ nfs3Errstr(rx.status); return -1; } if(!rx.haveHandle){ werrstr("nfs create did not return handle"); return -1; } *nh = rx.handle; *have = rx.haveAttr; if(rx.haveAttr) *attr = rx.attr; return 0; } int nfsRead(Auth *a, ulong tag, Nfs3Handle *h, u32int count, u64int offset, uchar **pp, u32int *pcount, uchar **pfreeme) { uchar *freeme; Nfs3TRead tx; Nfs3RRead rx; memset(&tx, 0, sizeof tx); nfs3Call(a, &tx.call, Nfs3CallTRead); tx.handle = *h; tx.count = count; tx.offset = offset; memset(&rx, 0, sizeof rx); nfs3Call(a, &rx.call, Nfs3CallRRead); if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, &freeme) < 0) return -1; if(rx.status != Nfs3Ok){ nfs3Errstr(rx.status); return -1; } if(rx.count != rx.ndata){ werrstr("nfs read returned count=%ud ndata=%ud", (uint)rx.count, (uint)rx.ndata); free(freeme); return -1; } *pfreeme = freeme; *pcount = rx.count; *pp = rx.data; return 0; } int nfsWrite(Auth *a, ulong tag, Nfs3Handle *h, uchar *data, u32int count, u64int offset, u32int *pcount) { Nfs3TWrite tx; Nfs3RWrite rx; memset(&tx, 0, sizeof tx); nfs3Call(a, &tx.call, Nfs3CallTWrite); tx.handle = *h; tx.count = count; tx.offset = offset; tx.data = data; tx.ndata = count; memset(&rx, 0, sizeof rx); nfs3Call(a, &rx.call, Nfs3CallRWrite); if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0) return -1; if(rx.status != Nfs3Ok){ nfs3Errstr(rx.status); return -1; } *pcount = rx.count; return 0; } int nfsRmdir(Auth *a, ulong tag, Nfs3Handle *h, char *name) { Nfs3TRmdir tx; Nfs3RRmdir rx; memset(&tx, 0, sizeof tx); nfs3Call(a, &tx.call, Nfs3CallTRmdir); tx.handle = *h; tx.name = name; memset(&rx, 0, sizeof rx); nfs3Call(a, &rx.call, Nfs3CallRRmdir); if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0) return -1; if(rx.status != Nfs3Ok){ nfs3Errstr(rx.status); return -1; } return 0; } int nfsRemove(Auth *a, ulong tag, Nfs3Handle *h, char *name) { Nfs3TRemove tx; Nfs3RRemove rx; memset(&tx, 0, sizeof tx); nfs3Call(a, &tx.call, Nfs3CallTRemove); tx.handle = *h; tx.name = name; memset(&rx, 0, sizeof rx); nfs3Call(a, &rx.call, Nfs3CallRRemove); if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0) return -1; if(rx.status != Nfs3Ok){ nfs3Errstr(rx.status); return -1; } return 0; } int nfsRename(Auth *a, ulong tag, Nfs3Handle *h, char *name, Nfs3Handle *th, char *tname) { Nfs3TRename tx; Nfs3RRename rx; memset(&tx, 0, sizeof tx); nfs3Call(a, &tx.call, Nfs3CallTRename); tx.from.handle = *h; tx.from.name = name; tx.to.handle = *th; tx.to.name = tname; memset(&rx, 0, sizeof rx); nfs3Call(a, &rx.call, Nfs3CallRRename); if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0) return -1; if(rx.status != Nfs3Ok){ nfs3Errstr(rx.status); return -1; } return 0; } int nfsSetattr(Auth *a, ulong tag, Nfs3Handle *h, Nfs3SetAttr *attr) { Nfs3TSetattr tx; Nfs3RSetattr rx; memset(&tx, 0, sizeof tx); nfs3Call(a, &tx.call, Nfs3CallTSetattr); tx.handle = *h; tx.attr = *attr; memset(&rx, 0, sizeof rx); nfs3Call(a, &rx.call, Nfs3CallRSetattr); if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0) return -1; if(rx.status != Nfs3Ok){ nfs3Errstr(rx.status); return -1; } return 0; } int nfsCommit(Auth *a, ulong tag, Nfs3Handle *h) { Nfs3TCommit tx; Nfs3RCommit rx; memset(&tx, 0, sizeof tx); nfs3Call(a, &tx.call, Nfs3CallTCommit); tx.handle = *h; memset(&rx, 0, sizeof rx); nfs3Call(a, &rx.call, Nfs3CallRCommit); if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0) return -1; if(rx.status != Nfs3Ok){ nfs3Errstr(rx.status); return -1; } return 0; } int nfsLookup(Auth *a, ulong tag, Nfs3Handle *h, char *name, Nfs3Handle *nh, u1int *have, Nfs3Attr *attr) { Nfs3TLookup tx; Nfs3RLookup rx; memset(&tx, 0, sizeof tx); nfs3Call(a, &tx.call, Nfs3CallTLookup); tx.handle = *h; tx.name = name; memset(&rx, 0, sizeof rx); nfs3Call(a, &rx.call, Nfs3CallRLookup); if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, nil) < 0) return -1; if(rx.status != Nfs3Ok){ nfs3Errstr(rx.status); return -1; } *nh = rx.handle; *have = rx.haveAttr; if(rx.haveAttr) *attr = rx.attr; return 0; }