devdup.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  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 *, Dirtab*, int, int s, Dir *dp)
  18. {
  19. Fgrp *fgrp = up->fgrp;
  20. Chan *f;
  21. static int perm[] = { 0400, 0200, 0600, 0 };
  22. int p;
  23. Qid q;
  24. if(s == DEVDOTDOT){
  25. devdir(c, c->qid, ".", 0, eve, DMDIR|0555, dp);
  26. return 1;
  27. }
  28. if(s == 0)
  29. return 0;
  30. s--;
  31. if(s/2 > fgrp->maxfd)
  32. return -1;
  33. if((f=fgrp->fd[s/2]) == nil)
  34. return 0;
  35. if(s & 1){
  36. p = 0400;
  37. sprint(up->genbuf, "%dctl", s/2);
  38. }else{
  39. p = perm[f->mode&3];
  40. sprint(up->genbuf, "%d", s/2);
  41. }
  42. mkqid(&q, s+1, 0, QTFILE);
  43. devdir(c, q, up->genbuf, 0, eve, p, dp);
  44. return 1;
  45. }
  46. static Chan*
  47. dupattach(char *spec)
  48. {
  49. return devattach('d', spec);
  50. }
  51. static Walkqid*
  52. dupwalk(Chan *c, Chan *nc, char **name, int nname)
  53. {
  54. return devwalk(c, nc, name, nname, (Dirtab *)0, 0, dupgen);
  55. }
  56. static int32_t
  57. dupstat(Chan *c, uint8_t *db, int32_t n)
  58. {
  59. return devstat(c, db, n, (Dirtab *)0, 0L, dupgen);
  60. }
  61. static Chan*
  62. dupopen(Chan *c, int omode)
  63. {
  64. Chan *f;
  65. int fd, twicefd;
  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. static void
  94. dupclose(Chan*)
  95. {
  96. }
  97. static int32_t
  98. dupread(Chan *c, void *va, int32_t n, int64_t off)
  99. {
  100. char buf[256];
  101. int fd, twicefd;
  102. if(c->qid.type & QTDIR)
  103. return devdirread(c, va, n, (Dirtab *)0, 0L, dupgen);
  104. twicefd = c->qid.path - 1;
  105. fd = twicefd/2;
  106. if(twicefd & 1){
  107. c = fdtochan(fd, -1, 0, 1);
  108. procfdprint(c, fd, 0, buf, sizeof buf);
  109. cclose(c);
  110. return readstr(off, va, n, buf);
  111. }
  112. panic("dupread");
  113. return 0;
  114. }
  115. static int32_t
  116. dupwrite(Chan*, void*, int32_t, int64_t)
  117. {
  118. error(Eperm);
  119. return 0; /* not reached */
  120. }
  121. Dev dupdevtab = {
  122. 'd',
  123. "dup",
  124. devreset,
  125. devinit,
  126. devshutdown,
  127. dupattach,
  128. dupwalk,
  129. dupstat,
  130. dupopen,
  131. devcreate,
  132. dupclose,
  133. dupread,
  134. devbread,
  135. dupwrite,
  136. devbwrite,
  137. devremove,
  138. devwstat,
  139. };