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