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