"Fossies" - the Fresh Open Source Software Archive

Member "fuse-3.2.1/lib/fuse_lowlevel.c" (14 Nov 2017, 73249 Bytes) of package /linux/misc/fuse-3.2.1.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "fuse_lowlevel.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 3.1.1_vs_3.2.0.

    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 
  316 void fuse_reply_none(fuse_req_t req)
  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 
  398 int fuse_reply_entry(fuse_req_t req, const struct fuse_entry_param *e)
  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 
  414 int fuse_reply_create(fuse_req_t req, const struct fuse_entry_param *e,
  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,
  691                 FUSE_BUF_FORCE_SPLICE | FUSE_BUF_SPLICE_NONBLOCK);
  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 
  908 int fuse_reply_ioctl_retry(fuse_req_t req,
  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,
 1918                FUSE_CAP_POSIX_LOCKS);
 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 capabilites "
 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 
 2315 void *fuse_req_userdata(fuse_req_t req)
 2316 {
 2317     return req->se->userdata;
 2318 }
 2319 
 2320 const struct fuse_ctx *fuse_req_ctx(fuse_req_t req)
 2321 {
 2322     return &req->ctx;
 2323 }
 2324 
 2325 void fuse_req_interrupt_func(fuse_req_t req, fuse_interrupt_func_t func,
 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 
 2338 int fuse_req_interrupted(fuse_req_t req)
 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 
 2580 void fuse_lowlevel_version(void)
 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 
 2587 void fuse_lowlevel_help(void)
 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 }