henesyinit from lsubb0c8bdb6 years agoHistory
305 lines · 6.0 KB · C
RawDownload
/* * Yet more code duplicated to perform the amount op. */#include <u.h>#include <libc.h>#include <fcall.h>#include <thread.h>#include <auth.h>#include <ip.h>#include "names.h"#include "vols.h" static intagetfrep(int fd, Frpc* fop){	int r; 	r = getfrep(fd, fop);	if (r > 0 || r == -1)		Dbgprint(fop->fid, "   <= %F\n", &fop->r);	return r;} static longfswrite(int fd, int fid, Frpc* fop, void* a, long n){	fop->f.tag = 0xb;	fop->f.type= Twrite;	fop->f.fid = fid;	fop->f.data = a;	fop->f.count = n;	if (putfcall(fd, fop) <= 0 || agetfrep(fd, fop) <= 0 ||	    fop->r.type != Rwrite || fop->r.tag != fop->f.tag)		return -1;	return fop->r.count;} static longfsread(int fd, int fid, Frpc* fop, void* a, long n){	fop->f.tag = 0xc;	fop->f.type= Tread;	fop->f.fid = fid;	fop->f.count = n;	if (putfcall(fd, fop) <= 0 || agetfrep(fd, fop) <= 0 ||	    fop->r.type != Rread || fop->r.tag != fop->f.tag)		return -1;	memmove(a, fop->r.data, fop->r.count);	return fop->r.count;} static longfsclose(int fd, int fid, Frpc* fop){	fop->f.tag = 0xd;	fop->f.type= Tclunk;	fop->f.fid = fid;	if (putfcall(fd, fop) <= 0 || agetfrep(fd, fop) <= 0 ||	    fop->r.type != Rclunk || fop->r.tag != fop->f.tag)		return -1;	return 0;} static intfsattach(int fd, int fid, int afid, char* spec, Frpc* fop, Qid* q){	fop->f.tag = 0xe;	fop->f.type= Tattach;	fop->f.fid = fid;	fop->f.afid= afid;	fop->f.uname = getuser();	fop->f.aname = spec;	if (putfcall(fd, fop) <= 0 || agetfrep(fd, fop) <= 0 ||	    fop->r.type != Rattach || fop->r.tag != fop->f.tag)		return -1;	*q = fop->r.qid;	return 0;} static char* anames[] = {	"ok", "done", "error", "needkey", "badkey", "writenext", "toosmall", "toobig",	"rpcfailure", "phase" }; static AuthInfo*fsfauth_proxy(int fsfd, int afid, Frpc* fop, AuthRpc *rpc, char* params){	char *buf;	int m, n, ret;	AuthInfo *a;	char oerr[ERRMAX];	int	id; 	rerrstr(oerr, sizeof oerr);	werrstr("UNKNOWN AUTH ERROR"); 	assert(rpc);	if(auth_rpc(rpc, "start", params, strlen(params)) != ARok){		werrstr("fauth_proxy start: %r");		return nil;	} 	buf = emalloc(AuthRpcMax);	for(;;){		id = auth_rpc(rpc, "read", nil, 0);		switch(id){		case ARdone:			free(buf);			a = auth_getinfo(rpc);			errstr(oerr, sizeof oerr);	/* no error, restore whatever was there */			return a;		case ARok:			if(fswrite(fsfd, afid, fop, rpc->arg, rpc->narg) != rpc->narg){				werrstr("auth_proxy write fd: %r");				goto Error;			}			break;		case ARphase:			n = 0;			memset(buf, 0, AuthRpcMax);			while((ret = auth_rpc(rpc, "write", buf, n)) == ARtoosmall){				if(atoi(rpc->arg) > AuthRpcMax)					break;				m = fsread(fsfd, afid, fop, buf+n, atoi(rpc->arg)-n);				if(m <= 0){					if(m == 0)						werrstr("auth_proxy short read: %s", buf);					goto Error;				}				n += m;			}			if (ret != ARok){				goto Error;			}			break;		default:			werrstr("auth_proxy rpc: %r");			goto Error;		}	}Error:	free(buf);	return nil;}  static AuthInfo*fsauth_proxy(int fsfd, int afid, Frpc* fop, char* params){	AuthInfo *ai;	AuthRpc *rpc;	int	afd; 	quotefmtinstall();	/* just in case */	afd = open("/mnt/factotum/rpc", ORDWR);	if(afd < 0){		// Try mounting it.		afd = open("#s/factotum", ORDWR);		if (afd < 0){			return nil;		}		mount(afd, -1, "/mnt", MREPL, "");		afd = open("/mnt/factotum/rpc", ORDWR);		if (afd < 0){			return nil;		}	}	rpc = auth_allocrpc(afd);	if(rpc == nil) {		close(afd);		return nil;	}	ai = fsfauth_proxy(fsfd, afid, fop, rpc, params);	auth_freerpc(rpc);	close(afd);	return ai;} static intauthfsfd(int fd, char* spec, Frpc* fop){	AuthInfo*ai;	int	afid; 	fop->f.tag = 0xb;	fop->f.type= Tauth;	fop->f.afid = getfidnr();	fop->f.uname = getuser();	fop->f.aname = spec;	afid = -1;	if (putfcall(fd, fop) <= 0 || agetfrep(fd, fop) <= 0)		goto fail;	if (fop->r.type == Rerror)  // no auth required.		goto done;	if (fop->r.type != Rauth || fop->r.tag != fop->f.tag)		goto fail;	else		afid = fop->f.afid;	/* The next call depends on linking against our own	 * fauth_proxy function, which speaks 9P to the server	 * instead of using the kernel.	 */	ai = fsauth_proxy(fd, afid, fop, "proto=p9any role=client");	if (0 && ai == nil) // Debugging this		goto fail;	auth_freeAI(ai);done:	return afid;fail:	close(fd);	return -1; } static intfsversion(int fd, Frpc* fop){	fop->f.tag = NOTAG;	fop->f.type= Tversion;	fop->f.msize= Maxmsglen;	fop->f.version = "9P2000";	if (putfcall(fd, fop) <= 0 || agetfrep(fd, fop) <= 0){		vdprint(2, "can't RPC Tversion: %r\n");		return -1;	}	if (fop->r.tag != NOTAG || fop->r.type != Rversion){		vdprint(2, "bad reply for Tversion");		return -1;	}	if (strcmp(fop->r.version, "9P2000")){		vdprint(2, "bad server version\n");		return -1;	}	if (fop->r.msize < Maxmsglen)		msglen = fop->r.msize;	return 1;} static intdialfs(Fs* fs){	int	fd, cfd;	char	dir[50];	char*	s; 	cfd = -1;	if (fs->addr[0] == '#' || fs->addr[0] == '/')		fd = open(fs->addr, ORDWR);	else {		s=smprint("/net/%s", fs->addr);		fd = dial(s, 0, dir, &cfd);		free(s);		if (cfd != -1){			fprint(cfd, "keepalive 2000\n");			close(cfd);		}	}	return fd;} intamountfs(Fs* fs){	int	fd, afid, r;	Frpc*	fop;	int	doversion;	Dir*	d; 	fd = dialfs(fs);	if (fd < 0){		vdprint(2, "%s: can't dial %s: %r\n", argv0, fs->addr);		return 0;	}	if (fs->addr[0] != '#' && fs->addr[0] != '/')		doversion = 1;	else {		d = dirfstat(fd);		if (d == nil)			return 0;		doversion = (d->qid.path != fs->fdqid.path);		fs->fdqid = d->qid;		free(d);	}	fop = rpcalloc();	if (doversion && fsversion(fd, fop) < 0){		vdprint(2, "%s: %s: bad fversion\n", argv0, fs->addr);		close(fd);		rpcfree(fop);		return 0;	}	afid = authfsfd(fd, fs->spec, fop);	if (fsattach(fd, fs->fid->snr, afid, fs->spec, fop, &fs->fid->qid) < 0){		vdprint(2, "%s: attach failed: %s\n", argv0, fs->addr);		close(fd); // afid will be collected by the server.		r = 0;	} else {		if (afid >= 0)			fsclose(fd, afid, fop);		fs->fid->qid.path |= fs->qid.path;		fs->fd = fd;	// make it official.		r = 1;	}	rpcfree(fop);	return r;}