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