You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

217 lines
4.2 KiB

  1. /*
  2. FUSE: Filesystem in Userspace
  3. Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
  4. This program can be distributed under the terms of the GNU LGPLv2.
  5. See the file COPYING.LIB
  6. */
  7. #include "fuse_i.h"
  8. #include "fuse_misc.h"
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <assert.h>
  13. #include <errno.h>
  14. struct fuse_chan
  15. {
  16. struct fuse_chan_ops op;
  17. struct fuse_session *se;
  18. int fd;
  19. size_t bufsize;
  20. void *data;
  21. };
  22. struct fuse_session *fuse_session_new(struct fuse_session_ops *op, void *data)
  23. {
  24. struct fuse_session *se = (struct fuse_session *) malloc(sizeof(*se));
  25. if (se == NULL) {
  26. fprintf(stderr, "fuse: failed to allocate session\n");
  27. return NULL;
  28. }
  29. memset(se, 0, sizeof(*se));
  30. se->op = *op;
  31. se->data = data;
  32. return se;
  33. }
  34. void fuse_session_add_chan(struct fuse_session *se, struct fuse_chan *ch)
  35. {
  36. assert(se->ch == NULL);
  37. assert(ch->se == NULL);
  38. se->ch = ch;
  39. ch->se = se;
  40. }
  41. void fuse_session_remove_chan(struct fuse_chan *ch)
  42. {
  43. struct fuse_session *se = ch->se;
  44. if (se) {
  45. assert(se->ch == ch);
  46. se->ch = NULL;
  47. ch->se = NULL;
  48. }
  49. }
  50. struct fuse_chan *fuse_session_next_chan(struct fuse_session *se,
  51. struct fuse_chan *ch)
  52. {
  53. assert(ch == NULL || ch == se->ch);
  54. if (ch == NULL)
  55. return se->ch;
  56. else
  57. return NULL;
  58. }
  59. void fuse_session_process(struct fuse_session *se, const char *buf, size_t len,
  60. struct fuse_chan *ch)
  61. {
  62. se->op.process(se->data, buf, len, ch);
  63. }
  64. void fuse_session_process_buf(struct fuse_session *se,
  65. const struct fuse_buf *buf, struct fuse_chan *ch)
  66. {
  67. if (se->process_buf) {
  68. se->process_buf(se->data, buf, ch);
  69. } else {
  70. assert(!(buf->flags & FUSE_BUF_IS_FD));
  71. fuse_session_process(se->data, buf->mem, buf->size, ch);
  72. }
  73. }
  74. int fuse_session_receive_buf(struct fuse_session *se, struct fuse_buf *buf,
  75. struct fuse_chan **chp)
  76. {
  77. int res;
  78. if (se->receive_buf) {
  79. res = se->receive_buf(se, buf, chp);
  80. } else {
  81. res = fuse_chan_recv(chp, buf->mem, buf->size);
  82. if (res > 0)
  83. buf->size = res;
  84. }
  85. return res;
  86. }
  87. void fuse_session_destroy(struct fuse_session *se)
  88. {
  89. if (se->op.destroy)
  90. se->op.destroy(se->data);
  91. if (se->ch != NULL)
  92. fuse_chan_destroy(se->ch);
  93. free(se);
  94. }
  95. void fuse_session_exit(struct fuse_session *se)
  96. {
  97. if (se->op.exit)
  98. se->op.exit(se->data, 1);
  99. se->exited = 1;
  100. }
  101. void fuse_session_reset(struct fuse_session *se)
  102. {
  103. if (se->op.exit)
  104. se->op.exit(se->data, 0);
  105. se->exited = 0;
  106. }
  107. int fuse_session_exited(struct fuse_session *se)
  108. {
  109. if (se->op.exited)
  110. return se->op.exited(se->data);
  111. else
  112. return se->exited;
  113. }
  114. void *fuse_session_data(struct fuse_session *se)
  115. {
  116. return se->data;
  117. }
  118. static struct fuse_chan *fuse_chan_new_common(struct fuse_chan_ops *op, int fd,
  119. size_t bufsize, void *data)
  120. {
  121. struct fuse_chan *ch = (struct fuse_chan *) malloc(sizeof(*ch));
  122. if (ch == NULL) {
  123. fprintf(stderr, "fuse: failed to allocate channel\n");
  124. return NULL;
  125. }
  126. memset(ch, 0, sizeof(*ch));
  127. ch->op = *op;
  128. ch->fd = fd;
  129. ch->bufsize = bufsize;
  130. ch->data = data;
  131. return ch;
  132. }
  133. struct fuse_chan *fuse_chan_new(struct fuse_chan_ops *op, int fd,
  134. size_t bufsize, void *data)
  135. {
  136. return fuse_chan_new_common(op, fd, bufsize, data);
  137. }
  138. int fuse_chan_fd(struct fuse_chan *ch)
  139. {
  140. return ch->fd;
  141. }
  142. int fuse_chan_clearfd(struct fuse_chan *ch)
  143. {
  144. int fd = ch->fd;
  145. ch->fd = -1;
  146. return fd;
  147. }
  148. size_t fuse_chan_bufsize(struct fuse_chan *ch)
  149. {
  150. return ch->bufsize;
  151. }
  152. void *fuse_chan_data(struct fuse_chan *ch)
  153. {
  154. return ch->data;
  155. }
  156. struct fuse_session *fuse_chan_session(struct fuse_chan *ch)
  157. {
  158. return ch->se;
  159. }
  160. int fuse_chan_recv(struct fuse_chan **chp, char *buf, size_t size)
  161. {
  162. struct fuse_chan *ch = *chp;
  163. return ch->op.receive(chp, buf, size);
  164. }
  165. int fuse_chan_receive(struct fuse_chan *ch, char *buf, size_t size)
  166. {
  167. int res;
  168. res = fuse_chan_recv(&ch, buf, size);
  169. return res >= 0 ? res : (res != -EINTR && res != -EAGAIN) ? -1 : 0;
  170. }
  171. int fuse_chan_send(struct fuse_chan *ch, const struct iovec iov[], size_t count)
  172. {
  173. return ch->op.send(ch, iov, count);
  174. }
  175. void fuse_chan_destroy(struct fuse_chan *ch)
  176. {
  177. fuse_session_remove_chan(ch);
  178. if (ch->op.destroy)
  179. ch->op.destroy(ch);
  180. free(ch);
  181. }