Пример #1
0
void
io(void)
{
	char *err;
	int n, nerr;
	char buf[ERRMAX];

	errstr(buf, sizeof buf);
	for(nerr=0, buf[0]='\0'; nerr<100; nerr++){
		/*
		 * reading from a pipe or a network device
		 * will give an error after a few eof reads
		 * however, we cannot tell the difference
		 * between a zero-length read and an interrupt
		 * on the processes writing to us,
		 * so we wait for the error
		 */
		n = read9pmsg(mfd[0], mdata, sizeof mdata);
		if(n==0)
			continue;
		if(n < 0){
			if(buf[0]=='\0')
				errstr(buf, sizeof buf);
			continue;
		}
		nerr = 0;
		buf[0] = '\0';
		if(convM2S(mdata, n, &rhdr) != n)
			error("convert error in convM2S");

		if(verbose)
			fprint(2, "tapefs: <=%F\n", &rhdr);/**/

		thdr.data = (char*)mdata + IOHDRSZ;
		thdr.stat = mdata + IOHDRSZ;
		if(!fcalls[rhdr.type])
			err = "bad fcall type";
		else
			err = (*fcalls[rhdr.type])(newfid(rhdr.fid));
		if(err){
			thdr.type = Rerror;
			thdr.ename = err;
		}else{
			thdr.type = rhdr.type + 1;
			thdr.fid = rhdr.fid;
		}
		thdr.tag = rhdr.tag;
		n = convS2M(&thdr, mdata, messagesize);
		if(n <= 0)
			error("convert error in convS2M");
		if(verbose)
			fprint(2, "tapefs: =>%F\n", &thdr);/**/
		if(write(mfd[1], mdata, n) != n)
			error("mount write");
	}
	if(buf[0]=='\0' || strstr(buf, "hungup"))
		exits("");
	fprint(2, "%s: mount read: %s\n", argv0, buf);
	exits(buf);
}
Пример #2
0
Файл: cs.c Проект: brho/akaros
static void sendmsg(struct job *job, char *err)
{
	int n;
	uint8_t mdata[IOHDRSZ + Maxfdata];
	char ename[ERRMAX];

	if (err) {
		job->reply.type = Rerror;
		snprintf(ename, sizeof(ename), "cs: %s", err);
		job->reply.ename = ename;
	} else {
		job->reply.type = job->request.type + 1;
	}
	job->reply.tag = job->request.tag;
	n = convS2M(&job->reply, mdata, sizeof(mdata));
	if (n == 1) {
		fprintf(stderr, "CS:sendmsg convS2M of %F returns 0",
			&job->reply);
		abort();
	}
	spinlock_lock(&joblock);
	if (job->flushed == 0)
		if (write(mfd[1], mdata, n) != n)
			error(1, 0, "%s: %r", "mount write");
	spinlock_unlock(&joblock);
	if (debug)
		fprintf(stderr, "CS:%F %d", &job->reply, n);
}
Пример #3
0
void
sendmsg(Job *job, char *err)
{
	int n;
	uchar mdata[IOHDRSZ + Maxfdata];
	char ename[ERRMAX];

	if(err){
		job->reply.type = Rerror;
		snprint(ename, sizeof ename, "dns: %s", err);
		job->reply.ename = ename;
	}else
		job->reply.type = job->request.type+1;
	job->reply.tag = job->request.tag;
	n = convS2M(&job->reply, mdata, sizeof mdata);
	if(n == 0){
		warning("sendmsg convS2M of %F returns 0", &job->reply);
		abort();
	}
	lock(&joblock);
	if(job->flushed == 0)
		if(write(mfd[1], mdata, n)!=n)
			sysfatal("mount write");
	unlock(&joblock);
	if(debug)
		dnslog("%F %d", &job->reply, n);
}
Пример #4
0
Файл: fsys.c Проект: npe9/harvey
Xfid*
respond(Xfid *x, Fcall *t, char *err)
{
    int n;

    if(err) {
        t->type = Rerror;
        t->ename = err;
    } else
        t->type = x->type+1;
    t->fid = x->fid;
    t->tag = x->tag;
    if(x->buf == nil)
        x->buf = emalloc(messagesize);
    n = convS2M(t, x->buf, messagesize);
    if(n <= 0)
        error("convert error in convS2M");
    if(write(sfd, x->buf, n) != n)
        error("write error in respond");
    free(x->buf);
    x->buf = nil;
    if(DEBUG)
        fprint(2, "r: %F\n", t);
    return x;
}
Пример #5
0
static void
reply(Devlogfs *d)
{
	d->readp = d->readbuf;
	d->readcount = convS2M(&d->out, d->readp, d->readbufsize);
//print("reply is %d bytes\n", d->readcount);
	if (d->readcount == 0)
		panic("logfs: reply: did not fit\n");
	d->reading = 1;
	Wakeup(&d->readrendez);
}
Пример #6
0
static int
putfcall(int fd, Fcall* f)
{
	int n;

	n = convS2M(f, txbuf, sizeof(txbuf));
	if (n == 0)
		return -1;
	if (write(fd, txbuf, n) != n)
		return -1;
	return n;
}
Пример #7
0
void
io(int srvfd)
{
	int n, pid;

	pid = getpid();

	fmtinstall('F', fcallfmt);
	for(;;){
		/*
		 * reading from a pipe or a network device
		 * will give an error after a few eof reads.
		 * however, we cannot tell the difference
		 * between a zero-length read and an interrupt
		 * on the processes writing to us,
		 * so we wait for the error.
		 */
		n = read9pmsg(srvfd, mdata, sizeof mdata);
		if(n < 0)
			break;
		if(n == 0)
			continue;
		if(convM2S(mdata, n, req) == 0)
			continue;

		if(chatty)
			fprint(2, "dossrv %d:<-%F\n", pid, req);

		errno = 0;
		if(!fcalls[req->type])
			errno = Ebadfcall;
		else
			(*fcalls[req->type])();
		if(errno){
			rep->type = Rerror;
			rep->ename = xerrstr(errno);
		}else{
			rep->type = req->type + 1;
			rep->fid = req->fid;
		}
		rep->tag = req->tag;
		if(chatty)
			fprint(2, "dossrv %d:->%F\n", pid, rep);
		n = convS2M(rep, mdata, sizeof mdata);
		if(n == 0)
			panic("convS2M error on write");
		if(write(srvfd, mdata, n) != n)
			panic("mount write");
	}
	chat("server shut down");
}
Пример #8
0
Файл: 9p.c Проект: 99years/plan9
int
xmesg(Session *s, int t)
{
	int n;

	if(chatty){
		if(0 <= t && t < nelem(tnames) && tnames[t])
			chat("T%s...", tnames[t]);
		else
			chat("T%d...", t);
	}
	s->f.type = t;
	s->f.tag = ++s->tag;
	if(p9debug)
		fprint(2, "xmseg\tsend %F\n", &s->f);
	n = convS2M(&s->f, s->data, messagesize);
	if(niwrite(s->fd, s->data, n) != n){
		clog("xmesg write error on %d: %r\n", s->fd);
		return -1;
	}
again:
	n = read9pmsg(s->fd, s->data, messagesize);
	if(n < 0){
		clog("xmesg read error: %r\n");
		return -1;
	}
	if(convM2S(s->data, n, &s->f) <= 0){
		clog("xmesg bad convM2S %d %.2x %.2x %.2x %.2x\n",
			n, ((uchar*)s->data)[0], ((uchar*)s->data)[1],
			((uchar*)s->data)[2], ((uchar*)s->data)[3]);
		return -1;
	}
	if(p9debug)
		fprint(2, "\trecv %F\n", &s->f);
	if(s->f.tag != s->tag){
		clog("xmesg tag %d for %d\n", s->f.tag, s->tag);
		goto again;
	}
	if(s->f.type == Rerror){
		if(t == Tclunk)
			clog("xmesg clunk: %s", s->f.ename);
		chat("xmesg %d error %s...", t, s->f.ename);
		return -1;
	}
	if(s->f.type != t+1){
		clog("xmesg type mismatch: %d, expected %d\n", s->f.type, t+1);
		return -1;
	}
	return 0;
}
Пример #9
0
void
sendomsg(Msg *m)
{
	int n, nn;

	n = sizeS2M(&m->tx);
	m->tpkt = emalloc(n);
	nn = convS2M(&m->tx, m->tpkt, n);
	if(nn <= BIT16SZ)
		sysfatal("convS2M conversion error");
	if(nn != n)
		sysfatal("sizeS2M and convS2M disagree");
	sendq(outq, m);
}
Пример #10
0
void
mainproc(void *v)
{
	int n, nn;
	Fcall f;
	USED(v);

	atnotify(ignorepipe, 1);
	fmtinstall('D', dirfmt);
	fmtinstall('M', dirmodefmt);
	fmtinstall('F', fcallfmt);
	fmtinstall('H', encodefmt);

	outq = qalloc();
	inq = qalloc();

	if(!versioned){
		f.type = Tversion;
		f.version = "9P2000";
		f.msize = msize;
		f.tag = NOTAG;
		n = convS2M(&f, vbuf, sizeof vbuf);
		if(n <= BIT16SZ)
			sysfatal("convS2M conversion error");
		if(verbose > 1) fprint(2, "%T * <- %F\n", &f);
		nn = write(1, vbuf, n);
		if(n != nn)
			sysfatal("error writing Tversion: %r\n");
		n = read9pmsg(0, vbuf, sizeof vbuf);
		if(n < 0)
			sysfatal("read9pmsg failure");
		if(convM2S(vbuf, n, &f) != n)
			sysfatal("convM2S failure");
		if(f.msize < msize)
			msize = f.msize;
		if(verbose > 1) fprint(2, "%T * -> %F\n", &f);
	}

	threadcreate(inputthread, nil, STACK);
	threadcreate(outputthread, nil, STACK);

/*	if(rootfid) */
/*		dorootstat(); */
	
	threadcreate(listenthread, nil, STACK);
	threadexits(0);
}
Пример #11
0
int
fsreply(int fd, Fcall *f)
{
	uchar buf[IOHDRSZ+Maxfdata];
	int n;

	if(dbg)
		fprint(2, "notefs: <-%F\n", f);
	n = convS2M(f, buf, sizeof buf);
	if(n > 0){
		if(write(fd, buf, n) != n){
			close(fd);
			return -1;
		}
	}
	return 0;
}
Пример #12
0
void
io(void)
{
	char *err;
	int n;

	for(;;){
		n = read9pmsg(mfd[0], mdata, sizeof mdata);
		if(n <= 0)
			break;
		if(convM2S(mdata, n, &rhdr) != n)
			sysfatal("convM2S conversion error");

		if(dflag)
			fprint(2, "vacfs:<-%F\n", &rhdr);

		thdr.data = (char*)mdata + IOHDRSZ;
		if(!fcalls[rhdr.type])
			err = "bad fcall type";
		else
			err = (*fcalls[rhdr.type])(newfid(rhdr.fid));
		if(err){
			thdr.type = Rerror;
			thdr.ename = err;
#ifdef PLAN9PORT
			thdr.errornum = 0;
#endif
		}else{
			thdr.type = rhdr.type + 1;
			thdr.fid = rhdr.fid;
		}
		thdr.tag = rhdr.tag;
		if(dflag)
			fprint(2, "vacfs:->%F\n", &thdr);
		n = convS2M(&thdr, mdata, messagesize);
		if(n <= BIT16SZ)
			sysfatal("convS2M conversion error");
		if(err)
			vtfree(err);

		if(write(mfd[1], mdata, n) != n)
			sysfatal("mount write: %r");
	}
}
Пример #13
0
/*
 *	write a protocol reply to the client
 */
static void
reply(Fcall *r, char *error)
{
    int n;

    if(error == nil)
        r->type++;
    else {
        r->type = Rerror;
        r->ename = error;
    }
    if(debugfd >= 0)
        fprint(debugfd, "->%F\n", r);/**/
    n = convS2M(r, rbuf, sizeof rbuf);
    if(n == 0)
        sysfatal("convS2M: %r");
    if(write(srvfd, rbuf, n) < 0)
        sysfatal("reply: %r");
}
Пример #14
0
void
fsreply(Fs *fs, Request *r, char *err)
{
	int n;
	uchar buf[MAXSIZE];

	if(err){
		r->f.type = Rerror;
		r->f.ename = err;
	}
	if(debug)
		fprint(2, "%F path %llux\n", &r->f, r->fid->qid.path);
	n = convS2M(&r->f, buf, messagesize);
	if(n == 0)
		fatal("bad convS2M");
	if(write(fs->fd, buf, n) != n)
		fatal("unmounted");
	free(r);
}
Пример #15
0
void
repack(Fcall *f, uchar **ppkt)
{
	uint n, nn;
	uchar *pkt;
	
	pkt = *ppkt;
	n = GBIT32(pkt);
	nn = sizeS2M(f);
	if(nn > n){
		free(pkt);
		pkt = emalloc(nn);
		*ppkt = pkt;
	}
	n = convS2M(f, pkt, nn);	
	if(n <= BIT16SZ)
		sysfatal("convS2M conversion error");
	if(n != nn)
		sysfatal("convS2M and sizeS2M disagree");
}
Пример #16
0
void
respond(Req *r, char *error)
{
	int i, m, n;
	char errbuf[ERRMAX];
	Srv *srv;

	srv = r->srv;
	assert(srv != nil);

	if(r->responded){
		assert(r->pool);
		goto free;
	}
		
	assert(r->responded == 0);
	r->error = error;

	switch(r->ifcall.type){
	default:
		assert(0);
	/*
	 * Flush is special.  If the handler says so, we return
	 * without further processing.  Respond will be called
	 * again once it is safe.
	 */
	case Tflush:
		if(rflush(r, error)<0)
			return;
		break;
	case Tversion:	rversion(r, error);	break;
	case Tauth:	rauth(r, error);	break;
	case Tattach:	rattach(r, error);	break;
	case Twalk:	rwalk(r, error);	break;
	case Topen:	ropen(r, error);	break;
	case Tcreate:	rcreate(r, error);	break;
	case Tread:	rread(r, error);	break;
	case Twrite:	rwrite(r, error);	break;
	case Tclunk:	rclunk(r, error);	break;
	case Tremove:	rremove(r, error, errbuf);	break;
	case Tstat:	rstat(r, error);	break;
	case Twstat:	rwstat(r, error);	break;
	}

	r->ofcall.tag = r->ifcall.tag;
	r->ofcall.type = r->ifcall.type+1;
	if(r->error)
		setfcallerror(&r->ofcall, r->error);

if(chatty9p)
	fprint(2, "-%d-> %F\n", srv->outfd, &r->ofcall);

	qlock(&srv->wlock);
	n = convS2M(&r->ofcall, srv->wbuf, srv->msize);
	if(n <= 0){
		fprint(2, "n = %d %F\n", n, &r->ofcall);
		abort();
	}
	assert(n > 2);
	/*
	 * There is a race here - we must remove the entry before
	 * the write, so that if the client is very fast and reuses the
	 * tag, the read loop won't think it is still in use.
	 * 
	 * By removing the entry before the write, we open up a 
	 * race with incoming Tflush messages.  Specifically, an
	 * incoming Tflush might not see r even though it has not
	 * yet been responded to.  It would then send an Rflush
	 * immediately, potentially before we do the write.  This can't
	 * happen because we already old srv->wlock, so nothing
	 * is going out on the wire before this write.
	 */
	if(r->pool)	/* not a fake */
		closereq(removereq(r->pool, r->ifcall.tag));

	qlock(&r->lk);
	r->responded = 1;
	if(r->pool)
	if(r->ref.ref == 1+r->nflush)
	if(r->fid){
		/*
		 * There are no references other than in our r->flush array,
		 * so no one else should be accessing r concurrently.
		 * Close the fid now, before responding to the message.
		 * 
		 * If the client is behaving (there are no outstanding T-messages
		 * that reference r->fid) and the message is a Tclunk or Tremove,
		 * then this closefid will call destroyfid.  
		 * 
		 * This means destroyfid can't piddle around 
		 * indefinitely (we're holding srv->wlock!), but it provides
		 * for tighter semantics as to when destroyfid is called.
		 *
		 * LANL has observed cases where waiting until after the write
		 * can delay a closefid on a Twrite for many 9P transactions,
		 * so that a handful of transactions can happen including a Tclunk
		 * and a Topen, and the original fid will still not be destroyed.
		 */
		closefid(r->fid);
		r->fid = nil;
	}
	qunlock(&r->lk);
	m = write(srv->outfd, srv->wbuf, n);
	if(m != n)
		sysfatal("lib9p srv: write %d returned %d on fd %d: %r", n, m, srv->outfd);
	qunlock(&srv->wlock);

free:
	qlock(&r->lk);	/* no one will add flushes now */

	for(i=0; i<r->nflush; i++){
		r->flush[i]->oldreq = nil;	/* so it doesn't try to lock us! */
		respond(r->flush[i], nil);
	}
	free(r->flush);
	r->flush = nil;
	r->nflush = 0;
	qunlock(&r->lk);

	if(r->pool)
		closereq(r);
	else
		free(r);
}
Пример #17
0
void
io(int srvfd)
{
	int n, pid;
	Fcall xreq, xrep;

	req = &xreq;
	rep = &xrep;
	pid = getpid();
	fmtinstall('F', fcallfmt);

	for(;;){
		/*
		 * reading from a pipe or a network device
		 * will give an error after a few eof reads.
		 * however, we cannot tell the difference
		 * between a zero-length read and an interrupt
		 * on the processes writing to us,
		 * so we wait for the error.
		 */
		n = read9pmsg(srvfd, mdata, sizeof mdata);
		if(n < 0)
			break;
		if(n == 0)
			continue;
		if(convM2S(mdata, n, req) == 0)
			continue;

		if(chatty)
			fprint(2, "9660srv %d:<-%F\n", pid, req);

		errno = 0;
		if(!waserror()){
			err_msg[0] = 0;
			if(req->type >= nelem(fcalls) || !fcalls[req->type])
				error("bad fcall type");
			(*fcalls[req->type])();
			poperror();
		}

		if(err_msg[0]){
			rep->type = Rerror;
			rep->ename = err_msg;
		}else{
			rep->type = req->type + 1;
			rep->fid = req->fid;
		}
		rep->tag = req->tag;

		if(chatty)
			fprint(2, "9660srv %d:->%F\n", pid, rep);
		n = convS2M(rep, mdata, sizeof mdata);
		if(n == 0)
			panic(1, "convS2M error on write");
		if(write(srvfd, mdata, n) != n)
			panic(1, "mount write");
		if(nerr_lab != 0)
			panic(0, "err stack %d");
	}
	chat("server shut down");
}
Пример #18
0
Файл: srv.c Проект: npe9/harvey
void
respond(Req *r, char *error)
{
	int i, m, n;
	char errbuf[ERRMAX];
	Srv *srv;

	srv = r->srv;
	assert(srv != nil);

	assert(r->responded == 0);
	r->error = error;

	switch(r->ifcall.type){
	default:
		assert(0);
	/*
	 * Flush is special.  If the handler says so, we return
	 * without further processing.  Respond will be called
	 * again once it is safe.
	 */
	case Tflush:
		if(rflush(r, error)<0)
			return;
		break;
	case Tversion:	rversion(r, error);	break;
	case Tauth:	rauth(r, error);	break;
	case Tattach:	rattach(r, error);	break;
	case Twalk:	rwalk(r, error);	break;
	case Topen:	ropen(r, error);	break;
	case Tcreate:	rcreate(r, error);	break;
	case Tread:	rread(r, error);	break;
	case Twrite:	rwrite(r, error);	break;
	case Tclunk:	rclunk(r, error);	break;
	case Tremove:	rremove(r, error, errbuf);	break;
	case Tstat:	rstat(r, error);	break;
	case Twstat:	rwstat(r, error);	break;
	}

	r->ofcall.tag = r->ifcall.tag;
	r->ofcall.type = r->ifcall.type+1;
	if(r->error)
		setfcallerror(&r->ofcall, r->error);

if(chatty9p)
	fprint(2, "-%d-> %F\n", srv->outfd, &r->ofcall);

	qlock(&srv->wlock);
	n = convS2M(&r->ofcall, srv->wbuf, srv->msize);
	if(n <= 0){
		fprint(2, "n = %d %F\n", n, &r->ofcall);
		abort();
	}
	assert(n > 2);
	if(r->pool)	/* not a fake */
		closereq(removereq(r->pool, r->ifcall.tag));
	m = write(srv->outfd, srv->wbuf, n);
	if(m != n)
		sysfatal("lib9p srv: write %d returned %d on fd %d: %r", n, m, srv->outfd);
	qunlock(&srv->wlock);

	qlock(&r->lk);	/* no one will add flushes now */
	r->responded = 1;
	qunlock(&r->lk);

	for(i=0; i<r->nflush; i++)
		respond(r->flush[i], nil);
	free(r->flush);
	r->flush = nil;
	r->nflush = 0;

	if(r->pool)
		closereq(r);
	else
		free(r);
}