fusermount: clean up do_mount() function
[fuse.git] / lib / fuse_lowlevel.c
bloba19d429fc51417f4d55797f6c8f10b7db316b1de
1 /*
2 FUSE: Filesystem in Userspace
3 Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
5 This program can be distributed under the terms of the GNU LGPLv2.
6 See the file COPYING.LIB
7 */
9 #define _GNU_SOURCE
11 #include "fuse_i.h"
12 #include "fuse_kernel.h"
13 #include "fuse_opt.h"
14 #include "fuse_misc.h"
15 #include "fuse_common_compat.h"
16 #include "fuse_lowlevel_compat.h"
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <stddef.h>
21 #include <string.h>
22 #include <unistd.h>
23 #include <limits.h>
24 #include <errno.h>
25 #include <assert.h>
27 #ifndef F_LINUX_SPECIFIC_BASE
28 #define F_LINUX_SPECIFIC_BASE 1024
29 #endif
30 #ifndef F_SETPIPE_SZ
31 #define F_SETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 7)
32 #endif
35 #define PARAM(inarg) (((char *)(inarg)) + sizeof(*(inarg)))
36 #define OFFSET_MAX 0x7fffffffffffffffLL
38 #define container_of(ptr, type, member) ({ \
39 const typeof( ((type *)0)->member ) *__mptr = (ptr); \
40 (type *)( (char *)__mptr - offsetof(type,member) );})
42 struct fuse_pollhandle {
43 uint64_t kh;
44 struct fuse_chan *ch;
45 struct fuse_ll *f;
48 static size_t pagesize;
50 static __attribute__((constructor)) void fuse_ll_init_pagesize(void)
52 pagesize = getpagesize();
55 static void convert_stat(const struct stat *stbuf, struct fuse_attr *attr)
57 attr->ino = stbuf->st_ino;
58 attr->mode = stbuf->st_mode;
59 attr->nlink = stbuf->st_nlink;
60 attr->uid = stbuf->st_uid;
61 attr->gid = stbuf->st_gid;
62 attr->rdev = stbuf->st_rdev;
63 attr->size = stbuf->st_size;
64 attr->blksize = stbuf->st_blksize;
65 attr->blocks = stbuf->st_blocks;
66 attr->atime = stbuf->st_atime;
67 attr->mtime = stbuf->st_mtime;
68 attr->ctime = stbuf->st_ctime;
69 attr->atimensec = ST_ATIM_NSEC(stbuf);
70 attr->mtimensec = ST_MTIM_NSEC(stbuf);
71 attr->ctimensec = ST_CTIM_NSEC(stbuf);
74 static void convert_attr(const struct fuse_setattr_in *attr, struct stat *stbuf)
76 stbuf->st_mode = attr->mode;
77 stbuf->st_uid = attr->uid;
78 stbuf->st_gid = attr->gid;
79 stbuf->st_size = attr->size;
80 stbuf->st_atime = attr->atime;
81 stbuf->st_mtime = attr->mtime;
82 ST_ATIM_NSEC_SET(stbuf, attr->atimensec);
83 ST_MTIM_NSEC_SET(stbuf, attr->mtimensec);
86 static size_t iov_length(const struct iovec *iov, size_t count)
88 size_t seg;
89 size_t ret = 0;
91 for (seg = 0; seg < count; seg++)
92 ret += iov[seg].iov_len;
93 return ret;
96 static void list_init_req(struct fuse_req *req)
98 req->next = req;
99 req->prev = req;
102 static void list_del_req(struct fuse_req *req)
104 struct fuse_req *prev = req->prev;
105 struct fuse_req *next = req->next;
106 prev->next = next;
107 next->prev = prev;
110 static void list_add_req(struct fuse_req *req, struct fuse_req *next)
112 struct fuse_req *prev = next->prev;
113 req->next = next;
114 req->prev = prev;
115 prev->next = req;
116 next->prev = req;
119 static void destroy_req(fuse_req_t req)
121 pthread_mutex_destroy(&req->lock);
122 free(req);
125 void fuse_free_req(fuse_req_t req)
127 int ctr;
128 struct fuse_ll *f = req->f;
130 pthread_mutex_lock(&f->lock);
131 req->u.ni.func = NULL;
132 req->u.ni.data = NULL;
133 list_del_req(req);
134 ctr = --req->ctr;
135 pthread_mutex_unlock(&f->lock);
136 if (!ctr)
137 destroy_req(req);
140 static int fuse_send_msg(struct fuse_ll *f, struct fuse_chan *ch,
141 struct iovec *iov, int count)
143 struct fuse_out_header *out = iov[0].iov_base;
145 out->len = iov_length(iov, count);
146 if (f->debug) {
147 if (out->unique == 0) {
148 fprintf(stderr, "NOTIFY: code=%d length=%u\n",
149 out->error, out->len);
150 } else if (out->error) {
151 fprintf(stderr,
152 " unique: %llu, error: %i (%s), outsize: %i\n",
153 (unsigned long long) out->unique, out->error,
154 strerror(-out->error), out->len);
155 } else {
156 fprintf(stderr,
157 " unique: %llu, success, outsize: %i\n",
158 (unsigned long long) out->unique, out->len);
162 return fuse_chan_send(ch, iov, count);
165 int fuse_send_reply_iov_nofree(fuse_req_t req, int error, struct iovec *iov,
166 int count)
168 struct fuse_out_header out;
170 if (error <= -1000 || error > 0) {
171 fprintf(stderr, "fuse: bad error value: %i\n", error);
172 error = -ERANGE;
175 out.unique = req->unique;
176 out.error = error;
178 iov[0].iov_base = &out;
179 iov[0].iov_len = sizeof(struct fuse_out_header);
181 return fuse_send_msg(req->f, req->ch, iov, count);
184 static int send_reply_iov(fuse_req_t req, int error, struct iovec *iov,
185 int count)
187 int res;
189 res = fuse_send_reply_iov_nofree(req, error, iov, count);
190 fuse_free_req(req);
191 return res;
194 static int send_reply(fuse_req_t req, int error, const void *arg,
195 size_t argsize)
197 struct iovec iov[2];
198 int count = 1;
199 if (argsize) {
200 iov[1].iov_base = (void *) arg;
201 iov[1].iov_len = argsize;
202 count++;
204 return send_reply_iov(req, error, iov, count);
207 int fuse_reply_iov(fuse_req_t req, const struct iovec *iov, int count)
209 int res;
210 struct iovec *padded_iov;
212 padded_iov = malloc((count + 1) * sizeof(struct iovec));
213 if (padded_iov == NULL)
214 return fuse_reply_err(req, ENOMEM);
216 memcpy(padded_iov + 1, iov, count * sizeof(struct iovec));
217 count++;
219 res = send_reply_iov(req, 0, padded_iov, count);
220 free(padded_iov);
222 return res;
225 size_t fuse_dirent_size(size_t namelen)
227 return FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + namelen);
230 char *fuse_add_dirent(char *buf, const char *name, const struct stat *stbuf,
231 off_t off)
233 unsigned namelen = strlen(name);
234 unsigned entlen = FUSE_NAME_OFFSET + namelen;
235 unsigned entsize = fuse_dirent_size(namelen);
236 unsigned padlen = entsize - entlen;
237 struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
239 dirent->ino = stbuf->st_ino;
240 dirent->off = off;
241 dirent->namelen = namelen;
242 dirent->type = (stbuf->st_mode & 0170000) >> 12;
243 strncpy(dirent->name, name, namelen);
244 if (padlen)
245 memset(buf + entlen, 0, padlen);
247 return buf + entsize;
250 size_t fuse_add_direntry(fuse_req_t req, char *buf, size_t bufsize,
251 const char *name, const struct stat *stbuf, off_t off)
253 size_t entsize;
255 (void) req;
256 entsize = fuse_dirent_size(strlen(name));
257 if (entsize <= bufsize && buf)
258 fuse_add_dirent(buf, name, stbuf, off);
259 return entsize;
262 static void convert_statfs(const struct statvfs *stbuf,
263 struct fuse_kstatfs *kstatfs)
265 kstatfs->bsize = stbuf->f_bsize;
266 kstatfs->frsize = stbuf->f_frsize;
267 kstatfs->blocks = stbuf->f_blocks;
268 kstatfs->bfree = stbuf->f_bfree;
269 kstatfs->bavail = stbuf->f_bavail;
270 kstatfs->files = stbuf->f_files;
271 kstatfs->ffree = stbuf->f_ffree;
272 kstatfs->namelen = stbuf->f_namemax;
275 static int send_reply_ok(fuse_req_t req, const void *arg, size_t argsize)
277 return send_reply(req, 0, arg, argsize);
280 int fuse_reply_err(fuse_req_t req, int err)
282 return send_reply(req, -err, NULL, 0);
285 void fuse_reply_none(fuse_req_t req)
287 fuse_chan_send(req->ch, NULL, 0);
288 fuse_free_req(req);
291 static unsigned long calc_timeout_sec(double t)
293 if (t > (double) ULONG_MAX)
294 return ULONG_MAX;
295 else if (t < 0.0)
296 return 0;
297 else
298 return (unsigned long) t;
301 static unsigned int calc_timeout_nsec(double t)
303 double f = t - (double) calc_timeout_sec(t);
304 if (f < 0.0)
305 return 0;
306 else if (f >= 0.999999999)
307 return 999999999;
308 else
309 return (unsigned int) (f * 1.0e9);
312 static void fill_entry(struct fuse_entry_out *arg,
313 const struct fuse_entry_param *e)
315 arg->nodeid = e->ino;
316 arg->generation = e->generation;
317 arg->entry_valid = calc_timeout_sec(e->entry_timeout);
318 arg->entry_valid_nsec = calc_timeout_nsec(e->entry_timeout);
319 arg->attr_valid = calc_timeout_sec(e->attr_timeout);
320 arg->attr_valid_nsec = calc_timeout_nsec(e->attr_timeout);
321 convert_stat(&e->attr, &arg->attr);
324 static void fill_open(struct fuse_open_out *arg,
325 const struct fuse_file_info *f)
327 arg->fh = f->fh;
328 if (f->direct_io)
329 arg->open_flags |= FOPEN_DIRECT_IO;
330 if (f->keep_cache)
331 arg->open_flags |= FOPEN_KEEP_CACHE;
332 if (f->nonseekable)
333 arg->open_flags |= FOPEN_NONSEEKABLE;
336 int fuse_reply_entry(fuse_req_t req, const struct fuse_entry_param *e)
338 struct fuse_entry_out arg;
339 size_t size = req->f->conn.proto_minor < 9 ?
340 FUSE_COMPAT_ENTRY_OUT_SIZE : sizeof(arg);
342 /* before ABI 7.4 e->ino == 0 was invalid, only ENOENT meant
343 negative entry */
344 if (!e->ino && req->f->conn.proto_minor < 4)
345 return fuse_reply_err(req, ENOENT);
347 memset(&arg, 0, sizeof(arg));
348 fill_entry(&arg, e);
349 return send_reply_ok(req, &arg, size);
352 int fuse_reply_create(fuse_req_t req, const struct fuse_entry_param *e,
353 const struct fuse_file_info *f)
355 char buf[sizeof(struct fuse_entry_out) + sizeof(struct fuse_open_out)];
356 size_t entrysize = req->f->conn.proto_minor < 9 ?
357 FUSE_COMPAT_ENTRY_OUT_SIZE : sizeof(struct fuse_entry_out);
358 struct fuse_entry_out *earg = (struct fuse_entry_out *) buf;
359 struct fuse_open_out *oarg = (struct fuse_open_out *) (buf + entrysize);
361 memset(buf, 0, sizeof(buf));
362 fill_entry(earg, e);
363 fill_open(oarg, f);
364 return send_reply_ok(req, buf,
365 entrysize + sizeof(struct fuse_open_out));
368 int fuse_reply_attr(fuse_req_t req, const struct stat *attr,
369 double attr_timeout)
371 struct fuse_attr_out arg;
372 size_t size = req->f->conn.proto_minor < 9 ?
373 FUSE_COMPAT_ATTR_OUT_SIZE : sizeof(arg);
375 memset(&arg, 0, sizeof(arg));
376 arg.attr_valid = calc_timeout_sec(attr_timeout);
377 arg.attr_valid_nsec = calc_timeout_nsec(attr_timeout);
378 convert_stat(attr, &arg.attr);
380 return send_reply_ok(req, &arg, size);
383 int fuse_reply_readlink(fuse_req_t req, const char *linkname)
385 return send_reply_ok(req, linkname, strlen(linkname));
388 int fuse_reply_open(fuse_req_t req, const struct fuse_file_info *f)
390 struct fuse_open_out arg;
392 memset(&arg, 0, sizeof(arg));
393 fill_open(&arg, f);
394 return send_reply_ok(req, &arg, sizeof(arg));
397 int fuse_reply_write(fuse_req_t req, size_t count)
399 struct fuse_write_out arg;
401 memset(&arg, 0, sizeof(arg));
402 arg.size = count;
404 return send_reply_ok(req, &arg, sizeof(arg));
407 int fuse_reply_buf(fuse_req_t req, const char *buf, size_t size)
409 return send_reply_ok(req, buf, size);
412 struct fuse_ll_pipe {
413 size_t size;
414 int can_grow;
415 int pipe[2];
418 static void fuse_ll_pipe_free(struct fuse_ll_pipe *llp)
420 close(llp->pipe[0]);
421 close(llp->pipe[1]);
422 free(llp);
425 static struct fuse_ll_pipe *fuse_ll_get_pipe(struct fuse_ll *f)
427 struct fuse_ll_pipe *llp = pthread_getspecific(f->pipe_key);
428 if (llp == NULL) {
429 int res;
431 llp = malloc(sizeof(struct fuse_ll_pipe));
432 if (llp == NULL)
433 return NULL;
435 res = pipe(llp->pipe);
436 if (res == -1) {
437 free(llp);
438 return NULL;
441 if (fcntl(llp->pipe[0], F_SETFL, O_NONBLOCK) == -1 ||
442 fcntl(llp->pipe[1], F_SETFL, O_NONBLOCK) == -1) {
443 close(llp->pipe[0]);
444 close(llp->pipe[1]);
445 free(llp);
446 return NULL;
450 *the default size is 16 pages on linux
452 llp->size = pagesize * 16;
453 llp->can_grow = 1;
455 pthread_setspecific(f->pipe_key, llp);
458 return llp;
461 static void fuse_ll_clear_pipe(struct fuse_ll *f)
463 struct fuse_ll_pipe *llp = pthread_getspecific(f->pipe_key);
464 if (llp) {
465 pthread_setspecific(f->pipe_key, NULL);
466 fuse_ll_pipe_free(llp);
470 static int read_back(int fd, char *buf, size_t len)
472 int res;
474 res = read(fd, buf, len);
475 if (res == -1) {
476 fprintf(stderr, "fuse: internal error: failed to read back from pipe: %s\n", strerror(errno));
477 return -EIO;
479 if (res != len) {
480 fprintf(stderr, "fuse: internal error: short read back from pipe: %i from %zi\n", res, len);
481 return -EIO;
483 return 0;
486 static int fuse_send_data_iov(struct fuse_ll *f, struct fuse_chan *ch,
487 struct iovec *iov, int iov_count,
488 struct fuse_bufvec *buf, unsigned int flags)
490 int res;
491 size_t len = fuse_buf_size(buf);
492 struct fuse_out_header *out = iov[0].iov_base;
493 struct fuse_ll_pipe *llp;
494 int splice_flags;
495 size_t pipesize;
496 size_t total_fd_size;
497 size_t idx;
498 size_t headerlen;
499 struct fuse_bufvec pipe_buf = FUSE_BUFVEC_INIT(len);
501 if (f->broken_splice_nonblock)
502 goto fallback;
504 if (flags & FUSE_BUF_NO_SPLICE)
505 goto fallback;
507 total_fd_size = 0;
508 for (idx = buf->idx; idx < buf->count; idx++) {
509 if (buf->buf[idx].flags & FUSE_BUF_IS_FD) {
510 total_fd_size = buf->buf[idx].size;
511 if (idx == buf->idx)
512 total_fd_size -= buf->off;
515 if (total_fd_size < 2 * pagesize)
516 goto fallback;
518 if (f->conn.proto_minor < 14 ||
519 !(f->conn.want & FUSE_CAP_SPLICE_WRITE))
520 goto fallback;
522 llp = fuse_ll_get_pipe(f);
523 if (llp == NULL)
524 goto fallback;
527 headerlen = iov_length(iov, iov_count);
529 out->len = headerlen + len;
532 * Heuristic for the required pipe size, does not work if the
533 * source contains less than page size fragments
535 pipesize = pagesize * (iov_count + buf->count + 1) + out->len;
537 if (llp->size < pipesize) {
538 if (llp->can_grow) {
539 res = fcntl(llp->pipe[0], F_SETPIPE_SZ, pipesize);
540 if (res == -1) {
541 llp->can_grow = 0;
542 goto fallback;
544 llp->size = res;
546 if (llp->size < pipesize)
547 goto fallback;
551 res = vmsplice(llp->pipe[1], iov, iov_count, SPLICE_F_NONBLOCK);
552 if (res == -1)
553 goto fallback;
555 if (res != headerlen) {
556 res = -EIO;
557 fprintf(stderr, "fuse: short vmsplice to pipe: %u/%zu\n", res,
558 headerlen);
559 goto clear_pipe;
562 pipe_buf.buf[0].flags = FUSE_BUF_IS_FD;
563 pipe_buf.buf[0].fd = llp->pipe[1];
565 res = fuse_buf_copy(&pipe_buf, buf,
566 FUSE_BUF_FORCE_SPLICE | FUSE_BUF_SPLICE_NONBLOCK);
567 if (res < 0) {
568 if (res == -EAGAIN || res == -EINVAL) {
570 * Should only get EAGAIN on kernels with
571 * broken SPLICE_F_NONBLOCK support (<=
572 * 2.6.35) where this error or a short read is
573 * returned even if the pipe itself is not
574 * full
576 * EINVAL might mean that splice can't handle
577 * this combination of input and output.
579 if (res == -EAGAIN)
580 f->broken_splice_nonblock = 1;
582 pthread_setspecific(f->pipe_key, NULL);
583 fuse_ll_pipe_free(llp);
584 goto fallback;
586 res = -res;
587 goto clear_pipe;
590 if (res != 0 && res < len) {
591 struct fuse_bufvec mem_buf = FUSE_BUFVEC_INIT(len);
592 void *mbuf;
593 size_t now_len = res;
595 * For regular files a short count is either
596 * 1) due to EOF, or
597 * 2) because of broken SPLICE_F_NONBLOCK (see above)
599 * For other inputs it's possible that we overflowed
600 * the pipe because of small buffer fragments.
603 res = posix_memalign(&mbuf, pagesize, len);
604 if (res != 0)
605 goto clear_pipe;
607 mem_buf.buf[0].mem = mbuf;
608 mem_buf.off = now_len;
609 res = fuse_buf_copy(&mem_buf, buf, 0);
610 if (res > 0) {
611 char *tmpbuf;
612 size_t extra_len = res;
614 * Trickiest case: got more data. Need to get
615 * back the data from the pipe and then fall
616 * back to regular write.
618 tmpbuf = malloc(headerlen);
619 if (tmpbuf == NULL) {
620 free(mbuf);
621 res = ENOMEM;
622 goto clear_pipe;
624 res = read_back(llp->pipe[0], tmpbuf, headerlen);
625 if (res != 0) {
626 free(mbuf);
627 goto clear_pipe;
629 free(tmpbuf);
630 res = read_back(llp->pipe[0], mbuf, now_len);
631 if (res != 0) {
632 free(mbuf);
633 goto clear_pipe;
635 len = now_len + extra_len;
636 iov[iov_count].iov_base = mbuf;
637 iov[iov_count].iov_len = len;
638 iov_count++;
639 res = fuse_send_msg(f, ch, iov, iov_count);
640 free(mbuf);
641 return res;
643 free(mbuf);
644 res = now_len;
646 len = res;
647 out->len = headerlen + len;
649 if (f->debug) {
650 fprintf(stderr,
651 " unique: %llu, success, outsize: %i (splice)\n",
652 (unsigned long long) out->unique, out->len);
655 splice_flags = 0;
656 if ((flags & FUSE_BUF_SPLICE_MOVE) &&
657 (f->conn.want & FUSE_CAP_SPLICE_MOVE))
658 splice_flags |= SPLICE_F_MOVE;
660 res = splice(llp->pipe[0], NULL,
661 fuse_chan_fd(ch), NULL, out->len, splice_flags);
662 if (res == -1) {
663 res = -errno;
664 perror("fuse: splice from pipe");
665 goto clear_pipe;
667 if (res != out->len) {
668 res = -EIO;
669 fprintf(stderr, "fuse: short splice from pipe: %u/%u\n",
670 res, out->len);
671 goto clear_pipe;
673 return 0;
675 clear_pipe:
676 fuse_ll_clear_pipe(f);
677 return res;
679 fallback:
681 struct fuse_bufvec mem_buf = FUSE_BUFVEC_INIT(len);
682 void *mbuf;
684 res = posix_memalign(&mbuf, pagesize, len);
685 if (res != 0)
686 return res;
688 mem_buf.buf[0].mem = mbuf;
689 res = fuse_buf_copy(&mem_buf, buf, 0);
690 if (res < 0) {
691 free(mbuf);
692 return -res;
694 len = res;
696 iov[iov_count].iov_base = mbuf;
697 iov[iov_count].iov_len = len;
698 iov_count++;
699 res = fuse_send_msg(f, ch, iov, iov_count);
700 free(mbuf);
702 return res;
706 int fuse_reply_data(fuse_req_t req, struct fuse_bufvec *bufv,
707 enum fuse_buf_copy_flags flags)
709 struct iovec iov[2];
710 struct fuse_out_header out;
711 int res;
713 iov[0].iov_base = &out;
714 iov[0].iov_len = sizeof(struct fuse_out_header);
716 out.unique = req->unique;
717 out.error = 0;
719 res = fuse_send_data_iov(req->f, req->ch, iov, 1, bufv, flags);
720 if (res <= 0)
721 return res;
722 else
723 return fuse_reply_err(req, res);
726 int fuse_reply_statfs(fuse_req_t req, const struct statvfs *stbuf)
728 struct fuse_statfs_out arg;
729 size_t size = req->f->conn.proto_minor < 4 ?
730 FUSE_COMPAT_STATFS_SIZE : sizeof(arg);
732 memset(&arg, 0, sizeof(arg));
733 convert_statfs(stbuf, &arg.st);
735 return send_reply_ok(req, &arg, size);
738 int fuse_reply_xattr(fuse_req_t req, size_t count)
740 struct fuse_getxattr_out arg;
742 memset(&arg, 0, sizeof(arg));
743 arg.size = count;
745 return send_reply_ok(req, &arg, sizeof(arg));
748 int fuse_reply_lock(fuse_req_t req, struct flock *lock)
750 struct fuse_lk_out arg;
752 memset(&arg, 0, sizeof(arg));
753 arg.lk.type = lock->l_type;
754 if (lock->l_type != F_UNLCK) {
755 arg.lk.start = lock->l_start;
756 if (lock->l_len == 0)
757 arg.lk.end = OFFSET_MAX;
758 else
759 arg.lk.end = lock->l_start + lock->l_len - 1;
761 arg.lk.pid = lock->l_pid;
762 return send_reply_ok(req, &arg, sizeof(arg));
765 int fuse_reply_bmap(fuse_req_t req, uint64_t idx)
767 struct fuse_bmap_out arg;
769 memset(&arg, 0, sizeof(arg));
770 arg.block = idx;
772 return send_reply_ok(req, &arg, sizeof(arg));
775 int fuse_reply_ioctl_retry(fuse_req_t req,
776 const struct iovec *in_iov, size_t in_count,
777 const struct iovec *out_iov, size_t out_count)
779 struct fuse_ioctl_out arg;
780 struct iovec iov[4];
781 size_t count = 1;
783 memset(&arg, 0, sizeof(arg));
784 arg.flags |= FUSE_IOCTL_RETRY;
785 arg.in_iovs = in_count;
786 arg.out_iovs = out_count;
787 iov[count].iov_base = &arg;
788 iov[count].iov_len = sizeof(arg);
789 count++;
791 if (in_count) {
792 iov[count].iov_base = (void *)in_iov;
793 iov[count].iov_len = sizeof(in_iov[0]) * in_count;
794 count++;
797 if (out_count) {
798 iov[count].iov_base = (void *)out_iov;
799 iov[count].iov_len = sizeof(out_iov[0]) * out_count;
800 count++;
803 return send_reply_iov(req, 0, iov, count);
806 int fuse_reply_ioctl(fuse_req_t req, int result, const void *buf, size_t size)
808 struct fuse_ioctl_out arg;
809 struct iovec iov[3];
810 size_t count = 1;
812 memset(&arg, 0, sizeof(arg));
813 arg.result = result;
814 iov[count].iov_base = &arg;
815 iov[count].iov_len = sizeof(arg);
816 count++;
818 if (size) {
819 iov[count].iov_base = (char *) buf;
820 iov[count].iov_len = size;
821 count++;
824 return send_reply_iov(req, 0, iov, count);
827 int fuse_reply_ioctl_iov(fuse_req_t req, int result, const struct iovec *iov,
828 int count)
830 struct iovec *padded_iov;
831 struct fuse_ioctl_out arg;
832 int res;
834 padded_iov = malloc((count + 2) * sizeof(struct iovec));
835 if (padded_iov == NULL)
836 return fuse_reply_err(req, ENOMEM);
838 memset(&arg, 0, sizeof(arg));
839 arg.result = result;
840 padded_iov[1].iov_base = &arg;
841 padded_iov[1].iov_len = sizeof(arg);
843 memcpy(&padded_iov[2], iov, count * sizeof(struct iovec));
845 res = send_reply_iov(req, 0, padded_iov, count + 2);
846 free(padded_iov);
848 return res;
851 int fuse_reply_poll(fuse_req_t req, unsigned revents)
853 struct fuse_poll_out arg;
855 memset(&arg, 0, sizeof(arg));
856 arg.revents = revents;
858 return send_reply_ok(req, &arg, sizeof(arg));
861 static void do_lookup(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
863 char *name = (char *) inarg;
865 if (req->f->op.lookup)
866 req->f->op.lookup(req, nodeid, name);
867 else
868 fuse_reply_err(req, ENOSYS);
871 static void do_forget(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
873 struct fuse_forget_in *arg = (struct fuse_forget_in *) inarg;
875 if (req->f->op.forget)
876 req->f->op.forget(req, nodeid, arg->nlookup);
877 else
878 fuse_reply_none(req);
881 static void do_getattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
883 struct fuse_file_info *fip = NULL;
884 struct fuse_file_info fi;
886 if (req->f->conn.proto_minor >= 9) {
887 struct fuse_getattr_in *arg = (struct fuse_getattr_in *) inarg;
889 if (arg->getattr_flags & FUSE_GETATTR_FH) {
890 memset(&fi, 0, sizeof(fi));
891 fi.fh = arg->fh;
892 fi.fh_old = fi.fh;
893 fip = &fi;
897 if (req->f->op.getattr)
898 req->f->op.getattr(req, nodeid, fip);
899 else
900 fuse_reply_err(req, ENOSYS);
903 static void do_setattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
905 struct fuse_setattr_in *arg = (struct fuse_setattr_in *) inarg;
907 if (req->f->op.setattr) {
908 struct fuse_file_info *fi = NULL;
909 struct fuse_file_info fi_store;
910 struct stat stbuf;
911 memset(&stbuf, 0, sizeof(stbuf));
912 convert_attr(arg, &stbuf);
913 if (arg->valid & FATTR_FH) {
914 arg->valid &= ~FATTR_FH;
915 memset(&fi_store, 0, sizeof(fi_store));
916 fi = &fi_store;
917 fi->fh = arg->fh;
918 fi->fh_old = fi->fh;
920 arg->valid &=
921 FUSE_SET_ATTR_MODE |
922 FUSE_SET_ATTR_UID |
923 FUSE_SET_ATTR_GID |
924 FUSE_SET_ATTR_SIZE |
925 FUSE_SET_ATTR_ATIME |
926 FUSE_SET_ATTR_MTIME |
927 FUSE_SET_ATTR_ATIME_NOW |
928 FUSE_SET_ATTR_MTIME_NOW;
930 req->f->op.setattr(req, nodeid, &stbuf, arg->valid, fi);
931 } else
932 fuse_reply_err(req, ENOSYS);
935 static void do_access(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
937 struct fuse_access_in *arg = (struct fuse_access_in *) inarg;
939 if (req->f->op.access)
940 req->f->op.access(req, nodeid, arg->mask);
941 else
942 fuse_reply_err(req, ENOSYS);
945 static void do_readlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
947 (void) inarg;
949 if (req->f->op.readlink)
950 req->f->op.readlink(req, nodeid);
951 else
952 fuse_reply_err(req, ENOSYS);
955 static void do_mknod(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
957 struct fuse_mknod_in *arg = (struct fuse_mknod_in *) inarg;
958 char *name = PARAM(arg);
960 if (req->f->conn.proto_minor >= 12)
961 req->ctx.umask = arg->umask;
962 else
963 name = (char *) inarg + FUSE_COMPAT_MKNOD_IN_SIZE;
965 if (req->f->op.mknod)
966 req->f->op.mknod(req, nodeid, name, arg->mode, arg->rdev);
967 else
968 fuse_reply_err(req, ENOSYS);
971 static void do_mkdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
973 struct fuse_mkdir_in *arg = (struct fuse_mkdir_in *) inarg;
975 if (req->f->conn.proto_minor >= 12)
976 req->ctx.umask = arg->umask;
978 if (req->f->op.mkdir)
979 req->f->op.mkdir(req, nodeid, PARAM(arg), arg->mode);
980 else
981 fuse_reply_err(req, ENOSYS);
984 static void do_unlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
986 char *name = (char *) inarg;
988 if (req->f->op.unlink)
989 req->f->op.unlink(req, nodeid, name);
990 else
991 fuse_reply_err(req, ENOSYS);
994 static void do_rmdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
996 char *name = (char *) inarg;
998 if (req->f->op.rmdir)
999 req->f->op.rmdir(req, nodeid, name);
1000 else
1001 fuse_reply_err(req, ENOSYS);
1004 static void do_symlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1006 char *name = (char *) inarg;
1007 char *linkname = ((char *) inarg) + strlen((char *) inarg) + 1;
1009 if (req->f->op.symlink)
1010 req->f->op.symlink(req, linkname, nodeid, name);
1011 else
1012 fuse_reply_err(req, ENOSYS);
1015 static void do_rename(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1017 struct fuse_rename_in *arg = (struct fuse_rename_in *) inarg;
1018 char *oldname = PARAM(arg);
1019 char *newname = oldname + strlen(oldname) + 1;
1021 if (req->f->op.rename)
1022 req->f->op.rename(req, nodeid, oldname, arg->newdir, newname);
1023 else
1024 fuse_reply_err(req, ENOSYS);
1027 static void do_link(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1029 struct fuse_link_in *arg = (struct fuse_link_in *) inarg;
1031 if (req->f->op.link)
1032 req->f->op.link(req, arg->oldnodeid, nodeid, PARAM(arg));
1033 else
1034 fuse_reply_err(req, ENOSYS);
1037 static void do_create(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1039 struct fuse_create_in *arg = (struct fuse_create_in *) inarg;
1041 if (req->f->op.create) {
1042 struct fuse_file_info fi;
1043 char *name = PARAM(arg);
1045 memset(&fi, 0, sizeof(fi));
1046 fi.flags = arg->flags;
1048 if (req->f->conn.proto_minor >= 12)
1049 req->ctx.umask = arg->umask;
1050 else
1051 name = (char *) inarg + sizeof(struct fuse_open_in);
1053 req->f->op.create(req, nodeid, name, arg->mode, &fi);
1054 } else
1055 fuse_reply_err(req, ENOSYS);
1058 static void do_open(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1060 struct fuse_open_in *arg = (struct fuse_open_in *) inarg;
1061 struct fuse_file_info fi;
1063 memset(&fi, 0, sizeof(fi));
1064 fi.flags = arg->flags;
1066 if (req->f->op.open)
1067 req->f->op.open(req, nodeid, &fi);
1068 else
1069 fuse_reply_open(req, &fi);
1072 static void do_read(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1074 struct fuse_read_in *arg = (struct fuse_read_in *) inarg;
1076 if (req->f->op.read) {
1077 struct fuse_file_info fi;
1079 memset(&fi, 0, sizeof(fi));
1080 fi.fh = arg->fh;
1081 fi.fh_old = fi.fh;
1082 if (req->f->conn.proto_minor >= 9) {
1083 fi.lock_owner = arg->lock_owner;
1084 fi.flags = arg->flags;
1086 req->f->op.read(req, nodeid, arg->size, arg->offset, &fi);
1087 } else
1088 fuse_reply_err(req, ENOSYS);
1091 static void do_write(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1093 struct fuse_write_in *arg = (struct fuse_write_in *) inarg;
1094 struct fuse_file_info fi;
1095 char *param;
1097 memset(&fi, 0, sizeof(fi));
1098 fi.fh = arg->fh;
1099 fi.fh_old = fi.fh;
1100 fi.writepage = arg->write_flags & 1;
1102 if (req->f->conn.proto_minor < 9) {
1103 param = ((char *) arg) + FUSE_COMPAT_WRITE_IN_SIZE;
1104 } else {
1105 fi.lock_owner = arg->lock_owner;
1106 fi.flags = arg->flags;
1107 param = PARAM(arg);
1110 if (req->f->op.write)
1111 req->f->op.write(req, nodeid, param, arg->size,
1112 arg->offset, &fi);
1113 else
1114 fuse_reply_err(req, ENOSYS);
1117 static void do_write_buf(fuse_req_t req, fuse_ino_t nodeid, const void *inarg,
1118 const struct fuse_buf *ibuf)
1120 struct fuse_ll *f = req->f;
1121 struct fuse_bufvec bufv = {
1122 .buf[0] = *ibuf,
1123 .count = 1,
1125 struct fuse_write_in *arg = (struct fuse_write_in *) inarg;
1126 struct fuse_file_info fi;
1128 memset(&fi, 0, sizeof(fi));
1129 fi.fh = arg->fh;
1130 fi.fh_old = fi.fh;
1131 fi.writepage = arg->write_flags & 1;
1133 if (req->f->conn.proto_minor < 9) {
1134 bufv.buf[0].mem = ((char *) arg) + FUSE_COMPAT_WRITE_IN_SIZE;
1135 bufv.buf[0].size -= sizeof(struct fuse_in_header) +
1136 FUSE_COMPAT_WRITE_IN_SIZE;
1137 assert(!(bufv.buf[0].flags & FUSE_BUF_IS_FD));
1138 } else {
1139 fi.lock_owner = arg->lock_owner;
1140 fi.flags = arg->flags;
1141 if (!(bufv.buf[0].flags & FUSE_BUF_IS_FD))
1142 bufv.buf[0].mem = PARAM(arg);
1144 bufv.buf[0].size -= sizeof(struct fuse_in_header) +
1145 sizeof(struct fuse_write_in);
1147 if (bufv.buf[0].size < arg->size) {
1148 fprintf(stderr, "fuse: do_write_buf: buffer size too small\n");
1149 fuse_reply_err(req, EIO);
1150 goto out;
1152 bufv.buf[0].size = arg->size;
1154 req->f->op.write_buf(req, nodeid, &bufv, arg->offset, &fi);
1156 out:
1157 /* Need to reset the pipe if ->write_buf() didn't consume all data */
1158 if ((ibuf->flags & FUSE_BUF_IS_FD) && bufv.idx < bufv.count)
1159 fuse_ll_clear_pipe(f);
1162 static void do_flush(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1164 struct fuse_flush_in *arg = (struct fuse_flush_in *) inarg;
1165 struct fuse_file_info fi;
1167 memset(&fi, 0, sizeof(fi));
1168 fi.fh = arg->fh;
1169 fi.fh_old = fi.fh;
1170 fi.flush = 1;
1171 if (req->f->conn.proto_minor >= 7)
1172 fi.lock_owner = arg->lock_owner;
1174 if (req->f->op.flush)
1175 req->f->op.flush(req, nodeid, &fi);
1176 else
1177 fuse_reply_err(req, ENOSYS);
1180 static void do_release(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1182 struct fuse_release_in *arg = (struct fuse_release_in *) inarg;
1183 struct fuse_file_info fi;
1185 memset(&fi, 0, sizeof(fi));
1186 fi.flags = arg->flags;
1187 fi.fh = arg->fh;
1188 fi.fh_old = fi.fh;
1189 if (req->f->conn.proto_minor >= 8) {
1190 fi.flush = (arg->release_flags & FUSE_RELEASE_FLUSH) ? 1 : 0;
1191 fi.lock_owner = arg->lock_owner;
1194 if (req->f->op.release)
1195 req->f->op.release(req, nodeid, &fi);
1196 else
1197 fuse_reply_err(req, 0);
1200 static void do_fsync(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1202 struct fuse_fsync_in *arg = (struct fuse_fsync_in *) inarg;
1203 struct fuse_file_info fi;
1205 memset(&fi, 0, sizeof(fi));
1206 fi.fh = arg->fh;
1207 fi.fh_old = fi.fh;
1209 if (req->f->op.fsync)
1210 req->f->op.fsync(req, nodeid, arg->fsync_flags & 1, &fi);
1211 else
1212 fuse_reply_err(req, ENOSYS);
1215 static void do_opendir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1217 struct fuse_open_in *arg = (struct fuse_open_in *) inarg;
1218 struct fuse_file_info fi;
1220 memset(&fi, 0, sizeof(fi));
1221 fi.flags = arg->flags;
1223 if (req->f->op.opendir)
1224 req->f->op.opendir(req, nodeid, &fi);
1225 else
1226 fuse_reply_open(req, &fi);
1229 static void do_readdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1231 struct fuse_read_in *arg = (struct fuse_read_in *) inarg;
1232 struct fuse_file_info fi;
1234 memset(&fi, 0, sizeof(fi));
1235 fi.fh = arg->fh;
1236 fi.fh_old = fi.fh;
1238 if (req->f->op.readdir)
1239 req->f->op.readdir(req, nodeid, arg->size, arg->offset, &fi);
1240 else
1241 fuse_reply_err(req, ENOSYS);
1244 static void do_releasedir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1246 struct fuse_release_in *arg = (struct fuse_release_in *) inarg;
1247 struct fuse_file_info fi;
1249 memset(&fi, 0, sizeof(fi));
1250 fi.flags = arg->flags;
1251 fi.fh = arg->fh;
1252 fi.fh_old = fi.fh;
1254 if (req->f->op.releasedir)
1255 req->f->op.releasedir(req, nodeid, &fi);
1256 else
1257 fuse_reply_err(req, 0);
1260 static void do_fsyncdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1262 struct fuse_fsync_in *arg = (struct fuse_fsync_in *) inarg;
1263 struct fuse_file_info fi;
1265 memset(&fi, 0, sizeof(fi));
1266 fi.fh = arg->fh;
1267 fi.fh_old = fi.fh;
1269 if (req->f->op.fsyncdir)
1270 req->f->op.fsyncdir(req, nodeid, arg->fsync_flags & 1, &fi);
1271 else
1272 fuse_reply_err(req, ENOSYS);
1275 static void do_statfs(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1277 (void) nodeid;
1278 (void) inarg;
1280 if (req->f->op.statfs)
1281 req->f->op.statfs(req, nodeid);
1282 else {
1283 struct statvfs buf = {
1284 .f_namemax = 255,
1285 .f_bsize = 512,
1287 fuse_reply_statfs(req, &buf);
1291 static void do_setxattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1293 struct fuse_setxattr_in *arg = (struct fuse_setxattr_in *) inarg;
1294 char *name = PARAM(arg);
1295 char *value = name + strlen(name) + 1;
1297 if (req->f->op.setxattr)
1298 req->f->op.setxattr(req, nodeid, name, value, arg->size,
1299 arg->flags);
1300 else
1301 fuse_reply_err(req, ENOSYS);
1304 static void do_getxattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1306 struct fuse_getxattr_in *arg = (struct fuse_getxattr_in *) inarg;
1308 if (req->f->op.getxattr)
1309 req->f->op.getxattr(req, nodeid, PARAM(arg), arg->size);
1310 else
1311 fuse_reply_err(req, ENOSYS);
1314 static void do_listxattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1316 struct fuse_getxattr_in *arg = (struct fuse_getxattr_in *) inarg;
1318 if (req->f->op.listxattr)
1319 req->f->op.listxattr(req, nodeid, arg->size);
1320 else
1321 fuse_reply_err(req, ENOSYS);
1324 static void do_removexattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1326 char *name = (char *) inarg;
1328 if (req->f->op.removexattr)
1329 req->f->op.removexattr(req, nodeid, name);
1330 else
1331 fuse_reply_err(req, ENOSYS);
1334 static void convert_fuse_file_lock(struct fuse_file_lock *fl,
1335 struct flock *flock)
1337 memset(flock, 0, sizeof(struct flock));
1338 flock->l_type = fl->type;
1339 flock->l_whence = SEEK_SET;
1340 flock->l_start = fl->start;
1341 if (fl->end == OFFSET_MAX)
1342 flock->l_len = 0;
1343 else
1344 flock->l_len = fl->end - fl->start + 1;
1345 flock->l_pid = fl->pid;
1348 static void do_getlk(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1350 struct fuse_lk_in *arg = (struct fuse_lk_in *) inarg;
1351 struct fuse_file_info fi;
1352 struct flock flock;
1354 memset(&fi, 0, sizeof(fi));
1355 fi.fh = arg->fh;
1356 fi.lock_owner = arg->owner;
1358 convert_fuse_file_lock(&arg->lk, &flock);
1359 if (req->f->op.getlk)
1360 req->f->op.getlk(req, nodeid, &fi, &flock);
1361 else
1362 fuse_reply_err(req, ENOSYS);
1365 static void do_setlk_common(fuse_req_t req, fuse_ino_t nodeid,
1366 const void *inarg, int sleep)
1368 struct fuse_lk_in *arg = (struct fuse_lk_in *) inarg;
1369 struct fuse_file_info fi;
1370 struct flock flock;
1372 memset(&fi, 0, sizeof(fi));
1373 fi.fh = arg->fh;
1374 fi.lock_owner = arg->owner;
1376 convert_fuse_file_lock(&arg->lk, &flock);
1377 if (req->f->op.setlk)
1378 req->f->op.setlk(req, nodeid, &fi, &flock, sleep);
1379 else
1380 fuse_reply_err(req, ENOSYS);
1383 static void do_setlk(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1385 do_setlk_common(req, nodeid, inarg, 0);
1388 static void do_setlkw(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1390 do_setlk_common(req, nodeid, inarg, 1);
1393 static int find_interrupted(struct fuse_ll *f, struct fuse_req *req)
1395 struct fuse_req *curr;
1397 for (curr = f->list.next; curr != &f->list; curr = curr->next) {
1398 if (curr->unique == req->u.i.unique) {
1399 fuse_interrupt_func_t func;
1400 void *data;
1402 curr->ctr++;
1403 pthread_mutex_unlock(&f->lock);
1405 /* Ugh, ugly locking */
1406 pthread_mutex_lock(&curr->lock);
1407 pthread_mutex_lock(&f->lock);
1408 curr->interrupted = 1;
1409 func = curr->u.ni.func;
1410 data = curr->u.ni.data;
1411 pthread_mutex_unlock(&f->lock);
1412 if (func)
1413 func(curr, data);
1414 pthread_mutex_unlock(&curr->lock);
1416 pthread_mutex_lock(&f->lock);
1417 curr->ctr--;
1418 if (!curr->ctr)
1419 destroy_req(curr);
1421 return 1;
1424 for (curr = f->interrupts.next; curr != &f->interrupts;
1425 curr = curr->next) {
1426 if (curr->u.i.unique == req->u.i.unique)
1427 return 1;
1429 return 0;
1432 static void do_interrupt(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1434 struct fuse_interrupt_in *arg = (struct fuse_interrupt_in *) inarg;
1435 struct fuse_ll *f = req->f;
1437 (void) nodeid;
1438 if (f->debug)
1439 fprintf(stderr, "INTERRUPT: %llu\n",
1440 (unsigned long long) arg->unique);
1442 req->u.i.unique = arg->unique;
1444 pthread_mutex_lock(&f->lock);
1445 if (find_interrupted(f, req))
1446 destroy_req(req);
1447 else
1448 list_add_req(req, &f->interrupts);
1449 pthread_mutex_unlock(&f->lock);
1452 static struct fuse_req *check_interrupt(struct fuse_ll *f, struct fuse_req *req)
1454 struct fuse_req *curr;
1456 for (curr = f->interrupts.next; curr != &f->interrupts;
1457 curr = curr->next) {
1458 if (curr->u.i.unique == req->unique) {
1459 req->interrupted = 1;
1460 list_del_req(curr);
1461 free(curr);
1462 return NULL;
1465 curr = f->interrupts.next;
1466 if (curr != &f->interrupts) {
1467 list_del_req(curr);
1468 list_init_req(curr);
1469 return curr;
1470 } else
1471 return NULL;
1474 static void do_bmap(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1476 struct fuse_bmap_in *arg = (struct fuse_bmap_in *) inarg;
1478 if (req->f->op.bmap)
1479 req->f->op.bmap(req, nodeid, arg->blocksize, arg->block);
1480 else
1481 fuse_reply_err(req, ENOSYS);
1484 static void do_ioctl(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1486 struct fuse_ioctl_in *arg = (struct fuse_ioctl_in *) inarg;
1487 unsigned int flags = arg->flags;
1488 void *in_buf = arg->in_size ? PARAM(arg) : NULL;
1489 struct fuse_file_info fi;
1491 memset(&fi, 0, sizeof(fi));
1492 fi.fh = arg->fh;
1493 fi.fh_old = fi.fh;
1495 if (req->f->op.ioctl)
1496 req->f->op.ioctl(req, nodeid, arg->cmd,
1497 (void *)(uintptr_t)arg->arg, &fi, flags,
1498 in_buf, arg->in_size, arg->out_size);
1499 else
1500 fuse_reply_err(req, ENOSYS);
1503 void fuse_pollhandle_destroy(struct fuse_pollhandle *ph)
1505 free(ph);
1508 static void do_poll(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1510 struct fuse_poll_in *arg = (struct fuse_poll_in *) inarg;
1511 struct fuse_file_info fi;
1513 memset(&fi, 0, sizeof(fi));
1514 fi.fh = arg->fh;
1515 fi.fh_old = fi.fh;
1517 if (req->f->op.poll) {
1518 struct fuse_pollhandle *ph = NULL;
1520 if (arg->flags & FUSE_POLL_SCHEDULE_NOTIFY) {
1521 ph = malloc(sizeof(struct fuse_pollhandle));
1522 if (ph == NULL) {
1523 fuse_reply_err(req, ENOMEM);
1524 return;
1526 ph->kh = arg->kh;
1527 ph->ch = req->ch;
1528 ph->f = req->f;
1531 req->f->op.poll(req, nodeid, &fi, ph);
1532 } else {
1533 fuse_reply_err(req, ENOSYS);
1537 static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1539 struct fuse_init_in *arg = (struct fuse_init_in *) inarg;
1540 struct fuse_init_out outarg;
1541 struct fuse_ll *f = req->f;
1542 size_t bufsize = fuse_chan_bufsize(req->ch);
1544 (void) nodeid;
1545 if (f->debug) {
1546 fprintf(stderr, "INIT: %u.%u\n", arg->major, arg->minor);
1547 if (arg->major == 7 && arg->minor >= 6) {
1548 fprintf(stderr, "flags=0x%08x\n", arg->flags);
1549 fprintf(stderr, "max_readahead=0x%08x\n",
1550 arg->max_readahead);
1553 f->conn.proto_major = arg->major;
1554 f->conn.proto_minor = arg->minor;
1555 f->conn.capable = 0;
1556 f->conn.want = 0;
1558 memset(&outarg, 0, sizeof(outarg));
1559 outarg.major = FUSE_KERNEL_VERSION;
1560 outarg.minor = FUSE_KERNEL_MINOR_VERSION;
1562 if (arg->major < 7) {
1563 fprintf(stderr, "fuse: unsupported protocol version: %u.%u\n",
1564 arg->major, arg->minor);
1565 fuse_reply_err(req, EPROTO);
1566 return;
1569 if (arg->major > 7) {
1570 /* Wait for a second INIT request with a 7.X version */
1571 send_reply_ok(req, &outarg, sizeof(outarg));
1572 return;
1575 if (arg->minor >= 6) {
1576 if (f->conn.async_read)
1577 f->conn.async_read = arg->flags & FUSE_ASYNC_READ;
1578 if (arg->max_readahead < f->conn.max_readahead)
1579 f->conn.max_readahead = arg->max_readahead;
1580 if (arg->flags & FUSE_ASYNC_READ)
1581 f->conn.capable |= FUSE_CAP_ASYNC_READ;
1582 if (arg->flags & FUSE_POSIX_LOCKS)
1583 f->conn.capable |= FUSE_CAP_POSIX_LOCKS;
1584 if (arg->flags & FUSE_ATOMIC_O_TRUNC)
1585 f->conn.capable |= FUSE_CAP_ATOMIC_O_TRUNC;
1586 if (arg->flags & FUSE_EXPORT_SUPPORT)
1587 f->conn.capable |= FUSE_CAP_EXPORT_SUPPORT;
1588 if (arg->flags & FUSE_BIG_WRITES)
1589 f->conn.capable |= FUSE_CAP_BIG_WRITES;
1590 if (arg->flags & FUSE_DONT_MASK)
1591 f->conn.capable |= FUSE_CAP_DONT_MASK;
1592 } else {
1593 f->conn.async_read = 0;
1594 f->conn.max_readahead = 0;
1597 if (req->f->conn.proto_minor >= 14) {
1598 f->conn.capable |= FUSE_CAP_SPLICE_WRITE | FUSE_CAP_SPLICE_MOVE;
1599 f->conn.capable |= FUSE_CAP_SPLICE_READ;
1600 if (!f->no_splice_write)
1601 f->conn.want |= FUSE_CAP_SPLICE_WRITE;
1602 if (!f->no_splice_move)
1603 f->conn.want |= FUSE_CAP_SPLICE_MOVE;
1604 if (!f->no_splice_read &&
1605 (f->op.write_buf || f->op.retrieve_reply))
1606 f->conn.want |= FUSE_CAP_SPLICE_READ;
1609 if (f->atomic_o_trunc)
1610 f->conn.want |= FUSE_CAP_ATOMIC_O_TRUNC;
1611 if (f->op.getlk && f->op.setlk && !f->no_remote_lock)
1612 f->conn.want |= FUSE_CAP_POSIX_LOCKS;
1613 if (f->big_writes)
1614 f->conn.want |= FUSE_CAP_BIG_WRITES;
1616 if (bufsize < FUSE_MIN_READ_BUFFER) {
1617 fprintf(stderr, "fuse: warning: buffer size too small: %zu\n",
1618 bufsize);
1619 bufsize = FUSE_MIN_READ_BUFFER;
1622 bufsize -= 4096;
1623 if (bufsize < f->conn.max_write)
1624 f->conn.max_write = bufsize;
1626 f->got_init = 1;
1627 if (f->op.init)
1628 f->op.init(f->userdata, &f->conn);
1630 if (f->conn.async_read || (f->conn.want & FUSE_CAP_ASYNC_READ))
1631 outarg.flags |= FUSE_ASYNC_READ;
1632 if (f->conn.want & FUSE_CAP_POSIX_LOCKS)
1633 outarg.flags |= FUSE_POSIX_LOCKS;
1634 if (f->conn.want & FUSE_CAP_ATOMIC_O_TRUNC)
1635 outarg.flags |= FUSE_ATOMIC_O_TRUNC;
1636 if (f->conn.want & FUSE_CAP_EXPORT_SUPPORT)
1637 outarg.flags |= FUSE_EXPORT_SUPPORT;
1638 if (f->conn.want & FUSE_CAP_BIG_WRITES)
1639 outarg.flags |= FUSE_BIG_WRITES;
1640 if (f->conn.want & FUSE_CAP_DONT_MASK)
1641 outarg.flags |= FUSE_DONT_MASK;
1642 outarg.max_readahead = f->conn.max_readahead;
1643 outarg.max_write = f->conn.max_write;
1644 if (f->conn.proto_minor >= 13) {
1645 if (f->conn.max_background >= (1 << 16))
1646 f->conn.max_background = (1 << 16) - 1;
1647 if (f->conn.congestion_threshold > f->conn.max_background)
1648 f->conn.congestion_threshold = f->conn.max_background;
1649 if (!f->conn.congestion_threshold) {
1650 f->conn.congestion_threshold =
1651 f->conn.max_background * 3 / 4;
1654 outarg.max_background = f->conn.max_background;
1655 outarg.congestion_threshold = f->conn.congestion_threshold;
1658 if (f->debug) {
1659 fprintf(stderr, " INIT: %u.%u\n", outarg.major, outarg.minor);
1660 fprintf(stderr, " flags=0x%08x\n", outarg.flags);
1661 fprintf(stderr, " max_readahead=0x%08x\n",
1662 outarg.max_readahead);
1663 fprintf(stderr, " max_write=0x%08x\n", outarg.max_write);
1664 fprintf(stderr, " max_background=%i\n",
1665 outarg.max_background);
1666 fprintf(stderr, " congestion_threshold=%i\n",
1667 outarg.congestion_threshold);
1670 send_reply_ok(req, &outarg, arg->minor < 5 ? 8 : sizeof(outarg));
1673 static void do_destroy(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1675 struct fuse_ll *f = req->f;
1677 (void) nodeid;
1678 (void) inarg;
1680 f->got_destroy = 1;
1681 if (f->op.destroy)
1682 f->op.destroy(f->userdata);
1684 send_reply_ok(req, NULL, 0);
1687 static void list_del_nreq(struct fuse_notify_req *nreq)
1689 struct fuse_notify_req *prev = nreq->prev;
1690 struct fuse_notify_req *next = nreq->next;
1691 prev->next = next;
1692 next->prev = prev;
1695 static void list_add_nreq(struct fuse_notify_req *nreq,
1696 struct fuse_notify_req *next)
1698 struct fuse_notify_req *prev = next->prev;
1699 nreq->next = next;
1700 nreq->prev = prev;
1701 prev->next = nreq;
1702 next->prev = nreq;
1705 static void list_init_nreq(struct fuse_notify_req *nreq)
1707 nreq->next = nreq;
1708 nreq->prev = nreq;
1711 static void do_notify_reply(fuse_req_t req, fuse_ino_t nodeid,
1712 const void *inarg, const struct fuse_buf *buf)
1714 struct fuse_ll *f = req->f;
1715 struct fuse_notify_req *nreq;
1716 struct fuse_notify_req *head;
1718 pthread_mutex_lock(&f->lock);
1719 head = &f->notify_list;
1720 for (nreq = head->next; nreq != head; nreq = nreq->next) {
1721 if (nreq->unique == req->unique) {
1722 list_del_nreq(nreq);
1723 break;
1726 pthread_mutex_unlock(&f->lock);
1728 if (nreq != head)
1729 nreq->reply(nreq, req, nodeid, inarg, buf);
1732 static int send_notify_iov(struct fuse_ll *f, struct fuse_chan *ch,
1733 int notify_code, struct iovec *iov, int count)
1735 struct fuse_out_header out;
1737 if (!f->got_init)
1738 return -ENOTCONN;
1740 out.unique = 0;
1741 out.error = notify_code;
1742 iov[0].iov_base = &out;
1743 iov[0].iov_len = sizeof(struct fuse_out_header);
1745 return fuse_send_msg(f, ch, iov, count);
1748 int fuse_lowlevel_notify_poll(struct fuse_pollhandle *ph)
1750 if (ph != NULL) {
1751 struct fuse_notify_poll_wakeup_out outarg;
1752 struct iovec iov[2];
1754 outarg.kh = ph->kh;
1756 iov[1].iov_base = &outarg;
1757 iov[1].iov_len = sizeof(outarg);
1759 return send_notify_iov(ph->f, ph->ch, FUSE_NOTIFY_POLL, iov, 2);
1760 } else {
1761 return 0;
1765 int fuse_lowlevel_notify_inval_inode(struct fuse_chan *ch, fuse_ino_t ino,
1766 off_t off, off_t len)
1768 struct fuse_notify_inval_inode_out outarg;
1769 struct fuse_ll *f;
1770 struct iovec iov[2];
1772 if (!ch)
1773 return -EINVAL;
1775 f = (struct fuse_ll *)fuse_session_data(fuse_chan_session(ch));
1776 if (!f)
1777 return -ENODEV;
1779 outarg.ino = ino;
1780 outarg.off = off;
1781 outarg.len = len;
1783 iov[1].iov_base = &outarg;
1784 iov[1].iov_len = sizeof(outarg);
1786 return send_notify_iov(f, ch, FUSE_NOTIFY_INVAL_INODE, iov, 2);
1789 int fuse_lowlevel_notify_inval_entry(struct fuse_chan *ch, fuse_ino_t parent,
1790 const char *name, size_t namelen)
1792 struct fuse_notify_inval_entry_out outarg;
1793 struct fuse_ll *f;
1794 struct iovec iov[3];
1796 if (!ch)
1797 return -EINVAL;
1799 f = (struct fuse_ll *)fuse_session_data(fuse_chan_session(ch));
1800 if (!f)
1801 return -ENODEV;
1803 outarg.parent = parent;
1804 outarg.namelen = namelen;
1805 outarg.padding = 0;
1807 iov[1].iov_base = &outarg;
1808 iov[1].iov_len = sizeof(outarg);
1809 iov[2].iov_base = (void *)name;
1810 iov[2].iov_len = namelen + 1;
1812 return send_notify_iov(f, ch, FUSE_NOTIFY_INVAL_ENTRY, iov, 3);
1815 int fuse_lowlevel_notify_store(struct fuse_chan *ch, fuse_ino_t ino,
1816 off_t offset, struct fuse_bufvec *bufv,
1817 enum fuse_buf_copy_flags flags)
1819 struct fuse_out_header out;
1820 struct fuse_notify_store_out outarg;
1821 struct fuse_ll *f;
1822 struct iovec iov[3];
1823 size_t size = fuse_buf_size(bufv);
1824 int res;
1826 if (!ch)
1827 return -EINVAL;
1829 f = (struct fuse_ll *)fuse_session_data(fuse_chan_session(ch));
1830 if (!f)
1831 return -ENODEV;
1833 out.unique = 0;
1834 out.error = FUSE_NOTIFY_STORE;
1836 outarg.nodeid = ino;
1837 outarg.offset = offset;
1838 outarg.size = size;
1840 iov[0].iov_base = &out;
1841 iov[0].iov_len = sizeof(out);
1842 iov[1].iov_base = &outarg;
1843 iov[1].iov_len = sizeof(outarg);
1845 res = fuse_send_data_iov(f, ch, iov, 2, bufv, flags);
1846 if (res > 0)
1847 res = -res;
1849 return res;
1852 struct fuse_retrieve_req {
1853 struct fuse_notify_req nreq;
1854 void *cookie;
1857 static void fuse_ll_retrieve_reply(struct fuse_notify_req *nreq,
1858 fuse_req_t req, fuse_ino_t ino,
1859 const void *inarg,
1860 const struct fuse_buf *ibuf)
1862 struct fuse_ll *f = req->f;
1863 struct fuse_retrieve_req *rreq =
1864 container_of(nreq, struct fuse_retrieve_req, nreq);
1865 const struct fuse_notify_retrieve_in *arg = inarg;
1866 struct fuse_bufvec bufv = {
1867 .buf[0] = *ibuf,
1868 .count = 1,
1871 if (!(bufv.buf[0].flags & FUSE_BUF_IS_FD))
1872 bufv.buf[0].mem = PARAM(arg);
1874 bufv.buf[0].size -= sizeof(struct fuse_in_header) +
1875 sizeof(struct fuse_notify_retrieve_in);
1877 if (bufv.buf[0].size < arg->size) {
1878 fprintf(stderr, "fuse: retrieve reply: buffer size too small\n");
1879 fuse_reply_none(req);
1880 goto out;
1882 bufv.buf[0].size = arg->size;
1884 if (req->f->op.retrieve_reply)
1885 req->f->op.retrieve_reply(rreq->cookie, ino, arg->offset, &bufv);
1886 fuse_reply_none(req);
1887 free(rreq);
1889 out:
1890 if ((ibuf->flags & FUSE_BUF_IS_FD) && bufv.idx < bufv.count)
1891 fuse_ll_clear_pipe(f);
1894 int fuse_lowlevel_notify_retrieve(struct fuse_chan *ch, fuse_ino_t ino,
1895 size_t size, off_t offset, void *cookie)
1897 struct fuse_notify_retrieve_out outarg;
1898 struct fuse_ll *f;
1899 struct iovec iov[2];
1900 struct fuse_retrieve_req *rreq;
1901 int err;
1903 if (!ch)
1904 return -EINVAL;
1906 f = (struct fuse_ll *)fuse_session_data(fuse_chan_session(ch));
1907 if (!f)
1908 return -ENODEV;
1910 rreq = malloc(sizeof(*rreq));
1911 if (rreq == NULL)
1912 return -ENOMEM;
1914 pthread_mutex_lock(&f->lock);
1915 rreq->cookie = cookie;
1916 rreq->nreq.unique = f->notify_ctr++;
1917 rreq->nreq.reply = fuse_ll_retrieve_reply;
1918 list_add_nreq(&rreq->nreq, &f->notify_list);
1919 pthread_mutex_unlock(&f->lock);
1921 outarg.notify_unique = rreq->nreq.unique;
1922 outarg.nodeid = ino;
1923 outarg.offset = offset;
1924 outarg.size = size;
1926 iov[1].iov_base = &outarg;
1927 iov[1].iov_len = sizeof(outarg);
1929 err = send_notify_iov(f, ch, FUSE_NOTIFY_RETRIEVE, iov, 2);
1930 if (err) {
1931 pthread_mutex_lock(&f->lock);
1932 list_del_nreq(&rreq->nreq);
1933 pthread_mutex_unlock(&f->lock);
1934 free(rreq);
1937 return err;
1940 void *fuse_req_userdata(fuse_req_t req)
1942 return req->f->userdata;
1945 const struct fuse_ctx *fuse_req_ctx(fuse_req_t req)
1947 return &req->ctx;
1951 * The size of fuse_ctx got extended, so need to be careful about
1952 * incompatibility (i.e. a new binary cannot work with an old
1953 * library).
1955 const struct fuse_ctx *fuse_req_ctx_compat24(fuse_req_t req);
1956 const struct fuse_ctx *fuse_req_ctx_compat24(fuse_req_t req)
1958 return fuse_req_ctx(req);
1960 #ifndef __NetBSD__
1961 FUSE_SYMVER(".symver fuse_req_ctx_compat24,fuse_req_ctx@FUSE_2.4");
1962 #endif
1965 void fuse_req_interrupt_func(fuse_req_t req, fuse_interrupt_func_t func,
1966 void *data)
1968 pthread_mutex_lock(&req->lock);
1969 pthread_mutex_lock(&req->f->lock);
1970 req->u.ni.func = func;
1971 req->u.ni.data = data;
1972 pthread_mutex_unlock(&req->f->lock);
1973 if (req->interrupted && func)
1974 func(req, data);
1975 pthread_mutex_unlock(&req->lock);
1978 int fuse_req_interrupted(fuse_req_t req)
1980 int interrupted;
1982 pthread_mutex_lock(&req->f->lock);
1983 interrupted = req->interrupted;
1984 pthread_mutex_unlock(&req->f->lock);
1986 return interrupted;
1989 static struct {
1990 void (*func)(fuse_req_t, fuse_ino_t, const void *);
1991 const char *name;
1992 } fuse_ll_ops[] = {
1993 [FUSE_LOOKUP] = { do_lookup, "LOOKUP" },
1994 [FUSE_FORGET] = { do_forget, "FORGET" },
1995 [FUSE_GETATTR] = { do_getattr, "GETATTR" },
1996 [FUSE_SETATTR] = { do_setattr, "SETATTR" },
1997 [FUSE_READLINK] = { do_readlink, "READLINK" },
1998 [FUSE_SYMLINK] = { do_symlink, "SYMLINK" },
1999 [FUSE_MKNOD] = { do_mknod, "MKNOD" },
2000 [FUSE_MKDIR] = { do_mkdir, "MKDIR" },
2001 [FUSE_UNLINK] = { do_unlink, "UNLINK" },
2002 [FUSE_RMDIR] = { do_rmdir, "RMDIR" },
2003 [FUSE_RENAME] = { do_rename, "RENAME" },
2004 [FUSE_LINK] = { do_link, "LINK" },
2005 [FUSE_OPEN] = { do_open, "OPEN" },
2006 [FUSE_READ] = { do_read, "READ" },
2007 [FUSE_WRITE] = { do_write, "WRITE" },
2008 [FUSE_STATFS] = { do_statfs, "STATFS" },
2009 [FUSE_RELEASE] = { do_release, "RELEASE" },
2010 [FUSE_FSYNC] = { do_fsync, "FSYNC" },
2011 [FUSE_SETXATTR] = { do_setxattr, "SETXATTR" },
2012 [FUSE_GETXATTR] = { do_getxattr, "GETXATTR" },
2013 [FUSE_LISTXATTR] = { do_listxattr, "LISTXATTR" },
2014 [FUSE_REMOVEXATTR] = { do_removexattr, "REMOVEXATTR" },
2015 [FUSE_FLUSH] = { do_flush, "FLUSH" },
2016 [FUSE_INIT] = { do_init, "INIT" },
2017 [FUSE_OPENDIR] = { do_opendir, "OPENDIR" },
2018 [FUSE_READDIR] = { do_readdir, "READDIR" },
2019 [FUSE_RELEASEDIR] = { do_releasedir, "RELEASEDIR" },
2020 [FUSE_FSYNCDIR] = { do_fsyncdir, "FSYNCDIR" },
2021 [FUSE_GETLK] = { do_getlk, "GETLK" },
2022 [FUSE_SETLK] = { do_setlk, "SETLK" },
2023 [FUSE_SETLKW] = { do_setlkw, "SETLKW" },
2024 [FUSE_ACCESS] = { do_access, "ACCESS" },
2025 [FUSE_CREATE] = { do_create, "CREATE" },
2026 [FUSE_INTERRUPT] = { do_interrupt, "INTERRUPT" },
2027 [FUSE_BMAP] = { do_bmap, "BMAP" },
2028 [FUSE_IOCTL] = { do_ioctl, "IOCTL" },
2029 [FUSE_POLL] = { do_poll, "POLL" },
2030 [FUSE_DESTROY] = { do_destroy, "DESTROY" },
2031 [FUSE_NOTIFY_REPLY] = { (void *) 1, "NOTIFY_REPLY" },
2032 [CUSE_INIT] = { cuse_lowlevel_init, "CUSE_INIT" },
2035 #define FUSE_MAXOP (sizeof(fuse_ll_ops) / sizeof(fuse_ll_ops[0]))
2037 static const char *opname(enum fuse_opcode opcode)
2039 if (opcode >= FUSE_MAXOP || !fuse_ll_ops[opcode].name)
2040 return "???";
2041 else
2042 return fuse_ll_ops[opcode].name;
2045 static int fuse_ll_copy_from_pipe(struct fuse_bufvec *dst,
2046 struct fuse_bufvec *src)
2048 int res = fuse_buf_copy(dst, src, 0);
2049 if (res < 0) {
2050 fprintf(stderr, "fuse: copy from pipe: %s\n", strerror(-res));
2051 return res;
2053 if (res < fuse_buf_size(dst)) {
2054 fprintf(stderr, "fuse: copy from pipe: short read\n");
2055 return -1;
2057 return 0;
2060 static void fuse_ll_process_buf(void *data, const struct fuse_buf *buf,
2061 struct fuse_chan *ch)
2063 struct fuse_ll *f = (struct fuse_ll *) data;
2064 const size_t write_header_size = sizeof(struct fuse_in_header) +
2065 sizeof(struct fuse_write_in);
2066 struct fuse_bufvec bufv = { .buf[0] = *buf, .count = 1 };
2067 struct fuse_bufvec tmpbuf = FUSE_BUFVEC_INIT(write_header_size);
2068 struct fuse_in_header *in;
2069 const void *inarg;
2070 struct fuse_req *req;
2071 void *mbuf = NULL;
2072 int err;
2073 int res;
2075 if (buf->flags & FUSE_BUF_IS_FD) {
2076 if (buf->size < tmpbuf.buf[0].size)
2077 tmpbuf.buf[0].size = buf->size;
2079 mbuf = malloc(tmpbuf.buf[0].size);
2080 if (mbuf == NULL) {
2081 fprintf(stderr, "fuse: failed to allocate header\n");
2082 goto clear_pipe;
2084 tmpbuf.buf[0].mem = mbuf;
2086 res = fuse_ll_copy_from_pipe(&tmpbuf, &bufv);
2087 if (res < 0)
2088 goto clear_pipe;
2090 in = mbuf;
2091 } else {
2092 in = buf->mem;
2095 req = (struct fuse_req *) calloc(1, sizeof(struct fuse_req));
2096 if (req == NULL) {
2097 fprintf(stderr, "fuse: failed to allocate request\n");
2098 goto clear_pipe;
2101 req->f = f;
2102 req->unique = in->unique;
2103 req->ctx.uid = in->uid;
2104 req->ctx.gid = in->gid;
2105 req->ctx.pid = in->pid;
2106 req->ch = ch;
2107 req->ctr = 1;
2108 list_init_req(req);
2109 fuse_mutex_init(&req->lock);
2111 if (f->debug)
2112 fprintf(stderr,
2113 "unique: %llu, opcode: %s (%i), nodeid: %lu, insize: %zu, pid: %u\n",
2114 (unsigned long long) in->unique,
2115 opname((enum fuse_opcode) in->opcode), in->opcode,
2116 (unsigned long) in->nodeid, buf->size, in->pid);
2119 err = EIO;
2120 if (!f->got_init) {
2121 enum fuse_opcode expected;
2123 expected = f->cuse_data ? CUSE_INIT : FUSE_INIT;
2124 if (in->opcode != expected)
2125 goto reply_err;
2126 } else if (in->opcode == FUSE_INIT || in->opcode == CUSE_INIT)
2127 goto reply_err;
2129 err = EACCES;
2130 if (f->allow_root && in->uid != f->owner && in->uid != 0 &&
2131 in->opcode != FUSE_INIT && in->opcode != FUSE_READ &&
2132 in->opcode != FUSE_WRITE && in->opcode != FUSE_FSYNC &&
2133 in->opcode != FUSE_RELEASE && in->opcode != FUSE_READDIR &&
2134 in->opcode != FUSE_FSYNCDIR && in->opcode != FUSE_RELEASEDIR &&
2135 in->opcode != FUSE_NOTIFY_REPLY)
2136 goto reply_err;
2138 err = ENOSYS;
2139 if (in->opcode >= FUSE_MAXOP || !fuse_ll_ops[in->opcode].func)
2140 goto reply_err;
2141 if (in->opcode != FUSE_INTERRUPT) {
2142 struct fuse_req *intr;
2143 pthread_mutex_lock(&f->lock);
2144 intr = check_interrupt(f, req);
2145 list_add_req(req, &f->list);
2146 pthread_mutex_unlock(&f->lock);
2147 if (intr)
2148 fuse_reply_err(intr, EAGAIN);
2151 if ((buf->flags & FUSE_BUF_IS_FD) && write_header_size < buf->size &&
2152 (in->opcode != FUSE_WRITE || !f->op.write_buf) &&
2153 in->opcode != FUSE_NOTIFY_REPLY) {
2154 void *newmbuf;
2156 err = ENOMEM;
2157 newmbuf = realloc(mbuf, buf->size);
2158 if (newmbuf == NULL)
2159 goto reply_err;
2160 mbuf = newmbuf;
2162 tmpbuf = FUSE_BUFVEC_INIT(buf->size - write_header_size);
2163 tmpbuf.buf[0].mem = mbuf + write_header_size;
2165 res = fuse_ll_copy_from_pipe(&tmpbuf, &bufv);
2166 err = -res;
2167 if (res < 0)
2168 goto reply_err;
2170 in = mbuf;
2173 inarg = (void *) &in[1];
2174 if (in->opcode == FUSE_WRITE && f->op.write_buf)
2175 do_write_buf(req, in->nodeid, inarg, buf);
2176 else if (in->opcode == FUSE_NOTIFY_REPLY)
2177 do_notify_reply(req, in->nodeid, inarg, buf);
2178 else
2179 fuse_ll_ops[in->opcode].func(req, in->nodeid, inarg);
2181 out_free:
2182 free(mbuf);
2183 return;
2185 reply_err:
2186 fuse_reply_err(req, err);
2187 clear_pipe:
2188 if (buf->flags & FUSE_BUF_IS_FD)
2189 fuse_ll_clear_pipe(f);
2190 goto out_free;
2193 static void fuse_ll_process(void *data, const char *buf, size_t len,
2194 struct fuse_chan *ch)
2196 struct fuse_buf fbuf = {
2197 .mem = (void *) buf,
2198 .size = len,
2201 fuse_ll_process_buf(data, &fbuf, ch);
2204 enum {
2205 KEY_HELP,
2206 KEY_VERSION,
2209 static struct fuse_opt fuse_ll_opts[] = {
2210 { "debug", offsetof(struct fuse_ll, debug), 1 },
2211 { "-d", offsetof(struct fuse_ll, debug), 1 },
2212 { "allow_root", offsetof(struct fuse_ll, allow_root), 1 },
2213 { "max_write=%u", offsetof(struct fuse_ll, conn.max_write), 0 },
2214 { "max_readahead=%u", offsetof(struct fuse_ll, conn.max_readahead), 0 },
2215 { "max_background=%u", offsetof(struct fuse_ll, conn.max_background), 0 },
2216 { "congestion_threshold=%u",
2217 offsetof(struct fuse_ll, conn.congestion_threshold), 0 },
2218 { "async_read", offsetof(struct fuse_ll, conn.async_read), 1 },
2219 { "sync_read", offsetof(struct fuse_ll, conn.async_read), 0 },
2220 { "atomic_o_trunc", offsetof(struct fuse_ll, atomic_o_trunc), 1},
2221 { "no_remote_lock", offsetof(struct fuse_ll, no_remote_lock), 1},
2222 { "big_writes", offsetof(struct fuse_ll, big_writes), 1},
2223 { "no_splice_write", offsetof(struct fuse_ll, no_splice_write), 1},
2224 { "no_splice_move", offsetof(struct fuse_ll, no_splice_move), 1},
2225 { "no_splice_read", offsetof(struct fuse_ll, no_splice_read), 1},
2226 FUSE_OPT_KEY("max_read=", FUSE_OPT_KEY_DISCARD),
2227 FUSE_OPT_KEY("-h", KEY_HELP),
2228 FUSE_OPT_KEY("--help", KEY_HELP),
2229 FUSE_OPT_KEY("-V", KEY_VERSION),
2230 FUSE_OPT_KEY("--version", KEY_VERSION),
2231 FUSE_OPT_END
2234 static void fuse_ll_version(void)
2236 fprintf(stderr, "using FUSE kernel interface version %i.%i\n",
2237 FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION);
2240 static void fuse_ll_help(void)
2242 fprintf(stderr,
2243 " -o max_write=N set maximum size of write requests\n"
2244 " -o max_readahead=N set maximum readahead\n"
2245 " -o max_background=N set number of maximum background requests\n"
2246 " -o congestion_threshold=N set kernel's congestion threshold\n"
2247 " -o async_read perform reads asynchronously (default)\n"
2248 " -o sync_read perform reads synchronously\n"
2249 " -o atomic_o_trunc enable atomic open+truncate support\n"
2250 " -o big_writes enable larger than 4kB writes\n"
2251 " -o no_remote_lock disable remote file locking\n"
2252 " -o no_splice_write don't use splice to write to the fuse device\n"
2253 " -o no_splice_move don't move data while splicing to the fuse device\n"
2254 " -o no_splice_read don't use splice to read from the fuse device\n"
2258 static int fuse_ll_opt_proc(void *data, const char *arg, int key,
2259 struct fuse_args *outargs)
2261 (void) data; (void) outargs;
2263 switch (key) {
2264 case KEY_HELP:
2265 fuse_ll_help();
2266 break;
2268 case KEY_VERSION:
2269 fuse_ll_version();
2270 break;
2272 default:
2273 fprintf(stderr, "fuse: unknown option `%s'\n", arg);
2276 return -1;
2279 int fuse_lowlevel_is_lib_option(const char *opt)
2281 return fuse_opt_match(fuse_ll_opts, opt);
2284 static void fuse_ll_destroy(void *data)
2286 struct fuse_ll *f = (struct fuse_ll *) data;
2287 struct fuse_ll_pipe *llp;
2289 if (f->got_init && !f->got_destroy) {
2290 if (f->op.destroy)
2291 f->op.destroy(f->userdata);
2293 llp = pthread_getspecific(f->pipe_key);
2294 if (llp != NULL)
2295 fuse_ll_pipe_free(llp);
2296 pthread_key_delete(f->pipe_key);
2297 pthread_mutex_destroy(&f->lock);
2298 free(f->cuse_data);
2299 free(f);
2302 static void fuse_ll_pipe_destructor(void *data)
2304 struct fuse_ll_pipe *llp = data;
2305 fuse_ll_pipe_free(llp);
2308 static int fuse_ll_receive_buf(struct fuse_session *se, struct fuse_buf *buf,
2309 struct fuse_chan **chp)
2311 struct fuse_chan *ch = *chp;
2312 struct fuse_ll *f = fuse_session_data(se);
2313 size_t bufsize = buf->size;
2314 struct fuse_ll_pipe *llp;
2315 struct fuse_buf tmpbuf;
2316 int err;
2317 int res;
2319 if (f->conn.proto_minor < 14 || !(f->conn.want & FUSE_CAP_SPLICE_READ))
2320 goto fallback;
2322 llp = fuse_ll_get_pipe(f);
2323 if (llp == NULL)
2324 goto fallback;
2326 if (llp->size < bufsize) {
2327 if (llp->can_grow) {
2328 res = fcntl(llp->pipe[0], F_SETPIPE_SZ, bufsize);
2329 if (res == -1) {
2330 llp->can_grow = 0;
2331 goto fallback;
2333 llp->size = res;
2335 if (llp->size < bufsize)
2336 goto fallback;
2339 res = splice(fuse_chan_fd(ch), NULL, llp->pipe[1], NULL, bufsize, 0);
2340 err = errno;
2342 if (fuse_session_exited(se))
2343 return 0;
2345 if (res == -1) {
2346 if (err == ENODEV) {
2347 fuse_session_exit(se);
2348 return 0;
2350 if (err != EINTR && err != EAGAIN)
2351 perror("fuse: splice from device");
2352 return -err;
2355 if (res < sizeof(struct fuse_in_header)) {
2356 fprintf(stderr, "short splice from fuse device\n");
2357 return -EIO;
2360 tmpbuf = (struct fuse_buf) {
2361 .size = res,
2362 .flags = FUSE_BUF_IS_FD,
2363 .fd = llp->pipe[0],
2367 * Don't bother with zero copy for small requests.
2368 * fuse_loop_mt() needs to check for FORGET so this more than
2369 * just an optimization.
2371 if (res < sizeof(struct fuse_in_header) +
2372 sizeof(struct fuse_write_in) + pagesize) {
2373 struct fuse_bufvec src = { .buf[0] = tmpbuf, .count = 1 };
2374 struct fuse_bufvec dst = { .buf[0] = *buf, .count = 1 };
2376 res = fuse_buf_copy(&dst, &src, 0);
2377 if (res < 0) {
2378 fprintf(stderr, "fuse: copy from pipe: %s\n",
2379 strerror(-res));
2380 fuse_ll_clear_pipe(f);
2381 return res;
2383 if (res < tmpbuf.size) {
2384 fprintf(stderr, "fuse: copy from pipe: short read\n");
2385 fuse_ll_clear_pipe(f);
2386 return -EIO;
2388 buf->size = tmpbuf.size;
2389 return buf->size;
2392 *buf = tmpbuf;
2394 return res;
2396 fallback:
2397 res = fuse_chan_recv(chp, buf->mem, bufsize);
2398 if (res <= 0)
2399 return res;
2401 buf->size = res;
2403 return res;
2407 * always call fuse_lowlevel_new_common() internally, to work around a
2408 * misfeature in the FreeBSD runtime linker, which links the old
2409 * version of a symbol to internal references.
2411 struct fuse_session *fuse_lowlevel_new_common(struct fuse_args *args,
2412 const struct fuse_lowlevel_ops *op,
2413 size_t op_size, void *userdata)
2415 int err;
2416 struct fuse_ll *f;
2417 struct fuse_session *se;
2418 struct fuse_session_ops sop = {
2419 .process = fuse_ll_process,
2420 .destroy = fuse_ll_destroy,
2423 if (sizeof(struct fuse_lowlevel_ops) < op_size) {
2424 fprintf(stderr, "fuse: warning: library too old, some operations may not work\n");
2425 op_size = sizeof(struct fuse_lowlevel_ops);
2428 f = (struct fuse_ll *) calloc(1, sizeof(struct fuse_ll));
2429 if (f == NULL) {
2430 fprintf(stderr, "fuse: failed to allocate fuse object\n");
2431 goto out;
2434 f->conn.async_read = 1;
2435 f->conn.max_write = UINT_MAX;
2436 f->conn.max_readahead = UINT_MAX;
2437 f->atomic_o_trunc = 0;
2438 list_init_req(&f->list);
2439 list_init_req(&f->interrupts);
2440 list_init_nreq(&f->notify_list);
2441 f->notify_ctr = 1;
2442 fuse_mutex_init(&f->lock);
2444 err = pthread_key_create(&f->pipe_key, fuse_ll_pipe_destructor);
2445 if (err) {
2446 fprintf(stderr, "fuse: failed to create thread specific key: %s\n",
2447 strerror(err));
2448 goto out_free;
2451 if (fuse_opt_parse(args, f, fuse_ll_opts, fuse_ll_opt_proc) == -1)
2452 goto out_key_destroy;
2454 if (f->debug)
2455 fprintf(stderr, "FUSE library version: %s\n", PACKAGE_VERSION);
2457 memcpy(&f->op, op, op_size);
2458 f->owner = getuid();
2459 f->userdata = userdata;
2461 se = fuse_session_new(&sop, f);
2462 if (!se)
2463 goto out_key_destroy;
2465 se->receive_buf = fuse_ll_receive_buf;
2466 se->process_buf = fuse_ll_process_buf;
2468 return se;
2470 out_key_destroy:
2471 pthread_key_delete(f->pipe_key);
2472 out_free:
2473 pthread_mutex_destroy(&f->lock);
2474 free(f);
2475 out:
2476 return NULL;
2480 struct fuse_session *fuse_lowlevel_new(struct fuse_args *args,
2481 const struct fuse_lowlevel_ops *op,
2482 size_t op_size, void *userdata)
2484 return fuse_lowlevel_new_common(args, op, op_size, userdata);
2487 #ifdef linux
2488 int fuse_req_getgroups(fuse_req_t req, int size, gid_t list[])
2490 char *buf;
2491 size_t bufsize = 1024;
2492 char path[128];
2493 int ret;
2494 int fd;
2495 unsigned long pid = req->ctx.pid;
2496 char *s;
2498 sprintf(path, "/proc/%lu/task/%lu/status", pid, pid);
2500 retry:
2501 buf = malloc(bufsize);
2502 if (buf == NULL)
2503 return -ENOMEM;
2505 ret = -EIO;
2506 fd = open(path, O_RDONLY);
2507 if (fd == -1)
2508 goto out_free;
2510 ret = read(fd, buf, bufsize);
2511 close(fd);
2512 if (ret == -1) {
2513 ret = -EIO;
2514 goto out_free;
2517 if (ret == bufsize) {
2518 free(buf);
2519 bufsize *= 4;
2520 goto retry;
2523 ret = -EIO;
2524 s = strstr(buf, "\nGroups:");
2525 if (s == NULL)
2526 goto out_free;
2528 s += 8;
2529 ret = 0;
2530 while (1) {
2531 char *end;
2532 unsigned long val = strtoul(s, &end, 0);
2533 if (end == s)
2534 break;
2536 s = end;
2537 if (ret < size)
2538 list[ret] = val;
2539 ret++;
2542 out_free:
2543 free(buf);
2544 return ret;
2546 #else /* linux */
2548 * This is currently not implemented on other than Linux...
2550 int fuse_req_getgroups(fuse_req_t req, int size, gid_t list[])
2552 return -ENOSYS;
2554 #endif
2556 #if !defined(__FreeBSD__) && !defined(__NetBSD__)
2558 static void fill_open_compat(struct fuse_open_out *arg,
2559 const struct fuse_file_info_compat *f)
2561 arg->fh = f->fh;
2562 if (f->direct_io)
2563 arg->open_flags |= FOPEN_DIRECT_IO;
2564 if (f->keep_cache)
2565 arg->open_flags |= FOPEN_KEEP_CACHE;
2568 static void convert_statfs_compat(const struct statfs *compatbuf,
2569 struct statvfs *buf)
2571 buf->f_bsize = compatbuf->f_bsize;
2572 buf->f_blocks = compatbuf->f_blocks;
2573 buf->f_bfree = compatbuf->f_bfree;
2574 buf->f_bavail = compatbuf->f_bavail;
2575 buf->f_files = compatbuf->f_files;
2576 buf->f_ffree = compatbuf->f_ffree;
2577 buf->f_namemax = compatbuf->f_namelen;
2580 int fuse_reply_open_compat(fuse_req_t req,
2581 const struct fuse_file_info_compat *f)
2583 struct fuse_open_out arg;
2585 memset(&arg, 0, sizeof(arg));
2586 fill_open_compat(&arg, f);
2587 return send_reply_ok(req, &arg, sizeof(arg));
2590 int fuse_reply_statfs_compat(fuse_req_t req, const struct statfs *stbuf)
2592 struct statvfs newbuf;
2594 memset(&newbuf, 0, sizeof(newbuf));
2595 convert_statfs_compat(stbuf, &newbuf);
2597 return fuse_reply_statfs(req, &newbuf);
2600 struct fuse_session *fuse_lowlevel_new_compat(const char *opts,
2601 const struct fuse_lowlevel_ops_compat *op,
2602 size_t op_size, void *userdata)
2604 struct fuse_session *se;
2605 struct fuse_args args = FUSE_ARGS_INIT(0, NULL);
2607 if (opts &&
2608 (fuse_opt_add_arg(&args, "") == -1 ||
2609 fuse_opt_add_arg(&args, "-o") == -1 ||
2610 fuse_opt_add_arg(&args, opts) == -1)) {
2611 fuse_opt_free_args(&args);
2612 return NULL;
2614 se = fuse_lowlevel_new(&args, (const struct fuse_lowlevel_ops *) op,
2615 op_size, userdata);
2616 fuse_opt_free_args(&args);
2618 return se;
2621 struct fuse_ll_compat_conf {
2622 unsigned max_read;
2623 int set_max_read;
2626 static const struct fuse_opt fuse_ll_opts_compat[] = {
2627 { "max_read=", offsetof(struct fuse_ll_compat_conf, set_max_read), 1 },
2628 { "max_read=%u", offsetof(struct fuse_ll_compat_conf, max_read), 0 },
2629 FUSE_OPT_KEY("max_read=", FUSE_OPT_KEY_KEEP),
2630 FUSE_OPT_END
2633 int fuse_sync_compat_args(struct fuse_args *args)
2635 struct fuse_ll_compat_conf conf;
2637 memset(&conf, 0, sizeof(conf));
2638 if (fuse_opt_parse(args, &conf, fuse_ll_opts_compat, NULL) == -1)
2639 return -1;
2641 if (fuse_opt_insert_arg(args, 1, "-osync_read"))
2642 return -1;
2644 if (conf.set_max_read) {
2645 char tmpbuf[64];
2647 sprintf(tmpbuf, "-omax_readahead=%u", conf.max_read);
2648 if (fuse_opt_insert_arg(args, 1, tmpbuf) == -1)
2649 return -1;
2651 return 0;
2654 FUSE_SYMVER(".symver fuse_reply_statfs_compat,fuse_reply_statfs@FUSE_2.4");
2655 FUSE_SYMVER(".symver fuse_reply_open_compat,fuse_reply_open@FUSE_2.4");
2656 FUSE_SYMVER(".symver fuse_lowlevel_new_compat,fuse_lowlevel_new@FUSE_2.4");
2658 #else /* __FreeBSD__ || __NetBSD__ */
2660 int fuse_sync_compat_args(struct fuse_args *args)
2662 (void) args;
2663 return 0;
2666 #endif /* __FreeBSD__ || __NetBSD__ */
2668 struct fuse_session *fuse_lowlevel_new_compat25(struct fuse_args *args,
2669 const struct fuse_lowlevel_ops_compat25 *op,
2670 size_t op_size, void *userdata)
2672 if (fuse_sync_compat_args(args) == -1)
2673 return NULL;
2675 return fuse_lowlevel_new_common(args,
2676 (const struct fuse_lowlevel_ops *) op,
2677 op_size, userdata);
2680 FUSE_SYMVER(".symver fuse_lowlevel_new_compat25,fuse_lowlevel_new@FUSE_2.5");