xref: /plan9/sys/src/9/port/devdup.c (revision 4e3613ab15c331a9ada113286cc0f2a35bc0373d)
13e12c5d1SDavid du Colombier #include	"u.h"
23e12c5d1SDavid du Colombier #include	"../port/lib.h"
33e12c5d1SDavid du Colombier #include	"mem.h"
43e12c5d1SDavid du Colombier #include	"dat.h"
53e12c5d1SDavid du Colombier #include	"fns.h"
63e12c5d1SDavid du Colombier #include	"../port/error.h"
73e12c5d1SDavid du Colombier 
89a747e4fSDavid du Colombier /* Qid is (2*fd + (file is ctl))+1 */
99a747e4fSDavid du Colombier 
107dd7cddfSDavid du Colombier static int
dupgen(Chan * c,char *,Dirtab *,int,int s,Dir * dp)119a747e4fSDavid du Colombier dupgen(Chan *c, char *, Dirtab*, int, int s, Dir *dp)
123e12c5d1SDavid du Colombier {
137dd7cddfSDavid du Colombier 	Fgrp *fgrp = up->fgrp;
143e12c5d1SDavid du Colombier 	Chan *f;
153e12c5d1SDavid du Colombier 	static int perm[] = { 0400, 0200, 0600, 0 };
169a747e4fSDavid du Colombier 	int p;
179a747e4fSDavid du Colombier 	Qid q;
183e12c5d1SDavid du Colombier 
197dd7cddfSDavid du Colombier 	if(s == DEVDOTDOT){
209a747e4fSDavid du Colombier 		devdir(c, c->qid, ".", 0, eve, DMDIR|0555, dp);
217dd7cddfSDavid du Colombier 		return 1;
227dd7cddfSDavid du Colombier 	}
239a747e4fSDavid du Colombier 	if(s == 0)
243e12c5d1SDavid du Colombier 		return 0;
259a747e4fSDavid du Colombier 	s--;
269a747e4fSDavid du Colombier 	if(s/2 > fgrp->maxfd)
279a747e4fSDavid du Colombier 		return -1;
289a747e4fSDavid du Colombier 	if((f=fgrp->fd[s/2]) == nil)
299a747e4fSDavid du Colombier 		return 0;
309a747e4fSDavid du Colombier 	if(s & 1){
319a747e4fSDavid du Colombier 		p = 0400;
32*4e3613abSDavid du Colombier 		snprint(up->genbuf, sizeof up->genbuf, "%dctl", s/2);
339a747e4fSDavid du Colombier 	}else{
349a747e4fSDavid du Colombier 		p = perm[f->mode&3];
35*4e3613abSDavid du Colombier 		snprint(up->genbuf, sizeof up->genbuf, "%d", s/2);
369a747e4fSDavid du Colombier 	}
379a747e4fSDavid du Colombier 	mkqid(&q, s+1, 0, QTFILE);
389a747e4fSDavid du Colombier 	devdir(c, q, up->genbuf, 0, eve, p, dp);
393e12c5d1SDavid du Colombier 	return 1;
403e12c5d1SDavid du Colombier }
413e12c5d1SDavid du Colombier 
427dd7cddfSDavid du Colombier static Chan*
dupattach(char * spec)433e12c5d1SDavid du Colombier dupattach(char *spec)
443e12c5d1SDavid du Colombier {
453e12c5d1SDavid du Colombier 	return devattach('d', spec);
463e12c5d1SDavid du Colombier }
473e12c5d1SDavid du Colombier 
489a747e4fSDavid du Colombier static Walkqid*
dupwalk(Chan * c,Chan * nc,char ** name,int nname)499a747e4fSDavid du Colombier dupwalk(Chan *c, Chan *nc, char **name, int nname)
503e12c5d1SDavid du Colombier {
519a747e4fSDavid du Colombier 	return devwalk(c, nc, name, nname, (Dirtab *)0, 0, dupgen);
523e12c5d1SDavid du Colombier }
533e12c5d1SDavid du Colombier 
549a747e4fSDavid du Colombier static int
dupstat(Chan * c,uchar * db,int n)559a747e4fSDavid du Colombier dupstat(Chan *c, uchar *db, int n)
563e12c5d1SDavid du Colombier {
579a747e4fSDavid du Colombier 	return devstat(c, db, n, (Dirtab *)0, 0L, dupgen);
583e12c5d1SDavid du Colombier }
593e12c5d1SDavid du Colombier 
607dd7cddfSDavid du Colombier static Chan*
dupopen(Chan * c,int omode)613e12c5d1SDavid du Colombier dupopen(Chan *c, int omode)
623e12c5d1SDavid du Colombier {
633e12c5d1SDavid du Colombier 	Chan *f;
649a747e4fSDavid du Colombier 	int fd, twicefd;
653e12c5d1SDavid du Colombier 
669a747e4fSDavid du Colombier 	if(c->qid.type & QTDIR){
673e12c5d1SDavid du Colombier 		if(omode != 0)
683e12c5d1SDavid du Colombier 			error(Eisdir);
693e12c5d1SDavid du Colombier 		c->mode = 0;
703e12c5d1SDavid du Colombier 		c->flag |= COPEN;
713e12c5d1SDavid du Colombier 		c->offset = 0;
723e12c5d1SDavid du Colombier 		return c;
733e12c5d1SDavid du Colombier 	}
749a747e4fSDavid du Colombier 	if(c->qid.type & QTAUTH)
759a747e4fSDavid du Colombier 		error(Eperm);
769a747e4fSDavid du Colombier 	twicefd = c->qid.path - 1;
779a747e4fSDavid du Colombier 	fd = twicefd/2;
789a747e4fSDavid du Colombier 	if((twicefd & 1)){
799a747e4fSDavid du Colombier 		/* ctl file */
809a747e4fSDavid du Colombier 		f = c;
819a747e4fSDavid du Colombier 		f->mode = openmode(omode);
829a747e4fSDavid du Colombier 		f->flag |= COPEN;
839a747e4fSDavid du Colombier 		f->offset = 0;
849a747e4fSDavid du Colombier 	}else{
859a747e4fSDavid du Colombier 		/* fd file */
869a747e4fSDavid du Colombier 		f = fdtochan(fd, openmode(omode), 0, 1);
877dd7cddfSDavid du Colombier 		cclose(c);
889a747e4fSDavid du Colombier 	}
893e12c5d1SDavid du Colombier 	if(omode & OCEXEC)
903e12c5d1SDavid du Colombier 		f->flag |= CCEXEC;
913e12c5d1SDavid du Colombier 	return f;
923e12c5d1SDavid du Colombier }
933e12c5d1SDavid du Colombier 
947dd7cddfSDavid du Colombier static void
dupclose(Chan *)957dd7cddfSDavid du Colombier dupclose(Chan*)
963e12c5d1SDavid du Colombier {
973e12c5d1SDavid du Colombier }
983e12c5d1SDavid du Colombier 
997dd7cddfSDavid du Colombier static long
dupread(Chan * c,void * va,long n,vlong offset)1009a747e4fSDavid du Colombier dupread(Chan *c, void *va, long n, vlong offset)
1013e12c5d1SDavid du Colombier {
1023e12c5d1SDavid du Colombier 	char *a = va;
1039a747e4fSDavid du Colombier 	char buf[256];
1049a747e4fSDavid du Colombier 	int fd, twicefd;
1053e12c5d1SDavid du Colombier 
1069a747e4fSDavid du Colombier 	if(c->qid.type == QTDIR)
1073e12c5d1SDavid du Colombier 		return devdirread(c, a, n, (Dirtab *)0, 0L, dupgen);
1089a747e4fSDavid du Colombier 	twicefd = c->qid.path - 1;
1099a747e4fSDavid du Colombier 	fd = twicefd/2;
1109a747e4fSDavid du Colombier 	if(twicefd & 1){
1119a747e4fSDavid du Colombier 		c = fdtochan(fd, -1, 0, 1);
1129a747e4fSDavid du Colombier 		procfdprint(c, fd, 0, buf, sizeof buf);
1139a747e4fSDavid du Colombier 		cclose(c);
1149a747e4fSDavid du Colombier 		return readstr((ulong)offset, va, n, buf);
1159a747e4fSDavid du Colombier 	}
1169a747e4fSDavid du Colombier 	panic("dupread");
1179a747e4fSDavid du Colombier 	return 0;
1183e12c5d1SDavid du Colombier }
1193e12c5d1SDavid du Colombier 
1207dd7cddfSDavid du Colombier static long
dupwrite(Chan *,void *,long,vlong)1217dd7cddfSDavid du Colombier dupwrite(Chan*, void*, long, vlong)
1223e12c5d1SDavid du Colombier {
1238f5875f3SDavid du Colombier 	error(Eperm);
1243e12c5d1SDavid du Colombier 	return 0;		/* not reached */
1253e12c5d1SDavid du Colombier }
1267dd7cddfSDavid du Colombier 
1277dd7cddfSDavid du Colombier Dev dupdevtab = {
1287dd7cddfSDavid du Colombier 	'd',
1297dd7cddfSDavid du Colombier 	"dup",
1307dd7cddfSDavid du Colombier 
1317dd7cddfSDavid du Colombier 	devreset,
1327dd7cddfSDavid du Colombier 	devinit,
1339a747e4fSDavid du Colombier 	devshutdown,
1347dd7cddfSDavid du Colombier 	dupattach,
1357dd7cddfSDavid du Colombier 	dupwalk,
1367dd7cddfSDavid du Colombier 	dupstat,
1377dd7cddfSDavid du Colombier 	dupopen,
1387dd7cddfSDavid du Colombier 	devcreate,
1397dd7cddfSDavid du Colombier 	dupclose,
1407dd7cddfSDavid du Colombier 	dupread,
1417dd7cddfSDavid du Colombier 	devbread,
1427dd7cddfSDavid du Colombier 	dupwrite,
1437dd7cddfSDavid du Colombier 	devbwrite,
1447dd7cddfSDavid du Colombier 	devremove,
1457dd7cddfSDavid du Colombier 	devwstat,
1467dd7cddfSDavid du Colombier };
147