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.

218 lines
4.2 KiB

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