fix lookup Oops
[fuse.git] / lib / fuse_kern_chan.c
blob45ff738b845f671bc23164ce515628c943cf7cca
1 /*
2 FUSE: Filesystem in Userspace
3 Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
5 This program can be distributed under the terms of the GNU LGPL.
6 See the file COPYING.LIB
7 */
9 #include "fuse_lowlevel.h"
10 #include "fuse_kernel.h"
12 #include <stdio.h>
13 #include <errno.h>
14 #include <unistd.h>
15 #include <assert.h>
17 static int fuse_kern_chan_receive(struct fuse_chan **chp, char *buf,
18 size_t size)
20 struct fuse_chan *ch = *chp;
21 int err;
22 ssize_t res;
23 struct fuse_session *se = fuse_chan_session(ch);
24 assert(se != NULL);
26 restart:
27 res = read(fuse_chan_fd(ch), buf, size);
28 err = errno;
30 if (fuse_session_exited(se))
31 return 0;
32 if (res == -1) {
33 /* ENOENT means the operation was interrupted, it's safe
34 to restart */
35 if (err == ENOENT)
36 goto restart;
38 /* Errors occuring during normal operation: EINTR (read
39 interrupted), EAGAIN (nonblocking I/O), ENODEV (filesystem
40 umounted) */
41 if (err != EINTR && err != EAGAIN && err != ENODEV)
42 perror("fuse: reading device");
43 return -err;
45 if ((size_t) res < sizeof(struct fuse_in_header)) {
46 fprintf(stderr, "short read on fuse device\n");
47 return -EIO;
49 return res;
52 static int fuse_kern_chan_send(struct fuse_chan *ch, const struct iovec iov[],
53 size_t count)
55 if (iov) {
56 ssize_t res = writev(fuse_chan_fd(ch), iov, count);
57 int err = errno;
59 if (res == -1) {
60 struct fuse_session *se = fuse_chan_session(ch);
62 assert(se != NULL);
64 /* ENOENT means the operation was interrupted */
65 if (!fuse_session_exited(se) && err != ENOENT)
66 perror("fuse: writing device");
67 return -err;
70 return 0;
73 static void fuse_kern_chan_destroy(struct fuse_chan *ch)
75 close(fuse_chan_fd(ch));
78 #define MIN_BUFSIZE 0x21000
80 struct fuse_chan *fuse_kern_chan_new(int fd)
82 struct fuse_chan_ops op = {
83 .receive = fuse_kern_chan_receive,
84 .send = fuse_kern_chan_send,
85 .destroy = fuse_kern_chan_destroy,
87 size_t bufsize = getpagesize() + 0x1000;
88 bufsize = bufsize < MIN_BUFSIZE ? MIN_BUFSIZE : bufsize;
89 return fuse_chan_new(&op, fd, bufsize, NULL);