* Make the number of max background requests and congestion
[fuse.git] / lib / fuse_lowlevel.c
blob109f92d7ec08c5d837bd8712d73a7f81353e2294
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>
26 #ifndef F_LINUX_SPECIFIC_BASE
27 #define F_LINUX_SPECIFIC_BASE 1024
28 #endif
29 #ifndef F_SETPIPE_SZ
30 #define F_SETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 7)
31 #endif
34 #define PARAM(inarg) (((char *)(inarg)) + sizeof(*(inarg)))
35 #define OFFSET_MAX 0x7fffffffffffffffLL
37 struct fuse_pollhandle {
38 uint64_t kh;
39 struct fuse_chan *ch;
40 struct fuse_ll *f;
43 static void convert_stat(const struct stat *stbuf, struct fuse_attr *attr)
45 attr->ino = stbuf->st_ino;
46 attr->mode = stbuf->st_mode;
47 attr->nlink = stbuf->st_nlink;
48 attr->uid = stbuf->st_uid;
49 attr->gid = stbuf->st_gid;
50 attr->rdev = stbuf->st_rdev;
51 attr->size = stbuf->st_size;
52 attr->blksize = stbuf->st_blksize;
53 attr->blocks = stbuf->st_blocks;
54 attr->atime = stbuf->st_atime;
55 attr->mtime = stbuf->st_mtime;
56 attr->ctime = stbuf->st_ctime;
57 attr->atimensec = ST_ATIM_NSEC(stbuf);
58 attr->mtimensec = ST_MTIM_NSEC(stbuf);
59 attr->ctimensec = ST_CTIM_NSEC(stbuf);
62 static void convert_attr(const struct fuse_setattr_in *attr, struct stat *stbuf)
64 stbuf->st_mode = attr->mode;
65 stbuf->st_uid = attr->uid;
66 stbuf->st_gid = attr->gid;
67 stbuf->st_size = attr->size;
68 stbuf->st_atime = attr->atime;
69 stbuf->st_mtime = attr->mtime;
70 ST_ATIM_NSEC_SET(stbuf, attr->atimensec);
71 ST_MTIM_NSEC_SET(stbuf, attr->mtimensec);
74 static size_t iov_length(const struct iovec *iov, size_t count)
76 size_t seg;
77 size_t ret = 0;
79 for (seg = 0; seg < count; seg++)
80 ret += iov[seg].iov_len;
81 return ret;
84 static void list_init_req(struct fuse_req *req)
86 req->next = req;
87 req->prev = req;
90 static void list_del_req(struct fuse_req *req)
92 struct fuse_req *prev = req->prev;
93 struct fuse_req *next = req->next;
94 prev->next = next;
95 next->prev = prev;
98 static void list_add_req(struct fuse_req *req, struct fuse_req *next)
100 struct fuse_req *prev = next->prev;
101 req->next = next;
102 req->prev = prev;
103 prev->next = req;
104 next->prev = req;
107 static void destroy_req(fuse_req_t req)
109 pthread_mutex_destroy(&req->lock);
110 free(req);
113 void fuse_free_req(fuse_req_t req)
115 int ctr;
116 struct fuse_ll *f = req->f;
118 pthread_mutex_lock(&f->lock);
119 req->u.ni.func = NULL;
120 req->u.ni.data = NULL;
121 list_del_req(req);
122 ctr = --req->ctr;
123 pthread_mutex_unlock(&f->lock);
124 if (!ctr)
125 destroy_req(req);
128 int fuse_send_reply_iov_nofree(fuse_req_t req, int error, struct iovec *iov,
129 int count)
131 struct fuse_out_header out;
133 if (error <= -1000 || error > 0) {
134 fprintf(stderr, "fuse: bad error value: %i\n", error);
135 error = -ERANGE;
138 out.unique = req->unique;
139 out.error = error;
140 iov[0].iov_base = &out;
141 iov[0].iov_len = sizeof(struct fuse_out_header);
142 out.len = iov_length(iov, count);
144 if (req->f->debug) {
145 if (out.error) {
146 fprintf(stderr,
147 " unique: %llu, error: %i (%s), outsize: %i\n",
148 (unsigned long long) out.unique, out.error,
149 strerror(-out.error), out.len);
150 } else {
151 fprintf(stderr,
152 " unique: %llu, success, outsize: %i\n",
153 (unsigned long long) out.unique, out.len);
157 return fuse_chan_send(req->ch, iov, count);
160 static int send_reply_iov(fuse_req_t req, int error, struct iovec *iov,
161 int count)
163 int res;
165 res = fuse_send_reply_iov_nofree(req, error, iov, count);
166 fuse_free_req(req);
167 return res;
170 static int send_reply(fuse_req_t req, int error, const void *arg,
171 size_t argsize)
173 struct iovec iov[2];
174 int count = 1;
175 if (argsize) {
176 iov[1].iov_base = (void *) arg;
177 iov[1].iov_len = argsize;
178 count++;
180 return send_reply_iov(req, error, iov, count);
183 int fuse_reply_iov(fuse_req_t req, const struct iovec *iov, int count)
185 int res;
186 struct iovec *padded_iov;
188 padded_iov = malloc((count + 1) * sizeof(struct iovec));
189 if (padded_iov == NULL)
190 return fuse_reply_err(req, ENOMEM);
192 memcpy(padded_iov + 1, iov, count * sizeof(struct iovec));
193 count++;
195 res = send_reply_iov(req, 0, padded_iov, count);
196 free(padded_iov);
198 return res;
201 size_t fuse_dirent_size(size_t namelen)
203 return FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + namelen);
206 char *fuse_add_dirent(char *buf, const char *name, const struct stat *stbuf,
207 off_t off)
209 unsigned namelen = strlen(name);
210 unsigned entlen = FUSE_NAME_OFFSET + namelen;
211 unsigned entsize = fuse_dirent_size(namelen);
212 unsigned padlen = entsize - entlen;
213 struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
215 dirent->ino = stbuf->st_ino;
216 dirent->off = off;
217 dirent->namelen = namelen;
218 dirent->type = (stbuf->st_mode & 0170000) >> 12;
219 strncpy(dirent->name, name, namelen);
220 if (padlen)
221 memset(buf + entlen, 0, padlen);
223 return buf + entsize;
226 size_t fuse_add_direntry(fuse_req_t req, char *buf, size_t bufsize,
227 const char *name, const struct stat *stbuf, off_t off)
229 size_t entsize;
231 (void) req;
232 entsize = fuse_dirent_size(strlen(name));
233 if (entsize <= bufsize && buf)
234 fuse_add_dirent(buf, name, stbuf, off);
235 return entsize;
238 static void convert_statfs(const struct statvfs *stbuf,
239 struct fuse_kstatfs *kstatfs)
241 kstatfs->bsize = stbuf->f_bsize;
242 kstatfs->frsize = stbuf->f_frsize;
243 kstatfs->blocks = stbuf->f_blocks;
244 kstatfs->bfree = stbuf->f_bfree;
245 kstatfs->bavail = stbuf->f_bavail;
246 kstatfs->files = stbuf->f_files;
247 kstatfs->ffree = stbuf->f_ffree;
248 kstatfs->namelen = stbuf->f_namemax;
251 static int send_reply_ok(fuse_req_t req, const void *arg, size_t argsize)
253 return send_reply(req, 0, arg, argsize);
256 int fuse_reply_err(fuse_req_t req, int err)
258 return send_reply(req, -err, NULL, 0);
261 void fuse_reply_none(fuse_req_t req)
263 fuse_chan_send(req->ch, NULL, 0);
264 fuse_free_req(req);
267 static unsigned long calc_timeout_sec(double t)
269 if (t > (double) ULONG_MAX)
270 return ULONG_MAX;
271 else if (t < 0.0)
272 return 0;
273 else
274 return (unsigned long) t;
277 static unsigned int calc_timeout_nsec(double t)
279 double f = t - (double) calc_timeout_sec(t);
280 if (f < 0.0)
281 return 0;
282 else if (f >= 0.999999999)
283 return 999999999;
284 else
285 return (unsigned int) (f * 1.0e9);
288 static void fill_entry(struct fuse_entry_out *arg,
289 const struct fuse_entry_param *e)
291 arg->nodeid = e->ino;
292 arg->generation = e->generation;
293 arg->entry_valid = calc_timeout_sec(e->entry_timeout);
294 arg->entry_valid_nsec = calc_timeout_nsec(e->entry_timeout);
295 arg->attr_valid = calc_timeout_sec(e->attr_timeout);
296 arg->attr_valid_nsec = calc_timeout_nsec(e->attr_timeout);
297 convert_stat(&e->attr, &arg->attr);
300 static void fill_open(struct fuse_open_out *arg,
301 const struct fuse_file_info *f)
303 arg->fh = f->fh;
304 if (f->direct_io)
305 arg->open_flags |= FOPEN_DIRECT_IO;
306 if (f->keep_cache)
307 arg->open_flags |= FOPEN_KEEP_CACHE;
308 if (f->nonseekable)
309 arg->open_flags |= FOPEN_NONSEEKABLE;
312 int fuse_reply_entry(fuse_req_t req, const struct fuse_entry_param *e)
314 struct fuse_entry_out arg;
315 size_t size = req->f->conn.proto_minor < 9 ?
316 FUSE_COMPAT_ENTRY_OUT_SIZE : sizeof(arg);
318 /* before ABI 7.4 e->ino == 0 was invalid, only ENOENT meant
319 negative entry */
320 if (!e->ino && req->f->conn.proto_minor < 4)
321 return fuse_reply_err(req, ENOENT);
323 memset(&arg, 0, sizeof(arg));
324 fill_entry(&arg, e);
325 return send_reply_ok(req, &arg, size);
328 int fuse_reply_create(fuse_req_t req, const struct fuse_entry_param *e,
329 const struct fuse_file_info *f)
331 char buf[sizeof(struct fuse_entry_out) + sizeof(struct fuse_open_out)];
332 size_t entrysize = req->f->conn.proto_minor < 9 ?
333 FUSE_COMPAT_ENTRY_OUT_SIZE : sizeof(struct fuse_entry_out);
334 struct fuse_entry_out *earg = (struct fuse_entry_out *) buf;
335 struct fuse_open_out *oarg = (struct fuse_open_out *) (buf + entrysize);
337 memset(buf, 0, sizeof(buf));
338 fill_entry(earg, e);
339 fill_open(oarg, f);
340 return send_reply_ok(req, buf,
341 entrysize + sizeof(struct fuse_open_out));
344 int fuse_reply_attr(fuse_req_t req, const struct stat *attr,
345 double attr_timeout)
347 struct fuse_attr_out arg;
348 size_t size = req->f->conn.proto_minor < 9 ?
349 FUSE_COMPAT_ATTR_OUT_SIZE : sizeof(arg);
351 memset(&arg, 0, sizeof(arg));
352 arg.attr_valid = calc_timeout_sec(attr_timeout);
353 arg.attr_valid_nsec = calc_timeout_nsec(attr_timeout);
354 convert_stat(attr, &arg.attr);
356 return send_reply_ok(req, &arg, size);
359 int fuse_reply_readlink(fuse_req_t req, const char *linkname)
361 return send_reply_ok(req, linkname, strlen(linkname));
364 int fuse_reply_open(fuse_req_t req, const struct fuse_file_info *f)
366 struct fuse_open_out arg;
368 memset(&arg, 0, sizeof(arg));
369 fill_open(&arg, f);
370 return send_reply_ok(req, &arg, sizeof(arg));
373 int fuse_reply_write(fuse_req_t req, size_t count)
375 struct fuse_write_out arg;
377 memset(&arg, 0, sizeof(arg));
378 arg.size = count;
380 return send_reply_ok(req, &arg, sizeof(arg));
383 int fuse_reply_buf(fuse_req_t req, const char *buf, size_t size)
385 return send_reply_ok(req, buf, size);
388 struct fuse_ll_pipe {
389 size_t size;
390 int can_grow;
391 int pipe[2];
394 static void fuse_ll_pipe_free(struct fuse_ll_pipe *llp)
396 close(llp->pipe[0]);
397 close(llp->pipe[1]);
398 free(llp);
401 static struct fuse_ll_pipe *fuse_ll_get_pipe(struct fuse_ll *f)
403 struct fuse_ll_pipe *llp = pthread_getspecific(f->pipe_key);
404 if (llp == NULL) {
405 int res;
407 llp = malloc(sizeof(struct fuse_ll_pipe));
408 if (llp == NULL)
409 return NULL;
411 res = pipe(llp->pipe);
412 if (res == -1) {
413 free(llp);
414 return NULL;
416 /* the default size is 16 pages on linux
418 llp->size = getpagesize() * 16;
419 llp->can_grow = 1;
421 pthread_setspecific(f->pipe_key, llp);
424 return llp;
427 int fuse_reply_fd(fuse_req_t req, int fd, loff_t *off, size_t len,
428 unsigned int flags)
430 int res;
431 void *buf;
432 struct fuse_out_header out;
433 struct iovec iov;
434 struct fuse_ll_pipe *llp;
435 int splice_flags;
436 size_t pipesize;
438 static size_t pagesize = 0;
439 if (!pagesize)
440 pagesize = getpagesize();
442 if (req->f->conn.proto_minor < 14 ||
443 !(req->f->conn.want & FUSE_CAP_SPLICE_WRITE))
444 goto fallback;
446 llp = fuse_ll_get_pipe(req->f);
447 if (llp == NULL)
448 goto fallback;
452 * Heuristic for the required pipe size, does not work if the
453 * source contains less than page size fragments
455 pipesize = pagesize * 2 + len;
457 if (llp->size < pipesize) {
458 if (llp->can_grow) {
459 res = fcntl(llp->pipe[0], F_SETPIPE_SZ, pipesize);
460 if (res == -1) {
461 llp->can_grow = 0;
462 goto fallback;
464 llp->size = res;
466 if (llp->size < pipesize)
467 goto fallback;
470 out.unique = req->unique;
471 out.error = 0;
472 out.len = len + sizeof(struct fuse_out_header);
474 iov.iov_base = &out;
475 iov.iov_len = sizeof(struct fuse_out_header);
477 res = vmsplice(llp->pipe[1], &iov, 1, 0);
478 if (res == -1) {
479 res = -errno;
480 perror("fuse: vmsplice to pipe");
481 return res;
483 if (res != sizeof(struct fuse_out_header)) {
484 res = -EIO;
485 fprintf(stderr, "fuse: short vmsplice to pipe: %u/%zu\n", res,
486 sizeof(struct fuse_out_header));
487 goto clear_pipe;
490 res = splice(fd, off, llp->pipe[1], NULL, len, 0);
491 if (res == -1) {
492 res = fuse_reply_err(req, errno);
493 goto clear_pipe;
495 len = res;
496 out.len = len + sizeof(struct fuse_out_header);
498 if (req->f->debug) {
499 fprintf(stderr,
500 " unique: %llu, success, outsize: %i (splice)\n",
501 (unsigned long long) out.unique, out.len);
504 splice_flags = 0;
505 if ((flags & FUSE_REPLY_FD_MOVE) &&
506 (req->f->conn.want & FUSE_CAP_SPLICE_MOVE))
507 splice_flags |= SPLICE_F_MOVE;
509 res = splice(llp->pipe[0], NULL,
510 fuse_chan_fd(req->ch), NULL, out.len, flags);
511 if (res == -1) {
512 res = -errno;
513 perror("fuse: splice from pipe");
514 goto clear_pipe;
516 if (res != out.len) {
517 res = -EIO;
518 fprintf(stderr, "fuse: short splice from pipe: %u/%u\n",
519 res, out.len);
520 goto clear_pipe;
522 return 0;
524 clear_pipe:
525 pthread_setspecific(req->f->pipe_key, NULL);
526 fuse_ll_pipe_free(llp);
527 return res;
529 fallback:
530 res = posix_memalign(&buf, pagesize, len);
531 if (res != 0)
532 return fuse_reply_err(req, res);
534 if (off != NULL) {
535 res = pread(fd, buf, len, *off);
536 if (res > 0)
537 *off += res;
538 } else {
539 res = read(fd, buf, len);
541 if (res == -1)
542 res = fuse_reply_err(req, errno);
543 else
544 res = fuse_reply_buf(req, buf, res);
545 free(buf);
547 return res;
550 int fuse_reply_statfs(fuse_req_t req, const struct statvfs *stbuf)
552 struct fuse_statfs_out arg;
553 size_t size = req->f->conn.proto_minor < 4 ?
554 FUSE_COMPAT_STATFS_SIZE : sizeof(arg);
556 memset(&arg, 0, sizeof(arg));
557 convert_statfs(stbuf, &arg.st);
559 return send_reply_ok(req, &arg, size);
562 int fuse_reply_xattr(fuse_req_t req, size_t count)
564 struct fuse_getxattr_out arg;
566 memset(&arg, 0, sizeof(arg));
567 arg.size = count;
569 return send_reply_ok(req, &arg, sizeof(arg));
572 int fuse_reply_lock(fuse_req_t req, struct flock *lock)
574 struct fuse_lk_out arg;
576 memset(&arg, 0, sizeof(arg));
577 arg.lk.type = lock->l_type;
578 if (lock->l_type != F_UNLCK) {
579 arg.lk.start = lock->l_start;
580 if (lock->l_len == 0)
581 arg.lk.end = OFFSET_MAX;
582 else
583 arg.lk.end = lock->l_start + lock->l_len - 1;
585 arg.lk.pid = lock->l_pid;
586 return send_reply_ok(req, &arg, sizeof(arg));
589 int fuse_reply_bmap(fuse_req_t req, uint64_t idx)
591 struct fuse_bmap_out arg;
593 memset(&arg, 0, sizeof(arg));
594 arg.block = idx;
596 return send_reply_ok(req, &arg, sizeof(arg));
599 int fuse_reply_ioctl_retry(fuse_req_t req,
600 const struct iovec *in_iov, size_t in_count,
601 const struct iovec *out_iov, size_t out_count)
603 struct fuse_ioctl_out arg;
604 struct iovec iov[4];
605 size_t count = 1;
607 memset(&arg, 0, sizeof(arg));
608 arg.flags |= FUSE_IOCTL_RETRY;
609 arg.in_iovs = in_count;
610 arg.out_iovs = out_count;
611 iov[count].iov_base = &arg;
612 iov[count].iov_len = sizeof(arg);
613 count++;
615 if (in_count) {
616 iov[count].iov_base = (void *)in_iov;
617 iov[count].iov_len = sizeof(in_iov[0]) * in_count;
618 count++;
621 if (out_count) {
622 iov[count].iov_base = (void *)out_iov;
623 iov[count].iov_len = sizeof(out_iov[0]) * out_count;
624 count++;
627 return send_reply_iov(req, 0, iov, count);
630 int fuse_reply_ioctl(fuse_req_t req, int result, const void *buf, size_t size)
632 struct fuse_ioctl_out arg;
633 struct iovec iov[3];
634 size_t count = 1;
636 memset(&arg, 0, sizeof(arg));
637 arg.result = result;
638 iov[count].iov_base = &arg;
639 iov[count].iov_len = sizeof(arg);
640 count++;
642 if (size) {
643 iov[count].iov_base = (char *) buf;
644 iov[count].iov_len = size;
645 count++;
648 return send_reply_iov(req, 0, iov, count);
651 int fuse_reply_ioctl_iov(fuse_req_t req, int result, const struct iovec *iov,
652 int count)
654 struct iovec *padded_iov;
655 struct fuse_ioctl_out arg;
656 int res;
658 padded_iov = malloc((count + 2) * sizeof(struct iovec));
659 if (padded_iov == NULL)
660 return fuse_reply_err(req, ENOMEM);
662 memset(&arg, 0, sizeof(arg));
663 arg.result = result;
664 padded_iov[1].iov_base = &arg;
665 padded_iov[1].iov_len = sizeof(arg);
667 memcpy(&padded_iov[2], iov, count * sizeof(struct iovec));
669 res = send_reply_iov(req, 0, padded_iov, count + 2);
670 free(padded_iov);
672 return res;
675 int fuse_reply_poll(fuse_req_t req, unsigned revents)
677 struct fuse_poll_out arg;
679 memset(&arg, 0, sizeof(arg));
680 arg.revents = revents;
682 return send_reply_ok(req, &arg, sizeof(arg));
685 static void do_lookup(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
687 char *name = (char *) inarg;
689 if (req->f->op.lookup)
690 req->f->op.lookup(req, nodeid, name);
691 else
692 fuse_reply_err(req, ENOSYS);
695 static void do_forget(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
697 struct fuse_forget_in *arg = (struct fuse_forget_in *) inarg;
699 if (req->f->op.forget)
700 req->f->op.forget(req, nodeid, arg->nlookup);
701 else
702 fuse_reply_none(req);
705 static void do_getattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
707 struct fuse_file_info *fip = NULL;
708 struct fuse_file_info fi;
710 if (req->f->conn.proto_minor >= 9) {
711 struct fuse_getattr_in *arg = (struct fuse_getattr_in *) inarg;
713 if (arg->getattr_flags & FUSE_GETATTR_FH) {
714 memset(&fi, 0, sizeof(fi));
715 fi.fh = arg->fh;
716 fi.fh_old = fi.fh;
717 fip = &fi;
721 if (req->f->op.getattr)
722 req->f->op.getattr(req, nodeid, fip);
723 else
724 fuse_reply_err(req, ENOSYS);
727 static void do_setattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
729 struct fuse_setattr_in *arg = (struct fuse_setattr_in *) inarg;
731 if (req->f->op.setattr) {
732 struct fuse_file_info *fi = NULL;
733 struct fuse_file_info fi_store;
734 struct stat stbuf;
735 memset(&stbuf, 0, sizeof(stbuf));
736 convert_attr(arg, &stbuf);
737 if (arg->valid & FATTR_FH) {
738 arg->valid &= ~FATTR_FH;
739 memset(&fi_store, 0, sizeof(fi_store));
740 fi = &fi_store;
741 fi->fh = arg->fh;
742 fi->fh_old = fi->fh;
744 arg->valid &=
745 FUSE_SET_ATTR_MODE |
746 FUSE_SET_ATTR_UID |
747 FUSE_SET_ATTR_GID |
748 FUSE_SET_ATTR_SIZE |
749 FUSE_SET_ATTR_ATIME |
750 FUSE_SET_ATTR_MTIME |
751 FUSE_SET_ATTR_ATIME_NOW |
752 FUSE_SET_ATTR_MTIME_NOW;
754 req->f->op.setattr(req, nodeid, &stbuf, arg->valid, fi);
755 } else
756 fuse_reply_err(req, ENOSYS);
759 static void do_access(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
761 struct fuse_access_in *arg = (struct fuse_access_in *) inarg;
763 if (req->f->op.access)
764 req->f->op.access(req, nodeid, arg->mask);
765 else
766 fuse_reply_err(req, ENOSYS);
769 static void do_readlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
771 (void) inarg;
773 if (req->f->op.readlink)
774 req->f->op.readlink(req, nodeid);
775 else
776 fuse_reply_err(req, ENOSYS);
779 static void do_mknod(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
781 struct fuse_mknod_in *arg = (struct fuse_mknod_in *) inarg;
782 char *name = PARAM(arg);
784 if (req->f->conn.proto_minor >= 12)
785 req->ctx.umask = arg->umask;
786 else
787 name = (char *) inarg + FUSE_COMPAT_MKNOD_IN_SIZE;
789 if (req->f->op.mknod)
790 req->f->op.mknod(req, nodeid, name, arg->mode, arg->rdev);
791 else
792 fuse_reply_err(req, ENOSYS);
795 static void do_mkdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
797 struct fuse_mkdir_in *arg = (struct fuse_mkdir_in *) inarg;
799 if (req->f->conn.proto_minor >= 12)
800 req->ctx.umask = arg->umask;
802 if (req->f->op.mkdir)
803 req->f->op.mkdir(req, nodeid, PARAM(arg), arg->mode);
804 else
805 fuse_reply_err(req, ENOSYS);
808 static void do_unlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
810 char *name = (char *) inarg;
812 if (req->f->op.unlink)
813 req->f->op.unlink(req, nodeid, name);
814 else
815 fuse_reply_err(req, ENOSYS);
818 static void do_rmdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
820 char *name = (char *) inarg;
822 if (req->f->op.rmdir)
823 req->f->op.rmdir(req, nodeid, name);
824 else
825 fuse_reply_err(req, ENOSYS);
828 static void do_symlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
830 char *name = (char *) inarg;
831 char *linkname = ((char *) inarg) + strlen((char *) inarg) + 1;
833 if (req->f->op.symlink)
834 req->f->op.symlink(req, linkname, nodeid, name);
835 else
836 fuse_reply_err(req, ENOSYS);
839 static void do_rename(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
841 struct fuse_rename_in *arg = (struct fuse_rename_in *) inarg;
842 char *oldname = PARAM(arg);
843 char *newname = oldname + strlen(oldname) + 1;
845 if (req->f->op.rename)
846 req->f->op.rename(req, nodeid, oldname, arg->newdir, newname);
847 else
848 fuse_reply_err(req, ENOSYS);
851 static void do_link(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
853 struct fuse_link_in *arg = (struct fuse_link_in *) inarg;
855 if (req->f->op.link)
856 req->f->op.link(req, arg->oldnodeid, nodeid, PARAM(arg));
857 else
858 fuse_reply_err(req, ENOSYS);
861 static void do_create(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
863 struct fuse_create_in *arg = (struct fuse_create_in *) inarg;
865 if (req->f->op.create) {
866 struct fuse_file_info fi;
867 char *name = PARAM(arg);
869 memset(&fi, 0, sizeof(fi));
870 fi.flags = arg->flags;
872 if (req->f->conn.proto_minor >= 12)
873 req->ctx.umask = arg->umask;
874 else
875 name = (char *) inarg + sizeof(struct fuse_open_in);
877 req->f->op.create(req, nodeid, name, arg->mode, &fi);
878 } else
879 fuse_reply_err(req, ENOSYS);
882 static void do_open(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
884 struct fuse_open_in *arg = (struct fuse_open_in *) inarg;
885 struct fuse_file_info fi;
887 memset(&fi, 0, sizeof(fi));
888 fi.flags = arg->flags;
890 if (req->f->op.open)
891 req->f->op.open(req, nodeid, &fi);
892 else
893 fuse_reply_open(req, &fi);
896 static void do_read(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
898 struct fuse_read_in *arg = (struct fuse_read_in *) inarg;
900 if (req->f->op.read) {
901 struct fuse_file_info fi;
903 memset(&fi, 0, sizeof(fi));
904 fi.fh = arg->fh;
905 fi.fh_old = fi.fh;
906 if (req->f->conn.proto_minor >= 9) {
907 fi.lock_owner = arg->lock_owner;
908 fi.flags = arg->flags;
910 req->f->op.read(req, nodeid, arg->size, arg->offset, &fi);
911 } else
912 fuse_reply_err(req, ENOSYS);
915 static void do_write(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
917 struct fuse_write_in *arg = (struct fuse_write_in *) inarg;
918 struct fuse_file_info fi;
919 char *param;
921 memset(&fi, 0, sizeof(fi));
922 fi.fh = arg->fh;
923 fi.fh_old = fi.fh;
924 fi.writepage = arg->write_flags & 1;
926 if (req->f->conn.proto_minor < 9) {
927 param = ((char *) arg) + FUSE_COMPAT_WRITE_IN_SIZE;
928 } else {
929 fi.lock_owner = arg->lock_owner;
930 fi.flags = arg->flags;
931 param = PARAM(arg);
934 if (req->f->op.write)
935 req->f->op.write(req, nodeid, param, arg->size,
936 arg->offset, &fi);
937 else
938 fuse_reply_err(req, ENOSYS);
941 static void do_flush(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
943 struct fuse_flush_in *arg = (struct fuse_flush_in *) inarg;
944 struct fuse_file_info fi;
946 memset(&fi, 0, sizeof(fi));
947 fi.fh = arg->fh;
948 fi.fh_old = fi.fh;
949 fi.flush = 1;
950 if (req->f->conn.proto_minor >= 7)
951 fi.lock_owner = arg->lock_owner;
953 if (req->f->op.flush)
954 req->f->op.flush(req, nodeid, &fi);
955 else
956 fuse_reply_err(req, ENOSYS);
959 static void do_release(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
961 struct fuse_release_in *arg = (struct fuse_release_in *) inarg;
962 struct fuse_file_info fi;
964 memset(&fi, 0, sizeof(fi));
965 fi.flags = arg->flags;
966 fi.fh = arg->fh;
967 fi.fh_old = fi.fh;
968 if (req->f->conn.proto_minor >= 8) {
969 fi.flush = (arg->release_flags & FUSE_RELEASE_FLUSH) ? 1 : 0;
970 fi.lock_owner = arg->lock_owner;
973 if (req->f->op.release)
974 req->f->op.release(req, nodeid, &fi);
975 else
976 fuse_reply_err(req, 0);
979 static void do_fsync(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
981 struct fuse_fsync_in *arg = (struct fuse_fsync_in *) inarg;
982 struct fuse_file_info fi;
984 memset(&fi, 0, sizeof(fi));
985 fi.fh = arg->fh;
986 fi.fh_old = fi.fh;
988 if (req->f->op.fsync)
989 req->f->op.fsync(req, nodeid, arg->fsync_flags & 1, &fi);
990 else
991 fuse_reply_err(req, ENOSYS);
994 static void do_opendir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
996 struct fuse_open_in *arg = (struct fuse_open_in *) inarg;
997 struct fuse_file_info fi;
999 memset(&fi, 0, sizeof(fi));
1000 fi.flags = arg->flags;
1002 if (req->f->op.opendir)
1003 req->f->op.opendir(req, nodeid, &fi);
1004 else
1005 fuse_reply_open(req, &fi);
1008 static void do_readdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1010 struct fuse_read_in *arg = (struct fuse_read_in *) inarg;
1011 struct fuse_file_info fi;
1013 memset(&fi, 0, sizeof(fi));
1014 fi.fh = arg->fh;
1015 fi.fh_old = fi.fh;
1017 if (req->f->op.readdir)
1018 req->f->op.readdir(req, nodeid, arg->size, arg->offset, &fi);
1019 else
1020 fuse_reply_err(req, ENOSYS);
1023 static void do_releasedir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1025 struct fuse_release_in *arg = (struct fuse_release_in *) inarg;
1026 struct fuse_file_info fi;
1028 memset(&fi, 0, sizeof(fi));
1029 fi.flags = arg->flags;
1030 fi.fh = arg->fh;
1031 fi.fh_old = fi.fh;
1033 if (req->f->op.releasedir)
1034 req->f->op.releasedir(req, nodeid, &fi);
1035 else
1036 fuse_reply_err(req, 0);
1039 static void do_fsyncdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1041 struct fuse_fsync_in *arg = (struct fuse_fsync_in *) inarg;
1042 struct fuse_file_info fi;
1044 memset(&fi, 0, sizeof(fi));
1045 fi.fh = arg->fh;
1046 fi.fh_old = fi.fh;
1048 if (req->f->op.fsyncdir)
1049 req->f->op.fsyncdir(req, nodeid, arg->fsync_flags & 1, &fi);
1050 else
1051 fuse_reply_err(req, ENOSYS);
1054 static void do_statfs(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1056 (void) nodeid;
1057 (void) inarg;
1059 if (req->f->op.statfs)
1060 req->f->op.statfs(req, nodeid);
1061 else {
1062 struct statvfs buf = {
1063 .f_namemax = 255,
1064 .f_bsize = 512,
1066 fuse_reply_statfs(req, &buf);
1070 static void do_setxattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1072 struct fuse_setxattr_in *arg = (struct fuse_setxattr_in *) inarg;
1073 char *name = PARAM(arg);
1074 char *value = name + strlen(name) + 1;
1076 if (req->f->op.setxattr)
1077 req->f->op.setxattr(req, nodeid, name, value, arg->size,
1078 arg->flags);
1079 else
1080 fuse_reply_err(req, ENOSYS);
1083 static void do_getxattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1085 struct fuse_getxattr_in *arg = (struct fuse_getxattr_in *) inarg;
1087 if (req->f->op.getxattr)
1088 req->f->op.getxattr(req, nodeid, PARAM(arg), arg->size);
1089 else
1090 fuse_reply_err(req, ENOSYS);
1093 static void do_listxattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1095 struct fuse_getxattr_in *arg = (struct fuse_getxattr_in *) inarg;
1097 if (req->f->op.listxattr)
1098 req->f->op.listxattr(req, nodeid, arg->size);
1099 else
1100 fuse_reply_err(req, ENOSYS);
1103 static void do_removexattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1105 char *name = (char *) inarg;
1107 if (req->f->op.removexattr)
1108 req->f->op.removexattr(req, nodeid, name);
1109 else
1110 fuse_reply_err(req, ENOSYS);
1113 static void convert_fuse_file_lock(struct fuse_file_lock *fl,
1114 struct flock *flock)
1116 memset(flock, 0, sizeof(struct flock));
1117 flock->l_type = fl->type;
1118 flock->l_whence = SEEK_SET;
1119 flock->l_start = fl->start;
1120 if (fl->end == OFFSET_MAX)
1121 flock->l_len = 0;
1122 else
1123 flock->l_len = fl->end - fl->start + 1;
1124 flock->l_pid = fl->pid;
1127 static void do_getlk(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1129 struct fuse_lk_in *arg = (struct fuse_lk_in *) inarg;
1130 struct fuse_file_info fi;
1131 struct flock flock;
1133 memset(&fi, 0, sizeof(fi));
1134 fi.fh = arg->fh;
1135 fi.lock_owner = arg->owner;
1137 convert_fuse_file_lock(&arg->lk, &flock);
1138 if (req->f->op.getlk)
1139 req->f->op.getlk(req, nodeid, &fi, &flock);
1140 else
1141 fuse_reply_err(req, ENOSYS);
1144 static void do_setlk_common(fuse_req_t req, fuse_ino_t nodeid,
1145 const void *inarg, int sleep)
1147 struct fuse_lk_in *arg = (struct fuse_lk_in *) inarg;
1148 struct fuse_file_info fi;
1149 struct flock flock;
1151 memset(&fi, 0, sizeof(fi));
1152 fi.fh = arg->fh;
1153 fi.lock_owner = arg->owner;
1155 convert_fuse_file_lock(&arg->lk, &flock);
1156 if (req->f->op.setlk)
1157 req->f->op.setlk(req, nodeid, &fi, &flock, sleep);
1158 else
1159 fuse_reply_err(req, ENOSYS);
1162 static void do_setlk(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1164 do_setlk_common(req, nodeid, inarg, 0);
1167 static void do_setlkw(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1169 do_setlk_common(req, nodeid, inarg, 1);
1172 static int find_interrupted(struct fuse_ll *f, struct fuse_req *req)
1174 struct fuse_req *curr;
1176 for (curr = f->list.next; curr != &f->list; curr = curr->next) {
1177 if (curr->unique == req->u.i.unique) {
1178 fuse_interrupt_func_t func;
1179 void *data;
1181 curr->ctr++;
1182 pthread_mutex_unlock(&f->lock);
1184 /* Ugh, ugly locking */
1185 pthread_mutex_lock(&curr->lock);
1186 pthread_mutex_lock(&f->lock);
1187 curr->interrupted = 1;
1188 func = curr->u.ni.func;
1189 data = curr->u.ni.data;
1190 pthread_mutex_unlock(&f->lock);
1191 if (func)
1192 func(curr, data);
1193 pthread_mutex_unlock(&curr->lock);
1195 pthread_mutex_lock(&f->lock);
1196 curr->ctr--;
1197 if (!curr->ctr)
1198 destroy_req(curr);
1200 return 1;
1203 for (curr = f->interrupts.next; curr != &f->interrupts;
1204 curr = curr->next) {
1205 if (curr->u.i.unique == req->u.i.unique)
1206 return 1;
1208 return 0;
1211 static void do_interrupt(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1213 struct fuse_interrupt_in *arg = (struct fuse_interrupt_in *) inarg;
1214 struct fuse_ll *f = req->f;
1216 (void) nodeid;
1217 if (f->debug)
1218 fprintf(stderr, "INTERRUPT: %llu\n",
1219 (unsigned long long) arg->unique);
1221 req->u.i.unique = arg->unique;
1223 pthread_mutex_lock(&f->lock);
1224 if (find_interrupted(f, req))
1225 destroy_req(req);
1226 else
1227 list_add_req(req, &f->interrupts);
1228 pthread_mutex_unlock(&f->lock);
1231 static struct fuse_req *check_interrupt(struct fuse_ll *f, struct fuse_req *req)
1233 struct fuse_req *curr;
1235 for (curr = f->interrupts.next; curr != &f->interrupts;
1236 curr = curr->next) {
1237 if (curr->u.i.unique == req->unique) {
1238 req->interrupted = 1;
1239 list_del_req(curr);
1240 free(curr);
1241 return NULL;
1244 curr = f->interrupts.next;
1245 if (curr != &f->interrupts) {
1246 list_del_req(curr);
1247 list_init_req(curr);
1248 return curr;
1249 } else
1250 return NULL;
1253 static void do_bmap(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1255 struct fuse_bmap_in *arg = (struct fuse_bmap_in *) inarg;
1257 if (req->f->op.bmap)
1258 req->f->op.bmap(req, nodeid, arg->blocksize, arg->block);
1259 else
1260 fuse_reply_err(req, ENOSYS);
1263 static void do_ioctl(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1265 struct fuse_ioctl_in *arg = (struct fuse_ioctl_in *) inarg;
1266 unsigned int flags = arg->flags;
1267 void *in_buf = arg->in_size ? PARAM(arg) : NULL;
1268 struct fuse_file_info fi;
1270 memset(&fi, 0, sizeof(fi));
1271 fi.fh = arg->fh;
1272 fi.fh_old = fi.fh;
1274 if (req->f->op.ioctl)
1275 req->f->op.ioctl(req, nodeid, arg->cmd,
1276 (void *)(uintptr_t)arg->arg, &fi, flags,
1277 in_buf, arg->in_size, arg->out_size);
1278 else
1279 fuse_reply_err(req, ENOSYS);
1282 void fuse_pollhandle_destroy(struct fuse_pollhandle *ph)
1284 free(ph);
1287 static void do_poll(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1289 struct fuse_poll_in *arg = (struct fuse_poll_in *) inarg;
1290 struct fuse_file_info fi;
1292 memset(&fi, 0, sizeof(fi));
1293 fi.fh = arg->fh;
1294 fi.fh_old = fi.fh;
1296 if (req->f->op.poll) {
1297 struct fuse_pollhandle *ph = NULL;
1299 if (arg->flags & FUSE_POLL_SCHEDULE_NOTIFY) {
1300 ph = malloc(sizeof(struct fuse_pollhandle));
1301 if (ph == NULL) {
1302 fuse_reply_err(req, ENOMEM);
1303 return;
1305 ph->kh = arg->kh;
1306 ph->ch = req->ch;
1307 ph->f = req->f;
1310 req->f->op.poll(req, nodeid, &fi, ph);
1311 } else {
1312 fuse_reply_err(req, ENOSYS);
1316 static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1318 struct fuse_init_in *arg = (struct fuse_init_in *) inarg;
1319 struct fuse_init_out outarg;
1320 struct fuse_ll *f = req->f;
1321 size_t bufsize = fuse_chan_bufsize(req->ch);
1323 (void) nodeid;
1324 if (f->debug) {
1325 fprintf(stderr, "INIT: %u.%u\n", arg->major, arg->minor);
1326 if (arg->major == 7 && arg->minor >= 6) {
1327 fprintf(stderr, "flags=0x%08x\n", arg->flags);
1328 fprintf(stderr, "max_readahead=0x%08x\n",
1329 arg->max_readahead);
1332 f->conn.proto_major = arg->major;
1333 f->conn.proto_minor = arg->minor;
1334 f->conn.capable = 0;
1335 f->conn.want = 0;
1337 memset(&outarg, 0, sizeof(outarg));
1338 outarg.major = FUSE_KERNEL_VERSION;
1339 outarg.minor = FUSE_KERNEL_MINOR_VERSION;
1341 if (arg->major < 7) {
1342 fprintf(stderr, "fuse: unsupported protocol version: %u.%u\n",
1343 arg->major, arg->minor);
1344 fuse_reply_err(req, EPROTO);
1345 return;
1348 if (arg->major > 7) {
1349 /* Wait for a second INIT request with a 7.X version */
1350 send_reply_ok(req, &outarg, sizeof(outarg));
1351 return;
1354 if (arg->minor >= 6) {
1355 if (f->conn.async_read)
1356 f->conn.async_read = arg->flags & FUSE_ASYNC_READ;
1357 if (arg->max_readahead < f->conn.max_readahead)
1358 f->conn.max_readahead = arg->max_readahead;
1359 if (arg->flags & FUSE_ASYNC_READ)
1360 f->conn.capable |= FUSE_CAP_ASYNC_READ;
1361 if (arg->flags & FUSE_POSIX_LOCKS)
1362 f->conn.capable |= FUSE_CAP_POSIX_LOCKS;
1363 if (arg->flags & FUSE_ATOMIC_O_TRUNC)
1364 f->conn.capable |= FUSE_CAP_ATOMIC_O_TRUNC;
1365 if (arg->flags & FUSE_EXPORT_SUPPORT)
1366 f->conn.capable |= FUSE_CAP_EXPORT_SUPPORT;
1367 if (arg->flags & FUSE_BIG_WRITES)
1368 f->conn.capable |= FUSE_CAP_BIG_WRITES;
1369 if (arg->flags & FUSE_DONT_MASK)
1370 f->conn.capable |= FUSE_CAP_DONT_MASK;
1371 } else {
1372 f->conn.async_read = 0;
1373 f->conn.max_readahead = 0;
1376 if (req->f->conn.proto_minor >= 14) {
1377 f->conn.capable |= FUSE_CAP_SPLICE_WRITE | FUSE_CAP_SPLICE_MOVE;
1378 if (!f->no_splice_write)
1379 f->conn.want |= FUSE_CAP_SPLICE_WRITE;
1380 if (!f->no_splice_move)
1381 f->conn.want |= FUSE_CAP_SPLICE_MOVE;
1384 if (f->atomic_o_trunc)
1385 f->conn.want |= FUSE_CAP_ATOMIC_O_TRUNC;
1386 if (f->op.getlk && f->op.setlk && !f->no_remote_lock)
1387 f->conn.want |= FUSE_CAP_POSIX_LOCKS;
1388 if (f->big_writes)
1389 f->conn.want |= FUSE_CAP_BIG_WRITES;
1391 if (bufsize < FUSE_MIN_READ_BUFFER) {
1392 fprintf(stderr, "fuse: warning: buffer size too small: %zu\n",
1393 bufsize);
1394 bufsize = FUSE_MIN_READ_BUFFER;
1397 bufsize -= 4096;
1398 if (bufsize < f->conn.max_write)
1399 f->conn.max_write = bufsize;
1401 f->got_init = 1;
1402 if (f->op.init)
1403 f->op.init(f->userdata, &f->conn);
1405 if (f->conn.async_read || (f->conn.want & FUSE_CAP_ASYNC_READ))
1406 outarg.flags |= FUSE_ASYNC_READ;
1407 if (f->conn.want & FUSE_CAP_POSIX_LOCKS)
1408 outarg.flags |= FUSE_POSIX_LOCKS;
1409 if (f->conn.want & FUSE_CAP_ATOMIC_O_TRUNC)
1410 outarg.flags |= FUSE_ATOMIC_O_TRUNC;
1411 if (f->conn.want & FUSE_CAP_EXPORT_SUPPORT)
1412 outarg.flags |= FUSE_EXPORT_SUPPORT;
1413 if (f->conn.want & FUSE_CAP_BIG_WRITES)
1414 outarg.flags |= FUSE_BIG_WRITES;
1415 if (f->conn.want & FUSE_CAP_DONT_MASK)
1416 outarg.flags |= FUSE_DONT_MASK;
1417 outarg.max_readahead = f->conn.max_readahead;
1418 outarg.max_write = f->conn.max_write;
1419 if (f->conn.proto_minor >= 13) {
1420 if (f->conn.max_background >= (1 << 16))
1421 f->conn.max_background = (1 << 16) - 1;
1422 if (f->conn.congestion_threshold > f->conn.max_background)
1423 f->conn.congestion_threshold = f->conn.max_background;
1424 if (!f->conn.congestion_threshold) {
1425 f->conn.congestion_threshold =
1426 f->conn.max_background * 3 / 4;
1429 outarg.max_background = f->conn.max_background;
1430 outarg.congestion_threshold = f->conn.congestion_threshold;
1433 if (f->debug) {
1434 fprintf(stderr, " INIT: %u.%u\n", outarg.major, outarg.minor);
1435 fprintf(stderr, " flags=0x%08x\n", outarg.flags);
1436 fprintf(stderr, " max_readahead=0x%08x\n",
1437 outarg.max_readahead);
1438 fprintf(stderr, " max_write=0x%08x\n", outarg.max_write);
1439 fprintf(stderr, " max_background=%i\n",
1440 outarg.max_background);
1441 fprintf(stderr, " congestion_threshold=%i\n",
1442 outarg.congestion_threshold);
1445 send_reply_ok(req, &outarg, arg->minor < 5 ? 8 : sizeof(outarg));
1448 static void do_destroy(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1450 struct fuse_ll *f = req->f;
1452 (void) nodeid;
1453 (void) inarg;
1455 f->got_destroy = 1;
1456 if (f->op.destroy)
1457 f->op.destroy(f->userdata);
1459 send_reply_ok(req, NULL, 0);
1462 static int send_notify_iov(struct fuse_ll *f, struct fuse_chan *ch,
1463 int notify_code, struct iovec *iov, int count)
1465 struct fuse_out_header out;
1467 out.unique = 0;
1468 out.error = notify_code;
1469 iov[0].iov_base = &out;
1470 iov[0].iov_len = sizeof(struct fuse_out_header);
1471 out.len = iov_length(iov, count);
1473 if (f->debug)
1474 fprintf(stderr, "NOTIFY: code=%d count=%d length=%u\n",
1475 notify_code, count, out.len);
1477 return fuse_chan_send(ch, iov, count);
1480 int fuse_lowlevel_notify_poll(struct fuse_pollhandle *ph)
1482 if (ph != NULL) {
1483 struct fuse_notify_poll_wakeup_out outarg;
1484 struct iovec iov[2];
1486 outarg.kh = ph->kh;
1488 iov[1].iov_base = &outarg;
1489 iov[1].iov_len = sizeof(outarg);
1491 return send_notify_iov(ph->f, ph->ch, FUSE_NOTIFY_POLL, iov, 2);
1492 } else {
1493 return 0;
1497 int fuse_lowlevel_notify_inval_inode(struct fuse_chan *ch, fuse_ino_t ino,
1498 off_t off, off_t len)
1500 struct fuse_notify_inval_inode_out outarg;
1501 struct fuse_ll *f;
1502 struct iovec iov[2];
1504 if (!ch)
1505 return -EINVAL;
1507 f = (struct fuse_ll *)fuse_session_data(fuse_chan_session(ch));
1508 if (!f)
1509 return -ENODEV;
1511 outarg.ino = ino;
1512 outarg.off = off;
1513 outarg.len = len;
1515 iov[1].iov_base = &outarg;
1516 iov[1].iov_len = sizeof(outarg);
1518 return send_notify_iov(f, ch, FUSE_NOTIFY_INVAL_INODE, iov, 2);
1521 int fuse_lowlevel_notify_inval_entry(struct fuse_chan *ch, fuse_ino_t parent,
1522 const char *name, size_t namelen)
1524 struct fuse_notify_inval_entry_out outarg;
1525 struct fuse_ll *f;
1526 struct iovec iov[3];
1528 if (!ch)
1529 return -EINVAL;
1531 f = (struct fuse_ll *)fuse_session_data(fuse_chan_session(ch));
1532 if (!f)
1533 return -ENODEV;
1535 outarg.parent = parent;
1536 outarg.namelen = namelen;
1537 outarg.padding = 0;
1539 iov[1].iov_base = &outarg;
1540 iov[1].iov_len = sizeof(outarg);
1541 iov[2].iov_base = (void *)name;
1542 iov[2].iov_len = namelen + 1;
1544 return send_notify_iov(f, ch, FUSE_NOTIFY_INVAL_ENTRY, iov, 3);
1547 void *fuse_req_userdata(fuse_req_t req)
1549 return req->f->userdata;
1552 const struct fuse_ctx *fuse_req_ctx(fuse_req_t req)
1554 return &req->ctx;
1558 * The size of fuse_ctx got extended, so need to be careful about
1559 * incompatibility (i.e. a new binary cannot work with an old
1560 * library).
1562 const struct fuse_ctx *fuse_req_ctx_compat24(fuse_req_t req);
1563 const struct fuse_ctx *fuse_req_ctx_compat24(fuse_req_t req)
1565 return fuse_req_ctx(req);
1567 FUSE_SYMVER(".symver fuse_req_ctx_compat24,fuse_req_ctx@FUSE_2.4");
1570 void fuse_req_interrupt_func(fuse_req_t req, fuse_interrupt_func_t func,
1571 void *data)
1573 pthread_mutex_lock(&req->lock);
1574 pthread_mutex_lock(&req->f->lock);
1575 req->u.ni.func = func;
1576 req->u.ni.data = data;
1577 pthread_mutex_unlock(&req->f->lock);
1578 if (req->interrupted && func)
1579 func(req, data);
1580 pthread_mutex_unlock(&req->lock);
1583 int fuse_req_interrupted(fuse_req_t req)
1585 int interrupted;
1587 pthread_mutex_lock(&req->f->lock);
1588 interrupted = req->interrupted;
1589 pthread_mutex_unlock(&req->f->lock);
1591 return interrupted;
1594 static struct {
1595 void (*func)(fuse_req_t, fuse_ino_t, const void *);
1596 const char *name;
1597 } fuse_ll_ops[] = {
1598 [FUSE_LOOKUP] = { do_lookup, "LOOKUP" },
1599 [FUSE_FORGET] = { do_forget, "FORGET" },
1600 [FUSE_GETATTR] = { do_getattr, "GETATTR" },
1601 [FUSE_SETATTR] = { do_setattr, "SETATTR" },
1602 [FUSE_READLINK] = { do_readlink, "READLINK" },
1603 [FUSE_SYMLINK] = { do_symlink, "SYMLINK" },
1604 [FUSE_MKNOD] = { do_mknod, "MKNOD" },
1605 [FUSE_MKDIR] = { do_mkdir, "MKDIR" },
1606 [FUSE_UNLINK] = { do_unlink, "UNLINK" },
1607 [FUSE_RMDIR] = { do_rmdir, "RMDIR" },
1608 [FUSE_RENAME] = { do_rename, "RENAME" },
1609 [FUSE_LINK] = { do_link, "LINK" },
1610 [FUSE_OPEN] = { do_open, "OPEN" },
1611 [FUSE_READ] = { do_read, "READ" },
1612 [FUSE_WRITE] = { do_write, "WRITE" },
1613 [FUSE_STATFS] = { do_statfs, "STATFS" },
1614 [FUSE_RELEASE] = { do_release, "RELEASE" },
1615 [FUSE_FSYNC] = { do_fsync, "FSYNC" },
1616 [FUSE_SETXATTR] = { do_setxattr, "SETXATTR" },
1617 [FUSE_GETXATTR] = { do_getxattr, "GETXATTR" },
1618 [FUSE_LISTXATTR] = { do_listxattr, "LISTXATTR" },
1619 [FUSE_REMOVEXATTR] = { do_removexattr, "REMOVEXATTR" },
1620 [FUSE_FLUSH] = { do_flush, "FLUSH" },
1621 [FUSE_INIT] = { do_init, "INIT" },
1622 [FUSE_OPENDIR] = { do_opendir, "OPENDIR" },
1623 [FUSE_READDIR] = { do_readdir, "READDIR" },
1624 [FUSE_RELEASEDIR] = { do_releasedir, "RELEASEDIR" },
1625 [FUSE_FSYNCDIR] = { do_fsyncdir, "FSYNCDIR" },
1626 [FUSE_GETLK] = { do_getlk, "GETLK" },
1627 [FUSE_SETLK] = { do_setlk, "SETLK" },
1628 [FUSE_SETLKW] = { do_setlkw, "SETLKW" },
1629 [FUSE_ACCESS] = { do_access, "ACCESS" },
1630 [FUSE_CREATE] = { do_create, "CREATE" },
1631 [FUSE_INTERRUPT] = { do_interrupt, "INTERRUPT" },
1632 [FUSE_BMAP] = { do_bmap, "BMAP" },
1633 [FUSE_IOCTL] = { do_ioctl, "IOCTL" },
1634 [FUSE_POLL] = { do_poll, "POLL" },
1635 [FUSE_DESTROY] = { do_destroy, "DESTROY" },
1636 [CUSE_INIT] = { cuse_lowlevel_init, "CUSE_INIT" },
1639 #define FUSE_MAXOP (sizeof(fuse_ll_ops) / sizeof(fuse_ll_ops[0]))
1641 static const char *opname(enum fuse_opcode opcode)
1643 if (opcode >= FUSE_MAXOP || !fuse_ll_ops[opcode].name)
1644 return "???";
1645 else
1646 return fuse_ll_ops[opcode].name;
1649 static void fuse_ll_process(void *data, const char *buf, size_t len,
1650 struct fuse_chan *ch)
1652 struct fuse_ll *f = (struct fuse_ll *) data;
1653 struct fuse_in_header *in = (struct fuse_in_header *) buf;
1654 const void *inarg = buf + sizeof(struct fuse_in_header);
1655 struct fuse_req *req;
1656 int err;
1658 if (f->debug)
1659 fprintf(stderr,
1660 "unique: %llu, opcode: %s (%i), nodeid: %lu, insize: %zu\n",
1661 (unsigned long long) in->unique,
1662 opname((enum fuse_opcode) in->opcode), in->opcode,
1663 (unsigned long) in->nodeid, len);
1665 req = (struct fuse_req *) calloc(1, sizeof(struct fuse_req));
1666 if (req == NULL) {
1667 fprintf(stderr, "fuse: failed to allocate request\n");
1668 return;
1671 req->f = f;
1672 req->unique = in->unique;
1673 req->ctx.uid = in->uid;
1674 req->ctx.gid = in->gid;
1675 req->ctx.pid = in->pid;
1676 req->ch = ch;
1677 req->ctr = 1;
1678 list_init_req(req);
1679 fuse_mutex_init(&req->lock);
1681 err = EIO;
1682 if (!f->got_init) {
1683 enum fuse_opcode expected;
1685 expected = f->cuse_data ? CUSE_INIT : FUSE_INIT;
1686 if (in->opcode != expected)
1687 goto reply_err;
1688 } else if (in->opcode == FUSE_INIT || in->opcode == CUSE_INIT)
1689 goto reply_err;
1691 err = EACCES;
1692 if (f->allow_root && in->uid != f->owner && in->uid != 0 &&
1693 in->opcode != FUSE_INIT && in->opcode != FUSE_READ &&
1694 in->opcode != FUSE_WRITE && in->opcode != FUSE_FSYNC &&
1695 in->opcode != FUSE_RELEASE && in->opcode != FUSE_READDIR &&
1696 in->opcode != FUSE_FSYNCDIR && in->opcode != FUSE_RELEASEDIR)
1697 goto reply_err;
1699 err = ENOSYS;
1700 if (in->opcode >= FUSE_MAXOP || !fuse_ll_ops[in->opcode].func)
1701 goto reply_err;
1702 if (in->opcode != FUSE_INTERRUPT) {
1703 struct fuse_req *intr;
1704 pthread_mutex_lock(&f->lock);
1705 intr = check_interrupt(f, req);
1706 list_add_req(req, &f->list);
1707 pthread_mutex_unlock(&f->lock);
1708 if (intr)
1709 fuse_reply_err(intr, EAGAIN);
1711 fuse_ll_ops[in->opcode].func(req, in->nodeid, inarg);
1712 return;
1714 reply_err:
1715 fuse_reply_err(req, err);
1718 enum {
1719 KEY_HELP,
1720 KEY_VERSION,
1723 static struct fuse_opt fuse_ll_opts[] = {
1724 { "debug", offsetof(struct fuse_ll, debug), 1 },
1725 { "-d", offsetof(struct fuse_ll, debug), 1 },
1726 { "allow_root", offsetof(struct fuse_ll, allow_root), 1 },
1727 { "max_write=%u", offsetof(struct fuse_ll, conn.max_write), 0 },
1728 { "max_readahead=%u", offsetof(struct fuse_ll, conn.max_readahead), 0 },
1729 { "max_background=%u", offsetof(struct fuse_ll, conn.max_background), 0 },
1730 { "congestion_threshold=%u",
1731 offsetof(struct fuse_ll, conn.congestion_threshold), 0 },
1732 { "async_read", offsetof(struct fuse_ll, conn.async_read), 1 },
1733 { "sync_read", offsetof(struct fuse_ll, conn.async_read), 0 },
1734 { "atomic_o_trunc", offsetof(struct fuse_ll, atomic_o_trunc), 1},
1735 { "no_remote_lock", offsetof(struct fuse_ll, no_remote_lock), 1},
1736 { "big_writes", offsetof(struct fuse_ll, big_writes), 1},
1737 { "no_splice_write", offsetof(struct fuse_ll, no_splice_write), 1},
1738 { "no_splice_move", offsetof(struct fuse_ll, no_splice_move), 1},
1739 FUSE_OPT_KEY("max_read=", FUSE_OPT_KEY_DISCARD),
1740 FUSE_OPT_KEY("-h", KEY_HELP),
1741 FUSE_OPT_KEY("--help", KEY_HELP),
1742 FUSE_OPT_KEY("-V", KEY_VERSION),
1743 FUSE_OPT_KEY("--version", KEY_VERSION),
1744 FUSE_OPT_END
1747 static void fuse_ll_version(void)
1749 fprintf(stderr, "using FUSE kernel interface version %i.%i\n",
1750 FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION);
1753 static void fuse_ll_help(void)
1755 fprintf(stderr,
1756 " -o max_write=N set maximum size of write requests\n"
1757 " -o max_readahead=N set maximum readahead\n"
1758 " -o max_background=N set number of maximum background requests\n"
1759 " -o congestion_threshold=N set kernel's congestion threshold\n"
1760 " -o async_read perform reads asynchronously (default)\n"
1761 " -o sync_read perform reads synchronously\n"
1762 " -o atomic_o_trunc enable atomic open+truncate support\n"
1763 " -o big_writes enable larger than 4kB writes\n"
1764 " -o no_remote_lock disable remote file locking\n"
1765 " -o no_splice_write don't use splice to write to the fuse device\n"
1766 " -o no_splice_move don't move data while splicing to the fuse device\n"
1770 static int fuse_ll_opt_proc(void *data, const char *arg, int key,
1771 struct fuse_args *outargs)
1773 (void) data; (void) outargs;
1775 switch (key) {
1776 case KEY_HELP:
1777 fuse_ll_help();
1778 break;
1780 case KEY_VERSION:
1781 fuse_ll_version();
1782 break;
1784 default:
1785 fprintf(stderr, "fuse: unknown option `%s'\n", arg);
1788 return -1;
1791 int fuse_lowlevel_is_lib_option(const char *opt)
1793 return fuse_opt_match(fuse_ll_opts, opt);
1796 static void fuse_ll_destroy(void *data)
1798 struct fuse_ll *f = (struct fuse_ll *) data;
1799 struct fuse_ll_pipe *llp;
1801 if (f->got_init && !f->got_destroy) {
1802 if (f->op.destroy)
1803 f->op.destroy(f->userdata);
1805 llp = pthread_getspecific(f->pipe_key);
1806 if (llp != NULL)
1807 fuse_ll_pipe_free(llp);
1808 pthread_key_delete(f->pipe_key);
1809 pthread_mutex_destroy(&f->lock);
1810 free(f->cuse_data);
1811 free(f);
1814 static void fuse_ll_pipe_destructor(void *data)
1816 struct fuse_ll_pipe *llp = data;
1817 fuse_ll_pipe_free(llp);
1821 * always call fuse_lowlevel_new_common() internally, to work around a
1822 * misfeature in the FreeBSD runtime linker, which links the old
1823 * version of a symbol to internal references.
1825 struct fuse_session *fuse_lowlevel_new_common(struct fuse_args *args,
1826 const struct fuse_lowlevel_ops *op,
1827 size_t op_size, void *userdata)
1829 int err;
1830 struct fuse_ll *f;
1831 struct fuse_session *se;
1832 struct fuse_session_ops sop = {
1833 .process = fuse_ll_process,
1834 .destroy = fuse_ll_destroy,
1837 if (sizeof(struct fuse_lowlevel_ops) < op_size) {
1838 fprintf(stderr, "fuse: warning: library too old, some operations may not work\n");
1839 op_size = sizeof(struct fuse_lowlevel_ops);
1842 f = (struct fuse_ll *) calloc(1, sizeof(struct fuse_ll));
1843 if (f == NULL) {
1844 fprintf(stderr, "fuse: failed to allocate fuse object\n");
1845 goto out;
1848 f->conn.async_read = 1;
1849 f->conn.max_write = UINT_MAX;
1850 f->conn.max_readahead = UINT_MAX;
1851 f->atomic_o_trunc = 0;
1852 list_init_req(&f->list);
1853 list_init_req(&f->interrupts);
1854 fuse_mutex_init(&f->lock);
1856 err = pthread_key_create(&f->pipe_key, fuse_ll_pipe_destructor);
1857 if (err) {
1858 fprintf(stderr, "fuse: failed to create thread specific key: %s\n",
1859 strerror(err));
1860 goto out_free;
1863 if (fuse_opt_parse(args, f, fuse_ll_opts, fuse_ll_opt_proc) == -1)
1864 goto out_key_destroy;
1866 if (f->debug)
1867 fprintf(stderr, "FUSE library version: %s\n", PACKAGE_VERSION);
1869 memcpy(&f->op, op, op_size);
1870 f->owner = getuid();
1871 f->userdata = userdata;
1873 se = fuse_session_new(&sop, f);
1874 if (!se)
1875 goto out_key_destroy;
1877 return se;
1879 out_key_destroy:
1880 pthread_key_delete(f->pipe_key);
1881 out_free:
1882 pthread_mutex_destroy(&f->lock);
1883 free(f);
1884 out:
1885 return NULL;
1889 struct fuse_session *fuse_lowlevel_new(struct fuse_args *args,
1890 const struct fuse_lowlevel_ops *op,
1891 size_t op_size, void *userdata)
1893 return fuse_lowlevel_new_common(args, op, op_size, userdata);
1896 #ifdef linux
1897 int fuse_req_getgroups(fuse_req_t req, int size, gid_t list[])
1899 char *buf;
1900 size_t bufsize = 1024;
1901 char path[128];
1902 int ret;
1903 int fd;
1904 unsigned long pid = req->ctx.pid;
1905 char *s;
1907 sprintf(path, "/proc/%lu/task/%lu/status", pid, pid);
1909 retry:
1910 buf = malloc(bufsize);
1911 if (buf == NULL)
1912 return -ENOMEM;
1914 ret = -EIO;
1915 fd = open(path, O_RDONLY);
1916 if (fd == -1)
1917 goto out_free;
1919 ret = read(fd, buf, bufsize);
1920 close(fd);
1921 if (ret == -1) {
1922 ret = -EIO;
1923 goto out_free;
1926 if (ret == bufsize) {
1927 free(buf);
1928 bufsize *= 4;
1929 goto retry;
1932 ret = -EIO;
1933 s = strstr(buf, "\nGroups:");
1934 if (s == NULL)
1935 goto out_free;
1937 s += 8;
1938 ret = 0;
1939 while (1) {
1940 char *end;
1941 unsigned long val = strtoul(s, &end, 0);
1942 if (end == s)
1943 break;
1945 s = end;
1946 if (ret < size)
1947 list[ret] = val;
1948 ret++;
1951 out_free:
1952 free(buf);
1953 return ret;
1955 #else /* linux */
1957 * This is currently not implemented on other than Linux...
1959 int fuse_req_getgroups(fuse_req_t req, int size, gid_t list[])
1961 return -ENOSYS;
1963 #endif
1965 #ifndef __FreeBSD__
1967 static void fill_open_compat(struct fuse_open_out *arg,
1968 const struct fuse_file_info_compat *f)
1970 arg->fh = f->fh;
1971 if (f->direct_io)
1972 arg->open_flags |= FOPEN_DIRECT_IO;
1973 if (f->keep_cache)
1974 arg->open_flags |= FOPEN_KEEP_CACHE;
1977 static void convert_statfs_compat(const struct statfs *compatbuf,
1978 struct statvfs *buf)
1980 buf->f_bsize = compatbuf->f_bsize;
1981 buf->f_blocks = compatbuf->f_blocks;
1982 buf->f_bfree = compatbuf->f_bfree;
1983 buf->f_bavail = compatbuf->f_bavail;
1984 buf->f_files = compatbuf->f_files;
1985 buf->f_ffree = compatbuf->f_ffree;
1986 buf->f_namemax = compatbuf->f_namelen;
1989 int fuse_reply_open_compat(fuse_req_t req,
1990 const struct fuse_file_info_compat *f)
1992 struct fuse_open_out arg;
1994 memset(&arg, 0, sizeof(arg));
1995 fill_open_compat(&arg, f);
1996 return send_reply_ok(req, &arg, sizeof(arg));
1999 int fuse_reply_statfs_compat(fuse_req_t req, const struct statfs *stbuf)
2001 struct statvfs newbuf;
2003 memset(&newbuf, 0, sizeof(newbuf));
2004 convert_statfs_compat(stbuf, &newbuf);
2006 return fuse_reply_statfs(req, &newbuf);
2009 struct fuse_session *fuse_lowlevel_new_compat(const char *opts,
2010 const struct fuse_lowlevel_ops_compat *op,
2011 size_t op_size, void *userdata)
2013 struct fuse_session *se;
2014 struct fuse_args args = FUSE_ARGS_INIT(0, NULL);
2016 if (opts &&
2017 (fuse_opt_add_arg(&args, "") == -1 ||
2018 fuse_opt_add_arg(&args, "-o") == -1 ||
2019 fuse_opt_add_arg(&args, opts) == -1)) {
2020 fuse_opt_free_args(&args);
2021 return NULL;
2023 se = fuse_lowlevel_new(&args, (const struct fuse_lowlevel_ops *) op,
2024 op_size, userdata);
2025 fuse_opt_free_args(&args);
2027 return se;
2030 struct fuse_ll_compat_conf {
2031 unsigned max_read;
2032 int set_max_read;
2035 static const struct fuse_opt fuse_ll_opts_compat[] = {
2036 { "max_read=", offsetof(struct fuse_ll_compat_conf, set_max_read), 1 },
2037 { "max_read=%u", offsetof(struct fuse_ll_compat_conf, max_read), 0 },
2038 FUSE_OPT_KEY("max_read=", FUSE_OPT_KEY_KEEP),
2039 FUSE_OPT_END
2042 int fuse_sync_compat_args(struct fuse_args *args)
2044 struct fuse_ll_compat_conf conf;
2046 memset(&conf, 0, sizeof(conf));
2047 if (fuse_opt_parse(args, &conf, fuse_ll_opts_compat, NULL) == -1)
2048 return -1;
2050 if (fuse_opt_insert_arg(args, 1, "-osync_read"))
2051 return -1;
2053 if (conf.set_max_read) {
2054 char tmpbuf[64];
2056 sprintf(tmpbuf, "-omax_readahead=%u", conf.max_read);
2057 if (fuse_opt_insert_arg(args, 1, tmpbuf) == -1)
2058 return -1;
2060 return 0;
2063 FUSE_SYMVER(".symver fuse_reply_statfs_compat,fuse_reply_statfs@FUSE_2.4");
2064 FUSE_SYMVER(".symver fuse_reply_open_compat,fuse_reply_open@FUSE_2.4");
2065 FUSE_SYMVER(".symver fuse_lowlevel_new_compat,fuse_lowlevel_new@FUSE_2.4");
2067 #else /* __FreeBSD__ */
2069 int fuse_sync_compat_args(struct fuse_args *args)
2071 (void) args;
2072 return 0;
2075 #endif /* __FreeBSD__ */
2077 struct fuse_session *fuse_lowlevel_new_compat25(struct fuse_args *args,
2078 const struct fuse_lowlevel_ops_compat25 *op,
2079 size_t op_size, void *userdata)
2081 if (fuse_sync_compat_args(args) == -1)
2082 return NULL;
2084 return fuse_lowlevel_new_common(args,
2085 (const struct fuse_lowlevel_ops *) op,
2086 op_size, userdata);
2089 FUSE_SYMVER(".symver fuse_lowlevel_new_compat25,fuse_lowlevel_new@FUSE_2.5");