FreeBSD/Linux Kernel Cross Reference
sys/port/devdup.c
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 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 };
Cache object: e00e1793e131e06466192dcb70dce197
|