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.

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