xref: /plan9/sys/src/9/port/devdup.c (revision 4e3613ab15c331a9ada113286cc0f2a35bc0373d)
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 int
dupstat(Chan * c,uchar * db,int n)55 dupstat(Chan *c, uchar *db, int 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 offset)100 dupread(Chan *c, void *va, long n, vlong offset)
101 {
102 	char *a = va;
103 	char buf[256];
104 	int fd, twicefd;
105 
106 	if(c->qid.type == QTDIR)
107 		return devdirread(c, a, n, (Dirtab *)0, 0L, dupgen);
108 	twicefd = c->qid.path - 1;
109 	fd = twicefd/2;
110 	if(twicefd & 1){
111 		c = fdtochan(fd, -1, 0, 1);
112 		procfdprint(c, fd, 0, buf, sizeof buf);
113 		cclose(c);
114 		return readstr((ulong)offset, va, n, buf);
115 	}
116 	panic("dupread");
117 	return 0;
118 }
119 
120 static long
dupwrite(Chan *,void *,long,vlong)121 dupwrite(Chan*, void*, long, vlong)
122 {
123 	error(Eperm);
124 	return 0;		/* not reached */
125 }
126 
127 Dev dupdevtab = {
128 	'd',
129 	"dup",
130 
131 	devreset,
132 	devinit,
133 	devshutdown,
134 	dupattach,
135 	dupwalk,
136 	dupstat,
137 	dupopen,
138 	devcreate,
139 	dupclose,
140 	dupread,
141 	devbread,
142 	dupwrite,
143 	devbwrite,
144 	devremove,
145 	devwstat,
146 };
147