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