devdup.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "u.h"
  10. #include "../port/lib.h"
  11. #include "mem.h"
  12. #include "dat.h"
  13. #include "fns.h"
  14. #include "../port/error.h"
  15. /* Qid is (2*fd + (file is ctl))+1 */
  16. static int
  17. dupgen(Chan *c, char *d, Dirtab* dir, int mm, int s, Dir *dp)
  18. {
  19. Proc *up = externup();
  20. Fgrp *fgrp = up->fgrp;
  21. Chan *f;
  22. static int perm[] = { 0400, 0200, 0600, 0 };
  23. int p;
  24. Qid q;
  25. if(s == DEVDOTDOT){
  26. devdir(c, c->qid, ".", 0, eve, DMDIR|0555, dp);
  27. return 1;
  28. }
  29. if(s == 0)
  30. return 0;
  31. s--;
  32. if(s/2 > fgrp->maxfd)
  33. return -1;
  34. if((f=fgrp->fd[s/2]) == nil)
  35. return 0;
  36. if(s & 1){
  37. p = 0400;
  38. sprint(up->genbuf, "%dctl", s/2);
  39. }else{
  40. p = perm[f->mode&3];
  41. sprint(up->genbuf, "%d", s/2);
  42. }
  43. mkqid(&q, s+1, 0, QTFILE);
  44. devdir(c, q, up->genbuf, 0, eve, p, dp);
  45. return 1;
  46. }
  47. static Chan*
  48. dupattach(char *spec)
  49. {
  50. return devattach('d', spec);
  51. }
  52. static Walkqid*
  53. dupwalk(Chan *c, Chan *nc, char **name, int nname)
  54. {
  55. return devwalk(c, nc, name, nname, (Dirtab *)0, 0, dupgen);
  56. }
  57. static int32_t
  58. dupstat(Chan *c, uint8_t *db, int32_t n)
  59. {
  60. return devstat(c, db, n, (Dirtab *)0, 0L, dupgen);
  61. }
  62. static Chan*
  63. dupopen(Chan *c, int omode)
  64. {
  65. Chan *f;
  66. int fd, twicefd;
  67. if(c->qid.type & QTDIR){
  68. if(omode != 0)
  69. error(Eisdir);
  70. c->mode = 0;
  71. c->flag |= COPEN;
  72. c->offset = 0;
  73. return c;
  74. }
  75. if(c->qid.type & QTAUTH)
  76. error(Eperm);
  77. twicefd = c->qid.path - 1;
  78. fd = twicefd/2;
  79. if((twicefd & 1)){
  80. /* ctl file */
  81. f = c;
  82. f->mode = openmode(omode);
  83. f->flag |= COPEN;
  84. f->offset = 0;
  85. }else{
  86. /* fd file */
  87. f = fdtochan(fd, openmode(omode), 0, 1);
  88. cclose(c);
  89. }
  90. if(omode & OCEXEC)
  91. f->flag |= CCEXEC;
  92. return f;
  93. }
  94. static void
  95. dupclose(Chan* c)
  96. {
  97. }
  98. static int32_t
  99. dupread(Chan *c, void *va, int32_t n, int64_t off)
  100. {
  101. char buf[256];
  102. int fd, twicefd;
  103. if(c->qid.type & QTDIR)
  104. return devdirread(c, va, n, (Dirtab *)0, 0L, dupgen);
  105. twicefd = c->qid.path - 1;
  106. fd = twicefd/2;
  107. if(twicefd & 1){
  108. c = fdtochan(fd, -1, 0, 1);
  109. procfdprint(c, fd, 0, buf, sizeof buf);
  110. cclose(c);
  111. return readstr(off, va, n, buf);
  112. }
  113. panic("dupread");
  114. return 0;
  115. }
  116. static int32_t
  117. dupwrite(Chan* c, void* v, int32_t i, int64_t n)
  118. {
  119. error(Eperm);
  120. return 0; /* not reached */
  121. }
  122. Dev dupdevtab = {
  123. .dc = 'd',
  124. .name = "dup",
  125. .reset = devreset,
  126. .init = devinit,
  127. .shutdown = devshutdown,
  128. .attach = dupattach,
  129. .walk = dupwalk,
  130. .stat = dupstat,
  131. .open = dupopen,
  132. .create = devcreate,
  133. .close = dupclose,
  134. .read = dupread,
  135. .bread = devbread,
  136. .write = dupwrite,
  137. .bwrite = devbwrite,
  138. .remove = devremove,
  139. .wstat = devwstat,
  140. };