16#include "fuse_config.h"
18#include "fuse_lowlevel.h"
21#include "fuse_kernel.h"
45#define FUSE_NODE_SLAB 1
51#ifndef RENAME_EXCHANGE
52#define RENAME_EXCHANGE (1 << 1)
55#define FUSE_DEFAULT_INTR_SIGNAL SIGUSR1
57#define FUSE_UNKNOWN_INO 0xffffffff
58#define OFFSET_MAX 0x7fffffffffffffffLL
60#define NODE_TABLE_MIN_SIZE 8192
73struct lock_queue_element {
74 struct lock_queue_element *next;
95#define list_entry(ptr, type, member) \
96 container_of(ptr, type, member)
99 struct list_head *next;
100 struct list_head *prev;
104 struct list_head list;
105 struct list_head freelist;
110 struct fuse_session *se;
111 struct node_table name_table;
112 struct node_table id_table;
113 struct list_head lru_table;
115 unsigned int generation;
116 unsigned int hidectr;
117 pthread_mutex_t lock;
121 struct lock_queue_element *lockq;
123 struct list_head partial_slabs;
124 struct list_head full_slabs;
125 pthread_t prune_thread;
138 struct node *name_next;
139 struct node *id_next;
141 unsigned int generation;
147 struct timespec stat_updated;
148 struct timespec mtime;
151 unsigned int is_hidden : 1;
152 unsigned int cache_valid : 1;
154 char inline_name[32];
157#define TREELOCK_WRITE -1
158#define TREELOCK_WAIT_OFFSET INT_MIN
162 struct list_head lru;
163 struct timespec forget_time;
166struct fuse_direntry {
170 struct fuse_direntry *next;
174 pthread_mutex_t lock;
178 struct fuse_direntry *first;
179 struct fuse_direntry **last;
189struct fuse_context_i {
200static pthread_key_t fuse_context_key;
201static pthread_mutex_t fuse_context_lock = PTHREAD_MUTEX_INITIALIZER;
202static int fuse_context_ref;
205static int fuse_register_module(
const char *name,
207 struct fusemod_so *so)
213 fuse_log(FUSE_LOG_ERR,
"fuse: failed to allocate module\n");
216 mod->name = strdup(name);
218 fuse_log(FUSE_LOG_ERR,
"fuse: failed to allocate module name\n");
222 mod->factory = factory;
227 mod->next = fuse_modules;
233static void fuse_unregister_module(
struct fuse_module *m)
236 for (mp = &fuse_modules; *mp; mp = &(*mp)->next) {
246static int fuse_load_so_module(
const char *module)
250 struct fusemod_so *so;
253 tmp = malloc(strlen(module) + 64);
255 fuse_log(FUSE_LOG_ERR,
"fuse: memory allocation failed\n");
258 sprintf(tmp,
"libfusemod_%s.so", module);
259 so = calloc(1,
sizeof(
struct fusemod_so));
261 fuse_log(FUSE_LOG_ERR,
"fuse: failed to allocate module so\n");
265 so->handle = dlopen(tmp, RTLD_NOW);
266 if (so->handle == NULL) {
267 fuse_log(FUSE_LOG_ERR,
"fuse: dlopen(%s) failed: %s\n",
272 sprintf(tmp,
"fuse_module_%s_factory", module);
274 if (factory == NULL) {
275 fuse_log(FUSE_LOG_ERR,
"fuse: symbol <%s> not found in module: %s\n",
279 ret = fuse_register_module(module, *factory, so);
294static struct fuse_module *fuse_find_module(
const char *module)
297 for (m = fuse_modules; m; m = m->next) {
298 if (strcmp(module, m->name) == 0) {
306static struct fuse_module *fuse_get_module(
const char *module)
310 pthread_mutex_lock(&fuse_context_lock);
311 m = fuse_find_module(module);
313 int err = fuse_load_so_module(module);
315 m = fuse_find_module(module);
317 pthread_mutex_unlock(&fuse_context_lock);
323 pthread_mutex_lock(&fuse_context_lock);
329 if (!m->ctr && m->so) {
330 struct fusemod_so *so = m->so;
335 for (mp = &fuse_modules; *mp;) {
337 fuse_unregister_module(*mp);
344 }
else if (!m->ctr) {
345 fuse_unregister_module(m);
347 pthread_mutex_unlock(&fuse_context_lock);
350static void init_list_head(
struct list_head *list)
356static int list_empty(
const struct list_head *head)
358 return head->next == head;
361static void list_add(
struct list_head *
new,
struct list_head *prev,
362 struct list_head *next)
370static inline void list_add_head(
struct list_head *
new,
struct list_head *head)
372 list_add(
new, head, head->next);
375static inline void list_add_tail(
struct list_head *
new,
struct list_head *head)
377 list_add(
new, head->prev, head);
380static inline void list_del(
struct list_head *entry)
382 struct list_head *prev = entry->prev;
383 struct list_head *next = entry->next;
389static inline int lru_enabled(
struct fuse *f)
391 return f->conf.remember > 0;
394static struct node_lru *node_lru(
struct node *node)
396 return (
struct node_lru *) node;
399static size_t get_node_size(
struct fuse *f)
402 return sizeof(
struct node_lru);
404 return sizeof(
struct node);
408static struct node_slab *list_to_slab(
struct list_head *head)
410 return (
struct node_slab *) head;
413static struct node_slab *node_to_slab(
struct fuse *f,
struct node *node)
415 return (
struct node_slab *) (((uintptr_t) node) & ~((uintptr_t) f->pagesize - 1));
418static int alloc_slab(
struct fuse *f)
421 struct node_slab *slab;
425 size_t node_size = get_node_size(f);
427 mem = mmap(NULL, f->pagesize, PROT_READ | PROT_WRITE,
428 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
430 if (mem == MAP_FAILED)
434 init_list_head(&slab->freelist);
436 num = (f->pagesize -
sizeof(
struct node_slab)) / node_size;
438 start = (
char *) mem + f->pagesize - num * node_size;
439 for (i = 0; i < num; i++) {
442 n = (
struct list_head *) (start + i * node_size);
443 list_add_tail(n, &slab->freelist);
445 list_add_tail(&slab->list, &f->partial_slabs);
450static struct node *alloc_node(
struct fuse *f)
452 struct node_slab *slab;
453 struct list_head *node;
455 if (list_empty(&f->partial_slabs)) {
456 int res = alloc_slab(f);
460 slab = list_to_slab(f->partial_slabs.next);
462 node = slab->freelist.next;
464 if (list_empty(&slab->freelist)) {
465 list_del(&slab->list);
466 list_add_tail(&slab->list, &f->full_slabs);
468 memset(node, 0,
sizeof(
struct node));
470 return (
struct node *) node;
473static void free_slab(
struct fuse *f,
struct node_slab *slab)
477 list_del(&slab->list);
478 res = munmap(slab, f->pagesize);
480 fuse_log(FUSE_LOG_WARNING,
"fuse warning: munmap(%p) failed\n",
484static void free_node_mem(
struct fuse *f,
struct node *node)
486 struct node_slab *slab = node_to_slab(f, node);
487 struct list_head *n = (
struct list_head *) node;
491 if (list_empty(&slab->freelist)) {
492 list_del(&slab->list);
493 list_add_tail(&slab->list, &f->partial_slabs);
495 list_add_head(n, &slab->freelist);
501static struct node *alloc_node(
struct fuse *f)
503 return (
struct node *) calloc(1, get_node_size(f));
506static void free_node_mem(
struct fuse *f,
struct node *node)
513static size_t id_hash(
struct fuse *f,
fuse_ino_t ino)
515 uint64_t hash = ((uint32_t) ino * 2654435761U) % f->id_table.size;
516 uint64_t oldhash = hash % (f->id_table.size / 2);
518 if (oldhash >= f->id_table.split)
524static struct node *get_node_nocheck(
struct fuse *f,
fuse_ino_t nodeid)
526 size_t hash = id_hash(f, nodeid);
529 for (node = f->id_table.array[hash]; node != NULL; node = node->id_next)
530 if (node->nodeid == nodeid)
536static struct node *get_node(
struct fuse *f,
fuse_ino_t nodeid)
538 struct node *node = get_node_nocheck(f, nodeid);
540 fuse_log(FUSE_LOG_ERR,
"fuse internal error: node %llu not found\n",
541 (
unsigned long long) nodeid);
547static void curr_time(
struct timespec *now);
548static double diff_timespec(
const struct timespec *t1,
549 const struct timespec *t2);
551static void remove_node_lru(
struct node *node)
553 struct node_lru *lnode = node_lru(node);
554 list_del(&lnode->lru);
555 init_list_head(&lnode->lru);
558static void set_forget_time(
struct fuse *f,
struct node *node)
560 struct node_lru *lnode = node_lru(node);
562 list_del(&lnode->lru);
563 list_add_tail(&lnode->lru, &f->lru_table);
564 curr_time(&lnode->forget_time);
567static void free_node(
struct fuse *f,
struct node *node)
569 if (node->name != node->inline_name)
571 free_node_mem(f, node);
574static void node_table_reduce(
struct node_table *t)
576 size_t newsize = t->size / 2;
579 if (newsize < NODE_TABLE_MIN_SIZE)
582 newarray = realloc(t->array,
sizeof(
struct node *) * newsize);
583 if (newarray != NULL)
587 t->split = t->size / 2;
590static void remerge_id(
struct fuse *f)
592 struct node_table *t = &f->id_table;
596 node_table_reduce(t);
598 for (iter = 8; t->split > 0 && iter; iter--) {
602 upper = &t->array[t->split + t->size / 2];
606 for (nodep = &t->array[t->split]; *nodep;
607 nodep = &(*nodep)->id_next);
616static void unhash_id(
struct fuse *f,
struct node *node)
618 struct node **nodep = &f->id_table.array[id_hash(f, node->nodeid)];
620 for (; *nodep != NULL; nodep = &(*nodep)->id_next)
621 if (*nodep == node) {
622 *nodep = node->id_next;
625 if(f->id_table.use < f->id_table.size / 4)
631static int node_table_resize(
struct node_table *t)
633 size_t newsize = t->size * 2;
636 newarray = realloc(t->array,
sizeof(
struct node *) * newsize);
637 if (newarray == NULL)
641 memset(t->array + t->size, 0, t->size *
sizeof(
struct node *));
648static void rehash_id(
struct fuse *f)
650 struct node_table *t = &f->id_table;
655 if (t->split == t->size / 2)
660 for (nodep = &t->array[hash]; *nodep != NULL; nodep = next) {
661 struct node *node = *nodep;
662 size_t newhash = id_hash(f, node->nodeid);
664 if (newhash != hash) {
666 *nodep = node->id_next;
667 node->id_next = t->array[newhash];
668 t->array[newhash] = node;
670 next = &node->id_next;
673 if (t->split == t->size / 2)
674 node_table_resize(t);
677static void hash_id(
struct fuse *f,
struct node *node)
679 size_t hash = id_hash(f, node->nodeid);
680 node->id_next = f->id_table.array[hash];
681 f->id_table.array[hash] = node;
684 if (f->id_table.use >= f->id_table.size / 2)
688static size_t name_hash(
struct fuse *f,
fuse_ino_t parent,
691 uint64_t hash = parent;
694 for (; *name; name++)
695 hash = hash * 31 + (
unsigned char) *name;
697 hash %= f->name_table.size;
698 oldhash = hash % (f->name_table.size / 2);
699 if (oldhash >= f->name_table.split)
705static void unref_node(
struct fuse *f,
struct node *node);
707static void remerge_name(
struct fuse *f)
709 struct node_table *t = &f->name_table;
713 node_table_reduce(t);
715 for (iter = 8; t->split > 0 && iter; iter--) {
719 upper = &t->array[t->split + t->size / 2];
723 for (nodep = &t->array[t->split]; *nodep;
724 nodep = &(*nodep)->name_next);
733static void unhash_name(
struct fuse *f,
struct node *node)
736 size_t hash = name_hash(f, node->parent->nodeid, node->name);
737 struct node **nodep = &f->name_table.array[hash];
739 for (; *nodep != NULL; nodep = &(*nodep)->name_next)
740 if (*nodep == node) {
741 *nodep = node->name_next;
742 node->name_next = NULL;
743 unref_node(f, node->parent);
744 if (node->name != node->inline_name)
750 if (f->name_table.use < f->name_table.size / 4)
755 "fuse internal error: unable to unhash node: %llu\n",
756 (
unsigned long long) node->nodeid);
761static void rehash_name(
struct fuse *f)
763 struct node_table *t = &f->name_table;
768 if (t->split == t->size / 2)
773 for (nodep = &t->array[hash]; *nodep != NULL; nodep = next) {
774 struct node *node = *nodep;
775 size_t newhash = name_hash(f, node->parent->nodeid, node->name);
777 if (newhash != hash) {
779 *nodep = node->name_next;
780 node->name_next = t->array[newhash];
781 t->array[newhash] = node;
783 next = &node->name_next;
786 if (t->split == t->size / 2)
787 node_table_resize(t);
790static int hash_name(
struct fuse *f,
struct node *node,
fuse_ino_t parentid,
793 size_t hash = name_hash(f, parentid, name);
794 struct node *parent = get_node(f, parentid);
795 if (strlen(name) <
sizeof(node->inline_name)) {
796 strcpy(node->inline_name, name);
797 node->name = node->inline_name;
799 node->name = strdup(name);
800 if (node->name == NULL)
805 node->parent = parent;
806 node->name_next = f->name_table.array[hash];
807 f->name_table.array[hash] = node;
810 if (f->name_table.use >= f->name_table.size / 2)
816static void delete_node(
struct fuse *f,
struct node *node)
819 fuse_log(FUSE_LOG_DEBUG,
"DELETE: %llu\n",
820 (
unsigned long long) node->nodeid);
822 assert(node->treelock == 0);
823 unhash_name(f, node);
825 remove_node_lru(node);
830static void unref_node(
struct fuse *f,
struct node *node)
832 assert(node->refctr > 0);
835 delete_node(f, node);
841 f->ctr = (f->ctr + 1) & 0xffffffff;
844 }
while (f->ctr == 0 || f->ctr == FUSE_UNKNOWN_INO ||
845 get_node_nocheck(f, f->ctr) != NULL);
849static struct node *lookup_node(
struct fuse *f,
fuse_ino_t parent,
852 size_t hash = name_hash(f, parent, name);
855 for (node = f->name_table.array[hash]; node != NULL; node = node->name_next)
856 if (node->parent->nodeid == parent &&
857 strcmp(node->name, name) == 0)
863static void inc_nlookup(
struct node *node)
870static struct node *find_node(
struct fuse *f,
fuse_ino_t parent,
875 pthread_mutex_lock(&f->lock);
877 node = get_node(f, parent);
879 node = lookup_node(f, parent, name);
881 node = alloc_node(f);
885 node->nodeid = next_id(f);
886 node->generation = f->generation;
887 if (f->conf.remember)
890 if (hash_name(f, node, parent, name) == -1) {
896 if (lru_enabled(f)) {
897 struct node_lru *lnode = node_lru(node);
898 init_list_head(&lnode->lru);
900 }
else if (lru_enabled(f) && node->nlookup == 1) {
901 remove_node_lru(node);
905 pthread_mutex_unlock(&f->lock);
909static int lookup_path_in_cache(
struct fuse *f,
912 char *tmp = strdup(path);
916 pthread_mutex_lock(&f->lock);
921 char *path_element = strtok_r(tmp,
"/", &save_ptr);
922 while (path_element != NULL) {
923 struct node *node = lookup_node(f, ino, path_element);
929 path_element = strtok_r(NULL,
"/", &save_ptr);
931 pthread_mutex_unlock(&f->lock);
939static char *add_name(
char **buf,
unsigned *bufsize,
char *s,
const char *name)
941 size_t len = strlen(name);
943 if (s - len <= *buf) {
944 unsigned pathlen = *bufsize - (s - *buf);
945 unsigned newbufsize = *bufsize;
948 while (newbufsize < pathlen + len + 1) {
949 if (newbufsize >= 0x80000000)
950 newbufsize = 0xffffffff;
955 newbuf = realloc(*buf, newbufsize);
960 s = newbuf + newbufsize - pathlen;
961 memmove(s, newbuf + *bufsize - pathlen, pathlen);
962 *bufsize = newbufsize;
965 memcpy(s, name, len);
972static void unlock_path(
struct fuse *f,
fuse_ino_t nodeid,
struct node *wnode,
978 assert(wnode->treelock == TREELOCK_WRITE);
982 for (node = get_node(f, nodeid);
983 node != end && node->nodeid != FUSE_ROOT_ID; node = node->parent) {
984 assert(node->treelock != 0);
985 assert(node->treelock != TREELOCK_WAIT_OFFSET);
986 assert(node->treelock != TREELOCK_WRITE);
988 if (node->treelock == TREELOCK_WAIT_OFFSET)
993static int try_get_path(
struct fuse *f,
fuse_ino_t nodeid,
const char *name,
994 char **path,
struct node **wnodep,
bool need_lock)
996 unsigned bufsize = 256;
1000 struct node *wnode = NULL;
1006 buf = malloc(bufsize);
1010 s = buf + bufsize - 1;
1014 s = add_name(&buf, &bufsize, s, name);
1022 wnode = lookup_node(f, nodeid, name);
1024 if (wnode->treelock != 0) {
1025 if (wnode->treelock > 0)
1026 wnode->treelock += TREELOCK_WAIT_OFFSET;
1030 wnode->treelock = TREELOCK_WRITE;
1034 for (node = get_node(f, nodeid); node->nodeid != FUSE_ROOT_ID;
1035 node = node->parent) {
1037 if (node->name == NULL || node->parent == NULL)
1041 s = add_name(&buf, &bufsize, s, node->name);
1047 if (node->treelock < 0)
1055 memmove(buf, s, bufsize - (s - buf));
1067 unlock_path(f, nodeid, wnode, node);
1075static int try_get_path2(
struct fuse *f,
fuse_ino_t nodeid1,
const char *name1,
1077 char **path1,
char **path2,
1078 struct node **wnode1,
struct node **wnode2)
1083 err = try_get_path(f, nodeid1, name1, path1, wnode1,
true);
1085 err = try_get_path(f, nodeid2, name2, path2, wnode2,
true);
1087 struct node *wn1 = wnode1 ? *wnode1 : NULL;
1089 unlock_path(f, nodeid1, wn1, NULL);
1096static void queue_element_wakeup(
struct fuse *f,
struct lock_queue_element *qe)
1102 if (get_node(f, qe->nodeid1)->treelock == 0)
1103 pthread_cond_signal(&qe->cond);
1112 err = try_get_path(f, qe->nodeid1, qe->name1, qe->path1,
1115 err = try_get_path2(f, qe->nodeid1, qe->name1, qe->nodeid2,
1116 qe->name2, qe->path1, qe->path2, qe->wnode1,
1125 pthread_cond_signal(&qe->cond);
1128static void wake_up_queued(
struct fuse *f)
1130 struct lock_queue_element *qe;
1132 for (qe = f->lockq; qe != NULL; qe = qe->next)
1133 queue_element_wakeup(f, qe);
1136static void debug_path(
struct fuse *f,
const char *msg,
fuse_ino_t nodeid,
1137 const char *name,
bool wr)
1139 if (f->conf.debug) {
1140 struct node *wnode = NULL;
1143 wnode = lookup_node(f, nodeid, name);
1146 fuse_log(FUSE_LOG_DEBUG,
"%s %llu (w)\n",
1147 msg, (
unsigned long long) wnode->nodeid);
1149 fuse_log(FUSE_LOG_DEBUG,
"%s %llu\n",
1150 msg, (
unsigned long long) nodeid);
1155static void queue_path(
struct fuse *f,
struct lock_queue_element *qe)
1157 struct lock_queue_element **qp;
1160 pthread_cond_init(&qe->cond, NULL);
1162 for (qp = &f->lockq; *qp != NULL; qp = &(*qp)->next);
1166static void dequeue_path(
struct fuse *f,
struct lock_queue_element *qe)
1168 struct lock_queue_element **qp;
1170 pthread_cond_destroy(&qe->cond);
1171 for (qp = &f->lockq; *qp != qe; qp = &(*qp)->next);
1175static int wait_path(
struct fuse *f,
struct lock_queue_element *qe)
1180 pthread_cond_wait(&qe->cond, &f->lock);
1181 }
while (!qe->done);
1183 dequeue_path(f, qe);
1188static int get_path_common(
struct fuse *f,
fuse_ino_t nodeid,
const char *name,
1189 char **path,
struct node **wnode)
1193 pthread_mutex_lock(&f->lock);
1194 err = try_get_path(f, nodeid, name, path, wnode,
true);
1195 if (err == -EAGAIN) {
1196 struct lock_queue_element qe = {
1202 debug_path(f,
"QUEUE PATH", nodeid, name, !!wnode);
1203 err = wait_path(f, &qe);
1204 debug_path(f,
"DEQUEUE PATH", nodeid, name, !!wnode);
1206 pthread_mutex_unlock(&f->lock);
1211static int get_path(
struct fuse *f,
fuse_ino_t nodeid,
char **path)
1213 return get_path_common(f, nodeid, NULL, path, NULL);
1216static int get_path_nullok(
struct fuse *f,
fuse_ino_t nodeid,
char **path)
1220 if (f->conf.nullpath_ok) {
1223 err = get_path_common(f, nodeid, NULL, path, NULL);
1231static int get_path_name(
struct fuse *f,
fuse_ino_t nodeid,
const char *name,
1234 return get_path_common(f, nodeid, name, path, NULL);
1237static int get_path_wrlock(
struct fuse *f,
fuse_ino_t nodeid,
const char *name,
1238 char **path,
struct node **wnode)
1240 return get_path_common(f, nodeid, name, path, wnode);
1243#if defined(__FreeBSD__)
1244#define CHECK_DIR_LOOP
1247#if defined(CHECK_DIR_LOOP)
1248static int check_dir_loop(
struct fuse *f,
1252 struct node *node, *node1, *node2;
1255 node1 = lookup_node(f, nodeid1, name1);
1256 id1 = node1 ? node1->nodeid : nodeid1;
1258 node2 = lookup_node(f, nodeid2, name2);
1259 id2 = node2 ? node2->nodeid : nodeid2;
1261 for (node = get_node(f, id2); node->nodeid != FUSE_ROOT_ID;
1262 node = node->parent) {
1263 if (node->name == NULL || node->parent == NULL)
1266 if (node->nodeid != id2 && node->nodeid == id1)
1272 for (node = get_node(f, id1); node->nodeid != FUSE_ROOT_ID;
1273 node = node->parent) {
1274 if (node->name == NULL || node->parent == NULL)
1277 if (node->nodeid != id1 && node->nodeid == id2)
1286static int get_path2(
struct fuse *f,
fuse_ino_t nodeid1,
const char *name1,
1288 char **path1,
char **path2,
1289 struct node **wnode1,
struct node **wnode2)
1293 pthread_mutex_lock(&f->lock);
1295#if defined(CHECK_DIR_LOOP)
1299 err = check_dir_loop(f, nodeid1, name1, nodeid2, name2);
1305 err = try_get_path2(f, nodeid1, name1, nodeid2, name2,
1306 path1, path2, wnode1, wnode2);
1307 if (err == -EAGAIN) {
1308 struct lock_queue_element qe = {
1319 debug_path(f,
"QUEUE PATH1", nodeid1, name1, !!wnode1);
1320 debug_path(f,
" PATH2", nodeid2, name2, !!wnode2);
1321 err = wait_path(f, &qe);
1322 debug_path(f,
"DEQUEUE PATH1", nodeid1, name1, !!wnode1);
1323 debug_path(f,
" PATH2", nodeid2, name2, !!wnode2);
1326#if defined(CHECK_DIR_LOOP)
1329 pthread_mutex_unlock(&f->lock);
1334static void free_path_wrlock(
struct fuse *f,
fuse_ino_t nodeid,
1335 struct node *wnode,
char *path)
1337 pthread_mutex_lock(&f->lock);
1338 unlock_path(f, nodeid, wnode, NULL);
1341 pthread_mutex_unlock(&f->lock);
1345static void free_path(
struct fuse *f,
fuse_ino_t nodeid,
char *path)
1348 free_path_wrlock(f, nodeid, NULL, path);
1352 struct node *wnode1,
struct node *wnode2,
1353 char *path1,
char *path2)
1355 pthread_mutex_lock(&f->lock);
1356 unlock_path(f, nodeid1, wnode1, NULL);
1357 unlock_path(f, nodeid2, wnode2, NULL);
1359 pthread_mutex_unlock(&f->lock);
1364static void forget_node(
struct fuse *f,
fuse_ino_t nodeid, uint64_t nlookup)
1367 if (nodeid == FUSE_ROOT_ID)
1369 pthread_mutex_lock(&f->lock);
1370 node = get_node(f, nodeid);
1376 while (node->nlookup == nlookup && node->treelock) {
1377 struct lock_queue_element qe = {
1381 debug_path(f,
"QUEUE PATH (forget)", nodeid, NULL,
false);
1385 pthread_cond_wait(&qe.cond, &f->lock);
1386 }
while (node->nlookup == nlookup && node->treelock);
1388 dequeue_path(f, &qe);
1389 debug_path(f,
"DEQUEUE_PATH (forget)", nodeid, NULL,
false);
1392 assert(node->nlookup >= nlookup);
1393 node->nlookup -= nlookup;
1394 if (!node->nlookup) {
1395 unref_node(f, node);
1396 }
else if (lru_enabled(f) && node->nlookup == 1) {
1397 set_forget_time(f, node);
1399 pthread_mutex_unlock(&f->lock);
1402static void unlink_node(
struct fuse *f,
struct node *node)
1404 if (f->conf.remember) {
1405 assert(node->nlookup > 1);
1408 unhash_name(f, node);
1411static void remove_node(
struct fuse *f,
fuse_ino_t dir,
const char *name)
1415 pthread_mutex_lock(&f->lock);
1416 node = lookup_node(f, dir, name);
1418 unlink_node(f, node);
1419 pthread_mutex_unlock(&f->lock);
1422static int rename_node(
struct fuse *f,
fuse_ino_t olddir,
const char *oldname,
1423 fuse_ino_t newdir,
const char *newname,
int hide)
1426 struct node *newnode;
1429 pthread_mutex_lock(&f->lock);
1430 node = lookup_node(f, olddir, oldname);
1431 newnode = lookup_node(f, newdir, newname);
1435 if (newnode != NULL) {
1437 fuse_log(FUSE_LOG_ERR,
"fuse: hidden file got created during hiding\n");
1441 unlink_node(f, newnode);
1444 unhash_name(f, node);
1445 if (hash_name(f, node, newdir, newname) == -1) {
1451 node->is_hidden = 1;
1454 pthread_mutex_unlock(&f->lock);
1458static int exchange_node(
struct fuse *f,
fuse_ino_t olddir,
const char *oldname,
1461 struct node *oldnode;
1462 struct node *newnode;
1465 pthread_mutex_lock(&f->lock);
1466 oldnode = lookup_node(f, olddir, oldname);
1467 newnode = lookup_node(f, newdir, newname);
1470 unhash_name(f, oldnode);
1472 unhash_name(f, newnode);
1476 if (hash_name(f, oldnode, newdir, newname) == -1)
1480 if (hash_name(f, newnode, olddir, oldname) == -1)
1485 pthread_mutex_unlock(&f->lock);
1489static void set_stat(
struct fuse *f,
fuse_ino_t nodeid,
struct stat *stbuf)
1491 if (!f->conf.use_ino)
1492 stbuf->st_ino = nodeid;
1493 if (f->conf.set_mode) {
1494 if (f->conf.dmask && S_ISDIR(stbuf->st_mode))
1495 stbuf->st_mode = (stbuf->st_mode & S_IFMT) |
1496 (0777 & ~f->conf.dmask);
1497 else if (f->conf.fmask)
1498 stbuf->st_mode = (stbuf->st_mode & S_IFMT) |
1499 (0777 & ~f->conf.fmask);
1501 stbuf->st_mode = (stbuf->st_mode & S_IFMT) |
1502 (0777 & ~f->conf.umask);
1504 if (f->conf.set_uid)
1505 stbuf->st_uid = f->conf.uid;
1506 if (f->conf.set_gid)
1507 stbuf->st_gid = f->conf.gid;
1511static void set_statx(
struct fuse *f,
fuse_ino_t nodeid,
struct statx *stxbuf)
1513 if (!f->conf.use_ino)
1514 stxbuf->stx_ino = nodeid;
1515 if (f->conf.set_mode) {
1516 if (f->conf.dmask && S_ISDIR(stxbuf->stx_mode))
1517 stxbuf->stx_mode = (stxbuf->stx_mode & S_IFMT) |
1518 (0777 & ~f->conf.dmask);
1519 else if (f->conf.fmask)
1520 stxbuf->stx_mode = (stxbuf->stx_mode & S_IFMT) |
1521 (0777 & ~f->conf.fmask);
1523 stxbuf->stx_mode = (stxbuf->stx_mode & S_IFMT) |
1524 (0777 & ~f->conf.umask);
1526 if (f->conf.set_uid)
1527 stxbuf->stx_uid = f->conf.uid;
1528 if (f->conf.set_gid)
1529 stxbuf->stx_gid = f->conf.gid;
1538static void fuse_intr_sighandler(
int sig)
1544struct fuse_intr_data {
1546 pthread_cond_t cond;
1550static void fuse_interrupt(
fuse_req_t req,
void *d_)
1552 struct fuse_intr_data *d = d_;
1553 struct fuse *f = req_fuse(req);
1555 if (d->id == pthread_self())
1558 pthread_mutex_lock(&f->lock);
1559 while (!d->finished) {
1561 struct timespec timeout;
1563 pthread_kill(d->id, f->conf.intr_signal);
1564 gettimeofday(&now, NULL);
1565 timeout.tv_sec = now.tv_sec + 1;
1566 timeout.tv_nsec = now.tv_usec * 1000;
1567 pthread_cond_timedwait(&d->cond, &f->lock, &timeout);
1569 pthread_mutex_unlock(&f->lock);
1572static void fuse_do_finish_interrupt(
struct fuse *f,
fuse_req_t req,
1573 struct fuse_intr_data *d)
1575 pthread_mutex_lock(&f->lock);
1577 pthread_cond_broadcast(&d->cond);
1578 pthread_mutex_unlock(&f->lock);
1580 pthread_cond_destroy(&d->cond);
1583static void fuse_do_prepare_interrupt(
fuse_req_t req,
struct fuse_intr_data *d)
1585 d->id = pthread_self();
1586 pthread_cond_init(&d->cond, NULL);
1591static inline void fuse_finish_interrupt(
struct fuse *f,
fuse_req_t req,
1592 struct fuse_intr_data *d)
1595 fuse_do_finish_interrupt(f, req, d);
1598static inline void fuse_prepare_interrupt(
struct fuse *f,
fuse_req_t req,
1599 struct fuse_intr_data *d)
1602 fuse_do_prepare_interrupt(req, d);
1606 char* buf,
size_t len)
1610 snprintf(buf, len,
"%llu", (
unsigned long long) fi->
fh);
1614int fuse_fs_getattr(
struct fuse_fs *fs,
const char *path,
struct stat *buf,
1618 if (!fs->op.getattr)
1624 fuse_log(FUSE_LOG_DEBUG,
"getattr[%s] %s\n",
1625 file_info_string(fi, buf,
sizeof(buf)),
1628 return fs->op.getattr(path, buf, fi);
1631int fuse_fs_rename(
struct fuse_fs *fs,
const char *oldpath,
1632 const char *newpath,
unsigned int flags)
1638 fuse_log(FUSE_LOG_DEBUG,
"rename %s %s 0x%x\n", oldpath, newpath,
1641 return fs->op.rename(oldpath, newpath, flags);
1644int fuse_fs_unlink(
struct fuse_fs *fs,
const char *path)
1650 fuse_log(FUSE_LOG_DEBUG,
"unlink %s\n", path);
1652 return fs->op.unlink(path);
1655int fuse_fs_rmdir(
struct fuse_fs *fs,
const char *path)
1661 fuse_log(FUSE_LOG_DEBUG,
"rmdir %s\n", path);
1663 return fs->op.rmdir(path);
1666int fuse_fs_symlink(
struct fuse_fs *fs,
const char *linkname,
const char *path)
1669 if (!fs->op.symlink)
1672 fuse_log(FUSE_LOG_DEBUG,
"symlink %s %s\n", linkname, path);
1674 return fs->op.symlink(linkname, path);
1677int fuse_fs_link(
struct fuse_fs *fs,
const char *oldpath,
const char *newpath)
1683 fuse_log(FUSE_LOG_DEBUG,
"link %s %s\n", oldpath, newpath);
1685 return fs->op.link(oldpath, newpath);
1688int fuse_fs_release(
struct fuse_fs *fs,
const char *path,
1692 if (!fs->op.release)
1696 fuse_log(FUSE_LOG_DEBUG,
"release%s[%llu] flags: 0x%x\n",
1697 fi->
flush ?
"+flush" :
"",
1698 (unsigned long long) fi->fh, fi->flags);
1700 return fs->op.release(path, fi);
1703int fuse_fs_opendir(
struct fuse_fs *fs,
const char *path,
1709 if (!fs->op.opendir)
1713 fuse_log(FUSE_LOG_DEBUG,
"opendir flags: 0x%x %s\n", fi->
flags,
1716 err = fs->op.opendir(path, fi);
1718 if (fs->debug && !err)
1719 fuse_log(FUSE_LOG_DEBUG,
" opendir[%llu] flags: 0x%x %s\n",
1720 (
unsigned long long) fi->
fh, fi->
flags, path);
1725int fuse_fs_open(
struct fuse_fs *fs,
const char *path,
1735 fuse_log(FUSE_LOG_DEBUG,
"open flags: 0x%x %s\n", fi->
flags,
1738 err = fs->op.open(path, fi);
1740 if (fs->debug && !err)
1741 fuse_log(FUSE_LOG_DEBUG,
" open[%llu] flags: 0x%x %s\n",
1742 (
unsigned long long) fi->
fh, fi->
flags, path);
1752 for (i = 0; i < buf->
count; i++)
1759int fuse_fs_read_buf(
struct fuse_fs *fs,
const char *path,
1760 struct fuse_bufvec **bufp,
size_t size, off_t off,
1766 if (!fs->op.read && !fs->op.read_buf)
1771 "read[%llu] %zu bytes from %llu flags: 0x%x\n",
1772 (
unsigned long long) fi->
fh,
1773 size, (
unsigned long long) off, fi->
flags);
1775 if (fs->op.read_buf) {
1776 res = fs->op.read_buf(path, bufp, size, off, fi);
1790 *
buf = FUSE_BUFVEC_INIT(size);
1794 res = fs->op.read(path, mem, size,
off, fi);
1799 if (fs->debug && res >= 0)
1800 fuse_log(FUSE_LOG_DEBUG,
" read[%llu] %zu bytes from %llu\n",
1801 (
unsigned long long) fi->
fh,
1803 (
unsigned long long)
off);
1805 fuse_log(FUSE_LOG_ERR,
"fuse: read too many bytes\n");
1813int fuse_fs_read(
struct fuse_fs *fs,
const char *path,
char *mem,
size_t size,
1819 if (!fs->op.read && !fs->op.read_buf)
1824 "read[%llu] %zu bytes from %llu flags: 0x%x\n",
1825 (
unsigned long long) fi->
fh,
1826 size, (
unsigned long long)
off, fi->
flags);
1828 if (fs->op.read_buf) {
1831 res = fs->op.read_buf(path, &
buf, size,
off, fi);
1840 res = fs->op.read(path, mem, size,
off, fi);
1843 if (fs->debug && res >= 0)
1844 fuse_log(FUSE_LOG_DEBUG,
" read[%llu] %u bytes from %llu\n",
1845 (
unsigned long long) fi->
fh,
1847 (
unsigned long long)
off);
1848 if (res >= 0 && res > (
int) size)
1849 fuse_log(FUSE_LOG_ERR,
"fuse: read too many bytes\n");
1854int fuse_fs_write_buf(
struct fuse_fs *fs,
const char *path,
1862 if (!fs->op.write_buf && !fs->op.write)
1866 assert(
buf->idx == 0 &&
buf->off == 0);
1869 "write%s[%llu] %zu bytes to %llu flags: 0x%x\n",
1871 (unsigned long long) fi->fh,
1873 (unsigned long long)
off,
1876 if (fs->op.write_buf) {
1877 res = fs->op.write_buf(path,
buf,
off, fi);
1883 if (
buf->count == 1 &&
1885 flatbuf = &
buf->buf[0];
1898 flatbuf = &tmp.
buf[0];
1901 res = fs->op.write(path, flatbuf->
mem, flatbuf->
size,
1907 if (fs->debug && res >= 0)
1908 fuse_log(FUSE_LOG_DEBUG,
" write%s[%llu] %u bytes to %llu\n",
1910 (unsigned long long) fi->fh, res,
1911 (unsigned long long)
off);
1912 if (res > (
int) size)
1913 fuse_log(FUSE_LOG_ERR,
"fuse: wrote too many bytes\n");
1918int fuse_fs_write(
struct fuse_fs *fs,
const char *path,
const char *mem,
1923 bufv.
buf[0].
mem = (
void *) mem;
1925 return fuse_fs_write_buf(fs, path, &bufv,
off, fi);
1928int fuse_fs_fsync(
struct fuse_fs *fs,
const char *path,
int datasync,
1936 fuse_log(FUSE_LOG_DEBUG,
"fsync[%llu] datasync: %i\n",
1937 (
unsigned long long) fi->
fh, datasync);
1939 return fs->op.fsync(path, datasync, fi);
1942int fuse_fs_fsyncdir(
struct fuse_fs *fs,
const char *path,
int datasync,
1946 if (!fs->op.fsyncdir)
1950 fuse_log(FUSE_LOG_DEBUG,
"fsyncdir[%llu] datasync: %i\n",
1951 (
unsigned long long) fi->
fh, datasync);
1953 return fs->op.fsyncdir(path, datasync, fi);
1956int fuse_fs_flush(
struct fuse_fs *fs,
const char *path,
1963 fuse_log(FUSE_LOG_DEBUG,
"flush[%llu]\n",
1964 (
unsigned long long) fi->
fh);
1966 return fs->op.flush(path, fi);
1969int fuse_fs_statfs(
struct fuse_fs *fs,
const char *path,
struct statvfs *
buf)
1972 if (fs->op.statfs) {
1974 fuse_log(FUSE_LOG_DEBUG,
"statfs %s\n", path);
1976 return fs->op.statfs(path,
buf);
1978 buf->f_namemax = 255;
1984int fuse_fs_releasedir(
struct fuse_fs *fs,
const char *path,
1988 if (!fs->op.releasedir)
1992 fuse_log(FUSE_LOG_DEBUG,
"releasedir[%llu] flags: 0x%x\n",
1993 (
unsigned long long) fi->
fh, fi->
flags);
1995 return fs->op.releasedir(path, fi);
1998int fuse_fs_readdir(
struct fuse_fs *fs,
const char *path,
void *
buf,
2004 if (!fs->op.readdir)
2007 fuse_log(FUSE_LOG_DEBUG,
"readdir%s[%llu] from %llu\n",
2008 (flags & FUSE_READDIR_PLUS) ?
"plus" :
"",
2009 (unsigned long long) fi->fh,
2010 (unsigned long long)
off);
2013 return fs->op.readdir(path,
buf, filler,
off, fi, flags);
2016int fuse_fs_create(
struct fuse_fs *fs,
const char *path, mode_t mode,
2027 "create flags: 0x%x %s 0%o umask=0%03o\n",
2028 fi->
flags, path, mode,
2031 err = fs->op.create(path, mode, fi);
2033 if (fs->debug && !err)
2034 fuse_log(FUSE_LOG_DEBUG,
" create[%llu] flags: 0x%x %s\n",
2035 (
unsigned long long) fi->
fh, fi->
flags, path);
2040int fuse_fs_lock(
struct fuse_fs *fs,
const char *path,
2048 fuse_log(FUSE_LOG_DEBUG,
"lock[%llu] %s %s start: %llu len: %llu pid: %llu\n",
2049 (
unsigned long long) fi->
fh,
2050 (cmd == F_GETLK ?
"F_GETLK" :
2051 (cmd == F_SETLK ?
"F_SETLK" :
2052 (cmd == F_SETLKW ?
"F_SETLKW" :
"???"))),
2053 (lock->l_type == F_RDLCK ?
"F_RDLCK" :
2054 (lock->l_type == F_WRLCK ?
"F_WRLCK" :
2055 (lock->l_type == F_UNLCK ?
"F_UNLCK" :
2057 (unsigned long long) lock->l_start,
2058 (unsigned long long) lock->l_len,
2059 (unsigned long long) lock->l_pid);
2061 return fs->op.lock(path, fi, cmd, lock);
2064int fuse_fs_flock(
struct fuse_fs *fs,
const char *path,
2072 int xop = op & ~LOCK_NB;
2074 fuse_log(FUSE_LOG_DEBUG,
"lock[%llu] %s%s\n",
2075 (
unsigned long long) fi->
fh,
2076 xop == LOCK_SH ?
"LOCK_SH" :
2077 (xop == LOCK_EX ?
"LOCK_EX" :
2078 (xop == LOCK_UN ?
"LOCK_UN" :
"???")),
2079 (op & LOCK_NB) ?
"|LOCK_NB" :
"");
2081 return fs->op.flock(path, fi, op);
2084int fuse_fs_chown(
struct fuse_fs *fs,
const char *path, uid_t uid,
2093 fuse_log(FUSE_LOG_DEBUG,
"chown[%s] %s %lu %lu\n",
2094 file_info_string(fi,
buf,
sizeof(
buf)),
2095 path, (
unsigned long) uid, (
unsigned long) gid);
2097 return fs->op.chown(path, uid, gid, fi);
2100int fuse_fs_truncate(
struct fuse_fs *fs,
const char *path, off_t size,
2104 if (!fs->op.truncate)
2109 fuse_log(FUSE_LOG_DEBUG,
"truncate[%s] %llu\n",
2110 file_info_string(fi,
buf,
sizeof(
buf)),
2111 (
unsigned long long) size);
2113 return fs->op.truncate(path, size, fi);
2116int fuse_fs_utimens(
struct fuse_fs *fs,
const char *path,
2120 if (!fs->op.utimens)
2125 fuse_log(FUSE_LOG_DEBUG,
"utimens[%s] %s %jd.%09ld %jd.%09ld\n",
2126 file_info_string(fi,
buf,
sizeof(
buf)),
2127 path, (intmax_t)tv[0].tv_sec, tv[0].tv_nsec,
2128 (intmax_t)tv[1].tv_sec, tv[1].tv_nsec);
2130 return fs->op.utimens(path, tv, fi);
2133int fuse_fs_access(
struct fuse_fs *fs,
const char *path,
int mask)
2139 fuse_log(FUSE_LOG_DEBUG,
"access %s 0%o\n", path, mask);
2141 return fs->op.access(path, mask);
2144int fuse_fs_readlink(
struct fuse_fs *fs,
const char *path,
char *
buf,
2148 if (!fs->op.readlink)
2151 fuse_log(FUSE_LOG_DEBUG,
"readlink %s %lu\n", path,
2152 (
unsigned long) len);
2154 return fs->op.readlink(path,
buf, len);
2157int fuse_fs_mknod(
struct fuse_fs *fs,
const char *path, mode_t mode,
2164 fuse_log(FUSE_LOG_DEBUG,
"mknod %s 0%o 0x%llx umask=0%03o\n",
2165 path, mode, (
unsigned long long) rdev,
2168 return fs->op.mknod(path, mode, rdev);
2171int fuse_fs_mkdir(
struct fuse_fs *fs,
const char *path, mode_t mode)
2177 fuse_log(FUSE_LOG_DEBUG,
"mkdir %s 0%o umask=0%03o\n",
2180 return fs->op.mkdir(path, mode);
2183int fuse_fs_setxattr(
struct fuse_fs *fs,
const char *path,
const char *name,
2184 const char *value,
size_t size,
int flags)
2187 if (!fs->op.setxattr)
2190 fuse_log(FUSE_LOG_DEBUG,
"setxattr %s %s %lu 0x%x\n",
2191 path, name, (
unsigned long) size, flags);
2193 return fs->op.setxattr(path, name, value, size, flags);
2196int fuse_fs_getxattr(
struct fuse_fs *fs,
const char *path,
const char *name,
2197 char *value,
size_t size)
2200 if (!fs->op.getxattr)
2203 fuse_log(FUSE_LOG_DEBUG,
"getxattr %s %s %lu\n",
2204 path, name, (
unsigned long) size);
2206 return fs->op.getxattr(path, name, value, size);
2209int fuse_fs_listxattr(
struct fuse_fs *fs,
const char *path,
char *list,
2213 if (!fs->op.listxattr)
2216 fuse_log(FUSE_LOG_DEBUG,
"listxattr %s %lu\n",
2217 path, (
unsigned long) size);
2219 return fs->op.listxattr(path, list, size);
2222int fuse_fs_bmap(
struct fuse_fs *fs,
const char *path,
size_t blocksize,
2229 fuse_log(FUSE_LOG_DEBUG,
"bmap %s blocksize: %lu index: %llu\n",
2230 path, (
unsigned long) blocksize,
2231 (
unsigned long long) *
idx);
2233 return fs->op.bmap(path, blocksize,
idx);
2236int fuse_fs_removexattr(
struct fuse_fs *fs,
const char *path,
const char *name)
2239 if (!fs->op.removexattr)
2242 fuse_log(FUSE_LOG_DEBUG,
"removexattr %s %s\n", path, name);
2244 return fs->op.removexattr(path, name);
2247int fuse_fs_ioctl(
struct fuse_fs *fs,
const char *path,
unsigned int cmd,
2255 fuse_log(FUSE_LOG_DEBUG,
"ioctl[%llu] 0x%x flags: 0x%x\n",
2256 (
unsigned long long) fi->
fh, cmd, flags);
2258 return fs->op.ioctl(path, cmd, arg, fi, flags, data);
2261int fuse_fs_poll(
struct fuse_fs *fs,
const char *path,
2271 fuse_log(FUSE_LOG_DEBUG,
"poll[%llu] ph: %p, events 0x%x\n",
2272 (
unsigned long long) fi->
fh, ph,
2275 res = fs->op.poll(path, fi, ph, reventsp);
2277 if (fs->debug && !res)
2278 fuse_log(FUSE_LOG_DEBUG,
" poll[%llu] revents: 0x%x\n",
2279 (
unsigned long long) fi->
fh, *reventsp);
2284int fuse_fs_fallocate(
struct fuse_fs *fs,
const char *path,
int mode,
2288 if (!fs->op.fallocate)
2291 fuse_log(FUSE_LOG_DEBUG,
"fallocate %s mode %x, offset: %llu, length: %llu\n",
2294 (
unsigned long long) offset,
2295 (
unsigned long long) length);
2297 return fs->op.fallocate(path, mode, offset, length, fi);
2300ssize_t fuse_fs_copy_file_range(
struct fuse_fs *fs,
const char *path_in,
2302 const char *path_out,
2304 size_t len,
int flags)
2307 if (!fs->op.copy_file_range)
2310 fuse_log(FUSE_LOG_DEBUG,
"copy_file_range from %s:%llu to "
2311 "%s:%llu, length: %llu\n",
2313 (
unsigned long long) off_in,
2315 (
unsigned long long) off_out,
2316 (
unsigned long long) len);
2318 return fs->op.copy_file_range(path_in, fi_in, off_in, path_out,
2319 fi_out, off_out, len, flags);
2322off_t fuse_fs_lseek(
struct fuse_fs *fs,
const char *path, off_t
off,
int whence,
2331 fuse_log(FUSE_LOG_DEBUG,
"lseek[%s] %llu %d\n",
2332 file_info_string(fi,
buf,
sizeof(
buf)),
2333 (
unsigned long long)
off, whence);
2335 return fs->op.lseek(path,
off, whence, fi);
2339int fuse_fs_statx(
struct fuse_fs *fs,
const char *path,
int flags,
int mask,
2347 fuse_log(FUSE_LOG_DEBUG,
"statx[%s] %s %d %d\n",
2348 file_info_string(fi,
buf,
sizeof(
buf)), path,
2351 return fs->op.statx(path, flags, mask, stxbuf, fi);
2357int fuse_fs_statx(
struct fuse_fs *fs,
const char *path,
int flags,
int mask,
2371static int is_open(
struct fuse *f,
fuse_ino_t dir,
const char *name)
2375 pthread_mutex_lock(&f->lock);
2376 node = lookup_node(f, dir, name);
2377 if (node && node->open_count > 0)
2379 pthread_mutex_unlock(&f->lock);
2383static char *hidden_name(
struct fuse *f,
fuse_ino_t dir,
const char *oldname,
2384 char *newname,
size_t bufsize)
2388 struct node *newnode;
2394 pthread_mutex_lock(&f->lock);
2395 node = lookup_node(f, dir, oldname);
2397 pthread_mutex_unlock(&f->lock);
2402 snprintf(newname, bufsize,
".fuse_hidden%08x%08x",
2403 (
unsigned int) node->nodeid, f->hidectr);
2404 newnode = lookup_node(f, dir, newname);
2407 res = try_get_path(f, dir, newname, &newpath, NULL,
false);
2408 pthread_mutex_unlock(&f->lock);
2412 memset(&buf, 0,
sizeof(buf));
2413 res = fuse_fs_getattr(f->fs, newpath, &buf, NULL);
2418 }
while(res == 0 && --failctr);
2423static int hide_node(
struct fuse *f,
const char *oldpath,
2430 newpath = hidden_name(f, dir, oldname, newname,
sizeof(newname));
2432 err = fuse_fs_rename(f->fs, oldpath, newpath, 0);
2434 err = rename_node(f, dir, oldname, dir, newname, 1);
2440static int mtime_eq(
const struct stat *stbuf,
const struct timespec *ts)
2442 return stbuf->st_mtime == ts->tv_sec &&
2443 ST_MTIM_NSEC(stbuf) == ts->tv_nsec;
2446#ifndef CLOCK_MONOTONIC
2447#define CLOCK_MONOTONIC CLOCK_REALTIME
2450static void curr_time(
struct timespec *now)
2452 static clockid_t clockid = CLOCK_MONOTONIC;
2453 int res = clock_gettime(clockid, now);
2454 if (res == -1 && errno == EINVAL) {
2455 clockid = CLOCK_REALTIME;
2456 res = clock_gettime(clockid, now);
2459 perror(
"fuse: clock_gettime");
2464static void update_stat(
struct node *node,
const struct stat *stbuf)
2466 if (node->cache_valid && (!mtime_eq(stbuf, &node->mtime) ||
2467 stbuf->st_size != node->size))
2468 node->cache_valid = 0;
2469 node->mtime.tv_sec = stbuf->st_mtime;
2470 node->mtime.tv_nsec = ST_MTIM_NSEC(stbuf);
2471 node->size = stbuf->st_size;
2472 curr_time(&node->stat_updated);
2475static int do_lookup(
struct fuse *f,
fuse_ino_t nodeid,
const char *name,
2480 node = find_node(f, nodeid, name);
2484 e->
ino = node->nodeid;
2488 if (f->conf.auto_cache) {
2489 pthread_mutex_lock(&f->lock);
2490 update_stat(node, &e->
attr);
2491 pthread_mutex_unlock(&f->lock);
2493 set_stat(f, e->
ino, &e->
attr);
2497static int lookup_path(
struct fuse *f,
fuse_ino_t nodeid,
2498 const char *name,
const char *path,
2504 res = fuse_fs_getattr(f->fs, path, &e->
attr, fi);
2506 res = do_lookup(f, nodeid, name, e);
2507 if (res == 0 && f->conf.debug) {
2508 fuse_log(FUSE_LOG_DEBUG,
" NODEID: %llu\n",
2509 (
unsigned long long) e->
ino);
2515static struct fuse_context_i *fuse_get_context_internal(
void)
2517 return (
struct fuse_context_i *) pthread_getspecific(fuse_context_key);
2520static struct fuse_context_i *fuse_create_context(
struct fuse *f)
2522 struct fuse_context_i *c = fuse_get_context_internal();
2524 c = (
struct fuse_context_i *)
2525 calloc(1,
sizeof(
struct fuse_context_i));
2531 fuse_log(FUSE_LOG_ERR,
"fuse: failed to allocate thread specific data\n");
2534 pthread_setspecific(fuse_context_key, c);
2536 memset(c, 0,
sizeof(*c));
2543static void fuse_freecontext(
void *data)
2548static int fuse_create_context_key(
void)
2551 pthread_mutex_lock(&fuse_context_lock);
2552 if (!fuse_context_ref) {
2553 err = pthread_key_create(&fuse_context_key, fuse_freecontext);
2555 fuse_log(FUSE_LOG_ERR,
"fuse: failed to create thread specific key: %s\n",
2557 pthread_mutex_unlock(&fuse_context_lock);
2562 pthread_mutex_unlock(&fuse_context_lock);
2566static void fuse_delete_context_key(
void)
2568 pthread_mutex_lock(&fuse_context_lock);
2570 if (!fuse_context_ref) {
2571 free(pthread_getspecific(fuse_context_key));
2572 pthread_key_delete(fuse_context_key);
2574 pthread_mutex_unlock(&fuse_context_lock);
2577static struct fuse *req_fuse_prepare(
fuse_req_t req)
2579 struct fuse_context_i *c = fuse_create_context(req_fuse(req));
2582 c->ctx.uid = ctx->
uid;
2583 c->ctx.gid = ctx->
gid;
2584 c->ctx.pid = ctx->
pid;
2585 c->ctx.umask = ctx->
umask;
2589static inline void reply_err(
fuse_req_t req,
int err)
2599 struct fuse *f = req_fuse(req);
2603 forget_node(f, e->
ino, 1);
2606 reply_err(req, err);
2609void fuse_fs_init(
struct fuse_fs *fs,
struct fuse_conn_info *conn,
2613 if (!fs->op.write_buf)
2620 fs->user_data = fs->op.init(conn, cfg);
2623static int fuse_init_intr_signal(
int signum,
int *installed);
2625static void fuse_lib_init(
void *data,
struct fuse_conn_info *conn)
2627 struct fuse *f = (
struct fuse *) data;
2629 fuse_create_context(f);
2631 fuse_fs_init(f->fs, conn, &f->conf);
2634 if (fuse_init_intr_signal(f->conf.intr_signal,
2635 &f->intr_installed) == -1)
2636 fuse_log(FUSE_LOG_ERR,
"fuse: failed to init interrupt signal\n");
2643void fuse_fs_destroy(
struct fuse_fs *fs)
2647 fs->op.destroy(fs->user_data);
2650static void fuse_lib_destroy(
void *data)
2652 struct fuse *f = (
struct fuse *) data;
2654 fuse_create_context(f);
2655 fuse_fs_destroy(f->fs);
2661 struct fuse *f = req_fuse_prepare(req);
2665 struct node *dot = NULL;
2667 if (name[0] ==
'.') {
2668 int len = strlen(name);
2670 if (len == 1 || (name[1] ==
'.' && len == 2)) {
2671 pthread_mutex_lock(&f->lock);
2674 fuse_log(FUSE_LOG_DEBUG,
"LOOKUP-DOT\n");
2675 dot = get_node_nocheck(f, parent);
2677 pthread_mutex_unlock(&f->lock);
2678 reply_entry(req, &e, -ESTALE);
2684 fuse_log(FUSE_LOG_DEBUG,
"LOOKUP-DOTDOT\n");
2685 parent = get_node(f, parent)->parent->nodeid;
2687 pthread_mutex_unlock(&f->lock);
2692 err = get_path_name(f, parent, name, &path);
2694 struct fuse_intr_data d;
2696 fuse_log(FUSE_LOG_DEBUG,
"LOOKUP %s\n", path);
2697 fuse_prepare_interrupt(f, req, &d);
2698 err = lookup_path(f, parent, name, path, &e, NULL);
2699 if (err == -ENOENT && f->conf.negative_timeout != 0.0) {
2704 fuse_finish_interrupt(f, req, &d);
2705 free_path(f, parent, path);
2708 pthread_mutex_lock(&f->lock);
2710 pthread_mutex_unlock(&f->lock);
2712 reply_entry(req, &e, err);
2715static void do_forget(
struct fuse *f,
fuse_ino_t ino, uint64_t nlookup)
2718 fuse_log(FUSE_LOG_DEBUG,
"FORGET %llu/%llu\n", (
unsigned long long)ino,
2719 (
unsigned long long) nlookup);
2720 forget_node(f, ino, nlookup);
2725 do_forget(req_fuse(req), ino, nlookup);
2729static void fuse_lib_forget_multi(
fuse_req_t req,
size_t count,
2730 struct fuse_forget_data *forgets)
2732 struct fuse *f = req_fuse(req);
2735 for (i = 0; i < count; i++)
2736 do_forget(f, forgets[i].ino, forgets[i].nlookup);
2745 struct fuse *f = req_fuse_prepare(req);
2750 memset(&buf, 0,
sizeof(buf));
2753 err = get_path_nullok(f, ino, &path);
2755 err = get_path(f, ino, &path);
2757 struct fuse_intr_data d;
2758 fuse_prepare_interrupt(f, req, &d);
2759 err = fuse_fs_getattr(f->fs, path, &buf, fi);
2760 fuse_finish_interrupt(f, req, &d);
2761 free_path(f, ino, path);
2766 pthread_mutex_lock(&f->lock);
2767 node = get_node(f, ino);
2768 if (node->is_hidden && buf.st_nlink > 0)
2770 if (f->conf.auto_cache)
2771 update_stat(node, &buf);
2772 pthread_mutex_unlock(&f->lock);
2773 set_stat(f, ino, &buf);
2776 reply_err(req, err);
2779int fuse_fs_chmod(
struct fuse_fs *fs,
const char *path, mode_t mode,
2789 fuse_log(FUSE_LOG_DEBUG,
"chmod[%s] %s %llo\n",
2790 file_info_string(fi, buf,
sizeof(buf)),
2791 path, (
unsigned long long) mode);
2793 return fs->op.chmod(path, mode, fi);
2799 struct fuse *f = req_fuse_prepare(req);
2804 memset(&buf, 0,
sizeof(buf));
2806 err = get_path_nullok(f, ino, &path);
2808 err = get_path(f, ino, &path);
2810 struct fuse_intr_data d;
2811 fuse_prepare_interrupt(f, req, &d);
2813 if (!err && (valid & FUSE_SET_ATTR_MODE))
2814 err = fuse_fs_chmod(f->fs, path, attr->st_mode, fi);
2815 if (!err && (valid & (FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID))) {
2816 uid_t uid = (valid & FUSE_SET_ATTR_UID) ?
2817 attr->st_uid : (uid_t) -1;
2818 gid_t gid = (valid & FUSE_SET_ATTR_GID) ?
2819 attr->st_gid : (gid_t) -1;
2820 err = fuse_fs_chown(f->fs, path, uid, gid, fi);
2822 if (!err && (valid & FUSE_SET_ATTR_SIZE)) {
2823 err = fuse_fs_truncate(f->fs, path,
2826#ifdef HAVE_UTIMENSAT
2828 (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME))) {
2829 struct timespec tv[2];
2833 tv[0].tv_nsec = UTIME_OMIT;
2834 tv[1].tv_nsec = UTIME_OMIT;
2836 if (valid & FUSE_SET_ATTR_ATIME_NOW)
2837 tv[0].tv_nsec = UTIME_NOW;
2838 else if (valid & FUSE_SET_ATTR_ATIME)
2839 tv[0] = attr->st_atim;
2841 if (valid & FUSE_SET_ATTR_MTIME_NOW)
2842 tv[1].tv_nsec = UTIME_NOW;
2843 else if (valid & FUSE_SET_ATTR_MTIME)
2844 tv[1] = attr->st_mtim;
2846 err = fuse_fs_utimens(f->fs, path, tv, fi);
2850 (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) ==
2851 (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) {
2852 struct timespec tv[2];
2853 tv[0].tv_sec = attr->st_atime;
2854 tv[0].tv_nsec = ST_ATIM_NSEC(attr);
2855 tv[1].tv_sec = attr->st_mtime;
2856 tv[1].tv_nsec = ST_MTIM_NSEC(attr);
2857 err = fuse_fs_utimens(f->fs, path, tv, fi);
2860 err = fuse_fs_getattr(f->fs, path, &buf, fi);
2862 fuse_finish_interrupt(f, req, &d);
2863 free_path(f, ino, path);
2866 if (f->conf.auto_cache) {
2867 pthread_mutex_lock(&f->lock);
2868 update_stat(get_node(f, ino), &buf);
2869 pthread_mutex_unlock(&f->lock);
2871 set_stat(f, ino, &buf);
2874 reply_err(req, err);
2879 struct fuse *f = req_fuse_prepare(req);
2883 err = get_path(f, ino, &path);
2885 struct fuse_intr_data d;
2887 fuse_prepare_interrupt(f, req, &d);
2888 err = fuse_fs_access(f->fs, path, mask);
2889 fuse_finish_interrupt(f, req, &d);
2890 free_path(f, ino, path);
2892 reply_err(req, err);
2897 struct fuse *f = req_fuse_prepare(req);
2898 char linkname[PATH_MAX + 1];
2902 err = get_path(f, ino, &path);
2904 struct fuse_intr_data d;
2905 fuse_prepare_interrupt(f, req, &d);
2906 err = fuse_fs_readlink(f->fs, path, linkname,
sizeof(linkname));
2907 fuse_finish_interrupt(f, req, &d);
2908 free_path(f, ino, path);
2911 linkname[PATH_MAX] =
'\0';
2914 reply_err(req, err);
2918 mode_t mode, dev_t rdev)
2920 struct fuse *f = req_fuse_prepare(req);
2925 err = get_path_name(f, parent, name, &path);
2927 struct fuse_intr_data d;
2929 fuse_prepare_interrupt(f, req, &d);
2931 if (S_ISREG(mode)) {
2934 memset(&fi, 0,
sizeof(fi));
2935 fi.
flags = O_CREAT | O_EXCL | O_WRONLY;
2936 err = fuse_fs_create(f->fs, path, mode, &fi);
2938 err = lookup_path(f, parent, name, path, &e,
2940 fuse_fs_release(f->fs, path, &fi);
2943 if (err == -ENOSYS) {
2944 err = fuse_fs_mknod(f->fs, path, mode, rdev);
2946 err = lookup_path(f, parent, name, path, &e,
2949 fuse_finish_interrupt(f, req, &d);
2950 free_path(f, parent, path);
2952 reply_entry(req, &e, err);
2958 struct fuse *f = req_fuse_prepare(req);
2963 err = get_path_name(f, parent, name, &path);
2965 struct fuse_intr_data d;
2967 fuse_prepare_interrupt(f, req, &d);
2968 err = fuse_fs_mkdir(f->fs, path, mode);
2970 err = lookup_path(f, parent, name, path, &e, NULL);
2971 fuse_finish_interrupt(f, req, &d);
2972 free_path(f, parent, path);
2974 reply_entry(req, &e, err);
2980 struct fuse *f = req_fuse_prepare(req);
2985 err = get_path_wrlock(f, parent, name, &path, &wnode);
2987 struct fuse_intr_data d;
2989 fuse_prepare_interrupt(f, req, &d);
2990 if (!f->conf.hard_remove && is_open(f, parent, name)) {
2991 err = hide_node(f, path, parent, name);
2994 if (!is_open(f, parent, wnode->name)) {
2998 if (try_get_path(f, wnode->nodeid, NULL, &unlinkpath, NULL,
false) == 0) {
2999 err = fuse_fs_unlink(f->fs, unlinkpath);
3001 remove_node(f, parent, wnode->name);
3007 err = fuse_fs_unlink(f->fs, path);
3009 remove_node(f, parent, name);
3011 fuse_finish_interrupt(f, req, &d);
3012 free_path_wrlock(f, parent, wnode, path);
3014 reply_err(req, err);
3019 struct fuse *f = req_fuse_prepare(req);
3024 err = get_path_wrlock(f, parent, name, &path, &wnode);
3026 struct fuse_intr_data d;
3028 fuse_prepare_interrupt(f, req, &d);
3029 err = fuse_fs_rmdir(f->fs, path);
3030 fuse_finish_interrupt(f, req, &d);
3032 remove_node(f, parent, name);
3033 free_path_wrlock(f, parent, wnode, path);
3035 reply_err(req, err);
3038static void fuse_lib_symlink(
fuse_req_t req,
const char *linkname,
3041 struct fuse *f = req_fuse_prepare(req);
3046 err = get_path_name(f, parent, name, &path);
3048 struct fuse_intr_data d;
3050 fuse_prepare_interrupt(f, req, &d);
3051 err = fuse_fs_symlink(f->fs, linkname, path);
3053 err = lookup_path(f, parent, name, path, &e, NULL);
3054 fuse_finish_interrupt(f, req, &d);
3055 free_path(f, parent, path);
3057 reply_entry(req, &e, err);
3062 const char *newname,
unsigned int flags)
3064 struct fuse *f = req_fuse_prepare(req);
3067 struct node *wnode1;
3068 struct node *wnode2;
3071 err = get_path2(f, olddir, oldname, newdir, newname,
3072 &oldpath, &newpath, &wnode1, &wnode2);
3074 struct fuse_intr_data d;
3076 fuse_prepare_interrupt(f, req, &d);
3077 if (!f->conf.hard_remove && !(flags & RENAME_EXCHANGE) &&
3078 is_open(f, newdir, newname))
3079 err = hide_node(f, newpath, newdir, newname);
3081 err = fuse_fs_rename(f->fs, oldpath, newpath, flags);
3083 if (flags & RENAME_EXCHANGE) {
3084 err = exchange_node(f, olddir, oldname,
3087 err = rename_node(f, olddir, oldname,
3088 newdir, newname, 0);
3092 fuse_finish_interrupt(f, req, &d);
3093 free_path2(f, olddir, newdir, wnode1, wnode2, oldpath, newpath);
3095 reply_err(req, err);
3099 const char *newname)
3101 struct fuse *f = req_fuse_prepare(req);
3107 err = get_path2(f,
ino, NULL, newparent, newname,
3108 &oldpath, &newpath, NULL, NULL);
3110 struct fuse_intr_data d;
3112 fuse_prepare_interrupt(f, req, &d);
3113 err = fuse_fs_link(f->fs, oldpath, newpath);
3115 err = lookup_path(f, newparent, newname, newpath,
3117 fuse_finish_interrupt(f, req, &d);
3118 free_path2(f, ino, newparent, NULL, NULL, oldpath, newpath);
3120 reply_entry(req, &e, err);
3123static void fuse_do_release(
struct fuse *f,
fuse_ino_t ino,
const char *path,
3127 int unlink_hidden = 0;
3129 fuse_fs_release(f->fs, path, fi);
3131 pthread_mutex_lock(&f->lock);
3132 node = get_node(f, ino);
3133 assert(node->open_count > 0);
3135 if (node->is_hidden && !node->open_count) {
3137 node->is_hidden = 0;
3139 pthread_mutex_unlock(&f->lock);
3143 fuse_fs_unlink(f->fs, path);
3144 }
else if (f->conf.nullpath_ok) {
3147 if (get_path(f, ino, &unlinkpath) == 0)
3148 fuse_fs_unlink(f->fs, unlinkpath);
3150 free_path(f, ino, unlinkpath);
3156 const char *name, mode_t mode,
3159 struct fuse *f = req_fuse_prepare(req);
3160 struct fuse_intr_data d;
3165 err = get_path_name(f, parent, name, &path);
3167 fuse_prepare_interrupt(f, req, &d);
3168 err = fuse_fs_create(f->fs, path, mode, fi);
3170 err = lookup_path(f, parent, name, path, &e, fi);
3172 fuse_fs_release(f->fs, path, fi);
3173 else if (!S_ISREG(e.
attr.st_mode)) {
3175 fuse_fs_release(f->fs, path, fi);
3176 forget_node(f, e.
ino, 1);
3178 if (f->conf.direct_io)
3180 if (f->conf.kernel_cache)
3183 f->conf.parallel_direct_writes)
3187 fuse_finish_interrupt(f, req, &d);
3190 pthread_mutex_lock(&f->lock);
3191 get_node(f, e.
ino)->open_count++;
3192 pthread_mutex_unlock(&f->lock);
3196 fuse_do_release(f, e.
ino, path, fi);
3197 forget_node(f, e.
ino, 1);
3200 reply_err(req, err);
3203 free_path(f, parent, path);
3206static double diff_timespec(
const struct timespec *t1,
3207 const struct timespec *t2)
3209 return (t1->tv_sec - t2->tv_sec) +
3210 ((double) t1->tv_nsec - (
double) t2->tv_nsec) / 1000000000.0;
3213static void open_auto_cache(
struct fuse *f,
fuse_ino_t ino,
const char *path,
3218 pthread_mutex_lock(&f->lock);
3219 node = get_node(f, ino);
3220 if (node->cache_valid) {
3221 struct timespec now;
3224 if (diff_timespec(&now, &node->stat_updated) >
3225 f->conf.ac_attr_timeout) {
3228 pthread_mutex_unlock(&f->lock);
3229 err = fuse_fs_getattr(f->fs, path, &stbuf, fi);
3230 pthread_mutex_lock(&f->lock);
3232 update_stat(node, &stbuf);
3234 node->cache_valid = 0;
3237 if (node->cache_valid)
3240 node->cache_valid = 1;
3241 pthread_mutex_unlock(&f->lock);
3247 struct fuse *f = req_fuse_prepare(req);
3248 struct fuse_intr_data d;
3252 err = get_path(f, ino, &path);
3254 fuse_prepare_interrupt(f, req, &d);
3255 err = fuse_fs_open(f->fs, path, fi);
3257 if (f->conf.direct_io)
3259 if (f->conf.kernel_cache)
3262 if (f->conf.auto_cache)
3263 open_auto_cache(f, ino, path, fi);
3265 if (f->conf.no_rofd_flush &&
3266 (fi->
flags & O_ACCMODE) == O_RDONLY)
3269 if (fi->
direct_io && f->conf.parallel_direct_writes)
3273 fuse_finish_interrupt(f, req, &d);
3276 pthread_mutex_lock(&f->lock);
3277 get_node(f, ino)->open_count++;
3278 pthread_mutex_unlock(&f->lock);
3282 fuse_do_release(f, ino, path, fi);
3285 reply_err(req, err);
3287 free_path(f, ino, path);
3293 struct fuse *f = req_fuse_prepare(req);
3298 res = get_path_nullok(f, ino, &path);
3300 struct fuse_intr_data d;
3302 fuse_prepare_interrupt(f, req, &d);
3303 res = fuse_fs_read_buf(f->fs, path, &buf, size, off, fi);
3304 fuse_finish_interrupt(f, req, &d);
3305 free_path(f, ino, path);
3311 reply_err(req, res);
3320 struct fuse *f = req_fuse_prepare(req);
3324 res = get_path_nullok(f, ino, &path);
3326 struct fuse_intr_data d;
3328 fuse_prepare_interrupt(f, req, &d);
3329 res = fuse_fs_write_buf(f->fs, path, buf, off, fi);
3330 fuse_finish_interrupt(f, req, &d);
3331 free_path(f, ino, path);
3337 reply_err(req, res);
3343 struct fuse *f = req_fuse_prepare(req);
3347 err = get_path_nullok(f, ino, &path);
3349 struct fuse_intr_data d;
3351 fuse_prepare_interrupt(f, req, &d);
3352 err = fuse_fs_fsync(f->fs, path, datasync, fi);
3353 fuse_finish_interrupt(f, req, &d);
3354 free_path(f, ino, path);
3356 reply_err(req, err);
3359static struct fuse_dh *get_dirhandle(
const struct fuse_file_info *llfi,
3362 struct fuse_dh *dh = (
struct fuse_dh *) (uintptr_t) llfi->
fh;
3371 struct fuse *f = req_fuse_prepare(req);
3372 struct fuse_intr_data d;
3378 dh = (
struct fuse_dh *) malloc(
sizeof(
struct fuse_dh));
3380 reply_err(req, -ENOMEM);
3383 memset(dh, 0,
sizeof(
struct fuse_dh));
3385 dh->contents = NULL;
3390 pthread_mutex_init(&dh->lock, NULL);
3392 llfi->
fh = (uintptr_t) dh;
3394 memset(&fi, 0,
sizeof(fi));
3397 err = get_path(f, ino, &path);
3399 fuse_prepare_interrupt(f, req, &d);
3400 err = fuse_fs_opendir(f->fs, path, &fi);
3401 fuse_finish_interrupt(f, req, &d);
3410 fuse_fs_releasedir(f->fs, path, &fi);
3411 pthread_mutex_destroy(&dh->lock);
3415 reply_err(req, err);
3416 pthread_mutex_destroy(&dh->lock);
3419 free_path(f, ino, path);
3422static int extend_contents(
struct fuse_dh *dh,
unsigned minsize)
3424 if (minsize > dh->size) {
3426 unsigned newsize = dh->size;
3429 while (newsize < minsize) {
3430 if (newsize >= 0x80000000)
3431 newsize = 0xffffffff;
3436 newptr = (
char *) realloc(dh->contents, newsize);
3438 dh->error = -ENOMEM;
3441 dh->contents = newptr;
3447static int fuse_add_direntry_to_dh(
struct fuse_dh *dh,
const char *name,
3450 struct fuse_direntry *de;
3452 de = malloc(
sizeof(
struct fuse_direntry));
3454 dh->error = -ENOMEM;
3457 de->name = strdup(name);
3459 dh->error = -ENOMEM;
3468 dh->last = &de->next;
3479 pthread_mutex_lock(&f->lock);
3480 node = lookup_node(f, parent, name);
3483 pthread_mutex_unlock(&f->lock);
3488static int fill_dir(
void *dh_,
const char *name,
const struct stat *statp,
3491 struct fuse_dh *dh = (
struct fuse_dh *) dh_;
3494 if ((flags & ~FUSE_FILL_DIR_PLUS) != 0) {
3502 memset(&stbuf, 0,
sizeof(stbuf));
3503 stbuf.st_ino = FUSE_UNKNOWN_INO;
3506 if (!dh->fuse->conf.use_ino) {
3507 stbuf.st_ino = FUSE_UNKNOWN_INO;
3508 if (dh->fuse->conf.readdir_ino) {
3509 stbuf.st_ino = (ino_t)
3510 lookup_nodeid(dh->fuse, dh->nodeid, name);
3527 if (extend_contents(dh, dh->needlen) == -1)
3532 dh->needlen - dh->len, name,
3534 if (newlen > dh->needlen)
3541 if (fuse_add_direntry_to_dh(dh, name, &stbuf, flags) == -1)
3547static int is_dot_or_dotdot(
const char *name)
3549 return name[0] ==
'.' && (name[1] ==
'\0' ||
3550 (name[1] ==
'.' && name[2] ==
'\0'));
3553static int fill_dir_plus(
void *dh_,
const char *name,
const struct stat *statp,
3556 struct fuse_dh *dh = (
struct fuse_dh *) dh_;
3561 struct fuse *f = dh->fuse;
3564 if ((flags & ~FUSE_FILL_DIR_PLUS) != 0) {
3569 if (statp && (flags & FUSE_FILL_DIR_PLUS)) {
3573 e.
attr.st_ino = FUSE_UNKNOWN_INO;
3575 e.
attr.st_mode = statp->st_mode;
3576 if (f->conf.use_ino)
3577 e.
attr.st_ino = statp->st_ino;
3579 if (!f->conf.use_ino && f->conf.readdir_ino) {
3580 e.
attr.st_ino = (ino_t)
3581 lookup_nodeid(f, dh->nodeid, name);
3596 if (extend_contents(dh, dh->needlen) == -1)
3599 if (statp && (flags & FUSE_FILL_DIR_PLUS)) {
3600 if (!is_dot_or_dotdot(name)) {
3601 res = do_lookup(f, dh->nodeid, name, &e);
3611 dh->needlen - dh->len, name,
3613 if (newlen > dh->needlen)
3619 if (fuse_add_direntry_to_dh(dh, name, &e.
attr, flags) == -1)
3626static void free_direntries(
struct fuse_direntry *de)
3629 struct fuse_direntry *next = de->next;
3637 size_t size, off_t off,
struct fuse_dh *dh,
3644 if (f->fs->op.readdir)
3645 err = get_path_nullok(f, ino, &path);
3647 err = get_path(f, ino, &path);
3649 struct fuse_intr_data d;
3652 if (flags & FUSE_READDIR_PLUS)
3653 filler = fill_dir_plus;
3655 free_direntries(dh->first);
3657 dh->last = &dh->first;
3663 fuse_prepare_interrupt(f, req, &d);
3664 err = fuse_fs_readdir(f->fs, path, dh, filler, off, fi, flags);
3665 fuse_finish_interrupt(f, req, &d);
3671 free_path(f, ino, path);
3676static int readdir_fill_from_list(
fuse_req_t req,
struct fuse_dh *dh,
3680 struct fuse_direntry *de = dh->first;
3685 if (extend_contents(dh, dh->needlen) == -1)
3688 for (pos = 0; pos < off; pos++) {
3695 char *p = dh->contents + dh->len;
3696 unsigned rem = dh->needlen - dh->len;
3701 if (flags & FUSE_READDIR_PLUS) {
3707 if (de->flags & FUSE_FILL_DIR_PLUS &&
3708 !is_dot_or_dotdot(de->name)) {
3709 res = do_lookup(dh->fuse, dh->nodeid,
3721 de->name, &de->stat, pos);
3723 newlen = dh->len + thislen;
3724 if (newlen > dh->needlen)
3736 struct fuse *f = req_fuse_prepare(req);
3738 struct fuse_dh *dh = get_dirhandle(llfi, &fi);
3741 pthread_mutex_lock(&dh->lock);
3748 err = readdir_fill(f, req, ino, size, off, dh, &fi, flags);
3750 reply_err(req, err);
3756 err = readdir_fill_from_list(req, dh, off, flags);
3758 reply_err(req, err);
3764 pthread_mutex_unlock(&dh->lock);
3770 fuse_readdir_common(req, ino, size, off, llfi, 0);
3776 fuse_readdir_common(req, ino, size, off, llfi, FUSE_READDIR_PLUS);
3782 struct fuse *f = req_fuse_prepare(req);
3783 struct fuse_intr_data d;
3785 struct fuse_dh *dh = get_dirhandle(llfi, &fi);
3788 get_path_nullok(f, ino, &path);
3790 fuse_prepare_interrupt(f, req, &d);
3791 fuse_fs_releasedir(f->fs, path, &fi);
3792 fuse_finish_interrupt(f, req, &d);
3793 free_path(f, ino, path);
3795 pthread_mutex_lock(&dh->lock);
3796 pthread_mutex_unlock(&dh->lock);
3797 pthread_mutex_destroy(&dh->lock);
3798 free_direntries(dh->first);
3807 struct fuse *f = req_fuse_prepare(req);
3812 get_dirhandle(llfi, &fi);
3814 err = get_path_nullok(f, ino, &path);
3816 struct fuse_intr_data d;
3817 fuse_prepare_interrupt(f, req, &d);
3818 err = fuse_fs_fsyncdir(f->fs, path, datasync, &fi);
3819 fuse_finish_interrupt(f, req, &d);
3820 free_path(f, ino, path);
3822 reply_err(req, err);
3827 struct fuse *f = req_fuse_prepare(req);
3832 memset(&buf, 0,
sizeof(buf));
3834 err = get_path(f, ino, &path);
3837 struct fuse_intr_data d;
3838 fuse_prepare_interrupt(f, req, &d);
3839 err = fuse_fs_statfs(f->fs, path ? path :
"/", &buf);
3840 fuse_finish_interrupt(f, req, &d);
3841 free_path(f, ino, path);
3847 reply_err(req, err);
3851 const char *value,
size_t size,
int flags)
3853 struct fuse *f = req_fuse_prepare(req);
3857 err = get_path(f, ino, &path);
3859 struct fuse_intr_data d;
3860 fuse_prepare_interrupt(f, req, &d);
3861 err = fuse_fs_setxattr(f->fs, path, name, value, size, flags);
3862 fuse_finish_interrupt(f, req, &d);
3863 free_path(f, ino, path);
3865 reply_err(req, err);
3869 const char *name,
char *value,
size_t size)
3874 err = get_path(f, ino, &path);
3876 struct fuse_intr_data d;
3877 fuse_prepare_interrupt(f, req, &d);
3878 err = fuse_fs_getxattr(f->fs, path, name, value, size);
3879 fuse_finish_interrupt(f, req, &d);
3880 free_path(f, ino, path);
3888 struct fuse *f = req_fuse_prepare(req);
3892 char *value = (
char *) malloc(size);
3893 if (value == NULL) {
3894 reply_err(req, -ENOMEM);
3897 res = common_getxattr(f, req, ino, name, value, size);
3901 reply_err(req, res);
3904 res = common_getxattr(f, req, ino, name, NULL, 0);
3908 reply_err(req, res);
3913 char *list,
size_t size)
3918 err = get_path(f, ino, &path);
3920 struct fuse_intr_data d;
3921 fuse_prepare_interrupt(f, req, &d);
3922 err = fuse_fs_listxattr(f->fs, path, list, size);
3923 fuse_finish_interrupt(f, req, &d);
3924 free_path(f, ino, path);
3931 struct fuse *f = req_fuse_prepare(req);
3935 char *list = (
char *) malloc(size);
3937 reply_err(req, -ENOMEM);
3940 res = common_listxattr(f, req, ino, list, size);
3944 reply_err(req, res);
3947 res = common_listxattr(f, req, ino, NULL, 0);
3951 reply_err(req, res);
3958 struct fuse *f = req_fuse_prepare(req);
3962 err = get_path(f, ino, &path);
3964 struct fuse_intr_data d;
3965 fuse_prepare_interrupt(f, req, &d);
3966 err = fuse_fs_removexattr(f->fs, path, name);
3967 fuse_finish_interrupt(f, req, &d);
3968 free_path(f, ino, path);
3970 reply_err(req, err);
3973static struct lock *locks_conflict(
struct node *node,
const struct lock *lock)
3977 for (l = node->locks; l; l = l->next)
3978 if (l->owner != lock->owner &&
3979 lock->start <= l->end && l->start <= lock->end &&
3980 (l->type == F_WRLCK || lock->type == F_WRLCK))
3986static void delete_lock(
struct lock **lockp)
3988 struct lock *l = *lockp;
3993static void insert_lock(
struct lock **pos,
struct lock *lock)
3999static int locks_insert(
struct node *node,
struct lock *lock)
4002 struct lock *newl1 = NULL;
4003 struct lock *newl2 = NULL;
4005 if (lock->type != F_UNLCK || lock->start != 0 ||
4006 lock->end != OFFSET_MAX) {
4007 newl1 = malloc(
sizeof(
struct lock));
4008 newl2 = malloc(
sizeof(
struct lock));
4010 if (!newl1 || !newl2) {
4017 for (lp = &node->locks; *lp;) {
4018 struct lock *l = *lp;
4019 if (l->owner != lock->owner)
4022 if (lock->type == l->type) {
4023 if (l->end < lock->start - 1)
4025 if (lock->end < l->start - 1)
4027 if (l->start <= lock->start && lock->end <= l->end)
4029 if (l->start < lock->start)
4030 lock->start = l->start;
4031 if (lock->end < l->end)
4035 if (l->end < lock->start)
4037 if (lock->end < l->start)
4039 if (lock->start <= l->start && l->end <= lock->end)
4041 if (l->end <= lock->end) {
4042 l->end = lock->start - 1;
4045 if (lock->start <= l->start) {
4046 l->start = lock->end + 1;
4050 newl2->start = lock->end + 1;
4051 l->end = lock->start - 1;
4052 insert_lock(&l->next, newl2);
4062 if (lock->type != F_UNLCK) {
4064 insert_lock(lp, newl1);
4073static void flock_to_lock(
struct flock *flock,
struct lock *lock)
4075 memset(lock, 0,
sizeof(
struct lock));
4076 lock->type = flock->l_type;
4077 lock->start = flock->l_start;
4079 flock->l_len ? flock->l_start + flock->l_len - 1 : OFFSET_MAX;
4080 lock->pid = flock->l_pid;
4083static void lock_to_flock(
struct lock *lock,
struct flock *flock)
4085 flock->l_type = lock->type;
4086 flock->l_start = lock->start;
4088 (lock->end == OFFSET_MAX) ? 0 : lock->end - lock->start + 1;
4089 flock->l_pid = lock->pid;
4095 struct fuse_intr_data d;
4101 fuse_prepare_interrupt(f, req, &d);
4102 memset(&lock, 0,
sizeof(lock));
4103 lock.l_type = F_UNLCK;
4104 lock.l_whence = SEEK_SET;
4105 err = fuse_fs_flush(f->fs, path, fi);
4106 errlock = fuse_fs_lock(f->fs, path, fi, F_SETLK, &lock);
4107 fuse_finish_interrupt(f, req, &d);
4109 if (errlock != -ENOSYS) {
4110 flock_to_lock(&lock, &l);
4112 pthread_mutex_lock(&f->lock);
4113 locks_insert(get_node(f, ino), &l);
4114 pthread_mutex_unlock(&f->lock);
4127 struct fuse *f = req_fuse_prepare(req);
4128 struct fuse_intr_data d;
4132 get_path_nullok(f, ino, &path);
4134 err = fuse_flush_common(f, req, ino, path, fi);
4139 fuse_prepare_interrupt(f, req, &d);
4140 fuse_do_release(f, ino, path, fi);
4141 fuse_finish_interrupt(f, req, &d);
4142 free_path(f, ino, path);
4144 reply_err(req, err);
4150 struct fuse *f = req_fuse_prepare(req);
4154 get_path_nullok(f, ino, &path);
4155 err = fuse_flush_common(f, req, ino, path, fi);
4156 free_path(f, ino, path);
4158 reply_err(req, err);
4165 struct fuse *f = req_fuse_prepare(req);
4169 err = get_path_nullok(f, ino, &path);
4171 struct fuse_intr_data d;
4172 fuse_prepare_interrupt(f, req, &d);
4173 err = fuse_fs_lock(f->fs, path, fi, cmd, lock);
4174 fuse_finish_interrupt(f, req, &d);
4175 free_path(f, ino, path);
4185 struct lock *conflict;
4186 struct fuse *f = req_fuse(req);
4188 flock_to_lock(lock, &l);
4190 pthread_mutex_lock(&f->lock);
4191 conflict = locks_conflict(get_node(f, ino), &l);
4193 lock_to_flock(conflict, lock);
4194 pthread_mutex_unlock(&f->lock);
4196 err = fuse_lock_common(req, ino, fi, lock, F_GETLK);
4203 reply_err(req, err);
4210 int err = fuse_lock_common(req, ino, fi, lock,
4211 sleep ? F_SETLKW : F_SETLK);
4213 struct fuse *f = req_fuse(req);
4215 flock_to_lock(lock, &l);
4217 pthread_mutex_lock(&f->lock);
4218 locks_insert(get_node(f, ino), &l);
4219 pthread_mutex_unlock(&f->lock);
4221 reply_err(req, err);
4227 struct fuse *f = req_fuse_prepare(req);
4231 err = get_path_nullok(f, ino, &path);
4233 struct fuse_intr_data d;
4234 fuse_prepare_interrupt(f, req, &d);
4235 err = fuse_fs_flock(f->fs, path, fi, op);
4236 fuse_finish_interrupt(f, req, &d);
4237 free_path(f, ino, path);
4239 reply_err(req, err);
4245 struct fuse *f = req_fuse_prepare(req);
4246 struct fuse_intr_data d;
4250 err = get_path(f, ino, &path);
4252 fuse_prepare_interrupt(f, req, &d);
4253 err = fuse_fs_bmap(f->fs, path, blocksize, &idx);
4254 fuse_finish_interrupt(f, req, &d);
4255 free_path(f, ino, path);
4260 reply_err(req, err);
4265 unsigned int flags,
const void *in_buf,
4266 size_t in_bufsz,
size_t out_bufsz)
4268 struct fuse *f = req_fuse_prepare(req);
4269 struct fuse_intr_data d;
4271 char *path, *out_buf = NULL;
4275 if (
flags & FUSE_IOCTL_UNRESTRICTED)
4278 if (
flags & FUSE_IOCTL_DIR)
4279 get_dirhandle(llfi, &fi);
4285 out_buf = malloc(out_bufsz);
4290 assert(!in_bufsz || !out_bufsz || in_bufsz == out_bufsz);
4291 if (out_buf && in_bufsz)
4292 memcpy(out_buf, in_buf, in_bufsz);
4294 err = get_path_nullok(f, ino, &path);
4298 fuse_prepare_interrupt(f, req, &d);
4300 err = fuse_fs_ioctl(f->fs, path, cmd, arg, &fi,
flags,
4301 out_buf ? out_buf : (void *)in_buf);
4303 fuse_finish_interrupt(f, req, &d);
4304 free_path(f, ino, path);
4311 reply_err(req, err);
4319 struct fuse *f = req_fuse_prepare(req);
4320 struct fuse_intr_data d;
4323 unsigned revents = 0;
4325 err = get_path_nullok(f, ino, &path);
4327 fuse_prepare_interrupt(f, req, &d);
4328 err = fuse_fs_poll(f->fs, path, fi, ph, &revents);
4329 fuse_finish_interrupt(f, req, &d);
4330 free_path(f, ino, path);
4335 reply_err(req, err);
4341 struct fuse *f = req_fuse_prepare(req);
4342 struct fuse_intr_data d;
4346 err = get_path_nullok(f, ino, &path);
4348 fuse_prepare_interrupt(f, req, &d);
4349 err = fuse_fs_fallocate(f->fs, path, mode, offset, length, fi);
4350 fuse_finish_interrupt(f, req, &d);
4351 free_path(f, ino, path);
4353 reply_err(req, err);
4362 struct fuse *f = req_fuse_prepare(req);
4363 struct fuse_intr_data d;
4364 char *path_in, *path_out;
4368 err = get_path_nullok(f, nodeid_in, &path_in);
4370 reply_err(req, err);
4374 err = get_path_nullok(f, nodeid_out, &path_out);
4376 free_path(f, nodeid_in, path_in);
4377 reply_err(req, err);
4381 fuse_prepare_interrupt(f, req, &d);
4382 res = fuse_fs_copy_file_range(f->fs, path_in, fi_in, off_in, path_out,
4383 fi_out, off_out, len, flags);
4384 fuse_finish_interrupt(f, req, &d);
4389 reply_err(req, res);
4391 free_path(f, nodeid_in, path_in);
4392 free_path(f, nodeid_out, path_out);
4398 struct fuse *f = req_fuse_prepare(req);
4399 struct fuse_intr_data d;
4404 err = get_path(f, ino, &path);
4406 reply_err(req, err);
4410 fuse_prepare_interrupt(f, req, &d);
4411 res = fuse_fs_lseek(f->fs, path, off, whence, fi);
4412 fuse_finish_interrupt(f, req, &d);
4413 free_path(f, ino, path);
4417 reply_err(req, res);
4424 struct fuse *f = req_fuse_prepare(req);
4425 struct statx stxbuf;
4429 memset(&stxbuf, 0,
sizeof(stxbuf));
4432 err = get_path_nullok(f, ino, &path);
4434 err = get_path(f, ino, &path);
4437 struct fuse_intr_data d;
4440 flags |= AT_EMPTY_PATH;
4441 fuse_prepare_interrupt(f, req, &d);
4442 err = fuse_fs_statx(f->fs, path, flags, mask, &stxbuf, fi);
4443 fuse_finish_interrupt(f, req, &d);
4444 free_path(f, ino, path);
4449 pthread_mutex_lock(&f->lock);
4450 node = get_node(f, ino);
4451 if (node->is_hidden && stxbuf.stx_nlink > 0)
4453 if (f->conf.auto_cache) {
4456 stbuf.st_mtime = stxbuf.stx_mtime.tv_nsec;
4457 ST_MTIM_NSEC(&stbuf) = stxbuf.stx_mtime.tv_nsec;
4458 stbuf.st_size = stxbuf.stx_size;
4459 update_stat(node, &stbuf);
4461 pthread_mutex_unlock(&f->lock);
4462 set_statx(f, ino, &stxbuf);
4465 reply_err(req, err);
4469static int clean_delay(
struct fuse *f)
4477 int max_sleep = 3600;
4478 int sleep_time = f->conf.remember / 10;
4480 if (sleep_time > max_sleep)
4482 if (sleep_time < min_sleep)
4489 struct node_lru *lnode;
4490 struct list_head *curr, *next;
4492 struct timespec now;
4494 pthread_mutex_lock(&f->lock);
4498 for (curr = f->lru_table.next; curr != &f->lru_table; curr = next) {
4502 lnode = list_entry(curr,
struct node_lru, lru);
4503 node = &lnode->node;
4505 age = diff_timespec(&now, &lnode->forget_time);
4506 if (age <= f->conf.remember)
4509 assert(node->nlookup == 1);
4512 if (node->refctr > 1)
4516 unhash_name(f, node);
4517 unref_node(f, node);
4519 pthread_mutex_unlock(&f->lock);
4521 return clean_delay(f);
4525 .
init = fuse_lib_init,
4526 .destroy = fuse_lib_destroy,
4527 .lookup = fuse_lib_lookup,
4528 .forget = fuse_lib_forget,
4529 .forget_multi = fuse_lib_forget_multi,
4530 .getattr = fuse_lib_getattr,
4531 .setattr = fuse_lib_setattr,
4532 .access = fuse_lib_access,
4533 .readlink = fuse_lib_readlink,
4534 .mknod = fuse_lib_mknod,
4535 .mkdir = fuse_lib_mkdir,
4536 .unlink = fuse_lib_unlink,
4537 .rmdir = fuse_lib_rmdir,
4538 .symlink = fuse_lib_symlink,
4539 .rename = fuse_lib_rename,
4540 .link = fuse_lib_link,
4541 .create = fuse_lib_create,
4542 .open = fuse_lib_open,
4543 .read = fuse_lib_read,
4544 .write_buf = fuse_lib_write_buf,
4545 .flush = fuse_lib_flush,
4546 .release = fuse_lib_release,
4547 .fsync = fuse_lib_fsync,
4548 .opendir = fuse_lib_opendir,
4549 .readdir = fuse_lib_readdir,
4550 .readdirplus = fuse_lib_readdirplus,
4551 .releasedir = fuse_lib_releasedir,
4552 .fsyncdir = fuse_lib_fsyncdir,
4553 .statfs = fuse_lib_statfs,
4554 .setxattr = fuse_lib_setxattr,
4555 .getxattr = fuse_lib_getxattr,
4556 .listxattr = fuse_lib_listxattr,
4557 .removexattr = fuse_lib_removexattr,
4558 .getlk = fuse_lib_getlk,
4559 .setlk = fuse_lib_setlk,
4560 .flock = fuse_lib_flock,
4561 .bmap = fuse_lib_bmap,
4562 .ioctl = fuse_lib_ioctl,
4563 .poll = fuse_lib_poll,
4564 .fallocate = fuse_lib_fallocate,
4565 .copy_file_range = fuse_lib_copy_file_range,
4566 .lseek = fuse_lib_lseek,
4568 .statx = fuse_lib_statx,
4572int fuse_notify_poll(
struct fuse_pollhandle *ph)
4582static int fuse_session_loop_remember(
struct fuse *f)
4584 struct fuse_session *se = f->se;
4586 struct timespec now;
4588 struct pollfd fds = {
4597 next_clean = now.tv_sec;
4602 if (now.tv_sec < next_clean)
4603 timeout = next_clean - now.tv_sec;
4607 res = poll(&fds, 1, timeout * 1000);
4613 }
else if (res > 0) {
4614 res = fuse_session_receive_buf_internal(se, &fbuf,
4621 fuse_session_process_buf_internal(se, &fbuf, NULL);
4625 next_clean = now.tv_sec + timeout;
4629 fuse_buf_free(&fbuf);
4630 return res < 0 ? -1 : 0;
4639 return fuse_session_loop_remember(f);
4644FUSE_SYMVER(
"fuse_loop_mt_312",
"fuse_loop_mt@@FUSE_3.12")
4659int fuse_loop_mt_32(
struct fuse *f,
struct fuse_loop_config_v1 *config_v1);
4660FUSE_SYMVER(
"fuse_loop_mt_32",
"fuse_loop_mt@FUSE_3.2")
4661int fuse_loop_mt_32(struct fuse *f, struct fuse_loop_config_v1 *config_v1)
4667 fuse_loop_cfg_convert(config, config_v1);
4669 int res = fuse_loop_mt_312(f, config);
4671 fuse_loop_cfg_destroy(config);
4676int fuse_loop_mt_31(
struct fuse *f,
int clone_fd);
4677FUSE_SYMVER(
"fuse_loop_mt_31",
"fuse_loop_mt@FUSE_3.0")
4678int fuse_loop_mt_31(struct fuse *f,
int clone_fd)
4686 fuse_loop_cfg_set_clone_fd(config,
clone_fd);
4688 err = fuse_loop_mt_312(f, config);
4690 fuse_loop_cfg_destroy(config);
4702 struct fuse_context_i *c = fuse_get_context_internal();
4712 struct fuse_context_i *c = fuse_get_context_internal();
4721 struct fuse_context_i *c = fuse_get_context_internal();
4731 int err = lookup_path_in_cache(f, path, &ino);
4739#define FUSE_LIB_OPT(t, p, v) { t, offsetof(struct fuse_config, p), v }
4741static const struct fuse_opt fuse_lib_opts[] = {
4744 FUSE_LIB_OPT(
"debug", debug, 1),
4745 FUSE_LIB_OPT(
"-d", debug, 1),
4746 FUSE_LIB_OPT(
"kernel_cache", kernel_cache, 1),
4747 FUSE_LIB_OPT(
"auto_cache", auto_cache, 1),
4748 FUSE_LIB_OPT(
"noauto_cache", auto_cache, 0),
4749 FUSE_LIB_OPT(
"no_rofd_flush", no_rofd_flush, 1),
4750 FUSE_LIB_OPT(
"umask=", set_mode, 1),
4751 FUSE_LIB_OPT(
"umask=%o", umask, 0),
4752 FUSE_LIB_OPT(
"fmask=", set_mode, 1),
4753 FUSE_LIB_OPT(
"fmask=%o", fmask, 0),
4754 FUSE_LIB_OPT(
"dmask=", set_mode, 1),
4755 FUSE_LIB_OPT(
"dmask=%o", dmask, 0),
4756 FUSE_LIB_OPT(
"uid=", set_uid, 1),
4757 FUSE_LIB_OPT(
"uid=%d", uid, 0),
4758 FUSE_LIB_OPT(
"gid=", set_gid, 1),
4759 FUSE_LIB_OPT(
"gid=%d", gid, 0),
4760 FUSE_LIB_OPT(
"entry_timeout=%lf", entry_timeout, 0),
4761 FUSE_LIB_OPT(
"attr_timeout=%lf", attr_timeout, 0),
4762 FUSE_LIB_OPT(
"ac_attr_timeout=%lf", ac_attr_timeout, 0),
4763 FUSE_LIB_OPT(
"ac_attr_timeout=", ac_attr_timeout_set, 1),
4764 FUSE_LIB_OPT(
"negative_timeout=%lf", negative_timeout, 0),
4765 FUSE_LIB_OPT(
"noforget", remember, -1),
4766 FUSE_LIB_OPT(
"remember=%u", remember, 0),
4767 FUSE_LIB_OPT(
"modules=%s", modules, 0),
4768 FUSE_LIB_OPT(
"parallel_direct_write=%d", parallel_direct_writes, 0),
4772static int fuse_lib_opt_proc(
void *data,
const char *arg,
int key,
4775 (void) arg; (void) outargs; (void) data; (void) key;
4782static const struct fuse_opt fuse_help_opts[] = {
4783 FUSE_LIB_OPT(
"modules=%s", modules, 1),
4788static void print_module_help(
const char *name,
4795 printf(
"\nOptions for %s module:\n", name);
4805" -o kernel_cache cache files in kernel\n"
4806" -o [no]auto_cache enable caching based on modification times (off)\n"
4807" -o no_rofd_flush disable flushing of read-only fd on close (off)\n"
4808" -o umask=M set file permissions (octal)\n"
4809" -o fmask=M set file permissions (octal)\n"
4810" -o dmask=M set dir permissions (octal)\n"
4811" -o uid=N set file owner\n"
4812" -o gid=N set file group\n"
4813" -o entry_timeout=T cache timeout for names (1.0s)\n"
4814" -o negative_timeout=T cache timeout for deleted names (0.0s)\n"
4815" -o attr_timeout=T cache timeout for attributes (1.0s)\n"
4816" -o ac_attr_timeout=T auto cache timeout for attributes (attr_timeout)\n"
4817" -o noforget never forget cached inodes\n"
4818" -o remember=T remember cached inodes for T seconds (0s)\n"
4819" -o modules=M1[:M2...] names of modules to push onto filesystem stack\n");
4826 print_module_help(
"subdir", &fuse_module_subdir_factory);
4828 print_module_help(
"iconv", &fuse_module_iconv_factory);
4835 fuse_lib_opt_proc) == -1
4844 for (module = conf.modules;
module;
module = next) {
4846 for (p = module; *p && *p !=
':'; p++);
4847 next = *p ? p + 1 : NULL;
4850 m = fuse_get_module(module);
4852 print_module_help(module, &m->factory);
4856static int fuse_init_intr_signal(
int signum,
int *installed)
4858 struct sigaction old_sa;
4860 if (sigaction(signum, NULL, &old_sa) == -1) {
4861 perror(
"fuse: cannot get old signal handler");
4865 if (old_sa.sa_handler == SIG_DFL) {
4866 struct sigaction sa;
4868 memset(&sa, 0,
sizeof(
struct sigaction));
4869 sa.sa_handler = fuse_intr_sighandler;
4870 sigemptyset(&sa.sa_mask);
4872 if (sigaction(signum, &sa, NULL) == -1) {
4873 perror(
"fuse: cannot set interrupt signal handler");
4881static void fuse_restore_intr_signal(
int signum)
4883 struct sigaction sa;
4885 memset(&sa, 0,
sizeof(
struct sigaction));
4886 sa.sa_handler = SIG_DFL;
4887 sigaction(signum, &sa, NULL);
4891static int fuse_push_module(
struct fuse *f,
const char *module,
4894 struct fuse_fs *fs[2] = { f->fs, NULL };
4895 struct fuse_fs *newfs;
4901 newfs = m->factory(args, fs);
4916 fuse_log(FUSE_LOG_ERR,
"fuse: warning: library too old, some operations may not not work\n");
4920 fs = (
struct fuse_fs *) calloc(1,
sizeof(
struct fuse_fs));
4922 fuse_log(FUSE_LOG_ERR,
"fuse: failed to allocate fuse_fs object\n");
4926 fs->user_data = user_data;
4928 memcpy(&fs->op, op, op_size);
4932static int node_table_init(
struct node_table *t)
4934 t->size = NODE_TABLE_MIN_SIZE;
4935 t->array = (
struct node **) calloc(1,
sizeof(
struct node *) * t->size);
4936 if (t->array == NULL) {
4937 fuse_log(FUSE_LOG_ERR,
"fuse: memory allocation failed\n");
4946static void *fuse_prune_nodes(
void *fuse)
4948 struct fuse *f = fuse;
4951 fuse_set_thread_name(
"fuse_prune_nodes");
4963 return fuse_start_thread(&f->prune_thread, fuse_prune_nodes, f);
4970 if (lru_enabled(f)) {
4971 pthread_mutex_lock(&f->lock);
4972 pthread_cancel(f->prune_thread);
4973 pthread_mutex_unlock(&f->lock);
4974 pthread_join(f->prune_thread, NULL);
4982struct fuse *_fuse_new_31(
struct fuse_args *args,
4991 f = (
struct fuse *) calloc(1,
sizeof(
struct fuse));
4993 fuse_log(FUSE_LOG_ERR,
"fuse: failed to allocate fuse object\n");
4997 f->conf.entry_timeout = 1.0;
4998 f->conf.attr_timeout = 1.0;
4999 f->conf.negative_timeout = 0.0;
5000 f->conf.intr_signal = FUSE_DEFAULT_INTR_SIGNAL;
5004 fuse_lib_opt_proc) == -1)
5007 pthread_mutex_lock(&fuse_context_lock);
5008 static int builtin_modules_registered = 0;
5010 if (builtin_modules_registered == 0) {
5012 fuse_register_module(
"subdir", fuse_module_subdir_factory, NULL);
5014 fuse_register_module(
"iconv", fuse_module_iconv_factory, NULL);
5016 builtin_modules_registered= 1;
5018 pthread_mutex_unlock(&fuse_context_lock);
5020 if (fuse_create_context_key() == -1)
5025 goto out_delete_context_key;
5035 f->pagesize = getpagesize();
5036 init_list_head(&f->partial_slabs);
5037 init_list_head(&f->full_slabs);
5038 init_list_head(&f->lru_table);
5040 if (f->conf.modules) {
5044 for (module = f->conf.modules;
module;
module = next) {
5046 for (p = module; *p && *p !=
':'; p++);
5047 next = *p ? p + 1 : NULL;
5050 fuse_push_module(f, module, args) == -1)
5055 if (!f->conf.ac_attr_timeout_set)
5056 f->conf.ac_attr_timeout = f->conf.attr_timeout;
5058#if defined(__FreeBSD__) || defined(__NetBSD__)
5063 f->conf.readdir_ino = 1;
5067 struct fuse_session *fuse_session_new_versioned(
5071 f->se = fuse_session_new_versioned(args, &llop,
sizeof(llop), version,
5077 f->fs->debug = f->conf.debug;
5080 if (node_table_init(&f->name_table) == -1)
5081 goto out_free_session;
5083 if (node_table_init(&f->id_table) == -1)
5084 goto out_free_name_table;
5086 pthread_mutex_init(&f->lock, NULL);
5088 root = alloc_node(f);
5090 fuse_log(FUSE_LOG_ERR,
"fuse: memory allocation failed\n");
5091 goto out_free_id_table;
5093 if (lru_enabled(f)) {
5094 struct node_lru *lnode = node_lru(root);
5095 init_list_head(&lnode->lru);
5098 strcpy(root->inline_name,
"/");
5099 root->name = root->inline_name;
5100 root->parent = NULL;
5101 root->nodeid = FUSE_ROOT_ID;
5108 free(f->id_table.array);
5110 free(f->name_table.array);
5115 free(f->conf.modules);
5116out_delete_context_key:
5117 fuse_delete_context_key();
5125FUSE_SYMVER(
"_fuse_new_30",
"_fuse_new@FUSE_3.0")
5126struct fuse *_fuse_new_30(struct
fuse_args *args,
5135 FUSE_LIB_OPT(
"-h", show_help, 1),
5136 FUSE_LIB_OPT(
"--help", show_help, 1),
5141 fuse_lib_opt_proc) == -1)
5148 return _fuse_new_31(args, op, op_size, version, user_data);
5153 size_t op_size,
void *user_data);
5154FUSE_SYMVER(
"fuse_new_31",
"fuse_new@FUSE_3.1")
5155struct fuse *fuse_new_31(struct
fuse_args *args,
5157 size_t op_size,
void *user_data)
5162 return _fuse_new_31(args, op, op_size, &version, user_data);
5170 size_t op_size,
void *user_data);
5171FUSE_SYMVER(
"fuse_new_30",
"fuse_new@FUSE_3.0")
5172struct fuse *fuse_new_30(struct
fuse_args *args,
5174 size_t op_size,
void *user_data)
5179 FUSE_LIB_OPT(
"-h", show_help, 1),
5180 FUSE_LIB_OPT(
"--help", show_help, 1),
5185 fuse_lib_opt_proc) == -1)
5192 return fuse_new_31(args, op, op_size, user_data);
5200 if (f->conf.intr && f->intr_installed)
5201 fuse_restore_intr_signal(f->conf.intr_signal);
5204 fuse_create_context(f);
5206 for (i = 0; i < f->id_table.size; i++) {
5209 for (node = f->id_table.array[i]; node != NULL;
5210 node = node->id_next) {
5211 if (node->is_hidden) {
5213 if (try_get_path(f, node->nodeid, NULL, &path, NULL,
false) == 0) {
5214 fuse_fs_unlink(f->fs, path);
5221 for (i = 0; i < f->id_table.size; i++) {
5225 for (node = f->id_table.array[i]; node != NULL; node = next) {
5226 next = node->id_next;
5231 assert(list_empty(&f->partial_slabs));
5232 assert(list_empty(&f->full_slabs));
5234 while (fuse_modules) {
5235 fuse_put_module(fuse_modules);
5237 free(f->id_table.array);
5238 free(f->name_table.array);
5239 pthread_mutex_destroy(&f->lock);
5242 free(f->conf.modules);
5244 fuse_delete_context_key();
5247int fuse_mount(
struct fuse *f,
const char *mountpoint) {
5258 return FUSE_VERSION;
5263 return PACKAGE_VERSION;
int fuse_getgroups(int size, gid_t list[])
int fuse_mount(struct fuse *f, const char *mountpoint)
int fuse_interrupted(void)
void fuse_destroy(struct fuse *f)
int fuse_start_cleanup_thread(struct fuse *fuse)
int fuse_invalidate_path(struct fuse *f, const char *path)
struct fuse_fs *(* fuse_module_factory_t)(struct fuse_args *args, struct fuse_fs *fs[])
struct fuse_context * fuse_get_context(void)
int fuse_loop(struct fuse *f)
int(* fuse_fill_dir_t)(void *buf, const char *name, const struct stat *stbuf, off_t off, enum fuse_fill_dir_flags flags)
void fuse_exit(struct fuse *f)
int fuse_clean_cache(struct fuse *fuse)
void fuse_lib_help(struct fuse_args *args)
struct fuse_session * fuse_get_session(struct fuse *f)
void fuse_unmount(struct fuse *f)
struct fuse_fs * fuse_fs_new(const struct fuse_operations *op, size_t op_size, void *private_data)
void fuse_stop_cleanup_thread(struct fuse *fuse)
void fuse_unset_feature_flag(struct fuse_conn_info *conn, uint64_t flag)
bool fuse_set_feature_flag(struct fuse_conn_info *conn, uint64_t flag)
#define FUSE_CAP_SPLICE_READ
size_t fuse_buf_size(const struct fuse_bufvec *bufv)
#define FUSE_CAP_EXPORT_SUPPORT
#define FUSE_CAP_POSIX_LOCKS
ssize_t fuse_buf_copy(struct fuse_bufvec *dst, struct fuse_bufvec *src, enum fuse_buf_copy_flags flags)
const char * fuse_pkgversion(void)
#define FUSE_CAP_FLOCK_LOCKS
void fuse_log(enum fuse_log_level level, const char *fmt,...)
void fuse_session_destroy(struct fuse_session *se)
int fuse_reply_data(fuse_req_t req, struct fuse_bufvec *bufv, enum fuse_buf_copy_flags flags)
int fuse_reply_lock(fuse_req_t req, const struct flock *lock)
int fuse_reply_open(fuse_req_t req, const struct fuse_file_info *fi)
void fuse_session_exit(struct fuse_session *se)
int fuse_reply_poll(fuse_req_t req, unsigned revents)
int fuse_reply_err(fuse_req_t req, int err)
const struct fuse_ctx * fuse_req_ctx(fuse_req_t req)
void * fuse_req_userdata(fuse_req_t req)
int fuse_reply_buf(fuse_req_t req, const char *buf, size_t size)
struct fuse_req * fuse_req_t
size_t fuse_add_direntry_plus(fuse_req_t req, char *buf, size_t bufsize, const char *name, const struct fuse_entry_param *e, off_t off)
int fuse_session_exited(struct fuse_session *se)
int fuse_req_interrupted(fuse_req_t req)
int fuse_req_getgroups(fuse_req_t req, int size, gid_t list[])
int fuse_reply_readlink(fuse_req_t req, const char *link)
int fuse_session_loop(struct fuse_session *se)
int fuse_reply_bmap(fuse_req_t req, uint64_t idx)
int fuse_reply_entry(fuse_req_t req, const struct fuse_entry_param *e)
void fuse_session_unmount(struct fuse_session *se)
void fuse_reply_none(fuse_req_t req)
void fuse_lowlevel_help(void)
int fuse_lowlevel_notify_inval_inode(struct fuse_session *se, fuse_ino_t ino, off_t off, off_t len)
int fuse_reply_statfs(fuse_req_t req, const struct statvfs *stbuf)
int fuse_reply_write(fuse_req_t req, size_t count)
int fuse_session_mount(struct fuse_session *se, const char *mountpoint)
int fuse_lowlevel_notify_poll(struct fuse_pollhandle *ph)
void fuse_req_interrupt_func(fuse_req_t req, fuse_interrupt_func_t func, void *data)
int fuse_reply_create(fuse_req_t req, const struct fuse_entry_param *e, const struct fuse_file_info *fi)
int fuse_reply_lseek(fuse_req_t req, off_t off)
size_t fuse_add_direntry(fuse_req_t req, char *buf, size_t bufsize, const char *name, const struct stat *stbuf, off_t off)
int fuse_reply_attr(fuse_req_t req, const struct stat *attr, double attr_timeout)
int fuse_reply_ioctl(fuse_req_t req, int result, const void *buf, size_t size)
int fuse_reply_xattr(fuse_req_t req, size_t count)
int fuse_opt_add_arg(struct fuse_args *args, const char *arg)
void fuse_opt_free_args(struct fuse_args *args)
#define FUSE_OPT_KEY(templ, key)
int fuse_opt_parse(struct fuse_args *args, void *data, const struct fuse_opt opts[], fuse_opt_proc_t proc)
#define FUSE_OPT_KEY_KEEP
#define FUSE_ARGS_INIT(argc, argv)
struct fuse_context * fuse_get_context(void)
int fuse_reply_statx(fuse_req_t req, int flags, struct statx *statx, double attr_timeout)
enum fuse_buf_flags flags
uint32_t parallel_direct_writes
void(* getlk)(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi, struct flock *lock)
void(* init)(void *userdata, struct fuse_conn_info *conn)
void(* setlk)(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi, struct flock *lock, int sleep)