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