libfuse
fuse_lowlevel.c
1 /*
2  FUSE: Filesystem in Userspace
3  Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
4 
5  Implementation of (most of) the low-level FUSE API. The session loop
6  functions are implemented in separate files.
7 
8  This program can be distributed under the terms of the GNU LGPLv2.
9  See the file COPYING.LIB
10 */
11 
12 #define _GNU_SOURCE
13 
14 #include "config.h"
15 #include "fuse_i.h"
16 #include "fuse_kernel.h"
17 #include "fuse_opt.h"
18 #include "fuse_misc.h"
19 #include "mount_util.h"
20 
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <stddef.h>
24 #include <string.h>
25 #include <unistd.h>
26 #include <limits.h>
27 #include <errno.h>
28 #include <assert.h>
29 #include <sys/file.h>
30 
31 #ifndef F_LINUX_SPECIFIC_BASE
32 #define F_LINUX_SPECIFIC_BASE 1024
33 #endif
34 #ifndef F_SETPIPE_SZ
35 #define F_SETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 7)
36 #endif
37 
38 
39 #define PARAM(inarg) (((char *)(inarg)) + sizeof(*(inarg)))
40 #define OFFSET_MAX 0x7fffffffffffffffLL
41 
42 #define container_of(ptr, type, member) ({ \
43  const typeof( ((type *)0)->member ) *__mptr = (ptr); \
44  (type *)( (char *)__mptr - offsetof(type,member) );})
45 
46 struct fuse_pollhandle {
47  uint64_t kh;
48  struct fuse_session *se;
49 };
50 
51 static size_t pagesize;
52 
53 static __attribute__((constructor)) void fuse_ll_init_pagesize(void)
54 {
55  pagesize = getpagesize();
56 }
57 
58 static void convert_stat(const struct stat *stbuf, struct fuse_attr *attr)
59 {
60  attr->ino = stbuf->st_ino;
61  attr->mode = stbuf->st_mode;
62  attr->nlink = stbuf->st_nlink;
63  attr->uid = stbuf->st_uid;
64  attr->gid = stbuf->st_gid;
65  attr->rdev = stbuf->st_rdev;
66  attr->size = stbuf->st_size;
67  attr->blksize = stbuf->st_blksize;
68  attr->blocks = stbuf->st_blocks;
69  attr->atime = stbuf->st_atime;
70  attr->mtime = stbuf->st_mtime;
71  attr->ctime = stbuf->st_ctime;
72  attr->atimensec = ST_ATIM_NSEC(stbuf);
73  attr->mtimensec = ST_MTIM_NSEC(stbuf);
74  attr->ctimensec = ST_CTIM_NSEC(stbuf);
75 }
76 
77 static void convert_attr(const struct fuse_setattr_in *attr, struct stat *stbuf)
78 {
79  stbuf->st_mode = attr->mode;
80  stbuf->st_uid = attr->uid;
81  stbuf->st_gid = attr->gid;
82  stbuf->st_size = attr->size;
83  stbuf->st_atime = attr->atime;
84  stbuf->st_mtime = attr->mtime;
85  stbuf->st_ctime = attr->ctime;
86  ST_ATIM_NSEC_SET(stbuf, attr->atimensec);
87  ST_MTIM_NSEC_SET(stbuf, attr->mtimensec);
88  ST_CTIM_NSEC_SET(stbuf, attr->ctimensec);
89 }
90 
91 static size_t iov_length(const struct iovec *iov, size_t count)
92 {
93  size_t seg;
94  size_t ret = 0;
95 
96  for (seg = 0; seg < count; seg++)
97  ret += iov[seg].iov_len;
98  return ret;
99 }
100 
101 static void list_init_req(struct fuse_req *req)
102 {
103  req->next = req;
104  req->prev = req;
105 }
106 
107 static void list_del_req(struct fuse_req *req)
108 {
109  struct fuse_req *prev = req->prev;
110  struct fuse_req *next = req->next;
111  prev->next = next;
112  next->prev = prev;
113 }
114 
115 static void list_add_req(struct fuse_req *req, struct fuse_req *next)
116 {
117  struct fuse_req *prev = next->prev;
118  req->next = next;
119  req->prev = prev;
120  prev->next = req;
121  next->prev = req;
122 }
123 
124 static void destroy_req(fuse_req_t req)
125 {
126  assert(req->ch == NULL);
127  pthread_mutex_destroy(&req->lock);
128  free(req);
129 }
130 
131 void fuse_free_req(fuse_req_t req)
132 {
133  int ctr;
134  struct fuse_session *se = req->se;
135 
136  pthread_mutex_lock(&se->lock);
137  req->u.ni.func = NULL;
138  req->u.ni.data = NULL;
139  list_del_req(req);
140  ctr = --req->ctr;
141  fuse_chan_put(req->ch);
142  req->ch = NULL;
143  pthread_mutex_unlock(&se->lock);
144  if (!ctr)
145  destroy_req(req);
146 }
147 
148 static struct fuse_req *fuse_ll_alloc_req(struct fuse_session *se)
149 {
150  struct fuse_req *req;
151 
152  req = (struct fuse_req *) calloc(1, sizeof(struct fuse_req));
153  if (req == NULL) {
154  fuse_log(FUSE_LOG_ERR, "fuse: failed to allocate request\n");
155  } else {
156  req->se = se;
157  req->ctr = 1;
158  list_init_req(req);
159  pthread_mutex_init(&req->lock, NULL);
160  }
161 
162  return req;
163 }
164 
165 /* Send data. If *ch* is NULL, send via session master fd */
166 static int fuse_send_msg(struct fuse_session *se, struct fuse_chan *ch,
167  struct iovec *iov, int count)
168 {
169  struct fuse_out_header *out = iov[0].iov_base;
170 
171  assert(se != NULL);
172  out->len = iov_length(iov, count);
173  if (se->debug) {
174  if (out->unique == 0) {
175  fuse_log(FUSE_LOG_DEBUG, "NOTIFY: code=%d length=%u\n",
176  out->error, out->len);
177  } else if (out->error) {
178  fuse_log(FUSE_LOG_DEBUG,
179  " unique: %llu, error: %i (%s), outsize: %i\n",
180  (unsigned long long) out->unique, out->error,
181  strerror(-out->error), out->len);
182  } else {
183  fuse_log(FUSE_LOG_DEBUG,
184  " unique: %llu, success, outsize: %i\n",
185  (unsigned long long) out->unique, out->len);
186  }
187  }
188 
189  ssize_t res;
190  if (se->io != NULL)
191  /* se->io->writev is never NULL if se->io is not NULL as
192  specified by fuse_session_custom_io()*/
193  res = se->io->writev(ch ? ch->fd : se->fd, iov, count,
194  se->userdata);
195  else
196  res = writev(ch ? ch->fd : se->fd, iov, count);
197 
198  int err = errno;
199 
200  if (res == -1) {
201  /* ENOENT means the operation was interrupted */
202  if (!fuse_session_exited(se) && err != ENOENT)
203  perror("fuse: writing device");
204  return -err;
205  }
206 
207  return 0;
208 }
209 
210 
211 int fuse_send_reply_iov_nofree(fuse_req_t req, int error, struct iovec *iov,
212  int count)
213 {
214  struct fuse_out_header out;
215 
216  if (error <= -1000 || error > 0) {
217  fuse_log(FUSE_LOG_ERR, "fuse: bad error value: %i\n", error);
218  error = -ERANGE;
219  }
220 
221  out.unique = req->unique;
222  out.error = error;
223 
224  iov[0].iov_base = &out;
225  iov[0].iov_len = sizeof(struct fuse_out_header);
226 
227  return fuse_send_msg(req->se, req->ch, iov, count);
228 }
229 
230 static int send_reply_iov(fuse_req_t req, int error, struct iovec *iov,
231  int count)
232 {
233  int res;
234 
235  res = fuse_send_reply_iov_nofree(req, error, iov, count);
236  fuse_free_req(req);
237  return res;
238 }
239 
240 static int send_reply(fuse_req_t req, int error, const void *arg,
241  size_t argsize)
242 {
243  struct iovec iov[2];
244  int count = 1;
245  if (argsize) {
246  iov[1].iov_base = (void *) arg;
247  iov[1].iov_len = argsize;
248  count++;
249  }
250  return send_reply_iov(req, error, iov, count);
251 }
252 
253 int fuse_reply_iov(fuse_req_t req, const struct iovec *iov, int count)
254 {
255  int res;
256  struct iovec *padded_iov;
257 
258  padded_iov = malloc((count + 1) * sizeof(struct iovec));
259  if (padded_iov == NULL)
260  return fuse_reply_err(req, ENOMEM);
261 
262  memcpy(padded_iov + 1, iov, count * sizeof(struct iovec));
263  count++;
264 
265  res = send_reply_iov(req, 0, padded_iov, count);
266  free(padded_iov);
267 
268  return res;
269 }
270 
271 
272 /* `buf` is allowed to be empty so that the proper size may be
273  allocated by the caller */
274 size_t fuse_add_direntry(fuse_req_t req, char *buf, size_t bufsize,
275  const char *name, const struct stat *stbuf, off_t off)
276 {
277  (void)req;
278  size_t namelen;
279  size_t entlen;
280  size_t entlen_padded;
281  struct fuse_dirent *dirent;
282 
283  namelen = strlen(name);
284  entlen = FUSE_NAME_OFFSET + namelen;
285  entlen_padded = FUSE_DIRENT_ALIGN(entlen);
286 
287  if ((buf == NULL) || (entlen_padded > bufsize))
288  return entlen_padded;
289 
290  dirent = (struct fuse_dirent*) buf;
291  dirent->ino = stbuf->st_ino;
292  dirent->off = off;
293  dirent->namelen = namelen;
294  dirent->type = (stbuf->st_mode & S_IFMT) >> 12;
295  memcpy(dirent->name, name, namelen);
296  memset(dirent->name + namelen, 0, entlen_padded - entlen);
297 
298  return entlen_padded;
299 }
300 
301 static void convert_statfs(const struct statvfs *stbuf,
302  struct fuse_kstatfs *kstatfs)
303 {
304  kstatfs->bsize = stbuf->f_bsize;
305  kstatfs->frsize = stbuf->f_frsize;
306  kstatfs->blocks = stbuf->f_blocks;
307  kstatfs->bfree = stbuf->f_bfree;
308  kstatfs->bavail = stbuf->f_bavail;
309  kstatfs->files = stbuf->f_files;
310  kstatfs->ffree = stbuf->f_ffree;
311  kstatfs->namelen = stbuf->f_namemax;
312 }
313 
314 static int send_reply_ok(fuse_req_t req, const void *arg, size_t argsize)
315 {
316  return send_reply(req, 0, arg, argsize);
317 }
318 
319 int fuse_reply_err(fuse_req_t req, int err)
320 {
321  return send_reply(req, -err, NULL, 0);
322 }
323 
325 {
326  fuse_free_req(req);
327 }
328 
329 static unsigned long calc_timeout_sec(double t)
330 {
331  if (t > (double) ULONG_MAX)
332  return ULONG_MAX;
333  else if (t < 0.0)
334  return 0;
335  else
336  return (unsigned long) t;
337 }
338 
339 static unsigned int calc_timeout_nsec(double t)
340 {
341  double f = t - (double) calc_timeout_sec(t);
342  if (f < 0.0)
343  return 0;
344  else if (f >= 0.999999999)
345  return 999999999;
346  else
347  return (unsigned int) (f * 1.0e9);
348 }
349 
350 static void fill_entry(struct fuse_entry_out *arg,
351  const struct fuse_entry_param *e)
352 {
353  arg->nodeid = e->ino;
354  arg->generation = e->generation;
355  arg->entry_valid = calc_timeout_sec(e->entry_timeout);
356  arg->entry_valid_nsec = calc_timeout_nsec(e->entry_timeout);
357  arg->attr_valid = calc_timeout_sec(e->attr_timeout);
358  arg->attr_valid_nsec = calc_timeout_nsec(e->attr_timeout);
359  convert_stat(&e->attr, &arg->attr);
360 }
361 
362 /* `buf` is allowed to be empty so that the proper size may be
363  allocated by the caller */
364 size_t fuse_add_direntry_plus(fuse_req_t req, char *buf, size_t bufsize,
365  const char *name,
366  const struct fuse_entry_param *e, off_t off)
367 {
368  (void)req;
369  size_t namelen;
370  size_t entlen;
371  size_t entlen_padded;
372 
373  namelen = strlen(name);
374  entlen = FUSE_NAME_OFFSET_DIRENTPLUS + namelen;
375  entlen_padded = FUSE_DIRENT_ALIGN(entlen);
376  if ((buf == NULL) || (entlen_padded > bufsize))
377  return entlen_padded;
378 
379  struct fuse_direntplus *dp = (struct fuse_direntplus *) buf;
380  memset(&dp->entry_out, 0, sizeof(dp->entry_out));
381  fill_entry(&dp->entry_out, e);
382 
383  struct fuse_dirent *dirent = &dp->dirent;
384  dirent->ino = e->attr.st_ino;
385  dirent->off = off;
386  dirent->namelen = namelen;
387  dirent->type = (e->attr.st_mode & S_IFMT) >> 12;
388  memcpy(dirent->name, name, namelen);
389  memset(dirent->name + namelen, 0, entlen_padded - entlen);
390 
391  return entlen_padded;
392 }
393 
394 static void fill_open(struct fuse_open_out *arg,
395  const struct fuse_file_info *f)
396 {
397  arg->fh = f->fh;
398  if (f->direct_io)
399  arg->open_flags |= FOPEN_DIRECT_IO;
400  if (f->keep_cache)
401  arg->open_flags |= FOPEN_KEEP_CACHE;
402  if (f->cache_readdir)
403  arg->open_flags |= FOPEN_CACHE_DIR;
404  if (f->nonseekable)
405  arg->open_flags |= FOPEN_NONSEEKABLE;
406  if (f->noflush)
407  arg->open_flags |= FOPEN_NOFLUSH;
408 }
409 
411 {
412  struct fuse_entry_out arg;
413  size_t size = req->se->conn.proto_minor < 9 ?
414  FUSE_COMPAT_ENTRY_OUT_SIZE : sizeof(arg);
415 
416  /* before ABI 7.4 e->ino == 0 was invalid, only ENOENT meant
417  negative entry */
418  if (!e->ino && req->se->conn.proto_minor < 4)
419  return fuse_reply_err(req, ENOENT);
420 
421  memset(&arg, 0, sizeof(arg));
422  fill_entry(&arg, e);
423  return send_reply_ok(req, &arg, size);
424 }
425 
427  const struct fuse_file_info *f)
428 {
429  char buf[sizeof(struct fuse_entry_out) + sizeof(struct fuse_open_out)];
430  size_t entrysize = req->se->conn.proto_minor < 9 ?
431  FUSE_COMPAT_ENTRY_OUT_SIZE : sizeof(struct fuse_entry_out);
432  struct fuse_entry_out *earg = (struct fuse_entry_out *) buf;
433  struct fuse_open_out *oarg = (struct fuse_open_out *) (buf + entrysize);
434 
435  memset(buf, 0, sizeof(buf));
436  fill_entry(earg, e);
437  fill_open(oarg, f);
438  return send_reply_ok(req, buf,
439  entrysize + sizeof(struct fuse_open_out));
440 }
441 
442 int fuse_reply_attr(fuse_req_t req, const struct stat *attr,
443  double attr_timeout)
444 {
445  struct fuse_attr_out arg;
446  size_t size = req->se->conn.proto_minor < 9 ?
447  FUSE_COMPAT_ATTR_OUT_SIZE : sizeof(arg);
448 
449  memset(&arg, 0, sizeof(arg));
450  arg.attr_valid = calc_timeout_sec(attr_timeout);
451  arg.attr_valid_nsec = calc_timeout_nsec(attr_timeout);
452  convert_stat(attr, &arg.attr);
453 
454  return send_reply_ok(req, &arg, size);
455 }
456 
457 int fuse_reply_readlink(fuse_req_t req, const char *linkname)
458 {
459  return send_reply_ok(req, linkname, strlen(linkname));
460 }
461 
462 int fuse_reply_open(fuse_req_t req, const struct fuse_file_info *f)
463 {
464  struct fuse_open_out arg;
465 
466  memset(&arg, 0, sizeof(arg));
467  fill_open(&arg, f);
468  return send_reply_ok(req, &arg, sizeof(arg));
469 }
470 
471 int fuse_reply_write(fuse_req_t req, size_t count)
472 {
473  struct fuse_write_out arg;
474 
475  memset(&arg, 0, sizeof(arg));
476  arg.size = count;
477 
478  return send_reply_ok(req, &arg, sizeof(arg));
479 }
480 
481 int fuse_reply_buf(fuse_req_t req, const char *buf, size_t size)
482 {
483  return send_reply_ok(req, buf, size);
484 }
485 
486 static int fuse_send_data_iov_fallback(struct fuse_session *se,
487  struct fuse_chan *ch,
488  struct iovec *iov, int iov_count,
489  struct fuse_bufvec *buf,
490  size_t len)
491 {
492  struct fuse_bufvec mem_buf = FUSE_BUFVEC_INIT(len);
493  void *mbuf;
494  int res;
495 
496  /* Optimize common case */
497  if (buf->count == 1 && buf->idx == 0 && buf->off == 0 &&
498  !(buf->buf[0].flags & FUSE_BUF_IS_FD)) {
499  /* FIXME: also avoid memory copy if there are multiple buffers
500  but none of them contain an fd */
501 
502  iov[iov_count].iov_base = buf->buf[0].mem;
503  iov[iov_count].iov_len = len;
504  iov_count++;
505  return fuse_send_msg(se, ch, iov, iov_count);
506  }
507 
508  res = posix_memalign(&mbuf, pagesize, len);
509  if (res != 0)
510  return res;
511 
512  mem_buf.buf[0].mem = mbuf;
513  res = fuse_buf_copy(&mem_buf, buf, 0);
514  if (res < 0) {
515  free(mbuf);
516  return -res;
517  }
518  len = res;
519 
520  iov[iov_count].iov_base = mbuf;
521  iov[iov_count].iov_len = len;
522  iov_count++;
523  res = fuse_send_msg(se, ch, iov, iov_count);
524  free(mbuf);
525 
526  return res;
527 }
528 
529 struct fuse_ll_pipe {
530  size_t size;
531  int can_grow;
532  int pipe[2];
533 };
534 
535 static void fuse_ll_pipe_free(struct fuse_ll_pipe *llp)
536 {
537  close(llp->pipe[0]);
538  close(llp->pipe[1]);
539  free(llp);
540 }
541 
542 #ifdef HAVE_SPLICE
543 #if !defined(HAVE_PIPE2) || !defined(O_CLOEXEC)
544 static int fuse_pipe(int fds[2])
545 {
546  int rv = pipe(fds);
547 
548  if (rv == -1)
549  return rv;
550 
551  if (fcntl(fds[0], F_SETFL, O_NONBLOCK) == -1 ||
552  fcntl(fds[1], F_SETFL, O_NONBLOCK) == -1 ||
553  fcntl(fds[0], F_SETFD, FD_CLOEXEC) == -1 ||
554  fcntl(fds[1], F_SETFD, FD_CLOEXEC) == -1) {
555  close(fds[0]);
556  close(fds[1]);
557  rv = -1;
558  }
559  return rv;
560 }
561 #else
562 static int fuse_pipe(int fds[2])
563 {
564  return pipe2(fds, O_CLOEXEC | O_NONBLOCK);
565 }
566 #endif
567 
568 static struct fuse_ll_pipe *fuse_ll_get_pipe(struct fuse_session *se)
569 {
570  struct fuse_ll_pipe *llp = pthread_getspecific(se->pipe_key);
571  if (llp == NULL) {
572  int res;
573 
574  llp = malloc(sizeof(struct fuse_ll_pipe));
575  if (llp == NULL)
576  return NULL;
577 
578  res = fuse_pipe(llp->pipe);
579  if (res == -1) {
580  free(llp);
581  return NULL;
582  }
583 
584  /*
585  *the default size is 16 pages on linux
586  */
587  llp->size = pagesize * 16;
588  llp->can_grow = 1;
589 
590  pthread_setspecific(se->pipe_key, llp);
591  }
592 
593  return llp;
594 }
595 #endif
596 
597 static void fuse_ll_clear_pipe(struct fuse_session *se)
598 {
599  struct fuse_ll_pipe *llp = pthread_getspecific(se->pipe_key);
600  if (llp) {
601  pthread_setspecific(se->pipe_key, NULL);
602  fuse_ll_pipe_free(llp);
603  }
604 }
605 
606 #if defined(HAVE_SPLICE) && defined(HAVE_VMSPLICE)
607 static int read_back(int fd, char *buf, size_t len)
608 {
609  int res;
610 
611  res = read(fd, buf, len);
612  if (res == -1) {
613  fuse_log(FUSE_LOG_ERR, "fuse: internal error: failed to read back from pipe: %s\n", strerror(errno));
614  return -EIO;
615  }
616  if (res != len) {
617  fuse_log(FUSE_LOG_ERR, "fuse: internal error: short read back from pipe: %i from %zi\n", res, len);
618  return -EIO;
619  }
620  return 0;
621 }
622 
623 static int grow_pipe_to_max(int pipefd)
624 {
625  int max;
626  int res;
627  int maxfd;
628  char buf[32];
629 
630  maxfd = open("/proc/sys/fs/pipe-max-size", O_RDONLY);
631  if (maxfd < 0)
632  return -errno;
633 
634  res = read(maxfd, buf, sizeof(buf) - 1);
635  if (res < 0) {
636  int saved_errno;
637 
638  saved_errno = errno;
639  close(maxfd);
640  return -saved_errno;
641  }
642  close(maxfd);
643  buf[res] = '\0';
644 
645  max = atoi(buf);
646  res = fcntl(pipefd, F_SETPIPE_SZ, max);
647  if (res < 0)
648  return -errno;
649  return max;
650 }
651 
652 static int fuse_send_data_iov(struct fuse_session *se, struct fuse_chan *ch,
653  struct iovec *iov, int iov_count,
654  struct fuse_bufvec *buf, unsigned int flags)
655 {
656  int res;
657  size_t len = fuse_buf_size(buf);
658  struct fuse_out_header *out = iov[0].iov_base;
659  struct fuse_ll_pipe *llp;
660  int splice_flags;
661  size_t pipesize;
662  size_t total_buf_size;
663  size_t idx;
664  size_t headerlen;
665  struct fuse_bufvec pipe_buf = FUSE_BUFVEC_INIT(len);
666 
667  if (se->broken_splice_nonblock)
668  goto fallback;
669 
670  if (flags & FUSE_BUF_NO_SPLICE)
671  goto fallback;
672 
673  total_buf_size = 0;
674  for (idx = buf->idx; idx < buf->count; idx++) {
675  total_buf_size += buf->buf[idx].size;
676  if (idx == buf->idx)
677  total_buf_size -= buf->off;
678  }
679  if (total_buf_size < 2 * pagesize)
680  goto fallback;
681 
682  if (se->conn.proto_minor < 14 ||
683  !(se->conn.want & FUSE_CAP_SPLICE_WRITE))
684  goto fallback;
685 
686  llp = fuse_ll_get_pipe(se);
687  if (llp == NULL)
688  goto fallback;
689 
690 
691  headerlen = iov_length(iov, iov_count);
692 
693  out->len = headerlen + len;
694 
695  /*
696  * Heuristic for the required pipe size, does not work if the
697  * source contains less than page size fragments
698  */
699  pipesize = pagesize * (iov_count + buf->count + 1) + out->len;
700 
701  if (llp->size < pipesize) {
702  if (llp->can_grow) {
703  res = fcntl(llp->pipe[0], F_SETPIPE_SZ, pipesize);
704  if (res == -1) {
705  res = grow_pipe_to_max(llp->pipe[0]);
706  if (res > 0)
707  llp->size = res;
708  llp->can_grow = 0;
709  goto fallback;
710  }
711  llp->size = res;
712  }
713  if (llp->size < pipesize)
714  goto fallback;
715  }
716 
717 
718  res = vmsplice(llp->pipe[1], iov, iov_count, SPLICE_F_NONBLOCK);
719  if (res == -1)
720  goto fallback;
721 
722  if (res != headerlen) {
723  res = -EIO;
724  fuse_log(FUSE_LOG_ERR, "fuse: short vmsplice to pipe: %u/%zu\n", res,
725  headerlen);
726  goto clear_pipe;
727  }
728 
729  pipe_buf.buf[0].flags = FUSE_BUF_IS_FD;
730  pipe_buf.buf[0].fd = llp->pipe[1];
731 
732  res = fuse_buf_copy(&pipe_buf, buf,
734  if (res < 0) {
735  if (res == -EAGAIN || res == -EINVAL) {
736  /*
737  * Should only get EAGAIN on kernels with
738  * broken SPLICE_F_NONBLOCK support (<=
739  * 2.6.35) where this error or a short read is
740  * returned even if the pipe itself is not
741  * full
742  *
743  * EINVAL might mean that splice can't handle
744  * this combination of input and output.
745  */
746  if (res == -EAGAIN)
747  se->broken_splice_nonblock = 1;
748 
749  pthread_setspecific(se->pipe_key, NULL);
750  fuse_ll_pipe_free(llp);
751  goto fallback;
752  }
753  res = -res;
754  goto clear_pipe;
755  }
756 
757  if (res != 0 && res < len) {
758  struct fuse_bufvec mem_buf = FUSE_BUFVEC_INIT(len);
759  void *mbuf;
760  size_t now_len = res;
761  /*
762  * For regular files a short count is either
763  * 1) due to EOF, or
764  * 2) because of broken SPLICE_F_NONBLOCK (see above)
765  *
766  * For other inputs it's possible that we overflowed
767  * the pipe because of small buffer fragments.
768  */
769 
770  res = posix_memalign(&mbuf, pagesize, len);
771  if (res != 0)
772  goto clear_pipe;
773 
774  mem_buf.buf[0].mem = mbuf;
775  mem_buf.off = now_len;
776  res = fuse_buf_copy(&mem_buf, buf, 0);
777  if (res > 0) {
778  char *tmpbuf;
779  size_t extra_len = res;
780  /*
781  * Trickiest case: got more data. Need to get
782  * back the data from the pipe and then fall
783  * back to regular write.
784  */
785  tmpbuf = malloc(headerlen);
786  if (tmpbuf == NULL) {
787  free(mbuf);
788  res = ENOMEM;
789  goto clear_pipe;
790  }
791  res = read_back(llp->pipe[0], tmpbuf, headerlen);
792  free(tmpbuf);
793  if (res != 0) {
794  free(mbuf);
795  goto clear_pipe;
796  }
797  res = read_back(llp->pipe[0], mbuf, now_len);
798  if (res != 0) {
799  free(mbuf);
800  goto clear_pipe;
801  }
802  len = now_len + extra_len;
803  iov[iov_count].iov_base = mbuf;
804  iov[iov_count].iov_len = len;
805  iov_count++;
806  res = fuse_send_msg(se, ch, iov, iov_count);
807  free(mbuf);
808  return res;
809  }
810  free(mbuf);
811  res = now_len;
812  }
813  len = res;
814  out->len = headerlen + len;
815 
816  if (se->debug) {
817  fuse_log(FUSE_LOG_DEBUG,
818  " unique: %llu, success, outsize: %i (splice)\n",
819  (unsigned long long) out->unique, out->len);
820  }
821 
822  splice_flags = 0;
823  if ((flags & FUSE_BUF_SPLICE_MOVE) &&
824  (se->conn.want & FUSE_CAP_SPLICE_MOVE))
825  splice_flags |= SPLICE_F_MOVE;
826 
827  if (se->io != NULL && se->io->splice_send != NULL) {
828  res = se->io->splice_send(llp->pipe[0], NULL,
829  ch ? ch->fd : se->fd, NULL, out->len,
830  splice_flags, se->userdata);
831  } else {
832  res = splice(llp->pipe[0], NULL, ch ? ch->fd : se->fd, NULL,
833  out->len, splice_flags);
834  }
835  if (res == -1) {
836  res = -errno;
837  perror("fuse: splice from pipe");
838  goto clear_pipe;
839  }
840  if (res != out->len) {
841  res = -EIO;
842  fuse_log(FUSE_LOG_ERR, "fuse: short splice from pipe: %u/%u\n",
843  res, out->len);
844  goto clear_pipe;
845  }
846  return 0;
847 
848 clear_pipe:
849  fuse_ll_clear_pipe(se);
850  return res;
851 
852 fallback:
853  return fuse_send_data_iov_fallback(se, ch, iov, iov_count, buf, len);
854 }
855 #else
856 static int fuse_send_data_iov(struct fuse_session *se, struct fuse_chan *ch,
857  struct iovec *iov, int iov_count,
858  struct fuse_bufvec *buf, unsigned int flags)
859 {
860  size_t len = fuse_buf_size(buf);
861  (void) flags;
862 
863  return fuse_send_data_iov_fallback(se, ch, iov, iov_count, buf, len);
864 }
865 #endif
866 
867 int fuse_reply_data(fuse_req_t req, struct fuse_bufvec *bufv,
868  enum fuse_buf_copy_flags flags)
869 {
870  struct iovec iov[2];
871  struct fuse_out_header out;
872  int res;
873 
874  iov[0].iov_base = &out;
875  iov[0].iov_len = sizeof(struct fuse_out_header);
876 
877  out.unique = req->unique;
878  out.error = 0;
879 
880  res = fuse_send_data_iov(req->se, req->ch, iov, 1, bufv, flags);
881  if (res <= 0) {
882  fuse_free_req(req);
883  return res;
884  } else {
885  return fuse_reply_err(req, res);
886  }
887 }
888 
889 int fuse_reply_statfs(fuse_req_t req, const struct statvfs *stbuf)
890 {
891  struct fuse_statfs_out arg;
892  size_t size = req->se->conn.proto_minor < 4 ?
893  FUSE_COMPAT_STATFS_SIZE : sizeof(arg);
894 
895  memset(&arg, 0, sizeof(arg));
896  convert_statfs(stbuf, &arg.st);
897 
898  return send_reply_ok(req, &arg, size);
899 }
900 
901 int fuse_reply_xattr(fuse_req_t req, size_t count)
902 {
903  struct fuse_getxattr_out arg;
904 
905  memset(&arg, 0, sizeof(arg));
906  arg.size = count;
907 
908  return send_reply_ok(req, &arg, sizeof(arg));
909 }
910 
911 int fuse_reply_lock(fuse_req_t req, const struct flock *lock)
912 {
913  struct fuse_lk_out arg;
914 
915  memset(&arg, 0, sizeof(arg));
916  arg.lk.type = lock->l_type;
917  if (lock->l_type != F_UNLCK) {
918  arg.lk.start = lock->l_start;
919  if (lock->l_len == 0)
920  arg.lk.end = OFFSET_MAX;
921  else
922  arg.lk.end = lock->l_start + lock->l_len - 1;
923  }
924  arg.lk.pid = lock->l_pid;
925  return send_reply_ok(req, &arg, sizeof(arg));
926 }
927 
928 int fuse_reply_bmap(fuse_req_t req, uint64_t idx)
929 {
930  struct fuse_bmap_out arg;
931 
932  memset(&arg, 0, sizeof(arg));
933  arg.block = idx;
934 
935  return send_reply_ok(req, &arg, sizeof(arg));
936 }
937 
938 static struct fuse_ioctl_iovec *fuse_ioctl_iovec_copy(const struct iovec *iov,
939  size_t count)
940 {
941  struct fuse_ioctl_iovec *fiov;
942  size_t i;
943 
944  fiov = malloc(sizeof(fiov[0]) * count);
945  if (!fiov)
946  return NULL;
947 
948  for (i = 0; i < count; i++) {
949  fiov[i].base = (uintptr_t) iov[i].iov_base;
950  fiov[i].len = iov[i].iov_len;
951  }
952 
953  return fiov;
954 }
955 
957  const struct iovec *in_iov, size_t in_count,
958  const struct iovec *out_iov, size_t out_count)
959 {
960  struct fuse_ioctl_out arg;
961  struct fuse_ioctl_iovec *in_fiov = NULL;
962  struct fuse_ioctl_iovec *out_fiov = NULL;
963  struct iovec iov[4];
964  size_t count = 1;
965  int res;
966 
967  memset(&arg, 0, sizeof(arg));
968  arg.flags |= FUSE_IOCTL_RETRY;
969  arg.in_iovs = in_count;
970  arg.out_iovs = out_count;
971  iov[count].iov_base = &arg;
972  iov[count].iov_len = sizeof(arg);
973  count++;
974 
975  if (req->se->conn.proto_minor < 16) {
976  if (in_count) {
977  iov[count].iov_base = (void *)in_iov;
978  iov[count].iov_len = sizeof(in_iov[0]) * in_count;
979  count++;
980  }
981 
982  if (out_count) {
983  iov[count].iov_base = (void *)out_iov;
984  iov[count].iov_len = sizeof(out_iov[0]) * out_count;
985  count++;
986  }
987  } else {
988  /* Can't handle non-compat 64bit ioctls on 32bit */
989  if (sizeof(void *) == 4 && req->ioctl_64bit) {
990  res = fuse_reply_err(req, EINVAL);
991  goto out;
992  }
993 
994  if (in_count) {
995  in_fiov = fuse_ioctl_iovec_copy(in_iov, in_count);
996  if (!in_fiov)
997  goto enomem;
998 
999  iov[count].iov_base = (void *)in_fiov;
1000  iov[count].iov_len = sizeof(in_fiov[0]) * in_count;
1001  count++;
1002  }
1003  if (out_count) {
1004  out_fiov = fuse_ioctl_iovec_copy(out_iov, out_count);
1005  if (!out_fiov)
1006  goto enomem;
1007 
1008  iov[count].iov_base = (void *)out_fiov;
1009  iov[count].iov_len = sizeof(out_fiov[0]) * out_count;
1010  count++;
1011  }
1012  }
1013 
1014  res = send_reply_iov(req, 0, iov, count);
1015 out:
1016  free(in_fiov);
1017  free(out_fiov);
1018 
1019  return res;
1020 
1021 enomem:
1022  res = fuse_reply_err(req, ENOMEM);
1023  goto out;
1024 }
1025 
1026 int fuse_reply_ioctl(fuse_req_t req, int result, const void *buf, size_t size)
1027 {
1028  struct fuse_ioctl_out arg;
1029  struct iovec iov[3];
1030  size_t count = 1;
1031 
1032  memset(&arg, 0, sizeof(arg));
1033  arg.result = result;
1034  iov[count].iov_base = &arg;
1035  iov[count].iov_len = sizeof(arg);
1036  count++;
1037 
1038  if (size) {
1039  iov[count].iov_base = (char *) buf;
1040  iov[count].iov_len = size;
1041  count++;
1042  }
1043 
1044  return send_reply_iov(req, 0, iov, count);
1045 }
1046 
1047 int fuse_reply_ioctl_iov(fuse_req_t req, int result, const struct iovec *iov,
1048  int count)
1049 {
1050  struct iovec *padded_iov;
1051  struct fuse_ioctl_out arg;
1052  int res;
1053 
1054  padded_iov = malloc((count + 2) * sizeof(struct iovec));
1055  if (padded_iov == NULL)
1056  return fuse_reply_err(req, ENOMEM);
1057 
1058  memset(&arg, 0, sizeof(arg));
1059  arg.result = result;
1060  padded_iov[1].iov_base = &arg;
1061  padded_iov[1].iov_len = sizeof(arg);
1062 
1063  memcpy(&padded_iov[2], iov, count * sizeof(struct iovec));
1064 
1065  res = send_reply_iov(req, 0, padded_iov, count + 2);
1066  free(padded_iov);
1067 
1068  return res;
1069 }
1070 
1071 int fuse_reply_poll(fuse_req_t req, unsigned revents)
1072 {
1073  struct fuse_poll_out arg;
1074 
1075  memset(&arg, 0, sizeof(arg));
1076  arg.revents = revents;
1077 
1078  return send_reply_ok(req, &arg, sizeof(arg));
1079 }
1080 
1081 int fuse_reply_lseek(fuse_req_t req, off_t off)
1082 {
1083  struct fuse_lseek_out arg;
1084 
1085  memset(&arg, 0, sizeof(arg));
1086  arg.offset = off;
1087 
1088  return send_reply_ok(req, &arg, sizeof(arg));
1089 }
1090 
1091 static void do_lookup(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1092 {
1093  char *name = (char *) inarg;
1094 
1095  if (req->se->op.lookup)
1096  req->se->op.lookup(req, nodeid, name);
1097  else
1098  fuse_reply_err(req, ENOSYS);
1099 }
1100 
1101 static void do_forget(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1102 {
1103  struct fuse_forget_in *arg = (struct fuse_forget_in *) inarg;
1104 
1105  if (req->se->op.forget)
1106  req->se->op.forget(req, nodeid, arg->nlookup);
1107  else
1108  fuse_reply_none(req);
1109 }
1110 
1111 static void do_batch_forget(fuse_req_t req, fuse_ino_t nodeid,
1112  const void *inarg)
1113 {
1114  struct fuse_batch_forget_in *arg = (void *) inarg;
1115  struct fuse_forget_one *param = (void *) PARAM(arg);
1116  unsigned int i;
1117 
1118  (void) nodeid;
1119 
1120  if (req->se->op.forget_multi) {
1121  req->se->op.forget_multi(req, arg->count,
1122  (struct fuse_forget_data *) param);
1123  } else if (req->se->op.forget) {
1124  for (i = 0; i < arg->count; i++) {
1125  struct fuse_forget_one *forget = &param[i];
1126  struct fuse_req *dummy_req;
1127 
1128  dummy_req = fuse_ll_alloc_req(req->se);
1129  if (dummy_req == NULL)
1130  break;
1131 
1132  dummy_req->unique = req->unique;
1133  dummy_req->ctx = req->ctx;
1134  dummy_req->ch = NULL;
1135 
1136  req->se->op.forget(dummy_req, forget->nodeid,
1137  forget->nlookup);
1138  }
1139  fuse_reply_none(req);
1140  } else {
1141  fuse_reply_none(req);
1142  }
1143 }
1144 
1145 static void do_getattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1146 {
1147  struct fuse_file_info *fip = NULL;
1148  struct fuse_file_info fi;
1149 
1150  if (req->se->conn.proto_minor >= 9) {
1151  struct fuse_getattr_in *arg = (struct fuse_getattr_in *) inarg;
1152 
1153  if (arg->getattr_flags & FUSE_GETATTR_FH) {
1154  memset(&fi, 0, sizeof(fi));
1155  fi.fh = arg->fh;
1156  fip = &fi;
1157  }
1158  }
1159 
1160  if (req->se->op.getattr)
1161  req->se->op.getattr(req, nodeid, fip);
1162  else
1163  fuse_reply_err(req, ENOSYS);
1164 }
1165 
1166 static void do_setattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1167 {
1168  struct fuse_setattr_in *arg = (struct fuse_setattr_in *) inarg;
1169 
1170  if (req->se->op.setattr) {
1171  struct fuse_file_info *fi = NULL;
1172  struct fuse_file_info fi_store;
1173  struct stat stbuf;
1174  memset(&stbuf, 0, sizeof(stbuf));
1175  convert_attr(arg, &stbuf);
1176  if (arg->valid & FATTR_FH) {
1177  arg->valid &= ~FATTR_FH;
1178  memset(&fi_store, 0, sizeof(fi_store));
1179  fi = &fi_store;
1180  fi->fh = arg->fh;
1181  }
1182  arg->valid &=
1183  FUSE_SET_ATTR_MODE |
1184  FUSE_SET_ATTR_UID |
1185  FUSE_SET_ATTR_GID |
1186  FUSE_SET_ATTR_SIZE |
1187  FUSE_SET_ATTR_ATIME |
1188  FUSE_SET_ATTR_MTIME |
1189  FUSE_SET_ATTR_ATIME_NOW |
1190  FUSE_SET_ATTR_MTIME_NOW |
1191  FUSE_SET_ATTR_CTIME;
1192 
1193  req->se->op.setattr(req, nodeid, &stbuf, arg->valid, fi);
1194  } else
1195  fuse_reply_err(req, ENOSYS);
1196 }
1197 
1198 static void do_access(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1199 {
1200  struct fuse_access_in *arg = (struct fuse_access_in *) inarg;
1201 
1202  if (req->se->op.access)
1203  req->se->op.access(req, nodeid, arg->mask);
1204  else
1205  fuse_reply_err(req, ENOSYS);
1206 }
1207 
1208 static void do_readlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1209 {
1210  (void) inarg;
1211 
1212  if (req->se->op.readlink)
1213  req->se->op.readlink(req, nodeid);
1214  else
1215  fuse_reply_err(req, ENOSYS);
1216 }
1217 
1218 static void do_mknod(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1219 {
1220  struct fuse_mknod_in *arg = (struct fuse_mknod_in *) inarg;
1221  char *name = PARAM(arg);
1222 
1223  if (req->se->conn.proto_minor >= 12)
1224  req->ctx.umask = arg->umask;
1225  else
1226  name = (char *) inarg + FUSE_COMPAT_MKNOD_IN_SIZE;
1227 
1228  if (req->se->op.mknod)
1229  req->se->op.mknod(req, nodeid, name, arg->mode, arg->rdev);
1230  else
1231  fuse_reply_err(req, ENOSYS);
1232 }
1233 
1234 static void do_mkdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1235 {
1236  struct fuse_mkdir_in *arg = (struct fuse_mkdir_in *) inarg;
1237 
1238  if (req->se->conn.proto_minor >= 12)
1239  req->ctx.umask = arg->umask;
1240 
1241  if (req->se->op.mkdir)
1242  req->se->op.mkdir(req, nodeid, PARAM(arg), arg->mode);
1243  else
1244  fuse_reply_err(req, ENOSYS);
1245 }
1246 
1247 static void do_unlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1248 {
1249  char *name = (char *) inarg;
1250 
1251  if (req->se->op.unlink)
1252  req->se->op.unlink(req, nodeid, name);
1253  else
1254  fuse_reply_err(req, ENOSYS);
1255 }
1256 
1257 static void do_rmdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1258 {
1259  char *name = (char *) inarg;
1260 
1261  if (req->se->op.rmdir)
1262  req->se->op.rmdir(req, nodeid, name);
1263  else
1264  fuse_reply_err(req, ENOSYS);
1265 }
1266 
1267 static void do_symlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1268 {
1269  char *name = (char *) inarg;
1270  char *linkname = ((char *) inarg) + strlen((char *) inarg) + 1;
1271 
1272  if (req->se->op.symlink)
1273  req->se->op.symlink(req, linkname, nodeid, name);
1274  else
1275  fuse_reply_err(req, ENOSYS);
1276 }
1277 
1278 static void do_rename(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1279 {
1280  struct fuse_rename_in *arg = (struct fuse_rename_in *) inarg;
1281  char *oldname = PARAM(arg);
1282  char *newname = oldname + strlen(oldname) + 1;
1283 
1284  if (req->se->op.rename)
1285  req->se->op.rename(req, nodeid, oldname, arg->newdir, newname,
1286  0);
1287  else
1288  fuse_reply_err(req, ENOSYS);
1289 }
1290 
1291 static void do_rename2(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1292 {
1293  struct fuse_rename2_in *arg = (struct fuse_rename2_in *) inarg;
1294  char *oldname = PARAM(arg);
1295  char *newname = oldname + strlen(oldname) + 1;
1296 
1297  if (req->se->op.rename)
1298  req->se->op.rename(req, nodeid, oldname, arg->newdir, newname,
1299  arg->flags);
1300  else
1301  fuse_reply_err(req, ENOSYS);
1302 }
1303 
1304 static void do_link(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1305 {
1306  struct fuse_link_in *arg = (struct fuse_link_in *) inarg;
1307 
1308  if (req->se->op.link)
1309  req->se->op.link(req, arg->oldnodeid, nodeid, PARAM(arg));
1310  else
1311  fuse_reply_err(req, ENOSYS);
1312 }
1313 
1314 static void do_create(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1315 {
1316  struct fuse_create_in *arg = (struct fuse_create_in *) inarg;
1317 
1318  if (req->se->op.create) {
1319  struct fuse_file_info fi;
1320  char *name = PARAM(arg);
1321 
1322  memset(&fi, 0, sizeof(fi));
1323  fi.flags = arg->flags;
1324 
1325  if (req->se->conn.proto_minor >= 12)
1326  req->ctx.umask = arg->umask;
1327  else
1328  name = (char *) inarg + sizeof(struct fuse_open_in);
1329 
1330  req->se->op.create(req, nodeid, name, arg->mode, &fi);
1331  } else
1332  fuse_reply_err(req, ENOSYS);
1333 }
1334 
1335 static void do_open(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1336 {
1337  struct fuse_open_in *arg = (struct fuse_open_in *) inarg;
1338  struct fuse_file_info fi;
1339 
1340  memset(&fi, 0, sizeof(fi));
1341  fi.flags = arg->flags;
1342 
1343  if (req->se->op.open)
1344  req->se->op.open(req, nodeid, &fi);
1345  else
1346  fuse_reply_open(req, &fi);
1347 }
1348 
1349 static void do_read(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1350 {
1351  struct fuse_read_in *arg = (struct fuse_read_in *) inarg;
1352 
1353  if (req->se->op.read) {
1354  struct fuse_file_info fi;
1355 
1356  memset(&fi, 0, sizeof(fi));
1357  fi.fh = arg->fh;
1358  if (req->se->conn.proto_minor >= 9) {
1359  fi.lock_owner = arg->lock_owner;
1360  fi.flags = arg->flags;
1361  }
1362  req->se->op.read(req, nodeid, arg->size, arg->offset, &fi);
1363  } else
1364  fuse_reply_err(req, ENOSYS);
1365 }
1366 
1367 static void do_write(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1368 {
1369  struct fuse_write_in *arg = (struct fuse_write_in *) inarg;
1370  struct fuse_file_info fi;
1371  char *param;
1372 
1373  memset(&fi, 0, sizeof(fi));
1374  fi.fh = arg->fh;
1375  fi.writepage = (arg->write_flags & FUSE_WRITE_CACHE) != 0;
1376 
1377  if (req->se->conn.proto_minor < 9) {
1378  param = ((char *) arg) + FUSE_COMPAT_WRITE_IN_SIZE;
1379  } else {
1380  fi.lock_owner = arg->lock_owner;
1381  fi.flags = arg->flags;
1382  param = PARAM(arg);
1383  }
1384 
1385  if (req->se->op.write)
1386  req->se->op.write(req, nodeid, param, arg->size,
1387  arg->offset, &fi);
1388  else
1389  fuse_reply_err(req, ENOSYS);
1390 }
1391 
1392 static void do_write_buf(fuse_req_t req, fuse_ino_t nodeid, const void *inarg,
1393  const struct fuse_buf *ibuf)
1394 {
1395  struct fuse_session *se = req->se;
1396  struct fuse_bufvec bufv = {
1397  .buf[0] = *ibuf,
1398  .count = 1,
1399  };
1400  struct fuse_write_in *arg = (struct fuse_write_in *) inarg;
1401  struct fuse_file_info fi;
1402 
1403  memset(&fi, 0, sizeof(fi));
1404  fi.fh = arg->fh;
1405  fi.writepage = arg->write_flags & FUSE_WRITE_CACHE;
1406 
1407  if (se->conn.proto_minor < 9) {
1408  bufv.buf[0].mem = ((char *) arg) + FUSE_COMPAT_WRITE_IN_SIZE;
1409  bufv.buf[0].size -= sizeof(struct fuse_in_header) +
1410  FUSE_COMPAT_WRITE_IN_SIZE;
1411  assert(!(bufv.buf[0].flags & FUSE_BUF_IS_FD));
1412  } else {
1413  fi.lock_owner = arg->lock_owner;
1414  fi.flags = arg->flags;
1415  if (!(bufv.buf[0].flags & FUSE_BUF_IS_FD))
1416  bufv.buf[0].mem = PARAM(arg);
1417 
1418  bufv.buf[0].size -= sizeof(struct fuse_in_header) +
1419  sizeof(struct fuse_write_in);
1420  }
1421  if (bufv.buf[0].size < arg->size) {
1422  fuse_log(FUSE_LOG_ERR, "fuse: do_write_buf: buffer size too small\n");
1423  fuse_reply_err(req, EIO);
1424  goto out;
1425  }
1426  bufv.buf[0].size = arg->size;
1427 
1428  se->op.write_buf(req, nodeid, &bufv, arg->offset, &fi);
1429 
1430 out:
1431  /* Need to reset the pipe if ->write_buf() didn't consume all data */
1432  if ((ibuf->flags & FUSE_BUF_IS_FD) && bufv.idx < bufv.count)
1433  fuse_ll_clear_pipe(se);
1434 }
1435 
1436 static void do_flush(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1437 {
1438  struct fuse_flush_in *arg = (struct fuse_flush_in *) inarg;
1439  struct fuse_file_info fi;
1440 
1441  memset(&fi, 0, sizeof(fi));
1442  fi.fh = arg->fh;
1443  fi.flush = 1;
1444  if (req->se->conn.proto_minor >= 7)
1445  fi.lock_owner = arg->lock_owner;
1446 
1447  if (req->se->op.flush)
1448  req->se->op.flush(req, nodeid, &fi);
1449  else
1450  fuse_reply_err(req, ENOSYS);
1451 }
1452 
1453 static void do_release(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1454 {
1455  struct fuse_release_in *arg = (struct fuse_release_in *) inarg;
1456  struct fuse_file_info fi;
1457 
1458  memset(&fi, 0, sizeof(fi));
1459  fi.flags = arg->flags;
1460  fi.fh = arg->fh;
1461  if (req->se->conn.proto_minor >= 8) {
1462  fi.flush = (arg->release_flags & FUSE_RELEASE_FLUSH) ? 1 : 0;
1463  fi.lock_owner = arg->lock_owner;
1464  }
1465  if (arg->release_flags & FUSE_RELEASE_FLOCK_UNLOCK) {
1466  fi.flock_release = 1;
1467  fi.lock_owner = arg->lock_owner;
1468  }
1469 
1470  if (req->se->op.release)
1471  req->se->op.release(req, nodeid, &fi);
1472  else
1473  fuse_reply_err(req, 0);
1474 }
1475 
1476 static void do_fsync(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1477 {
1478  struct fuse_fsync_in *arg = (struct fuse_fsync_in *) inarg;
1479  struct fuse_file_info fi;
1480  int datasync = arg->fsync_flags & 1;
1481 
1482  memset(&fi, 0, sizeof(fi));
1483  fi.fh = arg->fh;
1484 
1485  if (req->se->op.fsync)
1486  req->se->op.fsync(req, nodeid, datasync, &fi);
1487  else
1488  fuse_reply_err(req, ENOSYS);
1489 }
1490 
1491 static void do_opendir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1492 {
1493  struct fuse_open_in *arg = (struct fuse_open_in *) inarg;
1494  struct fuse_file_info fi;
1495 
1496  memset(&fi, 0, sizeof(fi));
1497  fi.flags = arg->flags;
1498 
1499  if (req->se->op.opendir)
1500  req->se->op.opendir(req, nodeid, &fi);
1501  else
1502  fuse_reply_open(req, &fi);
1503 }
1504 
1505 static void do_readdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1506 {
1507  struct fuse_read_in *arg = (struct fuse_read_in *) inarg;
1508  struct fuse_file_info fi;
1509 
1510  memset(&fi, 0, sizeof(fi));
1511  fi.fh = arg->fh;
1512 
1513  if (req->se->op.readdir)
1514  req->se->op.readdir(req, nodeid, arg->size, arg->offset, &fi);
1515  else
1516  fuse_reply_err(req, ENOSYS);
1517 }
1518 
1519 static void do_readdirplus(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1520 {
1521  struct fuse_read_in *arg = (struct fuse_read_in *) inarg;
1522  struct fuse_file_info fi;
1523 
1524  memset(&fi, 0, sizeof(fi));
1525  fi.fh = arg->fh;
1526 
1527  if (req->se->op.readdirplus)
1528  req->se->op.readdirplus(req, nodeid, arg->size, arg->offset, &fi);
1529  else
1530  fuse_reply_err(req, ENOSYS);
1531 }
1532 
1533 static void do_releasedir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1534 {
1535  struct fuse_release_in *arg = (struct fuse_release_in *) inarg;
1536  struct fuse_file_info fi;
1537 
1538  memset(&fi, 0, sizeof(fi));
1539  fi.flags = arg->flags;
1540  fi.fh = arg->fh;
1541 
1542  if (req->se->op.releasedir)
1543  req->se->op.releasedir(req, nodeid, &fi);
1544  else
1545  fuse_reply_err(req, 0);
1546 }
1547 
1548 static void do_fsyncdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1549 {
1550  struct fuse_fsync_in *arg = (struct fuse_fsync_in *) inarg;
1551  struct fuse_file_info fi;
1552  int datasync = arg->fsync_flags & 1;
1553 
1554  memset(&fi, 0, sizeof(fi));
1555  fi.fh = arg->fh;
1556 
1557  if (req->se->op.fsyncdir)
1558  req->se->op.fsyncdir(req, nodeid, datasync, &fi);
1559  else
1560  fuse_reply_err(req, ENOSYS);
1561 }
1562 
1563 static void do_statfs(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1564 {
1565  (void) nodeid;
1566  (void) inarg;
1567 
1568  if (req->se->op.statfs)
1569  req->se->op.statfs(req, nodeid);
1570  else {
1571  struct statvfs buf = {
1572  .f_namemax = 255,
1573  .f_bsize = 512,
1574  };
1575  fuse_reply_statfs(req, &buf);
1576  }
1577 }
1578 
1579 static void do_setxattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1580 {
1581  struct fuse_setxattr_in *arg = (struct fuse_setxattr_in *) inarg;
1582  char *name = PARAM(arg);
1583  char *value = name + strlen(name) + 1;
1584 
1585  if (req->se->op.setxattr)
1586  req->se->op.setxattr(req, nodeid, name, value, arg->size,
1587  arg->flags);
1588  else
1589  fuse_reply_err(req, ENOSYS);
1590 }
1591 
1592 static void do_getxattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1593 {
1594  struct fuse_getxattr_in *arg = (struct fuse_getxattr_in *) inarg;
1595 
1596  if (req->se->op.getxattr)
1597  req->se->op.getxattr(req, nodeid, PARAM(arg), arg->size);
1598  else
1599  fuse_reply_err(req, ENOSYS);
1600 }
1601 
1602 static void do_listxattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1603 {
1604  struct fuse_getxattr_in *arg = (struct fuse_getxattr_in *) inarg;
1605 
1606  if (req->se->op.listxattr)
1607  req->se->op.listxattr(req, nodeid, arg->size);
1608  else
1609  fuse_reply_err(req, ENOSYS);
1610 }
1611 
1612 static void do_removexattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1613 {
1614  char *name = (char *) inarg;
1615 
1616  if (req->se->op.removexattr)
1617  req->se->op.removexattr(req, nodeid, name);
1618  else
1619  fuse_reply_err(req, ENOSYS);
1620 }
1621 
1622 static void convert_fuse_file_lock(struct fuse_file_lock *fl,
1623  struct flock *flock)
1624 {
1625  memset(flock, 0, sizeof(struct flock));
1626  flock->l_type = fl->type;
1627  flock->l_whence = SEEK_SET;
1628  flock->l_start = fl->start;
1629  if (fl->end == OFFSET_MAX)
1630  flock->l_len = 0;
1631  else
1632  flock->l_len = fl->end - fl->start + 1;
1633  flock->l_pid = fl->pid;
1634 }
1635 
1636 static void do_getlk(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1637 {
1638  struct fuse_lk_in *arg = (struct fuse_lk_in *) inarg;
1639  struct fuse_file_info fi;
1640  struct flock flock;
1641 
1642  memset(&fi, 0, sizeof(fi));
1643  fi.fh = arg->fh;
1644  fi.lock_owner = arg->owner;
1645 
1646  convert_fuse_file_lock(&arg->lk, &flock);
1647  if (req->se->op.getlk)
1648  req->se->op.getlk(req, nodeid, &fi, &flock);
1649  else
1650  fuse_reply_err(req, ENOSYS);
1651 }
1652 
1653 static void do_setlk_common(fuse_req_t req, fuse_ino_t nodeid,
1654  const void *inarg, int sleep)
1655 {
1656  struct fuse_lk_in *arg = (struct fuse_lk_in *) inarg;
1657  struct fuse_file_info fi;
1658  struct flock flock;
1659 
1660  memset(&fi, 0, sizeof(fi));
1661  fi.fh = arg->fh;
1662  fi.lock_owner = arg->owner;
1663 
1664  if (arg->lk_flags & FUSE_LK_FLOCK) {
1665  int op = 0;
1666 
1667  switch (arg->lk.type) {
1668  case F_RDLCK:
1669  op = LOCK_SH;
1670  break;
1671  case F_WRLCK:
1672  op = LOCK_EX;
1673  break;
1674  case F_UNLCK:
1675  op = LOCK_UN;
1676  break;
1677  }
1678  if (!sleep)
1679  op |= LOCK_NB;
1680 
1681  if (req->se->op.flock)
1682  req->se->op.flock(req, nodeid, &fi, op);
1683  else
1684  fuse_reply_err(req, ENOSYS);
1685  } else {
1686  convert_fuse_file_lock(&arg->lk, &flock);
1687  if (req->se->op.setlk)
1688  req->se->op.setlk(req, nodeid, &fi, &flock, sleep);
1689  else
1690  fuse_reply_err(req, ENOSYS);
1691  }
1692 }
1693 
1694 static void do_setlk(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1695 {
1696  do_setlk_common(req, nodeid, inarg, 0);
1697 }
1698 
1699 static void do_setlkw(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1700 {
1701  do_setlk_common(req, nodeid, inarg, 1);
1702 }
1703 
1704 static int find_interrupted(struct fuse_session *se, struct fuse_req *req)
1705 {
1706  struct fuse_req *curr;
1707 
1708  for (curr = se->list.next; curr != &se->list; curr = curr->next) {
1709  if (curr->unique == req->u.i.unique) {
1710  fuse_interrupt_func_t func;
1711  void *data;
1712 
1713  curr->ctr++;
1714  pthread_mutex_unlock(&se->lock);
1715 
1716  /* Ugh, ugly locking */
1717  pthread_mutex_lock(&curr->lock);
1718  pthread_mutex_lock(&se->lock);
1719  curr->interrupted = 1;
1720  func = curr->u.ni.func;
1721  data = curr->u.ni.data;
1722  pthread_mutex_unlock(&se->lock);
1723  if (func)
1724  func(curr, data);
1725  pthread_mutex_unlock(&curr->lock);
1726 
1727  pthread_mutex_lock(&se->lock);
1728  curr->ctr--;
1729  if (!curr->ctr) {
1730  fuse_chan_put(req->ch);
1731  req->ch = NULL;
1732  destroy_req(curr);
1733  }
1734 
1735  return 1;
1736  }
1737  }
1738  for (curr = se->interrupts.next; curr != &se->interrupts;
1739  curr = curr->next) {
1740  if (curr->u.i.unique == req->u.i.unique)
1741  return 1;
1742  }
1743  return 0;
1744 }
1745 
1746 static void do_interrupt(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1747 {
1748  struct fuse_interrupt_in *arg = (struct fuse_interrupt_in *) inarg;
1749  struct fuse_session *se = req->se;
1750 
1751  (void) nodeid;
1752  if (se->debug)
1753  fuse_log(FUSE_LOG_DEBUG, "INTERRUPT: %llu\n",
1754  (unsigned long long) arg->unique);
1755 
1756  req->u.i.unique = arg->unique;
1757 
1758  pthread_mutex_lock(&se->lock);
1759  if (find_interrupted(se, req)) {
1760  fuse_chan_put(req->ch);
1761  req->ch = NULL;
1762  destroy_req(req);
1763  } else
1764  list_add_req(req, &se->interrupts);
1765  pthread_mutex_unlock(&se->lock);
1766 }
1767 
1768 static struct fuse_req *check_interrupt(struct fuse_session *se,
1769  struct fuse_req *req)
1770 {
1771  struct fuse_req *curr;
1772 
1773  for (curr = se->interrupts.next; curr != &se->interrupts;
1774  curr = curr->next) {
1775  if (curr->u.i.unique == req->unique) {
1776  req->interrupted = 1;
1777  list_del_req(curr);
1778  fuse_chan_put(curr->ch);
1779  curr->ch = NULL;
1780  destroy_req(curr);
1781  return NULL;
1782  }
1783  }
1784  curr = se->interrupts.next;
1785  if (curr != &se->interrupts) {
1786  list_del_req(curr);
1787  list_init_req(curr);
1788  return curr;
1789  } else
1790  return NULL;
1791 }
1792 
1793 static void do_bmap(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1794 {
1795  struct fuse_bmap_in *arg = (struct fuse_bmap_in *) inarg;
1796 
1797  if (req->se->op.bmap)
1798  req->se->op.bmap(req, nodeid, arg->blocksize, arg->block);
1799  else
1800  fuse_reply_err(req, ENOSYS);
1801 }
1802 
1803 static void do_ioctl(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1804 {
1805  struct fuse_ioctl_in *arg = (struct fuse_ioctl_in *) inarg;
1806  unsigned int flags = arg->flags;
1807  void *in_buf = arg->in_size ? PARAM(arg) : NULL;
1808  struct fuse_file_info fi;
1809 
1810  if (flags & FUSE_IOCTL_DIR &&
1811  !(req->se->conn.want & FUSE_CAP_IOCTL_DIR)) {
1812  fuse_reply_err(req, ENOTTY);
1813  return;
1814  }
1815 
1816  memset(&fi, 0, sizeof(fi));
1817  fi.fh = arg->fh;
1818 
1819  if (sizeof(void *) == 4 && req->se->conn.proto_minor >= 16 &&
1820  !(flags & FUSE_IOCTL_32BIT)) {
1821  req->ioctl_64bit = 1;
1822  }
1823 
1824  if (req->se->op.ioctl)
1825  req->se->op.ioctl(req, nodeid, arg->cmd,
1826  (void *)(uintptr_t)arg->arg, &fi, flags,
1827  in_buf, arg->in_size, arg->out_size);
1828  else
1829  fuse_reply_err(req, ENOSYS);
1830 }
1831 
1832 void fuse_pollhandle_destroy(struct fuse_pollhandle *ph)
1833 {
1834  free(ph);
1835 }
1836 
1837 static void do_poll(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1838 {
1839  struct fuse_poll_in *arg = (struct fuse_poll_in *) inarg;
1840  struct fuse_file_info fi;
1841 
1842  memset(&fi, 0, sizeof(fi));
1843  fi.fh = arg->fh;
1844  fi.poll_events = arg->events;
1845 
1846  if (req->se->op.poll) {
1847  struct fuse_pollhandle *ph = NULL;
1848 
1849  if (arg->flags & FUSE_POLL_SCHEDULE_NOTIFY) {
1850  ph = malloc(sizeof(struct fuse_pollhandle));
1851  if (ph == NULL) {
1852  fuse_reply_err(req, ENOMEM);
1853  return;
1854  }
1855  ph->kh = arg->kh;
1856  ph->se = req->se;
1857  }
1858 
1859  req->se->op.poll(req, nodeid, &fi, ph);
1860  } else {
1861  fuse_reply_err(req, ENOSYS);
1862  }
1863 }
1864 
1865 static void do_fallocate(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1866 {
1867  struct fuse_fallocate_in *arg = (struct fuse_fallocate_in *) inarg;
1868  struct fuse_file_info fi;
1869 
1870  memset(&fi, 0, sizeof(fi));
1871  fi.fh = arg->fh;
1872 
1873  if (req->se->op.fallocate)
1874  req->se->op.fallocate(req, nodeid, arg->mode, arg->offset, arg->length, &fi);
1875  else
1876  fuse_reply_err(req, ENOSYS);
1877 }
1878 
1879 static void do_copy_file_range(fuse_req_t req, fuse_ino_t nodeid_in, const void *inarg)
1880 {
1881  struct fuse_copy_file_range_in *arg = (struct fuse_copy_file_range_in *) inarg;
1882  struct fuse_file_info fi_in, fi_out;
1883 
1884  memset(&fi_in, 0, sizeof(fi_in));
1885  fi_in.fh = arg->fh_in;
1886 
1887  memset(&fi_out, 0, sizeof(fi_out));
1888  fi_out.fh = arg->fh_out;
1889 
1890 
1891  if (req->se->op.copy_file_range)
1892  req->se->op.copy_file_range(req, nodeid_in, arg->off_in,
1893  &fi_in, arg->nodeid_out,
1894  arg->off_out, &fi_out, arg->len,
1895  arg->flags);
1896  else
1897  fuse_reply_err(req, ENOSYS);
1898 }
1899 
1900 static void do_lseek(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1901 {
1902  struct fuse_lseek_in *arg = (struct fuse_lseek_in *) inarg;
1903  struct fuse_file_info fi;
1904 
1905  memset(&fi, 0, sizeof(fi));
1906  fi.fh = arg->fh;
1907 
1908  if (req->se->op.lseek)
1909  req->se->op.lseek(req, nodeid, arg->offset, arg->whence, &fi);
1910  else
1911  fuse_reply_err(req, ENOSYS);
1912 }
1913 
1914 /* Prevent bogus data races (bogus since "init" is called before
1915  * multi-threading becomes relevant */
1916 static __attribute__((no_sanitize("thread")))
1917 void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1918 {
1919  struct fuse_init_in *arg = (struct fuse_init_in *) inarg;
1920  struct fuse_init_out outarg;
1921  struct fuse_session *se = req->se;
1922  size_t bufsize = se->bufsize;
1923  size_t outargsize = sizeof(outarg);
1924  uint64_t inargflags = 0;
1925  uint64_t outargflags = 0;
1926  (void) nodeid;
1927  if (se->debug) {
1928  fuse_log(FUSE_LOG_DEBUG, "INIT: %u.%u\n", arg->major, arg->minor);
1929  if (arg->major == 7 && arg->minor >= 6) {
1930  fuse_log(FUSE_LOG_DEBUG, "flags=0x%08x\n", arg->flags);
1931  fuse_log(FUSE_LOG_DEBUG, "max_readahead=0x%08x\n",
1932  arg->max_readahead);
1933  }
1934  }
1935  se->conn.proto_major = arg->major;
1936  se->conn.proto_minor = arg->minor;
1937  se->conn.capable = 0;
1938  se->conn.want = 0;
1939 
1940  memset(&outarg, 0, sizeof(outarg));
1941  outarg.major = FUSE_KERNEL_VERSION;
1942  outarg.minor = FUSE_KERNEL_MINOR_VERSION;
1943 
1944  if (arg->major < 7) {
1945  fuse_log(FUSE_LOG_ERR, "fuse: unsupported protocol version: %u.%u\n",
1946  arg->major, arg->minor);
1947  fuse_reply_err(req, EPROTO);
1948  return;
1949  }
1950 
1951  if (arg->major > 7) {
1952  /* Wait for a second INIT request with a 7.X version */
1953  send_reply_ok(req, &outarg, sizeof(outarg));
1954  return;
1955  }
1956 
1957  if (arg->minor >= 6) {
1958  if (arg->max_readahead < se->conn.max_readahead)
1959  se->conn.max_readahead = arg->max_readahead;
1960  inargflags = arg->flags;
1961  if (inargflags & FUSE_INIT_EXT)
1962  inargflags = inargflags | (uint64_t) arg->flags2 << 32;
1963  if (inargflags & FUSE_ASYNC_READ)
1964  se->conn.capable |= FUSE_CAP_ASYNC_READ;
1965  if (inargflags & FUSE_POSIX_LOCKS)
1966  se->conn.capable |= FUSE_CAP_POSIX_LOCKS;
1967  if (inargflags & FUSE_ATOMIC_O_TRUNC)
1968  se->conn.capable |= FUSE_CAP_ATOMIC_O_TRUNC;
1969  if (inargflags & FUSE_EXPORT_SUPPORT)
1970  se->conn.capable |= FUSE_CAP_EXPORT_SUPPORT;
1971  if (inargflags & FUSE_DONT_MASK)
1972  se->conn.capable |= FUSE_CAP_DONT_MASK;
1973  if (inargflags & FUSE_FLOCK_LOCKS)
1974  se->conn.capable |= FUSE_CAP_FLOCK_LOCKS;
1975  if (inargflags & FUSE_AUTO_INVAL_DATA)
1976  se->conn.capable |= FUSE_CAP_AUTO_INVAL_DATA;
1977  if (inargflags & FUSE_DO_READDIRPLUS)
1978  se->conn.capable |= FUSE_CAP_READDIRPLUS;
1979  if (inargflags & FUSE_READDIRPLUS_AUTO)
1980  se->conn.capable |= FUSE_CAP_READDIRPLUS_AUTO;
1981  if (inargflags & FUSE_ASYNC_DIO)
1982  se->conn.capable |= FUSE_CAP_ASYNC_DIO;
1983  if (inargflags & FUSE_WRITEBACK_CACHE)
1984  se->conn.capable |= FUSE_CAP_WRITEBACK_CACHE;
1985  if (inargflags & FUSE_NO_OPEN_SUPPORT)
1986  se->conn.capable |= FUSE_CAP_NO_OPEN_SUPPORT;
1987  if (inargflags & FUSE_PARALLEL_DIROPS)
1988  se->conn.capable |= FUSE_CAP_PARALLEL_DIROPS;
1989  if (inargflags & FUSE_POSIX_ACL)
1990  se->conn.capable |= FUSE_CAP_POSIX_ACL;
1991  if (inargflags & FUSE_HANDLE_KILLPRIV)
1992  se->conn.capable |= FUSE_CAP_HANDLE_KILLPRIV;
1993  if (inargflags & FUSE_CACHE_SYMLINKS)
1994  se->conn.capable |= FUSE_CAP_CACHE_SYMLINKS;
1995  if (inargflags & FUSE_NO_OPENDIR_SUPPORT)
1996  se->conn.capable |= FUSE_CAP_NO_OPENDIR_SUPPORT;
1997  if (inargflags & FUSE_EXPLICIT_INVAL_DATA)
1998  se->conn.capable |= FUSE_CAP_EXPLICIT_INVAL_DATA;
1999  if (!(inargflags & FUSE_MAX_PAGES)) {
2000  size_t max_bufsize =
2001  FUSE_DEFAULT_MAX_PAGES_PER_REQ * getpagesize()
2002  + FUSE_BUFFER_HEADER_SIZE;
2003  if (bufsize > max_bufsize) {
2004  bufsize = max_bufsize;
2005  }
2006  }
2007  if (arg->minor >= 38)
2008  se->conn.capable |= FUSE_CAP_EXPIRE_ONLY;
2009  } else {
2010  se->conn.max_readahead = 0;
2011  }
2012 
2013  if (se->conn.proto_minor >= 14) {
2014 #ifdef HAVE_SPLICE
2015 #ifdef HAVE_VMSPLICE
2016  if ((se->io == NULL) || (se->io->splice_send != NULL)) {
2017  se->conn.capable |= FUSE_CAP_SPLICE_WRITE | FUSE_CAP_SPLICE_MOVE;
2018  }
2019 #endif
2020  if ((se->io == NULL) || (se->io->splice_receive != NULL)) {
2021  se->conn.capable |= FUSE_CAP_SPLICE_READ;
2022  }
2023 #endif
2024  }
2025  if (se->conn.proto_minor >= 18)
2026  se->conn.capable |= FUSE_CAP_IOCTL_DIR;
2027 
2028  /* Default settings for modern filesystems.
2029  *
2030  * Most of these capabilities were disabled by default in
2031  * libfuse2 for backwards compatibility reasons. In libfuse3,
2032  * we can finally enable them by default (as long as they're
2033  * supported by the kernel).
2034  */
2035 #define LL_SET_DEFAULT(cond, cap) \
2036  if ((cond) && (se->conn.capable & (cap))) \
2037  se->conn.want |= (cap)
2038  LL_SET_DEFAULT(1, FUSE_CAP_ASYNC_READ);
2039  LL_SET_DEFAULT(1, FUSE_CAP_PARALLEL_DIROPS);
2040  LL_SET_DEFAULT(1, FUSE_CAP_AUTO_INVAL_DATA);
2041  LL_SET_DEFAULT(1, FUSE_CAP_HANDLE_KILLPRIV);
2042  LL_SET_DEFAULT(1, FUSE_CAP_ASYNC_DIO);
2043  LL_SET_DEFAULT(1, FUSE_CAP_IOCTL_DIR);
2044  LL_SET_DEFAULT(1, FUSE_CAP_ATOMIC_O_TRUNC);
2045  LL_SET_DEFAULT(se->op.write_buf, FUSE_CAP_SPLICE_READ);
2046  LL_SET_DEFAULT(se->op.getlk && se->op.setlk,
2048  LL_SET_DEFAULT(se->op.flock, FUSE_CAP_FLOCK_LOCKS);
2049  LL_SET_DEFAULT(se->op.readdirplus, FUSE_CAP_READDIRPLUS);
2050  LL_SET_DEFAULT(se->op.readdirplus && se->op.readdir,
2052  se->conn.time_gran = 1;
2053 
2054  if (bufsize < FUSE_MIN_READ_BUFFER) {
2055  fuse_log(FUSE_LOG_ERR, "fuse: warning: buffer size too small: %zu\n",
2056  bufsize);
2057  bufsize = FUSE_MIN_READ_BUFFER;
2058  }
2059  se->bufsize = bufsize;
2060 
2061  if (se->conn.max_write > bufsize - FUSE_BUFFER_HEADER_SIZE)
2062  se->conn.max_write = bufsize - FUSE_BUFFER_HEADER_SIZE;
2063 
2064  se->got_init = 1;
2065  if (se->op.init)
2066  se->op.init(se->userdata, &se->conn);
2067 
2068  if (se->conn.want & (~se->conn.capable)) {
2069  fuse_log(FUSE_LOG_ERR, "fuse: error: filesystem requested capabilities "
2070  "0x%x that are not supported by kernel, aborting.\n",
2071  se->conn.want & (~se->conn.capable));
2072  fuse_reply_err(req, EPROTO);
2073  se->error = -EPROTO;
2074  fuse_session_exit(se);
2075  return;
2076  }
2077 
2078  unsigned max_read_mo = get_max_read(se->mo);
2079  if (se->conn.max_read != max_read_mo) {
2080  fuse_log(FUSE_LOG_ERR, "fuse: error: init() and fuse_session_new() "
2081  "requested different maximum read size (%u vs %u)\n",
2082  se->conn.max_read, max_read_mo);
2083  fuse_reply_err(req, EPROTO);
2084  se->error = -EPROTO;
2085  fuse_session_exit(se);
2086  return;
2087  }
2088 
2089  if (se->conn.max_write < bufsize - FUSE_BUFFER_HEADER_SIZE) {
2090  se->bufsize = se->conn.max_write + FUSE_BUFFER_HEADER_SIZE;
2091  }
2092  if (arg->flags & FUSE_MAX_PAGES) {
2093  outarg.flags |= FUSE_MAX_PAGES;
2094  outarg.max_pages = (se->conn.max_write - 1) / getpagesize() + 1;
2095  }
2096  outargflags = outarg.flags;
2097  /* Always enable big writes, this is superseded
2098  by the max_write option */
2099  outargflags |= FUSE_BIG_WRITES;
2100 
2101  if (se->conn.want & FUSE_CAP_ASYNC_READ)
2102  outargflags |= FUSE_ASYNC_READ;
2103  if (se->conn.want & FUSE_CAP_POSIX_LOCKS)
2104  outargflags |= FUSE_POSIX_LOCKS;
2105  if (se->conn.want & FUSE_CAP_ATOMIC_O_TRUNC)
2106  outargflags |= FUSE_ATOMIC_O_TRUNC;
2107  if (se->conn.want & FUSE_CAP_EXPORT_SUPPORT)
2108  outargflags |= FUSE_EXPORT_SUPPORT;
2109  if (se->conn.want & FUSE_CAP_DONT_MASK)
2110  outargflags |= FUSE_DONT_MASK;
2111  if (se->conn.want & FUSE_CAP_FLOCK_LOCKS)
2112  outargflags |= FUSE_FLOCK_LOCKS;
2113  if (se->conn.want & FUSE_CAP_AUTO_INVAL_DATA)
2114  outargflags |= FUSE_AUTO_INVAL_DATA;
2115  if (se->conn.want & FUSE_CAP_READDIRPLUS)
2116  outargflags |= FUSE_DO_READDIRPLUS;
2117  if (se->conn.want & FUSE_CAP_READDIRPLUS_AUTO)
2118  outargflags |= FUSE_READDIRPLUS_AUTO;
2119  if (se->conn.want & FUSE_CAP_ASYNC_DIO)
2120  outargflags |= FUSE_ASYNC_DIO;
2121  if (se->conn.want & FUSE_CAP_WRITEBACK_CACHE)
2122  outargflags |= FUSE_WRITEBACK_CACHE;
2123  if (se->conn.want & FUSE_CAP_POSIX_ACL)
2124  outargflags |= FUSE_POSIX_ACL;
2125  if (se->conn.want & FUSE_CAP_CACHE_SYMLINKS)
2126  outargflags |= FUSE_CACHE_SYMLINKS;
2127  if (se->conn.want & FUSE_CAP_EXPLICIT_INVAL_DATA)
2128  outargflags |= FUSE_EXPLICIT_INVAL_DATA;
2129 
2130  if (inargflags & FUSE_INIT_EXT) {
2131  outargflags |= FUSE_INIT_EXT;
2132  outarg.flags2 = outargflags >> 32;
2133  }
2134 
2135  outarg.flags = outargflags;
2136 
2137  outarg.max_readahead = se->conn.max_readahead;
2138  outarg.max_write = se->conn.max_write;
2139  if (se->conn.proto_minor >= 13) {
2140  if (se->conn.max_background >= (1 << 16))
2141  se->conn.max_background = (1 << 16) - 1;
2142  if (se->conn.congestion_threshold > se->conn.max_background)
2143  se->conn.congestion_threshold = se->conn.max_background;
2144  if (!se->conn.congestion_threshold) {
2145  se->conn.congestion_threshold =
2146  se->conn.max_background * 3 / 4;
2147  }
2148 
2149  outarg.max_background = se->conn.max_background;
2150  outarg.congestion_threshold = se->conn.congestion_threshold;
2151  }
2152  if (se->conn.proto_minor >= 23)
2153  outarg.time_gran = se->conn.time_gran;
2154 
2155  if (se->debug) {
2156  fuse_log(FUSE_LOG_DEBUG, " INIT: %u.%u\n", outarg.major, outarg.minor);
2157  fuse_log(FUSE_LOG_DEBUG, " flags=0x%08x\n", outarg.flags);
2158  fuse_log(FUSE_LOG_DEBUG, " max_readahead=0x%08x\n",
2159  outarg.max_readahead);
2160  fuse_log(FUSE_LOG_DEBUG, " max_write=0x%08x\n", outarg.max_write);
2161  fuse_log(FUSE_LOG_DEBUG, " max_background=%i\n",
2162  outarg.max_background);
2163  fuse_log(FUSE_LOG_DEBUG, " congestion_threshold=%i\n",
2164  outarg.congestion_threshold);
2165  fuse_log(FUSE_LOG_DEBUG, " time_gran=%u\n",
2166  outarg.time_gran);
2167  }
2168  if (arg->minor < 5)
2169  outargsize = FUSE_COMPAT_INIT_OUT_SIZE;
2170  else if (arg->minor < 23)
2171  outargsize = FUSE_COMPAT_22_INIT_OUT_SIZE;
2172 
2173  send_reply_ok(req, &outarg, outargsize);
2174 }
2175 
2176 static void do_destroy(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
2177 {
2178  struct fuse_session *se = req->se;
2179 
2180  (void) nodeid;
2181  (void) inarg;
2182 
2183  se->got_destroy = 1;
2184  if (se->op.destroy)
2185  se->op.destroy(se->userdata);
2186 
2187  send_reply_ok(req, NULL, 0);
2188 }
2189 
2190 static void list_del_nreq(struct fuse_notify_req *nreq)
2191 {
2192  struct fuse_notify_req *prev = nreq->prev;
2193  struct fuse_notify_req *next = nreq->next;
2194  prev->next = next;
2195  next->prev = prev;
2196 }
2197 
2198 static void list_add_nreq(struct fuse_notify_req *nreq,
2199  struct fuse_notify_req *next)
2200 {
2201  struct fuse_notify_req *prev = next->prev;
2202  nreq->next = next;
2203  nreq->prev = prev;
2204  prev->next = nreq;
2205  next->prev = nreq;
2206 }
2207 
2208 static void list_init_nreq(struct fuse_notify_req *nreq)
2209 {
2210  nreq->next = nreq;
2211  nreq->prev = nreq;
2212 }
2213 
2214 static void do_notify_reply(fuse_req_t req, fuse_ino_t nodeid,
2215  const void *inarg, const struct fuse_buf *buf)
2216 {
2217  struct fuse_session *se = req->se;
2218  struct fuse_notify_req *nreq;
2219  struct fuse_notify_req *head;
2220 
2221  pthread_mutex_lock(&se->lock);
2222  head = &se->notify_list;
2223  for (nreq = head->next; nreq != head; nreq = nreq->next) {
2224  if (nreq->unique == req->unique) {
2225  list_del_nreq(nreq);
2226  break;
2227  }
2228  }
2229  pthread_mutex_unlock(&se->lock);
2230 
2231  if (nreq != head)
2232  nreq->reply(nreq, req, nodeid, inarg, buf);
2233 }
2234 
2235 static int send_notify_iov(struct fuse_session *se, int notify_code,
2236  struct iovec *iov, int count)
2237 {
2238  struct fuse_out_header out;
2239 
2240  if (!se->got_init)
2241  return -ENOTCONN;
2242 
2243  out.unique = 0;
2244  out.error = notify_code;
2245  iov[0].iov_base = &out;
2246  iov[0].iov_len = sizeof(struct fuse_out_header);
2247 
2248  return fuse_send_msg(se, NULL, iov, count);
2249 }
2250 
2251 int fuse_lowlevel_notify_poll(struct fuse_pollhandle *ph)
2252 {
2253  if (ph != NULL) {
2254  struct fuse_notify_poll_wakeup_out outarg;
2255  struct iovec iov[2];
2256 
2257  outarg.kh = ph->kh;
2258 
2259  iov[1].iov_base = &outarg;
2260  iov[1].iov_len = sizeof(outarg);
2261 
2262  return send_notify_iov(ph->se, FUSE_NOTIFY_POLL, iov, 2);
2263  } else {
2264  return 0;
2265  }
2266 }
2267 
2268 int fuse_lowlevel_notify_inval_inode(struct fuse_session *se, fuse_ino_t ino,
2269  off_t off, off_t len)
2270 {
2271  struct fuse_notify_inval_inode_out outarg;
2272  struct iovec iov[2];
2273 
2274  if (!se)
2275  return -EINVAL;
2276 
2277  if (se->conn.proto_minor < 12)
2278  return -ENOSYS;
2279 
2280  outarg.ino = ino;
2281  outarg.off = off;
2282  outarg.len = len;
2283 
2284  iov[1].iov_base = &outarg;
2285  iov[1].iov_len = sizeof(outarg);
2286 
2287  return send_notify_iov(se, FUSE_NOTIFY_INVAL_INODE, iov, 2);
2288 }
2289 
2290 int fuse_lowlevel_notify_expire_entry(struct fuse_session *se, fuse_ino_t parent,
2291  const char *name, size_t namelen,
2292  enum fuse_expire_flags flags)
2293 {
2294  struct fuse_notify_inval_entry_out outarg;
2295  struct iovec iov[3];
2296 
2297  if (!se)
2298  return -EINVAL;
2299 
2300  if (se->conn.proto_minor < 12)
2301  return -ENOSYS;
2302 
2303  outarg.parent = parent;
2304  outarg.namelen = namelen;
2305  outarg.flags = 0;
2306  if (flags & FUSE_LL_EXPIRE_ONLY)
2307  outarg.flags |= FUSE_EXPIRE_ONLY;
2308 
2309  iov[1].iov_base = &outarg;
2310  iov[1].iov_len = sizeof(outarg);
2311  iov[2].iov_base = (void *)name;
2312  iov[2].iov_len = namelen + 1;
2313 
2314  return send_notify_iov(se, FUSE_NOTIFY_INVAL_ENTRY, iov, 3);
2315 }
2316 
2317 int fuse_lowlevel_notify_inval_entry(struct fuse_session *se, fuse_ino_t parent,
2318  const char *name, size_t namelen)
2319 {
2320  return fuse_lowlevel_notify_expire_entry(se, parent, name, namelen, 0);
2321 }
2322 
2323 
2324 int fuse_lowlevel_notify_delete(struct fuse_session *se,
2325  fuse_ino_t parent, fuse_ino_t child,
2326  const char *name, size_t namelen)
2327 {
2328  struct fuse_notify_delete_out outarg;
2329  struct iovec iov[3];
2330 
2331  if (!se)
2332  return -EINVAL;
2333 
2334  if (se->conn.proto_minor < 18)
2335  return -ENOSYS;
2336 
2337  outarg.parent = parent;
2338  outarg.child = child;
2339  outarg.namelen = namelen;
2340  outarg.padding = 0;
2341 
2342  iov[1].iov_base = &outarg;
2343  iov[1].iov_len = sizeof(outarg);
2344  iov[2].iov_base = (void *)name;
2345  iov[2].iov_len = namelen + 1;
2346 
2347  return send_notify_iov(se, FUSE_NOTIFY_DELETE, iov, 3);
2348 }
2349 
2350 int fuse_lowlevel_notify_store(struct fuse_session *se, fuse_ino_t ino,
2351  off_t offset, struct fuse_bufvec *bufv,
2352  enum fuse_buf_copy_flags flags)
2353 {
2354  struct fuse_out_header out;
2355  struct fuse_notify_store_out outarg;
2356  struct iovec iov[3];
2357  size_t size = fuse_buf_size(bufv);
2358  int res;
2359 
2360  if (!se)
2361  return -EINVAL;
2362 
2363  if (se->conn.proto_minor < 15)
2364  return -ENOSYS;
2365 
2366  out.unique = 0;
2367  out.error = FUSE_NOTIFY_STORE;
2368 
2369  outarg.nodeid = ino;
2370  outarg.offset = offset;
2371  outarg.size = size;
2372  outarg.padding = 0;
2373 
2374  iov[0].iov_base = &out;
2375  iov[0].iov_len = sizeof(out);
2376  iov[1].iov_base = &outarg;
2377  iov[1].iov_len = sizeof(outarg);
2378 
2379  res = fuse_send_data_iov(se, NULL, iov, 2, bufv, flags);
2380  if (res > 0)
2381  res = -res;
2382 
2383  return res;
2384 }
2385 
2386 struct fuse_retrieve_req {
2387  struct fuse_notify_req nreq;
2388  void *cookie;
2389 };
2390 
2391 static void fuse_ll_retrieve_reply(struct fuse_notify_req *nreq,
2392  fuse_req_t req, fuse_ino_t ino,
2393  const void *inarg,
2394  const struct fuse_buf *ibuf)
2395 {
2396  struct fuse_session *se = req->se;
2397  struct fuse_retrieve_req *rreq =
2398  container_of(nreq, struct fuse_retrieve_req, nreq);
2399  const struct fuse_notify_retrieve_in *arg = inarg;
2400  struct fuse_bufvec bufv = {
2401  .buf[0] = *ibuf,
2402  .count = 1,
2403  };
2404 
2405  if (!(bufv.buf[0].flags & FUSE_BUF_IS_FD))
2406  bufv.buf[0].mem = PARAM(arg);
2407 
2408  bufv.buf[0].size -= sizeof(struct fuse_in_header) +
2409  sizeof(struct fuse_notify_retrieve_in);
2410 
2411  if (bufv.buf[0].size < arg->size) {
2412  fuse_log(FUSE_LOG_ERR, "fuse: retrieve reply: buffer size too small\n");
2413  fuse_reply_none(req);
2414  goto out;
2415  }
2416  bufv.buf[0].size = arg->size;
2417 
2418  if (se->op.retrieve_reply) {
2419  se->op.retrieve_reply(req, rreq->cookie, ino,
2420  arg->offset, &bufv);
2421  } else {
2422  fuse_reply_none(req);
2423  }
2424 out:
2425  free(rreq);
2426  if ((ibuf->flags & FUSE_BUF_IS_FD) && bufv.idx < bufv.count)
2427  fuse_ll_clear_pipe(se);
2428 }
2429 
2430 int fuse_lowlevel_notify_retrieve(struct fuse_session *se, fuse_ino_t ino,
2431  size_t size, off_t offset, void *cookie)
2432 {
2433  struct fuse_notify_retrieve_out outarg;
2434  struct iovec iov[2];
2435  struct fuse_retrieve_req *rreq;
2436  int err;
2437 
2438  if (!se)
2439  return -EINVAL;
2440 
2441  if (se->conn.proto_minor < 15)
2442  return -ENOSYS;
2443 
2444  rreq = malloc(sizeof(*rreq));
2445  if (rreq == NULL)
2446  return -ENOMEM;
2447 
2448  pthread_mutex_lock(&se->lock);
2449  rreq->cookie = cookie;
2450  rreq->nreq.unique = se->notify_ctr++;
2451  rreq->nreq.reply = fuse_ll_retrieve_reply;
2452  list_add_nreq(&rreq->nreq, &se->notify_list);
2453  pthread_mutex_unlock(&se->lock);
2454 
2455  outarg.notify_unique = rreq->nreq.unique;
2456  outarg.nodeid = ino;
2457  outarg.offset = offset;
2458  outarg.size = size;
2459  outarg.padding = 0;
2460 
2461  iov[1].iov_base = &outarg;
2462  iov[1].iov_len = sizeof(outarg);
2463 
2464  err = send_notify_iov(se, FUSE_NOTIFY_RETRIEVE, iov, 2);
2465  if (err) {
2466  pthread_mutex_lock(&se->lock);
2467  list_del_nreq(&rreq->nreq);
2468  pthread_mutex_unlock(&se->lock);
2469  free(rreq);
2470  }
2471 
2472  return err;
2473 }
2474 
2476 {
2477  return req->se->userdata;
2478 }
2479 
2481 {
2482  return &req->ctx;
2483 }
2484 
2486  void *data)
2487 {
2488  pthread_mutex_lock(&req->lock);
2489  pthread_mutex_lock(&req->se->lock);
2490  req->u.ni.func = func;
2491  req->u.ni.data = data;
2492  pthread_mutex_unlock(&req->se->lock);
2493  if (req->interrupted && func)
2494  func(req, data);
2495  pthread_mutex_unlock(&req->lock);
2496 }
2497 
2499 {
2500  int interrupted;
2501 
2502  pthread_mutex_lock(&req->se->lock);
2503  interrupted = req->interrupted;
2504  pthread_mutex_unlock(&req->se->lock);
2505 
2506  return interrupted;
2507 }
2508 
2509 static struct {
2510  void (*func)(fuse_req_t, fuse_ino_t, const void *);
2511  const char *name;
2512 } fuse_ll_ops[] = {
2513  [FUSE_LOOKUP] = { do_lookup, "LOOKUP" },
2514  [FUSE_FORGET] = { do_forget, "FORGET" },
2515  [FUSE_GETATTR] = { do_getattr, "GETATTR" },
2516  [FUSE_SETATTR] = { do_setattr, "SETATTR" },
2517  [FUSE_READLINK] = { do_readlink, "READLINK" },
2518  [FUSE_SYMLINK] = { do_symlink, "SYMLINK" },
2519  [FUSE_MKNOD] = { do_mknod, "MKNOD" },
2520  [FUSE_MKDIR] = { do_mkdir, "MKDIR" },
2521  [FUSE_UNLINK] = { do_unlink, "UNLINK" },
2522  [FUSE_RMDIR] = { do_rmdir, "RMDIR" },
2523  [FUSE_RENAME] = { do_rename, "RENAME" },
2524  [FUSE_LINK] = { do_link, "LINK" },
2525  [FUSE_OPEN] = { do_open, "OPEN" },
2526  [FUSE_READ] = { do_read, "READ" },
2527  [FUSE_WRITE] = { do_write, "WRITE" },
2528  [FUSE_STATFS] = { do_statfs, "STATFS" },
2529  [FUSE_RELEASE] = { do_release, "RELEASE" },
2530  [FUSE_FSYNC] = { do_fsync, "FSYNC" },
2531  [FUSE_SETXATTR] = { do_setxattr, "SETXATTR" },
2532  [FUSE_GETXATTR] = { do_getxattr, "GETXATTR" },
2533  [FUSE_LISTXATTR] = { do_listxattr, "LISTXATTR" },
2534  [FUSE_REMOVEXATTR] = { do_removexattr, "REMOVEXATTR" },
2535  [FUSE_FLUSH] = { do_flush, "FLUSH" },
2536  [FUSE_INIT] = { do_init, "INIT" },
2537  [FUSE_OPENDIR] = { do_opendir, "OPENDIR" },
2538  [FUSE_READDIR] = { do_readdir, "READDIR" },
2539  [FUSE_RELEASEDIR] = { do_releasedir, "RELEASEDIR" },
2540  [FUSE_FSYNCDIR] = { do_fsyncdir, "FSYNCDIR" },
2541  [FUSE_GETLK] = { do_getlk, "GETLK" },
2542  [FUSE_SETLK] = { do_setlk, "SETLK" },
2543  [FUSE_SETLKW] = { do_setlkw, "SETLKW" },
2544  [FUSE_ACCESS] = { do_access, "ACCESS" },
2545  [FUSE_CREATE] = { do_create, "CREATE" },
2546  [FUSE_INTERRUPT] = { do_interrupt, "INTERRUPT" },
2547  [FUSE_BMAP] = { do_bmap, "BMAP" },
2548  [FUSE_IOCTL] = { do_ioctl, "IOCTL" },
2549  [FUSE_POLL] = { do_poll, "POLL" },
2550  [FUSE_FALLOCATE] = { do_fallocate, "FALLOCATE" },
2551  [FUSE_DESTROY] = { do_destroy, "DESTROY" },
2552  [FUSE_NOTIFY_REPLY] = { (void *) 1, "NOTIFY_REPLY" },
2553  [FUSE_BATCH_FORGET] = { do_batch_forget, "BATCH_FORGET" },
2554  [FUSE_READDIRPLUS] = { do_readdirplus, "READDIRPLUS"},
2555  [FUSE_RENAME2] = { do_rename2, "RENAME2" },
2556  [FUSE_COPY_FILE_RANGE] = { do_copy_file_range, "COPY_FILE_RANGE" },
2557  [FUSE_LSEEK] = { do_lseek, "LSEEK" },
2558  [CUSE_INIT] = { cuse_lowlevel_init, "CUSE_INIT" },
2559 };
2560 
2561 #define FUSE_MAXOP (sizeof(fuse_ll_ops) / sizeof(fuse_ll_ops[0]))
2562 
2563 static const char *opname(enum fuse_opcode opcode)
2564 {
2565  if (opcode >= FUSE_MAXOP || !fuse_ll_ops[opcode].name)
2566  return "???";
2567  else
2568  return fuse_ll_ops[opcode].name;
2569 }
2570 
2571 static int fuse_ll_copy_from_pipe(struct fuse_bufvec *dst,
2572  struct fuse_bufvec *src)
2573 {
2574  ssize_t res = fuse_buf_copy(dst, src, 0);
2575  if (res < 0) {
2576  fuse_log(FUSE_LOG_ERR, "fuse: copy from pipe: %s\n", strerror(-res));
2577  return res;
2578  }
2579  if ((size_t)res < fuse_buf_size(dst)) {
2580  fuse_log(FUSE_LOG_ERR, "fuse: copy from pipe: short read\n");
2581  return -1;
2582  }
2583  return 0;
2584 }
2585 
2586 void fuse_session_process_buf(struct fuse_session *se,
2587  const struct fuse_buf *buf)
2588 {
2589  fuse_session_process_buf_int(se, buf, NULL);
2590 }
2591 
2592 void fuse_session_process_buf_int(struct fuse_session *se,
2593  const struct fuse_buf *buf, struct fuse_chan *ch)
2594 {
2595  const size_t write_header_size = sizeof(struct fuse_in_header) +
2596  sizeof(struct fuse_write_in);
2597  struct fuse_bufvec bufv = { .buf[0] = *buf, .count = 1 };
2598  struct fuse_bufvec tmpbuf = FUSE_BUFVEC_INIT(write_header_size);
2599  struct fuse_in_header *in;
2600  const void *inarg;
2601  struct fuse_req *req;
2602  void *mbuf = NULL;
2603  int err;
2604  int res;
2605 
2606  if (buf->flags & FUSE_BUF_IS_FD) {
2607  if (buf->size < tmpbuf.buf[0].size)
2608  tmpbuf.buf[0].size = buf->size;
2609 
2610  mbuf = malloc(tmpbuf.buf[0].size);
2611  if (mbuf == NULL) {
2612  fuse_log(FUSE_LOG_ERR, "fuse: failed to allocate header\n");
2613  goto clear_pipe;
2614  }
2615  tmpbuf.buf[0].mem = mbuf;
2616 
2617  res = fuse_ll_copy_from_pipe(&tmpbuf, &bufv);
2618  if (res < 0)
2619  goto clear_pipe;
2620 
2621  in = mbuf;
2622  } else {
2623  in = buf->mem;
2624  }
2625 
2626  if (se->debug) {
2627  fuse_log(FUSE_LOG_DEBUG,
2628  "unique: %llu, opcode: %s (%i), nodeid: %llu, insize: %zu, pid: %u\n",
2629  (unsigned long long) in->unique,
2630  opname((enum fuse_opcode) in->opcode), in->opcode,
2631  (unsigned long long) in->nodeid, buf->size, in->pid);
2632  }
2633 
2634  req = fuse_ll_alloc_req(se);
2635  if (req == NULL) {
2636  struct fuse_out_header out = {
2637  .unique = in->unique,
2638  .error = -ENOMEM,
2639  };
2640  struct iovec iov = {
2641  .iov_base = &out,
2642  .iov_len = sizeof(struct fuse_out_header),
2643  };
2644 
2645  fuse_send_msg(se, ch, &iov, 1);
2646  goto clear_pipe;
2647  }
2648 
2649  req->unique = in->unique;
2650  req->ctx.uid = in->uid;
2651  req->ctx.gid = in->gid;
2652  req->ctx.pid = in->pid;
2653  req->ch = ch ? fuse_chan_get(ch) : NULL;
2654 
2655  err = EIO;
2656  if (!se->got_init) {
2657  enum fuse_opcode expected;
2658 
2659  expected = se->cuse_data ? CUSE_INIT : FUSE_INIT;
2660  if (in->opcode != expected)
2661  goto reply_err;
2662  } else if (in->opcode == FUSE_INIT || in->opcode == CUSE_INIT)
2663  goto reply_err;
2664 
2665  err = EACCES;
2666  /* Implement -o allow_root */
2667  if (se->deny_others && in->uid != se->owner && in->uid != 0 &&
2668  in->opcode != FUSE_INIT && in->opcode != FUSE_READ &&
2669  in->opcode != FUSE_WRITE && in->opcode != FUSE_FSYNC &&
2670  in->opcode != FUSE_RELEASE && in->opcode != FUSE_READDIR &&
2671  in->opcode != FUSE_FSYNCDIR && in->opcode != FUSE_RELEASEDIR &&
2672  in->opcode != FUSE_NOTIFY_REPLY &&
2673  in->opcode != FUSE_READDIRPLUS)
2674  goto reply_err;
2675 
2676  err = ENOSYS;
2677  if (in->opcode >= FUSE_MAXOP || !fuse_ll_ops[in->opcode].func)
2678  goto reply_err;
2679  if (in->opcode != FUSE_INTERRUPT) {
2680  struct fuse_req *intr;
2681  pthread_mutex_lock(&se->lock);
2682  intr = check_interrupt(se, req);
2683  list_add_req(req, &se->list);
2684  pthread_mutex_unlock(&se->lock);
2685  if (intr)
2686  fuse_reply_err(intr, EAGAIN);
2687  }
2688 
2689  if ((buf->flags & FUSE_BUF_IS_FD) && write_header_size < buf->size &&
2690  (in->opcode != FUSE_WRITE || !se->op.write_buf) &&
2691  in->opcode != FUSE_NOTIFY_REPLY) {
2692  void *newmbuf;
2693 
2694  err = ENOMEM;
2695  newmbuf = realloc(mbuf, buf->size);
2696  if (newmbuf == NULL)
2697  goto reply_err;
2698  mbuf = newmbuf;
2699 
2700  tmpbuf = FUSE_BUFVEC_INIT(buf->size - write_header_size);
2701  tmpbuf.buf[0].mem = (char *)mbuf + write_header_size;
2702 
2703  res = fuse_ll_copy_from_pipe(&tmpbuf, &bufv);
2704  err = -res;
2705  if (res < 0)
2706  goto reply_err;
2707 
2708  in = mbuf;
2709  }
2710 
2711  inarg = (void *) &in[1];
2712  if (in->opcode == FUSE_WRITE && se->op.write_buf)
2713  do_write_buf(req, in->nodeid, inarg, buf);
2714  else if (in->opcode == FUSE_NOTIFY_REPLY)
2715  do_notify_reply(req, in->nodeid, inarg, buf);
2716  else
2717  fuse_ll_ops[in->opcode].func(req, in->nodeid, inarg);
2718 
2719 out_free:
2720  free(mbuf);
2721  return;
2722 
2723 reply_err:
2724  fuse_reply_err(req, err);
2725 clear_pipe:
2726  if (buf->flags & FUSE_BUF_IS_FD)
2727  fuse_ll_clear_pipe(se);
2728  goto out_free;
2729 }
2730 
2731 #define LL_OPTION(n,o,v) \
2732  { n, offsetof(struct fuse_session, o), v }
2733 
2734 static const struct fuse_opt fuse_ll_opts[] = {
2735  LL_OPTION("debug", debug, 1),
2736  LL_OPTION("-d", debug, 1),
2737  LL_OPTION("--debug", debug, 1),
2738  LL_OPTION("allow_root", deny_others, 1),
2739  FUSE_OPT_END
2740 };
2741 
2743 {
2744  printf("using FUSE kernel interface version %i.%i\n",
2745  FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION);
2746  fuse_mount_version();
2747 }
2748 
2750 {
2751  /* These are not all options, but the ones that are
2752  potentially of interest to an end-user */
2753  printf(
2754 " -o allow_other allow access by all users\n"
2755 " -o allow_root allow access by root\n"
2756 " -o auto_unmount auto unmount on process termination\n");
2757 }
2758 
2759 void fuse_session_destroy(struct fuse_session *se)
2760 {
2761  struct fuse_ll_pipe *llp;
2762 
2763  if (se->got_init && !se->got_destroy) {
2764  if (se->op.destroy)
2765  se->op.destroy(se->userdata);
2766  }
2767  llp = pthread_getspecific(se->pipe_key);
2768  if (llp != NULL)
2769  fuse_ll_pipe_free(llp);
2770  pthread_key_delete(se->pipe_key);
2771  pthread_mutex_destroy(&se->lock);
2772  free(se->cuse_data);
2773  if (se->fd != -1)
2774  close(se->fd);
2775  if (se->io != NULL)
2776  free(se->io);
2777  destroy_mount_opts(se->mo);
2778  free(se);
2779 }
2780 
2781 
2782 static void fuse_ll_pipe_destructor(void *data)
2783 {
2784  struct fuse_ll_pipe *llp = data;
2785  fuse_ll_pipe_free(llp);
2786 }
2787 
2788 int fuse_session_receive_buf(struct fuse_session *se, struct fuse_buf *buf)
2789 {
2790  return fuse_session_receive_buf_int(se, buf, NULL);
2791 }
2792 
2793 int fuse_session_receive_buf_int(struct fuse_session *se, struct fuse_buf *buf,
2794  struct fuse_chan *ch)
2795 {
2796  int err;
2797  ssize_t res;
2798 #ifdef HAVE_SPLICE
2799  size_t bufsize = se->bufsize;
2800  struct fuse_ll_pipe *llp;
2801  struct fuse_buf tmpbuf;
2802 
2803  if (se->conn.proto_minor < 14 || !(se->conn.want & FUSE_CAP_SPLICE_READ))
2804  goto fallback;
2805 
2806  llp = fuse_ll_get_pipe(se);
2807  if (llp == NULL)
2808  goto fallback;
2809 
2810  if (llp->size < bufsize) {
2811  if (llp->can_grow) {
2812  res = fcntl(llp->pipe[0], F_SETPIPE_SZ, bufsize);
2813  if (res == -1) {
2814  llp->can_grow = 0;
2815  res = grow_pipe_to_max(llp->pipe[0]);
2816  if (res > 0)
2817  llp->size = res;
2818  goto fallback;
2819  }
2820  llp->size = res;
2821  }
2822  if (llp->size < bufsize)
2823  goto fallback;
2824  }
2825 
2826  if (se->io != NULL && se->io->splice_receive != NULL) {
2827  res = se->io->splice_receive(ch ? ch->fd : se->fd, NULL,
2828  llp->pipe[1], NULL, bufsize, 0,
2829  se->userdata);
2830  } else {
2831  res = splice(ch ? ch->fd : se->fd, NULL, llp->pipe[1], NULL,
2832  bufsize, 0);
2833  }
2834  err = errno;
2835 
2836  if (fuse_session_exited(se))
2837  return 0;
2838 
2839  if (res == -1) {
2840  if (err == ENODEV) {
2841  /* Filesystem was unmounted, or connection was aborted
2842  via /sys/fs/fuse/connections */
2843  fuse_session_exit(se);
2844  return 0;
2845  }
2846  if (err != EINTR && err != EAGAIN)
2847  perror("fuse: splice from device");
2848  return -err;
2849  }
2850 
2851  if (res < sizeof(struct fuse_in_header)) {
2852  fuse_log(FUSE_LOG_ERR, "short splice from fuse device\n");
2853  return -EIO;
2854  }
2855 
2856  tmpbuf = (struct fuse_buf) {
2857  .size = res,
2858  .flags = FUSE_BUF_IS_FD,
2859  .fd = llp->pipe[0],
2860  };
2861 
2862  /*
2863  * Don't bother with zero copy for small requests.
2864  * fuse_loop_mt() needs to check for FORGET so this more than
2865  * just an optimization.
2866  */
2867  if (res < sizeof(struct fuse_in_header) +
2868  sizeof(struct fuse_write_in) + pagesize) {
2869  struct fuse_bufvec src = { .buf[0] = tmpbuf, .count = 1 };
2870  struct fuse_bufvec dst = { .count = 1 };
2871 
2872  if (!buf->mem) {
2873  buf->mem = malloc(se->bufsize);
2874  if (!buf->mem) {
2875  fuse_log(FUSE_LOG_ERR,
2876  "fuse: failed to allocate read buffer\n");
2877  return -ENOMEM;
2878  }
2879  }
2880  buf->size = se->bufsize;
2881  buf->flags = 0;
2882  dst.buf[0] = *buf;
2883 
2884  res = fuse_buf_copy(&dst, &src, 0);
2885  if (res < 0) {
2886  fuse_log(FUSE_LOG_ERR, "fuse: copy from pipe: %s\n",
2887  strerror(-res));
2888  fuse_ll_clear_pipe(se);
2889  return res;
2890  }
2891  if (res < tmpbuf.size) {
2892  fuse_log(FUSE_LOG_ERR, "fuse: copy from pipe: short read\n");
2893  fuse_ll_clear_pipe(se);
2894  return -EIO;
2895  }
2896  assert(res == tmpbuf.size);
2897 
2898  } else {
2899  /* Don't overwrite buf->mem, as that would cause a leak */
2900  buf->fd = tmpbuf.fd;
2901  buf->flags = tmpbuf.flags;
2902  }
2903  buf->size = tmpbuf.size;
2904 
2905  return res;
2906 
2907 fallback:
2908 #endif
2909  if (!buf->mem) {
2910  buf->mem = malloc(se->bufsize);
2911  if (!buf->mem) {
2912  fuse_log(FUSE_LOG_ERR,
2913  "fuse: failed to allocate read buffer\n");
2914  return -ENOMEM;
2915  }
2916  }
2917 
2918 restart:
2919  if (se->io != NULL) {
2920  /* se->io->read is never NULL if se->io is not NULL as
2921  specified by fuse_session_custom_io()*/
2922  res = se->io->read(ch ? ch->fd : se->fd, buf->mem, se->bufsize,
2923  se->userdata);
2924  } else {
2925  res = read(ch ? ch->fd : se->fd, buf->mem, se->bufsize);
2926  }
2927  err = errno;
2928 
2929  if (fuse_session_exited(se))
2930  return 0;
2931  if (res == -1) {
2932  /* ENOENT means the operation was interrupted, it's safe
2933  to restart */
2934  if (err == ENOENT)
2935  goto restart;
2936 
2937  if (err == ENODEV) {
2938  /* Filesystem was unmounted, or connection was aborted
2939  via /sys/fs/fuse/connections */
2940  fuse_session_exit(se);
2941  return 0;
2942  }
2943  /* Errors occurring during normal operation: EINTR (read
2944  interrupted), EAGAIN (nonblocking I/O), ENODEV (filesystem
2945  umounted) */
2946  if (err != EINTR && err != EAGAIN)
2947  perror("fuse: reading device");
2948  return -err;
2949  }
2950  if ((size_t) res < sizeof(struct fuse_in_header)) {
2951  fuse_log(FUSE_LOG_ERR, "short read on fuse device\n");
2952  return -EIO;
2953  }
2954 
2955  buf->size = res;
2956 
2957  return res;
2958 }
2959 
2960 struct fuse_session *fuse_session_new(struct fuse_args *args,
2961  const struct fuse_lowlevel_ops *op,
2962  size_t op_size, void *userdata)
2963 {
2964  int err;
2965  struct fuse_session *se;
2966  struct mount_opts *mo;
2967 
2968  if (sizeof(struct fuse_lowlevel_ops) < op_size) {
2969  fuse_log(FUSE_LOG_ERR, "fuse: warning: library too old, some operations may not work\n");
2970  op_size = sizeof(struct fuse_lowlevel_ops);
2971  }
2972 
2973  if (args->argc == 0) {
2974  fuse_log(FUSE_LOG_ERR, "fuse: empty argv passed to fuse_session_new().\n");
2975  return NULL;
2976  }
2977 
2978  se = (struct fuse_session *) calloc(1, sizeof(struct fuse_session));
2979  if (se == NULL) {
2980  fuse_log(FUSE_LOG_ERR, "fuse: failed to allocate fuse object\n");
2981  goto out1;
2982  }
2983  se->fd = -1;
2984  se->conn.max_write = UINT_MAX;
2985  se->conn.max_readahead = UINT_MAX;
2986 
2987  /* Parse options */
2988  if(fuse_opt_parse(args, se, fuse_ll_opts, NULL) == -1)
2989  goto out2;
2990  if(se->deny_others) {
2991  /* Allowing access only by root is done by instructing
2992  * kernel to allow access by everyone, and then restricting
2993  * access to root and mountpoint owner in libfuse.
2994  */
2995  // We may be adding the option a second time, but
2996  // that doesn't hurt.
2997  if(fuse_opt_add_arg(args, "-oallow_other") == -1)
2998  goto out2;
2999  }
3000  mo = parse_mount_opts(args);
3001  if (mo == NULL)
3002  goto out3;
3003 
3004  if(args->argc == 1 &&
3005  args->argv[0][0] == '-') {
3006  fuse_log(FUSE_LOG_ERR, "fuse: warning: argv[0] looks like an option, but "
3007  "will be ignored\n");
3008  } else if (args->argc != 1) {
3009  int i;
3010  fuse_log(FUSE_LOG_ERR, "fuse: unknown option(s): `");
3011  for(i = 1; i < args->argc-1; i++)
3012  fuse_log(FUSE_LOG_ERR, "%s ", args->argv[i]);
3013  fuse_log(FUSE_LOG_ERR, "%s'\n", args->argv[i]);
3014  goto out4;
3015  }
3016 
3017  if (se->debug)
3018  fuse_log(FUSE_LOG_DEBUG, "FUSE library version: %s\n", PACKAGE_VERSION);
3019 
3020  se->bufsize = FUSE_MAX_MAX_PAGES * getpagesize() +
3021  FUSE_BUFFER_HEADER_SIZE;
3022 
3023  list_init_req(&se->list);
3024  list_init_req(&se->interrupts);
3025  list_init_nreq(&se->notify_list);
3026  se->notify_ctr = 1;
3027  pthread_mutex_init(&se->lock, NULL);
3028 
3029  err = pthread_key_create(&se->pipe_key, fuse_ll_pipe_destructor);
3030  if (err) {
3031  fuse_log(FUSE_LOG_ERR, "fuse: failed to create thread specific key: %s\n",
3032  strerror(err));
3033  goto out5;
3034  }
3035 
3036  memcpy(&se->op, op, op_size);
3037  se->owner = getuid();
3038  se->userdata = userdata;
3039 
3040  se->mo = mo;
3041  return se;
3042 
3043 out5:
3044  pthread_mutex_destroy(&se->lock);
3045 out4:
3046  fuse_opt_free_args(args);
3047 out3:
3048  if (mo != NULL)
3049  destroy_mount_opts(mo);
3050 out2:
3051  free(se);
3052 out1:
3053  return NULL;
3054 }
3055 
3056 int fuse_session_custom_io(struct fuse_session *se, const struct fuse_custom_io *io,
3057  int fd)
3058 {
3059  if (fd < 0) {
3060  fuse_log(FUSE_LOG_ERR, "Invalid file descriptor value %d passed to "
3061  "fuse_session_custom_io()\n", fd);
3062  return -EBADF;
3063  }
3064  if (io == NULL) {
3065  fuse_log(FUSE_LOG_ERR, "No custom IO passed to "
3066  "fuse_session_custom_io()\n");
3067  return -EINVAL;
3068  } else if (io->read == NULL || io->writev == NULL) {
3069  /* If the user provides their own file descriptor, we can't
3070  guarantee that the default behavior of the io operations made
3071  in libfuse will function properly. Therefore, we enforce the
3072  user to implement these io operations when using custom io. */
3073  fuse_log(FUSE_LOG_ERR, "io passed to fuse_session_custom_io() must "
3074  "implement both io->read() and io->writev\n");
3075  return -EINVAL;
3076  }
3077 
3078  se->io = malloc(sizeof(struct fuse_custom_io));
3079  if (se->io == NULL) {
3080  fuse_log(FUSE_LOG_ERR, "Failed to allocate memory for custom io. "
3081  "Error: %s\n", strerror(errno));
3082  return -errno;
3083  }
3084 
3085  se->fd = fd;
3086  *se->io = *io;
3087  return 0;
3088 }
3089 
3090 int fuse_session_mount(struct fuse_session *se, const char *mountpoint)
3091 {
3092  int fd;
3093 
3094  /*
3095  * Make sure file descriptors 0, 1 and 2 are open, otherwise chaos
3096  * would ensue.
3097  */
3098  do {
3099  fd = open("/dev/null", O_RDWR);
3100  if (fd > 2)
3101  close(fd);
3102  } while (fd >= 0 && fd <= 2);
3103 
3104  /*
3105  * To allow FUSE daemons to run without privileges, the caller may open
3106  * /dev/fuse before launching the file system and pass on the file
3107  * descriptor by specifying /dev/fd/N as the mount point. Note that the
3108  * parent process takes care of performing the mount in this case.
3109  */
3110  fd = fuse_mnt_parse_fuse_fd(mountpoint);
3111  if (fd != -1) {
3112  if (fcntl(fd, F_GETFD) == -1) {
3113  fuse_log(FUSE_LOG_ERR,
3114  "fuse: Invalid file descriptor /dev/fd/%u\n",
3115  fd);
3116  return -1;
3117  }
3118  se->fd = fd;
3119  return 0;
3120  }
3121 
3122  /* Open channel */
3123  fd = fuse_kern_mount(mountpoint, se->mo);
3124  if (fd == -1)
3125  return -1;
3126  se->fd = fd;
3127 
3128  /* Save mountpoint */
3129  se->mountpoint = strdup(mountpoint);
3130  if (se->mountpoint == NULL)
3131  goto error_out;
3132 
3133  return 0;
3134 
3135 error_out:
3136  fuse_kern_unmount(mountpoint, fd);
3137  return -1;
3138 }
3139 
3140 int fuse_session_fd(struct fuse_session *se)
3141 {
3142  return se->fd;
3143 }
3144 
3145 void fuse_session_unmount(struct fuse_session *se)
3146 {
3147  if (se->mountpoint != NULL) {
3148  fuse_kern_unmount(se->mountpoint, se->fd);
3149  se->fd = -1;
3150  free(se->mountpoint);
3151  se->mountpoint = NULL;
3152  }
3153 }
3154 
3155 #ifdef linux
3156 int fuse_req_getgroups(fuse_req_t req, int size, gid_t list[])
3157 {
3158  char *buf;
3159  size_t bufsize = 1024;
3160  char path[128];
3161  int ret;
3162  int fd;
3163  unsigned long pid = req->ctx.pid;
3164  char *s;
3165 
3166  sprintf(path, "/proc/%lu/task/%lu/status", pid, pid);
3167 
3168 retry:
3169  buf = malloc(bufsize);
3170  if (buf == NULL)
3171  return -ENOMEM;
3172 
3173  ret = -EIO;
3174  fd = open(path, O_RDONLY);
3175  if (fd == -1)
3176  goto out_free;
3177 
3178  ret = read(fd, buf, bufsize);
3179  close(fd);
3180  if (ret < 0) {
3181  ret = -EIO;
3182  goto out_free;
3183  }
3184 
3185  if ((size_t)ret == bufsize) {
3186  free(buf);
3187  bufsize *= 4;
3188  goto retry;
3189  }
3190 
3191  ret = -EIO;
3192  s = strstr(buf, "\nGroups:");
3193  if (s == NULL)
3194  goto out_free;
3195 
3196  s += 8;
3197  ret = 0;
3198  while (1) {
3199  char *end;
3200  unsigned long val = strtoul(s, &end, 0);
3201  if (end == s)
3202  break;
3203 
3204  s = end;
3205  if (ret < size)
3206  list[ret] = val;
3207  ret++;
3208  }
3209 
3210 out_free:
3211  free(buf);
3212  return ret;
3213 }
3214 #else /* linux */
3215 /*
3216  * This is currently not implemented on other than Linux...
3217  */
3218 int fuse_req_getgroups(fuse_req_t req, int size, gid_t list[])
3219 {
3220  (void) req; (void) size; (void) list;
3221  return -ENOSYS;
3222 }
3223 #endif
3224 
3225 /* Prevent spurious data race warning - we don't care
3226  * about races for this flag */
3227 __attribute__((no_sanitize_thread))
3228 void fuse_session_exit(struct fuse_session *se)
3229 {
3230  se->exited = 1;
3231 }
3232 
3233 __attribute__((no_sanitize_thread))
3234 void fuse_session_reset(struct fuse_session *se)
3235 {
3236  se->exited = 0;
3237  se->error = 0;
3238 }
3239 
3240 __attribute__((no_sanitize_thread))
3241 int fuse_session_exited(struct fuse_session *se)
3242 {
3243  return se->exited;
3244 }
#define FUSE_CAP_IOCTL_DIR
Definition: fuse_common.h:232
#define FUSE_CAP_DONT_MASK
Definition: fuse_common.h:187
#define FUSE_CAP_HANDLE_KILLPRIV
Definition: fuse_common.h:361
#define FUSE_CAP_AUTO_INVAL_DATA
Definition: fuse_common.h:254
#define FUSE_CAP_SPLICE_READ
Definition: fuse_common.h:212
#define FUSE_CAP_PARALLEL_DIROPS
Definition: fuse_common.h:333
size_t fuse_buf_size(const struct fuse_bufvec *bufv)
Definition: buffer.c:22
#define FUSE_CAP_WRITEBACK_CACHE
Definition: fuse_common.h:310
#define FUSE_CAP_EXPIRE_ONLY
Definition: fuse_common.h:425
#define FUSE_CAP_ATOMIC_O_TRUNC
Definition: fuse_common.h:172
#define FUSE_CAP_ASYNC_READ
Definition: fuse_common.h:155
#define FUSE_CAP_SPLICE_WRITE
Definition: fuse_common.h:195
#define FUSE_CAP_CACHE_SYMLINKS
Definition: fuse_common.h:374
#define FUSE_CAP_POSIX_ACL
Definition: fuse_common.h:352
@ FUSE_BUF_IS_FD
Definition: fuse_common.h:663
#define FUSE_CAP_EXPORT_SUPPORT
Definition: fuse_common.h:179
#define FUSE_CAP_POSIX_LOCKS
Definition: fuse_common.h:163
#define FUSE_CAP_EXPLICIT_INVAL_DATA
Definition: fuse_common.h:409
#define FUSE_CAP_READDIRPLUS_AUTO
Definition: fuse_common.h:290
ssize_t fuse_buf_copy(struct fuse_bufvec *dst, struct fuse_bufvec *src, enum fuse_buf_copy_flags flags)
Definition: buffer.c:284
#define FUSE_CAP_NO_OPENDIR_SUPPORT
Definition: fuse_common.h:386
#define FUSE_CAP_ASYNC_DIO
Definition: fuse_common.h:301
#define FUSE_CAP_NO_OPEN_SUPPORT
Definition: fuse_common.h:323
#define FUSE_CAP_READDIRPLUS
Definition: fuse_common.h:262
void fuse_pollhandle_destroy(struct fuse_pollhandle *ph)
fuse_buf_copy_flags
Definition: fuse_common.h:687
@ FUSE_BUF_SPLICE_NONBLOCK
Definition: fuse_common.h:723
@ FUSE_BUF_FORCE_SPLICE
Definition: fuse_common.h:705
@ FUSE_BUF_NO_SPLICE
Definition: fuse_common.h:697
@ FUSE_BUF_SPLICE_MOVE
Definition: fuse_common.h:714
#define FUSE_CAP_SPLICE_MOVE
Definition: fuse_common.h:203
#define FUSE_CAP_FLOCK_LOCKS
Definition: fuse_common.h:225
void fuse_log(enum fuse_log_level level, const char *fmt,...)
Definition: fuse_log.c:33
void fuse_session_destroy(struct fuse_session *se)
fuse_expire_flags
int fuse_reply_data(fuse_req_t req, struct fuse_bufvec *bufv, enum fuse_buf_copy_flags flags)
int fuse_reply_lock(fuse_req_t req, const struct flock *lock)
int fuse_reply_open(fuse_req_t req, const struct fuse_file_info *fi)
void fuse_session_exit(struct fuse_session *se)
void(* fuse_interrupt_func_t)(fuse_req_t req, void *data)
int fuse_reply_poll(fuse_req_t req, unsigned revents)
int fuse_reply_err(fuse_req_t req, int err)
int fuse_reply_buf(fuse_req_t req, const char *buf, size_t size)
struct fuse_req * fuse_req_t
Definition: fuse_lowlevel.h:49
size_t fuse_add_direntry_plus(fuse_req_t req, char *buf, size_t bufsize, const char *name, const struct fuse_entry_param *e, off_t off)
int fuse_reply_ioctl_iov(fuse_req_t req, int result, const struct iovec *iov, int count)
int fuse_lowlevel_notify_delete(struct fuse_session *se, fuse_ino_t parent, fuse_ino_t child, const char *name, size_t namelen)
void fuse_session_process_buf(struct fuse_session *se, const struct fuse_buf *buf)
int fuse_session_exited(struct fuse_session *se)
int fuse_session_fd(struct fuse_session *se)
int fuse_req_interrupted(fuse_req_t req)
int fuse_req_getgroups(fuse_req_t req, int size, gid_t list[])
int fuse_lowlevel_notify_retrieve(struct fuse_session *se, fuse_ino_t ino, size_t size, off_t offset, void *cookie)
int fuse_reply_readlink(fuse_req_t req, const char *link)
int fuse_reply_iov(fuse_req_t req, const struct iovec *iov, int count)
int fuse_reply_bmap(fuse_req_t req, uint64_t idx)
int fuse_reply_entry(fuse_req_t req, const struct fuse_entry_param *e)
void fuse_session_unmount(struct fuse_session *se)
void fuse_reply_none(fuse_req_t req)
int fuse_reply_ioctl_retry(fuse_req_t req, const struct iovec *in_iov, size_t in_count, const struct iovec *out_iov, size_t out_count)
void fuse_lowlevel_help(void)
int fuse_lowlevel_notify_inval_inode(struct fuse_session *se, fuse_ino_t ino, off_t off, off_t len)
struct fuse_session * fuse_session_new(struct fuse_args *args, const struct fuse_lowlevel_ops *op, size_t op_size, void *userdata)
int fuse_reply_statfs(fuse_req_t req, const struct statvfs *stbuf)
int fuse_reply_write(fuse_req_t req, size_t count)
int fuse_session_receive_buf(struct fuse_session *se, struct fuse_buf *buf)
int fuse_session_mount(struct fuse_session *se, const char *mountpoint)
void * fuse_req_userdata(fuse_req_t req)
int fuse_lowlevel_notify_expire_entry(struct fuse_session *se, fuse_ino_t parent, const char *name, size_t namelen, enum fuse_expire_flags flags)
int fuse_lowlevel_notify_poll(struct fuse_pollhandle *ph)
int fuse_lowlevel_notify_inval_entry(struct fuse_session *se, fuse_ino_t parent, const char *name, size_t namelen)
void fuse_req_interrupt_func(fuse_req_t req, fuse_interrupt_func_t func, void *data)
void fuse_session_reset(struct fuse_session *se)
int fuse_session_custom_io(struct fuse_session *se, const struct fuse_custom_io *io, int fd)
int fuse_reply_create(fuse_req_t req, const struct fuse_entry_param *e, const struct fuse_file_info *fi)
int fuse_reply_lseek(fuse_req_t req, off_t off)
void fuse_lowlevel_version(void)
uint64_t fuse_ino_t
Definition: fuse_lowlevel.h:46
size_t fuse_add_direntry(fuse_req_t req, char *buf, size_t bufsize, const char *name, const struct stat *stbuf, off_t off)
const struct fuse_ctx * fuse_req_ctx(fuse_req_t req)
int fuse_reply_attr(fuse_req_t req, const struct stat *attr, double attr_timeout)
int fuse_reply_ioctl(fuse_req_t req, int result, const void *buf, size_t size)
int fuse_lowlevel_notify_store(struct fuse_session *se, fuse_ino_t ino, off_t offset, struct fuse_bufvec *bufv, enum fuse_buf_copy_flags flags)
int fuse_reply_xattr(fuse_req_t req, size_t count)
int fuse_opt_add_arg(struct fuse_args *args, const char *arg)
Definition: fuse_opt.c:55
void fuse_opt_free_args(struct fuse_args *args)
Definition: fuse_opt.c:34
int fuse_opt_parse(struct fuse_args *args, void *data, const struct fuse_opt opts[], fuse_opt_proc_t proc)
Definition: fuse_opt.c:398
#define FUSE_OPT_END
Definition: fuse_opt.h:104
int argc
Definition: fuse_opt.h:111
char ** argv
Definition: fuse_opt.h:114
enum fuse_buf_flags flags
Definition: fuse_common.h:741
void * mem
Definition: fuse_common.h:748
size_t size
Definition: fuse_common.h:736
size_t off
Definition: fuse_common.h:787
size_t idx
Definition: fuse_common.h:782
struct fuse_buf buf[1]
Definition: fuse_common.h:792
size_t count
Definition: fuse_common.h:777
Definition: fuse_lowlevel.h:59
double entry_timeout
fuse_ino_t ino
Definition: fuse_lowlevel.h:67
uint64_t generation
Definition: fuse_lowlevel.h:79
double attr_timeout
Definition: fuse_lowlevel.h:94
struct stat attr
Definition: fuse_lowlevel.h:88
unsigned int direct_io
Definition: fuse_common.h:57
unsigned int keep_cache
Definition: fuse_common.h:64
unsigned int nonseekable
Definition: fuse_common.h:73
uint64_t lock_owner
Definition: fuse_common.h:100
uint64_t fh
Definition: fuse_common.h:97
uint32_t poll_events
Definition: fuse_common.h:104
unsigned int noflush
Definition: fuse_common.h:88
unsigned int writepage
Definition: fuse_common.h:54
unsigned int flush
Definition: fuse_common.h:69
unsigned int cache_readdir
Definition: fuse_common.h:84