1632 lines · 30.4 KB · C
RawDownload
/* 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.