1 #include "dat.h" 2 #include "fns.h" 3 #include "error.h" 4 #include "interp.h" 5 6 /* Qid is (2*fd + (file is ctl))+1 */ 7 8 static int 9 dupgen(Chan *c, char *name, Dirtab *tab, int ntab, int s, Dir *dp) 10 { 11 Fgrp *fgrp = up->env->fgrp; 12 Chan *f; 13 static int perm[] = { 0400, 0200, 0600, 0 }; 14 int p; 15 Qid q; 16 17 USED(name); USED(tab); USED(ntab); 18 if(s == DEVDOTDOT){ 19 devdir(c, c->qid, ".", 0, eve, DMDIR|0555, dp); 20 return 1; 21 } 22 if(s == 0) 23 return 0; 24 s--; 25 if(s/2 > fgrp->maxfd) 26 return -1; 27 if((f=fgrp->fd[s/2]) == nil) 28 return 0; 29 if(s & 1){ 30 p = 0400; 31 sprint(up->genbuf, "%dctl", s/2); 32 }else{ 33 p = perm[f->mode&3]; 34 sprint(up->genbuf, "%d", s/2); 35 } 36 mkqid(&q, s+1, 0, QTFILE); 37 devdir(c, q, up->genbuf, 0, eve, p, dp); 38 return 1; 39 } 40 41 static Chan* 42 dupattach(char *spec) 43 { 44 return devattach('d', spec); 45 } 46 47 static Walkqid* 48 dupwalk(Chan *c, Chan *nc, char **name, int nname) 49 { 50 return devwalk(c, nc, name, nname, nil, 0, dupgen); 51 } 52 53 static int 54 dupstat(Chan *c, uchar *db, int n) 55 { 56 return devstat(c, db, n, nil, 0, dupgen); 57 } 58 59 static Chan* 60 dupopen(Chan *c, int omode) 61 { 62 Chan *f; 63 int fd, twicefd; 64 65 if(c->qid.type & QTDIR){ 66 if(omode != 0) 67 error(Eisdir); 68 c->mode = 0; 69 c->flag |= COPEN; 70 c->offset = 0; 71 return c; 72 } 73 if(c->qid.type & QTAUTH) 74 error(Eperm); 75 twicefd = c->qid.path - 1; 76 fd = twicefd/2; 77 if((twicefd & 1)){ 78 /* ctl file */ 79 f = c; 80 f->mode = openmode(omode); 81 f->flag |= COPEN; 82 f->offset = 0; 83 }else{ 84 /* fd file */ 85 f = fdtochan(up->env->fgrp, fd, openmode(omode), 0, 1); 86 cclose(c); 87 } 88 if(omode & OCEXEC) 89 f->flag |= CCEXEC; 90 return f; 91 } 92 93 static void 94 dupclose(Chan *c) 95 { 96 USED(c); 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 *c, void *a, long n, vlong o) 127 { 128 USED(c); USED(a); USED(n); USED(o); 129 panic("dupwrite"); 130 return 0; /* not reached */ 131 } 132 133 Dev dupdevtab = { 134 'd', 135 "dup", 136 137 devinit, 138 dupattach, 139 dupwalk, 140 dupstat, 141 dupopen, 142 devcreate, 143 dupclose, 144 dupread, 145 devbread, 146 dupwrite, 147 devbwrite, 148 devremove, 149 devwstat, 150 }; 151