]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/port/devdup.c
kernel: use 64-bit virtual entry point for expanded header, document behaviour in...
[plan9front.git] / sys / src / 9 / 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, 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(omode & ORCLOSE)
67                 error(Eperm);
68         if(c->qid.type & QTDIR){
69                 if(omode != 0)
70                         error(Eisdir);
71                 c->mode = 0;
72                 c->flag |= COPEN;
73                 c->offset = 0;
74                 return c;
75         }
76         if(c->qid.type & QTAUTH)
77                 error(Eperm);
78         twicefd = c->qid.path - 1;
79         fd = twicefd/2;
80         if((twicefd & 1)){
81                 /* ctl file */
82                 f = c;
83                 f->mode = openmode(omode);
84                 f->flag |= COPEN;
85                 f->offset = 0;
86         }else{
87                 /* fd file */
88                 f = fdtochan(fd, openmode(omode), 0, 1);
89                 cclose(c);
90         }
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, 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 };