devdup.c (2332B)
1 #include "u.h" 2 #include "lib.h" 3 #include "mem.h" 4 #include "dat.h" 5 #include "fns.h" 6 #include "error.h" 7 8 /* Qid is (2*fd + (file is ctl))+1 */ 9 10 static int 11 dupgen(Chan *c, char *name, Dirtab *dt, int ndt, 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 *c) 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 *c, void *v, long n, vlong o) 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 };