summaryrefslogtreecommitdiff
path: root/lib/fuse_lowlevel.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/fuse_lowlevel.c')
-rw-r--r--lib/fuse_lowlevel.c84
1 files changed, 75 insertions, 9 deletions
diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c
index 7d76309..8fe47db 100644
--- a/lib/fuse_lowlevel.c
+++ b/lib/fuse_lowlevel.c
@@ -186,8 +186,15 @@ static int fuse_send_msg(struct fuse_session *se, struct fuse_chan *ch,
}
}
- ssize_t res = writev(ch ? ch->fd : se->fd,
- iov, count);
+ ssize_t res;
+ if (se->io != NULL)
+ /* se->io->writev is never NULL if se->io is not NULL as
+ specified by fuse_session_custom_io()*/
+ res = se->io->writev(ch ? ch->fd : se->fd, iov, count,
+ se->userdata);
+ else
+ res = writev(ch ? ch->fd : se->fd, iov, count);
+
int err = errno;
if (res == -1) {
@@ -817,8 +824,14 @@ static int fuse_send_data_iov(struct fuse_session *se, struct fuse_chan *ch,
(se->conn.want & FUSE_CAP_SPLICE_MOVE))
splice_flags |= SPLICE_F_MOVE;
- res = splice(llp->pipe[0], NULL, ch ? ch->fd : se->fd,
- NULL, out->len, splice_flags);
+ if (se->io != NULL && se->io->splice_send != NULL) {
+ res = se->io->splice_send(llp->pipe[0], NULL,
+ ch ? ch->fd : se->fd, NULL, out->len,
+ splice_flags, se->userdata);
+ } else {
+ res = splice(llp->pipe[0], NULL, ch ? ch->fd : se->fd, NULL,
+ out->len, splice_flags);
+ }
if (res == -1) {
res = -errno;
perror("fuse: splice from pipe");
@@ -2000,9 +2013,13 @@ void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
if (se->conn.proto_minor >= 14) {
#ifdef HAVE_SPLICE
#ifdef HAVE_VMSPLICE
- se->conn.capable |= FUSE_CAP_SPLICE_WRITE | FUSE_CAP_SPLICE_MOVE;
+ if ((se->io == NULL) || (se->io->splice_send != NULL)) {
+ se->conn.capable |= FUSE_CAP_SPLICE_WRITE | FUSE_CAP_SPLICE_MOVE;
+ }
#endif
- se->conn.capable |= FUSE_CAP_SPLICE_READ;
+ if ((se->io == NULL) || (se->io->splice_receive != NULL)) {
+ se->conn.capable |= FUSE_CAP_SPLICE_READ;
+ }
#endif
}
if (se->conn.proto_minor >= 18)
@@ -2755,6 +2772,8 @@ void fuse_session_destroy(struct fuse_session *se)
free(se->cuse_data);
if (se->fd != -1)
close(se->fd);
+ if (se->io != NULL)
+ free(se->io);
destroy_mount_opts(se->mo);
free(se);
}
@@ -2804,8 +2823,14 @@ int fuse_session_receive_buf_int(struct fuse_session *se, struct fuse_buf *buf,
goto fallback;
}
- res = splice(ch ? ch->fd : se->fd,
- NULL, llp->pipe[1], NULL, bufsize, 0);
+ if (se->io != NULL && se->io->splice_receive != NULL) {
+ res = se->io->splice_receive(ch ? ch->fd : se->fd, NULL,
+ llp->pipe[1], NULL, bufsize, 0,
+ se->userdata);
+ } else {
+ res = splice(ch ? ch->fd : se->fd, NULL, llp->pipe[1], NULL,
+ bufsize, 0);
+ }
err = errno;
if (fuse_session_exited(se))
@@ -2891,7 +2916,14 @@ fallback:
}
restart:
- res = read(ch ? ch->fd : se->fd, buf->mem, se->bufsize);
+ if (se->io != NULL) {
+ /* se->io->read is never NULL if se->io is not NULL as
+ specified by fuse_session_custom_io()*/
+ res = se->io->read(ch ? ch->fd : se->fd, buf->mem, se->bufsize,
+ se->userdata);
+ } else {
+ res = read(ch ? ch->fd : se->fd, buf->mem, se->bufsize);
+ }
err = errno;
if (fuse_session_exited(se))
@@ -3021,6 +3053,40 @@ out1:
return NULL;
}
+int fuse_session_custom_io(struct fuse_session *se, const struct fuse_custom_io *io,
+ int fd)
+{
+ if (fd < 0) {
+ fuse_log(FUSE_LOG_ERR, "Invalid file descriptor value %d passed to "
+ "fuse_session_custom_io()\n", fd);
+ return -EBADF;
+ }
+ if (io == NULL) {
+ fuse_log(FUSE_LOG_ERR, "No custom IO passed to "
+ "fuse_session_custom_io()\n");
+ return -EINVAL;
+ } else if (io->read == NULL || io->writev == NULL) {
+ /* If the user provides their own file descriptor, we can't
+ guarantee that the default behavior of the io operations made
+ in libfuse will function properly. Therefore, we enforce the
+ user to implement these io operations when using custom io. */
+ fuse_log(FUSE_LOG_ERR, "io passed to fuse_session_custom_io() must "
+ "implement both io->read() and io->writev\n");
+ return -EINVAL;
+ }
+
+ se->io = malloc(sizeof(struct fuse_custom_io));
+ if (se->io == NULL) {
+ fuse_log(FUSE_LOG_ERR, "Failed to allocate memory for custom io. "
+ "Error: %s\n", strerror(errno));
+ return -errno;
+ }
+
+ se->fd = fd;
+ *se->io = *io;
+ return 0;
+}
+
int fuse_session_mount(struct fuse_session *se, const char *mountpoint)
{
int fd;