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