xref: /plan9/sys/src/9/port/devdup.c (revision ff8c3af2f44d95267f67219afa20ba82ff6cf7e4)
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
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 		sprint(up->genbuf, "%dctl", s/2);
33 	}else{
34 		p = perm[f->mode&3];
35 		sprint(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*
43 dupattach(char *spec)
44 {
45 	return devattach('d', spec);
46 }
47 
48 static Walkqid*
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
55 dupstat(Chan *c, uchar *db, int n)
56 {
57 	return devstat(c, db, n, (Dirtab *)0, 0L, dupgen);
58 }
59 
60 static Chan*
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
95 dupclose(Chan*)
96 {
97 }
98 
99 static long
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
121 dupwrite(Chan*, void*, long, vlong)
122 {
123 	panic("dupwrite");
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