xref: /plan9-contrib/sys/src/9k/port/devdup.c (revision 406c76facc4b13aa2a55454bf4091aab9f03da22)
1 #include	"u.h"
2 #include	"../port/lib.h"
3 #include	"mem.h"
4 #include	"dat.h"
5 #include	"fns.h"
6 #include	"../port/error.h"
7 
8 /* Qid is (2*fd + (file is ctl))+1 */
9 
10 static int
dupgen(Chan * c,char *,Dirtab *,int,int s,Dir * dp)11 dupgen(Chan *c, char *, Dirtab*, int, int s, Dir *dp)
12 {
13 	Fgrp *fgrp = up->fgrp;
14 	Chan *f;
15 	static int perm[] = { 0400, 0200, 0600, 0 };
16 	int p;
17 	Qid q;
18 
19 	if(s == DEVDOTDOT){
20 		devdir(c, c->qid, ".", 0, eve, DMDIR|0555, dp);
21 		return 1;
22 	}
23 	if(s == 0)
24 		return 0;
25 	s--;
26 	if(s/2 > fgrp->maxfd)
27 		return -1;
28 	if((f=fgrp->fd[s/2]) == nil)
29 		return 0;
30 	if(s & 1){
31 		p = 0400;
32 		snprint(up->genbuf, sizeof up->genbuf, "%dctl", s/2);
33 	}else{
34 		p = perm[f->mode&3];
35 		snprint(up->genbuf, sizeof up->genbuf, "%d", s/2);
36 	}
37 	mkqid(&q, s+1, 0, QTFILE);
38 	devdir(c, q, up->genbuf, 0, eve, p, dp);
39 	return 1;
40 }
41 
42 static Chan*
dupattach(char * spec)43 dupattach(char *spec)
44 {
45 	return devattach('d', spec);
46 }
47 
48 static Walkqid*
dupwalk(Chan * c,Chan * nc,char ** name,int nname)49 dupwalk(Chan *c, Chan *nc, char **name, int nname)
50 {
51 	return devwalk(c, nc, name, nname, (Dirtab *)0, 0, dupgen);
52 }
53 
54 static long
dupstat(Chan * c,uchar * db,long n)55 dupstat(Chan *c, uchar *db, long n)
56 {
57 	return devstat(c, db, n, (Dirtab *)0, 0L, dupgen);
58 }
59 
60 static Chan*
dupopen(Chan * c,int omode)61 dupopen(Chan *c, int omode)
62 {
63 	Chan *f;
64 	int fd, twicefd;
65 
66 	if(c->qid.type & QTDIR){
67 		if(omode != 0)
68 			error(Eisdir);
69 		c->mode = 0;
70 		c->flag |= COPEN;
71 		c->offset = 0;
72 		return c;
73 	}
74 	if(c->qid.type & QTAUTH)
75 		error(Eperm);
76 	twicefd = c->qid.path - 1;
77 	fd = twicefd/2;
78 	if((twicefd & 1)){
79 		/* ctl file */
80 		f = c;
81 		f->mode = openmode(omode);
82 		f->flag |= COPEN;
83 		f->offset = 0;
84 	}else{
85 		/* fd file */
86 		f = fdtochan(fd, openmode(omode), 0, 1);
87 		cclose(c);
88 	}
89 	if(omode & OCEXEC)
90 		f->flag |= CCEXEC;
91 	return f;
92 }
93 
94 static void
dupclose(Chan *)95 dupclose(Chan*)
96 {
97 }
98 
99 static long
dupread(Chan * c,void * va,long n,vlong off)100 dupread(Chan *c, void *va, long n, vlong off)
101 {
102 	char buf[256];
103 	int fd, twicefd;
104 
105 	if(c->qid.type & QTDIR)
106 		return devdirread(c, va, n, (Dirtab *)0, 0L, dupgen);
107 	twicefd = c->qid.path - 1;
108 	fd = twicefd/2;
109 	if(twicefd & 1){
110 		c = fdtochan(fd, -1, 0, 1);
111 		procfdprint(c, fd, 0, buf, sizeof buf);
112 		cclose(c);
113 		return readstr(off, va, n, buf);
114 	}
115 	panic("dupread");
116 	return 0;
117 }
118 
119 static long
dupwrite(Chan *,void *,long,vlong)120 dupwrite(Chan*, void*, long, vlong)
121 {
122 	error(Eperm);
123 	return 0;		/* not reached */
124 }
125 
126 Dev dupdevtab = {
127 	'd',
128 	"dup",
129 
130 	devreset,
131 	devinit,
132 	devshutdown,
133 	dupattach,
134 	dupwalk,
135 	dupstat,
136 	dupopen,
137 	devcreate,
138 	dupclose,
139 	dupread,
140 	devbread,
141 	dupwrite,
142 	devbwrite,
143 	devremove,
144 	devwstat,
145 };
146