"Fossies" - the Fresh Open Source Software Archive

Member "ntfs-3g_ntfsprogs-2017.3.23/libfuse-lite/fuse.c" (23 Mar 2017, 88462 Bytes) of package /linux/misc/ntfs-3g_ntfsprogs-2017.3.23.tgz:


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.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 3g_ntfsprogs-2016.2.22_vs_3g_ntfsprogs-2017.3.23.

    1 /*
    2     FUSE: Filesystem in Userspace
    3     Copyright (C) 2001-2007  Miklos Szeredi <miklos@szeredi.hu>
    4 
    5     This program can be distributed under the terms of the GNU LGPLv2.
    6     See the file COPYING.LIB
    7 */
    8 
    9 #ifdef __SOLARIS__
   10 /* For pthread_rwlock_t */
   11 #define _GNU_SOURCE
   12 #endif /* __SOLARIS__ */
   13 
   14 #include "config.h"
   15 #include "fuse_i.h"
   16 #include "fuse_lowlevel.h"
   17 #include "fuse_opt.h"
   18 #include "fuse_misc.h"
   19 
   20 #include <stdio.h>
   21 #include <string.h>
   22 #include <stdlib.h>
   23 #include <stddef.h>
   24 #include <unistd.h>
   25 #include <time.h>
   26 #include <fcntl.h>
   27 #include <limits.h>
   28 #include <errno.h>
   29 #include <signal.h>
   30 #include <dlfcn.h>
   31 #include <assert.h>
   32 #include <sys/param.h>
   33 #include <sys/uio.h>
   34 #include <sys/time.h>
   35 
   36 #ifdef __SOLARIS__
   37 #define FUSE_MAX_PATH 4096
   38 #endif /* __SOLARIS__ */
   39 
   40 #define FUSE_DEFAULT_INTR_SIGNAL SIGUSR1
   41 
   42 #define FUSE_UNKNOWN_INO 0xffffffff
   43 #define OFFSET_MAX 0x7fffffffffffffffLL
   44 
   45 struct fuse_config {
   46     unsigned int uid;
   47     unsigned int gid;
   48     unsigned int  umask;
   49     double entry_timeout;
   50     double negative_timeout;
   51     double attr_timeout;
   52     double ac_attr_timeout;
   53     int ac_attr_timeout_set;
   54     int debug;
   55     int hard_remove;
   56     int use_ino;
   57     int readdir_ino;
   58     int set_mode;
   59     int set_uid;
   60     int set_gid;
   61     int direct_io;
   62     int kernel_cache;
   63     int intr;
   64     int intr_signal;
   65     int help;
   66 #ifdef __SOLARIS__
   67     int auto_cache;
   68     char *modules;
   69 #endif /* __SOLARIS__ */
   70 };
   71 
   72 struct fuse_fs {
   73     struct fuse_operations op;
   74     void *user_data;
   75 #ifdef __SOLARIS__
   76     struct fuse_module *m;
   77 #endif /* __SOLARIS__ */
   78 };
   79 
   80 #ifdef __SOLARIS__
   81 struct fusemod_so {
   82     void *handle;
   83     int ctr;
   84 };
   85 #endif /* __SOLARIS__ */
   86 
   87 struct fuse {
   88     struct fuse_session *se;
   89     struct node **name_table;
   90     size_t name_table_size;
   91     struct node **id_table;
   92     size_t id_table_size;
   93     fuse_ino_t ctr;
   94     unsigned int generation;
   95     unsigned int hidectr;
   96     pthread_mutex_t lock;
   97     pthread_rwlock_t tree_lock;
   98     struct fuse_config conf;
   99     int intr_installed;
  100     struct fuse_fs *fs;
  101 };
  102 
  103 struct lock {
  104     int type;
  105     off_t start;
  106     off_t end;
  107     pid_t pid;
  108     uint64_t owner;
  109     struct lock *next;
  110 };
  111 
  112 struct node {
  113     struct node *name_next;
  114     struct node *id_next;
  115     fuse_ino_t nodeid;
  116     unsigned int generation;
  117     int refctr;
  118     struct node *parent;
  119     char *name;
  120     uint64_t nlookup;
  121     int open_count;
  122     int is_hidden;
  123 #ifdef __SOLARIS__
  124     struct timespec stat_updated;
  125     struct timespec mtime;
  126     off_t size;
  127     int cache_valid;
  128 #endif /* __SOLARIS__ */
  129     struct lock *locks;
  130 };
  131 
  132 struct fuse_dh {
  133     pthread_mutex_t lock;
  134     struct fuse *fuse;
  135     fuse_req_t req;
  136     char *contents;
  137     int allocated;
  138     unsigned len;
  139     unsigned size;
  140     unsigned needlen;
  141     int filled;
  142     uint64_t fh;
  143     int error;
  144     fuse_ino_t nodeid;
  145 };
  146 
  147 struct fuse_context_i {
  148     struct fuse_context ctx;
  149     fuse_req_t req;
  150 };
  151 
  152 static pthread_key_t fuse_context_key;
  153 static pthread_mutex_t fuse_context_lock = PTHREAD_MUTEX_INITIALIZER;
  154 static int fuse_context_ref;
  155 
  156 #ifdef __SOLARIS__
  157 
  158 static struct fusemod_so *fuse_current_so;
  159 static struct fuse_module *fuse_modules;
  160 
  161 static int fuse_load_so_name(const char *soname)
  162 {
  163     struct fusemod_so *so;
  164 
  165     so = calloc(1, sizeof(struct fusemod_so));
  166     if (!so) {
  167         fprintf(stderr, "fuse: memory allocation failed\n");
  168         return -1;
  169     }
  170 
  171     fuse_current_so = so;
  172     so->handle = dlopen(soname, RTLD_NOW);
  173     fuse_current_so = NULL;
  174     if (!so->handle) {
  175         fprintf(stderr, "fuse: %s\n", dlerror());
  176         goto err;
  177     }
  178     if (!so->ctr) {
  179         fprintf(stderr, "fuse: %s did not register any modules", soname);
  180         goto err;
  181     }
  182     return 0;
  183 
  184  err:
  185     if (so->handle)
  186         dlclose(so->handle);
  187     free(so);
  188     return -1;
  189 }
  190 
  191 static int fuse_load_so_module(const char *module)
  192 {
  193     int res;
  194     char *soname = malloc(strlen(module) + 64);
  195     if (!soname) {
  196         fprintf(stderr, "fuse: memory allocation failed\n");
  197         return -1;
  198     }
  199     sprintf(soname, "libfusemod_%s.so", module);
  200     res = fuse_load_so_name(soname);
  201     free(soname);
  202     return res;
  203 }
  204 
  205 static struct fuse_module *fuse_find_module(const char *module)
  206 {
  207     struct fuse_module *m;
  208     for (m = fuse_modules; m; m = m->next) {
  209         if (strcmp(module, m->name) == 0) {
  210             m->ctr++;
  211             break;
  212         }
  213     }
  214     return m;
  215 }
  216 
  217 static struct fuse_module *fuse_get_module(const char *module)
  218 {
  219     struct fuse_module *m;
  220 
  221     pthread_mutex_lock(&fuse_context_lock);
  222     m = fuse_find_module(module);
  223     if (!m) {
  224         int err = fuse_load_so_module(module);
  225         if (!err)
  226             m = fuse_find_module(module);
  227     }
  228     pthread_mutex_unlock(&fuse_context_lock);
  229     return m;
  230 }
  231 
  232 static void fuse_put_module(struct fuse_module *m)
  233 {
  234     pthread_mutex_lock(&fuse_context_lock);
  235     assert(m->ctr > 0);
  236     m->ctr--;
  237     if (!m->ctr && m->so) {
  238         struct fusemod_so *so = m->so;
  239         assert(so->ctr > 0);
  240         so->ctr--;
  241         if (!so->ctr) {
  242             struct fuse_module **mp;
  243             for (mp = &fuse_modules; *mp;) {
  244                 if ((*mp)->so == so)
  245                     *mp = (*mp)->next;
  246                 else
  247                     mp = &(*mp)->next;
  248             }
  249             dlclose(so->handle);
  250             free(so);
  251         }
  252     }
  253     pthread_mutex_unlock(&fuse_context_lock);
  254 }
  255 #endif /* __SOLARIS__ */
  256 
  257 static struct node *get_node_nocheck(struct fuse *f, fuse_ino_t nodeid)
  258 {
  259     size_t hash = nodeid % f->id_table_size;
  260     struct node *node;
  261 
  262     for (node = f->id_table[hash]; node != NULL; node = node->id_next)
  263         if (node->nodeid == nodeid)
  264             return node;
  265 
  266     return NULL;
  267 }
  268 
  269 static struct node *get_node(struct fuse *f, fuse_ino_t nodeid)
  270 {
  271     struct node *node = get_node_nocheck(f, nodeid);
  272     if (!node) {
  273         fprintf(stderr, "fuse internal error: node %llu not found\n",
  274                 (unsigned long long) nodeid);
  275         abort();
  276     }
  277     return node;
  278 }
  279 
  280 static void free_node(struct node *node)
  281 {
  282     free(node->name);
  283     free(node);
  284 }
  285 
  286 static void unhash_id(struct fuse *f, struct node *node)
  287 {
  288     size_t hash = node->nodeid % f->id_table_size;
  289     struct node **nodep = &f->id_table[hash];
  290 
  291     for (; *nodep != NULL; nodep = &(*nodep)->id_next)
  292         if (*nodep == node) {
  293             *nodep = node->id_next;
  294             return;
  295         }
  296 }
  297 
  298 static void hash_id(struct fuse *f, struct node *node)
  299 {
  300     size_t hash = node->nodeid % f->id_table_size;
  301     node->id_next = f->id_table[hash];
  302     f->id_table[hash] = node;
  303 }
  304 
  305 static unsigned int name_hash(struct fuse *f, fuse_ino_t parent,
  306                               const char *name)
  307 {
  308     unsigned int hash = *name;
  309 
  310     if (hash)
  311         for (name += 1; *name != '\0'; name++)
  312             hash = (hash << 5) - hash + *name;
  313 
  314     return (hash + parent) % f->name_table_size;
  315 }
  316 
  317 static void unref_node(struct fuse *f, struct node *node);
  318 
  319 static void unhash_name(struct fuse *f, struct node *node)
  320 {
  321     if (node->name) {
  322         size_t hash = name_hash(f, node->parent->nodeid, node->name);
  323         struct node **nodep = &f->name_table[hash];
  324 
  325         for (; *nodep != NULL; nodep = &(*nodep)->name_next)
  326             if (*nodep == node) {
  327                 *nodep = node->name_next;
  328                 node->name_next = NULL;
  329                 unref_node(f, node->parent);
  330                 free(node->name);
  331                 node->name = NULL;
  332                 node->parent = NULL;
  333                 return;
  334             }
  335         fprintf(stderr, "fuse internal error: unable to unhash node: %llu\n",
  336                 (unsigned long long) node->nodeid);
  337         abort();
  338     }
  339 }
  340 
  341 static int hash_name(struct fuse *f, struct node *node, fuse_ino_t parentid,
  342                      const char *name)
  343 {
  344     size_t hash = name_hash(f, parentid, name);
  345     struct node *parent = get_node(f, parentid);
  346     node->name = strdup(name);
  347     if (node->name == NULL)
  348         return -1;
  349 
  350     parent->refctr ++;
  351     node->parent = parent;
  352     node->name_next = f->name_table[hash];
  353     f->name_table[hash] = node;
  354     return 0;
  355 }
  356 
  357 static void delete_node(struct fuse *f, struct node *node)
  358 {
  359     if (f->conf.debug)
  360         fprintf(stderr, "delete: %llu\n", (unsigned long long) node->nodeid);
  361 
  362     assert(!node->name);
  363     unhash_id(f, node);
  364     free_node(node);
  365 }
  366 
  367 static void unref_node(struct fuse *f, struct node *node)
  368 {
  369     assert(node->refctr > 0);
  370     node->refctr --;
  371     if (!node->refctr)
  372         delete_node(f, node);
  373 }
  374 
  375 static fuse_ino_t next_id(struct fuse *f)
  376 {
  377     do {
  378         f->ctr = (f->ctr + 1) & 0xffffffff;
  379         if (!f->ctr)
  380             f->generation ++;
  381     } while (f->ctr == 0 || f->ctr == FUSE_UNKNOWN_INO ||
  382              get_node_nocheck(f, f->ctr) != NULL);
  383     return f->ctr;
  384 }
  385 
  386 static struct node *lookup_node(struct fuse *f, fuse_ino_t parent,
  387                                 const char *name)
  388 {
  389     size_t hash = name_hash(f, parent, name);
  390     struct node *node;
  391 
  392     for (node = f->name_table[hash]; node != NULL; node = node->name_next)
  393         if (node->parent->nodeid == parent && strcmp(node->name, name) == 0)
  394             return node;
  395 
  396     return NULL;
  397 }
  398 
  399 static struct node *find_node(struct fuse *f, fuse_ino_t parent,
  400                               const char *name)
  401 {
  402     struct node *node;
  403 
  404     pthread_mutex_lock(&f->lock);
  405     node = lookup_node(f, parent, name);
  406     if (node == NULL) {
  407         node = (struct node *) calloc(1, sizeof(struct node));
  408         if (node == NULL)
  409             goto out_err;
  410 
  411         node->refctr = 1;
  412         node->nodeid = next_id(f);
  413         node->open_count = 0;
  414         node->is_hidden = 0;
  415         node->generation = f->generation;
  416         if (hash_name(f, node, parent, name) == -1) {
  417             free(node);
  418             node = NULL;
  419             goto out_err;
  420         }
  421         hash_id(f, node);
  422     }
  423     node->nlookup ++;
  424  out_err:
  425     pthread_mutex_unlock(&f->lock);
  426     return node;
  427 }
  428 
  429 #ifndef __SOLARIS__
  430 static char *add_name(char **buf, unsigned *bufsize, char *s, const char *name)
  431 #else /* __SOLARIS__ */
  432 static char *add_name(char *buf, char *s, const char *name)
  433 #endif /* __SOLARIS__ */
  434 {
  435     size_t len = strlen(name);
  436 
  437 #ifndef __SOLARIS__
  438     if (s - len <= *buf) {
  439     unsigned pathlen = *bufsize - (s - *buf);
  440     unsigned newbufsize = *bufsize;
  441     char *newbuf;
  442 
  443     while (newbufsize < pathlen + len + 1) {
  444         if (newbufsize >= 0x80000000)
  445             newbufsize = 0xffffffff;
  446         else
  447             newbufsize *= 2;
  448     }
  449 
  450     newbuf = realloc(*buf, newbufsize);
  451     if (newbuf == NULL)
  452         return NULL;
  453 
  454     *buf = newbuf;
  455     s = newbuf + newbufsize - pathlen;
  456     memmove(s, newbuf + *bufsize - pathlen, pathlen);
  457     *bufsize = newbufsize;
  458     }
  459     s -= len;
  460 #else /* ! __SOLARIS__ */
  461     s -= len;
  462     if (s <= buf) {
  463         fprintf(stderr, "fuse: path too long: ...%s\n", s + len);
  464         return NULL;
  465     }
  466 #endif /* __SOLARIS__ */
  467     strncpy(s, name, len);
  468     s--;
  469     *s = '/';
  470 
  471     return s;
  472 }
  473 
  474 static char *get_path_name(struct fuse *f, fuse_ino_t nodeid, const char *name)
  475 {
  476 #ifdef __SOLARIS__
  477     char buf[FUSE_MAX_PATH];
  478     char *s = buf + FUSE_MAX_PATH - 1;
  479     struct node *node;
  480 
  481     *s = '\0';
  482 
  483     if (name != NULL) {
  484         s = add_name(buf, s, name);
  485         if (s == NULL)
  486             return NULL;
  487     }
  488 
  489     pthread_mutex_lock(&f->lock);
  490     for (node = get_node(f, nodeid); node && node->nodeid != FUSE_ROOT_ID;
  491          node = node->parent) {
  492         if (node->name == NULL) {
  493             s = NULL;
  494             break;
  495         }
  496 
  497         s = add_name(buf, s, node->name);
  498         if (s == NULL)
  499             break;
  500     }
  501     pthread_mutex_unlock(&f->lock);
  502 
  503     if (node == NULL || s == NULL)
  504         return NULL;
  505     else if (*s == '\0')
  506         return strdup("/");
  507     else
  508         return strdup(s);
  509 
  510 #else /* __SOLARIS__ */
  511 
  512     unsigned bufsize = 256;
  513     char *buf;
  514     char *s;
  515     struct node *node;
  516 
  517     buf = malloc(bufsize);
  518     if (buf == NULL)
  519             return NULL;
  520 
  521     s = buf + bufsize - 1;
  522     *s = '\0';
  523 
  524     if (name != NULL) {
  525         s = add_name(&buf, &bufsize, s, name);
  526         if (s == NULL)
  527             goto out_free;
  528     }
  529 
  530     pthread_mutex_lock(&f->lock);
  531     for (node = get_node(f, nodeid); node && node->nodeid != FUSE_ROOT_ID;
  532          node = node->parent) {
  533         if (node->name == NULL) {
  534             s = NULL;
  535             break;
  536         }
  537 
  538         s = add_name(&buf, &bufsize, s, node->name);
  539         if (s == NULL)
  540             break;
  541     }
  542     pthread_mutex_unlock(&f->lock);
  543 
  544     if (node == NULL || s == NULL)
  545         goto out_free;
  546     
  547     if (s[0])
  548             memmove(buf, s, bufsize - (s - buf));
  549     else
  550             strcpy(buf, "/");
  551     return buf;
  552     
  553 out_free:
  554     free(buf);
  555     return NULL;
  556 #endif /* __SOLARIS__ */
  557 }
  558 
  559 static char *get_path(struct fuse *f, fuse_ino_t nodeid)
  560 {
  561     return get_path_name(f, nodeid, NULL);
  562 }
  563 
  564 static void forget_node(struct fuse *f, fuse_ino_t nodeid, uint64_t nlookup)
  565 {
  566     struct node *node;
  567     if (nodeid == FUSE_ROOT_ID)
  568         return;
  569     pthread_mutex_lock(&f->lock);
  570     node = get_node(f, nodeid);
  571     assert(node->nlookup >= nlookup);
  572     node->nlookup -= nlookup;
  573     if (!node->nlookup) {
  574         unhash_name(f, node);
  575         unref_node(f, node);
  576     }
  577     pthread_mutex_unlock(&f->lock);
  578 }
  579 
  580 static void remove_node(struct fuse *f, fuse_ino_t dir, const char *name)
  581 {
  582     struct node *node;
  583 
  584     pthread_mutex_lock(&f->lock);
  585     node = lookup_node(f, dir, name);
  586     if (node != NULL)
  587         unhash_name(f, node);
  588     pthread_mutex_unlock(&f->lock);
  589 }
  590 
  591 static int rename_node(struct fuse *f, fuse_ino_t olddir, const char *oldname,
  592                         fuse_ino_t newdir, const char *newname, int hide)
  593 {
  594     struct node *node;
  595     struct node *newnode;
  596     int err = 0;
  597 
  598     pthread_mutex_lock(&f->lock);
  599     node  = lookup_node(f, olddir, oldname);
  600     newnode  = lookup_node(f, newdir, newname);
  601     if (node == NULL)
  602         goto out;
  603 
  604     if (newnode != NULL) {
  605         if (hide) {
  606             fprintf(stderr, "fuse: hidden file got created during hiding\n");
  607             err = -EBUSY;
  608             goto out;
  609         }
  610         unhash_name(f, newnode);
  611     }
  612 
  613     unhash_name(f, node);
  614     if (hash_name(f, node, newdir, newname) == -1) {
  615         err = -ENOMEM;
  616         goto out;
  617     }
  618 
  619     if (hide)
  620         node->is_hidden = 1;
  621 
  622  out:
  623     pthread_mutex_unlock(&f->lock);
  624     return err;
  625 }
  626 
  627 static void set_stat(struct fuse *f, fuse_ino_t nodeid, struct stat *stbuf)
  628 {
  629     if (!f->conf.use_ino)
  630         stbuf->st_ino = nodeid;
  631     if (f->conf.set_mode)
  632         stbuf->st_mode = (stbuf->st_mode & S_IFMT) | (0777 & ~f->conf.umask);
  633     if (f->conf.set_uid)
  634         stbuf->st_uid = f->conf.uid;
  635     if (f->conf.set_gid)
  636         stbuf->st_gid = f->conf.gid;
  637 }
  638 
  639 static struct fuse *req_fuse(fuse_req_t req)
  640 {
  641     return (struct fuse *) fuse_req_userdata(req);
  642 }
  643 
  644 static void fuse_intr_sighandler(int sig)
  645 {
  646     (void) sig;
  647     /* Nothing to do */
  648 }
  649 
  650 struct fuse_intr_data {
  651     pthread_t id;
  652     pthread_cond_t cond;
  653     int finished;
  654 };
  655 
  656 static void fuse_interrupt(fuse_req_t req, void *d_)
  657 {
  658     struct fuse_intr_data *d = d_;
  659     struct fuse *f = req_fuse(req);
  660 
  661     if (d->id == pthread_self())
  662         return;
  663 
  664     pthread_mutex_lock(&f->lock);
  665     while (!d->finished) {
  666         struct timeval now;
  667         struct timespec timeout;
  668 
  669         pthread_kill(d->id, f->conf.intr_signal);
  670         gettimeofday(&now, NULL);
  671         timeout.tv_sec = now.tv_sec + 1;
  672         timeout.tv_nsec = now.tv_usec * 1000;
  673         pthread_cond_timedwait(&d->cond, &f->lock, &timeout);
  674     }
  675     pthread_mutex_unlock(&f->lock);
  676 }
  677 
  678 static void fuse_do_finish_interrupt(struct fuse *f, fuse_req_t req,
  679                                      struct fuse_intr_data *d)
  680 {
  681     pthread_mutex_lock(&f->lock);
  682     d->finished = 1;
  683     pthread_cond_broadcast(&d->cond);
  684     pthread_mutex_unlock(&f->lock);
  685     fuse_req_interrupt_func(req, NULL, NULL);
  686     pthread_cond_destroy(&d->cond);
  687 }
  688 
  689 static void fuse_do_prepare_interrupt(fuse_req_t req, struct fuse_intr_data *d)
  690 {
  691     d->id = pthread_self();
  692     pthread_cond_init(&d->cond, NULL);
  693     d->finished = 0;
  694     fuse_req_interrupt_func(req, fuse_interrupt, d);
  695 }
  696 
  697 static void fuse_finish_interrupt(struct fuse *f, fuse_req_t req,
  698                                          struct fuse_intr_data *d)
  699 {
  700     if (f->conf.intr)
  701         fuse_do_finish_interrupt(f, req, d);
  702 }
  703 
  704 static void fuse_prepare_interrupt(struct fuse *f, fuse_req_t req,
  705                                           struct fuse_intr_data *d)
  706 {
  707     if (f->conf.intr)
  708         fuse_do_prepare_interrupt(req, d);
  709 }
  710 
  711 int fuse_fs_getattr(struct fuse_fs *fs, const char *path, struct stat *buf)
  712 {
  713     fuse_get_context()->private_data = fs->user_data;
  714     if (fs->op.getattr)
  715         return fs->op.getattr(path, buf);
  716     else
  717         return -ENOSYS;
  718 }
  719 
  720 int fuse_fs_fgetattr(struct fuse_fs *fs, const char *path, struct stat *buf,
  721                      struct fuse_file_info *fi)
  722 {
  723     fuse_get_context()->private_data = fs->user_data;
  724     if (fs->op.fgetattr)
  725         return fs->op.fgetattr(path, buf, fi);
  726     else if (fs->op.getattr)
  727         return fs->op.getattr(path, buf);
  728     else
  729         return -ENOSYS;
  730 }
  731 
  732 int fuse_fs_rename(struct fuse_fs *fs, const char *oldpath,
  733                    const char *newpath)
  734 {
  735     fuse_get_context()->private_data = fs->user_data;
  736     if (fs->op.rename)
  737         return fs->op.rename(oldpath, newpath);
  738     else
  739         return -ENOSYS;
  740 }
  741 
  742 int fuse_fs_unlink(struct fuse_fs *fs, const char *path)
  743 {
  744     fuse_get_context()->private_data = fs->user_data;
  745     if (fs->op.unlink)
  746         return fs->op.unlink(path);
  747     else
  748         return -ENOSYS;
  749 }
  750 
  751 int fuse_fs_rmdir(struct fuse_fs *fs, const char *path)
  752 {
  753     fuse_get_context()->private_data = fs->user_data;
  754     if (fs->op.rmdir)
  755         return fs->op.rmdir(path);
  756     else
  757         return -ENOSYS;
  758 }
  759 
  760 int fuse_fs_symlink(struct fuse_fs *fs, const char *linkname, const char *path)
  761 {
  762     fuse_get_context()->private_data = fs->user_data;
  763     if (fs->op.symlink)
  764         return fs->op.symlink(linkname, path);
  765     else
  766         return -ENOSYS;
  767 }
  768 
  769 int fuse_fs_link(struct fuse_fs *fs, const char *oldpath, const char *newpath)
  770 {
  771     fuse_get_context()->private_data = fs->user_data;
  772     if (fs->op.link)
  773         return fs->op.link(oldpath, newpath);
  774     else
  775         return -ENOSYS;
  776 }
  777 
  778 int fuse_fs_release(struct fuse_fs *fs,  const char *path,
  779                     struct fuse_file_info *fi)
  780 {
  781     fuse_get_context()->private_data = fs->user_data;
  782     if (fs->op.release)
  783         return fs->op.release(path, fi);
  784     else
  785         return 0;
  786 }
  787 
  788 int fuse_fs_opendir(struct fuse_fs *fs, const char *path,
  789                     struct fuse_file_info *fi)
  790 {
  791     fuse_get_context()->private_data = fs->user_data;
  792     if (fs->op.opendir)
  793         return fs->op.opendir(path, fi);
  794     else
  795         return 0;
  796 }
  797 
  798 int fuse_fs_open(struct fuse_fs *fs, const char *path,
  799                  struct fuse_file_info *fi)
  800 {
  801     fuse_get_context()->private_data = fs->user_data;
  802     if (fs->op.open)
  803         return fs->op.open(path, fi);
  804     else
  805         return 0;
  806 }
  807 
  808 int fuse_fs_read(struct fuse_fs *fs, const char *path, char *buf, size_t size,
  809                  off_t off, struct fuse_file_info *fi)
  810 {
  811     fuse_get_context()->private_data = fs->user_data;
  812     if (fs->op.read)
  813         return fs->op.read(path, buf, size, off, fi);
  814     else
  815         return -ENOSYS;
  816 }
  817 
  818 int fuse_fs_write(struct fuse_fs *fs, const char *path, const char *buf,
  819                   size_t size, off_t off, struct fuse_file_info *fi)
  820 {
  821     fuse_get_context()->private_data = fs->user_data;
  822     if (fs->op.write)
  823         return fs->op.write(path, buf, size, off, fi);
  824     else
  825         return -ENOSYS;
  826 }
  827 
  828 int fuse_fs_fsync(struct fuse_fs *fs, const char *path, int datasync,
  829                   struct fuse_file_info *fi)
  830 {
  831     fuse_get_context()->private_data = fs->user_data;
  832     if (fs->op.fsync)
  833         return fs->op.fsync(path, datasync, fi);
  834     else
  835         return -ENOSYS;
  836 }
  837 
  838 int fuse_fs_fsyncdir(struct fuse_fs *fs, const char *path, int datasync,
  839                      struct fuse_file_info *fi)
  840 {
  841     fuse_get_context()->private_data = fs->user_data;
  842     if (fs->op.fsyncdir)
  843         return fs->op.fsyncdir(path, datasync, fi);
  844     else
  845         return -ENOSYS;
  846 }
  847 
  848 int fuse_fs_flush(struct fuse_fs *fs, const char *path,
  849                   struct fuse_file_info *fi)
  850 {
  851     fuse_get_context()->private_data = fs->user_data;
  852     if (fs->op.flush)
  853         return fs->op.flush(path, fi);
  854     else
  855         return -ENOSYS;
  856 }
  857 
  858 int fuse_fs_statfs(struct fuse_fs *fs, const char *path, struct statvfs *buf)
  859 {
  860     fuse_get_context()->private_data = fs->user_data;
  861     if (fs->op.statfs)
  862         return fs->op.statfs(path, buf);
  863     else {
  864         buf->f_namemax = 255;
  865         buf->f_bsize = 512;
  866         return 0;
  867     }
  868 }
  869 
  870 int fuse_fs_releasedir(struct fuse_fs *fs, const char *path,
  871                        struct fuse_file_info *fi)
  872 {
  873     fuse_get_context()->private_data = fs->user_data;
  874     if (fs->op.releasedir)
  875         return fs->op.releasedir(path, fi);
  876     else
  877         return 0;
  878 }
  879 
  880 int fuse_fs_readdir(struct fuse_fs *fs, const char *path, void *buf,
  881                     fuse_fill_dir_t filler, off_t off,
  882                     struct fuse_file_info *fi)
  883 {
  884     fuse_get_context()->private_data = fs->user_data;
  885     if (fs->op.readdir)
  886         return fs->op.readdir(path, buf, filler, off, fi);
  887     else
  888         return -ENOSYS;
  889 }
  890 
  891 int fuse_fs_create(struct fuse_fs *fs, const char *path, mode_t mode,
  892                    struct fuse_file_info *fi)
  893 {
  894     fuse_get_context()->private_data = fs->user_data;
  895     if (fs->op.create)
  896         return fs->op.create(path, mode, fi);
  897     else
  898         return -ENOSYS;
  899 }
  900 
  901 int fuse_fs_lock(struct fuse_fs *fs, const char *path,
  902                  struct fuse_file_info *fi, int cmd, struct flock *lock)
  903 {
  904     fuse_get_context()->private_data = fs->user_data;
  905     if (fs->op.lock)
  906         return fs->op.lock(path, fi, cmd, lock);
  907     else
  908         return -ENOSYS;
  909 }
  910 
  911 int fuse_fs_chown(struct fuse_fs *fs, const char *path, uid_t uid, gid_t gid)
  912 {
  913     fuse_get_context()->private_data = fs->user_data;
  914     if (fs->op.chown)
  915         return fs->op.chown(path, uid, gid);
  916     else
  917         return -ENOSYS;
  918 }
  919 
  920 int fuse_fs_truncate(struct fuse_fs *fs, const char *path, off_t size)
  921 {
  922     fuse_get_context()->private_data = fs->user_data;
  923     if (fs->op.truncate)
  924         return fs->op.truncate(path, size);
  925     else
  926         return -ENOSYS;
  927 }
  928 
  929 int fuse_fs_ftruncate(struct fuse_fs *fs, const char *path, off_t size,
  930                       struct fuse_file_info *fi)
  931 {
  932     fuse_get_context()->private_data = fs->user_data;
  933     if (fs->op.ftruncate)
  934         return fs->op.ftruncate(path, size, fi);
  935     else if (fs->op.truncate)
  936         return fs->op.truncate(path, size);
  937     else
  938         return -ENOSYS;
  939 }
  940 
  941 int fuse_fs_utimens(struct fuse_fs *fs, const char *path,
  942                     const struct timespec tv[2])
  943 {
  944     fuse_get_context()->private_data = fs->user_data;
  945     if (fs->op.utimens)
  946         return fs->op.utimens(path, tv);
  947     else if(fs->op.utime) {
  948         struct utimbuf buf;
  949         buf.actime = tv[0].tv_sec;
  950         buf.modtime = tv[1].tv_sec;
  951         return fs->op.utime(path, &buf);
  952     } else
  953         return -ENOSYS;
  954 }
  955 
  956 int fuse_fs_access(struct fuse_fs *fs, const char *path, int mask)
  957 {
  958     fuse_get_context()->private_data = fs->user_data;
  959     if (fs->op.access)
  960         return fs->op.access(path, mask);
  961     else
  962         return -ENOSYS;
  963 }
  964 
  965 int fuse_fs_readlink(struct fuse_fs *fs, const char *path, char *buf,
  966                      size_t len)
  967 {
  968     fuse_get_context()->private_data = fs->user_data;
  969     if (fs->op.readlink)
  970         return fs->op.readlink(path, buf, len);
  971     else
  972         return -ENOSYS;
  973 }
  974 
  975 int fuse_fs_mknod(struct fuse_fs *fs, const char *path, mode_t mode,
  976                   dev_t rdev)
  977 {
  978     fuse_get_context()->private_data = fs->user_data;
  979     if (fs->op.mknod)
  980         return fs->op.mknod(path, mode, rdev);
  981     else
  982         return -ENOSYS;
  983 }
  984 
  985 int fuse_fs_mkdir(struct fuse_fs *fs, const char *path, mode_t mode)
  986 {
  987     fuse_get_context()->private_data = fs->user_data;
  988     if (fs->op.mkdir)
  989         return fs->op.mkdir(path, mode);
  990     else
  991         return -ENOSYS;
  992 }
  993 
  994 int fuse_fs_setxattr(struct fuse_fs *fs, const char *path, const char *name,
  995                      const char *value, size_t size, int flags)
  996 {
  997     fuse_get_context()->private_data = fs->user_data;
  998     if (fs->op.setxattr)
  999         return fs->op.setxattr(path, name, value, size, flags);
 1000     else
 1001         return -ENOSYS;
 1002 }
 1003 
 1004 int fuse_fs_getxattr(struct fuse_fs *fs, const char *path, const char *name,
 1005                      char *value, size_t size)
 1006 {
 1007     fuse_get_context()->private_data = fs->user_data;
 1008     if (fs->op.getxattr)
 1009         return fs->op.getxattr(path, name, value, size);
 1010     else
 1011         return -ENOSYS;
 1012 }
 1013 
 1014 int fuse_fs_listxattr(struct fuse_fs *fs, const char *path, char *list,
 1015                       size_t size)
 1016 {
 1017     fuse_get_context()->private_data = fs->user_data;
 1018     if (fs->op.listxattr)
 1019         return fs->op.listxattr(path, list, size);
 1020     else
 1021         return -ENOSYS;
 1022 }
 1023 
 1024 int fuse_fs_bmap(struct fuse_fs *fs, const char *path, size_t blocksize,
 1025                  uint64_t *idx)
 1026 {
 1027     fuse_get_context()->private_data = fs->user_data;
 1028     if (fs->op.bmap)
 1029         return fs->op.bmap(path, blocksize, idx);
 1030     else
 1031         return -ENOSYS;
 1032 }
 1033 
 1034 int fuse_fs_removexattr(struct fuse_fs *fs, const char *path, const char *name)
 1035 {
 1036     fuse_get_context()->private_data = fs->user_data;
 1037     if (fs->op.removexattr)
 1038         return fs->op.removexattr(path, name);
 1039     else
 1040         return -ENOSYS;
 1041 }
 1042 
 1043 int fuse_fs_ioctl(struct fuse_fs *fs, const char *path, int cmd, void *arg,
 1044           struct fuse_file_info *fi, unsigned int flags, void *data)
 1045 {
 1046     fuse_get_context()->private_data = fs->user_data;
 1047     if (fs->op.ioctl) {
 1048 /*
 1049     if (fs->debug)
 1050         fprintf(stderr, "ioctl[%llu] 0x%x flags: 0x%x\n",
 1051             (unsigned long long) fi->fh, cmd, flags);
 1052 */
 1053     return fs->op.ioctl(path, cmd, arg, fi, flags, data);
 1054     } else
 1055     return -ENOSYS;
 1056 }
 1057 
 1058 static int is_open(struct fuse *f, fuse_ino_t dir, const char *name)
 1059 {
 1060     struct node *node;
 1061     int isopen = 0;
 1062     pthread_mutex_lock(&f->lock);
 1063     node = lookup_node(f, dir, name);
 1064     if (node && node->open_count > 0)
 1065         isopen = 1;
 1066     pthread_mutex_unlock(&f->lock);
 1067     return isopen;
 1068 }
 1069 
 1070 static char *hidden_name(struct fuse *f, fuse_ino_t dir, const char *oldname,
 1071                          char *newname, size_t bufsize)
 1072 {
 1073     struct stat buf;
 1074     struct node *node;
 1075     struct node *newnode;
 1076     char *newpath;
 1077     int res;
 1078     int failctr = 10;
 1079 
 1080     do {
 1081         pthread_mutex_lock(&f->lock);
 1082         node = lookup_node(f, dir, oldname);
 1083         if (node == NULL) {
 1084             pthread_mutex_unlock(&f->lock);
 1085             return NULL;
 1086         }
 1087         do {
 1088             f->hidectr ++;
 1089             snprintf(newname, bufsize, ".fuse_hidden%08x%08x",
 1090                      (unsigned int) node->nodeid, f->hidectr);
 1091             newnode = lookup_node(f, dir, newname);
 1092         } while(newnode);
 1093         pthread_mutex_unlock(&f->lock);
 1094 
 1095         newpath = get_path_name(f, dir, newname);
 1096         if (!newpath)
 1097             break;
 1098 
 1099         res = fuse_fs_getattr(f->fs, newpath, &buf);
 1100         if (res == -ENOENT)
 1101             break;
 1102         free(newpath);
 1103         newpath = NULL;
 1104     } while(res == 0 && --failctr);
 1105 
 1106     return newpath;
 1107 }
 1108 
 1109 static int hide_node(struct fuse *f, const char *oldpath,
 1110                      fuse_ino_t dir, const char *oldname)
 1111 {
 1112     char newname[64];
 1113     char *newpath;
 1114     int err = -EBUSY;
 1115 
 1116     newpath = hidden_name(f, dir, oldname, newname, sizeof(newname));
 1117     if (newpath) {
 1118         err = fuse_fs_rename(f->fs, oldpath, newpath);
 1119         if (!err)
 1120             err = rename_node(f, dir, oldname, dir, newname, 1);
 1121         free(newpath);
 1122     }
 1123     return err;
 1124 }
 1125 
 1126 #ifdef __SOLARIS__
 1127 
 1128 static int mtime_eq(const struct stat *stbuf, const struct timespec *ts)
 1129 {
 1130     return stbuf->st_mtime == ts->tv_sec && ST_MTIM_NSEC(stbuf) == ts->tv_nsec;
 1131 }
 1132 
 1133 #ifndef CLOCK_MONOTONIC
 1134 #define CLOCK_MONOTONIC CLOCK_REALTIME
 1135 #endif
 1136 
 1137 static void curr_time(struct timespec *now)
 1138 {
 1139     static clockid_t clockid = CLOCK_MONOTONIC;
 1140     int res = clock_gettime(clockid, now);
 1141     if (res == -1 && errno == EINVAL) {
 1142         clockid = CLOCK_REALTIME;
 1143         res = clock_gettime(clockid, now);
 1144     }
 1145     if (res == -1) {
 1146         perror("fuse: clock_gettime");
 1147         abort();
 1148     }
 1149 }
 1150 
 1151 static void update_stat(struct node *node, const struct stat *stbuf)
 1152 {
 1153     if (node->cache_valid && (!mtime_eq(stbuf, &node->mtime) ||
 1154                               stbuf->st_size != node->size))
 1155         node->cache_valid = 0;
 1156     node->mtime.tv_sec = stbuf->st_mtime;
 1157     node->mtime.tv_nsec = ST_MTIM_NSEC(stbuf);
 1158     node->size = stbuf->st_size;
 1159     curr_time(&node->stat_updated);
 1160 }
 1161 
 1162 #endif /* __SOLARIS__ */
 1163 
 1164 static int lookup_path(struct fuse *f, fuse_ino_t nodeid,
 1165                        const char *name, const char *path,
 1166                        struct fuse_entry_param *e, struct fuse_file_info *fi)
 1167 {
 1168     int res;
 1169 
 1170     memset(e, 0, sizeof(struct fuse_entry_param));
 1171     if (fi)
 1172         res = fuse_fs_fgetattr(f->fs, path, &e->attr, fi);
 1173     else
 1174         res = fuse_fs_getattr(f->fs, path, &e->attr);
 1175     if (res == 0) {
 1176         struct node *node;
 1177 
 1178         node = find_node(f, nodeid, name);
 1179         if (node == NULL)
 1180             res = -ENOMEM;
 1181         else {
 1182             e->ino = node->nodeid;
 1183             e->generation = node->generation;
 1184             e->entry_timeout = f->conf.entry_timeout;
 1185             e->attr_timeout = f->conf.attr_timeout;
 1186 #ifdef __SOLARIS__
 1187             if (f->conf.auto_cache) {
 1188                 pthread_mutex_lock(&f->lock);
 1189                 update_stat(node, &e->attr);
 1190                 pthread_mutex_unlock(&f->lock);
 1191             }
 1192 #endif /* __SOLARIS__ */
 1193             set_stat(f, e->ino, &e->attr);
 1194             if (f->conf.debug)
 1195                 fprintf(stderr, "   NODEID: %lu\n", (unsigned long) e->ino);
 1196         }
 1197     }
 1198     return res;
 1199 }
 1200 
 1201 static struct fuse_context_i *fuse_get_context_internal(void)
 1202 {
 1203     struct fuse_context_i *c;
 1204 
 1205     c = (struct fuse_context_i *) pthread_getspecific(fuse_context_key);
 1206     if (c == NULL) {
 1207         c = (struct fuse_context_i *) malloc(sizeof(struct fuse_context_i));
 1208         if (c == NULL) {
 1209             /* This is hard to deal with properly, so just abort.  If
 1210                memory is so low that the context cannot be allocated,
 1211                there's not much hope for the filesystem anyway */ 
 1212             fprintf(stderr, "fuse: failed to allocate thread specific data\n");
 1213             abort();
 1214         }
 1215         pthread_setspecific(fuse_context_key, c);
 1216     }
 1217     return c;
 1218 }
 1219 
 1220 static void fuse_freecontext(void *data)
 1221 {
 1222     free(data);
 1223 }
 1224 
 1225 static int fuse_create_context_key(void)
 1226 {
 1227     int err = 0;
 1228     pthread_mutex_lock(&fuse_context_lock);
 1229     if (!fuse_context_ref) {
 1230         err = pthread_key_create(&fuse_context_key, fuse_freecontext);
 1231         if (err) {
 1232             fprintf(stderr, "fuse: failed to create thread specific key: %s\n",
 1233                     strerror(err));
 1234             pthread_mutex_unlock(&fuse_context_lock);
 1235             return -1;
 1236         }
 1237     }
 1238     fuse_context_ref++;
 1239     pthread_mutex_unlock(&fuse_context_lock);
 1240     return 0;
 1241 }
 1242 
 1243 static void fuse_delete_context_key(void)
 1244 {
 1245     pthread_mutex_lock(&fuse_context_lock);
 1246     fuse_context_ref--;
 1247     if (!fuse_context_ref) {
 1248         free(pthread_getspecific(fuse_context_key));
 1249         pthread_key_delete(fuse_context_key);
 1250     }
 1251     pthread_mutex_unlock(&fuse_context_lock);
 1252 }
 1253 
 1254 static struct fuse *req_fuse_prepare(fuse_req_t req)
 1255 {
 1256     struct fuse_context_i *c = fuse_get_context_internal();
 1257     const struct fuse_ctx *ctx = fuse_req_ctx(req);
 1258     c->req = req;
 1259     c->ctx.fuse = req_fuse(req);
 1260     c->ctx.uid = ctx->uid;
 1261     c->ctx.gid = ctx->gid;
 1262     c->ctx.pid = ctx->pid;
 1263 #ifdef POSIXACLS
 1264     c->ctx.umask = ctx->umask;
 1265 #endif
 1266     return c->ctx.fuse;
 1267 }
 1268 
 1269 #ifndef __SOLARIS__
 1270 static void reply_err(fuse_req_t req, int err)
 1271 #else /* __SOLARIS__ */
 1272 static inline void reply_err(fuse_req_t req, int err)
 1273 #endif /* __SOLARIS__ */
 1274 {
 1275     /* fuse_reply_err() uses non-negated errno values */
 1276     fuse_reply_err(req, -err);
 1277 }
 1278 
 1279 static void reply_entry(fuse_req_t req, const struct fuse_entry_param *e,
 1280                         int err)
 1281 {
 1282     if (!err) {
 1283         struct fuse *f = req_fuse(req);
 1284 #ifdef __SOLARIS__
 1285                      /* Skip forget for negative result */
 1286         if ((fuse_reply_entry(req, e) == -ENOENT)
 1287           && (e->ino != 0))
 1288             forget_node(f, e->ino, 1);
 1289 #else /* __SOLARIS__ */
 1290         if (fuse_reply_entry(req, e) == -ENOENT)
 1291             forget_node(f, e->ino, 1);
 1292 #endif
 1293     } else
 1294         reply_err(req, err);
 1295 }
 1296 
 1297 void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn)
 1298 {
 1299     fuse_get_context()->private_data = fs->user_data;
 1300     if (fs->op.init)
 1301         fs->user_data = fs->op.init(conn);
 1302 }
 1303 
 1304 static void fuse_lib_init(void *data, struct fuse_conn_info *conn)
 1305 {
 1306     struct fuse *f = (struct fuse *) data;
 1307     struct fuse_context_i *c = fuse_get_context_internal();
 1308 
 1309     memset(c, 0, sizeof(*c));
 1310     c->ctx.fuse = f;
 1311     fuse_fs_init(f->fs, conn);
 1312 }
 1313 
 1314 void fuse_fs_destroy(struct fuse_fs *fs)
 1315 {
 1316     fuse_get_context()->private_data = fs->user_data;
 1317     if (fs->op.destroy)
 1318         fs->op.destroy(fs->user_data);
 1319 #ifdef __SOLARIS__
 1320     if (fs->m)
 1321         fuse_put_module(fs->m);
 1322 #endif /* __SOLARIS__ */
 1323     free(fs);
 1324 }
 1325 
 1326 static void fuse_lib_destroy(void *data)
 1327 {
 1328     struct fuse *f = (struct fuse *) data;
 1329     struct fuse_context_i *c = fuse_get_context_internal();
 1330 
 1331     memset(c, 0, sizeof(*c));
 1332     c->ctx.fuse = f;
 1333     fuse_fs_destroy(f->fs);
 1334     f->fs = NULL;
 1335 }
 1336 
 1337 static void fuse_lib_lookup(fuse_req_t req, fuse_ino_t parent,
 1338                             const char *name)
 1339 {
 1340     struct fuse *f = req_fuse_prepare(req);
 1341     struct fuse_entry_param e;
 1342     char *path;
 1343     int err;
 1344 
 1345     err = -ENOENT;
 1346     pthread_rwlock_rdlock(&f->tree_lock);
 1347     path = get_path_name(f, parent, name);
 1348     if (path != NULL) {
 1349         struct fuse_intr_data d;
 1350         if (f->conf.debug)
 1351             fprintf(stderr, "LOOKUP %s\n", path);
 1352         fuse_prepare_interrupt(f, req, &d); 
 1353         err = lookup_path(f, parent, name, path, &e, NULL);
 1354         if (err == -ENOENT && f->conf.negative_timeout != 0.0) {
 1355             e.ino = 0;
 1356             e.entry_timeout = f->conf.negative_timeout;
 1357             err = 0;
 1358         }
 1359         fuse_finish_interrupt(f, req, &d);
 1360         free(path);
 1361     }
 1362     pthread_rwlock_unlock(&f->tree_lock);
 1363     reply_entry(req, &e, err);
 1364 }
 1365 
 1366 static void fuse_lib_forget(fuse_req_t req, fuse_ino_t ino,
 1367                             unsigned long nlookup)
 1368 {
 1369     struct fuse *f = req_fuse(req);
 1370     if (f->conf.debug)
 1371         fprintf(stderr, "FORGET %llu/%lu\n", (unsigned long long)ino, nlookup);
 1372     forget_node(f, ino, nlookup);
 1373     fuse_reply_none(req);
 1374 }
 1375 
 1376 static void fuse_lib_getattr(fuse_req_t req, fuse_ino_t ino,
 1377                              struct fuse_file_info *fi)
 1378 {
 1379     struct fuse *f = req_fuse_prepare(req);
 1380     struct stat buf;
 1381     char *path;
 1382     int err;
 1383 
 1384     (void) fi;
 1385     memset(&buf, 0, sizeof(buf));
 1386 
 1387     err = -ENOENT;
 1388     pthread_rwlock_rdlock(&f->tree_lock);
 1389     path = get_path(f, ino);
 1390     if (path != NULL) {
 1391         struct fuse_intr_data d;
 1392         fuse_prepare_interrupt(f, req, &d);
 1393         err = fuse_fs_getattr(f->fs, path, &buf);
 1394         fuse_finish_interrupt(f, req, &d);
 1395         free(path);
 1396     }
 1397     pthread_rwlock_unlock(&f->tree_lock);
 1398     if (!err) {
 1399 #ifdef __SOLARIS__
 1400         if (f->conf.auto_cache) {
 1401             pthread_mutex_lock(&f->lock);
 1402             update_stat(get_node(f, ino), &buf);
 1403             pthread_mutex_unlock(&f->lock);
 1404         }
 1405 #endif /* __SOLARIS__ */
 1406         set_stat(f, ino, &buf);
 1407         fuse_reply_attr(req, &buf, f->conf.attr_timeout);
 1408     } else
 1409         reply_err(req, err);
 1410 }
 1411 
 1412 int fuse_fs_chmod(struct fuse_fs *fs, const char *path, mode_t mode)
 1413 {
 1414     fuse_get_context()->private_data = fs->user_data;
 1415     if (fs->op.chmod)
 1416         return fs->op.chmod(path, mode);
 1417     else
 1418         return -ENOSYS;
 1419 }
 1420 
 1421 static void fuse_lib_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
 1422                              int valid, struct fuse_file_info *fi)
 1423 {
 1424     struct fuse *f = req_fuse_prepare(req);
 1425     struct stat buf;
 1426     char *path;
 1427     int err;
 1428 
 1429     err = -ENOENT;
 1430     pthread_rwlock_rdlock(&f->tree_lock);
 1431     path = get_path(f, ino);
 1432     if (path != NULL) {
 1433         struct fuse_intr_data d;
 1434         fuse_prepare_interrupt(f, req, &d);
 1435         err = 0;
 1436         if (!err && (valid & FUSE_SET_ATTR_MODE))
 1437             err = fuse_fs_chmod(f->fs, path, attr->st_mode);
 1438         if (!err && (valid & (FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID))) {
 1439             uid_t uid = 
 1440                 (valid & FUSE_SET_ATTR_UID) ? attr->st_uid : (uid_t) -1;
 1441             gid_t gid = 
 1442                 (valid & FUSE_SET_ATTR_GID) ? attr->st_gid : (gid_t) -1;
 1443             err = fuse_fs_chown(f->fs, path, uid, gid);
 1444         }
 1445         if (!err && (valid & FUSE_SET_ATTR_SIZE)) {
 1446             if (fi)
 1447                 err = fuse_fs_ftruncate(f->fs, path, attr->st_size, fi);
 1448             else
 1449                 err = fuse_fs_truncate(f->fs, path, attr->st_size);
 1450         }
 1451 #ifdef HAVE_UTIMENSAT
 1452         if (!err &&
 1453             (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME))) {
 1454             struct timespec tv[2];
 1455 
 1456             tv[0].tv_sec = 0;
 1457             tv[1].tv_sec = 0;
 1458             tv[0].tv_nsec = UTIME_OMIT;
 1459             tv[1].tv_nsec = UTIME_OMIT;
 1460 
 1461             if (valid & FUSE_SET_ATTR_ATIME_NOW)
 1462                 tv[0].tv_nsec = UTIME_NOW;
 1463             else if (valid & FUSE_SET_ATTR_ATIME)
 1464                 tv[0] = attr->st_atim;
 1465 
 1466             if (valid & FUSE_SET_ATTR_MTIME_NOW)
 1467                 tv[1].tv_nsec = UTIME_NOW;
 1468             else if (valid & FUSE_SET_ATTR_MTIME)
 1469                 tv[1] = attr->st_mtim;
 1470 
 1471             err = fuse_fs_utimens(f->fs, path, tv);
 1472         } else
 1473 #endif
 1474         if (!err && (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) ==
 1475             (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) {
 1476             struct timespec tv[2];
 1477             tv[0].tv_sec = attr->st_atime;
 1478             tv[0].tv_nsec = ST_ATIM_NSEC(attr);
 1479             tv[1].tv_sec = attr->st_mtime;
 1480             tv[1].tv_nsec = ST_MTIM_NSEC(attr);
 1481             err = fuse_fs_utimens(f->fs, path, tv);
 1482         }
 1483         if (!err)
 1484             err = fuse_fs_getattr(f->fs,  path, &buf);
 1485         fuse_finish_interrupt(f, req, &d);
 1486         free(path);
 1487     }
 1488     pthread_rwlock_unlock(&f->tree_lock);
 1489     if (!err) {
 1490 #ifdef __SOLARIS__
 1491         if (f->conf.auto_cache) {
 1492             pthread_mutex_lock(&f->lock);
 1493             update_stat(get_node(f, ino), &buf);
 1494             pthread_mutex_unlock(&f->lock);
 1495         }
 1496 #endif /* __SOLARIS__ */
 1497         set_stat(f, ino, &buf);
 1498         fuse_reply_attr(req, &buf, f->conf.attr_timeout);
 1499     } else
 1500         reply_err(req, err);
 1501 }
 1502 
 1503 static void fuse_lib_access(fuse_req_t req, fuse_ino_t ino, int mask)
 1504 {
 1505     struct fuse *f = req_fuse_prepare(req);
 1506     char *path;
 1507     int err;
 1508 
 1509     err = -ENOENT;
 1510     pthread_rwlock_rdlock(&f->tree_lock);
 1511     path = get_path(f, ino);
 1512     if (path != NULL) {
 1513         struct fuse_intr_data d;
 1514         if (f->conf.debug)
 1515             fprintf(stderr, "ACCESS %s 0%o\n", path, mask);
 1516         fuse_prepare_interrupt(f, req, &d);
 1517         err = fuse_fs_access(f->fs, path, mask);
 1518         fuse_finish_interrupt(f, req, &d);
 1519         free(path);
 1520     }
 1521     pthread_rwlock_unlock(&f->tree_lock);
 1522     reply_err(req, err);
 1523 }
 1524 
 1525 static void fuse_lib_readlink(fuse_req_t req, fuse_ino_t ino)
 1526 {
 1527     struct fuse *f = req_fuse_prepare(req);
 1528     char linkname[PATH_MAX + 1];
 1529     char *path;
 1530     int err;
 1531 
 1532     err = -ENOENT;
 1533     pthread_rwlock_rdlock(&f->tree_lock);
 1534     path = get_path(f, ino);
 1535     if (path != NULL) {
 1536         struct fuse_intr_data d;
 1537         fuse_prepare_interrupt(f, req, &d);
 1538         err = fuse_fs_readlink(f->fs, path, linkname, sizeof(linkname));
 1539         fuse_finish_interrupt(f, req, &d);
 1540         free(path);
 1541     }
 1542     pthread_rwlock_unlock(&f->tree_lock);
 1543     if (!err) {
 1544         linkname[PATH_MAX] = '\0';
 1545         fuse_reply_readlink(req, linkname);
 1546     } else
 1547         reply_err(req, err);
 1548 }
 1549 
 1550 static void fuse_lib_mknod(fuse_req_t req, fuse_ino_t parent, const char *name,
 1551                            mode_t mode, dev_t rdev)
 1552 {
 1553     struct fuse *f = req_fuse_prepare(req);
 1554     struct fuse_entry_param e;
 1555     char *path;
 1556     int err;
 1557 
 1558     err = -ENOENT;
 1559     pthread_rwlock_rdlock(&f->tree_lock);
 1560     path = get_path_name(f, parent, name);
 1561     if (path) {
 1562         struct fuse_intr_data d;
 1563         if (f->conf.debug)
 1564             fprintf(stderr, "MKNOD %s\n", path);
 1565         fuse_prepare_interrupt(f, req, &d);
 1566         err = -ENOSYS;
 1567         if (S_ISREG(mode)) {
 1568             struct fuse_file_info fi;
 1569 
 1570             memset(&fi, 0, sizeof(fi));
 1571             fi.flags = O_CREAT | O_EXCL | O_WRONLY;
 1572             err = fuse_fs_create(f->fs, path, mode, &fi);
 1573             if (!err) {
 1574                 err = lookup_path(f, parent, name, path, &e, &fi);
 1575                 fuse_fs_release(f->fs, path, &fi);
 1576             }
 1577         }
 1578         if (err == -ENOSYS) {
 1579             err = fuse_fs_mknod(f->fs, path, mode, rdev);
 1580             if (!err)
 1581                 err = lookup_path(f, parent, name, path, &e, NULL);
 1582         }
 1583         fuse_finish_interrupt(f, req, &d);
 1584         free(path);
 1585     }
 1586     pthread_rwlock_unlock(&f->tree_lock);
 1587     reply_entry(req, &e, err);
 1588 }
 1589 
 1590 static void fuse_lib_mkdir(fuse_req_t req, fuse_ino_t parent, const char *name,
 1591                            mode_t mode)
 1592 {
 1593     struct fuse *f = req_fuse_prepare(req);
 1594     struct fuse_entry_param e;
 1595     char *path;
 1596     int err;
 1597 
 1598     err = -ENOENT;
 1599     pthread_rwlock_rdlock(&f->tree_lock);
 1600     path = get_path_name(f, parent, name);
 1601     if (path != NULL) {
 1602         struct fuse_intr_data d;
 1603         if (f->conf.debug)
 1604             fprintf(stderr, "MKDIR %s\n", path);
 1605         fuse_prepare_interrupt(f, req, &d);
 1606         err = fuse_fs_mkdir(f->fs, path, mode);
 1607         if (!err)
 1608             err = lookup_path(f, parent, name, path, &e, NULL);
 1609         fuse_finish_interrupt(f, req, &d);
 1610         free(path);
 1611     }
 1612     pthread_rwlock_unlock(&f->tree_lock);
 1613     reply_entry(req, &e, err);
 1614 }
 1615 
 1616 static void fuse_lib_unlink(fuse_req_t req, fuse_ino_t parent,
 1617                             const char *name)
 1618 {
 1619     struct fuse *f = req_fuse_prepare(req);
 1620     char *path;
 1621     int err;
 1622 
 1623     err = -ENOENT;
 1624     pthread_rwlock_wrlock(&f->tree_lock);
 1625     path = get_path_name(f, parent, name);
 1626     if (path != NULL) {
 1627         struct fuse_intr_data d;
 1628         if (f->conf.debug)
 1629             fprintf(stderr, "UNLINK %s\n", path);
 1630         fuse_prepare_interrupt(f, req, &d);
 1631         if (!f->conf.hard_remove && is_open(f, parent, name))
 1632             err = hide_node(f, path, parent, name);
 1633         else {
 1634             err = fuse_fs_unlink(f->fs, path);
 1635             if (!err)
 1636                 remove_node(f, parent, name);
 1637         }
 1638         fuse_finish_interrupt(f, req, &d);
 1639         free(path);
 1640     }
 1641     pthread_rwlock_unlock(&f->tree_lock);
 1642     reply_err(req, err);
 1643 }
 1644 
 1645 static void fuse_lib_rmdir(fuse_req_t req, fuse_ino_t parent, const char *name)
 1646 {
 1647     struct fuse *f = req_fuse_prepare(req);
 1648     char *path;
 1649     int err;
 1650 
 1651     err = -ENOENT;
 1652     pthread_rwlock_wrlock(&f->tree_lock);
 1653     path = get_path_name(f, parent, name);
 1654     if (path != NULL) {
 1655         struct fuse_intr_data d;
 1656         if (f->conf.debug)
 1657             fprintf(stderr, "RMDIR %s\n", path);
 1658         fuse_prepare_interrupt(f, req, &d);
 1659         err = fuse_fs_rmdir(f->fs, path);
 1660         fuse_finish_interrupt(f, req, &d);
 1661         if (!err)
 1662             remove_node(f, parent, name);
 1663         free(path);
 1664     }
 1665     pthread_rwlock_unlock(&f->tree_lock);
 1666     reply_err(req, err);
 1667 }
 1668 
 1669 static void fuse_lib_symlink(fuse_req_t req, const char *linkname,
 1670                              fuse_ino_t parent, const char *name)
 1671 {
 1672     struct fuse *f = req_fuse_prepare(req);
 1673     struct fuse_entry_param e;
 1674     char *path;
 1675     int err;
 1676 
 1677     err = -ENOENT;
 1678     pthread_rwlock_rdlock(&f->tree_lock);
 1679     path = get_path_name(f, parent, name);
 1680     if (path != NULL) {
 1681         struct fuse_intr_data d;
 1682         if (f->conf.debug)
 1683             fprintf(stderr, "SYMLINK %s\n", path);
 1684         fuse_prepare_interrupt(f, req, &d);
 1685         err = fuse_fs_symlink(f->fs, linkname, path);
 1686         if (!err)
 1687             err = lookup_path(f, parent, name, path, &e, NULL);
 1688         fuse_finish_interrupt(f, req, &d);
 1689         free(path);
 1690     }
 1691     pthread_rwlock_unlock(&f->tree_lock);
 1692     reply_entry(req, &e, err);
 1693 }
 1694 
 1695 static void fuse_lib_rename(fuse_req_t req, fuse_ino_t olddir,
 1696                             const char *oldname, fuse_ino_t newdir,
 1697                             const char *newname)
 1698 {
 1699     struct fuse *f = req_fuse_prepare(req);
 1700     char *oldpath;
 1701     char *newpath;
 1702     int err;
 1703 
 1704     err = -ENOENT;
 1705     pthread_rwlock_wrlock(&f->tree_lock);
 1706     oldpath = get_path_name(f, olddir, oldname);
 1707     if (oldpath != NULL) {
 1708         newpath = get_path_name(f, newdir, newname);
 1709         if (newpath != NULL) {
 1710             struct fuse_intr_data d;
 1711             if (f->conf.debug)
 1712                 fprintf(stderr, "RENAME %s -> %s\n", oldpath, newpath);
 1713             err = 0;
 1714             fuse_prepare_interrupt(f, req, &d);
 1715             if (!f->conf.hard_remove && is_open(f, newdir, newname))
 1716                 err = hide_node(f, newpath, newdir, newname);
 1717             if (!err) {
 1718                 err = fuse_fs_rename(f->fs, oldpath, newpath);
 1719                 if (!err)
 1720                     err = rename_node(f, olddir, oldname, newdir, newname, 0);
 1721             }
 1722             fuse_finish_interrupt(f, req, &d);
 1723             free(newpath);
 1724         }
 1725         free(oldpath);
 1726     }
 1727     pthread_rwlock_unlock(&f->tree_lock);
 1728     reply_err(req, err);
 1729 }
 1730 
 1731 static void fuse_lib_link(fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent,
 1732                           const char *newname)
 1733 {
 1734     struct fuse *f = req_fuse_prepare(req);
 1735     struct fuse_entry_param e;
 1736     char *oldpath;
 1737     char *newpath;
 1738     int err;
 1739 
 1740     err = -ENOENT;
 1741     pthread_rwlock_rdlock(&f->tree_lock);
 1742     oldpath = get_path(f, ino);
 1743     if (oldpath != NULL) {
 1744         newpath =  get_path_name(f, newparent, newname);
 1745         if (newpath != NULL) {
 1746             struct fuse_intr_data d;
 1747             if (f->conf.debug)
 1748                 fprintf(stderr, "LINK %s\n", newpath);
 1749             fuse_prepare_interrupt(f, req, &d);
 1750             err = fuse_fs_link(f->fs, oldpath, newpath);
 1751             if (!err)
 1752                 err = lookup_path(f, newparent, newname, newpath, &e, NULL);
 1753             fuse_finish_interrupt(f, req, &d);
 1754             free(newpath);
 1755         }
 1756         free(oldpath);
 1757     }
 1758     pthread_rwlock_unlock(&f->tree_lock);
 1759     reply_entry(req, &e, err);
 1760 }
 1761 
 1762 static void fuse_do_release(struct fuse *f, fuse_ino_t ino, const char *path,
 1763                             struct fuse_file_info *fi)
 1764 {
 1765     struct node *node;
 1766     int unlink_hidden = 0;
 1767 
 1768     fuse_fs_release(f->fs, path ? path : "-", fi);
 1769 
 1770     pthread_mutex_lock(&f->lock);
 1771     node = get_node(f, ino);
 1772     assert(node->open_count > 0);
 1773     --node->open_count;
 1774     if (node->is_hidden && !node->open_count) {
 1775         unlink_hidden = 1;
 1776         node->is_hidden = 0;
 1777     }
 1778     pthread_mutex_unlock(&f->lock);
 1779 
 1780     if(unlink_hidden && path)
 1781         fuse_fs_unlink(f->fs, path);
 1782 }
 1783 
 1784 static void fuse_lib_create(fuse_req_t req, fuse_ino_t parent,
 1785                             const char *name, mode_t mode,
 1786                             struct fuse_file_info *fi)
 1787 {
 1788     struct fuse *f = req_fuse_prepare(req);
 1789     struct fuse_intr_data d;
 1790     struct fuse_entry_param e;
 1791     char *path;
 1792     int err;
 1793 
 1794     err = -ENOENT;
 1795     pthread_rwlock_rdlock(&f->tree_lock);
 1796     path = get_path_name(f, parent, name);
 1797     if (path) {
 1798         fuse_prepare_interrupt(f, req, &d);
 1799         err = fuse_fs_create(f->fs, path, mode, fi);
 1800         if (!err) {
 1801             err = lookup_path(f, parent, name, path, &e, fi);
 1802             if (err)
 1803                 fuse_fs_release(f->fs, path, fi);
 1804             else if (!S_ISREG(e.attr.st_mode)) {
 1805                 err = -EIO;
 1806                 fuse_fs_release(f->fs, path, fi);
 1807                 forget_node(f, e.ino, 1);
 1808             } else {
 1809                 if (f->conf.direct_io)
 1810                     fi->direct_io = 1;
 1811                 if (f->conf.kernel_cache)
 1812                     fi->keep_cache = 1;
 1813 
 1814             }
 1815         }
 1816         fuse_finish_interrupt(f, req, &d);
 1817     }
 1818     if (!err) {
 1819         pthread_mutex_lock(&f->lock);
 1820         get_node(f, e.ino)->open_count++;
 1821         pthread_mutex_unlock(&f->lock);
 1822         if (fuse_reply_create(req, &e, fi) == -ENOENT) {
 1823             /* The open syscall was interrupted, so it must be cancelled */
 1824             fuse_prepare_interrupt(f, req, &d);
 1825             fuse_do_release(f, e.ino, path, fi);
 1826             fuse_finish_interrupt(f, req, &d);
 1827             forget_node(f, e.ino, 1);
 1828         } else if (f->conf.debug) {
 1829             fprintf(stderr, "  CREATE[%llu] flags: 0x%x %s\n",
 1830                     (unsigned long long) fi->fh, fi->flags, path);
 1831         }
 1832     } else
 1833         reply_err(req, err);
 1834 
 1835     if (path)
 1836         free(path);
 1837 
 1838     pthread_rwlock_unlock(&f->tree_lock);
 1839 }
 1840 
 1841 #ifdef __SOLARIS__
 1842 
 1843 static double diff_timespec(const struct timespec *t1,
 1844                             const struct timespec *t2)
 1845 {
 1846     return (t1->tv_sec - t2->tv_sec) + 
 1847         ((double) t1->tv_nsec - (double) t2->tv_nsec) / 1000000000.0;
 1848 }
 1849 
 1850 static void open_auto_cache(struct fuse *f, fuse_ino_t ino, const char *path,
 1851                             struct fuse_file_info *fi)
 1852 {
 1853     struct node *node;
 1854 
 1855     pthread_mutex_lock(&f->lock);
 1856     node = get_node(f, ino);
 1857     if (node->cache_valid) {
 1858         struct timespec now;
 1859 
 1860         curr_time(&now);
 1861         if (diff_timespec(&now, &node->stat_updated) > f->conf.ac_attr_timeout) {
 1862             struct stat stbuf;
 1863             int err;
 1864             pthread_mutex_unlock(&f->lock);
 1865             err = fuse_fs_fgetattr(f->fs, path, &stbuf, fi);
 1866             pthread_mutex_lock(&f->lock);
 1867             if (!err)
 1868                 update_stat(node, &stbuf);
 1869             else
 1870                 node->cache_valid = 0;
 1871         }
 1872     }
 1873     if (node->cache_valid)
 1874         fi->keep_cache = 1;
 1875 
 1876     node->cache_valid = 1;
 1877     pthread_mutex_unlock(&f->lock);
 1878 }
 1879 
 1880 #endif /* __SOLARIS__ */
 1881 
 1882 static void fuse_lib_open(fuse_req_t req, fuse_ino_t ino,
 1883                           struct fuse_file_info *fi)
 1884 {
 1885     struct fuse *f = req_fuse_prepare(req);
 1886     struct fuse_intr_data d;
 1887     char *path = NULL;
 1888     int err = 0;
 1889 
 1890     err = -ENOENT;
 1891     pthread_rwlock_rdlock(&f->tree_lock);
 1892     path = get_path(f, ino);
 1893     if (path) {
 1894         fuse_prepare_interrupt(f, req, &d);
 1895         err = fuse_fs_open(f->fs, path, fi);
 1896         if (!err) {
 1897             if (f->conf.direct_io)
 1898                 fi->direct_io = 1;
 1899             if (f->conf.kernel_cache)
 1900                 fi->keep_cache = 1;
 1901 #ifdef __SOLARIS__
 1902 
 1903             if (f->conf.auto_cache)
 1904                 open_auto_cache(f, ino, path, fi);
 1905 #endif /* __SOLARIS__ */
 1906         }
 1907         fuse_finish_interrupt(f, req, &d);
 1908     }
 1909     if (!err) {
 1910         pthread_mutex_lock(&f->lock);
 1911         get_node(f, ino)->open_count++;
 1912         pthread_mutex_unlock(&f->lock);
 1913         if (fuse_reply_open(req, fi) == -ENOENT) {
 1914             /* The open syscall was interrupted, so it must be cancelled */
 1915             fuse_prepare_interrupt(f, req, &d);
 1916             fuse_do_release(f, ino, path, fi);
 1917             fuse_finish_interrupt(f, req, &d);
 1918         } else if (f->conf.debug) {
 1919             fprintf(stderr, "OPEN[%llu] flags: 0x%x %s\n",
 1920                     (unsigned long long) fi->fh, fi->flags, path);
 1921         }
 1922     } else
 1923         reply_err(req, err);
 1924 
 1925     if (path)
 1926         free(path);
 1927     pthread_rwlock_unlock(&f->tree_lock);
 1928 }
 1929 
 1930 static void fuse_lib_read(fuse_req_t req, fuse_ino_t ino, size_t size,
 1931                           off_t off, struct fuse_file_info *fi)
 1932 {
 1933     struct fuse *f = req_fuse_prepare(req);
 1934     char *path;
 1935     char *buf;
 1936     int res;
 1937 
 1938     buf = (char *) malloc(size);
 1939     if (buf == NULL) {
 1940         reply_err(req, -ENOMEM);
 1941         return;
 1942     }
 1943 
 1944     res = -ENOENT;
 1945     pthread_rwlock_rdlock(&f->tree_lock);
 1946     path = get_path(f, ino);
 1947     if (path != NULL) {
 1948         struct fuse_intr_data d;
 1949         if (f->conf.debug)
 1950             fprintf(stderr, "READ[%llu] %lu bytes from %llu\n",
 1951                     (unsigned long long) fi->fh, (unsigned long) size,
 1952                     (unsigned long long) off);
 1953 
 1954         fuse_prepare_interrupt(f, req, &d);
 1955         res = fuse_fs_read(f->fs, path, buf, size, off, fi);
 1956         fuse_finish_interrupt(f, req, &d);
 1957         free(path);
 1958     }
 1959     pthread_rwlock_unlock(&f->tree_lock);
 1960 
 1961     if (res >= 0) {
 1962         if (f->conf.debug)
 1963             fprintf(stderr, "   READ[%llu] %u bytes\n",
 1964                     (unsigned long long)fi->fh, res);
 1965         if ((size_t) res > size)
 1966             fprintf(stderr, "fuse: read too many bytes");
 1967         fuse_reply_buf(req, buf, res);
 1968     } else
 1969         reply_err(req, res);
 1970 
 1971     free(buf);
 1972 }
 1973 
 1974 static void fuse_lib_write(fuse_req_t req, fuse_ino_t ino, const char *buf,
 1975                        size_t size, off_t off, struct fuse_file_info *fi)
 1976 {
 1977     struct fuse *f = req_fuse_prepare(req);
 1978     char *path;
 1979     int res;
 1980 
 1981     res = -ENOENT;
 1982     pthread_rwlock_rdlock(&f->tree_lock);
 1983     path = get_path(f, ino);
 1984     if (path != NULL) {
 1985         struct fuse_intr_data d;
 1986         if (f->conf.debug)
 1987             fprintf(stderr, "WRITE%s[%llu] %lu bytes to %llu\n",
 1988                     fi->writepage ? "PAGE" : "", (unsigned long long) fi->fh,
 1989                     (unsigned long) size, (unsigned long long) off);
 1990 
 1991         fuse_prepare_interrupt(f, req, &d);
 1992         res = fuse_fs_write(f->fs, path, buf, size, off, fi);
 1993         fuse_finish_interrupt(f, req, &d);
 1994         free(path);
 1995     }
 1996     pthread_rwlock_unlock(&f->tree_lock);
 1997 
 1998     if (res >= 0) {
 1999         if (f->conf.debug)
 2000             fprintf(stderr, "   WRITE%s[%llu] %u bytes\n",
 2001                     fi->writepage ? "PAGE" : "", (unsigned long long) fi->fh,
 2002                     res);
 2003         if ((size_t) res > size)
 2004             fprintf(stderr, "fuse: wrote too many bytes");
 2005         fuse_reply_write(req, res);
 2006     } else
 2007         reply_err(req, res);
 2008 }
 2009 
 2010 static void fuse_lib_fsync(fuse_req_t req, fuse_ino_t ino, int datasync,
 2011                        struct fuse_file_info *fi)
 2012 {
 2013     struct fuse *f = req_fuse_prepare(req);
 2014     char *path;
 2015     int err;
 2016 
 2017     err = -ENOENT;
 2018     pthread_rwlock_rdlock(&f->tree_lock);
 2019     path = get_path(f, ino);
 2020     if (path != NULL) {
 2021         struct fuse_intr_data d;
 2022         if (f->conf.debug)
 2023             fprintf(stderr, "FSYNC[%llu]\n", (unsigned long long) fi->fh);
 2024         fuse_prepare_interrupt(f, req, &d);
 2025         err = fuse_fs_fsync(f->fs, path, datasync, fi);
 2026         fuse_finish_interrupt(f, req, &d);
 2027         free(path);
 2028     }
 2029     pthread_rwlock_unlock(&f->tree_lock);
 2030     reply_err(req, err);
 2031 }
 2032 
 2033 static struct fuse_dh *get_dirhandle(const struct fuse_file_info *llfi,
 2034                                      struct fuse_file_info *fi)
 2035 {
 2036     struct fuse_dh *dh = (struct fuse_dh *) (uintptr_t) llfi->fh;
 2037     memset(fi, 0, sizeof(struct fuse_file_info));
 2038     fi->fh = dh->fh;
 2039     fi->fh_old = dh->fh;
 2040     return dh;
 2041 }
 2042 
 2043 static void fuse_lib_opendir(fuse_req_t req, fuse_ino_t ino,
 2044                        struct fuse_file_info *llfi)
 2045 {
 2046     struct fuse *f = req_fuse_prepare(req);
 2047     struct fuse_intr_data d;
 2048     struct fuse_dh *dh;
 2049     struct fuse_file_info fi;
 2050     char *path;
 2051     int err;
 2052 
 2053     dh = (struct fuse_dh *) malloc(sizeof(struct fuse_dh));
 2054     if (dh == NULL) {
 2055         reply_err(req, -ENOMEM);
 2056         return;
 2057     }
 2058     memset(dh, 0, sizeof(struct fuse_dh));
 2059     dh->fuse = f;
 2060     dh->contents = NULL;
 2061     dh->len = 0;
 2062     dh->filled = 0;
 2063     dh->nodeid = ino;
 2064     fuse_mutex_init(&dh->lock);
 2065 
 2066     llfi->fh = (uintptr_t) dh;
 2067 
 2068     memset(&fi, 0, sizeof(fi));
 2069     fi.flags = llfi->flags;
 2070 
 2071     err = -ENOENT;
 2072     pthread_rwlock_rdlock(&f->tree_lock);
 2073     path = get_path(f, ino);
 2074     if (path != NULL) {
 2075         fuse_prepare_interrupt(f, req, &d);
 2076         err = fuse_fs_opendir(f->fs, path, &fi);
 2077         fuse_finish_interrupt(f, req, &d);
 2078         dh->fh = fi.fh;
 2079     }
 2080     if (!err) {
 2081         if (fuse_reply_open(req, llfi) == -ENOENT) {
 2082             /* The opendir syscall was interrupted, so it must be cancelled */
 2083             fuse_prepare_interrupt(f, req, &d);
 2084             fuse_fs_releasedir(f->fs, path, &fi);
 2085             fuse_finish_interrupt(f, req, &d);
 2086             pthread_mutex_destroy(&dh->lock);
 2087             free(dh);
 2088         }
 2089     } else {
 2090         reply_err(req, err);
 2091         pthread_mutex_destroy(&dh->lock);
 2092         free(dh);
 2093     }
 2094     free(path);
 2095     pthread_rwlock_unlock(&f->tree_lock);
 2096 }
 2097 
 2098 static int extend_contents(struct fuse_dh *dh, unsigned minsize)
 2099 {
 2100     if (minsize > dh->size) {
 2101         char *newptr;
 2102         unsigned newsize = dh->size;
 2103         if (!newsize)
 2104             newsize = 1024;
 2105 #ifndef __SOLARIS__
 2106         while (newsize < minsize) {
 2107         if (newsize >= 0x80000000)
 2108             newsize = 0xffffffff;
 2109         else
 2110             newsize *= 2;
 2111         }
 2112 #else /* __SOLARIS__ */
 2113         while (newsize < minsize)
 2114             newsize *= 2;
 2115 #endif /* __SOLARIS__ */
 2116 
 2117         newptr = (char *) realloc(dh->contents, newsize);
 2118         if (!newptr) {
 2119             dh->error = -ENOMEM;
 2120             return -1;
 2121         }
 2122         dh->contents = newptr;
 2123         dh->size = newsize;
 2124     }
 2125     return 0;
 2126 }
 2127 
 2128 static int fill_dir(void *dh_, const char *name, const struct stat *statp,
 2129                     off_t off)
 2130 {
 2131     struct fuse_dh *dh = (struct fuse_dh *) dh_;
 2132     struct stat stbuf;
 2133     size_t newlen;
 2134 
 2135     if (statp)
 2136         stbuf = *statp;
 2137     else {
 2138         memset(&stbuf, 0, sizeof(stbuf));
 2139         stbuf.st_ino = FUSE_UNKNOWN_INO;
 2140     }
 2141 
 2142     if (!dh->fuse->conf.use_ino) {
 2143         stbuf.st_ino = FUSE_UNKNOWN_INO;
 2144         if (dh->fuse->conf.readdir_ino) {
 2145             struct node *node;
 2146             pthread_mutex_lock(&dh->fuse->lock);
 2147             node = lookup_node(dh->fuse, dh->nodeid, name);
 2148             if (node)
 2149                 stbuf.st_ino  = (ino_t) node->nodeid;
 2150             pthread_mutex_unlock(&dh->fuse->lock);
 2151         }
 2152     }
 2153 
 2154     if (off) {
 2155         if (extend_contents(dh, dh->needlen) == -1)
 2156             return 1;
 2157 
 2158         dh->filled = 0;
 2159         newlen = dh->len + fuse_add_direntry(dh->req, dh->contents + dh->len,
 2160                                              dh->needlen - dh->len, name,
 2161                                              &stbuf, off);
 2162         if (newlen > dh->needlen)
 2163             return 1;
 2164     } else {
 2165         newlen = dh->len + fuse_add_direntry(dh->req, NULL, 0, name, NULL, 0);
 2166         if (extend_contents(dh, newlen) == -1)
 2167             return 1;
 2168 
 2169         fuse_add_direntry(dh->req, dh->contents + dh->len, dh->size - dh->len,
 2170                           name, &stbuf, newlen);
 2171     }
 2172     dh->len = newlen;
 2173     return 0;
 2174 }
 2175 
 2176 static int readdir_fill(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
 2177                         size_t size, off_t off, struct fuse_dh *dh,
 2178                         struct fuse_file_info *fi)
 2179 {
 2180     int err = -ENOENT;
 2181     char *path;
 2182     pthread_rwlock_rdlock(&f->tree_lock);
 2183     path = get_path(f, ino);
 2184     if (path != NULL) {
 2185         struct fuse_intr_data d;
 2186 
 2187         dh->len = 0;
 2188         dh->error = 0;
 2189         dh->needlen = size;
 2190         dh->filled = 1;
 2191         dh->req = req;
 2192         fuse_prepare_interrupt(f, req, &d);
 2193         err = fuse_fs_readdir(f->fs, path, dh, fill_dir, off, fi);
 2194         fuse_finish_interrupt(f, req, &d);
 2195         dh->req = NULL;
 2196         if (!err)
 2197             err = dh->error;
 2198         if (err)
 2199             dh->filled = 0;
 2200         free(path);
 2201     }
 2202     pthread_rwlock_unlock(&f->tree_lock);
 2203     return err;
 2204 }
 2205 
 2206 static void fuse_lib_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
 2207                              off_t off, struct fuse_file_info *llfi)
 2208 {
 2209     struct fuse *f = req_fuse_prepare(req);
 2210     struct fuse_file_info fi;
 2211     struct fuse_dh *dh = get_dirhandle(llfi, &fi);
 2212 
 2213     pthread_mutex_lock(&dh->lock);
 2214     /* According to SUS, directory contents need to be refreshed on
 2215        rewinddir() */
 2216     if (!off)
 2217         dh->filled = 0;
 2218 
 2219     if (!dh->filled) {
 2220         int err = readdir_fill(f, req, ino, size, off, dh, &fi);
 2221         if (err) {
 2222             reply_err(req, err);
 2223             goto out;
 2224         }
 2225     }
 2226     if (dh->filled) {
 2227         if (off < dh->len) {
 2228             if (off + size > dh->len)
 2229                 size = dh->len - off;
 2230         } else
 2231             size = 0;
 2232     } else {
 2233         size = dh->len;
 2234         off = 0;
 2235     }
 2236     fuse_reply_buf(req, dh->contents + off, size);
 2237  out:
 2238     pthread_mutex_unlock(&dh->lock);
 2239 }
 2240 
 2241 static void fuse_lib_releasedir(fuse_req_t req, fuse_ino_t ino,
 2242                             struct fuse_file_info *llfi)
 2243 {
 2244     struct fuse *f = req_fuse_prepare(req);
 2245     struct fuse_intr_data d;
 2246     struct fuse_file_info fi;
 2247     struct fuse_dh *dh = get_dirhandle(llfi, &fi);
 2248     char *path;
 2249 
 2250     pthread_rwlock_rdlock(&f->tree_lock);
 2251     path = get_path(f, ino);
 2252     fuse_prepare_interrupt(f, req, &d);
 2253     fuse_fs_releasedir(f->fs, path ? path : "-", &fi);
 2254     fuse_finish_interrupt(f, req, &d);
 2255     if (path)
 2256         free(path);
 2257     pthread_rwlock_unlock(&f->tree_lock);
 2258     pthread_mutex_lock(&dh->lock);
 2259     pthread_mutex_unlock(&dh->lock);
 2260     pthread_mutex_destroy(&dh->lock);
 2261     free(dh->contents);
 2262     free(dh);
 2263     reply_err(req, 0);
 2264 }
 2265 
 2266 static void fuse_lib_fsyncdir(fuse_req_t req, fuse_ino_t ino, int datasync,
 2267                           struct fuse_file_info *llfi)
 2268 {
 2269     struct fuse *f = req_fuse_prepare(req);
 2270     struct fuse_file_info fi;
 2271     char *path;
 2272     int err;
 2273 
 2274     get_dirhandle(llfi, &fi);
 2275 
 2276     err = -ENOENT;
 2277     pthread_rwlock_rdlock(&f->tree_lock);
 2278     path = get_path(f, ino);
 2279     if (path != NULL) {
 2280         struct fuse_intr_data d;
 2281         fuse_prepare_interrupt(f, req, &d);
 2282         err = fuse_fs_fsyncdir(f->fs, path, datasync, &fi);
 2283         fuse_finish_interrupt(f, req, &d);
 2284         free(path);
 2285     }
 2286     pthread_rwlock_unlock(&f->tree_lock);
 2287     reply_err(req, err);
 2288 }
 2289 
 2290 static void fuse_lib_statfs(fuse_req_t req, fuse_ino_t ino)
 2291 {
 2292     struct fuse *f = req_fuse_prepare(req);
 2293     struct statvfs buf;
 2294     char *path;
 2295     int err;
 2296 
 2297     memset(&buf, 0, sizeof(buf));
 2298     pthread_rwlock_rdlock(&f->tree_lock);
 2299     if (!ino) {
 2300         err = -ENOMEM;
 2301         path = strdup("/");
 2302     } else {
 2303         err = -ENOENT;
 2304         path = get_path(f, ino);
 2305     }
 2306     if (path) {
 2307         struct fuse_intr_data d;
 2308         fuse_prepare_interrupt(f, req, &d);
 2309         err = fuse_fs_statfs(f->fs, path, &buf);
 2310         fuse_finish_interrupt(f, req, &d);
 2311         free(path);
 2312     }
 2313     pthread_rwlock_unlock(&f->tree_lock);
 2314 
 2315     if (!err)
 2316         fuse_reply_statfs(req, &buf);
 2317     else
 2318         reply_err(req, err);
 2319 }
 2320 
 2321 static void fuse_lib_setxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
 2322                               const char *value, size_t size, int flags)
 2323 {
 2324     struct fuse *f = req_fuse_prepare(req);
 2325     char *path;
 2326     int err;
 2327 
 2328     err = -ENOENT;
 2329     pthread_rwlock_rdlock(&f->tree_lock);
 2330     path = get_path(f, ino);
 2331     if (path != NULL) {
 2332         struct fuse_intr_data d;
 2333         fuse_prepare_interrupt(f, req, &d);
 2334         err = fuse_fs_setxattr(f->fs, path, name, value, size, flags);
 2335         fuse_finish_interrupt(f, req, &d);
 2336         free(path);
 2337     }
 2338     pthread_rwlock_unlock(&f->tree_lock);
 2339     reply_err(req, err);
 2340 }
 2341 
 2342 static int common_getxattr(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
 2343                            const char *name, char *value, size_t size)
 2344 {
 2345     int err;
 2346     char *path;
 2347 
 2348     err = -ENOENT;
 2349     pthread_rwlock_rdlock(&f->tree_lock);
 2350     path = get_path(f, ino);
 2351     if (path != NULL) {
 2352         struct fuse_intr_data d;
 2353         fuse_prepare_interrupt(f, req, &d);
 2354         err = fuse_fs_getxattr(f->fs, path, name, value, size);
 2355         fuse_finish_interrupt(f, req, &d);
 2356         free(path);
 2357     }
 2358     pthread_rwlock_unlock(&f->tree_lock);
 2359     return err;
 2360 }
 2361 
 2362 static void fuse_lib_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
 2363                               size_t size)
 2364 {
 2365     struct fuse *f = req_fuse_prepare(req);
 2366     int res;
 2367 
 2368     if (size) {
 2369         char *value = (char *) malloc(size);
 2370         if (value == NULL) {
 2371             reply_err(req, -ENOMEM);
 2372             return;
 2373         }
 2374         res = common_getxattr(f, req, ino, name, value, size);
 2375         if (res > 0)
 2376             fuse_reply_buf(req, value, res);
 2377         else
 2378             reply_err(req, res);
 2379         free(value);
 2380     } else {
 2381         res = common_getxattr(f, req, ino, name, NULL, 0);
 2382         if (res >= 0)
 2383             fuse_reply_xattr(req, res);
 2384         else
 2385             reply_err(req, res);
 2386     }
 2387 }
 2388 
 2389 static int common_listxattr(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
 2390                             char *list, size_t size)
 2391 {
 2392     char *path;
 2393     int err;
 2394 
 2395     err = -ENOENT;
 2396     pthread_rwlock_rdlock(&f->tree_lock);
 2397     path = get_path(f, ino);
 2398     if (path != NULL) {
 2399         struct fuse_intr_data d;
 2400         fuse_prepare_interrupt(f, req, &d);
 2401         err = fuse_fs_listxattr(f->fs, path, list, size);
 2402         fuse_finish_interrupt(f, req, &d);
 2403         free(path);
 2404     }
 2405     pthread_rwlock_unlock(&f->tree_lock);
 2406     return err;
 2407 }
 2408 
 2409 static void fuse_lib_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size)
 2410 {
 2411     struct fuse *f = req_fuse_prepare(req);
 2412     int res;
 2413 
 2414     if (size) {
 2415         char *list = (char *) malloc(size);
 2416         if (list == NULL) {
 2417             reply_err(req, -ENOMEM);
 2418             return;
 2419         }
 2420         res = common_listxattr(f, req, ino, list, size);
 2421         if (res > 0)
 2422             fuse_reply_buf(req, list, res);
 2423         else
 2424             reply_err(req, res);
 2425         free(list);
 2426     } else {
 2427         res = common_listxattr(f, req, ino, NULL, 0);
 2428         if (res >= 0)
 2429             fuse_reply_xattr(req, res);
 2430         else
 2431             reply_err(req, res);
 2432     }
 2433 }
 2434 
 2435 static void fuse_lib_removexattr(fuse_req_t req, fuse_ino_t ino,
 2436                                  const char *name)
 2437 {
 2438     struct fuse *f = req_fuse_prepare(req);
 2439     char *path;
 2440     int err;
 2441 
 2442     err = -ENOENT;
 2443     pthread_rwlock_rdlock(&f->tree_lock);
 2444     path = get_path(f, ino);
 2445     if (path != NULL) {
 2446         struct fuse_intr_data d;
 2447         fuse_prepare_interrupt(f, req, &d);
 2448         err = fuse_fs_removexattr(f->fs, path, name);
 2449         fuse_finish_interrupt(f, req, &d);
 2450         free(path);
 2451     }
 2452     pthread_rwlock_unlock(&f->tree_lock);
 2453     reply_err(req, err);
 2454 }
 2455 
 2456 static struct lock *locks_conflict(struct node *node, const struct lock *lock)
 2457 {
 2458     struct lock *l;
 2459 
 2460     for (l = node->locks; l; l = l->next)
 2461         if (l->owner != lock->owner &&
 2462             lock->start <= l->end && l->start <= lock->end &&
 2463             (l->type == F_WRLCK || lock->type == F_WRLCK))
 2464             break;
 2465 
 2466     return l;
 2467 }
 2468 
 2469 static void delete_lock(struct lock **lockp)
 2470 {
 2471     struct lock *l = *lockp;
 2472     *lockp = l->next;
 2473     free(l);
 2474 }
 2475 
 2476 static void insert_lock(struct lock **pos, struct lock *lock)
 2477 {
 2478     lock->next = *pos;
 2479     *pos = lock;
 2480 }
 2481 
 2482 static int locks_insert(struct node *node, struct lock *lock)
 2483 {
 2484     struct lock **lp;
 2485     struct lock *newl1 = NULL;
 2486     struct lock *newl2 = NULL;
 2487 
 2488     if (lock->type != F_UNLCK || lock->start != 0 || lock->end != OFFSET_MAX) {
 2489         newl1 = malloc(sizeof(struct lock));
 2490         newl2 = malloc(sizeof(struct lock));
 2491 
 2492         if (!newl1 || !newl2) {
 2493             free(newl1);
 2494             free(newl2);
 2495             return -ENOLCK;
 2496         }
 2497     }
 2498 
 2499     for (lp = &node->locks; *lp;) {
 2500         struct lock *l = *lp;
 2501         if (l->owner != lock->owner)
 2502             goto skip;
 2503 
 2504         if (lock->type == l->type) {
 2505             if (l->end < lock->start - 1)
 2506                 goto skip;
 2507             if (lock->end < l->start - 1)
 2508                 break;
 2509             if (l->start <= lock->start && lock->end <= l->end)
 2510                 goto out;
 2511             if (l->start < lock->start)
 2512                 lock->start = l->start;
 2513             if (lock->end < l->end)
 2514                 lock->end = l->end;
 2515             goto delete;
 2516         } else {
 2517             if (l->end < lock->start)
 2518                 goto skip;
 2519             if (lock->end < l->start)
 2520                 break;
 2521             if (lock->start <= l->start && l->end <= lock->end)
 2522                 goto delete;
 2523             if (l->end <= lock->end) {
 2524                 l->end = lock->start - 1;
 2525                 goto skip;
 2526             }
 2527             if (lock->start <= l->start) {
 2528                 l->start = lock->end + 1;
 2529                 break;
 2530             }
 2531             *newl2 = *l;
 2532             newl2->start = lock->end + 1;
 2533             l->end = lock->start - 1;
 2534             insert_lock(&l->next, newl2);
 2535             newl2 = NULL;
 2536         }
 2537     skip:
 2538         lp = &l->next;
 2539         continue;
 2540 
 2541     delete:
 2542         delete_lock(lp);
 2543     }
 2544     if (lock->type != F_UNLCK) {
 2545         *newl1 = *lock;
 2546         insert_lock(lp, newl1);
 2547         newl1 = NULL;
 2548     }
 2549 out:
 2550     free(newl1);
 2551     free(newl2);
 2552     return 0;
 2553 }
 2554 
 2555 static void flock_to_lock(struct flock *flock, struct lock *lock)
 2556 {
 2557     memset(lock, 0, sizeof(struct lock));
 2558     lock->type = flock->l_type;
 2559     lock->start = flock->l_start;
 2560     lock->end = flock->l_len ? flock->l_start + flock->l_len - 1 : OFFSET_MAX;
 2561     lock->pid = flock->l_pid;
 2562 }
 2563 
 2564 static void lock_to_flock(struct lock *lock, struct flock *flock)
 2565 {
 2566     flock->l_type = lock->type;
 2567     flock->l_start = lock->start;
 2568     flock->l_len = (lock->end == OFFSET_MAX) ? 0 : lock->end - lock->start + 1;
 2569     flock->l_pid = lock->pid;
 2570 }
 2571 
 2572 static int fuse_flush_common(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
 2573                              const char *path, struct fuse_file_info *fi)
 2574 {
 2575     struct fuse_intr_data d;
 2576     struct flock lock;
 2577     struct lock l;
 2578     int err;
 2579     int errlock;
 2580 
 2581     fuse_prepare_interrupt(f, req, &d);
 2582     memset(&lock, 0, sizeof(lock));
 2583     lock.l_type = F_UNLCK;
 2584     lock.l_whence = SEEK_SET;
 2585     err = fuse_fs_flush(f->fs, path, fi);
 2586     errlock = fuse_fs_lock(f->fs, path, fi, F_SETLK, &lock);
 2587     fuse_finish_interrupt(f, req, &d);
 2588 
 2589     if (errlock != -ENOSYS) {
 2590         flock_to_lock(&lock, &l);
 2591         l.owner = fi->lock_owner;
 2592         pthread_mutex_lock(&f->lock);
 2593         locks_insert(get_node(f, ino), &l);
 2594         pthread_mutex_unlock(&f->lock);
 2595 
 2596         /* if op.lock() is defined FLUSH is needed regardless of op.flush() */
 2597         if (err == -ENOSYS)
 2598             err = 0;
 2599     }
 2600     return err;
 2601 }
 2602 
 2603 static void fuse_lib_release(fuse_req_t req, fuse_ino_t ino,
 2604                              struct fuse_file_info *fi)
 2605 {
 2606     struct fuse *f = req_fuse_prepare(req);
 2607     struct fuse_intr_data d;
 2608     char *path;
 2609     int err = 0;
 2610 
 2611     pthread_rwlock_rdlock(&f->tree_lock);
 2612     path = get_path(f, ino);
 2613     if (f->conf.debug)
 2614         fprintf(stderr, "RELEASE%s[%llu] flags: 0x%x\n",
 2615                 fi->flush ? "+FLUSH" : "",
 2616                 (unsigned long long) fi->fh, fi->flags);
 2617 
 2618     if (fi->flush) {
 2619         err = fuse_flush_common(f, req, ino, path, fi);
 2620         if (err == -ENOSYS)
 2621             err = 0;
 2622     }
 2623 
 2624     fuse_prepare_interrupt(f, req, &d);
 2625     fuse_do_release(f, ino, path, fi);
 2626     fuse_finish_interrupt(f, req, &d);
 2627     free(path);
 2628     pthread_rwlock_unlock(&f->tree_lock);
 2629 
 2630     reply_err(req, err);
 2631 }
 2632 
 2633 static void fuse_lib_flush(fuse_req_t req, fuse_ino_t ino,
 2634                        struct fuse_file_info *fi)
 2635 {
 2636     struct fuse *f = req_fuse_prepare(req);
 2637     char *path;
 2638     int err;
 2639 
 2640     pthread_rwlock_rdlock(&f->tree_lock);
 2641     path = get_path(f, ino);
 2642     if (path && f->conf.debug)
 2643         fprintf(stderr, "FLUSH[%llu]\n", (unsigned long long) fi->fh);
 2644     err = fuse_flush_common(f, req, ino, path, fi);
 2645     free(path);
 2646     pthread_rwlock_unlock(&f->tree_lock);
 2647     reply_err(req, err);
 2648 }
 2649 
 2650 static int fuse_lock_common(fuse_req_t req, fuse_ino_t ino,
 2651                             struct fuse_file_info *fi, struct flock *lock,
 2652                             int cmd)
 2653 {
 2654     struct fuse *f = req_fuse_prepare(req);
 2655     char *path;
 2656     int err;
 2657 
 2658     err = -ENOENT;
 2659     pthread_rwlock_rdlock(&f->tree_lock);
 2660     path = get_path(f, ino);
 2661     if (path != NULL) {
 2662         struct fuse_intr_data d;
 2663         fuse_prepare_interrupt(f, req, &d);
 2664         err = fuse_fs_lock(f->fs, path, fi, cmd, lock);
 2665         fuse_finish_interrupt(f, req, &d);
 2666         free(path);
 2667     }
 2668     pthread_rwlock_unlock(&f->tree_lock);
 2669     return err;
 2670 }
 2671 
 2672 static void fuse_lib_getlk(fuse_req_t req, fuse_ino_t ino,
 2673                            struct fuse_file_info *fi, struct flock *lock)
 2674 {
 2675     int err;
 2676     struct lock l;
 2677     struct lock *conflict;
 2678     struct fuse *f = req_fuse(req);
 2679 
 2680     flock_to_lock(lock, &l);
 2681     l.owner = fi->lock_owner;
 2682     pthread_mutex_lock(&f->lock);
 2683     conflict = locks_conflict(get_node(f, ino), &l);
 2684     if (conflict)
 2685         lock_to_flock(conflict, lock);
 2686     pthread_mutex_unlock(&f->lock);
 2687     if (!conflict)
 2688         err = fuse_lock_common(req, ino, fi, lock, F_GETLK);
 2689     else
 2690         err = 0;
 2691 
 2692     if (!err)
 2693         fuse_reply_lock(req, lock);
 2694     else
 2695         reply_err(req, err);
 2696 }
 2697 
 2698 static void fuse_lib_setlk(fuse_req_t req, fuse_ino_t ino,
 2699                            struct fuse_file_info *fi, struct flock *lock,
 2700                            int should_sleep)
 2701 {
 2702     int err = fuse_lock_common(req, ino, fi, lock, should_sleep ? F_SETLKW : F_SETLK);
 2703     if (!err) {
 2704         struct fuse *f = req_fuse(req);
 2705         struct lock l;
 2706         flock_to_lock(lock, &l);
 2707         l.owner = fi->lock_owner;
 2708         pthread_mutex_lock(&f->lock);
 2709         locks_insert(get_node(f, ino), &l);
 2710         pthread_mutex_unlock(&f->lock);
 2711     }
 2712     reply_err(req, err);
 2713 }
 2714 
 2715 static void fuse_lib_bmap(fuse_req_t req, fuse_ino_t ino, size_t blocksize,
 2716                           uint64_t idx)
 2717 {
 2718     struct fuse *f = req_fuse_prepare(req);
 2719     struct fuse_intr_data d;
 2720     char *path;
 2721     int err;
 2722 
 2723     err = -ENOENT;
 2724     pthread_rwlock_rdlock(&f->tree_lock);
 2725     path = get_path(f, ino);
 2726     if (path != NULL) {
 2727         fuse_prepare_interrupt(f, req, &d);
 2728         err = fuse_fs_bmap(f->fs, path, blocksize, &idx);
 2729         fuse_finish_interrupt(f, req, &d);
 2730         free(path);
 2731     }
 2732     pthread_rwlock_unlock(&f->tree_lock);
 2733     if (!err)
 2734         fuse_reply_bmap(req, idx);
 2735     else
 2736         reply_err(req, err);
 2737 }
 2738 
 2739 static void fuse_lib_ioctl(fuse_req_t req, fuse_ino_t ino, int cmd, void *arg,
 2740                struct fuse_file_info *llfi, unsigned int flags,
 2741                const void *in_buf, size_t in_bufsz,
 2742                size_t out_bufsz)
 2743 {
 2744     struct fuse *f = req_fuse_prepare(req);
 2745     struct fuse_intr_data d;
 2746     struct fuse_file_info fi;
 2747     char *path, *out_buf = NULL;
 2748     int err;
 2749 
 2750     err = -EPERM;
 2751     if (flags & FUSE_IOCTL_UNRESTRICTED)
 2752     goto err;
 2753 
 2754     if (flags & FUSE_IOCTL_DIR)
 2755     get_dirhandle(llfi, &fi);
 2756     else
 2757     fi = *llfi;
 2758 
 2759     if (out_bufsz) {
 2760     err = -ENOMEM;
 2761     out_buf = malloc(out_bufsz);
 2762     if (!out_buf)
 2763         goto err;
 2764     }
 2765 
 2766     assert(!in_bufsz || !out_bufsz || in_bufsz == out_bufsz);
 2767     if (out_buf)
 2768     memcpy(out_buf, in_buf, in_bufsz);
 2769 
 2770     path = get_path(f, ino); /* Should be get_path_nullok() */
 2771     if (!path) {
 2772     err = ENOENT;
 2773     goto err;
 2774     }
 2775 
 2776     fuse_prepare_interrupt(f, req, &d);
 2777 
 2778     /* Note : const qualifier dropped */
 2779     err = fuse_fs_ioctl(f->fs, path, cmd, arg, &fi, flags,
 2780             out_buf ? (void*)out_buf : (void*)(uintptr_t)in_buf);
 2781 
 2782     fuse_finish_interrupt(f, req, &d);
 2783     free(path);
 2784 
 2785     fuse_reply_ioctl(req, err, out_buf, out_bufsz);
 2786     goto out;
 2787 err:
 2788     reply_err(req, err);
 2789 out:
 2790     free(out_buf);
 2791 }
 2792 
 2793 static struct fuse_lowlevel_ops fuse_path_ops = {
 2794     .init = fuse_lib_init,
 2795     .destroy = fuse_lib_destroy,
 2796     .lookup = fuse_lib_lookup,
 2797     .forget = fuse_lib_forget,
 2798     .getattr = fuse_lib_getattr,
 2799     .setattr = fuse_lib_setattr,
 2800     .access = fuse_lib_access,
 2801     .readlink = fuse_lib_readlink,
 2802     .mknod = fuse_lib_mknod,
 2803     .mkdir = fuse_lib_mkdir,
 2804     .unlink = fuse_lib_unlink,
 2805     .rmdir = fuse_lib_rmdir,
 2806     .symlink = fuse_lib_symlink,
 2807     .rename = fuse_lib_rename,
 2808     .link = fuse_lib_link,
 2809     .create = fuse_lib_create,
 2810     .open = fuse_lib_open,
 2811     .read = fuse_lib_read,
 2812     .write = fuse_lib_write,
 2813     .flush = fuse_lib_flush,
 2814     .release = fuse_lib_release,
 2815     .fsync = fuse_lib_fsync,
 2816     .opendir = fuse_lib_opendir,
 2817     .readdir = fuse_lib_readdir,
 2818     .releasedir = fuse_lib_releasedir,
 2819     .fsyncdir = fuse_lib_fsyncdir,
 2820     .statfs = fuse_lib_statfs,
 2821     .setxattr = fuse_lib_setxattr,
 2822     .getxattr = fuse_lib_getxattr,
 2823     .listxattr = fuse_lib_listxattr,
 2824     .removexattr = fuse_lib_removexattr,
 2825     .getlk = fuse_lib_getlk,
 2826     .setlk = fuse_lib_setlk,
 2827     .bmap = fuse_lib_bmap,
 2828     .ioctl = fuse_lib_ioctl,
 2829 };
 2830 
 2831 struct fuse_session *fuse_get_session(struct fuse *f)
 2832 {
 2833     return f->se;
 2834 }
 2835 
 2836 int fuse_loop(struct fuse *f)
 2837 {
 2838     if (f)
 2839         return fuse_session_loop(f->se);
 2840     else
 2841         return -1;
 2842 }
 2843 
 2844 void fuse_exit(struct fuse *f)
 2845 {
 2846     fuse_session_exit(f->se);
 2847 }
 2848 
 2849 struct fuse_context *fuse_get_context(void)
 2850 {
 2851     return &fuse_get_context_internal()->ctx;
 2852 }
 2853 
 2854 int fuse_interrupted(void)
 2855 {
 2856     return fuse_req_interrupted(fuse_get_context_internal()->req);
 2857 }
 2858 
 2859 enum {
 2860     KEY_HELP,
 2861 };
 2862 
 2863 #define FUSE_LIB_OPT(t, p, v) { t, offsetof(struct fuse_config, p), v }
 2864 
 2865 static const struct fuse_opt fuse_lib_opts[] = {
 2866     FUSE_OPT_KEY("-h",                    KEY_HELP),
 2867     FUSE_OPT_KEY("--help",                KEY_HELP),
 2868     FUSE_OPT_KEY("debug",                 FUSE_OPT_KEY_KEEP),
 2869     FUSE_OPT_KEY("-d",                    FUSE_OPT_KEY_KEEP),
 2870     FUSE_LIB_OPT("debug",                 debug, 1),
 2871     FUSE_LIB_OPT("-d",                    debug, 1),
 2872     FUSE_LIB_OPT("hard_remove",           hard_remove, 1),
 2873     FUSE_LIB_OPT("use_ino",               use_ino, 1),
 2874     FUSE_LIB_OPT("readdir_ino",           readdir_ino, 1),
 2875     FUSE_LIB_OPT("direct_io",             direct_io, 1),
 2876     FUSE_LIB_OPT("kernel_cache",          kernel_cache, 1),
 2877 #ifdef __SOLARIS__
 2878     FUSE_LIB_OPT("auto_cache",            auto_cache, 1),
 2879     FUSE_LIB_OPT("noauto_cache",          auto_cache, 0),
 2880 #endif /* __SOLARIS__ */
 2881     FUSE_LIB_OPT("umask=",                set_mode, 1),
 2882     FUSE_LIB_OPT("umask=%o",              umask, 0),
 2883     FUSE_LIB_OPT("uid=",                  set_uid, 1),
 2884     FUSE_LIB_OPT("uid=%d",                uid, 0),
 2885     FUSE_LIB_OPT("gid=",                  set_gid, 1),
 2886     FUSE_LIB_OPT("gid=%d",                gid, 0),
 2887     FUSE_LIB_OPT("entry_timeout=%lf",     entry_timeout, 0),
 2888     FUSE_LIB_OPT("attr_timeout=%lf",      attr_timeout, 0),
 2889     FUSE_LIB_OPT("ac_attr_timeout=%lf",   ac_attr_timeout, 0),
 2890     FUSE_LIB_OPT("ac_attr_timeout=",      ac_attr_timeout_set, 1),
 2891     FUSE_LIB_OPT("negative_timeout=%lf",  negative_timeout, 0),
 2892     FUSE_LIB_OPT("intr",                  intr, 1),
 2893     FUSE_LIB_OPT("intr_signal=%d",        intr_signal, 0),
 2894 #ifdef __SOLARIS__
 2895     FUSE_LIB_OPT("modules=%s",            modules, 0),
 2896 #endif /* __SOLARIS__ */
 2897     FUSE_OPT_END
 2898 };
 2899 
 2900 static void fuse_lib_help(void)
 2901 {
 2902     fprintf(stderr,
 2903 "    -o hard_remove         immediate removal (don't hide files)\n"
 2904 "    -o use_ino             let filesystem set inode numbers\n"
 2905 "    -o readdir_ino         try to fill in d_ino in readdir\n"
 2906 "    -o direct_io           use direct I/O\n"
 2907 "    -o kernel_cache        cache files in kernel\n"
 2908 #ifdef __SOLARIS__
 2909 "    -o [no]auto_cache      enable caching based on modification times (off)\n"
 2910 #endif /* __SOLARIS__ */
 2911 "    -o umask=M             set file permissions (octal)\n"
 2912 "    -o uid=N               set file owner\n"
 2913 "    -o gid=N               set file group\n"
 2914 "    -o entry_timeout=T     cache timeout for names (1.0s)\n"
 2915 "    -o negative_timeout=T  cache timeout for deleted names (0.0s)\n"
 2916 "    -o attr_timeout=T      cache timeout for attributes (1.0s)\n"
 2917 "    -o ac_attr_timeout=T   auto cache timeout for attributes (attr_timeout)\n"
 2918 "    -o intr                allow requests to be interrupted\n"
 2919 "    -o intr_signal=NUM     signal to send on interrupt (%i)\n"
 2920 #ifdef __SOLARIS__
 2921 "    -o modules=M1[:M2...]  names of modules to push onto filesystem stack\n"
 2922 #endif /* __SOLARIS__ */
 2923 "\n", FUSE_DEFAULT_INTR_SIGNAL);
 2924 }
 2925 
 2926 #ifdef __SOLARIS__
 2927 
 2928 static void fuse_lib_help_modules(void)
 2929 {
 2930     struct fuse_module *m;
 2931     fprintf(stderr, "\nModule options:\n");
 2932     pthread_mutex_lock(&fuse_context_lock);
 2933     for (m = fuse_modules; m; m = m->next) {
 2934         struct fuse_fs *fs = NULL;
 2935         struct fuse_fs *newfs;
 2936         struct fuse_args args = FUSE_ARGS_INIT(0, NULL);
 2937         if (fuse_opt_add_arg(&args, "") != -1 &&
 2938             fuse_opt_add_arg(&args, "-h") != -1) {
 2939             fprintf(stderr, "\n[%s]\n", m->name);
 2940             newfs = m->factory(&args, &fs);
 2941             assert(newfs == NULL);
 2942         }
 2943         fuse_opt_free_args(&args);
 2944     }
 2945     pthread_mutex_unlock(&fuse_context_lock);
 2946 }
 2947 
 2948 int fuse_is_lib_option(const char *opt)
 2949 {
 2950     return fuse_lowlevel_is_lib_option(opt) ||
 2951         fuse_opt_match(fuse_lib_opts, opt);
 2952 }
 2953 
 2954 #endif /* __SOLARIS__ */
 2955 
 2956 static int fuse_lib_opt_proc(void *data, const char *arg, int key,
 2957                              struct fuse_args *outargs)
 2958 {
 2959     (void) arg; (void) outargs;
 2960 
 2961     if (key == KEY_HELP) {
 2962         struct fuse_config *conf = (struct fuse_config *) data;
 2963         fuse_lib_help();
 2964         conf->help = 1;
 2965     }
 2966 
 2967     return 1;
 2968 }
 2969 
 2970 static int fuse_init_intr_signal(int signum, int *installed)
 2971 {
 2972     struct sigaction old_sa;
 2973 
 2974     if (sigaction(signum, NULL, &old_sa) == -1) {
 2975         perror("fuse: cannot get old signal handler");
 2976         return -1;
 2977     }
 2978 
 2979     if (old_sa.sa_handler == SIG_DFL) {
 2980         struct sigaction sa;
 2981 
 2982         memset(&sa, 0, sizeof(struct sigaction));
 2983         sa.sa_handler = fuse_intr_sighandler;
 2984         sigemptyset(&sa.sa_mask);
 2985 
 2986         if (sigaction(signum, &sa, NULL) == -1) {
 2987             perror("fuse: cannot set interrupt signal handler");
 2988             return -1;
 2989         }
 2990         *installed = 1;
 2991     }
 2992     return 0;
 2993 }
 2994 
 2995 static void fuse_restore_intr_signal(int signum)
 2996 {
 2997     struct sigaction sa;
 2998 
 2999     memset(&sa, 0, sizeof(struct sigaction));
 3000     sa.sa_handler = SIG_DFL;
 3001     sigaction(signum, &sa, NULL);
 3002 }
 3003 
 3004 #ifdef __SOLARIS__
 3005 
 3006 static int fuse_push_module(struct fuse *f, const char *module,
 3007                             struct fuse_args *args)
 3008 {
 3009     struct fuse_fs *newfs;
 3010     struct fuse_module *m = fuse_get_module(module);
 3011     struct fuse_fs *fs[2];
 3012 
 3013     fs[0] = f->fs;
 3014     fs[1] = NULL;
 3015     if (!m)
 3016         return -1;
 3017 
 3018     newfs = m->factory(args, fs);
 3019     if (!newfs) {
 3020         fuse_put_module(m);
 3021         return -1;
 3022     }
 3023     newfs->m = m;
 3024     f->fs = newfs;
 3025     return 0;
 3026 }
 3027 
 3028 #endif /* __SOLARIS__ */
 3029 
 3030 struct fuse_fs *fuse_fs_new(const struct fuse_operations *op, size_t op_size,
 3031                             void *user_data)
 3032 {
 3033     struct fuse_fs *fs;
 3034 
 3035     if (sizeof(struct fuse_operations) < op_size) {
 3036         fprintf(stderr, "fuse: warning: library too old, some operations may not not work\n");
 3037         op_size = sizeof(struct fuse_operations);
 3038     }
 3039 
 3040     fs = (struct fuse_fs *) calloc(1, sizeof(struct fuse_fs));
 3041     if (!fs) {
 3042         fprintf(stderr, "fuse: failed to allocate fuse_fs object\n");
 3043         return NULL;
 3044     }
 3045 
 3046     fs->user_data = user_data;
 3047     if (op)
 3048         memcpy(&fs->op, op, op_size);
 3049     return fs;
 3050 }
 3051 
 3052 struct fuse *fuse_new(struct fuse_chan *ch, struct fuse_args *args,
 3053               const struct fuse_operations *op, size_t op_size,
 3054               void *user_data)
 3055 {
 3056     struct fuse *f;
 3057     struct node *root;
 3058     struct fuse_fs *fs;
 3059     struct fuse_lowlevel_ops llop = fuse_path_ops;
 3060 
 3061     if (fuse_create_context_key() == -1)
 3062         goto out;
 3063 
 3064     f = (struct fuse *) calloc(1, sizeof(struct fuse));
 3065     if (f == NULL) {
 3066         fprintf(stderr, "fuse: failed to allocate fuse object\n");
 3067         goto out_delete_context_key;
 3068     }
 3069 
 3070     fs = fuse_fs_new(op, op_size, user_data);
 3071     if (!fs)
 3072         goto out_free;
 3073 
 3074     f->fs = fs;
 3075 
 3076     /* Oh f**k, this is ugly! */
 3077     if (!fs->op.lock) {
 3078         llop.getlk = NULL;
 3079         llop.setlk = NULL;
 3080     }
 3081 
 3082     f->conf.entry_timeout = 1.0;
 3083     f->conf.attr_timeout = 1.0;
 3084     f->conf.negative_timeout = 0.0;
 3085     f->conf.intr_signal = FUSE_DEFAULT_INTR_SIGNAL;
 3086 
 3087     if (fuse_opt_parse(args, &f->conf, fuse_lib_opts, fuse_lib_opt_proc) == -1)
 3088         goto out_free_fs;
 3089 
 3090 #ifdef __SOLARIS__
 3091     if (f->conf.modules) {
 3092         char *module;
 3093         char *next;
 3094 
 3095         for (module = f->conf.modules; module; module = next) {
 3096             char *p;
 3097             for (p = module; *p && *p != ':'; p++);
 3098             next = *p ? p + 1 : NULL;
 3099             *p = '\0';
 3100             if (module[0] && fuse_push_module(f, module, args) == -1)
 3101                 goto out_free_fs;
 3102         }
 3103     }
 3104 #endif /* __SOLARIS__ */
 3105 
 3106     if (!f->conf.ac_attr_timeout_set)
 3107         f->conf.ac_attr_timeout = f->conf.attr_timeout;
 3108 
 3109 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
 3110     /*
 3111      * In FreeBSD, we always use these settings as inode numbers are needed to
 3112      * make getcwd(3) work.
 3113      */
 3114     f->conf.readdir_ino = 1;
 3115 #endif
 3116 
 3117     f->se = fuse_lowlevel_new(args, &llop, sizeof(llop), f);
 3118 
 3119     if (f->se == NULL) {
 3120 #ifdef __SOLARIS__
 3121         if (f->conf.help)
 3122             fuse_lib_help_modules();
 3123 #endif /* __SOLARIS__ */
 3124         goto out_free_fs;
 3125     }
 3126 
 3127     fuse_session_add_chan(f->se, ch);
 3128 
 3129     f->ctr = 0;
 3130     f->generation = 0;
 3131     /* FIXME: Dynamic hash table */
 3132     f->name_table_size = 14057;
 3133     f->name_table = (struct node **)
 3134         calloc(1, sizeof(struct node *) * f->name_table_size);
 3135     if (f->name_table == NULL) {
 3136         fprintf(stderr, "fuse: memory allocation failed\n");
 3137         goto out_free_session;
 3138     }
 3139 
 3140     f->id_table_size = 14057;
 3141     f->id_table = (struct node **)
 3142         calloc(1, sizeof(struct node *) * f->id_table_size);
 3143     if (f->id_table == NULL) {
 3144         fprintf(stderr, "fuse: memory allocation failed\n");
 3145         goto out_free_name_table;
 3146     }
 3147 
 3148     fuse_mutex_init(&f->lock);
 3149     pthread_rwlock_init(&f->tree_lock, NULL);
 3150 
 3151     root = (struct node *) calloc(1, sizeof(struct node));
 3152     if (root == NULL) {
 3153         fprintf(stderr, "fuse: memory allocation failed\n");
 3154         goto out_free_id_table;
 3155     }
 3156 
 3157     root->name = strdup("/");
 3158     if (root->name == NULL) {
 3159         fprintf(stderr, "fuse: memory allocation failed\n");
 3160         goto out_free_root;
 3161     }
 3162 
 3163     if (f->conf.intr &&
 3164         fuse_init_intr_signal(f->conf.intr_signal, &f->intr_installed) == -1)
 3165         goto out_free_root_name;
 3166 
 3167     root->parent = NULL;
 3168     root->nodeid = FUSE_ROOT_ID;
 3169     root->generation = 0;
 3170     root->refctr = 1;
 3171     root->nlookup = 1;
 3172     hash_id(f, root);
 3173 
 3174     return f;
 3175 
 3176  out_free_root_name:
 3177     free(root->name);
 3178  out_free_root:
 3179     free(root);
 3180  out_free_id_table:
 3181     free(f->id_table);
 3182  out_free_name_table:
 3183     free(f->name_table);
 3184  out_free_session:
 3185     fuse_session_destroy(f->se);
 3186  out_free_fs:
 3187     /* Horrible compatibility hack to stop the destructor from being
 3188        called on the filesystem without init being called first */
 3189     fs->op.destroy = NULL;
 3190     fuse_fs_destroy(f->fs);
 3191 #ifdef __SOLARIS__
 3192     free(f->conf.modules);
 3193 #endif /* __SOLARIS__ */
 3194  out_free:
 3195     free(f);
 3196  out_delete_context_key:
 3197     fuse_delete_context_key();
 3198  out:
 3199     return NULL;
 3200 }
 3201 
 3202 void fuse_destroy(struct fuse *f)
 3203 {
 3204     size_t i;
 3205 
 3206     if (f->conf.intr && f->intr_installed)
 3207         fuse_restore_intr_signal(f->conf.intr_signal);
 3208 
 3209     if (f->fs) {
 3210         struct fuse_context_i *c = fuse_get_context_internal();
 3211 
 3212         memset(c, 0, sizeof(*c));
 3213         c->ctx.fuse = f;
 3214 
 3215         for (i = 0; i < f->id_table_size; i++) {
 3216             struct node *node;
 3217 
 3218             for (node = f->id_table[i]; node != NULL; node = node->id_next) {
 3219                 if (node->is_hidden) {
 3220                     char *path = get_path(f, node->nodeid);
 3221                     if (path) {
 3222                         fuse_fs_unlink(f->fs, path);
 3223                         free(path);
 3224                     }
 3225                 }
 3226             }
 3227         }
 3228     }
 3229     for (i = 0; i < f->id_table_size; i++) {
 3230         struct node *node;
 3231         struct node *next;
 3232 
 3233         for (node = f->id_table[i]; node != NULL; node = next) {
 3234             next = node->id_next;
 3235             free_node(node);
 3236         }
 3237     }
 3238     free(f->id_table);
 3239     free(f->name_table);
 3240     pthread_mutex_destroy(&f->lock);
 3241     pthread_rwlock_destroy(&f->tree_lock);
 3242     fuse_session_destroy(f->se);
 3243 #ifdef __SOLARIS__
 3244     free(f->conf.modules);
 3245 #endif /* __SOLARIS__ */
 3246     free(f);
 3247     fuse_delete_context_key();
 3248 }