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 
10 /* For pthread_rwlock_t */
11 #define _GNU_SOURCE
12 
13 #include "config.h"
14 #include "fuse_i.h"
15 #include "fuse_lowlevel.h"
16 #include "fuse_opt.h"
17 #include "fuse_misc.h"
18 #include "fuse_common_compat.h"
19 #include "fuse_compat.h"
20 #include "fuse_kernel.h"
21 
22 #include <stdio.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include <stddef.h>
26 #include <stdbool.h>
27 #include <unistd.h>
28 #include <time.h>
29 #include <fcntl.h>
30 #include <limits.h>
31 #include <errno.h>
32 #include <signal.h>
33 #include <dlfcn.h>
34 #include <assert.h>
35 #include <poll.h>
36 #include <sys/param.h>
37 #include <sys/uio.h>
38 #include <sys/time.h>
39 #include <sys/mman.h>
40 #include <sys/file.h>
41 
42 #define FUSE_NODE_SLAB 1
43 
44 #ifndef MAP_ANONYMOUS
45 #undef FUSE_NODE_SLAB
46 #endif
47 
48 #define FUSE_DEFAULT_INTR_SIGNAL SIGUSR1
49 
50 #define FUSE_UNKNOWN_INO 0xffffffff
51 #define OFFSET_MAX 0x7fffffffffffffffLL
52 
53 #define NODE_TABLE_MIN_SIZE 8192
54 
55 struct fuse_config {
56 	unsigned int uid;
57 	unsigned int gid;
58 	unsigned int  umask;
59 	double entry_timeout;
60 	double negative_timeout;
61 	double attr_timeout;
62 	double ac_attr_timeout;
63 	int ac_attr_timeout_set;
64 	int remember;
65 	int nopath;
66 	int debug;
67 	int hard_remove;
68 	int use_ino;
69 	int readdir_ino;
70 	int set_mode;
71 	int set_uid;
72 	int set_gid;
73 	int direct_io;
74 	int kernel_cache;
75 	int auto_cache;
76 	int intr;
77 	int intr_signal;
78 	int help;
79 	char *modules;
80 };
81 
82 struct fuse_fs {
83 	struct fuse_operations op;
84 	struct fuse_module *m;
85 	void *user_data;
86 	int compat;
87 	int debug;
88 };
89 
90 struct fusemod_so {
91 	void *handle;
92 	int ctr;
93 };
94 
95 struct lock_queue_element {
96 	struct lock_queue_element *next;
97 	pthread_cond_t cond;
98 	fuse_ino_t nodeid1;
99 	const char *name1;
100 	char **path1;
101 	struct node **wnode1;
102 	fuse_ino_t nodeid2;
103 	const char *name2;
104 	char **path2;
105 	struct node **wnode2;
106 	int err;
107 	bool first_locked : 1;
108 	bool second_locked : 1;
109 	bool done : 1;
110 };
111 
112 struct node_table {
113 	struct node **array;
114 	size_t use;
115 	size_t size;
116 	size_t split;
117 };
118 
119 #define container_of(ptr, type, member) ({                              \
120                         const typeof( ((type *)0)->member ) *__mptr = (ptr); \
121                         (type *)( (char *)__mptr - offsetof(type,member) );})
122 
123 #define list_entry(ptr, type, member)           \
124         container_of(ptr, type, member)
125 
126 struct list_head {
127 	struct list_head *next;
128 	struct list_head *prev;
129 };
130 
131 struct node_slab {
132 	struct list_head list;  /* must be the first member */
133 	struct list_head freelist;
134 	int used;
135 };
136 
137 struct fuse {
138 	struct fuse_session *se;
139 	struct node_table name_table;
140 	struct node_table id_table;
141 	struct list_head lru_table;
142 	fuse_ino_t ctr;
143 	unsigned int generation;
144 	unsigned int hidectr;
145 	pthread_mutex_t lock;
146 	struct fuse_config conf;
147 	int intr_installed;
148 	struct fuse_fs *fs;
149 	int nullpath_ok;
150 	int utime_omit_ok;
151 	struct lock_queue_element *lockq;
152 	int pagesize;
153 	struct list_head partial_slabs;
154 	struct list_head full_slabs;
155 	pthread_t prune_thread;
156 };
157 
158 struct lock {
159 	int type;
160 	off_t start;
161 	off_t end;
162 	pid_t pid;
163 	uint64_t owner;
164 	struct lock *next;
165 };
166 
167 struct node {
168 	struct node *name_next;
169 	struct node *id_next;
170 	fuse_ino_t nodeid;
171 	unsigned int generation;
172 	int refctr;
173 	struct node *parent;
174 	char *name;
175 	uint64_t nlookup;
176 	int open_count;
177 	struct timespec stat_updated;
178 	struct timespec mtime;
179 	off_t size;
180 	struct lock *locks;
181 	unsigned int is_hidden : 1;
182 	unsigned int cache_valid : 1;
183 	int treelock;
184 	char inline_name[32];
185 };
186 
187 #define TREELOCK_WRITE -1
188 #define TREELOCK_WAIT_OFFSET INT_MIN
189 
190 struct node_lru {
191 	struct node node;
192 	struct list_head lru;
193 	struct timespec forget_time;
194 };
195 
196 struct fuse_dh {
197 	pthread_mutex_t lock;
198 	struct fuse *fuse;
199 	fuse_req_t req;
200 	char *contents;
201 	int allocated;
202 	unsigned len;
203 	unsigned size;
204 	unsigned needlen;
205 	int filled;
206 	uint64_t fh;
207 	int error;
208 	fuse_ino_t nodeid;
209 };
210 
211 /* old dir handle */
212 struct fuse_dirhandle {
213 	fuse_fill_dir_t filler;
214 	void *buf;
215 };
216 
217 struct fuse_context_i {
218 	struct fuse_context ctx;
219 	fuse_req_t req;
220 };
221 
222 static pthread_key_t fuse_context_key;
223 static pthread_mutex_t fuse_context_lock = PTHREAD_MUTEX_INITIALIZER;
224 static int fuse_context_ref;
225 static struct fusemod_so *fuse_current_so;
226 static struct fuse_module *fuse_modules;
227 
fuse_load_so_name(const char * soname)228 static int fuse_load_so_name(const char *soname)
229 {
230 	struct fusemod_so *so;
231 
232 	so = calloc(1, sizeof(struct fusemod_so));
233 	if (!so) {
234 		fprintf(stderr, "fuse: memory allocation failed\n");
235 		return -1;
236 	}
237 
238 	fuse_current_so = so;
239 	so->handle = dlopen(soname, RTLD_NOW);
240 	fuse_current_so = NULL;
241 	if (!so->handle) {
242 		fprintf(stderr, "fuse: %s\n", dlerror());
243 		goto err;
244 	}
245 	if (!so->ctr) {
246 		fprintf(stderr, "fuse: %s did not register any modules\n",
247 			soname);
248 		goto err;
249 	}
250 	return 0;
251 
252 err:
253 	if (so->handle)
254 		dlclose(so->handle);
255 	free(so);
256 	return -1;
257 }
258 
fuse_load_so_module(const char * module)259 static int fuse_load_so_module(const char *module)
260 {
261 	int res;
262 	char *soname = malloc(strlen(module) + 64);
263 	if (!soname) {
264 		fprintf(stderr, "fuse: memory allocation failed\n");
265 		return -1;
266 	}
267 	sprintf(soname, "libfusemod_%s.so", module);
268 	res = fuse_load_so_name(soname);
269 	free(soname);
270 	return res;
271 }
272 
fuse_find_module(const char * module)273 static struct fuse_module *fuse_find_module(const char *module)
274 {
275 	struct fuse_module *m;
276 	for (m = fuse_modules; m; m = m->next) {
277 		if (strcmp(module, m->name) == 0) {
278 			m->ctr++;
279 			break;
280 		}
281 	}
282 	return m;
283 }
284 
fuse_get_module(const char * module)285 static struct fuse_module *fuse_get_module(const char *module)
286 {
287 	struct fuse_module *m;
288 
289 	pthread_mutex_lock(&fuse_context_lock);
290 	m = fuse_find_module(module);
291 	if (!m) {
292 		int err = fuse_load_so_module(module);
293 		if (!err)
294 			m = fuse_find_module(module);
295 	}
296 	pthread_mutex_unlock(&fuse_context_lock);
297 	return m;
298 }
299 
fuse_put_module(struct fuse_module * m)300 static void fuse_put_module(struct fuse_module *m)
301 {
302 	pthread_mutex_lock(&fuse_context_lock);
303 	assert(m->ctr > 0);
304 	m->ctr--;
305 	if (!m->ctr && m->so) {
306 		struct fusemod_so *so = m->so;
307 		assert(so->ctr > 0);
308 		so->ctr--;
309 		if (!so->ctr) {
310 			struct fuse_module **mp;
311 			for (mp = &fuse_modules; *mp;) {
312 				if ((*mp)->so == so)
313 					*mp = (*mp)->next;
314 				else
315 					mp = &(*mp)->next;
316 			}
317 			dlclose(so->handle);
318 			free(so);
319 		}
320 	}
321 	pthread_mutex_unlock(&fuse_context_lock);
322 }
323 
init_list_head(struct list_head * list)324 static void init_list_head(struct list_head *list)
325 {
326 	list->next = list;
327 	list->prev = list;
328 }
329 
list_empty(const struct list_head * head)330 static int list_empty(const struct list_head *head)
331 {
332 	return head->next == head;
333 }
334 
list_add(struct list_head * new,struct list_head * prev,struct list_head * next)335 static void list_add(struct list_head *new, struct list_head *prev,
336 		     struct list_head *next)
337 {
338 	next->prev = new;
339 	new->next = next;
340 	new->prev = prev;
341 	prev->next = new;
342 }
343 
list_add_head(struct list_head * new,struct list_head * head)344 static inline void list_add_head(struct list_head *new, struct list_head *head)
345 {
346 	list_add(new, head, head->next);
347 }
348 
list_add_tail(struct list_head * new,struct list_head * head)349 static inline void list_add_tail(struct list_head *new, struct list_head *head)
350 {
351 	list_add(new, head->prev, head);
352 }
353 
list_del(struct list_head * entry)354 static inline void list_del(struct list_head *entry)
355 {
356 	struct list_head *prev = entry->prev;
357 	struct list_head *next = entry->next;
358 
359 	next->prev = prev;
360 	prev->next = next;
361 }
362 
lru_enabled(struct fuse * f)363 static inline int lru_enabled(struct fuse *f)
364 {
365 	return f->conf.remember > 0;
366 }
367 
node_lru(struct node * node)368 static struct node_lru *node_lru(struct node *node)
369 {
370 	return (struct node_lru *) node;
371 }
372 
get_node_size(struct fuse * f)373 static size_t get_node_size(struct fuse *f)
374 {
375 	if (lru_enabled(f))
376 		return sizeof(struct node_lru);
377 	else
378 		return sizeof(struct node);
379 }
380 
381 #ifdef FUSE_NODE_SLAB
list_to_slab(struct list_head * head)382 static struct node_slab *list_to_slab(struct list_head *head)
383 {
384 	return (struct node_slab *) head;
385 }
386 
node_to_slab(struct fuse * f,struct node * node)387 static struct node_slab *node_to_slab(struct fuse *f, struct node *node)
388 {
389 	return (struct node_slab *) (((uintptr_t) node) & ~((uintptr_t) f->pagesize - 1));
390 }
391 
alloc_slab(struct fuse * f)392 static int alloc_slab(struct fuse *f)
393 {
394 	void *mem;
395 	struct node_slab *slab;
396 	char *start;
397 	size_t num;
398 	size_t i;
399 	size_t node_size = get_node_size(f);
400 
401 	mem = mmap(NULL, f->pagesize, PROT_READ | PROT_WRITE,
402 		   MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
403 
404 	if (mem == MAP_FAILED)
405 		return -1;
406 
407 	slab = mem;
408 	init_list_head(&slab->freelist);
409 	slab->used = 0;
410 	num = (f->pagesize - sizeof(struct node_slab)) / node_size;
411 
412 	start = (char *) mem + f->pagesize - num * node_size;
413 	for (i = 0; i < num; i++) {
414 		struct list_head *n;
415 
416 		n = (struct list_head *) (start + i * node_size);
417 		list_add_tail(n, &slab->freelist);
418 	}
419 	list_add_tail(&slab->list, &f->partial_slabs);
420 
421 	return 0;
422 }
423 
alloc_node(struct fuse * f)424 static struct node *alloc_node(struct fuse *f)
425 {
426 	struct node_slab *slab;
427 	struct list_head *node;
428 
429 	if (list_empty(&f->partial_slabs)) {
430 		int res = alloc_slab(f);
431 		if (res != 0)
432 			return NULL;
433 	}
434 	slab = list_to_slab(f->partial_slabs.next);
435 	slab->used++;
436 	node = slab->freelist.next;
437 	list_del(node);
438 	if (list_empty(&slab->freelist)) {
439 		list_del(&slab->list);
440 		list_add_tail(&slab->list, &f->full_slabs);
441 	}
442 	memset(node, 0, sizeof(struct node));
443 
444 	return (struct node *) node;
445 }
446 
free_slab(struct fuse * f,struct node_slab * slab)447 static void free_slab(struct fuse *f, struct node_slab *slab)
448 {
449 	int res;
450 
451 	list_del(&slab->list);
452 	res = munmap(slab, f->pagesize);
453 	if (res == -1)
454 		fprintf(stderr, "fuse warning: munmap(%p) failed\n", slab);
455 }
456 
free_node_mem(struct fuse * f,struct node * node)457 static void free_node_mem(struct fuse *f, struct node *node)
458 {
459 	struct node_slab *slab = node_to_slab(f, node);
460 	struct list_head *n = (struct list_head *) node;
461 
462 	slab->used--;
463 	if (slab->used) {
464 		if (list_empty(&slab->freelist)) {
465 			list_del(&slab->list);
466 			list_add_tail(&slab->list, &f->partial_slabs);
467 		}
468 		list_add_head(n, &slab->freelist);
469 	} else {
470 		free_slab(f, slab);
471 	}
472 }
473 #else
alloc_node(struct fuse * f)474 static struct node *alloc_node(struct fuse *f)
475 {
476 	return (struct node *) calloc(1, get_node_size(f));
477 }
478 
free_node_mem(struct fuse * f,struct node * node)479 static void free_node_mem(struct fuse *f, struct node *node)
480 {
481 	(void) f;
482 	free(node);
483 }
484 #endif
485 
id_hash(struct fuse * f,fuse_ino_t ino)486 static size_t id_hash(struct fuse *f, fuse_ino_t ino)
487 {
488 	uint64_t hash = ((uint32_t) ino * 2654435761U) % f->id_table.size;
489 	uint64_t oldhash = hash % (f->id_table.size / 2);
490 
491 	if (oldhash >= f->id_table.split)
492 		return oldhash;
493 	else
494 		return hash;
495 }
496 
get_node_nocheck(struct fuse * f,fuse_ino_t nodeid)497 static struct node *get_node_nocheck(struct fuse *f, fuse_ino_t nodeid)
498 {
499 	size_t hash = id_hash(f, nodeid);
500 	struct node *node;
501 
502 	for (node = f->id_table.array[hash]; node != NULL; node = node->id_next)
503 		if (node->nodeid == nodeid)
504 			return node;
505 
506 	return NULL;
507 }
508 
get_node(struct fuse * f,fuse_ino_t nodeid)509 static struct node *get_node(struct fuse *f, fuse_ino_t nodeid)
510 {
511 	struct node *node = get_node_nocheck(f, nodeid);
512 	if (!node) {
513 		fprintf(stderr, "fuse internal error: node %llu not found\n",
514 			(unsigned long long) nodeid);
515 		abort();
516 	}
517 	return node;
518 }
519 
520 static void curr_time(struct timespec *now);
521 static double diff_timespec(const struct timespec *t1,
522 			   const struct timespec *t2);
523 
remove_node_lru(struct node * node)524 static void remove_node_lru(struct node *node)
525 {
526 	struct node_lru *lnode = node_lru(node);
527 	list_del(&lnode->lru);
528 	init_list_head(&lnode->lru);
529 }
530 
set_forget_time(struct fuse * f,struct node * node)531 static void set_forget_time(struct fuse *f, struct node *node)
532 {
533 	struct node_lru *lnode = node_lru(node);
534 
535 	list_del(&lnode->lru);
536 	list_add_tail(&lnode->lru, &f->lru_table);
537 	curr_time(&lnode->forget_time);
538 }
539 
free_node(struct fuse * f,struct node * node)540 static void free_node(struct fuse *f, struct node *node)
541 {
542 	if (node->name != node->inline_name)
543 		free(node->name);
544 	free_node_mem(f, node);
545 }
546 
node_table_reduce(struct node_table * t)547 static void node_table_reduce(struct node_table *t)
548 {
549 	size_t newsize = t->size / 2;
550 	void *newarray;
551 
552 	if (newsize < NODE_TABLE_MIN_SIZE)
553 		return;
554 
555 	newarray = realloc(t->array, sizeof(struct node *) * newsize);
556 	if (newarray != NULL)
557 		t->array = newarray;
558 
559 	t->size = newsize;
560 	t->split = t->size / 2;
561 }
562 
remerge_id(struct fuse * f)563 static void remerge_id(struct fuse *f)
564 {
565 	struct node_table *t = &f->id_table;
566 	int iter;
567 
568 	if (t->split == 0)
569 		node_table_reduce(t);
570 
571 	for (iter = 8; t->split > 0 && iter; iter--) {
572 		struct node **upper;
573 
574 		t->split--;
575 		upper = &t->array[t->split + t->size / 2];
576 		if (*upper) {
577 			struct node **nodep;
578 
579 			for (nodep = &t->array[t->split]; *nodep;
580 			     nodep = &(*nodep)->id_next);
581 
582 			*nodep = *upper;
583 			*upper = NULL;
584 			break;
585 		}
586 	}
587 }
588 
unhash_id(struct fuse * f,struct node * node)589 static void unhash_id(struct fuse *f, struct node *node)
590 {
591 	struct node **nodep = &f->id_table.array[id_hash(f, node->nodeid)];
592 
593 	for (; *nodep != NULL; nodep = &(*nodep)->id_next)
594 		if (*nodep == node) {
595 			*nodep = node->id_next;
596 			f->id_table.use--;
597 
598 			if(f->id_table.use < f->id_table.size / 4)
599 				remerge_id(f);
600 			return;
601 		}
602 }
603 
node_table_resize(struct node_table * t)604 static int node_table_resize(struct node_table *t)
605 {
606 	size_t newsize = t->size * 2;
607 	void *newarray;
608 
609 	newarray = realloc(t->array, sizeof(struct node *) * newsize);
610 	if (newarray == NULL)
611 		return -1;
612 
613 	t->array = newarray;
614 	memset(t->array + t->size, 0, t->size * sizeof(struct node *));
615 	t->size = newsize;
616 	t->split = 0;
617 
618 	return 0;
619 }
620 
rehash_id(struct fuse * f)621 static void rehash_id(struct fuse *f)
622 {
623 	struct node_table *t = &f->id_table;
624 	struct node **nodep;
625 	struct node **next;
626 	size_t hash;
627 
628 	if (t->split == t->size / 2)
629 		return;
630 
631 	hash = t->split;
632 	t->split++;
633 	for (nodep = &t->array[hash]; *nodep != NULL; nodep = next) {
634 		struct node *node = *nodep;
635 		size_t newhash = id_hash(f, node->nodeid);
636 
637 		if (newhash != hash) {
638 			next = nodep;
639 			*nodep = node->id_next;
640 			node->id_next = t->array[newhash];
641 			t->array[newhash] = node;
642 		} else {
643 			next = &node->id_next;
644 		}
645 	}
646 	if (t->split == t->size / 2)
647 		node_table_resize(t);
648 }
649 
hash_id(struct fuse * f,struct node * node)650 static void hash_id(struct fuse *f, struct node *node)
651 {
652 	size_t hash = id_hash(f, node->nodeid);
653 	node->id_next = f->id_table.array[hash];
654 	f->id_table.array[hash] = node;
655 	f->id_table.use++;
656 
657 	if (f->id_table.use >= f->id_table.size / 2)
658 		rehash_id(f);
659 }
660 
name_hash(struct fuse * f,fuse_ino_t parent,const char * name)661 static size_t name_hash(struct fuse *f, fuse_ino_t parent,
662 			const char *name)
663 {
664 	uint64_t hash = parent;
665 	uint64_t oldhash;
666 
667 	for (; *name; name++)
668 		hash = hash * 31 + (unsigned char) *name;
669 
670 	hash %= f->name_table.size;
671 	oldhash = hash % (f->name_table.size / 2);
672 	if (oldhash >= f->name_table.split)
673 		return oldhash;
674 	else
675 		return hash;
676 }
677 
678 static void unref_node(struct fuse *f, struct node *node);
679 
remerge_name(struct fuse * f)680 static void remerge_name(struct fuse *f)
681 {
682 	struct node_table *t = &f->name_table;
683 	int iter;
684 
685 	if (t->split == 0)
686 		node_table_reduce(t);
687 
688 	for (iter = 8; t->split > 0 && iter; iter--) {
689 		struct node **upper;
690 
691 		t->split--;
692 		upper = &t->array[t->split + t->size / 2];
693 		if (*upper) {
694 			struct node **nodep;
695 
696 			for (nodep = &t->array[t->split]; *nodep;
697 			     nodep = &(*nodep)->name_next);
698 
699 			*nodep = *upper;
700 			*upper = NULL;
701 			break;
702 		}
703 	}
704 }
705 
unhash_name(struct fuse * f,struct node * node)706 static void unhash_name(struct fuse *f, struct node *node)
707 {
708 	if (node->name) {
709 		size_t hash = name_hash(f, node->parent->nodeid, node->name);
710 		struct node **nodep = &f->name_table.array[hash];
711 
712 		for (; *nodep != NULL; nodep = &(*nodep)->name_next)
713 			if (*nodep == node) {
714 				*nodep = node->name_next;
715 				node->name_next = NULL;
716 				unref_node(f, node->parent);
717 				if (node->name != node->inline_name)
718 					free(node->name);
719 				node->name = NULL;
720 				node->parent = NULL;
721 				f->name_table.use--;
722 
723 				if (f->name_table.use < f->name_table.size / 4)
724 					remerge_name(f);
725 				return;
726 			}
727 		fprintf(stderr,
728 			"fuse internal error: unable to unhash node: %llu\n",
729 			(unsigned long long) node->nodeid);
730 		abort();
731 	}
732 }
733 
rehash_name(struct fuse * f)734 static void rehash_name(struct fuse *f)
735 {
736 	struct node_table *t = &f->name_table;
737 	struct node **nodep;
738 	struct node **next;
739 	size_t hash;
740 
741 	if (t->split == t->size / 2)
742 		return;
743 
744 	hash = t->split;
745 	t->split++;
746 	for (nodep = &t->array[hash]; *nodep != NULL; nodep = next) {
747 		struct node *node = *nodep;
748 		size_t newhash = name_hash(f, node->parent->nodeid, node->name);
749 
750 		if (newhash != hash) {
751 			next = nodep;
752 			*nodep = node->name_next;
753 			node->name_next = t->array[newhash];
754 			t->array[newhash] = node;
755 		} else {
756 			next = &node->name_next;
757 		}
758 	}
759 	if (t->split == t->size / 2)
760 		node_table_resize(t);
761 }
762 
hash_name(struct fuse * f,struct node * node,fuse_ino_t parentid,const char * name)763 static int hash_name(struct fuse *f, struct node *node, fuse_ino_t parentid,
764 		     const char *name)
765 {
766 	size_t hash = name_hash(f, parentid, name);
767 	struct node *parent = get_node(f, parentid);
768 	if (strlen(name) < sizeof(node->inline_name)) {
769 		strcpy(node->inline_name, name);
770 		node->name = node->inline_name;
771 	} else {
772 		node->name = strdup(name);
773 		if (node->name == NULL)
774 			return -1;
775 	}
776 
777 	parent->refctr ++;
778 	node->parent = parent;
779 	node->name_next = f->name_table.array[hash];
780 	f->name_table.array[hash] = node;
781 	f->name_table.use++;
782 
783 	if (f->name_table.use >= f->name_table.size / 2)
784 		rehash_name(f);
785 
786 	return 0;
787 }
788 
delete_node(struct fuse * f,struct node * node)789 static void delete_node(struct fuse *f, struct node *node)
790 {
791 	if (f->conf.debug)
792 		fprintf(stderr, "DELETE: %llu\n",
793 			(unsigned long long) node->nodeid);
794 
795 	assert(node->treelock == 0);
796 	unhash_name(f, node);
797 	if (lru_enabled(f))
798 		remove_node_lru(node);
799 	unhash_id(f, node);
800 	free_node(f, node);
801 }
802 
unref_node(struct fuse * f,struct node * node)803 static void unref_node(struct fuse *f, struct node *node)
804 {
805 	assert(node->refctr > 0);
806 	node->refctr --;
807 	if (!node->refctr)
808 		delete_node(f, node);
809 }
810 
next_id(struct fuse * f)811 static fuse_ino_t next_id(struct fuse *f)
812 {
813 	do {
814 		f->ctr = (f->ctr + 1) & 0xffffffff;
815 		if (!f->ctr)
816 			f->generation ++;
817 	} while (f->ctr == 0 || f->ctr == FUSE_UNKNOWN_INO ||
818 		 get_node_nocheck(f, f->ctr) != NULL);
819 	return f->ctr;
820 }
821 
lookup_node(struct fuse * f,fuse_ino_t parent,const char * name)822 static struct node *lookup_node(struct fuse *f, fuse_ino_t parent,
823 				const char *name)
824 {
825 	size_t hash = name_hash(f, parent, name);
826 	struct node *node;
827 
828 	for (node = f->name_table.array[hash]; node != NULL; node = node->name_next)
829 		if (node->parent->nodeid == parent &&
830 		    strcmp(node->name, name) == 0)
831 			return node;
832 
833 	return NULL;
834 }
835 
inc_nlookup(struct node * node)836 static void inc_nlookup(struct node *node)
837 {
838 	if (!node->nlookup)
839 		node->refctr++;
840 	node->nlookup++;
841 }
842 
find_node(struct fuse * f,fuse_ino_t parent,const char * name)843 static struct node *find_node(struct fuse *f, fuse_ino_t parent,
844 			      const char *name)
845 {
846 	struct node *node;
847 
848 	pthread_mutex_lock(&f->lock);
849 	if (!name)
850 		node = get_node(f, parent);
851 	else
852 		node = lookup_node(f, parent, name);
853 	if (node == NULL) {
854 		node = alloc_node(f);
855 		if (node == NULL)
856 			goto out_err;
857 
858 		node->nodeid = next_id(f);
859 		node->generation = f->generation;
860 		if (f->conf.remember)
861 			inc_nlookup(node);
862 
863 		if (hash_name(f, node, parent, name) == -1) {
864 			free_node(f, node);
865 			node = NULL;
866 			goto out_err;
867 		}
868 		hash_id(f, node);
869 		if (lru_enabled(f)) {
870 			struct node_lru *lnode = node_lru(node);
871 			init_list_head(&lnode->lru);
872 		}
873 	} else if (lru_enabled(f) && node->nlookup == 1) {
874 		remove_node_lru(node);
875 	}
876 	inc_nlookup(node);
877 out_err:
878 	pthread_mutex_unlock(&f->lock);
879 	return node;
880 }
881 
add_name(char ** buf,unsigned * bufsize,char * s,const char * name)882 static char *add_name(char **buf, unsigned *bufsize, char *s, const char *name)
883 {
884 	size_t len = strlen(name);
885 
886 	if (s - len <= *buf) {
887 		unsigned pathlen = *bufsize - (s - *buf);
888 		unsigned newbufsize = *bufsize;
889 		char *newbuf;
890 
891 		while (newbufsize < pathlen + len + 1) {
892 			if (newbufsize >= 0x80000000)
893 				newbufsize = 0xffffffff;
894 			else
895 				newbufsize *= 2;
896 		}
897 
898 		newbuf = realloc(*buf, newbufsize);
899 		if (newbuf == NULL)
900 			return NULL;
901 
902 		*buf = newbuf;
903 		s = newbuf + newbufsize - pathlen;
904 		memmove(s, newbuf + *bufsize - pathlen, pathlen);
905 		*bufsize = newbufsize;
906 	}
907 	s -= len;
908 	strncpy(s, name, len);
909 	s--;
910 	*s = '/';
911 
912 	return s;
913 }
914 
unlock_path(struct fuse * f,fuse_ino_t nodeid,struct node * wnode,struct node * end)915 static void unlock_path(struct fuse *f, fuse_ino_t nodeid, struct node *wnode,
916 			struct node *end)
917 {
918 	struct node *node;
919 
920 	if (wnode) {
921 		assert(wnode->treelock == TREELOCK_WRITE);
922 		wnode->treelock = 0;
923 	}
924 
925 	for (node = get_node(f, nodeid);
926 	     node != end && node->nodeid != FUSE_ROOT_ID; node = node->parent) {
927 		assert(node->treelock != 0);
928 		assert(node->treelock != TREELOCK_WAIT_OFFSET);
929 		assert(node->treelock != TREELOCK_WRITE);
930 		node->treelock--;
931 		if (node->treelock == TREELOCK_WAIT_OFFSET)
932 			node->treelock = 0;
933 	}
934 }
935 
try_get_path(struct fuse * f,fuse_ino_t nodeid,const char * name,char ** path,struct node ** wnodep,bool need_lock)936 static int try_get_path(struct fuse *f, fuse_ino_t nodeid, const char *name,
937 			char **path, struct node **wnodep, bool need_lock)
938 {
939 	unsigned bufsize = 256;
940 	char *buf;
941 	char *s;
942 	struct node *node;
943 	struct node *wnode = NULL;
944 	int err;
945 
946 	*path = NULL;
947 
948 	err = -ENOMEM;
949 	buf = malloc(bufsize);
950 	if (buf == NULL)
951 		goto out_err;
952 
953 	s = buf + bufsize - 1;
954 	*s = '\0';
955 
956 	if (name != NULL) {
957 		s = add_name(&buf, &bufsize, s, name);
958 		err = -ENOMEM;
959 		if (s == NULL)
960 			goto out_free;
961 	}
962 
963 	if (wnodep) {
964 		assert(need_lock);
965 		wnode = lookup_node(f, nodeid, name);
966 		if (wnode) {
967 			if (wnode->treelock != 0) {
968 				if (wnode->treelock > 0)
969 					wnode->treelock += TREELOCK_WAIT_OFFSET;
970 				err = -EAGAIN;
971 				goto out_free;
972 			}
973 			wnode->treelock = TREELOCK_WRITE;
974 		}
975 	}
976 
977 	for (node = get_node(f, nodeid); node->nodeid != FUSE_ROOT_ID;
978 	     node = node->parent) {
979 		err = -ENOENT;
980 		if (node->name == NULL || node->parent == NULL)
981 			goto out_unlock;
982 
983 		err = -ENOMEM;
984 		s = add_name(&buf, &bufsize, s, node->name);
985 		if (s == NULL)
986 			goto out_unlock;
987 
988 		if (need_lock) {
989 			err = -EAGAIN;
990 			if (node->treelock < 0)
991 				goto out_unlock;
992 
993 			node->treelock++;
994 		}
995 	}
996 
997 	if (s[0])
998 		memmove(buf, s, bufsize - (s - buf));
999 	else
1000 		strcpy(buf, "/");
1001 
1002 	*path = buf;
1003 	if (wnodep)
1004 		*wnodep = wnode;
1005 
1006 	return 0;
1007 
1008  out_unlock:
1009 	if (need_lock)
1010 		unlock_path(f, nodeid, wnode, node);
1011  out_free:
1012 	free(buf);
1013 
1014  out_err:
1015 	return err;
1016 }
1017 
queue_element_unlock(struct fuse * f,struct lock_queue_element * qe)1018 static void queue_element_unlock(struct fuse *f, struct lock_queue_element *qe)
1019 {
1020 	struct node *wnode;
1021 
1022 	if (qe->first_locked) {
1023 		wnode = qe->wnode1 ? *qe->wnode1 : NULL;
1024 		unlock_path(f, qe->nodeid1, wnode, NULL);
1025 		qe->first_locked = false;
1026 	}
1027 	if (qe->second_locked) {
1028 		wnode = qe->wnode2 ? *qe->wnode2 : NULL;
1029 		unlock_path(f, qe->nodeid2, wnode, NULL);
1030 		qe->second_locked = false;
1031 	}
1032 }
1033 
queue_element_wakeup(struct fuse * f,struct lock_queue_element * qe)1034 static void queue_element_wakeup(struct fuse *f, struct lock_queue_element *qe)
1035 {
1036 	int err;
1037 	bool first = (qe == f->lockq);
1038 
1039 	if (!qe->path1) {
1040 		/* Just waiting for it to be unlocked */
1041 		if (get_node(f, qe->nodeid1)->treelock == 0)
1042 			pthread_cond_signal(&qe->cond);
1043 
1044 		return;
1045 	}
1046 
1047 	if (!qe->first_locked) {
1048 		err = try_get_path(f, qe->nodeid1, qe->name1, qe->path1,
1049 				   qe->wnode1, true);
1050 		if (!err)
1051 			qe->first_locked = true;
1052 		else if (err != -EAGAIN)
1053 			goto err_unlock;
1054 	}
1055 	if (!qe->second_locked && qe->path2) {
1056 		err = try_get_path(f, qe->nodeid2, qe->name2, qe->path2,
1057 				   qe->wnode2, true);
1058 		if (!err)
1059 			qe->second_locked = true;
1060 		else if (err != -EAGAIN)
1061 			goto err_unlock;
1062 	}
1063 
1064 	if (qe->first_locked && (qe->second_locked || !qe->path2)) {
1065 		err = 0;
1066 		goto done;
1067 	}
1068 
1069 	/*
1070 	 * Only let the first element be partially locked otherwise there could
1071 	 * be a deadlock.
1072 	 *
1073 	 * But do allow the first element to be partially locked to prevent
1074 	 * starvation.
1075 	 */
1076 	if (!first)
1077 		queue_element_unlock(f, qe);
1078 
1079 	/* keep trying */
1080 	return;
1081 
1082 err_unlock:
1083 	queue_element_unlock(f, qe);
1084 done:
1085 	qe->err = err;
1086 	qe->done = true;
1087 	pthread_cond_signal(&qe->cond);
1088 }
1089 
wake_up_queued(struct fuse * f)1090 static void wake_up_queued(struct fuse *f)
1091 {
1092 	struct lock_queue_element *qe;
1093 
1094 	for (qe = f->lockq; qe != NULL; qe = qe->next)
1095 		queue_element_wakeup(f, qe);
1096 }
1097 
debug_path(struct fuse * f,const char * msg,fuse_ino_t nodeid,const char * name,bool wr)1098 static void debug_path(struct fuse *f, const char *msg, fuse_ino_t nodeid,
1099 		       const char *name, bool wr)
1100 {
1101 	if (f->conf.debug) {
1102 		struct node *wnode = NULL;
1103 
1104 		if (wr)
1105 			wnode = lookup_node(f, nodeid, name);
1106 
1107 		if (wnode)
1108 			fprintf(stderr, "%s %li (w)\n",	msg, wnode->nodeid);
1109 		else
1110 			fprintf(stderr, "%s %li\n", msg, nodeid);
1111 	}
1112 }
1113 
queue_path(struct fuse * f,struct lock_queue_element * qe)1114 static void queue_path(struct fuse *f, struct lock_queue_element *qe)
1115 {
1116 	struct lock_queue_element **qp;
1117 
1118 	qe->done = false;
1119 	qe->first_locked = false;
1120 	qe->second_locked = false;
1121 	pthread_cond_init(&qe->cond, NULL);
1122 	qe->next = NULL;
1123 	for (qp = &f->lockq; *qp != NULL; qp = &(*qp)->next);
1124 	*qp = qe;
1125 }
1126 
dequeue_path(struct fuse * f,struct lock_queue_element * qe)1127 static void dequeue_path(struct fuse *f, struct lock_queue_element *qe)
1128 {
1129 	struct lock_queue_element **qp;
1130 
1131 	pthread_cond_destroy(&qe->cond);
1132 	for (qp = &f->lockq; *qp != qe; qp = &(*qp)->next);
1133 	*qp = qe->next;
1134 }
1135 
wait_path(struct fuse * f,struct lock_queue_element * qe)1136 static int wait_path(struct fuse *f, struct lock_queue_element *qe)
1137 {
1138 	queue_path(f, qe);
1139 
1140 	do {
1141 		pthread_cond_wait(&qe->cond, &f->lock);
1142 	} while (!qe->done);
1143 
1144 	dequeue_path(f, qe);
1145 
1146 	return qe->err;
1147 }
1148 
get_path_common(struct fuse * f,fuse_ino_t nodeid,const char * name,char ** path,struct node ** wnode)1149 static int get_path_common(struct fuse *f, fuse_ino_t nodeid, const char *name,
1150 			   char **path, struct node **wnode)
1151 {
1152 	int err;
1153 
1154 	pthread_mutex_lock(&f->lock);
1155 	err = try_get_path(f, nodeid, name, path, wnode, true);
1156 	if (err == -EAGAIN) {
1157 		struct lock_queue_element qe = {
1158 			.nodeid1 = nodeid,
1159 			.name1 = name,
1160 			.path1 = path,
1161 			.wnode1 = wnode,
1162 		};
1163 		debug_path(f, "QUEUE PATH", nodeid, name, !!wnode);
1164 		err = wait_path(f, &qe);
1165 		debug_path(f, "DEQUEUE PATH", nodeid, name, !!wnode);
1166 	}
1167 	pthread_mutex_unlock(&f->lock);
1168 
1169 	return err;
1170 }
1171 
get_path(struct fuse * f,fuse_ino_t nodeid,char ** path)1172 static int get_path(struct fuse *f, fuse_ino_t nodeid, char **path)
1173 {
1174 	return get_path_common(f, nodeid, NULL, path, NULL);
1175 }
1176 
get_path_nullok(struct fuse * f,fuse_ino_t nodeid,char ** path)1177 static int get_path_nullok(struct fuse *f, fuse_ino_t nodeid, char **path)
1178 {
1179 	int err = 0;
1180 
1181 	if (f->conf.nopath) {
1182 		*path = NULL;
1183 	} else {
1184 		err = get_path_common(f, nodeid, NULL, path, NULL);
1185 		if (err == -ENOENT && f->nullpath_ok)
1186 			err = 0;
1187 	}
1188 
1189 	return err;
1190 }
1191 
get_path_name(struct fuse * f,fuse_ino_t nodeid,const char * name,char ** path)1192 static int get_path_name(struct fuse *f, fuse_ino_t nodeid, const char *name,
1193 			 char **path)
1194 {
1195 	return get_path_common(f, nodeid, name, path, NULL);
1196 }
1197 
get_path_wrlock(struct fuse * f,fuse_ino_t nodeid,const char * name,char ** path,struct node ** wnode)1198 static int get_path_wrlock(struct fuse *f, fuse_ino_t nodeid, const char *name,
1199 			   char **path, struct node **wnode)
1200 {
1201 	return get_path_common(f, nodeid, name, path, wnode);
1202 }
1203 
1204 #if defined(__FreeBSD__) || defined(__DragonFly__)
1205 #define CHECK_DIR_LOOP
1206 #endif
1207 
1208 #if defined(CHECK_DIR_LOOP)
check_dir_loop(struct fuse * f,fuse_ino_t nodeid1,const char * name1,fuse_ino_t nodeid2,const char * name2)1209 static int check_dir_loop(struct fuse *f,
1210 			  fuse_ino_t nodeid1, const char *name1,
1211 			  fuse_ino_t nodeid2, const char *name2)
1212 {
1213 	struct node *node, *node1, *node2;
1214 	fuse_ino_t id1, id2;
1215 
1216 	node1 = lookup_node(f, nodeid1, name1);
1217 	id1 = node1 ? node1->nodeid : nodeid1;
1218 
1219 	node2 = lookup_node(f, nodeid2, name2);
1220 	id2 = node2 ? node2->nodeid : nodeid2;
1221 
1222 	for (node = get_node(f, id2); node->nodeid != FUSE_ROOT_ID;
1223 	     node = node->parent) {
1224 		if (node->name == NULL || node->parent == NULL)
1225 			break;
1226 
1227 		if (node->nodeid != id2 && node->nodeid == id1)
1228 			return -EINVAL;
1229 	}
1230 
1231 	if (node2)
1232 	{
1233 		for (node = get_node(f, id1); node->nodeid != FUSE_ROOT_ID;
1234 		     node = node->parent) {
1235 			if (node->name == NULL || node->parent == NULL)
1236 				break;
1237 
1238 			if (node->nodeid != id1 && node->nodeid == id2)
1239 				return -ENOTEMPTY;
1240 		}
1241 	}
1242 
1243 	return 0;
1244 }
1245 #endif
1246 
try_get_path2(struct fuse * f,fuse_ino_t nodeid1,const char * name1,fuse_ino_t nodeid2,const char * name2,char ** path1,char ** path2,struct node ** wnode1,struct node ** wnode2)1247 static int try_get_path2(struct fuse *f, fuse_ino_t nodeid1, const char *name1,
1248 			 fuse_ino_t nodeid2, const char *name2,
1249 			 char **path1, char **path2,
1250 			 struct node **wnode1, struct node **wnode2)
1251 {
1252 	int err;
1253 
1254 	/* FIXME: locking two paths needs deadlock checking */
1255 	err = try_get_path(f, nodeid1, name1, path1, wnode1, true);
1256 	if (!err) {
1257 		err = try_get_path(f, nodeid2, name2, path2, wnode2, true);
1258 		if (err) {
1259 			struct node *wn1 = wnode1 ? *wnode1 : NULL;
1260 
1261 			unlock_path(f, nodeid1, wn1, NULL);
1262 			free(*path1);
1263 		}
1264 	}
1265 	return err;
1266 }
1267 
get_path2(struct fuse * f,fuse_ino_t nodeid1,const char * name1,fuse_ino_t nodeid2,const char * name2,char ** path1,char ** path2,struct node ** wnode1,struct node ** wnode2)1268 static int get_path2(struct fuse *f, fuse_ino_t nodeid1, const char *name1,
1269 		     fuse_ino_t nodeid2, const char *name2,
1270 		     char **path1, char **path2,
1271 		     struct node **wnode1, struct node **wnode2)
1272 {
1273 	int err;
1274 
1275 	pthread_mutex_lock(&f->lock);
1276 
1277 #if defined(CHECK_DIR_LOOP)
1278 	if (name1)
1279 	{
1280 		// called during rename; perform dir loop check
1281 		err = check_dir_loop(f, nodeid1, name1, nodeid2, name2);
1282 		if (err)
1283 			goto out_unlock;
1284 	}
1285 #endif
1286 
1287 	err = try_get_path2(f, nodeid1, name1, nodeid2, name2,
1288 			    path1, path2, wnode1, wnode2);
1289 	if (err == -EAGAIN) {
1290 		struct lock_queue_element qe = {
1291 			.nodeid1 = nodeid1,
1292 			.name1 = name1,
1293 			.path1 = path1,
1294 			.wnode1 = wnode1,
1295 			.nodeid2 = nodeid2,
1296 			.name2 = name2,
1297 			.path2 = path2,
1298 			.wnode2 = wnode2,
1299 		};
1300 
1301 		debug_path(f, "QUEUE PATH1", nodeid1, name1, !!wnode1);
1302 		debug_path(f, "      PATH2", nodeid2, name2, !!wnode2);
1303 		err = wait_path(f, &qe);
1304 		debug_path(f, "DEQUEUE PATH1", nodeid1, name1, !!wnode1);
1305 		debug_path(f, "        PATH2", nodeid2, name2, !!wnode2);
1306 	}
1307 
1308 #if defined(CHECK_DIR_LOOP)
1309 out_unlock:
1310 #endif
1311 	pthread_mutex_unlock(&f->lock);
1312 
1313 	return err;
1314 }
1315 
free_path_wrlock(struct fuse * f,fuse_ino_t nodeid,struct node * wnode,char * path)1316 static void free_path_wrlock(struct fuse *f, fuse_ino_t nodeid,
1317 			     struct node *wnode, char *path)
1318 {
1319 	pthread_mutex_lock(&f->lock);
1320 	unlock_path(f, nodeid, wnode, NULL);
1321 	if (f->lockq)
1322 		wake_up_queued(f);
1323 	pthread_mutex_unlock(&f->lock);
1324 	free(path);
1325 }
1326 
free_path(struct fuse * f,fuse_ino_t nodeid,char * path)1327 static void free_path(struct fuse *f, fuse_ino_t nodeid, char *path)
1328 {
1329 	if (path)
1330 		free_path_wrlock(f, nodeid, NULL, path);
1331 }
1332 
free_path2(struct fuse * f,fuse_ino_t nodeid1,fuse_ino_t nodeid2,struct node * wnode1,struct node * wnode2,char * path1,char * path2)1333 static void free_path2(struct fuse *f, fuse_ino_t nodeid1, fuse_ino_t nodeid2,
1334 		       struct node *wnode1, struct node *wnode2,
1335 		       char *path1, char *path2)
1336 {
1337 	pthread_mutex_lock(&f->lock);
1338 	unlock_path(f, nodeid1, wnode1, NULL);
1339 	unlock_path(f, nodeid2, wnode2, NULL);
1340 	wake_up_queued(f);
1341 	pthread_mutex_unlock(&f->lock);
1342 	free(path1);
1343 	free(path2);
1344 }
1345 
forget_node(struct fuse * f,fuse_ino_t nodeid,uint64_t nlookup)1346 static void forget_node(struct fuse *f, fuse_ino_t nodeid, uint64_t nlookup)
1347 {
1348 	struct node *node;
1349 	if (nodeid == FUSE_ROOT_ID)
1350 		return;
1351 	pthread_mutex_lock(&f->lock);
1352 	node = get_node(f, nodeid);
1353 
1354 	/*
1355 	 * Node may still be locked due to interrupt idiocy in open,
1356 	 * create and opendir
1357 	 */
1358 	while (node->nlookup == nlookup && node->treelock) {
1359 		struct lock_queue_element qe = {
1360 			.nodeid1 = nodeid,
1361 		};
1362 
1363 		debug_path(f, "QUEUE PATH (forget)", nodeid, NULL, false);
1364 		queue_path(f, &qe);
1365 
1366 		do {
1367 			pthread_cond_wait(&qe.cond, &f->lock);
1368 		} while (node->nlookup == nlookup && node->treelock);
1369 
1370 		dequeue_path(f, &qe);
1371 		debug_path(f, "DEQUEUE_PATH (forget)", nodeid, NULL, false);
1372 	}
1373 
1374 	assert(node->nlookup >= nlookup);
1375 	node->nlookup -= nlookup;
1376 	if (!node->nlookup) {
1377 		unref_node(f, node);
1378 	} else if (lru_enabled(f) && node->nlookup == 1) {
1379 		set_forget_time(f, node);
1380 	}
1381 	pthread_mutex_unlock(&f->lock);
1382 }
1383 
unlink_node(struct fuse * f,struct node * node)1384 static void unlink_node(struct fuse *f, struct node *node)
1385 {
1386 	if (f->conf.remember) {
1387 		assert(node->nlookup > 1);
1388 		node->nlookup--;
1389 	}
1390 	unhash_name(f, node);
1391 }
1392 
remove_node(struct fuse * f,fuse_ino_t dir,const char * name)1393 static void remove_node(struct fuse *f, fuse_ino_t dir, const char *name)
1394 {
1395 	struct node *node;
1396 
1397 	pthread_mutex_lock(&f->lock);
1398 	node = lookup_node(f, dir, name);
1399 	if (node != NULL)
1400 		unlink_node(f, node);
1401 	pthread_mutex_unlock(&f->lock);
1402 }
1403 
rename_node(struct fuse * f,fuse_ino_t olddir,const char * oldname,fuse_ino_t newdir,const char * newname,int hide)1404 static int rename_node(struct fuse *f, fuse_ino_t olddir, const char *oldname,
1405 		       fuse_ino_t newdir, const char *newname, int hide)
1406 {
1407 	struct node *node;
1408 	struct node *newnode;
1409 	int err = 0;
1410 
1411 	pthread_mutex_lock(&f->lock);
1412 	node  = lookup_node(f, olddir, oldname);
1413 	newnode	 = lookup_node(f, newdir, newname);
1414 	if (node == NULL)
1415 		goto out;
1416 
1417 	if (newnode != NULL) {
1418 		if (hide) {
1419 			fprintf(stderr, "fuse: hidden file got created during hiding\n");
1420 			err = -EBUSY;
1421 			goto out;
1422 		}
1423 		unlink_node(f, newnode);
1424 	}
1425 
1426 	unhash_name(f, node);
1427 	if (hash_name(f, node, newdir, newname) == -1) {
1428 		err = -ENOMEM;
1429 		goto out;
1430 	}
1431 
1432 	if (hide)
1433 		node->is_hidden = 1;
1434 
1435 out:
1436 	pthread_mutex_unlock(&f->lock);
1437 	return err;
1438 }
1439 
set_stat(struct fuse * f,fuse_ino_t nodeid,struct stat * stbuf)1440 static void set_stat(struct fuse *f, fuse_ino_t nodeid, struct stat *stbuf)
1441 {
1442 	if (!f->conf.use_ino)
1443 		stbuf->st_ino = nodeid;
1444 	if (f->conf.set_mode)
1445 		stbuf->st_mode = (stbuf->st_mode & S_IFMT) |
1446 				 (0777 & ~f->conf.umask);
1447 	if (f->conf.set_uid)
1448 		stbuf->st_uid = f->conf.uid;
1449 	if (f->conf.set_gid)
1450 		stbuf->st_gid = f->conf.gid;
1451 }
1452 
req_fuse(fuse_req_t req)1453 static struct fuse *req_fuse(fuse_req_t req)
1454 {
1455 	return (struct fuse *) fuse_req_userdata(req);
1456 }
1457 
fuse_intr_sighandler(int sig)1458 static void fuse_intr_sighandler(int sig)
1459 {
1460 	(void) sig;
1461 	/* Nothing to do */
1462 }
1463 
1464 struct fuse_intr_data {
1465 	pthread_t id;
1466 	pthread_cond_t cond;
1467 	int finished;
1468 };
1469 
fuse_interrupt(fuse_req_t req,void * d_)1470 static void fuse_interrupt(fuse_req_t req, void *d_)
1471 {
1472 	struct fuse_intr_data *d = d_;
1473 	struct fuse *f = req_fuse(req);
1474 
1475 	if (d->id == pthread_self())
1476 		return;
1477 
1478 	pthread_mutex_lock(&f->lock);
1479 	while (!d->finished) {
1480 		struct timeval now;
1481 		struct timespec timeout;
1482 
1483 		pthread_kill(d->id, f->conf.intr_signal);
1484 		gettimeofday(&now, NULL);
1485 		timeout.tv_sec = now.tv_sec + 1;
1486 		timeout.tv_nsec = now.tv_usec * 1000;
1487 		pthread_cond_timedwait(&d->cond, &f->lock, &timeout);
1488 	}
1489 	pthread_mutex_unlock(&f->lock);
1490 }
1491 
fuse_do_finish_interrupt(struct fuse * f,fuse_req_t req,struct fuse_intr_data * d)1492 static void fuse_do_finish_interrupt(struct fuse *f, fuse_req_t req,
1493 				     struct fuse_intr_data *d)
1494 {
1495 	pthread_mutex_lock(&f->lock);
1496 	d->finished = 1;
1497 	pthread_cond_broadcast(&d->cond);
1498 	pthread_mutex_unlock(&f->lock);
1499 	fuse_req_interrupt_func(req, NULL, NULL);
1500 	pthread_cond_destroy(&d->cond);
1501 }
1502 
fuse_do_prepare_interrupt(fuse_req_t req,struct fuse_intr_data * d)1503 static void fuse_do_prepare_interrupt(fuse_req_t req, struct fuse_intr_data *d)
1504 {
1505 	d->id = pthread_self();
1506 	pthread_cond_init(&d->cond, NULL);
1507 	d->finished = 0;
1508 	fuse_req_interrupt_func(req, fuse_interrupt, d);
1509 }
1510 
fuse_finish_interrupt(struct fuse * f,fuse_req_t req,struct fuse_intr_data * d)1511 static inline void fuse_finish_interrupt(struct fuse *f, fuse_req_t req,
1512 					 struct fuse_intr_data *d)
1513 {
1514 	if (f->conf.intr)
1515 		fuse_do_finish_interrupt(f, req, d);
1516 }
1517 
fuse_prepare_interrupt(struct fuse * f,fuse_req_t req,struct fuse_intr_data * d)1518 static inline void fuse_prepare_interrupt(struct fuse *f, fuse_req_t req,
1519 					  struct fuse_intr_data *d)
1520 {
1521 	if (f->conf.intr)
1522 		fuse_do_prepare_interrupt(req, d);
1523 }
1524 
1525 #if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__DragonFly__)
1526 
fuse_compat_open(struct fuse_fs * fs,const char * path,struct fuse_file_info * fi)1527 static int fuse_compat_open(struct fuse_fs *fs, const char *path,
1528 			    struct fuse_file_info *fi)
1529 {
1530 	int err;
1531 	if (!fs->compat || fs->compat >= 25)
1532 		err = fs->op.open(path, fi);
1533 	else if (fs->compat == 22) {
1534 		struct fuse_file_info_compat tmp;
1535 		memcpy(&tmp, fi, sizeof(tmp));
1536 		err = ((struct fuse_operations_compat22 *) &fs->op)->open(path,
1537 									  &tmp);
1538 		memcpy(fi, &tmp, sizeof(tmp));
1539 		fi->fh = tmp.fh;
1540 	} else
1541 		err = ((struct fuse_operations_compat2 *) &fs->op)
1542 			->open(path, fi->flags);
1543 	return err;
1544 }
1545 
fuse_compat_release(struct fuse_fs * fs,const char * path,struct fuse_file_info * fi)1546 static int fuse_compat_release(struct fuse_fs *fs, const char *path,
1547 			       struct fuse_file_info *fi)
1548 {
1549 	if (!fs->compat || fs->compat >= 22)
1550 		return fs->op.release(path, fi);
1551 	else
1552 		return ((struct fuse_operations_compat2 *) &fs->op)
1553 			->release(path, fi->flags);
1554 }
1555 
fuse_compat_opendir(struct fuse_fs * fs,const char * path,struct fuse_file_info * fi)1556 static int fuse_compat_opendir(struct fuse_fs *fs, const char *path,
1557 			       struct fuse_file_info *fi)
1558 {
1559 	if (!fs->compat || fs->compat >= 25)
1560 		return fs->op.opendir(path, fi);
1561 	else {
1562 		int err;
1563 		struct fuse_file_info_compat tmp;
1564 		memcpy(&tmp, fi, sizeof(tmp));
1565 		err = ((struct fuse_operations_compat22 *) &fs->op)
1566 			->opendir(path, &tmp);
1567 		memcpy(fi, &tmp, sizeof(tmp));
1568 		fi->fh = tmp.fh;
1569 		return err;
1570 	}
1571 }
1572 
convert_statfs_compat(struct fuse_statfs_compat1 * compatbuf,struct statvfs * stbuf)1573 static void convert_statfs_compat(struct fuse_statfs_compat1 *compatbuf,
1574 				  struct statvfs *stbuf)
1575 {
1576 	stbuf->f_bsize	 = compatbuf->block_size;
1577 	stbuf->f_blocks	 = compatbuf->blocks;
1578 	stbuf->f_bfree	 = compatbuf->blocks_free;
1579 	stbuf->f_bavail	 = compatbuf->blocks_free;
1580 	stbuf->f_files	 = compatbuf->files;
1581 	stbuf->f_ffree	 = compatbuf->files_free;
1582 	stbuf->f_namemax = compatbuf->namelen;
1583 }
1584 
convert_statfs_old(struct statfs * oldbuf,struct statvfs * stbuf)1585 static void convert_statfs_old(struct statfs *oldbuf, struct statvfs *stbuf)
1586 {
1587 	stbuf->f_bsize	 = oldbuf->f_bsize;
1588 	stbuf->f_blocks	 = oldbuf->f_blocks;
1589 	stbuf->f_bfree	 = oldbuf->f_bfree;
1590 	stbuf->f_bavail	 = oldbuf->f_bavail;
1591 	stbuf->f_files	 = oldbuf->f_files;
1592 	stbuf->f_ffree	 = oldbuf->f_ffree;
1593 	stbuf->f_namemax = oldbuf->f_namelen;
1594 }
1595 
fuse_compat_statfs(struct fuse_fs * fs,const char * path,struct statvfs * buf)1596 static int fuse_compat_statfs(struct fuse_fs *fs, const char *path,
1597 			      struct statvfs *buf)
1598 {
1599 	int err;
1600 
1601 	if (!fs->compat || fs->compat >= 25) {
1602 		err = fs->op.statfs(fs->compat == 25 ? "/" : path, buf);
1603 	} else if (fs->compat > 11) {
1604 		struct statfs oldbuf;
1605 		err = ((struct fuse_operations_compat22 *) &fs->op)
1606 			->statfs("/", &oldbuf);
1607 		if (!err)
1608 			convert_statfs_old(&oldbuf, buf);
1609 	} else {
1610 		struct fuse_statfs_compat1 compatbuf;
1611 		memset(&compatbuf, 0, sizeof(struct fuse_statfs_compat1));
1612 		err = ((struct fuse_operations_compat1 *) &fs->op)
1613 			->statfs(&compatbuf);
1614 		if (!err)
1615 			convert_statfs_compat(&compatbuf, buf);
1616 	}
1617 	return err;
1618 }
1619 
1620 #else /* __FreeBSD__ || __NetBSD__ */
1621 
fuse_compat_open(struct fuse_fs * fs,char * path,struct fuse_file_info * fi)1622 static inline int fuse_compat_open(struct fuse_fs *fs, char *path,
1623 				   struct fuse_file_info *fi)
1624 {
1625 	return fs->op.open(path, fi);
1626 }
1627 
fuse_compat_release(struct fuse_fs * fs,const char * path,struct fuse_file_info * fi)1628 static inline int fuse_compat_release(struct fuse_fs *fs, const char *path,
1629 				      struct fuse_file_info *fi)
1630 {
1631 	return fs->op.release(path, fi);
1632 }
1633 
fuse_compat_opendir(struct fuse_fs * fs,const char * path,struct fuse_file_info * fi)1634 static inline int fuse_compat_opendir(struct fuse_fs *fs, const char *path,
1635 				      struct fuse_file_info *fi)
1636 {
1637 	return fs->op.opendir(path, fi);
1638 }
1639 
fuse_compat_statfs(struct fuse_fs * fs,const char * path,struct statvfs * buf)1640 static inline int fuse_compat_statfs(struct fuse_fs *fs, const char *path,
1641 				     struct statvfs *buf)
1642 {
1643 	return fs->op.statfs(fs->compat == 25 ? "/" : path, buf);
1644 }
1645 
1646 #endif /* __FreeBSD__ || __NetBSD__ */
1647 
fuse_fs_getattr(struct fuse_fs * fs,const char * path,struct stat * buf)1648 int fuse_fs_getattr(struct fuse_fs *fs, const char *path, struct stat *buf)
1649 {
1650 	fuse_get_context()->private_data = fs->user_data;
1651 	if (fs->op.getattr) {
1652 		if (fs->debug)
1653 			fprintf(stderr, "getattr %s\n", path);
1654 
1655 		return fs->op.getattr(path, buf);
1656 	} else {
1657 		return -ENOSYS;
1658 	}
1659 }
1660 
fuse_fs_fgetattr(struct fuse_fs * fs,const char * path,struct stat * buf,struct fuse_file_info * fi)1661 int fuse_fs_fgetattr(struct fuse_fs *fs, const char *path, struct stat *buf,
1662 		     struct fuse_file_info *fi)
1663 {
1664 	fuse_get_context()->private_data = fs->user_data;
1665 	if (fs->op.fgetattr) {
1666 		if (fs->debug)
1667 			fprintf(stderr, "fgetattr[%llu] %s\n",
1668 				(unsigned long long) fi->fh, path);
1669 
1670 		return fs->op.fgetattr(path, buf, fi);
1671 	} else if (path && fs->op.getattr) {
1672 		if (fs->debug)
1673 			fprintf(stderr, "getattr %s\n", path);
1674 
1675 		return fs->op.getattr(path, buf);
1676 	} else {
1677 		return -ENOSYS;
1678 	}
1679 }
1680 
fuse_fs_rename(struct fuse_fs * fs,const char * oldpath,const char * newpath)1681 int fuse_fs_rename(struct fuse_fs *fs, const char *oldpath,
1682 		   const char *newpath)
1683 {
1684 	fuse_get_context()->private_data = fs->user_data;
1685 	if (fs->op.rename) {
1686 		if (fs->debug)
1687 			fprintf(stderr, "rename %s %s\n", oldpath, newpath);
1688 
1689 		return fs->op.rename(oldpath, newpath);
1690 	} else {
1691 		return -ENOSYS;
1692 	}
1693 }
1694 
fuse_fs_unlink(struct fuse_fs * fs,const char * path)1695 int fuse_fs_unlink(struct fuse_fs *fs, const char *path)
1696 {
1697 	fuse_get_context()->private_data = fs->user_data;
1698 	if (fs->op.unlink) {
1699 		if (fs->debug)
1700 			fprintf(stderr, "unlink %s\n", path);
1701 
1702 		return fs->op.unlink(path);
1703 	} else {
1704 		return -ENOSYS;
1705 	}
1706 }
1707 
fuse_fs_rmdir(struct fuse_fs * fs,const char * path)1708 int fuse_fs_rmdir(struct fuse_fs *fs, const char *path)
1709 {
1710 	fuse_get_context()->private_data = fs->user_data;
1711 	if (fs->op.rmdir) {
1712 		if (fs->debug)
1713 			fprintf(stderr, "rmdir %s\n", path);
1714 
1715 		return fs->op.rmdir(path);
1716 	} else {
1717 		return -ENOSYS;
1718 	}
1719 }
1720 
fuse_fs_symlink(struct fuse_fs * fs,const char * linkname,const char * path)1721 int fuse_fs_symlink(struct fuse_fs *fs, const char *linkname, const char *path)
1722 {
1723 	fuse_get_context()->private_data = fs->user_data;
1724 	if (fs->op.symlink) {
1725 		if (fs->debug)
1726 			fprintf(stderr, "symlink %s %s\n", linkname, path);
1727 
1728 		return fs->op.symlink(linkname, path);
1729 	} else {
1730 		return -ENOSYS;
1731 	}
1732 }
1733 
fuse_fs_link(struct fuse_fs * fs,const char * oldpath,const char * newpath)1734 int fuse_fs_link(struct fuse_fs *fs, const char *oldpath, const char *newpath)
1735 {
1736 	fuse_get_context()->private_data = fs->user_data;
1737 	if (fs->op.link) {
1738 		if (fs->debug)
1739 			fprintf(stderr, "link %s %s\n", oldpath, newpath);
1740 
1741 		return fs->op.link(oldpath, newpath);
1742 	} else {
1743 		return -ENOSYS;
1744 	}
1745 }
1746 
fuse_fs_release(struct fuse_fs * fs,const char * path,struct fuse_file_info * fi)1747 int fuse_fs_release(struct fuse_fs *fs,	 const char *path,
1748 		    struct fuse_file_info *fi)
1749 {
1750 	fuse_get_context()->private_data = fs->user_data;
1751 	if (fs->op.release) {
1752 		if (fs->debug)
1753 			fprintf(stderr, "release%s[%llu] flags: 0x%x\n",
1754 				fi->flush ? "+flush" : "",
1755 				(unsigned long long) fi->fh, fi->flags);
1756 
1757 		return fuse_compat_release(fs, path, fi);
1758 	} else {
1759 		return 0;
1760 	}
1761 }
1762 
fuse_fs_opendir(struct fuse_fs * fs,const char * path,struct fuse_file_info * fi)1763 int fuse_fs_opendir(struct fuse_fs *fs, const char *path,
1764 		    struct fuse_file_info *fi)
1765 {
1766 	fuse_get_context()->private_data = fs->user_data;
1767 	if (fs->op.opendir) {
1768 		int err;
1769 
1770 		if (fs->debug)
1771 			fprintf(stderr, "opendir flags: 0x%x %s\n", fi->flags,
1772 				path);
1773 
1774 		err = fuse_compat_opendir(fs, path, fi);
1775 
1776 		if (fs->debug && !err)
1777 			fprintf(stderr, "   opendir[%lli] flags: 0x%x %s\n",
1778 				(unsigned long long) fi->fh, fi->flags, path);
1779 
1780 		return err;
1781 	} else {
1782 		return 0;
1783 	}
1784 }
1785 
fuse_fs_open(struct fuse_fs * fs,const char * path,struct fuse_file_info * fi)1786 int fuse_fs_open(struct fuse_fs *fs, const char *path,
1787 		 struct fuse_file_info *fi)
1788 {
1789 	fuse_get_context()->private_data = fs->user_data;
1790 	if (fs->op.open) {
1791 		int err;
1792 
1793 		if (fs->debug)
1794 			fprintf(stderr, "open flags: 0x%x %s\n", fi->flags,
1795 				path);
1796 
1797 		err = fuse_compat_open(fs, path, fi);
1798 
1799 		if (fs->debug && !err)
1800 			fprintf(stderr, "   open[%lli] flags: 0x%x %s\n",
1801 				(unsigned long long) fi->fh, fi->flags, path);
1802 
1803 		return err;
1804 	} else {
1805 		return 0;
1806 	}
1807 }
1808 
fuse_free_buf(struct fuse_bufvec * buf)1809 static void fuse_free_buf(struct fuse_bufvec *buf)
1810 {
1811 	if (buf != NULL) {
1812 		size_t i;
1813 
1814 		for (i = 0; i < buf->count; i++)
1815 			free(buf->buf[i].mem);
1816 		free(buf);
1817 	}
1818 }
1819 
fuse_fs_read_buf(struct fuse_fs * fs,const char * path,struct fuse_bufvec ** bufp,size_t size,off_t off,struct fuse_file_info * fi)1820 int fuse_fs_read_buf(struct fuse_fs *fs, const char *path,
1821 		     struct fuse_bufvec **bufp, size_t size, off_t off,
1822 		     struct fuse_file_info *fi)
1823 {
1824 	fuse_get_context()->private_data = fs->user_data;
1825 	if (fs->op.read || fs->op.read_buf) {
1826 		int res;
1827 
1828 		if (fs->debug)
1829 			fprintf(stderr,
1830 				"read[%llu] %zu bytes from %llu flags: 0x%x\n",
1831 				(unsigned long long) fi->fh,
1832 				size, (unsigned long long) off, fi->flags);
1833 
1834 		if (fs->op.read_buf) {
1835 			res = fs->op.read_buf(path, bufp, size, off, fi);
1836 		} else {
1837 			struct fuse_bufvec *buf;
1838 			void *mem;
1839 
1840 			buf = malloc(sizeof(struct fuse_bufvec));
1841 			if (buf == NULL)
1842 				return -ENOMEM;
1843 
1844 			mem = malloc(size);
1845 			if (mem == NULL) {
1846 				free(buf);
1847 				return -ENOMEM;
1848 			}
1849 			*buf = FUSE_BUFVEC_INIT(size);
1850 			buf->buf[0].mem = mem;
1851 			*bufp = buf;
1852 
1853 			res = fs->op.read(path, mem, size, off, fi);
1854 			if (res >= 0)
1855 				buf->buf[0].size = res;
1856 		}
1857 
1858 		if (fs->debug && res >= 0)
1859 			fprintf(stderr, "   read[%llu] %zu bytes from %llu\n",
1860 				(unsigned long long) fi->fh,
1861 				fuse_buf_size(*bufp),
1862 				(unsigned long long) off);
1863 		if (res >= 0 && fuse_buf_size(*bufp) > (int) size)
1864 			fprintf(stderr, "fuse: read too many bytes\n");
1865 
1866 		if (res < 0)
1867 			return res;
1868 
1869 		return 0;
1870 	} else {
1871 		return -ENOSYS;
1872 	}
1873 }
1874 
fuse_fs_read(struct fuse_fs * fs,const char * path,char * mem,size_t size,off_t off,struct fuse_file_info * fi)1875 int fuse_fs_read(struct fuse_fs *fs, const char *path, char *mem, size_t size,
1876 		 off_t off, struct fuse_file_info *fi)
1877 {
1878 	int res;
1879 	struct fuse_bufvec *buf = NULL;
1880 
1881 	res = fuse_fs_read_buf(fs, path, &buf, size, off, fi);
1882 	if (res == 0) {
1883 		struct fuse_bufvec dst = FUSE_BUFVEC_INIT(size);
1884 
1885 		dst.buf[0].mem = mem;
1886 		res = fuse_buf_copy(&dst, buf, 0);
1887 	}
1888 	fuse_free_buf(buf);
1889 
1890 	return res;
1891 }
1892 
fuse_fs_write_buf(struct fuse_fs * fs,const char * path,struct fuse_bufvec * buf,off_t off,struct fuse_file_info * fi)1893 int fuse_fs_write_buf(struct fuse_fs *fs, const char *path,
1894 		      struct fuse_bufvec *buf, off_t off,
1895 		      struct fuse_file_info *fi)
1896 {
1897 	fuse_get_context()->private_data = fs->user_data;
1898 	if (fs->op.write_buf || fs->op.write) {
1899 		int res;
1900 		size_t size = fuse_buf_size(buf);
1901 
1902 		assert(buf->idx == 0 && buf->off == 0);
1903 		if (fs->debug)
1904 			fprintf(stderr,
1905 				"write%s[%llu] %zu bytes to %llu flags: 0x%x\n",
1906 				fi->writepage ? "page" : "",
1907 				(unsigned long long) fi->fh,
1908 				size,
1909 				(unsigned long long) off,
1910 				fi->flags);
1911 
1912 		if (fs->op.write_buf) {
1913 			res = fs->op.write_buf(path, buf, off, fi);
1914 		} else {
1915 			void *mem = NULL;
1916 			struct fuse_buf *flatbuf;
1917 			struct fuse_bufvec tmp = FUSE_BUFVEC_INIT(size);
1918 
1919 			if (buf->count == 1 &&
1920 			    !(buf->buf[0].flags & FUSE_BUF_IS_FD)) {
1921 				flatbuf = &buf->buf[0];
1922 			} else {
1923 				res = -ENOMEM;
1924 				mem = malloc(size);
1925 				if (mem == NULL)
1926 					goto out;
1927 
1928 				tmp.buf[0].mem = mem;
1929 				res = fuse_buf_copy(&tmp, buf, 0);
1930 				if (res <= 0)
1931 					goto out_free;
1932 
1933 				tmp.buf[0].size = res;
1934 				flatbuf = &tmp.buf[0];
1935 			}
1936 
1937 			res = fs->op.write(path, flatbuf->mem, flatbuf->size,
1938 					   off, fi);
1939 out_free:
1940 			free(mem);
1941 		}
1942 out:
1943 		if (fs->debug && res >= 0)
1944 			fprintf(stderr, "   write%s[%llu] %u bytes to %llu\n",
1945 				fi->writepage ? "page" : "",
1946 				(unsigned long long) fi->fh, res,
1947 				(unsigned long long) off);
1948 		if (res > (int) size)
1949 			fprintf(stderr, "fuse: wrote too many bytes\n");
1950 
1951 		return res;
1952 	} else {
1953 		return -ENOSYS;
1954 	}
1955 }
1956 
fuse_fs_write(struct fuse_fs * fs,const char * path,const char * mem,size_t size,off_t off,struct fuse_file_info * fi)1957 int fuse_fs_write(struct fuse_fs *fs, const char *path, const char *mem,
1958 		  size_t size, off_t off, struct fuse_file_info *fi)
1959 {
1960 	struct fuse_bufvec bufv = FUSE_BUFVEC_INIT(size);
1961 
1962 	bufv.buf[0].mem = (void *) mem;
1963 
1964 	return fuse_fs_write_buf(fs, path, &bufv, off, fi);
1965 }
1966 
fuse_fs_fsync(struct fuse_fs * fs,const char * path,int datasync,struct fuse_file_info * fi)1967 int fuse_fs_fsync(struct fuse_fs *fs, const char *path, int datasync,
1968 		  struct fuse_file_info *fi)
1969 {
1970 	fuse_get_context()->private_data = fs->user_data;
1971 	if (fs->op.fsync) {
1972 		if (fs->debug)
1973 			fprintf(stderr, "fsync[%llu] datasync: %i\n",
1974 				(unsigned long long) fi->fh, datasync);
1975 
1976 		return fs->op.fsync(path, datasync, fi);
1977 	} else {
1978 		return -ENOSYS;
1979 	}
1980 }
1981 
fuse_fs_fsyncdir(struct fuse_fs * fs,const char * path,int datasync,struct fuse_file_info * fi)1982 int fuse_fs_fsyncdir(struct fuse_fs *fs, const char *path, int datasync,
1983 		     struct fuse_file_info *fi)
1984 {
1985 	fuse_get_context()->private_data = fs->user_data;
1986 	if (fs->op.fsyncdir) {
1987 		if (fs->debug)
1988 			fprintf(stderr, "fsyncdir[%llu] datasync: %i\n",
1989 				(unsigned long long) fi->fh, datasync);
1990 
1991 		return fs->op.fsyncdir(path, datasync, fi);
1992 	} else {
1993 		return -ENOSYS;
1994 	}
1995 }
1996 
fuse_fs_flush(struct fuse_fs * fs,const char * path,struct fuse_file_info * fi)1997 int fuse_fs_flush(struct fuse_fs *fs, const char *path,
1998 		  struct fuse_file_info *fi)
1999 {
2000 	fuse_get_context()->private_data = fs->user_data;
2001 	if (fs->op.flush) {
2002 		if (fs->debug)
2003 			fprintf(stderr, "flush[%llu]\n",
2004 				(unsigned long long) fi->fh);
2005 
2006 		return fs->op.flush(path, fi);
2007 	} else {
2008 		return -ENOSYS;
2009 	}
2010 }
2011 
fuse_fs_statfs(struct fuse_fs * fs,const char * path,struct statvfs * buf)2012 int fuse_fs_statfs(struct fuse_fs *fs, const char *path, struct statvfs *buf)
2013 {
2014 	fuse_get_context()->private_data = fs->user_data;
2015 	if (fs->op.statfs) {
2016 		if (fs->debug)
2017 			fprintf(stderr, "statfs %s\n", path);
2018 
2019 		return fuse_compat_statfs(fs, path, buf);
2020 	} else {
2021 		buf->f_namemax = 255;
2022 		buf->f_bsize = 512;
2023 		return 0;
2024 	}
2025 }
2026 
fuse_fs_releasedir(struct fuse_fs * fs,const char * path,struct fuse_file_info * fi)2027 int fuse_fs_releasedir(struct fuse_fs *fs, const char *path,
2028 		       struct fuse_file_info *fi)
2029 {
2030 	fuse_get_context()->private_data = fs->user_data;
2031 	if (fs->op.releasedir) {
2032 		if (fs->debug)
2033 			fprintf(stderr, "releasedir[%llu] flags: 0x%x\n",
2034 				(unsigned long long) fi->fh, fi->flags);
2035 
2036 		return fs->op.releasedir(path, fi);
2037 	} else {
2038 		return 0;
2039 	}
2040 }
2041 
fill_dir_old(struct fuse_dirhandle * dh,const char * name,int type,ino_t ino)2042 static int fill_dir_old(struct fuse_dirhandle *dh, const char *name, int type,
2043 			ino_t ino)
2044 {
2045 	int res;
2046 	struct stat stbuf;
2047 
2048 	memset(&stbuf, 0, sizeof(stbuf));
2049 	stbuf.st_mode = type << 12;
2050 	stbuf.st_ino = ino;
2051 
2052 	res = dh->filler(dh->buf, name, &stbuf, 0);
2053 	return res ? -ENOMEM : 0;
2054 }
2055 
fuse_fs_readdir(struct fuse_fs * fs,const char * path,void * buf,fuse_fill_dir_t filler,off_t off,struct fuse_file_info * fi)2056 int fuse_fs_readdir(struct fuse_fs *fs, const char *path, void *buf,
2057 		    fuse_fill_dir_t filler, off_t off,
2058 		    struct fuse_file_info *fi)
2059 {
2060 	fuse_get_context()->private_data = fs->user_data;
2061 	if (fs->op.readdir) {
2062 		if (fs->debug)
2063 			fprintf(stderr, "readdir[%llu] from %llu\n",
2064 				(unsigned long long) fi->fh,
2065 				(unsigned long long) off);
2066 
2067 		return fs->op.readdir(path, buf, filler, off, fi);
2068 	} else if (fs->op.getdir) {
2069 		struct fuse_dirhandle dh;
2070 
2071 		if (fs->debug)
2072 			fprintf(stderr, "getdir[%llu]\n",
2073 				(unsigned long long) fi->fh);
2074 
2075 		dh.filler = filler;
2076 		dh.buf = buf;
2077 		return fs->op.getdir(path, &dh, fill_dir_old);
2078 	} else {
2079 		return -ENOSYS;
2080 	}
2081 }
2082 
fuse_fs_create(struct fuse_fs * fs,const char * path,mode_t mode,struct fuse_file_info * fi)2083 int fuse_fs_create(struct fuse_fs *fs, const char *path, mode_t mode,
2084 		   struct fuse_file_info *fi)
2085 {
2086 	fuse_get_context()->private_data = fs->user_data;
2087 	if (fs->op.create) {
2088 		int err;
2089 
2090 		if (fs->debug)
2091 			fprintf(stderr,
2092 				"create flags: 0x%x %s 0%o umask=0%03o\n",
2093 				fi->flags, path, mode,
2094 				fuse_get_context()->umask);
2095 
2096 		err = fs->op.create(path, mode, fi);
2097 
2098 		if (fs->debug && !err)
2099 			fprintf(stderr, "   create[%llu] flags: 0x%x %s\n",
2100 				(unsigned long long) fi->fh, fi->flags, path);
2101 
2102 		return err;
2103 	} else {
2104 		return -ENOSYS;
2105 	}
2106 }
2107 
fuse_fs_lock(struct fuse_fs * fs,const char * path,struct fuse_file_info * fi,int cmd,struct flock * lock)2108 int fuse_fs_lock(struct fuse_fs *fs, const char *path,
2109 		 struct fuse_file_info *fi, int cmd, struct flock *lock)
2110 {
2111 	fuse_get_context()->private_data = fs->user_data;
2112 	if (fs->op.lock) {
2113 		if (fs->debug)
2114 			fprintf(stderr, "lock[%llu] %s %s start: %llu len: %llu pid: %llu\n",
2115 				(unsigned long long) fi->fh,
2116 				(cmd == F_GETLK ? "F_GETLK" :
2117 				 (cmd == F_SETLK ? "F_SETLK" :
2118 				  (cmd == F_SETLKW ? "F_SETLKW" : "???"))),
2119 				(lock->l_type == F_RDLCK ? "F_RDLCK" :
2120 				 (lock->l_type == F_WRLCK ? "F_WRLCK" :
2121 				  (lock->l_type == F_UNLCK ? "F_UNLCK" :
2122 				   "???"))),
2123 				(unsigned long long) lock->l_start,
2124 				(unsigned long long) lock->l_len,
2125 				(unsigned long long) lock->l_pid);
2126 
2127 		return fs->op.lock(path, fi, cmd, lock);
2128 	} else {
2129 		return -ENOSYS;
2130 	}
2131 }
2132 
fuse_fs_flock(struct fuse_fs * fs,const char * path,struct fuse_file_info * fi,int op)2133 int fuse_fs_flock(struct fuse_fs *fs, const char *path,
2134 		  struct fuse_file_info *fi, int op)
2135 {
2136 	fuse_get_context()->private_data = fs->user_data;
2137 	if (fs->op.flock) {
2138 		if (fs->debug) {
2139 			int xop = op & ~LOCK_NB;
2140 
2141 			fprintf(stderr, "lock[%llu] %s%s\n",
2142 				(unsigned long long) fi->fh,
2143 				xop == LOCK_SH ? "LOCK_SH" :
2144 				(xop == LOCK_EX ? "LOCK_EX" :
2145 				 (xop == LOCK_UN ? "LOCK_UN" : "???")),
2146 				(op & LOCK_NB) ? "|LOCK_NB" : "");
2147 		}
2148 		return fs->op.flock(path, fi, op);
2149 	} else {
2150 		return -ENOSYS;
2151 	}
2152 }
2153 
fuse_fs_chown(struct fuse_fs * fs,const char * path,uid_t uid,gid_t gid)2154 int fuse_fs_chown(struct fuse_fs *fs, const char *path, uid_t uid, gid_t gid)
2155 {
2156 	fuse_get_context()->private_data = fs->user_data;
2157 	if (fs->op.chown) {
2158 		if (fs->debug)
2159 			fprintf(stderr, "chown %s %lu %lu\n", path,
2160 				(unsigned long) uid, (unsigned long) gid);
2161 
2162 		return fs->op.chown(path, uid, gid);
2163 	} else {
2164 		return -ENOSYS;
2165 	}
2166 }
2167 
fuse_fs_truncate(struct fuse_fs * fs,const char * path,off_t size)2168 int fuse_fs_truncate(struct fuse_fs *fs, const char *path, off_t size)
2169 {
2170 	fuse_get_context()->private_data = fs->user_data;
2171 	if (fs->op.truncate) {
2172 		if (fs->debug)
2173 			fprintf(stderr, "truncate %s %llu\n", path,
2174 				(unsigned long long) size);
2175 
2176 		return fs->op.truncate(path, size);
2177 	} else {
2178 		return -ENOSYS;
2179 	}
2180 }
2181 
fuse_fs_ftruncate(struct fuse_fs * fs,const char * path,off_t size,struct fuse_file_info * fi)2182 int fuse_fs_ftruncate(struct fuse_fs *fs, const char *path, off_t size,
2183 		      struct fuse_file_info *fi)
2184 {
2185 	fuse_get_context()->private_data = fs->user_data;
2186 	if (fs->op.ftruncate) {
2187 		if (fs->debug)
2188 			fprintf(stderr, "ftruncate[%llu] %llu\n",
2189 				(unsigned long long) fi->fh,
2190 				(unsigned long long) size);
2191 
2192 		return fs->op.ftruncate(path, size, fi);
2193 	} else if (path && fs->op.truncate) {
2194 		if (fs->debug)
2195 			fprintf(stderr, "truncate %s %llu\n", path,
2196 				(unsigned long long) size);
2197 
2198 		return fs->op.truncate(path, size);
2199 	} else {
2200 		return -ENOSYS;
2201 	}
2202 }
2203 
fuse_fs_utimens(struct fuse_fs * fs,const char * path,const struct timespec tv[2])2204 int fuse_fs_utimens(struct fuse_fs *fs, const char *path,
2205 		    const struct timespec tv[2])
2206 {
2207 	fuse_get_context()->private_data = fs->user_data;
2208 	if (fs->op.utimens) {
2209 		if (fs->debug)
2210 			fprintf(stderr, "utimens %s %li.%09lu %li.%09lu\n",
2211 				path, tv[0].tv_sec, tv[0].tv_nsec,
2212 				tv[1].tv_sec, tv[1].tv_nsec);
2213 
2214 		return fs->op.utimens(path, tv);
2215 	} else if(fs->op.utime) {
2216 		struct utimbuf buf;
2217 
2218 		if (fs->debug)
2219 			fprintf(stderr, "utime %s %li %li\n", path,
2220 				tv[0].tv_sec, tv[1].tv_sec);
2221 
2222 		buf.actime = tv[0].tv_sec;
2223 		buf.modtime = tv[1].tv_sec;
2224 		return fs->op.utime(path, &buf);
2225 	} else {
2226 		return -ENOSYS;
2227 	}
2228 }
2229 
fuse_fs_access(struct fuse_fs * fs,const char * path,int mask)2230 int fuse_fs_access(struct fuse_fs *fs, const char *path, int mask)
2231 {
2232 	fuse_get_context()->private_data = fs->user_data;
2233 	if (fs->op.access) {
2234 		if (fs->debug)
2235 			fprintf(stderr, "access %s 0%o\n", path, mask);
2236 
2237 		return fs->op.access(path, mask);
2238 	} else {
2239 		return -ENOSYS;
2240 	}
2241 }
2242 
fuse_fs_readlink(struct fuse_fs * fs,const char * path,char * buf,size_t len)2243 int fuse_fs_readlink(struct fuse_fs *fs, const char *path, char *buf,
2244 		     size_t len)
2245 {
2246 	fuse_get_context()->private_data = fs->user_data;
2247 	if (fs->op.readlink) {
2248 		if (fs->debug)
2249 			fprintf(stderr, "readlink %s %lu\n", path,
2250 				(unsigned long) len);
2251 
2252 		return fs->op.readlink(path, buf, len);
2253 	} else {
2254 		return -ENOSYS;
2255 	}
2256 }
2257 
fuse_fs_mknod(struct fuse_fs * fs,const char * path,mode_t mode,dev_t rdev)2258 int fuse_fs_mknod(struct fuse_fs *fs, const char *path, mode_t mode,
2259 		  dev_t rdev)
2260 {
2261 	fuse_get_context()->private_data = fs->user_data;
2262 	if (fs->op.mknod) {
2263 		if (fs->debug)
2264 			fprintf(stderr, "mknod %s 0%o 0x%llx umask=0%03o\n",
2265 				path, mode, (unsigned long long) rdev,
2266 				fuse_get_context()->umask);
2267 
2268 		return fs->op.mknod(path, mode, rdev);
2269 	} else {
2270 		return -ENOSYS;
2271 	}
2272 }
2273 
fuse_fs_mkdir(struct fuse_fs * fs,const char * path,mode_t mode)2274 int fuse_fs_mkdir(struct fuse_fs *fs, const char *path, mode_t mode)
2275 {
2276 	fuse_get_context()->private_data = fs->user_data;
2277 	if (fs->op.mkdir) {
2278 		if (fs->debug)
2279 			fprintf(stderr, "mkdir %s 0%o umask=0%03o\n",
2280 				path, mode, fuse_get_context()->umask);
2281 
2282 		return fs->op.mkdir(path, mode);
2283 	} else {
2284 		return -ENOSYS;
2285 	}
2286 }
2287 
fuse_fs_setxattr(struct fuse_fs * fs,const char * path,const char * name,const char * value,size_t size,int flags)2288 int fuse_fs_setxattr(struct fuse_fs *fs, const char *path, const char *name,
2289 		     const char *value, size_t size, int flags)
2290 {
2291 	fuse_get_context()->private_data = fs->user_data;
2292 	if (fs->op.setxattr) {
2293 		if (fs->debug)
2294 			fprintf(stderr, "setxattr %s %s %lu 0x%x\n",
2295 				path, name, (unsigned long) size, flags);
2296 
2297 		return fs->op.setxattr(path, name, value, size, flags);
2298 	} else {
2299 		return -ENOSYS;
2300 	}
2301 }
2302 
fuse_fs_getxattr(struct fuse_fs * fs,const char * path,const char * name,char * value,size_t size)2303 int fuse_fs_getxattr(struct fuse_fs *fs, const char *path, const char *name,
2304 		     char *value, size_t size)
2305 {
2306 	fuse_get_context()->private_data = fs->user_data;
2307 	if (fs->op.getxattr) {
2308 		if (fs->debug)
2309 			fprintf(stderr, "getxattr %s %s %lu\n",
2310 				path, name, (unsigned long) size);
2311 
2312 		return fs->op.getxattr(path, name, value, size);
2313 	} else {
2314 		return -ENOSYS;
2315 	}
2316 }
2317 
fuse_fs_listxattr(struct fuse_fs * fs,const char * path,char * list,size_t size)2318 int fuse_fs_listxattr(struct fuse_fs *fs, const char *path, char *list,
2319 		      size_t size)
2320 {
2321 	fuse_get_context()->private_data = fs->user_data;
2322 	if (fs->op.listxattr) {
2323 		if (fs->debug)
2324 			fprintf(stderr, "listxattr %s %lu\n",
2325 				path, (unsigned long) size);
2326 
2327 		return fs->op.listxattr(path, list, size);
2328 	} else {
2329 		return -ENOSYS;
2330 	}
2331 }
2332 
fuse_fs_bmap(struct fuse_fs * fs,const char * path,size_t blocksize,uint64_t * idx)2333 int fuse_fs_bmap(struct fuse_fs *fs, const char *path, size_t blocksize,
2334 		 uint64_t *idx)
2335 {
2336 	fuse_get_context()->private_data = fs->user_data;
2337 	if (fs->op.bmap) {
2338 		if (fs->debug)
2339 			fprintf(stderr, "bmap %s blocksize: %lu index: %llu\n",
2340 				path, (unsigned long) blocksize,
2341 				(unsigned long long) *idx);
2342 
2343 		return fs->op.bmap(path, blocksize, idx);
2344 	} else {
2345 		return -ENOSYS;
2346 	}
2347 }
2348 
fuse_fs_removexattr(struct fuse_fs * fs,const char * path,const char * name)2349 int fuse_fs_removexattr(struct fuse_fs *fs, const char *path, const char *name)
2350 {
2351 	fuse_get_context()->private_data = fs->user_data;
2352 	if (fs->op.removexattr) {
2353 		if (fs->debug)
2354 			fprintf(stderr, "removexattr %s %s\n", path, name);
2355 
2356 		return fs->op.removexattr(path, name);
2357 	} else {
2358 		return -ENOSYS;
2359 	}
2360 }
2361 
fuse_fs_ioctl(struct fuse_fs * fs,const char * path,int cmd,void * arg,struct fuse_file_info * fi,unsigned int flags,void * data)2362 int fuse_fs_ioctl(struct fuse_fs *fs, const char *path, int cmd, void *arg,
2363 		  struct fuse_file_info *fi, unsigned int flags, void *data)
2364 {
2365 	fuse_get_context()->private_data = fs->user_data;
2366 	if (fs->op.ioctl) {
2367 		if (fs->debug)
2368 			fprintf(stderr, "ioctl[%llu] 0x%x flags: 0x%x\n",
2369 				(unsigned long long) fi->fh, cmd, flags);
2370 
2371 		return fs->op.ioctl(path, cmd, arg, fi, flags, data);
2372 	} else
2373 		return -ENOSYS;
2374 }
2375 
fuse_fs_poll(struct fuse_fs * fs,const char * path,struct fuse_file_info * fi,struct fuse_pollhandle * ph,unsigned * reventsp)2376 int fuse_fs_poll(struct fuse_fs *fs, const char *path,
2377 		 struct fuse_file_info *fi, struct fuse_pollhandle *ph,
2378 		 unsigned *reventsp)
2379 {
2380 	fuse_get_context()->private_data = fs->user_data;
2381 	if (fs->op.poll) {
2382 		int res;
2383 
2384 		if (fs->debug)
2385 			fprintf(stderr, "poll[%llu] ph: %p\n",
2386 				(unsigned long long) fi->fh, ph);
2387 
2388 		res = fs->op.poll(path, fi, ph, reventsp);
2389 
2390 		if (fs->debug && !res)
2391 			fprintf(stderr, "   poll[%llu] revents: 0x%x\n",
2392 				(unsigned long long) fi->fh, *reventsp);
2393 
2394 		return res;
2395 	} else
2396 		return -ENOSYS;
2397 }
2398 
fuse_fs_fallocate(struct fuse_fs * fs,const char * path,int mode,off_t offset,off_t length,struct fuse_file_info * fi)2399 int fuse_fs_fallocate(struct fuse_fs *fs, const char *path, int mode,
2400 		off_t offset, off_t length, struct fuse_file_info *fi)
2401 {
2402 	fuse_get_context()->private_data = fs->user_data;
2403 	if (fs->op.fallocate) {
2404 		if (fs->debug)
2405 			fprintf(stderr, "fallocate %s mode %x, offset: %llu, length: %llu\n",
2406 				path,
2407 				mode,
2408 				(unsigned long long) offset,
2409 				(unsigned long long) length);
2410 
2411 		return fs->op.fallocate(path, mode, offset, length, fi);
2412 	} else
2413 		return -ENOSYS;
2414 }
2415 
is_open(struct fuse * f,fuse_ino_t dir,const char * name)2416 static int is_open(struct fuse *f, fuse_ino_t dir, const char *name)
2417 {
2418 	struct node *node;
2419 	int isopen = 0;
2420 	pthread_mutex_lock(&f->lock);
2421 	node = lookup_node(f, dir, name);
2422 	if (node && node->open_count > 0)
2423 		isopen = 1;
2424 	pthread_mutex_unlock(&f->lock);
2425 	return isopen;
2426 }
2427 
hidden_name(struct fuse * f,fuse_ino_t dir,const char * oldname,char * newname,size_t bufsize)2428 static char *hidden_name(struct fuse *f, fuse_ino_t dir, const char *oldname,
2429 			 char *newname, size_t bufsize)
2430 {
2431 	struct stat buf;
2432 	struct node *node;
2433 	struct node *newnode;
2434 	char *newpath;
2435 	int res;
2436 	int failctr = 10;
2437 
2438 	do {
2439 		pthread_mutex_lock(&f->lock);
2440 		node = lookup_node(f, dir, oldname);
2441 		if (node == NULL) {
2442 			pthread_mutex_unlock(&f->lock);
2443 			return NULL;
2444 		}
2445 		do {
2446 			f->hidectr ++;
2447 			snprintf(newname, bufsize, ".fuse_hidden%08x%08x",
2448 				 (unsigned int) node->nodeid, f->hidectr);
2449 			newnode = lookup_node(f, dir, newname);
2450 		} while(newnode);
2451 
2452 		res = try_get_path(f, dir, newname, &newpath, NULL, false);
2453 		pthread_mutex_unlock(&f->lock);
2454 		if (res)
2455 			break;
2456 
2457 		memset(&buf, 0, sizeof(buf));
2458 		res = fuse_fs_getattr(f->fs, newpath, &buf);
2459 		if (res == -ENOENT)
2460 			break;
2461 		free(newpath);
2462 		newpath = NULL;
2463 	} while(res == 0 && --failctr);
2464 
2465 	return newpath;
2466 }
2467 
hide_node(struct fuse * f,const char * oldpath,fuse_ino_t dir,const char * oldname)2468 static int hide_node(struct fuse *f, const char *oldpath,
2469 		     fuse_ino_t dir, const char *oldname)
2470 {
2471 	char newname[64];
2472 	char *newpath;
2473 	int err = -EBUSY;
2474 
2475 	newpath = hidden_name(f, dir, oldname, newname, sizeof(newname));
2476 	if (newpath) {
2477 		err = fuse_fs_rename(f->fs, oldpath, newpath);
2478 		if (!err)
2479 			err = rename_node(f, dir, oldname, dir, newname, 1);
2480 		free(newpath);
2481 	}
2482 	return err;
2483 }
2484 
mtime_eq(const struct stat * stbuf,const struct timespec * ts)2485 static int mtime_eq(const struct stat *stbuf, const struct timespec *ts)
2486 {
2487 	return stbuf->st_mtime == ts->tv_sec &&
2488 		ST_MTIM_NSEC(stbuf) == ts->tv_nsec;
2489 }
2490 
2491 #ifndef CLOCK_MONOTONIC
2492 #define CLOCK_MONOTONIC CLOCK_REALTIME
2493 #endif
2494 
curr_time(struct timespec * now)2495 static void curr_time(struct timespec *now)
2496 {
2497 	static clockid_t clockid = CLOCK_MONOTONIC;
2498 	int res = clock_gettime(clockid, now);
2499 	if (res == -1 && errno == EINVAL) {
2500 		clockid = CLOCK_REALTIME;
2501 		res = clock_gettime(clockid, now);
2502 	}
2503 	if (res == -1) {
2504 		perror("fuse: clock_gettime");
2505 		abort();
2506 	}
2507 }
2508 
update_stat(struct node * node,const struct stat * stbuf)2509 static void update_stat(struct node *node, const struct stat *stbuf)
2510 {
2511 	if (node->cache_valid && (!mtime_eq(stbuf, &node->mtime) ||
2512 				  stbuf->st_size != node->size))
2513 		node->cache_valid = 0;
2514 	node->mtime.tv_sec = stbuf->st_mtime;
2515 	node->mtime.tv_nsec = ST_MTIM_NSEC(stbuf);
2516 	node->size = stbuf->st_size;
2517 	curr_time(&node->stat_updated);
2518 }
2519 
lookup_path(struct fuse * f,fuse_ino_t nodeid,const char * name,const char * path,struct fuse_entry_param * e,struct fuse_file_info * fi)2520 static int lookup_path(struct fuse *f, fuse_ino_t nodeid,
2521 		       const char *name, const char *path,
2522 		       struct fuse_entry_param *e, struct fuse_file_info *fi)
2523 {
2524 	int res;
2525 
2526 	memset(e, 0, sizeof(struct fuse_entry_param));
2527 	if (fi)
2528 		res = fuse_fs_fgetattr(f->fs, path, &e->attr, fi);
2529 	else
2530 		res = fuse_fs_getattr(f->fs, path, &e->attr);
2531 	if (res == 0) {
2532 		struct node *node;
2533 
2534 		node = find_node(f, nodeid, name);
2535 		if (node == NULL)
2536 			res = -ENOMEM;
2537 		else {
2538 			e->ino = node->nodeid;
2539 			e->generation = node->generation;
2540 			e->entry_timeout = f->conf.entry_timeout;
2541 			e->attr_timeout = f->conf.attr_timeout;
2542 			if (f->conf.auto_cache) {
2543 				pthread_mutex_lock(&f->lock);
2544 				update_stat(node, &e->attr);
2545 				pthread_mutex_unlock(&f->lock);
2546 			}
2547 			set_stat(f, e->ino, &e->attr);
2548 			if (f->conf.debug)
2549 				fprintf(stderr, "   NODEID: %lu\n",
2550 					(unsigned long) e->ino);
2551 		}
2552 	}
2553 	return res;
2554 }
2555 
fuse_get_context_internal(void)2556 static struct fuse_context_i *fuse_get_context_internal(void)
2557 {
2558 	struct fuse_context_i *c;
2559 
2560 	c = (struct fuse_context_i *) pthread_getspecific(fuse_context_key);
2561 	if (c == NULL) {
2562 		c = (struct fuse_context_i *)
2563 			calloc(1, sizeof(struct fuse_context_i));
2564 		if (c == NULL) {
2565 			/* This is hard to deal with properly, so just
2566 			   abort.  If memory is so low that the
2567 			   context cannot be allocated, there's not
2568 			   much hope for the filesystem anyway */
2569 			fprintf(stderr, "fuse: failed to allocate thread specific data\n");
2570 			abort();
2571 		}
2572 		pthread_setspecific(fuse_context_key, c);
2573 	}
2574 	return c;
2575 }
2576 
fuse_freecontext(void * data)2577 static void fuse_freecontext(void *data)
2578 {
2579 	free(data);
2580 }
2581 
fuse_create_context_key(void)2582 static int fuse_create_context_key(void)
2583 {
2584 	int err = 0;
2585 	pthread_mutex_lock(&fuse_context_lock);
2586 	if (!fuse_context_ref) {
2587 		err = pthread_key_create(&fuse_context_key, fuse_freecontext);
2588 		if (err) {
2589 			fprintf(stderr, "fuse: failed to create thread specific key: %s\n",
2590 				strerror(err));
2591 			pthread_mutex_unlock(&fuse_context_lock);
2592 			return -1;
2593 		}
2594 	}
2595 	fuse_context_ref++;
2596 	pthread_mutex_unlock(&fuse_context_lock);
2597 	return 0;
2598 }
2599 
fuse_delete_context_key(void)2600 static void fuse_delete_context_key(void)
2601 {
2602 	pthread_mutex_lock(&fuse_context_lock);
2603 	fuse_context_ref--;
2604 	if (!fuse_context_ref) {
2605 		free(pthread_getspecific(fuse_context_key));
2606 		pthread_key_delete(fuse_context_key);
2607 	}
2608 	pthread_mutex_unlock(&fuse_context_lock);
2609 }
2610 
req_fuse_prepare(fuse_req_t req)2611 static struct fuse *req_fuse_prepare(fuse_req_t req)
2612 {
2613 	struct fuse_context_i *c = fuse_get_context_internal();
2614 	const struct fuse_ctx *ctx = fuse_req_ctx(req);
2615 	c->req = req;
2616 	c->ctx.fuse = req_fuse(req);
2617 	c->ctx.uid = ctx->uid;
2618 	c->ctx.gid = ctx->gid;
2619 	c->ctx.pid = ctx->pid;
2620 	c->ctx.umask = ctx->umask;
2621 	return c->ctx.fuse;
2622 }
2623 
reply_err(fuse_req_t req,int err)2624 static inline void reply_err(fuse_req_t req, int err)
2625 {
2626 	/* fuse_reply_err() uses non-negated errno values */
2627 	fuse_reply_err(req, -err);
2628 }
2629 
reply_entry(fuse_req_t req,const struct fuse_entry_param * e,int err)2630 static void reply_entry(fuse_req_t req, const struct fuse_entry_param *e,
2631 			int err)
2632 {
2633 	if (!err) {
2634 		struct fuse *f = req_fuse(req);
2635 		if (fuse_reply_entry(req, e) == -ENOENT) {
2636 			/* Skip forget for negative result */
2637 			if  (e->ino != 0)
2638 				forget_node(f, e->ino, 1);
2639 		}
2640 	} else
2641 		reply_err(req, err);
2642 }
2643 
fuse_fs_init(struct fuse_fs * fs,struct fuse_conn_info * conn)2644 void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn)
2645 {
2646 	fuse_get_context()->private_data = fs->user_data;
2647 	if (!fs->op.write_buf)
2648 		conn->want &= ~FUSE_CAP_SPLICE_READ;
2649 	if (!fs->op.lock)
2650 		conn->want &= ~FUSE_CAP_POSIX_LOCKS;
2651 	if (!fs->op.flock)
2652 		conn->want &= ~FUSE_CAP_FLOCK_LOCKS;
2653 	if (fs->op.init)
2654 		fs->user_data = fs->op.init(conn);
2655 }
2656 
fuse_lib_init(void * data,struct fuse_conn_info * conn)2657 static void fuse_lib_init(void *data, struct fuse_conn_info *conn)
2658 {
2659 	struct fuse *f = (struct fuse *) data;
2660 	struct fuse_context_i *c = fuse_get_context_internal();
2661 
2662 	memset(c, 0, sizeof(*c));
2663 	c->ctx.fuse = f;
2664 	conn->want |= FUSE_CAP_EXPORT_SUPPORT;
2665 	fuse_fs_init(f->fs, conn);
2666 }
2667 
fuse_fs_destroy(struct fuse_fs * fs)2668 void fuse_fs_destroy(struct fuse_fs *fs)
2669 {
2670 	fuse_get_context()->private_data = fs->user_data;
2671 	if (fs->op.destroy)
2672 		fs->op.destroy(fs->user_data);
2673 	if (fs->m)
2674 		fuse_put_module(fs->m);
2675 	free(fs);
2676 }
2677 
fuse_lib_destroy(void * data)2678 static void fuse_lib_destroy(void *data)
2679 {
2680 	struct fuse *f = (struct fuse *) data;
2681 	struct fuse_context_i *c = fuse_get_context_internal();
2682 
2683 	memset(c, 0, sizeof(*c));
2684 	c->ctx.fuse = f;
2685 	fuse_fs_destroy(f->fs);
2686 	f->fs = NULL;
2687 }
2688 
fuse_lib_lookup(fuse_req_t req,fuse_ino_t parent,const char * name)2689 static void fuse_lib_lookup(fuse_req_t req, fuse_ino_t parent,
2690 			    const char *name)
2691 {
2692 	struct fuse *f = req_fuse_prepare(req);
2693 	struct fuse_entry_param e;
2694 	char *path;
2695 	int err;
2696 	struct node *dot = NULL;
2697 
2698 	if (name[0] == '.') {
2699 		int len = strlen(name);
2700 
2701 		if (len == 1 || (name[1] == '.' && len == 2)) {
2702 			pthread_mutex_lock(&f->lock);
2703 			if (len == 1) {
2704 				if (f->conf.debug)
2705 					fprintf(stderr, "LOOKUP-DOT\n");
2706 				dot = get_node_nocheck(f, parent);
2707 				if (dot == NULL) {
2708 					pthread_mutex_unlock(&f->lock);
2709 					reply_entry(req, &e, -ESTALE);
2710 					return;
2711 				}
2712 				dot->refctr++;
2713 			} else {
2714 				if (f->conf.debug)
2715 					fprintf(stderr, "LOOKUP-DOTDOT\n");
2716 				parent = get_node(f, parent)->parent->nodeid;
2717 			}
2718 			pthread_mutex_unlock(&f->lock);
2719 			name = NULL;
2720 		}
2721 	}
2722 
2723 	err = get_path_name(f, parent, name, &path);
2724 	if (!err) {
2725 		struct fuse_intr_data d;
2726 		if (f->conf.debug)
2727 			fprintf(stderr, "LOOKUP %s\n", path);
2728 		fuse_prepare_interrupt(f, req, &d);
2729 		err = lookup_path(f, parent, name, path, &e, NULL);
2730 		if (err == -ENOENT && f->conf.negative_timeout != 0.0) {
2731 			e.ino = 0;
2732 			e.entry_timeout = f->conf.negative_timeout;
2733 			err = 0;
2734 		}
2735 		fuse_finish_interrupt(f, req, &d);
2736 		free_path(f, parent, path);
2737 	}
2738 	if (dot) {
2739 		pthread_mutex_lock(&f->lock);
2740 		unref_node(f, dot);
2741 		pthread_mutex_unlock(&f->lock);
2742 	}
2743 	reply_entry(req, &e, err);
2744 }
2745 
do_forget(struct fuse * f,fuse_ino_t ino,uint64_t nlookup)2746 static void do_forget(struct fuse *f, fuse_ino_t ino, uint64_t nlookup)
2747 {
2748 	if (f->conf.debug)
2749 		fprintf(stderr, "FORGET %llu/%llu\n", (unsigned long long)ino,
2750 			(unsigned long long) nlookup);
2751 	forget_node(f, ino, nlookup);
2752 }
2753 
fuse_lib_forget(fuse_req_t req,fuse_ino_t ino,unsigned long nlookup)2754 static void fuse_lib_forget(fuse_req_t req, fuse_ino_t ino,
2755 			    unsigned long nlookup)
2756 {
2757 	do_forget(req_fuse(req), ino, nlookup);
2758 	fuse_reply_none(req);
2759 }
2760 
fuse_lib_forget_multi(fuse_req_t req,size_t count,struct fuse_forget_data * forgets)2761 static void fuse_lib_forget_multi(fuse_req_t req, size_t count,
2762 				  struct fuse_forget_data *forgets)
2763 {
2764 	struct fuse *f = req_fuse(req);
2765 	size_t i;
2766 
2767 	for (i = 0; i < count; i++)
2768 		do_forget(f, forgets[i].ino, forgets[i].nlookup);
2769 
2770 	fuse_reply_none(req);
2771 }
2772 
2773 
fuse_lib_getattr(fuse_req_t req,fuse_ino_t ino,struct fuse_file_info * fi)2774 static void fuse_lib_getattr(fuse_req_t req, fuse_ino_t ino,
2775 			     struct fuse_file_info *fi)
2776 {
2777 	struct fuse *f = req_fuse_prepare(req);
2778 	struct stat buf;
2779 	char *path;
2780 	int err;
2781 
2782 	memset(&buf, 0, sizeof(buf));
2783 
2784 	if (fi != NULL && f->fs->op.fgetattr)
2785 		err = get_path_nullok(f, ino, &path);
2786 	else
2787 		err = get_path(f, ino, &path);
2788 	if (!err) {
2789 		struct fuse_intr_data d;
2790 		fuse_prepare_interrupt(f, req, &d);
2791 		if (fi)
2792 			err = fuse_fs_fgetattr(f->fs, path, &buf, fi);
2793 		else
2794 			err = fuse_fs_getattr(f->fs, path, &buf);
2795 		fuse_finish_interrupt(f, req, &d);
2796 		free_path(f, ino, path);
2797 	}
2798 	if (!err) {
2799 		struct node *node;
2800 
2801 		pthread_mutex_lock(&f->lock);
2802 		node = get_node(f, ino);
2803 		if (node->is_hidden && buf.st_nlink > 0)
2804 			buf.st_nlink--;
2805 		if (f->conf.auto_cache)
2806 			update_stat(node, &buf);
2807 		pthread_mutex_unlock(&f->lock);
2808 		set_stat(f, ino, &buf);
2809 		fuse_reply_attr(req, &buf, f->conf.attr_timeout);
2810 	} else
2811 		reply_err(req, err);
2812 }
2813 
fuse_fs_chmod(struct fuse_fs * fs,const char * path,mode_t mode)2814 int fuse_fs_chmod(struct fuse_fs *fs, const char *path, mode_t mode)
2815 {
2816 	fuse_get_context()->private_data = fs->user_data;
2817 	if (fs->op.chmod)
2818 		return fs->op.chmod(path, mode);
2819 	else
2820 		return -ENOSYS;
2821 }
2822 
fuse_lib_setattr(fuse_req_t req,fuse_ino_t ino,struct stat * attr,int valid,struct fuse_file_info * fi)2823 static void fuse_lib_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
2824 			     int valid, struct fuse_file_info *fi)
2825 {
2826 	struct fuse *f = req_fuse_prepare(req);
2827 	struct stat buf;
2828 	char *path;
2829 	int err;
2830 
2831 	memset(&buf, 0, sizeof(buf));
2832 	if (valid == FUSE_SET_ATTR_SIZE && fi != NULL &&
2833 	    f->fs->op.ftruncate && f->fs->op.fgetattr)
2834 		err = get_path_nullok(f, ino, &path);
2835 	else
2836 		err = get_path(f, ino, &path);
2837 	if (!err) {
2838 		struct fuse_intr_data d;
2839 		fuse_prepare_interrupt(f, req, &d);
2840 		err = 0;
2841 		if (!err && (valid & FUSE_SET_ATTR_MODE))
2842 			err = fuse_fs_chmod(f->fs, path, attr->st_mode);
2843 		if (!err && (valid & (FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID))) {
2844 			uid_t uid = (valid & FUSE_SET_ATTR_UID) ?
2845 				attr->st_uid : (uid_t) -1;
2846 			gid_t gid = (valid & FUSE_SET_ATTR_GID) ?
2847 				attr->st_gid : (gid_t) -1;
2848 			err = fuse_fs_chown(f->fs, path, uid, gid);
2849 		}
2850 		if (!err && (valid & FUSE_SET_ATTR_SIZE)) {
2851 			if (fi)
2852 				err = fuse_fs_ftruncate(f->fs, path,
2853 							attr->st_size, fi);
2854 			else
2855 				err = fuse_fs_truncate(f->fs, path,
2856 						       attr->st_size);
2857 		}
2858 #ifdef HAVE_UTIMENSAT
2859 		if (!err && f->utime_omit_ok &&
2860 		    (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME))) {
2861 			struct timespec tv[2];
2862 
2863 			tv[0].tv_sec = 0;
2864 			tv[1].tv_sec = 0;
2865 			tv[0].tv_nsec = UTIME_OMIT;
2866 			tv[1].tv_nsec = UTIME_OMIT;
2867 
2868 			if (valid & FUSE_SET_ATTR_ATIME_NOW)
2869 				tv[0].tv_nsec = UTIME_NOW;
2870 			else if (valid & FUSE_SET_ATTR_ATIME)
2871 				tv[0] = attr->st_atim;
2872 
2873 			if (valid & FUSE_SET_ATTR_MTIME_NOW)
2874 				tv[1].tv_nsec = UTIME_NOW;
2875 			else if (valid & FUSE_SET_ATTR_MTIME)
2876 				tv[1] = attr->st_mtim;
2877 
2878 			err = fuse_fs_utimens(f->fs, path, tv);
2879 		} else
2880 #endif
2881 		if (!err &&
2882 		    (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) ==
2883 		    (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) {
2884 			struct timespec tv[2];
2885 			tv[0].tv_sec = attr->st_atime;
2886 			tv[0].tv_nsec = ST_ATIM_NSEC(attr);
2887 			tv[1].tv_sec = attr->st_mtime;
2888 			tv[1].tv_nsec = ST_MTIM_NSEC(attr);
2889 			err = fuse_fs_utimens(f->fs, path, tv);
2890 		}
2891 		if (!err) {
2892 			if (fi)
2893 				err = fuse_fs_fgetattr(f->fs, path, &buf, fi);
2894 			else
2895 				err = fuse_fs_getattr(f->fs, path, &buf);
2896 		}
2897 		fuse_finish_interrupt(f, req, &d);
2898 		free_path(f, ino, path);
2899 	}
2900 	if (!err) {
2901 		if (f->conf.auto_cache) {
2902 			pthread_mutex_lock(&f->lock);
2903 			update_stat(get_node(f, ino), &buf);
2904 			pthread_mutex_unlock(&f->lock);
2905 		}
2906 		set_stat(f, ino, &buf);
2907 		fuse_reply_attr(req, &buf, f->conf.attr_timeout);
2908 	} else
2909 		reply_err(req, err);
2910 }
2911 
fuse_lib_access(fuse_req_t req,fuse_ino_t ino,int mask)2912 static void fuse_lib_access(fuse_req_t req, fuse_ino_t ino, int mask)
2913 {
2914 	struct fuse *f = req_fuse_prepare(req);
2915 	char *path;
2916 	int err;
2917 
2918 	err = get_path(f, ino, &path);
2919 	if (!err) {
2920 		struct fuse_intr_data d;
2921 
2922 		fuse_prepare_interrupt(f, req, &d);
2923 		err = fuse_fs_access(f->fs, path, mask);
2924 		fuse_finish_interrupt(f, req, &d);
2925 		free_path(f, ino, path);
2926 	}
2927 	reply_err(req, err);
2928 }
2929 
fuse_lib_readlink(fuse_req_t req,fuse_ino_t ino)2930 static void fuse_lib_readlink(fuse_req_t req, fuse_ino_t ino)
2931 {
2932 	struct fuse *f = req_fuse_prepare(req);
2933 	char linkname[PATH_MAX + 1];
2934 	char *path;
2935 	int err;
2936 
2937 	err = get_path(f, ino, &path);
2938 	if (!err) {
2939 		struct fuse_intr_data d;
2940 		fuse_prepare_interrupt(f, req, &d);
2941 		err = fuse_fs_readlink(f->fs, path, linkname, sizeof(linkname));
2942 		fuse_finish_interrupt(f, req, &d);
2943 		free_path(f, ino, path);
2944 	}
2945 	if (!err) {
2946 		linkname[PATH_MAX] = '\0';
2947 		fuse_reply_readlink(req, linkname);
2948 	} else
2949 		reply_err(req, err);
2950 }
2951 
fuse_lib_mknod(fuse_req_t req,fuse_ino_t parent,const char * name,mode_t mode,dev_t rdev)2952 static void fuse_lib_mknod(fuse_req_t req, fuse_ino_t parent, const char *name,
2953 			   mode_t mode, dev_t rdev)
2954 {
2955 	struct fuse *f = req_fuse_prepare(req);
2956 	struct fuse_entry_param e;
2957 	char *path;
2958 	int err;
2959 
2960 	err = get_path_name(f, parent, name, &path);
2961 	if (!err) {
2962 		struct fuse_intr_data d;
2963 
2964 		fuse_prepare_interrupt(f, req, &d);
2965 		err = -ENOSYS;
2966 		if (S_ISREG(mode)) {
2967 			struct fuse_file_info fi;
2968 
2969 			memset(&fi, 0, sizeof(fi));
2970 			fi.flags = O_CREAT | O_EXCL | O_WRONLY;
2971 			err = fuse_fs_create(f->fs, path, mode, &fi);
2972 			if (!err) {
2973 				err = lookup_path(f, parent, name, path, &e,
2974 						  &fi);
2975 				fuse_fs_release(f->fs, path, &fi);
2976 			}
2977 		}
2978 		if (err == -ENOSYS) {
2979 			err = fuse_fs_mknod(f->fs, path, mode, rdev);
2980 			if (!err)
2981 				err = lookup_path(f, parent, name, path, &e,
2982 						  NULL);
2983 		}
2984 		fuse_finish_interrupt(f, req, &d);
2985 		free_path(f, parent, path);
2986 	}
2987 	reply_entry(req, &e, err);
2988 }
2989 
fuse_lib_mkdir(fuse_req_t req,fuse_ino_t parent,const char * name,mode_t mode)2990 static void fuse_lib_mkdir(fuse_req_t req, fuse_ino_t parent, const char *name,
2991 			   mode_t mode)
2992 {
2993 	struct fuse *f = req_fuse_prepare(req);
2994 	struct fuse_entry_param e;
2995 	char *path;
2996 	int err;
2997 
2998 	err = get_path_name(f, parent, name, &path);
2999 	if (!err) {
3000 		struct fuse_intr_data d;
3001 
3002 		fuse_prepare_interrupt(f, req, &d);
3003 		err = fuse_fs_mkdir(f->fs, path, mode);
3004 		if (!err)
3005 			err = lookup_path(f, parent, name, path, &e, NULL);
3006 		fuse_finish_interrupt(f, req, &d);
3007 		free_path(f, parent, path);
3008 	}
3009 	reply_entry(req, &e, err);
3010 }
3011 
fuse_lib_unlink(fuse_req_t req,fuse_ino_t parent,const char * name)3012 static void fuse_lib_unlink(fuse_req_t req, fuse_ino_t parent,
3013 			    const char *name)
3014 {
3015 	struct fuse *f = req_fuse_prepare(req);
3016 	struct node *wnode;
3017 	char *path;
3018 	int err;
3019 
3020 	err = get_path_wrlock(f, parent, name, &path, &wnode);
3021 	if (!err) {
3022 		struct fuse_intr_data d;
3023 
3024 		fuse_prepare_interrupt(f, req, &d);
3025 		if (!f->conf.hard_remove && is_open(f, parent, name)) {
3026 			err = hide_node(f, path, parent, name);
3027 		} else {
3028 			err = fuse_fs_unlink(f->fs, path);
3029 			if (!err)
3030 				remove_node(f, parent, name);
3031 		}
3032 		fuse_finish_interrupt(f, req, &d);
3033 		free_path_wrlock(f, parent, wnode, path);
3034 	}
3035 	reply_err(req, err);
3036 }
3037 
fuse_lib_rmdir(fuse_req_t req,fuse_ino_t parent,const char * name)3038 static void fuse_lib_rmdir(fuse_req_t req, fuse_ino_t parent, const char *name)
3039 {
3040 	struct fuse *f = req_fuse_prepare(req);
3041 	struct node *wnode;
3042 	char *path;
3043 	int err;
3044 
3045 	err = get_path_wrlock(f, parent, name, &path, &wnode);
3046 	if (!err) {
3047 		struct fuse_intr_data d;
3048 
3049 		fuse_prepare_interrupt(f, req, &d);
3050 		err = fuse_fs_rmdir(f->fs, path);
3051 		fuse_finish_interrupt(f, req, &d);
3052 		if (!err)
3053 			remove_node(f, parent, name);
3054 		free_path_wrlock(f, parent, wnode, path);
3055 	}
3056 	reply_err(req, err);
3057 }
3058 
fuse_lib_symlink(fuse_req_t req,const char * linkname,fuse_ino_t parent,const char * name)3059 static void fuse_lib_symlink(fuse_req_t req, const char *linkname,
3060 			     fuse_ino_t parent, const char *name)
3061 {
3062 	struct fuse *f = req_fuse_prepare(req);
3063 	struct fuse_entry_param e;
3064 	char *path;
3065 	int err;
3066 
3067 	err = get_path_name(f, parent, name, &path);
3068 	if (!err) {
3069 		struct fuse_intr_data d;
3070 
3071 		fuse_prepare_interrupt(f, req, &d);
3072 		err = fuse_fs_symlink(f->fs, linkname, path);
3073 		if (!err)
3074 			err = lookup_path(f, parent, name, path, &e, NULL);
3075 		fuse_finish_interrupt(f, req, &d);
3076 		free_path(f, parent, path);
3077 	}
3078 	reply_entry(req, &e, err);
3079 }
3080 
fuse_lib_rename(fuse_req_t req,fuse_ino_t olddir,const char * oldname,fuse_ino_t newdir,const char * newname)3081 static void fuse_lib_rename(fuse_req_t req, fuse_ino_t olddir,
3082 			    const char *oldname, fuse_ino_t newdir,
3083 			    const char *newname)
3084 {
3085 	struct fuse *f = req_fuse_prepare(req);
3086 	char *oldpath;
3087 	char *newpath;
3088 	struct node *wnode1;
3089 	struct node *wnode2;
3090 	int err;
3091 
3092 	err = get_path2(f, olddir, oldname, newdir, newname,
3093 			&oldpath, &newpath, &wnode1, &wnode2);
3094 	if (!err) {
3095 		struct fuse_intr_data d;
3096 		err = 0;
3097 		fuse_prepare_interrupt(f, req, &d);
3098 		if (!f->conf.hard_remove && is_open(f, newdir, newname))
3099 			err = hide_node(f, newpath, newdir, newname);
3100 		if (!err) {
3101 			err = fuse_fs_rename(f->fs, oldpath, newpath);
3102 			if (!err)
3103 				err = rename_node(f, olddir, oldname, newdir,
3104 						  newname, 0);
3105 		}
3106 		fuse_finish_interrupt(f, req, &d);
3107 		free_path2(f, olddir, newdir, wnode1, wnode2, oldpath, newpath);
3108 	}
3109 	reply_err(req, err);
3110 }
3111 
fuse_lib_link(fuse_req_t req,fuse_ino_t ino,fuse_ino_t newparent,const char * newname)3112 static void fuse_lib_link(fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent,
3113 			  const char *newname)
3114 {
3115 	struct fuse *f = req_fuse_prepare(req);
3116 	struct fuse_entry_param e;
3117 	char *oldpath;
3118 	char *newpath;
3119 	int err;
3120 
3121 	err = get_path2(f, ino, NULL, newparent, newname,
3122 			&oldpath, &newpath, NULL, NULL);
3123 	if (!err) {
3124 		struct fuse_intr_data d;
3125 
3126 		fuse_prepare_interrupt(f, req, &d);
3127 		err = fuse_fs_link(f->fs, oldpath, newpath);
3128 		if (!err)
3129 			err = lookup_path(f, newparent, newname, newpath,
3130 					  &e, NULL);
3131 		fuse_finish_interrupt(f, req, &d);
3132 		free_path2(f, ino, newparent, NULL, NULL, oldpath, newpath);
3133 	}
3134 	reply_entry(req, &e, err);
3135 }
3136 
fuse_do_release(struct fuse * f,fuse_ino_t ino,const char * path,struct fuse_file_info * fi)3137 static void fuse_do_release(struct fuse *f, fuse_ino_t ino, const char *path,
3138 			    struct fuse_file_info *fi)
3139 {
3140 	struct node *node;
3141 	int unlink_hidden = 0;
3142 	const char *compatpath;
3143 
3144 	if (path != NULL || f->nullpath_ok || f->conf.nopath)
3145 		compatpath = path;
3146 	else
3147 		compatpath = "-";
3148 
3149 	fuse_fs_release(f->fs, compatpath, fi);
3150 
3151 	pthread_mutex_lock(&f->lock);
3152 	node = get_node(f, ino);
3153 	assert(node->open_count > 0);
3154 	--node->open_count;
3155 	if (node->is_hidden && !node->open_count) {
3156 		unlink_hidden = 1;
3157 		node->is_hidden = 0;
3158 	}
3159 	pthread_mutex_unlock(&f->lock);
3160 
3161 	if(unlink_hidden) {
3162 		if (path) {
3163 			fuse_fs_unlink(f->fs, path);
3164 		} else if (f->conf.nopath) {
3165 			char *unlinkpath;
3166 
3167 			if (get_path(f, ino, &unlinkpath) == 0)
3168 				fuse_fs_unlink(f->fs, unlinkpath);
3169 
3170 			free_path(f, ino, unlinkpath);
3171 		}
3172 	}
3173 }
3174 
fuse_lib_create(fuse_req_t req,fuse_ino_t parent,const char * name,mode_t mode,struct fuse_file_info * fi)3175 static void fuse_lib_create(fuse_req_t req, fuse_ino_t parent,
3176 			    const char *name, mode_t mode,
3177 			    struct fuse_file_info *fi)
3178 {
3179 	struct fuse *f = req_fuse_prepare(req);
3180 	struct fuse_intr_data d;
3181 	struct fuse_entry_param e;
3182 	char *path;
3183 	int err;
3184 
3185 	err = get_path_name(f, parent, name, &path);
3186 	if (!err) {
3187 		fuse_prepare_interrupt(f, req, &d);
3188 		err = fuse_fs_create(f->fs, path, mode, fi);
3189 		if (!err) {
3190 			err = lookup_path(f, parent, name, path, &e, fi);
3191 			if (err)
3192 				fuse_fs_release(f->fs, path, fi);
3193 			else if (!S_ISREG(e.attr.st_mode)) {
3194 				err = -EIO;
3195 				fuse_fs_release(f->fs, path, fi);
3196 				forget_node(f, e.ino, 1);
3197 			} else {
3198 				if (f->conf.direct_io)
3199 					fi->direct_io = 1;
3200 				if (f->conf.kernel_cache)
3201 					fi->keep_cache = 1;
3202 
3203 			}
3204 		}
3205 		fuse_finish_interrupt(f, req, &d);
3206 	}
3207 	if (!err) {
3208 		pthread_mutex_lock(&f->lock);
3209 		get_node(f, e.ino)->open_count++;
3210 		pthread_mutex_unlock(&f->lock);
3211 		if (fuse_reply_create(req, &e, fi) == -ENOENT) {
3212 			/* The open syscall was interrupted, so it
3213 			   must be cancelled */
3214 			fuse_do_release(f, e.ino, path, fi);
3215 			forget_node(f, e.ino, 1);
3216 		}
3217 	} else {
3218 		reply_err(req, err);
3219 	}
3220 
3221 	free_path(f, parent, path);
3222 }
3223 
diff_timespec(const struct timespec * t1,const struct timespec * t2)3224 static double diff_timespec(const struct timespec *t1,
3225 			    const struct timespec *t2)
3226 {
3227 	return (t1->tv_sec - t2->tv_sec) +
3228 		((double) t1->tv_nsec - (double) t2->tv_nsec) / 1000000000.0;
3229 }
3230 
open_auto_cache(struct fuse * f,fuse_ino_t ino,const char * path,struct fuse_file_info * fi)3231 static void open_auto_cache(struct fuse *f, fuse_ino_t ino, const char *path,
3232 			    struct fuse_file_info *fi)
3233 {
3234 	struct node *node;
3235 
3236 	pthread_mutex_lock(&f->lock);
3237 	node = get_node(f, ino);
3238 	if (node->cache_valid) {
3239 		struct timespec now;
3240 
3241 		curr_time(&now);
3242 		if (diff_timespec(&now, &node->stat_updated) >
3243 		    f->conf.ac_attr_timeout) {
3244 			struct stat stbuf;
3245 			int err;
3246 			pthread_mutex_unlock(&f->lock);
3247 			err = fuse_fs_fgetattr(f->fs, path, &stbuf, fi);
3248 			pthread_mutex_lock(&f->lock);
3249 			if (!err)
3250 				update_stat(node, &stbuf);
3251 			else
3252 				node->cache_valid = 0;
3253 		}
3254 	}
3255 	if (node->cache_valid)
3256 		fi->keep_cache = 1;
3257 
3258 	node->cache_valid = 1;
3259 	pthread_mutex_unlock(&f->lock);
3260 }
3261 
fuse_lib_open(fuse_req_t req,fuse_ino_t ino,struct fuse_file_info * fi)3262 static void fuse_lib_open(fuse_req_t req, fuse_ino_t ino,
3263 			  struct fuse_file_info *fi)
3264 {
3265 	struct fuse *f = req_fuse_prepare(req);
3266 	struct fuse_intr_data d;
3267 	char *path;
3268 	int err;
3269 
3270 	err = get_path(f, ino, &path);
3271 	if (!err) {
3272 		fuse_prepare_interrupt(f, req, &d);
3273 		err = fuse_fs_open(f->fs, path, fi);
3274 		if (!err) {
3275 			if (f->conf.direct_io)
3276 				fi->direct_io = 1;
3277 			if (f->conf.kernel_cache)
3278 				fi->keep_cache = 1;
3279 
3280 			if (f->conf.auto_cache)
3281 				open_auto_cache(f, ino, path, fi);
3282 		}
3283 		fuse_finish_interrupt(f, req, &d);
3284 	}
3285 	if (!err) {
3286 		pthread_mutex_lock(&f->lock);
3287 		get_node(f, ino)->open_count++;
3288 		pthread_mutex_unlock(&f->lock);
3289 		if (fuse_reply_open(req, fi) == -ENOENT) {
3290 			/* The open syscall was interrupted, so it
3291 			   must be cancelled */
3292 			fuse_do_release(f, ino, path, fi);
3293 		}
3294 	} else
3295 		reply_err(req, err);
3296 
3297 	free_path(f, ino, path);
3298 }
3299 
fuse_lib_read(fuse_req_t req,fuse_ino_t ino,size_t size,off_t off,struct fuse_file_info * fi)3300 static void fuse_lib_read(fuse_req_t req, fuse_ino_t ino, size_t size,
3301 			  off_t off, struct fuse_file_info *fi)
3302 {
3303 	struct fuse *f = req_fuse_prepare(req);
3304 	struct fuse_bufvec *buf = NULL;
3305 	char *path;
3306 	int res;
3307 
3308 	res = get_path_nullok(f, ino, &path);
3309 	if (res == 0) {
3310 		struct fuse_intr_data d;
3311 
3312 		fuse_prepare_interrupt(f, req, &d);
3313 		res = fuse_fs_read_buf(f->fs, path, &buf, size, off, fi);
3314 		fuse_finish_interrupt(f, req, &d);
3315 		free_path(f, ino, path);
3316 	}
3317 
3318 	if (res == 0)
3319 		fuse_reply_data(req, buf, FUSE_BUF_SPLICE_MOVE);
3320 	else
3321 		reply_err(req, res);
3322 
3323 	fuse_free_buf(buf);
3324 }
3325 
fuse_lib_write_buf(fuse_req_t req,fuse_ino_t ino,struct fuse_bufvec * buf,off_t off,struct fuse_file_info * fi)3326 static void fuse_lib_write_buf(fuse_req_t req, fuse_ino_t ino,
3327 			       struct fuse_bufvec *buf, off_t off,
3328 			       struct fuse_file_info *fi)
3329 {
3330 	struct fuse *f = req_fuse_prepare(req);
3331 	char *path;
3332 	int res;
3333 
3334 	res = get_path_nullok(f, ino, &path);
3335 	if (res == 0) {
3336 		struct fuse_intr_data d;
3337 
3338 		fuse_prepare_interrupt(f, req, &d);
3339 		res = fuse_fs_write_buf(f->fs, path, buf, off, fi);
3340 		fuse_finish_interrupt(f, req, &d);
3341 		free_path(f, ino, path);
3342 	}
3343 
3344 	if (res >= 0)
3345 		fuse_reply_write(req, res);
3346 	else
3347 		reply_err(req, res);
3348 }
3349 
fuse_lib_fsync(fuse_req_t req,fuse_ino_t ino,int datasync,struct fuse_file_info * fi)3350 static void fuse_lib_fsync(fuse_req_t req, fuse_ino_t ino, int datasync,
3351 			   struct fuse_file_info *fi)
3352 {
3353 	struct fuse *f = req_fuse_prepare(req);
3354 	char *path;
3355 	int err;
3356 
3357 	err = get_path_nullok(f, ino, &path);
3358 	if (!err) {
3359 		struct fuse_intr_data d;
3360 
3361 		fuse_prepare_interrupt(f, req, &d);
3362 		err = fuse_fs_fsync(f->fs, path, datasync, fi);
3363 		fuse_finish_interrupt(f, req, &d);
3364 		free_path(f, ino, path);
3365 	}
3366 	reply_err(req, err);
3367 }
3368 
get_dirhandle(const struct fuse_file_info * llfi,struct fuse_file_info * fi)3369 static struct fuse_dh *get_dirhandle(const struct fuse_file_info *llfi,
3370 				     struct fuse_file_info *fi)
3371 {
3372 	struct fuse_dh *dh = (struct fuse_dh *) (uintptr_t) llfi->fh;
3373 	memset(fi, 0, sizeof(struct fuse_file_info));
3374 	fi->fh = dh->fh;
3375 	fi->fh_old = dh->fh;
3376 	return dh;
3377 }
3378 
fuse_lib_opendir(fuse_req_t req,fuse_ino_t ino,struct fuse_file_info * llfi)3379 static void fuse_lib_opendir(fuse_req_t req, fuse_ino_t ino,
3380 			     struct fuse_file_info *llfi)
3381 {
3382 	struct fuse *f = req_fuse_prepare(req);
3383 	struct fuse_intr_data d;
3384 	struct fuse_dh *dh;
3385 	struct fuse_file_info fi;
3386 	char *path;
3387 	int err;
3388 
3389 	dh = (struct fuse_dh *) malloc(sizeof(struct fuse_dh));
3390 	if (dh == NULL) {
3391 		reply_err(req, -ENOMEM);
3392 		return;
3393 	}
3394 	memset(dh, 0, sizeof(struct fuse_dh));
3395 	dh->fuse = f;
3396 	dh->contents = NULL;
3397 	dh->len = 0;
3398 	dh->filled = 0;
3399 	dh->nodeid = ino;
3400 	fuse_mutex_init(&dh->lock);
3401 
3402 	llfi->fh = (uintptr_t) dh;
3403 
3404 	memset(&fi, 0, sizeof(fi));
3405 	fi.flags = llfi->flags;
3406 
3407 	err = get_path(f, ino, &path);
3408 	if (!err) {
3409 		fuse_prepare_interrupt(f, req, &d);
3410 		err = fuse_fs_opendir(f->fs, path, &fi);
3411 		fuse_finish_interrupt(f, req, &d);
3412 		dh->fh = fi.fh;
3413 	}
3414 	if (!err) {
3415 		if (fuse_reply_open(req, llfi) == -ENOENT) {
3416 			/* The opendir syscall was interrupted, so it
3417 			   must be cancelled */
3418 			fuse_fs_releasedir(f->fs, path, &fi);
3419 			pthread_mutex_destroy(&dh->lock);
3420 			free(dh);
3421 		}
3422 	} else {
3423 		reply_err(req, err);
3424 		pthread_mutex_destroy(&dh->lock);
3425 		free(dh);
3426 	}
3427 	free_path(f, ino, path);
3428 }
3429 
extend_contents(struct fuse_dh * dh,unsigned minsize)3430 static int extend_contents(struct fuse_dh *dh, unsigned minsize)
3431 {
3432 	if (minsize > dh->size) {
3433 		char *newptr;
3434 		unsigned newsize = dh->size;
3435 		if (!newsize)
3436 			newsize = 1024;
3437 		while (newsize < minsize) {
3438 			if (newsize >= 0x80000000)
3439 				newsize = 0xffffffff;
3440 			else
3441 				newsize *= 2;
3442 		}
3443 
3444 		newptr = (char *) realloc(dh->contents, newsize);
3445 		if (!newptr) {
3446 			dh->error = -ENOMEM;
3447 			return -1;
3448 		}
3449 		dh->contents = newptr;
3450 		dh->size = newsize;
3451 	}
3452 	return 0;
3453 }
3454 
fill_dir(void * dh_,const char * name,const struct stat * statp,off_t off)3455 static int fill_dir(void *dh_, const char *name, const struct stat *statp,
3456 		    off_t off)
3457 {
3458 	struct fuse_dh *dh = (struct fuse_dh *) dh_;
3459 	struct stat stbuf;
3460 	size_t newlen;
3461 
3462 	if (statp)
3463 		stbuf = *statp;
3464 	else {
3465 		memset(&stbuf, 0, sizeof(stbuf));
3466 		stbuf.st_ino = FUSE_UNKNOWN_INO;
3467 	}
3468 
3469 	if (!dh->fuse->conf.use_ino) {
3470 		stbuf.st_ino = FUSE_UNKNOWN_INO;
3471 		if (dh->fuse->conf.readdir_ino) {
3472 			struct node *node;
3473 			pthread_mutex_lock(&dh->fuse->lock);
3474 			node = lookup_node(dh->fuse, dh->nodeid, name);
3475 			if (node)
3476 				stbuf.st_ino  = (ino_t) node->nodeid;
3477 			pthread_mutex_unlock(&dh->fuse->lock);
3478 		}
3479 	}
3480 
3481 	if (off) {
3482 		if (dh->filled) {
3483 			dh->error = -EIO;
3484 			return 1;
3485 		}
3486 
3487 		if (extend_contents(dh, dh->needlen) == -1)
3488 			return 1;
3489 
3490 		newlen = dh->len +
3491 			fuse_add_direntry(dh->req, dh->contents + dh->len,
3492 					  dh->needlen - dh->len, name,
3493 					  &stbuf, off);
3494 		if (newlen > dh->needlen)
3495 			return 1;
3496 	} else {
3497 		dh->filled = 1;
3498 
3499 		newlen = dh->len +
3500 			fuse_add_direntry(dh->req, NULL, 0, name, NULL, 0);
3501 		if (extend_contents(dh, newlen) == -1)
3502 			return 1;
3503 
3504 		fuse_add_direntry(dh->req, dh->contents + dh->len,
3505 				  dh->size - dh->len, name, &stbuf, newlen);
3506 	}
3507 	dh->len = newlen;
3508 	return 0;
3509 }
3510 
readdir_fill(struct fuse * f,fuse_req_t req,fuse_ino_t ino,size_t size,off_t off,struct fuse_dh * dh,struct fuse_file_info * fi)3511 static int readdir_fill(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
3512 			size_t size, off_t off, struct fuse_dh *dh,
3513 			struct fuse_file_info *fi)
3514 {
3515 	char *path;
3516 	int err;
3517 
3518 	if (f->fs->op.readdir)
3519 		err = get_path_nullok(f, ino, &path);
3520 	else
3521 		err = get_path(f, ino, &path);
3522 	if (!err) {
3523 		struct fuse_intr_data d;
3524 
3525 		dh->len = 0;
3526 		dh->error = 0;
3527 		dh->needlen = size;
3528 		dh->filled = 0;
3529 		dh->req = req;
3530 		fuse_prepare_interrupt(f, req, &d);
3531 		err = fuse_fs_readdir(f->fs, path, dh, fill_dir, off, fi);
3532 		fuse_finish_interrupt(f, req, &d);
3533 		dh->req = NULL;
3534 		if (!err)
3535 			err = dh->error;
3536 		if (err)
3537 			dh->filled = 0;
3538 		free_path(f, ino, path);
3539 	}
3540 	return err;
3541 }
3542 
fuse_lib_readdir(fuse_req_t req,fuse_ino_t ino,size_t size,off_t off,struct fuse_file_info * llfi)3543 static void fuse_lib_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
3544 			     off_t off, struct fuse_file_info *llfi)
3545 {
3546 	struct fuse *f = req_fuse_prepare(req);
3547 	struct fuse_file_info fi;
3548 	struct fuse_dh *dh = get_dirhandle(llfi, &fi);
3549 
3550 	pthread_mutex_lock(&dh->lock);
3551 	/* According to SUS, directory contents need to be refreshed on
3552 	   rewinddir() */
3553 	if (!off)
3554 		dh->filled = 0;
3555 
3556 	if (!dh->filled) {
3557 		int err = readdir_fill(f, req, ino, size, off, dh, &fi);
3558 		if (err) {
3559 			reply_err(req, err);
3560 			goto out;
3561 		}
3562 	}
3563 	if (dh->filled) {
3564 		if (off < dh->len) {
3565 			if (off + size > dh->len)
3566 				size = dh->len - off;
3567 		} else
3568 			size = 0;
3569 	} else {
3570 		size = dh->len;
3571 		off = 0;
3572 	}
3573 	fuse_reply_buf(req, dh->contents + off, size);
3574 out:
3575 	pthread_mutex_unlock(&dh->lock);
3576 }
3577 
fuse_lib_releasedir(fuse_req_t req,fuse_ino_t ino,struct fuse_file_info * llfi)3578 static void fuse_lib_releasedir(fuse_req_t req, fuse_ino_t ino,
3579 				struct fuse_file_info *llfi)
3580 {
3581 	struct fuse *f = req_fuse_prepare(req);
3582 	struct fuse_intr_data d;
3583 	struct fuse_file_info fi;
3584 	struct fuse_dh *dh = get_dirhandle(llfi, &fi);
3585 	char *path;
3586 	const char *compatpath;
3587 
3588 	get_path_nullok(f, ino, &path);
3589 	if (path != NULL || f->nullpath_ok || f->conf.nopath)
3590 		compatpath = path;
3591 	else
3592 		compatpath = "-";
3593 
3594 	fuse_prepare_interrupt(f, req, &d);
3595 	fuse_fs_releasedir(f->fs, compatpath, &fi);
3596 	fuse_finish_interrupt(f, req, &d);
3597 	free_path(f, ino, path);
3598 
3599 	pthread_mutex_lock(&dh->lock);
3600 	pthread_mutex_unlock(&dh->lock);
3601 	pthread_mutex_destroy(&dh->lock);
3602 	free(dh->contents);
3603 	free(dh);
3604 	reply_err(req, 0);
3605 }
3606 
fuse_lib_fsyncdir(fuse_req_t req,fuse_ino_t ino,int datasync,struct fuse_file_info * llfi)3607 static void fuse_lib_fsyncdir(fuse_req_t req, fuse_ino_t ino, int datasync,
3608 			      struct fuse_file_info *llfi)
3609 {
3610 	struct fuse *f = req_fuse_prepare(req);
3611 	struct fuse_file_info fi;
3612 	char *path;
3613 	int err;
3614 
3615 	get_dirhandle(llfi, &fi);
3616 
3617 	err = get_path_nullok(f, ino, &path);
3618 	if (!err) {
3619 		struct fuse_intr_data d;
3620 		fuse_prepare_interrupt(f, req, &d);
3621 		err = fuse_fs_fsyncdir(f->fs, path, datasync, &fi);
3622 		fuse_finish_interrupt(f, req, &d);
3623 		free_path(f, ino, path);
3624 	}
3625 	reply_err(req, err);
3626 }
3627 
fuse_lib_statfs(fuse_req_t req,fuse_ino_t ino)3628 static void fuse_lib_statfs(fuse_req_t req, fuse_ino_t ino)
3629 {
3630 	struct fuse *f = req_fuse_prepare(req);
3631 	struct statvfs buf;
3632 	char *path = NULL;
3633 	int err = 0;
3634 
3635 	memset(&buf, 0, sizeof(buf));
3636 	if (ino)
3637 		err = get_path(f, ino, &path);
3638 
3639 	if (!err) {
3640 		struct fuse_intr_data d;
3641 		fuse_prepare_interrupt(f, req, &d);
3642 		err = fuse_fs_statfs(f->fs, path ? path : "/", &buf);
3643 		fuse_finish_interrupt(f, req, &d);
3644 		free_path(f, ino, path);
3645 	}
3646 
3647 	if (!err)
3648 		fuse_reply_statfs(req, &buf);
3649 	else
3650 		reply_err(req, err);
3651 }
3652 
fuse_lib_setxattr(fuse_req_t req,fuse_ino_t ino,const char * name,const char * value,size_t size,int flags)3653 static void fuse_lib_setxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
3654 			      const char *value, size_t size, int flags)
3655 {
3656 	struct fuse *f = req_fuse_prepare(req);
3657 	char *path;
3658 	int err;
3659 
3660 	err = get_path(f, ino, &path);
3661 	if (!err) {
3662 		struct fuse_intr_data d;
3663 		fuse_prepare_interrupt(f, req, &d);
3664 		err = fuse_fs_setxattr(f->fs, path, name, value, size, flags);
3665 		fuse_finish_interrupt(f, req, &d);
3666 		free_path(f, ino, path);
3667 	}
3668 	reply_err(req, err);
3669 }
3670 
common_getxattr(struct fuse * f,fuse_req_t req,fuse_ino_t ino,const char * name,char * value,size_t size)3671 static int common_getxattr(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
3672 			   const char *name, char *value, size_t size)
3673 {
3674 	int err;
3675 	char *path;
3676 
3677 	err = get_path(f, ino, &path);
3678 	if (!err) {
3679 		struct fuse_intr_data d;
3680 		fuse_prepare_interrupt(f, req, &d);
3681 		err = fuse_fs_getxattr(f->fs, path, name, value, size);
3682 		fuse_finish_interrupt(f, req, &d);
3683 		free_path(f, ino, path);
3684 	}
3685 	return err;
3686 }
3687 
fuse_lib_getxattr(fuse_req_t req,fuse_ino_t ino,const char * name,size_t size)3688 static void fuse_lib_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
3689 			      size_t size)
3690 {
3691 	struct fuse *f = req_fuse_prepare(req);
3692 	int res;
3693 
3694 	if (size) {
3695 		char *value = (char *) malloc(size);
3696 		if (value == NULL) {
3697 			reply_err(req, -ENOMEM);
3698 			return;
3699 		}
3700 		res = common_getxattr(f, req, ino, name, value, size);
3701 		if (res > 0)
3702 			fuse_reply_buf(req, value, res);
3703 		else
3704 			reply_err(req, res);
3705 		free(value);
3706 	} else {
3707 		res = common_getxattr(f, req, ino, name, NULL, 0);
3708 		if (res >= 0)
3709 			fuse_reply_xattr(req, res);
3710 		else
3711 			reply_err(req, res);
3712 	}
3713 }
3714 
common_listxattr(struct fuse * f,fuse_req_t req,fuse_ino_t ino,char * list,size_t size)3715 static int common_listxattr(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
3716 			    char *list, size_t size)
3717 {
3718 	char *path;
3719 	int err;
3720 
3721 	err = get_path(f, ino, &path);
3722 	if (!err) {
3723 		struct fuse_intr_data d;
3724 		fuse_prepare_interrupt(f, req, &d);
3725 		err = fuse_fs_listxattr(f->fs, path, list, size);
3726 		fuse_finish_interrupt(f, req, &d);
3727 		free_path(f, ino, path);
3728 	}
3729 	return err;
3730 }
3731 
fuse_lib_listxattr(fuse_req_t req,fuse_ino_t ino,size_t size)3732 static void fuse_lib_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size)
3733 {
3734 	struct fuse *f = req_fuse_prepare(req);
3735 	int res;
3736 
3737 	if (size) {
3738 		char *list = (char *) malloc(size);
3739 		if (list == NULL) {
3740 			reply_err(req, -ENOMEM);
3741 			return;
3742 		}
3743 		res = common_listxattr(f, req, ino, list, size);
3744 		if (res > 0)
3745 			fuse_reply_buf(req, list, res);
3746 		else
3747 			reply_err(req, res);
3748 		free(list);
3749 	} else {
3750 		res = common_listxattr(f, req, ino, NULL, 0);
3751 		if (res >= 0)
3752 			fuse_reply_xattr(req, res);
3753 		else
3754 			reply_err(req, res);
3755 	}
3756 }
3757 
fuse_lib_removexattr(fuse_req_t req,fuse_ino_t ino,const char * name)3758 static void fuse_lib_removexattr(fuse_req_t req, fuse_ino_t ino,
3759 				 const char *name)
3760 {
3761 	struct fuse *f = req_fuse_prepare(req);
3762 	char *path;
3763 	int err;
3764 
3765 	err = get_path(f, ino, &path);
3766 	if (!err) {
3767 		struct fuse_intr_data d;
3768 		fuse_prepare_interrupt(f, req, &d);
3769 		err = fuse_fs_removexattr(f->fs, path, name);
3770 		fuse_finish_interrupt(f, req, &d);
3771 		free_path(f, ino, path);
3772 	}
3773 	reply_err(req, err);
3774 }
3775 
locks_conflict(struct node * node,const struct lock * lock)3776 static struct lock *locks_conflict(struct node *node, const struct lock *lock)
3777 {
3778 	struct lock *l;
3779 
3780 	for (l = node->locks; l; l = l->next)
3781 		if (l->owner != lock->owner &&
3782 		    lock->start <= l->end && l->start <= lock->end &&
3783 		    (l->type == F_WRLCK || lock->type == F_WRLCK))
3784 			break;
3785 
3786 	return l;
3787 }
3788 
delete_lock(struct lock ** lockp)3789 static void delete_lock(struct lock **lockp)
3790 {
3791 	struct lock *l = *lockp;
3792 	*lockp = l->next;
3793 	free(l);
3794 }
3795 
insert_lock(struct lock ** pos,struct lock * lock)3796 static void insert_lock(struct lock **pos, struct lock *lock)
3797 {
3798 	lock->next = *pos;
3799 	*pos = lock;
3800 }
3801 
locks_insert(struct node * node,struct lock * lock)3802 static int locks_insert(struct node *node, struct lock *lock)
3803 {
3804 	struct lock **lp;
3805 	struct lock *newl1 = NULL;
3806 	struct lock *newl2 = NULL;
3807 
3808 	if (lock->type != F_UNLCK || lock->start != 0 ||
3809 	    lock->end != OFFSET_MAX) {
3810 		newl1 = malloc(sizeof(struct lock));
3811 		newl2 = malloc(sizeof(struct lock));
3812 
3813 		if (!newl1 || !newl2) {
3814 			free(newl1);
3815 			free(newl2);
3816 			return -ENOLCK;
3817 		}
3818 	}
3819 
3820 	for (lp = &node->locks; *lp;) {
3821 		struct lock *l = *lp;
3822 		if (l->owner != lock->owner)
3823 			goto skip;
3824 
3825 		if (lock->type == l->type) {
3826 			if (l->end < lock->start - 1)
3827 				goto skip;
3828 			if (lock->end < l->start - 1)
3829 				break;
3830 			if (l->start <= lock->start && lock->end <= l->end)
3831 				goto out;
3832 			if (l->start < lock->start)
3833 				lock->start = l->start;
3834 			if (lock->end < l->end)
3835 				lock->end = l->end;
3836 			goto delete;
3837 		} else {
3838 			if (l->end < lock->start)
3839 				goto skip;
3840 			if (lock->end < l->start)
3841 				break;
3842 			if (lock->start <= l->start && l->end <= lock->end)
3843 				goto delete;
3844 			if (l->end <= lock->end) {
3845 				l->end = lock->start - 1;
3846 				goto skip;
3847 			}
3848 			if (lock->start <= l->start) {
3849 				l->start = lock->end + 1;
3850 				break;
3851 			}
3852 			*newl2 = *l;
3853 			newl2->start = lock->end + 1;
3854 			l->end = lock->start - 1;
3855 			insert_lock(&l->next, newl2);
3856 			newl2 = NULL;
3857 		}
3858 	skip:
3859 		lp = &l->next;
3860 		continue;
3861 
3862 	delete:
3863 		delete_lock(lp);
3864 	}
3865 	if (lock->type != F_UNLCK) {
3866 		*newl1 = *lock;
3867 		insert_lock(lp, newl1);
3868 		newl1 = NULL;
3869 	}
3870 out:
3871 	free(newl1);
3872 	free(newl2);
3873 	return 0;
3874 }
3875 
flock_to_lock(struct flock * flock,struct lock * lock)3876 static void flock_to_lock(struct flock *flock, struct lock *lock)
3877 {
3878 	memset(lock, 0, sizeof(struct lock));
3879 	lock->type = flock->l_type;
3880 	lock->start = flock->l_start;
3881 	lock->end =
3882 		flock->l_len ? flock->l_start + flock->l_len - 1 : OFFSET_MAX;
3883 	lock->pid = flock->l_pid;
3884 }
3885 
lock_to_flock(struct lock * lock,struct flock * flock)3886 static void lock_to_flock(struct lock *lock, struct flock *flock)
3887 {
3888 	flock->l_type = lock->type;
3889 	flock->l_start = lock->start;
3890 	flock->l_len =
3891 		(lock->end == OFFSET_MAX) ? 0 : lock->end - lock->start + 1;
3892 	flock->l_pid = lock->pid;
3893 }
3894 
fuse_flush_common(struct fuse * f,fuse_req_t req,fuse_ino_t ino,const char * path,struct fuse_file_info * fi)3895 static int fuse_flush_common(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
3896 			     const char *path, struct fuse_file_info *fi)
3897 {
3898 	struct fuse_intr_data d;
3899 	struct flock lock;
3900 	struct lock l;
3901 	int err;
3902 	int errlock;
3903 
3904 	fuse_prepare_interrupt(f, req, &d);
3905 	memset(&lock, 0, sizeof(lock));
3906 	lock.l_type = F_UNLCK;
3907 	lock.l_whence = SEEK_SET;
3908 	err = fuse_fs_flush(f->fs, path, fi);
3909 	errlock = fuse_fs_lock(f->fs, path, fi, F_SETLK, &lock);
3910 	fuse_finish_interrupt(f, req, &d);
3911 
3912 	if (errlock != -ENOSYS) {
3913 		flock_to_lock(&lock, &l);
3914 		l.owner = fi->lock_owner;
3915 		pthread_mutex_lock(&f->lock);
3916 		locks_insert(get_node(f, ino), &l);
3917 		pthread_mutex_unlock(&f->lock);
3918 
3919 		/* if op.lock() is defined FLUSH is needed regardless
3920 		   of op.flush() */
3921 		if (err == -ENOSYS)
3922 			err = 0;
3923 	}
3924 	return err;
3925 }
3926 
fuse_lib_release(fuse_req_t req,fuse_ino_t ino,struct fuse_file_info * fi)3927 static void fuse_lib_release(fuse_req_t req, fuse_ino_t ino,
3928 			     struct fuse_file_info *fi)
3929 {
3930 	struct fuse *f = req_fuse_prepare(req);
3931 	struct fuse_intr_data d;
3932 	char *path;
3933 	int err = 0;
3934 
3935 	get_path_nullok(f, ino, &path);
3936 	if (fi->flush) {
3937 		err = fuse_flush_common(f, req, ino, path, fi);
3938 		if (err == -ENOSYS)
3939 			err = 0;
3940 	}
3941 
3942 	fuse_prepare_interrupt(f, req, &d);
3943 	fuse_do_release(f, ino, path, fi);
3944 	fuse_finish_interrupt(f, req, &d);
3945 	free_path(f, ino, path);
3946 
3947 	reply_err(req, err);
3948 }
3949 
fuse_lib_flush(fuse_req_t req,fuse_ino_t ino,struct fuse_file_info * fi)3950 static void fuse_lib_flush(fuse_req_t req, fuse_ino_t ino,
3951 			   struct fuse_file_info *fi)
3952 {
3953 	struct fuse *f = req_fuse_prepare(req);
3954 	char *path;
3955 	int err;
3956 
3957 	get_path_nullok(f, ino, &path);
3958 	err = fuse_flush_common(f, req, ino, path, fi);
3959 	free_path(f, ino, path);
3960 
3961 	reply_err(req, err);
3962 }
3963 
fuse_lock_common(fuse_req_t req,fuse_ino_t ino,struct fuse_file_info * fi,struct flock * lock,int cmd)3964 static int fuse_lock_common(fuse_req_t req, fuse_ino_t ino,
3965 			    struct fuse_file_info *fi, struct flock *lock,
3966 			    int cmd)
3967 {
3968 	struct fuse *f = req_fuse_prepare(req);
3969 	char *path;
3970 	int err;
3971 
3972 	err = get_path_nullok(f, ino, &path);
3973 	if (!err) {
3974 		struct fuse_intr_data d;
3975 		fuse_prepare_interrupt(f, req, &d);
3976 		err = fuse_fs_lock(f->fs, path, fi, cmd, lock);
3977 		fuse_finish_interrupt(f, req, &d);
3978 		free_path(f, ino, path);
3979 	}
3980 	return err;
3981 }
3982 
fuse_lib_getlk(fuse_req_t req,fuse_ino_t ino,struct fuse_file_info * fi,struct flock * lock)3983 static void fuse_lib_getlk(fuse_req_t req, fuse_ino_t ino,
3984 			   struct fuse_file_info *fi, struct flock *lock)
3985 {
3986 	int err;
3987 	struct lock l;
3988 	struct lock *conflict;
3989 	struct fuse *f = req_fuse(req);
3990 
3991 	flock_to_lock(lock, &l);
3992 	l.owner = fi->lock_owner;
3993 	pthread_mutex_lock(&f->lock);
3994 	conflict = locks_conflict(get_node(f, ino), &l);
3995 	if (conflict)
3996 		lock_to_flock(conflict, lock);
3997 	pthread_mutex_unlock(&f->lock);
3998 	if (!conflict)
3999 		err = fuse_lock_common(req, ino, fi, lock, F_GETLK);
4000 	else
4001 		err = 0;
4002 
4003 	if (!err)
4004 		fuse_reply_lock(req, lock);
4005 	else
4006 		reply_err(req, err);
4007 }
4008 
fuse_lib_setlk(fuse_req_t req,fuse_ino_t ino,struct fuse_file_info * fi,struct flock * lock,int sleep)4009 static void fuse_lib_setlk(fuse_req_t req, fuse_ino_t ino,
4010 			   struct fuse_file_info *fi, struct flock *lock,
4011 			   int sleep)
4012 {
4013 	int err = fuse_lock_common(req, ino, fi, lock,
4014 				   sleep ? F_SETLKW : F_SETLK);
4015 	if (!err) {
4016 		struct fuse *f = req_fuse(req);
4017 		struct lock l;
4018 		flock_to_lock(lock, &l);
4019 		l.owner = fi->lock_owner;
4020 		pthread_mutex_lock(&f->lock);
4021 		locks_insert(get_node(f, ino), &l);
4022 		pthread_mutex_unlock(&f->lock);
4023 	}
4024 	reply_err(req, err);
4025 }
4026 
fuse_lib_flock(fuse_req_t req,fuse_ino_t ino,struct fuse_file_info * fi,int op)4027 static void fuse_lib_flock(fuse_req_t req, fuse_ino_t ino,
4028 			   struct fuse_file_info *fi, int op)
4029 {
4030 	struct fuse *f = req_fuse_prepare(req);
4031 	char *path;
4032 	int err;
4033 
4034 	err = get_path_nullok(f, ino, &path);
4035 	if (err == 0) {
4036 		struct fuse_intr_data d;
4037 		fuse_prepare_interrupt(f, req, &d);
4038 		err = fuse_fs_flock(f->fs, path, fi, op);
4039 		fuse_finish_interrupt(f, req, &d);
4040 		free_path(f, ino, path);
4041 	}
4042 	reply_err(req, err);
4043 }
4044 
fuse_lib_bmap(fuse_req_t req,fuse_ino_t ino,size_t blocksize,uint64_t idx)4045 static void fuse_lib_bmap(fuse_req_t req, fuse_ino_t ino, size_t blocksize,
4046 			  uint64_t idx)
4047 {
4048 	struct fuse *f = req_fuse_prepare(req);
4049 	struct fuse_intr_data d;
4050 	char *path;
4051 	int err;
4052 
4053 	err = get_path(f, ino, &path);
4054 	if (!err) {
4055 		fuse_prepare_interrupt(f, req, &d);
4056 		err = fuse_fs_bmap(f->fs, path, blocksize, &idx);
4057 		fuse_finish_interrupt(f, req, &d);
4058 		free_path(f, ino, path);
4059 	}
4060 	if (!err)
4061 		fuse_reply_bmap(req, idx);
4062 	else
4063 		reply_err(req, err);
4064 }
4065 
fuse_lib_ioctl(fuse_req_t req,fuse_ino_t ino,int cmd,void * arg,struct fuse_file_info * llfi,unsigned int flags,const void * in_buf,size_t in_bufsz,size_t out_bufsz)4066 static void fuse_lib_ioctl(fuse_req_t req, fuse_ino_t ino, int cmd, void *arg,
4067 			   struct fuse_file_info *llfi, unsigned int flags,
4068 			   const void *in_buf, size_t in_bufsz,
4069 			   size_t out_bufsz)
4070 {
4071 	struct fuse *f = req_fuse_prepare(req);
4072 	struct fuse_intr_data d;
4073 	struct fuse_file_info fi;
4074 	char *path, *out_buf = NULL;
4075 	int err;
4076 
4077 	err = -EPERM;
4078 	if (flags & FUSE_IOCTL_UNRESTRICTED)
4079 		goto err;
4080 
4081 	if (flags & FUSE_IOCTL_DIR)
4082 		get_dirhandle(llfi, &fi);
4083 	else
4084 		fi = *llfi;
4085 
4086 	if (out_bufsz) {
4087 		err = -ENOMEM;
4088 		out_buf = malloc(out_bufsz);
4089 		if (!out_buf)
4090 			goto err;
4091 	}
4092 
4093 	assert(!in_bufsz || !out_bufsz || in_bufsz == out_bufsz);
4094 	if (out_buf)
4095 		memcpy(out_buf, in_buf, in_bufsz);
4096 
4097 	err = get_path_nullok(f, ino, &path);
4098 	if (err)
4099 		goto err;
4100 
4101 	fuse_prepare_interrupt(f, req, &d);
4102 
4103 	err = fuse_fs_ioctl(f->fs, path, cmd, arg, &fi, flags,
4104 			    out_buf ?: (void *)in_buf);
4105 
4106 	fuse_finish_interrupt(f, req, &d);
4107 	free_path(f, ino, path);
4108 
4109 	fuse_reply_ioctl(req, err, out_buf, out_bufsz);
4110 	goto out;
4111 err:
4112 	reply_err(req, err);
4113 out:
4114 	free(out_buf);
4115 }
4116 
fuse_lib_poll(fuse_req_t req,fuse_ino_t ino,struct fuse_file_info * fi,struct fuse_pollhandle * ph)4117 static void fuse_lib_poll(fuse_req_t req, fuse_ino_t ino,
4118 			  struct fuse_file_info *fi, struct fuse_pollhandle *ph)
4119 {
4120 	struct fuse *f = req_fuse_prepare(req);
4121 	struct fuse_intr_data d;
4122 	char *path;
4123 	int err;
4124 	unsigned revents = 0;
4125 
4126 	err = get_path_nullok(f, ino, &path);
4127 	if (!err) {
4128 		fuse_prepare_interrupt(f, req, &d);
4129 		err = fuse_fs_poll(f->fs, path, fi, ph, &revents);
4130 		fuse_finish_interrupt(f, req, &d);
4131 		free_path(f, ino, path);
4132 	}
4133 	if (!err)
4134 		fuse_reply_poll(req, revents);
4135 	else
4136 		reply_err(req, err);
4137 }
4138 
fuse_lib_fallocate(fuse_req_t req,fuse_ino_t ino,int mode,off_t offset,off_t length,struct fuse_file_info * fi)4139 static void fuse_lib_fallocate(fuse_req_t req, fuse_ino_t ino, int mode,
4140 		off_t offset, off_t length, struct fuse_file_info *fi)
4141 {
4142 	struct fuse *f = req_fuse_prepare(req);
4143 	struct fuse_intr_data d;
4144 	char *path;
4145 	int err;
4146 
4147 	err = get_path_nullok(f, ino, &path);
4148 	if (!err) {
4149 		fuse_prepare_interrupt(f, req, &d);
4150 		err = fuse_fs_fallocate(f->fs, path, mode, offset, length, fi);
4151 		fuse_finish_interrupt(f, req, &d);
4152 		free_path(f, ino, path);
4153 	}
4154 	reply_err(req, err);
4155 }
4156 
clean_delay(struct fuse * f)4157 static int clean_delay(struct fuse *f)
4158 {
4159 	/*
4160 	 * This is calculating the delay between clean runs.  To
4161 	 * reduce the number of cleans we are doing them 10 times
4162 	 * within the remember window.
4163 	 */
4164 	int min_sleep = 60;
4165 	int max_sleep = 3600;
4166 	int sleep_time = f->conf.remember / 10;
4167 
4168 	if (sleep_time > max_sleep)
4169 		return max_sleep;
4170 	if (sleep_time < min_sleep)
4171 		return min_sleep;
4172 	return sleep_time;
4173 }
4174 
fuse_clean_cache(struct fuse * f)4175 int fuse_clean_cache(struct fuse *f)
4176 {
4177 	struct node_lru *lnode;
4178 	struct list_head *curr, *next;
4179 	struct node *node;
4180 	struct timespec now;
4181 
4182 	pthread_mutex_lock(&f->lock);
4183 
4184 	curr_time(&now);
4185 
4186 	for (curr = f->lru_table.next; curr != &f->lru_table; curr = next) {
4187 		double age;
4188 
4189 		next = curr->next;
4190 		lnode = list_entry(curr, struct node_lru, lru);
4191 		node = &lnode->node;
4192 
4193 		age = diff_timespec(&now, &lnode->forget_time);
4194 		if (age <= f->conf.remember)
4195 			break;
4196 
4197 		assert(node->nlookup == 1);
4198 
4199 		/* Don't forget active directories */
4200 		if (node->refctr > 1)
4201 			continue;
4202 
4203 		node->nlookup = 0;
4204 		unhash_name(f, node);
4205 		unref_node(f, node);
4206 	}
4207 	pthread_mutex_unlock(&f->lock);
4208 
4209 	return clean_delay(f);
4210 }
4211 
4212 static struct fuse_lowlevel_ops fuse_path_ops = {
4213 	.init = fuse_lib_init,
4214 	.destroy = fuse_lib_destroy,
4215 	.lookup = fuse_lib_lookup,
4216 	.forget = fuse_lib_forget,
4217 	.forget_multi = fuse_lib_forget_multi,
4218 	.getattr = fuse_lib_getattr,
4219 	.setattr = fuse_lib_setattr,
4220 	.access = fuse_lib_access,
4221 	.readlink = fuse_lib_readlink,
4222 	.mknod = fuse_lib_mknod,
4223 	.mkdir = fuse_lib_mkdir,
4224 	.unlink = fuse_lib_unlink,
4225 	.rmdir = fuse_lib_rmdir,
4226 	.symlink = fuse_lib_symlink,
4227 	.rename = fuse_lib_rename,
4228 	.link = fuse_lib_link,
4229 	.create = fuse_lib_create,
4230 	.open = fuse_lib_open,
4231 	.read = fuse_lib_read,
4232 	.write_buf = fuse_lib_write_buf,
4233 	.flush = fuse_lib_flush,
4234 	.release = fuse_lib_release,
4235 	.fsync = fuse_lib_fsync,
4236 	.opendir = fuse_lib_opendir,
4237 	.readdir = fuse_lib_readdir,
4238 	.releasedir = fuse_lib_releasedir,
4239 	.fsyncdir = fuse_lib_fsyncdir,
4240 	.statfs = fuse_lib_statfs,
4241 	.setxattr = fuse_lib_setxattr,
4242 	.getxattr = fuse_lib_getxattr,
4243 	.listxattr = fuse_lib_listxattr,
4244 	.removexattr = fuse_lib_removexattr,
4245 	.getlk = fuse_lib_getlk,
4246 	.setlk = fuse_lib_setlk,
4247 	.flock = fuse_lib_flock,
4248 	.bmap = fuse_lib_bmap,
4249 	.ioctl = fuse_lib_ioctl,
4250 	.poll = fuse_lib_poll,
4251 	.fallocate = fuse_lib_fallocate,
4252 };
4253 
fuse_notify_poll(struct fuse_pollhandle * ph)4254 int fuse_notify_poll(struct fuse_pollhandle *ph)
4255 {
4256 	return fuse_lowlevel_notify_poll(ph);
4257 }
4258 
free_cmd(struct fuse_cmd * cmd)4259 static void free_cmd(struct fuse_cmd *cmd)
4260 {
4261 	free(cmd->buf);
4262 	free(cmd);
4263 }
4264 
fuse_process_cmd(struct fuse * f,struct fuse_cmd * cmd)4265 void fuse_process_cmd(struct fuse *f, struct fuse_cmd *cmd)
4266 {
4267 	fuse_session_process(f->se, cmd->buf, cmd->buflen, cmd->ch);
4268 	free_cmd(cmd);
4269 }
4270 
fuse_exited(struct fuse * f)4271 int fuse_exited(struct fuse *f)
4272 {
4273 	return fuse_session_exited(f->se);
4274 }
4275 
fuse_get_session(struct fuse * f)4276 struct fuse_session *fuse_get_session(struct fuse *f)
4277 {
4278 	return f->se;
4279 }
4280 
fuse_alloc_cmd(size_t bufsize)4281 static struct fuse_cmd *fuse_alloc_cmd(size_t bufsize)
4282 {
4283 	struct fuse_cmd *cmd = (struct fuse_cmd *) malloc(sizeof(*cmd));
4284 	if (cmd == NULL) {
4285 		fprintf(stderr, "fuse: failed to allocate cmd\n");
4286 		return NULL;
4287 	}
4288 	cmd->buf = (char *) malloc(bufsize);
4289 	if (cmd->buf == NULL) {
4290 		fprintf(stderr, "fuse: failed to allocate read buffer\n");
4291 		free(cmd);
4292 		return NULL;
4293 	}
4294 	return cmd;
4295 }
4296 
fuse_read_cmd(struct fuse * f)4297 struct fuse_cmd *fuse_read_cmd(struct fuse *f)
4298 {
4299 	struct fuse_chan *ch = fuse_session_next_chan(f->se, NULL);
4300 	size_t bufsize = fuse_chan_bufsize(ch);
4301 	struct fuse_cmd *cmd = fuse_alloc_cmd(bufsize);
4302 	if (cmd != NULL) {
4303 		int res = fuse_chan_recv(&ch, cmd->buf, bufsize);
4304 		if (res <= 0) {
4305 			free_cmd(cmd);
4306 			if (res < 0 && res != -EINTR && res != -EAGAIN)
4307 				fuse_exit(f);
4308 			return NULL;
4309 		}
4310 		cmd->buflen = res;
4311 		cmd->ch = ch;
4312 	}
4313 	return cmd;
4314 }
4315 
fuse_session_loop_remember(struct fuse * f)4316 static int fuse_session_loop_remember(struct fuse *f)
4317 {
4318 	struct fuse_session *se = f->se;
4319 	int res = 0;
4320 	struct timespec now;
4321 	time_t next_clean;
4322 	struct fuse_chan *ch = fuse_session_next_chan(se, NULL);
4323 	size_t bufsize = fuse_chan_bufsize(ch);
4324 	char *buf = (char *) malloc(bufsize);
4325 	struct pollfd fds = {
4326 		.fd = fuse_chan_fd(ch),
4327 		.events = POLLIN
4328 	};
4329 
4330 	if (!buf) {
4331 		fprintf(stderr, "fuse: failed to allocate read buffer\n");
4332 		return -1;
4333 	}
4334 
4335 	curr_time(&now);
4336 	next_clean = now.tv_sec;
4337 	while (!fuse_session_exited(se)) {
4338 		struct fuse_chan *tmpch = ch;
4339 		struct fuse_buf fbuf = {
4340 			.mem = buf,
4341 			.size = bufsize,
4342 		};
4343 		unsigned timeout;
4344 
4345 		curr_time(&now);
4346 		if (now.tv_sec < next_clean)
4347 			timeout = next_clean - now.tv_sec;
4348 		else
4349 			timeout = 0;
4350 
4351 		res = poll(&fds, 1, timeout * 1000);
4352 		if (res == -1) {
4353 			if (errno == -EINTR)
4354 				continue;
4355 			else
4356 				break;
4357 		} else if (res > 0) {
4358 			res = fuse_session_receive_buf(se, &fbuf, &tmpch);
4359 
4360 			if (res == -EINTR)
4361 				continue;
4362 			if (res <= 0)
4363 				break;
4364 
4365 			fuse_session_process_buf(se, &fbuf, tmpch);
4366 		} else {
4367 			timeout = fuse_clean_cache(f);
4368 			curr_time(&now);
4369 			next_clean = now.tv_sec + timeout;
4370 		}
4371 	}
4372 
4373 	free(buf);
4374 	fuse_session_reset(se);
4375 	return res < 0 ? -1 : 0;
4376 }
4377 
fuse_loop(struct fuse * f)4378 int fuse_loop(struct fuse *f)
4379 {
4380 	if (!f)
4381 		return -1;
4382 
4383 	if (lru_enabled(f))
4384 		return fuse_session_loop_remember(f);
4385 
4386 	return fuse_session_loop(f->se);
4387 }
4388 
fuse_invalidate(struct fuse * f,const char * path)4389 int fuse_invalidate(struct fuse *f, const char *path)
4390 {
4391 	(void) f;
4392 	(void) path;
4393 	return -EINVAL;
4394 }
4395 
fuse_exit(struct fuse * f)4396 void fuse_exit(struct fuse *f)
4397 {
4398 	fuse_session_exit(f->se);
4399 }
4400 
fuse_get_context(void)4401 struct fuse_context *fuse_get_context(void)
4402 {
4403 	return &fuse_get_context_internal()->ctx;
4404 }
4405 
4406 /*
4407  * The size of fuse_context got extended, so need to be careful about
4408  * incompatibility (i.e. a new binary cannot work with an old
4409  * library).
4410  */
4411 struct fuse_context *fuse_get_context_compat22(void);
fuse_get_context_compat22(void)4412 struct fuse_context *fuse_get_context_compat22(void)
4413 {
4414 	return &fuse_get_context_internal()->ctx;
4415 }
4416 FUSE_SYMVER(".symver fuse_get_context_compat22,fuse_get_context@FUSE_2.2");
4417 
fuse_getgroups(int size,gid_t list[])4418 int fuse_getgroups(int size, gid_t list[])
4419 {
4420 	fuse_req_t req = fuse_get_context_internal()->req;
4421 	return fuse_req_getgroups(req, size, list);
4422 }
4423 
fuse_interrupted(void)4424 int fuse_interrupted(void)
4425 {
4426 	struct fuse_context_i *c = fuse_get_context_internal();
4427 
4428 	return c->req ? fuse_req_interrupted(c->req) : 0;
4429 }
4430 
fuse_set_getcontext_func(struct fuse_context * (* func)(void))4431 void fuse_set_getcontext_func(struct fuse_context *(*func)(void))
4432 {
4433 	(void) func;
4434 	/* no-op */
4435 }
4436 
4437 enum {
4438 	KEY_HELP,
4439 };
4440 
4441 #define FUSE_LIB_OPT(t, p, v) { t, offsetof(struct fuse_config, p), v }
4442 
4443 static const struct fuse_opt fuse_lib_opts[] = {
4444 	FUSE_OPT_KEY("-h",		      KEY_HELP),
4445 	FUSE_OPT_KEY("--help",		      KEY_HELP),
4446 	FUSE_OPT_KEY("debug",		      FUSE_OPT_KEY_KEEP),
4447 	FUSE_OPT_KEY("-d",		      FUSE_OPT_KEY_KEEP),
4448 	FUSE_LIB_OPT("debug",		      debug, 1),
4449 	FUSE_LIB_OPT("-d",		      debug, 1),
4450 	FUSE_LIB_OPT("hard_remove",	      hard_remove, 1),
4451 	FUSE_LIB_OPT("use_ino",		      use_ino, 1),
4452 	FUSE_LIB_OPT("readdir_ino",	      readdir_ino, 1),
4453 	FUSE_LIB_OPT("direct_io",	      direct_io, 1),
4454 	FUSE_LIB_OPT("kernel_cache",	      kernel_cache, 1),
4455 	FUSE_LIB_OPT("auto_cache",	      auto_cache, 1),
4456 	FUSE_LIB_OPT("noauto_cache",	      auto_cache, 0),
4457 	FUSE_LIB_OPT("umask=",		      set_mode, 1),
4458 	FUSE_LIB_OPT("umask=%o",	      umask, 0),
4459 	FUSE_LIB_OPT("uid=",		      set_uid, 1),
4460 	FUSE_LIB_OPT("uid=%d",		      uid, 0),
4461 	FUSE_LIB_OPT("gid=",		      set_gid, 1),
4462 	FUSE_LIB_OPT("gid=%d",		      gid, 0),
4463 	FUSE_LIB_OPT("entry_timeout=%lf",     entry_timeout, 0),
4464 	FUSE_LIB_OPT("attr_timeout=%lf",      attr_timeout, 0),
4465 	FUSE_LIB_OPT("ac_attr_timeout=%lf",   ac_attr_timeout, 0),
4466 	FUSE_LIB_OPT("ac_attr_timeout=",      ac_attr_timeout_set, 1),
4467 	FUSE_LIB_OPT("negative_timeout=%lf",  negative_timeout, 0),
4468 	FUSE_LIB_OPT("noforget",              remember, -1),
4469 	FUSE_LIB_OPT("remember=%u",           remember, 0),
4470 	FUSE_LIB_OPT("nopath",                nopath, 1),
4471 	FUSE_LIB_OPT("intr",		      intr, 1),
4472 	FUSE_LIB_OPT("intr_signal=%d",	      intr_signal, 0),
4473 	FUSE_LIB_OPT("modules=%s",	      modules, 0),
4474 	FUSE_OPT_END
4475 };
4476 
fuse_lib_help(void)4477 static void fuse_lib_help(void)
4478 {
4479 	fprintf(stderr,
4480 "    -o hard_remove         immediate removal (don't hide files)\n"
4481 "    -o use_ino             let filesystem set inode numbers\n"
4482 "    -o readdir_ino         try to fill in d_ino in readdir\n"
4483 "    -o direct_io           use direct I/O\n"
4484 "    -o kernel_cache        cache files in kernel\n"
4485 "    -o [no]auto_cache      enable caching based on modification times (off)\n"
4486 "    -o umask=M             set file permissions (octal)\n"
4487 "    -o uid=N               set file owner\n"
4488 "    -o gid=N               set file group\n"
4489 "    -o entry_timeout=T     cache timeout for names (1.0s)\n"
4490 "    -o negative_timeout=T  cache timeout for deleted names (0.0s)\n"
4491 "    -o attr_timeout=T      cache timeout for attributes (1.0s)\n"
4492 "    -o ac_attr_timeout=T   auto cache timeout for attributes (attr_timeout)\n"
4493 "    -o noforget            never forget cached inodes\n"
4494 "    -o remember=T          remember cached inodes for T seconds (0s)\n"
4495 "    -o nopath              don't supply path if not necessary\n"
4496 "    -o intr                allow requests to be interrupted\n"
4497 "    -o intr_signal=NUM     signal to send on interrupt (%i)\n"
4498 "    -o modules=M1[:M2...]  names of modules to push onto filesystem stack\n"
4499 "\n", FUSE_DEFAULT_INTR_SIGNAL);
4500 }
4501 
fuse_lib_help_modules(void)4502 static void fuse_lib_help_modules(void)
4503 {
4504 	struct fuse_module *m;
4505 	fprintf(stderr, "\nModule options:\n");
4506 	pthread_mutex_lock(&fuse_context_lock);
4507 	for (m = fuse_modules; m; m = m->next) {
4508 		struct fuse_fs *fs = NULL;
4509 		struct fuse_fs *newfs;
4510 		struct fuse_args args = FUSE_ARGS_INIT(0, NULL);
4511 		if (fuse_opt_add_arg(&args, "") != -1 &&
4512 		    fuse_opt_add_arg(&args, "-h") != -1) {
4513 			fprintf(stderr, "\n[%s]\n", m->name);
4514 			newfs = m->factory(&args, &fs);
4515 			assert(newfs == NULL);
4516 		}
4517 		fuse_opt_free_args(&args);
4518 	}
4519 	pthread_mutex_unlock(&fuse_context_lock);
4520 }
4521 
fuse_lib_opt_proc(void * data,const char * arg,int key,struct fuse_args * outargs)4522 static int fuse_lib_opt_proc(void *data, const char *arg, int key,
4523 			     struct fuse_args *outargs)
4524 {
4525 	(void) arg; (void) outargs;
4526 
4527 	if (key == KEY_HELP) {
4528 		struct fuse_config *conf = (struct fuse_config *) data;
4529 		fuse_lib_help();
4530 		conf->help = 1;
4531 	}
4532 
4533 	return 1;
4534 }
4535 
fuse_is_lib_option(const char * opt)4536 int fuse_is_lib_option(const char *opt)
4537 {
4538 	return fuse_lowlevel_is_lib_option(opt) ||
4539 		fuse_opt_match(fuse_lib_opts, opt);
4540 }
4541 
fuse_init_intr_signal(int signum,int * installed)4542 static int fuse_init_intr_signal(int signum, int *installed)
4543 {
4544 	struct sigaction old_sa;
4545 
4546 	if (sigaction(signum, NULL, &old_sa) == -1) {
4547 		perror("fuse: cannot get old signal handler");
4548 		return -1;
4549 	}
4550 
4551 	if (old_sa.sa_handler == SIG_DFL) {
4552 		struct sigaction sa;
4553 
4554 		memset(&sa, 0, sizeof(struct sigaction));
4555 		sa.sa_handler = fuse_intr_sighandler;
4556 		sigemptyset(&sa.sa_mask);
4557 
4558 		if (sigaction(signum, &sa, NULL) == -1) {
4559 			perror("fuse: cannot set interrupt signal handler");
4560 			return -1;
4561 		}
4562 		*installed = 1;
4563 	}
4564 	return 0;
4565 }
4566 
fuse_restore_intr_signal(int signum)4567 static void fuse_restore_intr_signal(int signum)
4568 {
4569 	struct sigaction sa;
4570 
4571 	memset(&sa, 0, sizeof(struct sigaction));
4572 	sa.sa_handler = SIG_DFL;
4573 	sigaction(signum, &sa, NULL);
4574 }
4575 
4576 
fuse_push_module(struct fuse * f,const char * module,struct fuse_args * args)4577 static int fuse_push_module(struct fuse *f, const char *module,
4578 			    struct fuse_args *args)
4579 {
4580 	struct fuse_fs *fs[2] = { f->fs, NULL };
4581 	struct fuse_fs *newfs;
4582 	struct fuse_module *m = fuse_get_module(module);
4583 
4584 	if (!m)
4585 		return -1;
4586 
4587 	newfs = m->factory(args, fs);
4588 	if (!newfs) {
4589 		fuse_put_module(m);
4590 		return -1;
4591 	}
4592 	newfs->m = m;
4593 	f->fs = newfs;
4594 	f->nullpath_ok = newfs->op.flag_nullpath_ok && f->nullpath_ok;
4595 	f->conf.nopath = newfs->op.flag_nopath && f->conf.nopath;
4596 	f->utime_omit_ok = newfs->op.flag_utime_omit_ok && f->utime_omit_ok;
4597 	return 0;
4598 }
4599 
fuse_fs_new(const struct fuse_operations * op,size_t op_size,void * user_data)4600 struct fuse_fs *fuse_fs_new(const struct fuse_operations *op, size_t op_size,
4601 			    void *user_data)
4602 {
4603 	struct fuse_fs *fs;
4604 
4605 	if (sizeof(struct fuse_operations) < op_size) {
4606 		fprintf(stderr, "fuse: warning: library too old, some operations may not not work\n");
4607 		op_size = sizeof(struct fuse_operations);
4608 	}
4609 
4610 	fs = (struct fuse_fs *) calloc(1, sizeof(struct fuse_fs));
4611 	if (!fs) {
4612 		fprintf(stderr, "fuse: failed to allocate fuse_fs object\n");
4613 		return NULL;
4614 	}
4615 
4616 	fs->user_data = user_data;
4617 	if (op)
4618 		memcpy(&fs->op, op, op_size);
4619 	return fs;
4620 }
4621 
node_table_init(struct node_table * t)4622 static int node_table_init(struct node_table *t)
4623 {
4624 	t->size = NODE_TABLE_MIN_SIZE;
4625 	t->array = (struct node **) calloc(1, sizeof(struct node *) * t->size);
4626 	if (t->array == NULL) {
4627 		fprintf(stderr, "fuse: memory allocation failed\n");
4628 		return -1;
4629 	}
4630 	t->use = 0;
4631 	t->split = 0;
4632 
4633 	return 0;
4634 }
4635 
fuse_prune_nodes(void * fuse)4636 static void *fuse_prune_nodes(void *fuse)
4637 {
4638 	struct fuse *f = fuse;
4639 	int sleep_time;
4640 
4641 	while(1) {
4642 		sleep_time = fuse_clean_cache(f);
4643 		sleep(sleep_time);
4644 	}
4645 	return NULL;
4646 }
4647 
fuse_start_cleanup_thread(struct fuse * f)4648 int fuse_start_cleanup_thread(struct fuse *f)
4649 {
4650 	if (lru_enabled(f))
4651 		return fuse_start_thread(&f->prune_thread, fuse_prune_nodes, f);
4652 
4653 	return 0;
4654 }
4655 
fuse_stop_cleanup_thread(struct fuse * f)4656 void fuse_stop_cleanup_thread(struct fuse *f)
4657 {
4658 	if (lru_enabled(f)) {
4659 		pthread_mutex_lock(&f->lock);
4660 		pthread_cancel(f->prune_thread);
4661 		pthread_mutex_unlock(&f->lock);
4662 		pthread_join(f->prune_thread, NULL);
4663 	}
4664 }
4665 
fuse_new_common(struct fuse_chan * ch,struct fuse_args * args,const struct fuse_operations * op,size_t op_size,void * user_data,int compat)4666 struct fuse *fuse_new_common(struct fuse_chan *ch, struct fuse_args *args,
4667 			     const struct fuse_operations *op,
4668 			     size_t op_size, void *user_data, int compat)
4669 {
4670 	struct fuse *f;
4671 	struct node *root;
4672 	struct fuse_fs *fs;
4673 	struct fuse_lowlevel_ops llop = fuse_path_ops;
4674 
4675 	if (fuse_create_context_key() == -1)
4676 		goto out;
4677 
4678 	f = (struct fuse *) calloc(1, sizeof(struct fuse));
4679 	if (f == NULL) {
4680 		fprintf(stderr, "fuse: failed to allocate fuse object\n");
4681 		goto out_delete_context_key;
4682 	}
4683 
4684 	fs = fuse_fs_new(op, op_size, user_data);
4685 	if (!fs)
4686 		goto out_free;
4687 
4688 	fs->compat = compat;
4689 	f->fs = fs;
4690 	f->nullpath_ok = fs->op.flag_nullpath_ok;
4691 	f->conf.nopath = fs->op.flag_nopath;
4692 	f->utime_omit_ok = fs->op.flag_utime_omit_ok;
4693 
4694 	/* Oh f**k, this is ugly! */
4695 	if (!fs->op.lock) {
4696 		llop.getlk = NULL;
4697 		llop.setlk = NULL;
4698 	}
4699 
4700 	f->conf.entry_timeout = 1.0;
4701 	f->conf.attr_timeout = 1.0;
4702 	f->conf.negative_timeout = 0.0;
4703 	f->conf.intr_signal = FUSE_DEFAULT_INTR_SIGNAL;
4704 
4705 	f->pagesize = getpagesize();
4706 	init_list_head(&f->partial_slabs);
4707 	init_list_head(&f->full_slabs);
4708 	init_list_head(&f->lru_table);
4709 
4710 	if (fuse_opt_parse(args, &f->conf, fuse_lib_opts,
4711 			   fuse_lib_opt_proc) == -1)
4712 		goto out_free_fs;
4713 
4714 	if (f->conf.modules) {
4715 		char *module;
4716 		char *next;
4717 
4718 		for (module = f->conf.modules; module; module = next) {
4719 			char *p;
4720 			for (p = module; *p && *p != ':'; p++);
4721 			next = *p ? p + 1 : NULL;
4722 			*p = '\0';
4723 			if (module[0] &&
4724 			    fuse_push_module(f, module, args) == -1)
4725 				goto out_free_fs;
4726 		}
4727 	}
4728 
4729 	if (!f->conf.ac_attr_timeout_set)
4730 		f->conf.ac_attr_timeout = f->conf.attr_timeout;
4731 
4732 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
4733 	/*
4734 	 * In FreeBSD, we always use these settings as inode numbers
4735 	 * are needed to make getcwd(3) work.
4736 	 */
4737 	f->conf.readdir_ino = 1;
4738 #endif
4739 
4740 	if (compat && compat <= 25) {
4741 		if (fuse_sync_compat_args(args) == -1)
4742 			goto out_free_fs;
4743 	}
4744 
4745 	f->se = fuse_lowlevel_new_common(args, &llop, sizeof(llop), f);
4746 	if (f->se == NULL) {
4747 		if (f->conf.help)
4748 			fuse_lib_help_modules();
4749 		goto out_free_fs;
4750 	}
4751 
4752 	fuse_session_add_chan(f->se, ch);
4753 
4754 	if (f->conf.debug) {
4755 		fprintf(stderr, "nullpath_ok: %i\n", f->nullpath_ok);
4756 		fprintf(stderr, "nopath: %i\n", f->conf.nopath);
4757 		fprintf(stderr, "utime_omit_ok: %i\n", f->utime_omit_ok);
4758 	}
4759 
4760 	/* Trace topmost layer by default */
4761 	f->fs->debug = f->conf.debug;
4762 	f->ctr = 0;
4763 	f->generation = 0;
4764 	if (node_table_init(&f->name_table) == -1)
4765 		goto out_free_session;
4766 
4767 	if (node_table_init(&f->id_table) == -1)
4768 		goto out_free_name_table;
4769 
4770 	fuse_mutex_init(&f->lock);
4771 
4772 	root = alloc_node(f);
4773 	if (root == NULL) {
4774 		fprintf(stderr, "fuse: memory allocation failed\n");
4775 		goto out_free_id_table;
4776 	}
4777 	if (lru_enabled(f)) {
4778 		struct node_lru *lnode = node_lru(root);
4779 		init_list_head(&lnode->lru);
4780 	}
4781 
4782 	strcpy(root->inline_name, "/");
4783 	root->name = root->inline_name;
4784 
4785 	if (f->conf.intr &&
4786 	    fuse_init_intr_signal(f->conf.intr_signal,
4787 				  &f->intr_installed) == -1)
4788 		goto out_free_root;
4789 
4790 	root->parent = NULL;
4791 	root->nodeid = FUSE_ROOT_ID;
4792 	inc_nlookup(root);
4793 	hash_id(f, root);
4794 
4795 	return f;
4796 
4797 out_free_root:
4798 	free(root);
4799 out_free_id_table:
4800 	free(f->id_table.array);
4801 out_free_name_table:
4802 	free(f->name_table.array);
4803 out_free_session:
4804 	fuse_session_destroy(f->se);
4805 out_free_fs:
4806 	/* Horrible compatibility hack to stop the destructor from being
4807 	   called on the filesystem without init being called first */
4808 	fs->op.destroy = NULL;
4809 	fuse_fs_destroy(f->fs);
4810 	free(f->conf.modules);
4811 out_free:
4812 	free(f);
4813 out_delete_context_key:
4814 	fuse_delete_context_key();
4815 out:
4816 	return NULL;
4817 }
4818 
fuse_new(struct fuse_chan * ch,struct fuse_args * args,const struct fuse_operations * op,size_t op_size,void * user_data)4819 struct fuse *fuse_new(struct fuse_chan *ch, struct fuse_args *args,
4820 		      const struct fuse_operations *op, size_t op_size,
4821 		      void *user_data)
4822 {
4823 	return fuse_new_common(ch, args, op, op_size, user_data, 0);
4824 }
4825 
fuse_destroy(struct fuse * f)4826 void fuse_destroy(struct fuse *f)
4827 {
4828 	size_t i;
4829 
4830 	if (f->conf.intr && f->intr_installed)
4831 		fuse_restore_intr_signal(f->conf.intr_signal);
4832 
4833 	if (f->fs) {
4834 		struct fuse_context_i *c = fuse_get_context_internal();
4835 
4836 		memset(c, 0, sizeof(*c));
4837 		c->ctx.fuse = f;
4838 
4839 		for (i = 0; i < f->id_table.size; i++) {
4840 			struct node *node;
4841 
4842 			for (node = f->id_table.array[i]; node != NULL;
4843 			     node = node->id_next) {
4844 				if (node->is_hidden) {
4845 					char *path;
4846 					if (try_get_path(f, node->nodeid, NULL, &path, NULL, false) == 0) {
4847 						fuse_fs_unlink(f->fs, path);
4848 						free(path);
4849 					}
4850 				}
4851 			}
4852 		}
4853 	}
4854 	for (i = 0; i < f->id_table.size; i++) {
4855 		struct node *node;
4856 		struct node *next;
4857 
4858 		for (node = f->id_table.array[i]; node != NULL; node = next) {
4859 			next = node->id_next;
4860 			free_node(f, node);
4861 			f->id_table.use--;
4862 		}
4863 	}
4864 	assert(list_empty(&f->partial_slabs));
4865 	assert(list_empty(&f->full_slabs));
4866 
4867 	free(f->id_table.array);
4868 	free(f->name_table.array);
4869 	pthread_mutex_destroy(&f->lock);
4870 	fuse_session_destroy(f->se);
4871 	free(f->conf.modules);
4872 	free(f);
4873 	fuse_delete_context_key();
4874 }
4875 
fuse_new_common_compat25(int fd,struct fuse_args * args,const struct fuse_operations * op,size_t op_size,int compat)4876 static struct fuse *fuse_new_common_compat25(int fd, struct fuse_args *args,
4877 					     const struct fuse_operations *op,
4878 					     size_t op_size, int compat)
4879 {
4880 	struct fuse *f = NULL;
4881 	struct fuse_chan *ch = fuse_kern_chan_new(fd);
4882 
4883 	if (ch)
4884 		f = fuse_new_common(ch, args, op, op_size, NULL, compat);
4885 
4886 	return f;
4887 }
4888 
4889 /* called with fuse_context_lock held or during initialization (before
4890    main() has been called) */
fuse_register_module(struct fuse_module * mod)4891 void fuse_register_module(struct fuse_module *mod)
4892 {
4893 	mod->ctr = 0;
4894 	mod->so = fuse_current_so;
4895 	if (mod->so)
4896 		mod->so->ctr++;
4897 	mod->next = fuse_modules;
4898 	fuse_modules = mod;
4899 }
4900 
4901 #if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__DragonFly__)
4902 
fuse_new_common_compat(int fd,const char * opts,const struct fuse_operations * op,size_t op_size,int compat)4903 static struct fuse *fuse_new_common_compat(int fd, const char *opts,
4904 					   const struct fuse_operations *op,
4905 					   size_t op_size, int compat)
4906 {
4907 	struct fuse *f;
4908 	struct fuse_args args = FUSE_ARGS_INIT(0, NULL);
4909 
4910 	if (fuse_opt_add_arg(&args, "") == -1)
4911 		return NULL;
4912 	if (opts &&
4913 	    (fuse_opt_add_arg(&args, "-o") == -1 ||
4914 	     fuse_opt_add_arg(&args, opts) == -1)) {
4915 		fuse_opt_free_args(&args);
4916 		return NULL;
4917 	}
4918 	f = fuse_new_common_compat25(fd, &args, op, op_size, compat);
4919 	fuse_opt_free_args(&args);
4920 
4921 	return f;
4922 }
4923 
fuse_new_compat22(int fd,const char * opts,const struct fuse_operations_compat22 * op,size_t op_size)4924 struct fuse *fuse_new_compat22(int fd, const char *opts,
4925 			       const struct fuse_operations_compat22 *op,
4926 			       size_t op_size)
4927 {
4928 	return fuse_new_common_compat(fd, opts, (struct fuse_operations *) op,
4929 				      op_size, 22);
4930 }
4931 
fuse_new_compat2(int fd,const char * opts,const struct fuse_operations_compat2 * op)4932 struct fuse *fuse_new_compat2(int fd, const char *opts,
4933 			      const struct fuse_operations_compat2 *op)
4934 {
4935 	return fuse_new_common_compat(fd, opts, (struct fuse_operations *) op,
4936 				      sizeof(struct fuse_operations_compat2),
4937 				      21);
4938 }
4939 
fuse_new_compat1(int fd,int flags,const struct fuse_operations_compat1 * op)4940 struct fuse *fuse_new_compat1(int fd, int flags,
4941 			      const struct fuse_operations_compat1 *op)
4942 {
4943 	const char *opts = NULL;
4944 	if (flags & FUSE_DEBUG_COMPAT1)
4945 		opts = "debug";
4946 	return fuse_new_common_compat(fd, opts, (struct fuse_operations *) op,
4947 				      sizeof(struct fuse_operations_compat1),
4948 				      11);
4949 }
4950 
4951 FUSE_SYMVER(".symver fuse_exited,__fuse_exited@");
4952 FUSE_SYMVER(".symver fuse_process_cmd,__fuse_process_cmd@");
4953 FUSE_SYMVER(".symver fuse_read_cmd,__fuse_read_cmd@");
4954 FUSE_SYMVER(".symver fuse_set_getcontext_func,__fuse_set_getcontext_func@");
4955 FUSE_SYMVER(".symver fuse_new_compat2,fuse_new@");
4956 FUSE_SYMVER(".symver fuse_new_compat22,fuse_new@FUSE_2.2");
4957 
4958 #endif /* __FreeBSD__ || __NetBSD__  */
4959 
fuse_new_compat25(int fd,struct fuse_args * args,const struct fuse_operations_compat25 * op,size_t op_size)4960 struct fuse *fuse_new_compat25(int fd, struct fuse_args *args,
4961 			       const struct fuse_operations_compat25 *op,
4962 			       size_t op_size)
4963 {
4964 	return fuse_new_common_compat25(fd, args, (struct fuse_operations *) op,
4965 					op_size, 25);
4966 }
4967 
4968 FUSE_SYMVER(".symver fuse_new_compat25,fuse_new@FUSE_2.5");
4969