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->env->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, nil, 0, dupgen); 52 } 53 54 static int 55 dupstat(Chan *c, uchar *db, int n) 56 { 57 return devstat(c, db, n, nil, 0, 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(up->env->fgrp, 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, 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*, void*, long, vlong) 127 { 128 panic("dupwrite"); 129 return 0; /* not reached */ 130 } 131 132 Dev dupdevtab = { 133 'd', 134 "dup", 135 136 devreset, 137 devinit, 138 devshutdown, 139 dupattach, 140 dupwalk, 141 dupstat, 142 dupopen, 143 devcreate, 144 dupclose, 145 dupread, 146 devbread, 147 dupwrite, 148 devbwrite, 149 devremove, 150 devwstat, 151 }; 152