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.

98 lines
2.1 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_lowlevel.h"
  8. #include "fuse_kernel.h"
  9. #include "fuse_i.h"
  10. #include <stdio.h>
  11. #include <errno.h>
  12. #include <unistd.h>
  13. #include <assert.h>
  14. static int fuse_kern_chan_receive(struct fuse_chan **chp, char *buf,
  15. size_t size)
  16. {
  17. struct fuse_chan *ch = *chp;
  18. int err;
  19. ssize_t res;
  20. struct fuse_session *se = fuse_chan_session(ch);
  21. assert(se != NULL);
  22. restart:
  23. res = read(fuse_chan_fd(ch), buf, size);
  24. err = errno;
  25. if (fuse_session_exited(se))
  26. return 0;
  27. if (res == -1) {
  28. /* ENOENT means the operation was interrupted, it's safe
  29. to restart */
  30. if (err == ENOENT)
  31. goto restart;
  32. if (err == ENODEV) {
  33. fuse_session_exit(se);
  34. return 0;
  35. }
  36. /* Errors occurring during normal operation: EINTR (read
  37. interrupted), EAGAIN (nonblocking I/O), ENODEV (filesystem
  38. umounted) */
  39. if (err != EINTR && err != EAGAIN)
  40. perror("fuse: reading device");
  41. return -err;
  42. }
  43. if ((size_t) res < sizeof(struct fuse_in_header)) {
  44. fprintf(stderr, "short read on fuse device\n");
  45. return -EIO;
  46. }
  47. return res;
  48. }
  49. static int fuse_kern_chan_send(struct fuse_chan *ch, const struct iovec iov[],
  50. size_t count)
  51. {
  52. if (iov) {
  53. ssize_t res = writev(fuse_chan_fd(ch), iov, count);
  54. int err = errno;
  55. if (res == -1) {
  56. struct fuse_session *se = fuse_chan_session(ch);
  57. assert(se != NULL);
  58. /* ENOENT means the operation was interrupted */
  59. if (!fuse_session_exited(se) && err != ENOENT)
  60. perror("fuse: writing device");
  61. return -err;
  62. }
  63. }
  64. return 0;
  65. }
  66. static void fuse_kern_chan_destroy(struct fuse_chan *ch)
  67. {
  68. int fd = fuse_chan_fd(ch);
  69. if (fd != -1)
  70. close(fd);
  71. }
  72. #define MIN_BUFSIZE 0x21000
  73. struct fuse_chan *fuse_kern_chan_new(int fd)
  74. {
  75. struct fuse_chan_ops op = {
  76. .receive = fuse_kern_chan_receive,
  77. .send = fuse_kern_chan_send,
  78. .destroy = fuse_kern_chan_destroy,
  79. };
  80. size_t bufsize = getpagesize() + 0x1000;
  81. bufsize = bufsize < MIN_BUFSIZE ? MIN_BUFSIZE : bufsize;
  82. return fuse_chan_new(&op, fd, bufsize, NULL);
  83. }