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