xref: /plan9-contrib/sys/src/9k/port/devdup.c (revision 406c76facc4b13aa2a55454bf4091aab9f03da22)
19ef1f84bSDavid du Colombier #include	"u.h"
29ef1f84bSDavid du Colombier #include	"../port/lib.h"
39ef1f84bSDavid du Colombier #include	"mem.h"
49ef1f84bSDavid du Colombier #include	"dat.h"
59ef1f84bSDavid du Colombier #include	"fns.h"
69ef1f84bSDavid du Colombier #include	"../port/error.h"
79ef1f84bSDavid du Colombier 
89ef1f84bSDavid du Colombier /* Qid is (2*fd + (file is ctl))+1 */
99ef1f84bSDavid du Colombier 
109ef1f84bSDavid du Colombier static int
dupgen(Chan * c,char *,Dirtab *,int,int s,Dir * dp)119ef1f84bSDavid du Colombier dupgen(Chan *c, char *, Dirtab*, int, int s, Dir *dp)
129ef1f84bSDavid du Colombier {
139ef1f84bSDavid du Colombier 	Fgrp *fgrp = up->fgrp;
149ef1f84bSDavid du Colombier 	Chan *f;
159ef1f84bSDavid du Colombier 	static int perm[] = { 0400, 0200, 0600, 0 };
169ef1f84bSDavid du Colombier 	int p;
179ef1f84bSDavid du Colombier 	Qid q;
189ef1f84bSDavid du Colombier 
199ef1f84bSDavid du Colombier 	if(s == DEVDOTDOT){
209ef1f84bSDavid du Colombier 		devdir(c, c->qid, ".", 0, eve, DMDIR|0555, dp);
219ef1f84bSDavid du Colombier 		return 1;
229ef1f84bSDavid du Colombier 	}
239ef1f84bSDavid du Colombier 	if(s == 0)
249ef1f84bSDavid du Colombier 		return 0;
259ef1f84bSDavid du Colombier 	s--;
269ef1f84bSDavid du Colombier 	if(s/2 > fgrp->maxfd)
279ef1f84bSDavid du Colombier 		return -1;
289ef1f84bSDavid du Colombier 	if((f=fgrp->fd[s/2]) == nil)
299ef1f84bSDavid du Colombier 		return 0;
309ef1f84bSDavid du Colombier 	if(s & 1){
319ef1f84bSDavid du Colombier 		p = 0400;
32*406c76faSDavid du Colombier 		snprint(up->genbuf, sizeof up->genbuf, "%dctl", s/2);
339ef1f84bSDavid du Colombier 	}else{
349ef1f84bSDavid du Colombier 		p = perm[f->mode&3];
35*406c76faSDavid du Colombier 		snprint(up->genbuf, sizeof up->genbuf, "%d", s/2);
369ef1f84bSDavid du Colombier 	}
379ef1f84bSDavid du Colombier 	mkqid(&q, s+1, 0, QTFILE);
389ef1f84bSDavid du Colombier 	devdir(c, q, up->genbuf, 0, eve, p, dp);
399ef1f84bSDavid du Colombier 	return 1;
409ef1f84bSDavid du Colombier }
419ef1f84bSDavid du Colombier 
429ef1f84bSDavid du Colombier static Chan*
dupattach(char * spec)439ef1f84bSDavid du Colombier dupattach(char *spec)
449ef1f84bSDavid du Colombier {
459ef1f84bSDavid du Colombier 	return devattach('d', spec);
469ef1f84bSDavid du Colombier }
479ef1f84bSDavid du Colombier 
489ef1f84bSDavid du Colombier static Walkqid*
dupwalk(Chan * c,Chan * nc,char ** name,int nname)499ef1f84bSDavid du Colombier dupwalk(Chan *c, Chan *nc, char **name, int nname)
509ef1f84bSDavid du Colombier {
519ef1f84bSDavid du Colombier 	return devwalk(c, nc, name, nname, (Dirtab *)0, 0, dupgen);
529ef1f84bSDavid du Colombier }
539ef1f84bSDavid du Colombier 
549ef1f84bSDavid du Colombier static long
dupstat(Chan * c,uchar * db,long n)559ef1f84bSDavid du Colombier dupstat(Chan *c, uchar *db, long n)
569ef1f84bSDavid du Colombier {
579ef1f84bSDavid du Colombier 	return devstat(c, db, n, (Dirtab *)0, 0L, dupgen);
589ef1f84bSDavid du Colombier }
599ef1f84bSDavid du Colombier 
609ef1f84bSDavid du Colombier static Chan*
dupopen(Chan * c,int omode)619ef1f84bSDavid du Colombier dupopen(Chan *c, int omode)
629ef1f84bSDavid du Colombier {
639ef1f84bSDavid du Colombier 	Chan *f;
649ef1f84bSDavid du Colombier 	int fd, twicefd;
659ef1f84bSDavid du Colombier 
669ef1f84bSDavid du Colombier 	if(c->qid.type & QTDIR){
679ef1f84bSDavid du Colombier 		if(omode != 0)
689ef1f84bSDavid du Colombier 			error(Eisdir);
699ef1f84bSDavid du Colombier 		c->mode = 0;
709ef1f84bSDavid du Colombier 		c->flag |= COPEN;
719ef1f84bSDavid du Colombier 		c->offset = 0;
729ef1f84bSDavid du Colombier 		return c;
739ef1f84bSDavid du Colombier 	}
749ef1f84bSDavid du Colombier 	if(c->qid.type & QTAUTH)
759ef1f84bSDavid du Colombier 		error(Eperm);
769ef1f84bSDavid du Colombier 	twicefd = c->qid.path - 1;
779ef1f84bSDavid du Colombier 	fd = twicefd/2;
789ef1f84bSDavid du Colombier 	if((twicefd & 1)){
799ef1f84bSDavid du Colombier 		/* ctl file */
809ef1f84bSDavid du Colombier 		f = c;
819ef1f84bSDavid du Colombier 		f->mode = openmode(omode);
829ef1f84bSDavid du Colombier 		f->flag |= COPEN;
839ef1f84bSDavid du Colombier 		f->offset = 0;
849ef1f84bSDavid du Colombier 	}else{
859ef1f84bSDavid du Colombier 		/* fd file */
869ef1f84bSDavid du Colombier 		f = fdtochan(fd, openmode(omode), 0, 1);
879ef1f84bSDavid du Colombier 		cclose(c);
889ef1f84bSDavid du Colombier 	}
899ef1f84bSDavid du Colombier 	if(omode & OCEXEC)
909ef1f84bSDavid du Colombier 		f->flag |= CCEXEC;
919ef1f84bSDavid du Colombier 	return f;
929ef1f84bSDavid du Colombier }
939ef1f84bSDavid du Colombier 
949ef1f84bSDavid du Colombier static void
dupclose(Chan *)959ef1f84bSDavid du Colombier dupclose(Chan*)
969ef1f84bSDavid du Colombier {
979ef1f84bSDavid du Colombier }
989ef1f84bSDavid du Colombier 
999ef1f84bSDavid du Colombier static long
dupread(Chan * c,void * va,long n,vlong off)1009ef1f84bSDavid du Colombier dupread(Chan *c, void *va, long n, vlong off)
1019ef1f84bSDavid du Colombier {
1029ef1f84bSDavid du Colombier 	char buf[256];
1039ef1f84bSDavid du Colombier 	int fd, twicefd;
1049ef1f84bSDavid du Colombier 
1059ef1f84bSDavid du Colombier 	if(c->qid.type & QTDIR)
1069ef1f84bSDavid du Colombier 		return devdirread(c, va, n, (Dirtab *)0, 0L, dupgen);
1079ef1f84bSDavid du Colombier 	twicefd = c->qid.path - 1;
1089ef1f84bSDavid du Colombier 	fd = twicefd/2;
1099ef1f84bSDavid du Colombier 	if(twicefd & 1){
1109ef1f84bSDavid du Colombier 		c = fdtochan(fd, -1, 0, 1);
1119ef1f84bSDavid du Colombier 		procfdprint(c, fd, 0, buf, sizeof buf);
1129ef1f84bSDavid du Colombier 		cclose(c);
1139ef1f84bSDavid du Colombier 		return readstr(off, va, n, buf);
1149ef1f84bSDavid du Colombier 	}
1159ef1f84bSDavid du Colombier 	panic("dupread");
1169ef1f84bSDavid du Colombier 	return 0;
1179ef1f84bSDavid du Colombier }
1189ef1f84bSDavid du Colombier 
1199ef1f84bSDavid du Colombier static long
dupwrite(Chan *,void *,long,vlong)1209ef1f84bSDavid du Colombier dupwrite(Chan*, void*, long, vlong)
1219ef1f84bSDavid du Colombier {
1229ef1f84bSDavid du Colombier 	error(Eperm);
1239ef1f84bSDavid du Colombier 	return 0;		/* not reached */
1249ef1f84bSDavid du Colombier }
1259ef1f84bSDavid du Colombier 
1269ef1f84bSDavid du Colombier Dev dupdevtab = {
1279ef1f84bSDavid du Colombier 	'd',
1289ef1f84bSDavid du Colombier 	"dup",
1299ef1f84bSDavid du Colombier 
1309ef1f84bSDavid du Colombier 	devreset,
1319ef1f84bSDavid du Colombier 	devinit,
1329ef1f84bSDavid du Colombier 	devshutdown,
1339ef1f84bSDavid du Colombier 	dupattach,
1349ef1f84bSDavid du Colombier 	dupwalk,
1359ef1f84bSDavid du Colombier 	dupstat,
1369ef1f84bSDavid du Colombier 	dupopen,
1379ef1f84bSDavid du Colombier 	devcreate,
1389ef1f84bSDavid du Colombier 	dupclose,
1399ef1f84bSDavid du Colombier 	dupread,
1409ef1f84bSDavid du Colombier 	devbread,
1419ef1f84bSDavid du Colombier 	dupwrite,
1429ef1f84bSDavid du Colombier 	devbwrite,
1439ef1f84bSDavid du Colombier 	devremove,
1449ef1f84bSDavid du Colombier 	devwstat,
1459ef1f84bSDavid du Colombier };
146