1987da915Sopenharmony_ci/* 2987da915Sopenharmony_ci FUSE: Filesystem in Userspace 3987da915Sopenharmony_ci Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu> 4987da915Sopenharmony_ci 5987da915Sopenharmony_ci This program can be distributed under the terms of the GNU LGPLv2. 6987da915Sopenharmony_ci See the file COPYING.LIB 7987da915Sopenharmony_ci*/ 8987da915Sopenharmony_ci 9987da915Sopenharmony_ci#ifdef __SOLARIS__ 10987da915Sopenharmony_ci/* For pthread_rwlock_t */ 11987da915Sopenharmony_ci#define _GNU_SOURCE 12987da915Sopenharmony_ci#endif /* __SOLARIS__ */ 13987da915Sopenharmony_ci 14987da915Sopenharmony_ci#include "config.h" 15987da915Sopenharmony_ci#include "fuse_i.h" 16987da915Sopenharmony_ci#include "fuse_lowlevel.h" 17987da915Sopenharmony_ci#include "fuse_opt.h" 18987da915Sopenharmony_ci#include "fuse_misc.h" 19987da915Sopenharmony_ci 20987da915Sopenharmony_ci#include <stdio.h> 21987da915Sopenharmony_ci#include <string.h> 22987da915Sopenharmony_ci#include <stdlib.h> 23987da915Sopenharmony_ci#include <stddef.h> 24987da915Sopenharmony_ci#include <unistd.h> 25987da915Sopenharmony_ci#include <time.h> 26987da915Sopenharmony_ci#include <fcntl.h> 27987da915Sopenharmony_ci#include <limits.h> 28987da915Sopenharmony_ci#include <errno.h> 29987da915Sopenharmony_ci#include <signal.h> 30987da915Sopenharmony_ci#include <dlfcn.h> 31987da915Sopenharmony_ci#include <assert.h> 32987da915Sopenharmony_ci#include <sys/param.h> 33987da915Sopenharmony_ci#include <sys/uio.h> 34987da915Sopenharmony_ci#include <sys/time.h> 35987da915Sopenharmony_ci 36987da915Sopenharmony_ci#ifdef __SOLARIS__ 37987da915Sopenharmony_ci#define FUSE_MAX_PATH 4096 38987da915Sopenharmony_ci#endif /* __SOLARIS__ */ 39987da915Sopenharmony_ci 40987da915Sopenharmony_ci#define FUSE_DEFAULT_INTR_SIGNAL SIGUSR1 41987da915Sopenharmony_ci 42987da915Sopenharmony_ci#define FUSE_UNKNOWN_INO 0xffffffff 43987da915Sopenharmony_ci#define OFFSET_MAX 0x7fffffffffffffffLL 44987da915Sopenharmony_ci 45987da915Sopenharmony_cistruct fuse_config { 46987da915Sopenharmony_ci unsigned int uid; 47987da915Sopenharmony_ci unsigned int gid; 48987da915Sopenharmony_ci unsigned int umask; 49987da915Sopenharmony_ci double entry_timeout; 50987da915Sopenharmony_ci double negative_timeout; 51987da915Sopenharmony_ci double attr_timeout; 52987da915Sopenharmony_ci double ac_attr_timeout; 53987da915Sopenharmony_ci int ac_attr_timeout_set; 54987da915Sopenharmony_ci int debug; 55987da915Sopenharmony_ci int hard_remove; 56987da915Sopenharmony_ci int use_ino; 57987da915Sopenharmony_ci int readdir_ino; 58987da915Sopenharmony_ci int set_mode; 59987da915Sopenharmony_ci int set_uid; 60987da915Sopenharmony_ci int set_gid; 61987da915Sopenharmony_ci int direct_io; 62987da915Sopenharmony_ci int kernel_cache; 63987da915Sopenharmony_ci int intr; 64987da915Sopenharmony_ci int intr_signal; 65987da915Sopenharmony_ci int help; 66987da915Sopenharmony_ci#ifdef __SOLARIS__ 67987da915Sopenharmony_ci int auto_cache; 68987da915Sopenharmony_ci char *modules; 69987da915Sopenharmony_ci#endif /* __SOLARIS__ */ 70987da915Sopenharmony_ci}; 71987da915Sopenharmony_ci 72987da915Sopenharmony_cistruct fuse_fs { 73987da915Sopenharmony_ci struct fuse_operations op; 74987da915Sopenharmony_ci void *user_data; 75987da915Sopenharmony_ci#ifdef __SOLARIS__ 76987da915Sopenharmony_ci struct fuse_module *m; 77987da915Sopenharmony_ci#endif /* __SOLARIS__ */ 78987da915Sopenharmony_ci}; 79987da915Sopenharmony_ci 80987da915Sopenharmony_ci#ifdef __SOLARIS__ 81987da915Sopenharmony_cistruct fusemod_so { 82987da915Sopenharmony_ci void *handle; 83987da915Sopenharmony_ci int ctr; 84987da915Sopenharmony_ci}; 85987da915Sopenharmony_ci#endif /* __SOLARIS__ */ 86987da915Sopenharmony_ci 87987da915Sopenharmony_cistruct fuse { 88987da915Sopenharmony_ci struct fuse_session *se; 89987da915Sopenharmony_ci struct node **name_table; 90987da915Sopenharmony_ci size_t name_table_size; 91987da915Sopenharmony_ci struct node **id_table; 92987da915Sopenharmony_ci size_t id_table_size; 93987da915Sopenharmony_ci fuse_ino_t ctr; 94987da915Sopenharmony_ci unsigned int generation; 95987da915Sopenharmony_ci unsigned int hidectr; 96987da915Sopenharmony_ci pthread_mutex_t lock; 97987da915Sopenharmony_ci pthread_rwlock_t tree_lock; 98987da915Sopenharmony_ci struct fuse_config conf; 99987da915Sopenharmony_ci int intr_installed; 100987da915Sopenharmony_ci struct fuse_fs *fs; 101987da915Sopenharmony_ci}; 102987da915Sopenharmony_ci 103987da915Sopenharmony_cistruct lock { 104987da915Sopenharmony_ci int type; 105987da915Sopenharmony_ci off_t start; 106987da915Sopenharmony_ci off_t end; 107987da915Sopenharmony_ci pid_t pid; 108987da915Sopenharmony_ci uint64_t owner; 109987da915Sopenharmony_ci struct lock *next; 110987da915Sopenharmony_ci}; 111987da915Sopenharmony_ci 112987da915Sopenharmony_cistruct node { 113987da915Sopenharmony_ci struct node *name_next; 114987da915Sopenharmony_ci struct node *id_next; 115987da915Sopenharmony_ci fuse_ino_t nodeid; 116987da915Sopenharmony_ci unsigned int generation; 117987da915Sopenharmony_ci int refctr; 118987da915Sopenharmony_ci struct node *parent; 119987da915Sopenharmony_ci char *name; 120987da915Sopenharmony_ci uint64_t nlookup; 121987da915Sopenharmony_ci int open_count; 122987da915Sopenharmony_ci int is_hidden; 123987da915Sopenharmony_ci#ifdef __SOLARIS__ 124987da915Sopenharmony_ci struct timespec stat_updated; 125987da915Sopenharmony_ci struct timespec mtime; 126987da915Sopenharmony_ci off_t size; 127987da915Sopenharmony_ci int cache_valid; 128987da915Sopenharmony_ci#endif /* __SOLARIS__ */ 129987da915Sopenharmony_ci struct lock *locks; 130987da915Sopenharmony_ci}; 131987da915Sopenharmony_ci 132987da915Sopenharmony_cistruct fuse_dh { 133987da915Sopenharmony_ci pthread_mutex_t lock; 134987da915Sopenharmony_ci struct fuse *fuse; 135987da915Sopenharmony_ci fuse_req_t req; 136987da915Sopenharmony_ci char *contents; 137987da915Sopenharmony_ci unsigned len; 138987da915Sopenharmony_ci unsigned size; 139987da915Sopenharmony_ci unsigned needlen; 140987da915Sopenharmony_ci int filled; 141987da915Sopenharmony_ci uint64_t fh; 142987da915Sopenharmony_ci int error; 143987da915Sopenharmony_ci fuse_ino_t nodeid; 144987da915Sopenharmony_ci}; 145987da915Sopenharmony_ci 146987da915Sopenharmony_cistruct fuse_context_i { 147987da915Sopenharmony_ci struct fuse_context ctx; 148987da915Sopenharmony_ci fuse_req_t req; 149987da915Sopenharmony_ci}; 150987da915Sopenharmony_ci 151987da915Sopenharmony_cistatic pthread_key_t fuse_context_key; 152987da915Sopenharmony_cistatic pthread_mutex_t fuse_context_lock = PTHREAD_MUTEX_INITIALIZER; 153987da915Sopenharmony_cistatic int fuse_context_ref; 154987da915Sopenharmony_ci 155987da915Sopenharmony_ci#ifdef __SOLARIS__ 156987da915Sopenharmony_ci 157987da915Sopenharmony_cistatic struct fusemod_so *fuse_current_so; 158987da915Sopenharmony_cistatic struct fuse_module *fuse_modules; 159987da915Sopenharmony_ci 160987da915Sopenharmony_cistatic int fuse_load_so_name(const char *soname) 161987da915Sopenharmony_ci{ 162987da915Sopenharmony_ci struct fusemod_so *so; 163987da915Sopenharmony_ci 164987da915Sopenharmony_ci so = calloc(1, sizeof(struct fusemod_so)); 165987da915Sopenharmony_ci if (!so) { 166987da915Sopenharmony_ci fprintf(stderr, "fuse: memory allocation failed\n"); 167987da915Sopenharmony_ci return -1; 168987da915Sopenharmony_ci } 169987da915Sopenharmony_ci 170987da915Sopenharmony_ci fuse_current_so = so; 171987da915Sopenharmony_ci so->handle = dlopen(soname, RTLD_NOW); 172987da915Sopenharmony_ci fuse_current_so = NULL; 173987da915Sopenharmony_ci if (!so->handle) { 174987da915Sopenharmony_ci fprintf(stderr, "fuse: %s\n", dlerror()); 175987da915Sopenharmony_ci goto err; 176987da915Sopenharmony_ci } 177987da915Sopenharmony_ci if (!so->ctr) { 178987da915Sopenharmony_ci fprintf(stderr, "fuse: %s did not register any modules", soname); 179987da915Sopenharmony_ci goto err; 180987da915Sopenharmony_ci } 181987da915Sopenharmony_ci return 0; 182987da915Sopenharmony_ci 183987da915Sopenharmony_ci err: 184987da915Sopenharmony_ci if (so->handle) 185987da915Sopenharmony_ci dlclose(so->handle); 186987da915Sopenharmony_ci free(so); 187987da915Sopenharmony_ci return -1; 188987da915Sopenharmony_ci} 189987da915Sopenharmony_ci 190987da915Sopenharmony_cistatic int fuse_load_so_module(const char *module) 191987da915Sopenharmony_ci{ 192987da915Sopenharmony_ci int res; 193987da915Sopenharmony_ci char *soname = malloc(strlen(module) + 64); 194987da915Sopenharmony_ci if (!soname) { 195987da915Sopenharmony_ci fprintf(stderr, "fuse: memory allocation failed\n"); 196987da915Sopenharmony_ci return -1; 197987da915Sopenharmony_ci } 198987da915Sopenharmony_ci sprintf(soname, "libfusemod_%s.so", module); 199987da915Sopenharmony_ci res = fuse_load_so_name(soname); 200987da915Sopenharmony_ci free(soname); 201987da915Sopenharmony_ci return res; 202987da915Sopenharmony_ci} 203987da915Sopenharmony_ci 204987da915Sopenharmony_cistatic struct fuse_module *fuse_find_module(const char *module) 205987da915Sopenharmony_ci{ 206987da915Sopenharmony_ci struct fuse_module *m; 207987da915Sopenharmony_ci for (m = fuse_modules; m; m = m->next) { 208987da915Sopenharmony_ci if (strcmp(module, m->name) == 0) { 209987da915Sopenharmony_ci m->ctr++; 210987da915Sopenharmony_ci break; 211987da915Sopenharmony_ci } 212987da915Sopenharmony_ci } 213987da915Sopenharmony_ci return m; 214987da915Sopenharmony_ci} 215987da915Sopenharmony_ci 216987da915Sopenharmony_cistatic struct fuse_module *fuse_get_module(const char *module) 217987da915Sopenharmony_ci{ 218987da915Sopenharmony_ci struct fuse_module *m; 219987da915Sopenharmony_ci 220987da915Sopenharmony_ci pthread_mutex_lock(&fuse_context_lock); 221987da915Sopenharmony_ci m = fuse_find_module(module); 222987da915Sopenharmony_ci if (!m) { 223987da915Sopenharmony_ci int err = fuse_load_so_module(module); 224987da915Sopenharmony_ci if (!err) 225987da915Sopenharmony_ci m = fuse_find_module(module); 226987da915Sopenharmony_ci } 227987da915Sopenharmony_ci pthread_mutex_unlock(&fuse_context_lock); 228987da915Sopenharmony_ci return m; 229987da915Sopenharmony_ci} 230987da915Sopenharmony_ci 231987da915Sopenharmony_cistatic void fuse_put_module(struct fuse_module *m) 232987da915Sopenharmony_ci{ 233987da915Sopenharmony_ci pthread_mutex_lock(&fuse_context_lock); 234987da915Sopenharmony_ci assert(m->ctr > 0); 235987da915Sopenharmony_ci m->ctr--; 236987da915Sopenharmony_ci if (!m->ctr && m->so) { 237987da915Sopenharmony_ci struct fusemod_so *so = m->so; 238987da915Sopenharmony_ci assert(so->ctr > 0); 239987da915Sopenharmony_ci so->ctr--; 240987da915Sopenharmony_ci if (!so->ctr) { 241987da915Sopenharmony_ci struct fuse_module **mp; 242987da915Sopenharmony_ci for (mp = &fuse_modules; *mp;) { 243987da915Sopenharmony_ci if ((*mp)->so == so) 244987da915Sopenharmony_ci *mp = (*mp)->next; 245987da915Sopenharmony_ci else 246987da915Sopenharmony_ci mp = &(*mp)->next; 247987da915Sopenharmony_ci } 248987da915Sopenharmony_ci dlclose(so->handle); 249987da915Sopenharmony_ci free(so); 250987da915Sopenharmony_ci } 251987da915Sopenharmony_ci } 252987da915Sopenharmony_ci pthread_mutex_unlock(&fuse_context_lock); 253987da915Sopenharmony_ci} 254987da915Sopenharmony_ci#endif /* __SOLARIS__ */ 255987da915Sopenharmony_ci 256987da915Sopenharmony_cistatic struct node *get_node_nocheck(struct fuse *f, fuse_ino_t nodeid) 257987da915Sopenharmony_ci{ 258987da915Sopenharmony_ci size_t hash = nodeid % f->id_table_size; 259987da915Sopenharmony_ci struct node *node; 260987da915Sopenharmony_ci 261987da915Sopenharmony_ci for (node = f->id_table[hash]; node != NULL; node = node->id_next) 262987da915Sopenharmony_ci if (node->nodeid == nodeid) 263987da915Sopenharmony_ci return node; 264987da915Sopenharmony_ci 265987da915Sopenharmony_ci return NULL; 266987da915Sopenharmony_ci} 267987da915Sopenharmony_ci 268987da915Sopenharmony_cistatic struct node *get_node(struct fuse *f, fuse_ino_t nodeid) 269987da915Sopenharmony_ci{ 270987da915Sopenharmony_ci struct node *node = get_node_nocheck(f, nodeid); 271987da915Sopenharmony_ci if (!node) { 272987da915Sopenharmony_ci fprintf(stderr, "fuse internal error: node %llu not found\n", 273987da915Sopenharmony_ci (unsigned long long) nodeid); 274987da915Sopenharmony_ci abort(); 275987da915Sopenharmony_ci } 276987da915Sopenharmony_ci return node; 277987da915Sopenharmony_ci} 278987da915Sopenharmony_ci 279987da915Sopenharmony_cistatic void free_node(struct node *node) 280987da915Sopenharmony_ci{ 281987da915Sopenharmony_ci free(node->name); 282987da915Sopenharmony_ci free(node); 283987da915Sopenharmony_ci} 284987da915Sopenharmony_ci 285987da915Sopenharmony_cistatic void unhash_id(struct fuse *f, struct node *node) 286987da915Sopenharmony_ci{ 287987da915Sopenharmony_ci size_t hash = node->nodeid % f->id_table_size; 288987da915Sopenharmony_ci struct node **nodep = &f->id_table[hash]; 289987da915Sopenharmony_ci 290987da915Sopenharmony_ci for (; *nodep != NULL; nodep = &(*nodep)->id_next) 291987da915Sopenharmony_ci if (*nodep == node) { 292987da915Sopenharmony_ci *nodep = node->id_next; 293987da915Sopenharmony_ci return; 294987da915Sopenharmony_ci } 295987da915Sopenharmony_ci} 296987da915Sopenharmony_ci 297987da915Sopenharmony_cistatic void hash_id(struct fuse *f, struct node *node) 298987da915Sopenharmony_ci{ 299987da915Sopenharmony_ci size_t hash = node->nodeid % f->id_table_size; 300987da915Sopenharmony_ci node->id_next = f->id_table[hash]; 301987da915Sopenharmony_ci f->id_table[hash] = node; 302987da915Sopenharmony_ci} 303987da915Sopenharmony_ci 304987da915Sopenharmony_cistatic unsigned int name_hash(struct fuse *f, fuse_ino_t parent, 305987da915Sopenharmony_ci const char *name) 306987da915Sopenharmony_ci{ 307987da915Sopenharmony_ci unsigned int hash = *name; 308987da915Sopenharmony_ci 309987da915Sopenharmony_ci if (hash) 310987da915Sopenharmony_ci for (name += 1; *name != '\0'; name++) 311987da915Sopenharmony_ci hash = (hash << 5) - hash + *name; 312987da915Sopenharmony_ci 313987da915Sopenharmony_ci return (hash + parent) % f->name_table_size; 314987da915Sopenharmony_ci} 315987da915Sopenharmony_ci 316987da915Sopenharmony_cistatic void unref_node(struct fuse *f, struct node *node); 317987da915Sopenharmony_ci 318987da915Sopenharmony_cistatic void unhash_name(struct fuse *f, struct node *node) 319987da915Sopenharmony_ci{ 320987da915Sopenharmony_ci if (node->name) { 321987da915Sopenharmony_ci size_t hash = name_hash(f, node->parent->nodeid, node->name); 322987da915Sopenharmony_ci struct node **nodep = &f->name_table[hash]; 323987da915Sopenharmony_ci 324987da915Sopenharmony_ci for (; *nodep != NULL; nodep = &(*nodep)->name_next) 325987da915Sopenharmony_ci if (*nodep == node) { 326987da915Sopenharmony_ci *nodep = node->name_next; 327987da915Sopenharmony_ci node->name_next = NULL; 328987da915Sopenharmony_ci unref_node(f, node->parent); 329987da915Sopenharmony_ci free(node->name); 330987da915Sopenharmony_ci node->name = NULL; 331987da915Sopenharmony_ci node->parent = NULL; 332987da915Sopenharmony_ci return; 333987da915Sopenharmony_ci } 334987da915Sopenharmony_ci fprintf(stderr, "fuse internal error: unable to unhash node: %llu\n", 335987da915Sopenharmony_ci (unsigned long long) node->nodeid); 336987da915Sopenharmony_ci abort(); 337987da915Sopenharmony_ci } 338987da915Sopenharmony_ci} 339987da915Sopenharmony_ci 340987da915Sopenharmony_cistatic int hash_name(struct fuse *f, struct node *node, fuse_ino_t parentid, 341987da915Sopenharmony_ci const char *name) 342987da915Sopenharmony_ci{ 343987da915Sopenharmony_ci size_t hash = name_hash(f, parentid, name); 344987da915Sopenharmony_ci struct node *parent = get_node(f, parentid); 345987da915Sopenharmony_ci node->name = strdup(name); 346987da915Sopenharmony_ci if (node->name == NULL) 347987da915Sopenharmony_ci return -1; 348987da915Sopenharmony_ci 349987da915Sopenharmony_ci parent->refctr ++; 350987da915Sopenharmony_ci node->parent = parent; 351987da915Sopenharmony_ci node->name_next = f->name_table[hash]; 352987da915Sopenharmony_ci f->name_table[hash] = node; 353987da915Sopenharmony_ci return 0; 354987da915Sopenharmony_ci} 355987da915Sopenharmony_ci 356987da915Sopenharmony_cistatic void delete_node(struct fuse *f, struct node *node) 357987da915Sopenharmony_ci{ 358987da915Sopenharmony_ci if (f->conf.debug) 359987da915Sopenharmony_ci fprintf(stderr, "delete: %llu\n", (unsigned long long) node->nodeid); 360987da915Sopenharmony_ci 361987da915Sopenharmony_ci assert(!node->name); 362987da915Sopenharmony_ci unhash_id(f, node); 363987da915Sopenharmony_ci free_node(node); 364987da915Sopenharmony_ci} 365987da915Sopenharmony_ci 366987da915Sopenharmony_cistatic void unref_node(struct fuse *f, struct node *node) 367987da915Sopenharmony_ci{ 368987da915Sopenharmony_ci assert(node->refctr > 0); 369987da915Sopenharmony_ci node->refctr --; 370987da915Sopenharmony_ci if (!node->refctr) 371987da915Sopenharmony_ci delete_node(f, node); 372987da915Sopenharmony_ci} 373987da915Sopenharmony_ci 374987da915Sopenharmony_cistatic fuse_ino_t next_id(struct fuse *f) 375987da915Sopenharmony_ci{ 376987da915Sopenharmony_ci do { 377987da915Sopenharmony_ci f->ctr = (f->ctr + 1) & 0xffffffff; 378987da915Sopenharmony_ci if (!f->ctr) 379987da915Sopenharmony_ci f->generation ++; 380987da915Sopenharmony_ci } while (f->ctr == 0 || f->ctr == FUSE_UNKNOWN_INO || 381987da915Sopenharmony_ci get_node_nocheck(f, f->ctr) != NULL); 382987da915Sopenharmony_ci return f->ctr; 383987da915Sopenharmony_ci} 384987da915Sopenharmony_ci 385987da915Sopenharmony_cistatic struct node *lookup_node(struct fuse *f, fuse_ino_t parent, 386987da915Sopenharmony_ci const char *name) 387987da915Sopenharmony_ci{ 388987da915Sopenharmony_ci size_t hash = name_hash(f, parent, name); 389987da915Sopenharmony_ci struct node *node; 390987da915Sopenharmony_ci 391987da915Sopenharmony_ci for (node = f->name_table[hash]; node != NULL; node = node->name_next) 392987da915Sopenharmony_ci if (node->parent->nodeid == parent && strcmp(node->name, name) == 0) 393987da915Sopenharmony_ci return node; 394987da915Sopenharmony_ci 395987da915Sopenharmony_ci return NULL; 396987da915Sopenharmony_ci} 397987da915Sopenharmony_ci 398987da915Sopenharmony_cistatic struct node *find_node(struct fuse *f, fuse_ino_t parent, 399987da915Sopenharmony_ci const char *name) 400987da915Sopenharmony_ci{ 401987da915Sopenharmony_ci struct node *node; 402987da915Sopenharmony_ci 403987da915Sopenharmony_ci pthread_mutex_lock(&f->lock); 404987da915Sopenharmony_ci node = lookup_node(f, parent, name); 405987da915Sopenharmony_ci if (node == NULL) { 406987da915Sopenharmony_ci node = (struct node *) calloc(1, sizeof(struct node)); 407987da915Sopenharmony_ci if (node == NULL) 408987da915Sopenharmony_ci goto out_err; 409987da915Sopenharmony_ci 410987da915Sopenharmony_ci node->refctr = 1; 411987da915Sopenharmony_ci node->nodeid = next_id(f); 412987da915Sopenharmony_ci node->open_count = 0; 413987da915Sopenharmony_ci node->is_hidden = 0; 414987da915Sopenharmony_ci node->generation = f->generation; 415987da915Sopenharmony_ci if (hash_name(f, node, parent, name) == -1) { 416987da915Sopenharmony_ci free(node); 417987da915Sopenharmony_ci node = NULL; 418987da915Sopenharmony_ci goto out_err; 419987da915Sopenharmony_ci } 420987da915Sopenharmony_ci hash_id(f, node); 421987da915Sopenharmony_ci } 422987da915Sopenharmony_ci node->nlookup ++; 423987da915Sopenharmony_ci out_err: 424987da915Sopenharmony_ci pthread_mutex_unlock(&f->lock); 425987da915Sopenharmony_ci return node; 426987da915Sopenharmony_ci} 427987da915Sopenharmony_ci 428987da915Sopenharmony_ci#ifndef __SOLARIS__ 429987da915Sopenharmony_cistatic char *add_name(char **buf, unsigned *bufsize, char *s, const char *name) 430987da915Sopenharmony_ci#else /* __SOLARIS__ */ 431987da915Sopenharmony_cistatic char *add_name(char *buf, char *s, const char *name) 432987da915Sopenharmony_ci#endif /* __SOLARIS__ */ 433987da915Sopenharmony_ci{ 434987da915Sopenharmony_ci size_t len = strlen(name); 435987da915Sopenharmony_ci 436987da915Sopenharmony_ci#ifndef __SOLARIS__ 437987da915Sopenharmony_ci if (s - len <= *buf) { 438987da915Sopenharmony_ci unsigned pathlen = *bufsize - (s - *buf); 439987da915Sopenharmony_ci unsigned newbufsize = *bufsize; 440987da915Sopenharmony_ci char *newbuf; 441987da915Sopenharmony_ci 442987da915Sopenharmony_ci while (newbufsize < pathlen + len + 1) { 443987da915Sopenharmony_ci if (newbufsize >= 0x80000000) 444987da915Sopenharmony_ci newbufsize = 0xffffffff; 445987da915Sopenharmony_ci else 446987da915Sopenharmony_ci newbufsize *= 2; 447987da915Sopenharmony_ci } 448987da915Sopenharmony_ci 449987da915Sopenharmony_ci newbuf = realloc(*buf, newbufsize); 450987da915Sopenharmony_ci if (newbuf == NULL) 451987da915Sopenharmony_ci return NULL; 452987da915Sopenharmony_ci 453987da915Sopenharmony_ci *buf = newbuf; 454987da915Sopenharmony_ci s = newbuf + newbufsize - pathlen; 455987da915Sopenharmony_ci memmove(s, newbuf + *bufsize - pathlen, pathlen); 456987da915Sopenharmony_ci *bufsize = newbufsize; 457987da915Sopenharmony_ci } 458987da915Sopenharmony_ci s -= len; 459987da915Sopenharmony_ci#else /* ! __SOLARIS__ */ 460987da915Sopenharmony_ci s -= len; 461987da915Sopenharmony_ci if (s <= buf) { 462987da915Sopenharmony_ci fprintf(stderr, "fuse: path too long: ...%s\n", s + len); 463987da915Sopenharmony_ci return NULL; 464987da915Sopenharmony_ci } 465987da915Sopenharmony_ci#endif /* __SOLARIS__ */ 466987da915Sopenharmony_ci memcpy(s, name, len); 467987da915Sopenharmony_ci s--; 468987da915Sopenharmony_ci *s = '/'; 469987da915Sopenharmony_ci 470987da915Sopenharmony_ci return s; 471987da915Sopenharmony_ci} 472987da915Sopenharmony_ci 473987da915Sopenharmony_cistatic char *get_path_name(struct fuse *f, fuse_ino_t nodeid, const char *name) 474987da915Sopenharmony_ci{ 475987da915Sopenharmony_ci#ifdef __SOLARIS__ 476987da915Sopenharmony_ci char buf[FUSE_MAX_PATH]; 477987da915Sopenharmony_ci char *s = buf + FUSE_MAX_PATH - 1; 478987da915Sopenharmony_ci struct node *node; 479987da915Sopenharmony_ci 480987da915Sopenharmony_ci *s = '\0'; 481987da915Sopenharmony_ci 482987da915Sopenharmony_ci if (name != NULL) { 483987da915Sopenharmony_ci s = add_name(buf, s, name); 484987da915Sopenharmony_ci if (s == NULL) 485987da915Sopenharmony_ci return NULL; 486987da915Sopenharmony_ci } 487987da915Sopenharmony_ci 488987da915Sopenharmony_ci pthread_mutex_lock(&f->lock); 489987da915Sopenharmony_ci for (node = get_node(f, nodeid); node && node->nodeid != FUSE_ROOT_ID; 490987da915Sopenharmony_ci node = node->parent) { 491987da915Sopenharmony_ci if (node->name == NULL) { 492987da915Sopenharmony_ci s = NULL; 493987da915Sopenharmony_ci break; 494987da915Sopenharmony_ci } 495987da915Sopenharmony_ci 496987da915Sopenharmony_ci s = add_name(buf, s, node->name); 497987da915Sopenharmony_ci if (s == NULL) 498987da915Sopenharmony_ci break; 499987da915Sopenharmony_ci } 500987da915Sopenharmony_ci pthread_mutex_unlock(&f->lock); 501987da915Sopenharmony_ci 502987da915Sopenharmony_ci if (node == NULL || s == NULL) 503987da915Sopenharmony_ci return NULL; 504987da915Sopenharmony_ci else if (*s == '\0') 505987da915Sopenharmony_ci return strdup("/"); 506987da915Sopenharmony_ci else 507987da915Sopenharmony_ci return strdup(s); 508987da915Sopenharmony_ci 509987da915Sopenharmony_ci#else /* __SOLARIS__ */ 510987da915Sopenharmony_ci 511987da915Sopenharmony_ci unsigned bufsize = 256; 512987da915Sopenharmony_ci char *buf; 513987da915Sopenharmony_ci char *s; 514987da915Sopenharmony_ci struct node *node; 515987da915Sopenharmony_ci 516987da915Sopenharmony_ci buf = malloc(bufsize); 517987da915Sopenharmony_ci if (buf == NULL) 518987da915Sopenharmony_ci return NULL; 519987da915Sopenharmony_ci 520987da915Sopenharmony_ci s = buf + bufsize - 1; 521987da915Sopenharmony_ci *s = '\0'; 522987da915Sopenharmony_ci 523987da915Sopenharmony_ci if (name != NULL) { 524987da915Sopenharmony_ci s = add_name(&buf, &bufsize, s, name); 525987da915Sopenharmony_ci if (s == NULL) 526987da915Sopenharmony_ci goto out_free; 527987da915Sopenharmony_ci } 528987da915Sopenharmony_ci 529987da915Sopenharmony_ci pthread_mutex_lock(&f->lock); 530987da915Sopenharmony_ci for (node = get_node(f, nodeid); node && node->nodeid != FUSE_ROOT_ID; 531987da915Sopenharmony_ci node = node->parent) { 532987da915Sopenharmony_ci if (node->name == NULL) { 533987da915Sopenharmony_ci s = NULL; 534987da915Sopenharmony_ci break; 535987da915Sopenharmony_ci } 536987da915Sopenharmony_ci 537987da915Sopenharmony_ci s = add_name(&buf, &bufsize, s, node->name); 538987da915Sopenharmony_ci if (s == NULL) 539987da915Sopenharmony_ci break; 540987da915Sopenharmony_ci } 541987da915Sopenharmony_ci pthread_mutex_unlock(&f->lock); 542987da915Sopenharmony_ci 543987da915Sopenharmony_ci if (node == NULL || s == NULL) 544987da915Sopenharmony_ci goto out_free; 545987da915Sopenharmony_ci 546987da915Sopenharmony_ci if (s[0]) 547987da915Sopenharmony_ci memmove(buf, s, bufsize - (s - buf)); 548987da915Sopenharmony_ci else 549987da915Sopenharmony_ci strcpy(buf, "/"); 550987da915Sopenharmony_ci return buf; 551987da915Sopenharmony_ci 552987da915Sopenharmony_ciout_free: 553987da915Sopenharmony_ci free(buf); 554987da915Sopenharmony_ci return NULL; 555987da915Sopenharmony_ci#endif /* __SOLARIS__ */ 556987da915Sopenharmony_ci} 557987da915Sopenharmony_ci 558987da915Sopenharmony_cistatic char *get_path(struct fuse *f, fuse_ino_t nodeid) 559987da915Sopenharmony_ci{ 560987da915Sopenharmony_ci return get_path_name(f, nodeid, NULL); 561987da915Sopenharmony_ci} 562987da915Sopenharmony_ci 563987da915Sopenharmony_cistatic void forget_node(struct fuse *f, fuse_ino_t nodeid, uint64_t nlookup) 564987da915Sopenharmony_ci{ 565987da915Sopenharmony_ci struct node *node; 566987da915Sopenharmony_ci if (nodeid == FUSE_ROOT_ID) 567987da915Sopenharmony_ci return; 568987da915Sopenharmony_ci pthread_mutex_lock(&f->lock); 569987da915Sopenharmony_ci node = get_node(f, nodeid); 570987da915Sopenharmony_ci assert(node->nlookup >= nlookup); 571987da915Sopenharmony_ci node->nlookup -= nlookup; 572987da915Sopenharmony_ci if (!node->nlookup) { 573987da915Sopenharmony_ci unhash_name(f, node); 574987da915Sopenharmony_ci unref_node(f, node); 575987da915Sopenharmony_ci } 576987da915Sopenharmony_ci pthread_mutex_unlock(&f->lock); 577987da915Sopenharmony_ci} 578987da915Sopenharmony_ci 579987da915Sopenharmony_cistatic void remove_node(struct fuse *f, fuse_ino_t dir, const char *name) 580987da915Sopenharmony_ci{ 581987da915Sopenharmony_ci struct node *node; 582987da915Sopenharmony_ci 583987da915Sopenharmony_ci pthread_mutex_lock(&f->lock); 584987da915Sopenharmony_ci node = lookup_node(f, dir, name); 585987da915Sopenharmony_ci if (node != NULL) 586987da915Sopenharmony_ci unhash_name(f, node); 587987da915Sopenharmony_ci pthread_mutex_unlock(&f->lock); 588987da915Sopenharmony_ci} 589987da915Sopenharmony_ci 590987da915Sopenharmony_cistatic int rename_node(struct fuse *f, fuse_ino_t olddir, const char *oldname, 591987da915Sopenharmony_ci fuse_ino_t newdir, const char *newname, int hide) 592987da915Sopenharmony_ci{ 593987da915Sopenharmony_ci struct node *node; 594987da915Sopenharmony_ci struct node *newnode; 595987da915Sopenharmony_ci int err = 0; 596987da915Sopenharmony_ci 597987da915Sopenharmony_ci pthread_mutex_lock(&f->lock); 598987da915Sopenharmony_ci node = lookup_node(f, olddir, oldname); 599987da915Sopenharmony_ci newnode = lookup_node(f, newdir, newname); 600987da915Sopenharmony_ci if (node == NULL) 601987da915Sopenharmony_ci goto out; 602987da915Sopenharmony_ci 603987da915Sopenharmony_ci if (newnode != NULL) { 604987da915Sopenharmony_ci if (hide) { 605987da915Sopenharmony_ci fprintf(stderr, "fuse: hidden file got created during hiding\n"); 606987da915Sopenharmony_ci err = -EBUSY; 607987da915Sopenharmony_ci goto out; 608987da915Sopenharmony_ci } 609987da915Sopenharmony_ci unhash_name(f, newnode); 610987da915Sopenharmony_ci } 611987da915Sopenharmony_ci 612987da915Sopenharmony_ci unhash_name(f, node); 613987da915Sopenharmony_ci if (hash_name(f, node, newdir, newname) == -1) { 614987da915Sopenharmony_ci err = -ENOMEM; 615987da915Sopenharmony_ci goto out; 616987da915Sopenharmony_ci } 617987da915Sopenharmony_ci 618987da915Sopenharmony_ci if (hide) 619987da915Sopenharmony_ci node->is_hidden = 1; 620987da915Sopenharmony_ci 621987da915Sopenharmony_ci out: 622987da915Sopenharmony_ci pthread_mutex_unlock(&f->lock); 623987da915Sopenharmony_ci return err; 624987da915Sopenharmony_ci} 625987da915Sopenharmony_ci 626987da915Sopenharmony_cistatic void set_stat(struct fuse *f, fuse_ino_t nodeid, struct stat *stbuf) 627987da915Sopenharmony_ci{ 628987da915Sopenharmony_ci if (!f->conf.use_ino) 629987da915Sopenharmony_ci stbuf->st_ino = nodeid; 630987da915Sopenharmony_ci if (f->conf.set_mode) 631987da915Sopenharmony_ci stbuf->st_mode = (stbuf->st_mode & S_IFMT) | (0777 & ~f->conf.umask); 632987da915Sopenharmony_ci if (f->conf.set_uid) 633987da915Sopenharmony_ci stbuf->st_uid = f->conf.uid; 634987da915Sopenharmony_ci if (f->conf.set_gid) 635987da915Sopenharmony_ci stbuf->st_gid = f->conf.gid; 636987da915Sopenharmony_ci} 637987da915Sopenharmony_ci 638987da915Sopenharmony_cistatic struct fuse *req_fuse(fuse_req_t req) 639987da915Sopenharmony_ci{ 640987da915Sopenharmony_ci return (struct fuse *) fuse_req_userdata(req); 641987da915Sopenharmony_ci} 642987da915Sopenharmony_ci 643987da915Sopenharmony_cistatic void fuse_intr_sighandler(int sig) 644987da915Sopenharmony_ci{ 645987da915Sopenharmony_ci (void) sig; 646987da915Sopenharmony_ci /* Nothing to do */ 647987da915Sopenharmony_ci} 648987da915Sopenharmony_ci 649987da915Sopenharmony_cistruct fuse_intr_data { 650987da915Sopenharmony_ci pthread_t id; 651987da915Sopenharmony_ci pthread_cond_t cond; 652987da915Sopenharmony_ci int finished; 653987da915Sopenharmony_ci}; 654987da915Sopenharmony_ci 655987da915Sopenharmony_cistatic void fuse_interrupt(fuse_req_t req, void *d_) 656987da915Sopenharmony_ci{ 657987da915Sopenharmony_ci struct fuse_intr_data *d = d_; 658987da915Sopenharmony_ci struct fuse *f = req_fuse(req); 659987da915Sopenharmony_ci 660987da915Sopenharmony_ci if (d->id == pthread_self()) 661987da915Sopenharmony_ci return; 662987da915Sopenharmony_ci 663987da915Sopenharmony_ci pthread_mutex_lock(&f->lock); 664987da915Sopenharmony_ci while (!d->finished) { 665987da915Sopenharmony_ci struct timeval now; 666987da915Sopenharmony_ci struct timespec timeout; 667987da915Sopenharmony_ci 668987da915Sopenharmony_ci pthread_kill(d->id, f->conf.intr_signal); 669987da915Sopenharmony_ci gettimeofday(&now, NULL); 670987da915Sopenharmony_ci timeout.tv_sec = now.tv_sec + 1; 671987da915Sopenharmony_ci timeout.tv_nsec = now.tv_usec * 1000; 672987da915Sopenharmony_ci pthread_cond_timedwait(&d->cond, &f->lock, &timeout); 673987da915Sopenharmony_ci } 674987da915Sopenharmony_ci pthread_mutex_unlock(&f->lock); 675987da915Sopenharmony_ci} 676987da915Sopenharmony_ci 677987da915Sopenharmony_cistatic void fuse_do_finish_interrupt(struct fuse *f, fuse_req_t req, 678987da915Sopenharmony_ci struct fuse_intr_data *d) 679987da915Sopenharmony_ci{ 680987da915Sopenharmony_ci pthread_mutex_lock(&f->lock); 681987da915Sopenharmony_ci d->finished = 1; 682987da915Sopenharmony_ci pthread_cond_broadcast(&d->cond); 683987da915Sopenharmony_ci pthread_mutex_unlock(&f->lock); 684987da915Sopenharmony_ci fuse_req_interrupt_func(req, NULL, NULL); 685987da915Sopenharmony_ci pthread_cond_destroy(&d->cond); 686987da915Sopenharmony_ci} 687987da915Sopenharmony_ci 688987da915Sopenharmony_cistatic void fuse_do_prepare_interrupt(fuse_req_t req, struct fuse_intr_data *d) 689987da915Sopenharmony_ci{ 690987da915Sopenharmony_ci d->id = pthread_self(); 691987da915Sopenharmony_ci pthread_cond_init(&d->cond, NULL); 692987da915Sopenharmony_ci d->finished = 0; 693987da915Sopenharmony_ci fuse_req_interrupt_func(req, fuse_interrupt, d); 694987da915Sopenharmony_ci} 695987da915Sopenharmony_ci 696987da915Sopenharmony_cistatic void fuse_finish_interrupt(struct fuse *f, fuse_req_t req, 697987da915Sopenharmony_ci struct fuse_intr_data *d) 698987da915Sopenharmony_ci{ 699987da915Sopenharmony_ci if (f->conf.intr) 700987da915Sopenharmony_ci fuse_do_finish_interrupt(f, req, d); 701987da915Sopenharmony_ci} 702987da915Sopenharmony_ci 703987da915Sopenharmony_cistatic void fuse_prepare_interrupt(struct fuse *f, fuse_req_t req, 704987da915Sopenharmony_ci struct fuse_intr_data *d) 705987da915Sopenharmony_ci{ 706987da915Sopenharmony_ci if (f->conf.intr) 707987da915Sopenharmony_ci fuse_do_prepare_interrupt(req, d); 708987da915Sopenharmony_ci} 709987da915Sopenharmony_ci 710987da915Sopenharmony_ciint fuse_fs_getattr(struct fuse_fs *fs, const char *path, struct stat *buf) 711987da915Sopenharmony_ci{ 712987da915Sopenharmony_ci fuse_get_context()->private_data = fs->user_data; 713987da915Sopenharmony_ci if (fs->op.getattr) 714987da915Sopenharmony_ci return fs->op.getattr(path, buf); 715987da915Sopenharmony_ci else 716987da915Sopenharmony_ci return -ENOSYS; 717987da915Sopenharmony_ci} 718987da915Sopenharmony_ci 719987da915Sopenharmony_ciint fuse_fs_fgetattr(struct fuse_fs *fs, const char *path, struct stat *buf, 720987da915Sopenharmony_ci struct fuse_file_info *fi) 721987da915Sopenharmony_ci{ 722987da915Sopenharmony_ci fuse_get_context()->private_data = fs->user_data; 723987da915Sopenharmony_ci if (fs->op.fgetattr) 724987da915Sopenharmony_ci return fs->op.fgetattr(path, buf, fi); 725987da915Sopenharmony_ci else if (fs->op.getattr) 726987da915Sopenharmony_ci return fs->op.getattr(path, buf); 727987da915Sopenharmony_ci else 728987da915Sopenharmony_ci return -ENOSYS; 729987da915Sopenharmony_ci} 730987da915Sopenharmony_ci 731987da915Sopenharmony_ciint fuse_fs_rename(struct fuse_fs *fs, const char *oldpath, 732987da915Sopenharmony_ci const char *newpath) 733987da915Sopenharmony_ci{ 734987da915Sopenharmony_ci fuse_get_context()->private_data = fs->user_data; 735987da915Sopenharmony_ci if (fs->op.rename) 736987da915Sopenharmony_ci return fs->op.rename(oldpath, newpath); 737987da915Sopenharmony_ci else 738987da915Sopenharmony_ci return -ENOSYS; 739987da915Sopenharmony_ci} 740987da915Sopenharmony_ci 741987da915Sopenharmony_ciint fuse_fs_unlink(struct fuse_fs *fs, const char *path) 742987da915Sopenharmony_ci{ 743987da915Sopenharmony_ci fuse_get_context()->private_data = fs->user_data; 744987da915Sopenharmony_ci if (fs->op.unlink) 745987da915Sopenharmony_ci return fs->op.unlink(path); 746987da915Sopenharmony_ci else 747987da915Sopenharmony_ci return -ENOSYS; 748987da915Sopenharmony_ci} 749987da915Sopenharmony_ci 750987da915Sopenharmony_ciint fuse_fs_rmdir(struct fuse_fs *fs, const char *path) 751987da915Sopenharmony_ci{ 752987da915Sopenharmony_ci fuse_get_context()->private_data = fs->user_data; 753987da915Sopenharmony_ci if (fs->op.rmdir) 754987da915Sopenharmony_ci return fs->op.rmdir(path); 755987da915Sopenharmony_ci else 756987da915Sopenharmony_ci return -ENOSYS; 757987da915Sopenharmony_ci} 758987da915Sopenharmony_ci 759987da915Sopenharmony_ciint fuse_fs_symlink(struct fuse_fs *fs, const char *linkname, const char *path) 760987da915Sopenharmony_ci{ 761987da915Sopenharmony_ci fuse_get_context()->private_data = fs->user_data; 762987da915Sopenharmony_ci if (fs->op.symlink) 763987da915Sopenharmony_ci return fs->op.symlink(linkname, path); 764987da915Sopenharmony_ci else 765987da915Sopenharmony_ci return -ENOSYS; 766987da915Sopenharmony_ci} 767987da915Sopenharmony_ci 768987da915Sopenharmony_ciint fuse_fs_link(struct fuse_fs *fs, const char *oldpath, const char *newpath) 769987da915Sopenharmony_ci{ 770987da915Sopenharmony_ci fuse_get_context()->private_data = fs->user_data; 771987da915Sopenharmony_ci if (fs->op.link) 772987da915Sopenharmony_ci return fs->op.link(oldpath, newpath); 773987da915Sopenharmony_ci else 774987da915Sopenharmony_ci return -ENOSYS; 775987da915Sopenharmony_ci} 776987da915Sopenharmony_ci 777987da915Sopenharmony_ciint fuse_fs_release(struct fuse_fs *fs, const char *path, 778987da915Sopenharmony_ci struct fuse_file_info *fi) 779987da915Sopenharmony_ci{ 780987da915Sopenharmony_ci fuse_get_context()->private_data = fs->user_data; 781987da915Sopenharmony_ci if (fs->op.release) 782987da915Sopenharmony_ci return fs->op.release(path, fi); 783987da915Sopenharmony_ci else 784987da915Sopenharmony_ci return 0; 785987da915Sopenharmony_ci} 786987da915Sopenharmony_ci 787987da915Sopenharmony_ciint fuse_fs_opendir(struct fuse_fs *fs, const char *path, 788987da915Sopenharmony_ci struct fuse_file_info *fi) 789987da915Sopenharmony_ci{ 790987da915Sopenharmony_ci fuse_get_context()->private_data = fs->user_data; 791987da915Sopenharmony_ci if (fs->op.opendir) 792987da915Sopenharmony_ci return fs->op.opendir(path, fi); 793987da915Sopenharmony_ci else 794987da915Sopenharmony_ci return 0; 795987da915Sopenharmony_ci} 796987da915Sopenharmony_ci 797987da915Sopenharmony_ciint fuse_fs_open(struct fuse_fs *fs, const char *path, 798987da915Sopenharmony_ci struct fuse_file_info *fi) 799987da915Sopenharmony_ci{ 800987da915Sopenharmony_ci fuse_get_context()->private_data = fs->user_data; 801987da915Sopenharmony_ci if (fs->op.open) 802987da915Sopenharmony_ci return fs->op.open(path, fi); 803987da915Sopenharmony_ci else 804987da915Sopenharmony_ci return 0; 805987da915Sopenharmony_ci} 806987da915Sopenharmony_ci 807987da915Sopenharmony_ciint fuse_fs_read(struct fuse_fs *fs, const char *path, char *buf, size_t size, 808987da915Sopenharmony_ci off_t off, struct fuse_file_info *fi) 809987da915Sopenharmony_ci{ 810987da915Sopenharmony_ci fuse_get_context()->private_data = fs->user_data; 811987da915Sopenharmony_ci if (fs->op.read) 812987da915Sopenharmony_ci return fs->op.read(path, buf, size, off, fi); 813987da915Sopenharmony_ci else 814987da915Sopenharmony_ci return -ENOSYS; 815987da915Sopenharmony_ci} 816987da915Sopenharmony_ci 817987da915Sopenharmony_ciint fuse_fs_write(struct fuse_fs *fs, const char *path, const char *buf, 818987da915Sopenharmony_ci size_t size, off_t off, struct fuse_file_info *fi) 819987da915Sopenharmony_ci{ 820987da915Sopenharmony_ci fuse_get_context()->private_data = fs->user_data; 821987da915Sopenharmony_ci if (fs->op.write) 822987da915Sopenharmony_ci return fs->op.write(path, buf, size, off, fi); 823987da915Sopenharmony_ci else 824987da915Sopenharmony_ci return -ENOSYS; 825987da915Sopenharmony_ci} 826987da915Sopenharmony_ci 827987da915Sopenharmony_ciint fuse_fs_fsync(struct fuse_fs *fs, const char *path, int datasync, 828987da915Sopenharmony_ci struct fuse_file_info *fi) 829987da915Sopenharmony_ci{ 830987da915Sopenharmony_ci fuse_get_context()->private_data = fs->user_data; 831987da915Sopenharmony_ci if (fs->op.fsync) 832987da915Sopenharmony_ci return fs->op.fsync(path, datasync, fi); 833987da915Sopenharmony_ci else 834987da915Sopenharmony_ci return -ENOSYS; 835987da915Sopenharmony_ci} 836987da915Sopenharmony_ci 837987da915Sopenharmony_ciint fuse_fs_fsyncdir(struct fuse_fs *fs, const char *path, int datasync, 838987da915Sopenharmony_ci struct fuse_file_info *fi) 839987da915Sopenharmony_ci{ 840987da915Sopenharmony_ci fuse_get_context()->private_data = fs->user_data; 841987da915Sopenharmony_ci if (fs->op.fsyncdir) 842987da915Sopenharmony_ci return fs->op.fsyncdir(path, datasync, fi); 843987da915Sopenharmony_ci else 844987da915Sopenharmony_ci return -ENOSYS; 845987da915Sopenharmony_ci} 846987da915Sopenharmony_ci 847987da915Sopenharmony_ciint fuse_fs_flush(struct fuse_fs *fs, const char *path, 848987da915Sopenharmony_ci struct fuse_file_info *fi) 849987da915Sopenharmony_ci{ 850987da915Sopenharmony_ci fuse_get_context()->private_data = fs->user_data; 851987da915Sopenharmony_ci if (fs->op.flush) 852987da915Sopenharmony_ci return fs->op.flush(path, fi); 853987da915Sopenharmony_ci else 854987da915Sopenharmony_ci return -ENOSYS; 855987da915Sopenharmony_ci} 856987da915Sopenharmony_ci 857987da915Sopenharmony_ciint fuse_fs_statfs(struct fuse_fs *fs, const char *path, struct statvfs *buf) 858987da915Sopenharmony_ci{ 859987da915Sopenharmony_ci fuse_get_context()->private_data = fs->user_data; 860987da915Sopenharmony_ci if (fs->op.statfs) 861987da915Sopenharmony_ci return fs->op.statfs(path, buf); 862987da915Sopenharmony_ci else { 863987da915Sopenharmony_ci buf->f_namemax = 255; 864987da915Sopenharmony_ci buf->f_bsize = 512; 865987da915Sopenharmony_ci return 0; 866987da915Sopenharmony_ci } 867987da915Sopenharmony_ci} 868987da915Sopenharmony_ci 869987da915Sopenharmony_ciint fuse_fs_releasedir(struct fuse_fs *fs, const char *path, 870987da915Sopenharmony_ci struct fuse_file_info *fi) 871987da915Sopenharmony_ci{ 872987da915Sopenharmony_ci fuse_get_context()->private_data = fs->user_data; 873987da915Sopenharmony_ci if (fs->op.releasedir) 874987da915Sopenharmony_ci return fs->op.releasedir(path, fi); 875987da915Sopenharmony_ci else 876987da915Sopenharmony_ci return 0; 877987da915Sopenharmony_ci} 878987da915Sopenharmony_ci 879987da915Sopenharmony_ciint fuse_fs_readdir(struct fuse_fs *fs, const char *path, void *buf, 880987da915Sopenharmony_ci fuse_fill_dir_t filler, off_t off, 881987da915Sopenharmony_ci struct fuse_file_info *fi) 882987da915Sopenharmony_ci{ 883987da915Sopenharmony_ci fuse_get_context()->private_data = fs->user_data; 884987da915Sopenharmony_ci if (fs->op.readdir) 885987da915Sopenharmony_ci return fs->op.readdir(path, buf, filler, off, fi); 886987da915Sopenharmony_ci else 887987da915Sopenharmony_ci return -ENOSYS; 888987da915Sopenharmony_ci} 889987da915Sopenharmony_ci 890987da915Sopenharmony_ciint fuse_fs_create(struct fuse_fs *fs, const char *path, mode_t mode, 891987da915Sopenharmony_ci struct fuse_file_info *fi) 892987da915Sopenharmony_ci{ 893987da915Sopenharmony_ci fuse_get_context()->private_data = fs->user_data; 894987da915Sopenharmony_ci if (fs->op.create) 895987da915Sopenharmony_ci return fs->op.create(path, mode, fi); 896987da915Sopenharmony_ci else 897987da915Sopenharmony_ci return -ENOSYS; 898987da915Sopenharmony_ci} 899987da915Sopenharmony_ci 900987da915Sopenharmony_ciint fuse_fs_lock(struct fuse_fs *fs, const char *path, 901987da915Sopenharmony_ci struct fuse_file_info *fi, int cmd, struct flock *lock) 902987da915Sopenharmony_ci{ 903987da915Sopenharmony_ci fuse_get_context()->private_data = fs->user_data; 904987da915Sopenharmony_ci if (fs->op.lock) 905987da915Sopenharmony_ci return fs->op.lock(path, fi, cmd, lock); 906987da915Sopenharmony_ci else 907987da915Sopenharmony_ci return -ENOSYS; 908987da915Sopenharmony_ci} 909987da915Sopenharmony_ci 910987da915Sopenharmony_ciint fuse_fs_chown(struct fuse_fs *fs, const char *path, uid_t uid, gid_t gid) 911987da915Sopenharmony_ci{ 912987da915Sopenharmony_ci fuse_get_context()->private_data = fs->user_data; 913987da915Sopenharmony_ci if (fs->op.chown) 914987da915Sopenharmony_ci return fs->op.chown(path, uid, gid); 915987da915Sopenharmony_ci else 916987da915Sopenharmony_ci return -ENOSYS; 917987da915Sopenharmony_ci} 918987da915Sopenharmony_ci 919987da915Sopenharmony_ciint fuse_fs_truncate(struct fuse_fs *fs, const char *path, off_t size) 920987da915Sopenharmony_ci{ 921987da915Sopenharmony_ci fuse_get_context()->private_data = fs->user_data; 922987da915Sopenharmony_ci if (fs->op.truncate) 923987da915Sopenharmony_ci return fs->op.truncate(path, size); 924987da915Sopenharmony_ci else 925987da915Sopenharmony_ci return -ENOSYS; 926987da915Sopenharmony_ci} 927987da915Sopenharmony_ci 928987da915Sopenharmony_ciint fuse_fs_ftruncate(struct fuse_fs *fs, const char *path, off_t size, 929987da915Sopenharmony_ci struct fuse_file_info *fi) 930987da915Sopenharmony_ci{ 931987da915Sopenharmony_ci fuse_get_context()->private_data = fs->user_data; 932987da915Sopenharmony_ci if (fs->op.ftruncate) 933987da915Sopenharmony_ci return fs->op.ftruncate(path, size, fi); 934987da915Sopenharmony_ci else if (fs->op.truncate) 935987da915Sopenharmony_ci return fs->op.truncate(path, size); 936987da915Sopenharmony_ci else 937987da915Sopenharmony_ci return -ENOSYS; 938987da915Sopenharmony_ci} 939987da915Sopenharmony_ci 940987da915Sopenharmony_ciint fuse_fs_utimens(struct fuse_fs *fs, const char *path, 941987da915Sopenharmony_ci const struct timespec tv[2]) 942987da915Sopenharmony_ci{ 943987da915Sopenharmony_ci fuse_get_context()->private_data = fs->user_data; 944987da915Sopenharmony_ci if (fs->op.utimens) 945987da915Sopenharmony_ci return fs->op.utimens(path, tv); 946987da915Sopenharmony_ci else if(fs->op.utime) { 947987da915Sopenharmony_ci struct utimbuf buf; 948987da915Sopenharmony_ci buf.actime = tv[0].tv_sec; 949987da915Sopenharmony_ci buf.modtime = tv[1].tv_sec; 950987da915Sopenharmony_ci return fs->op.utime(path, &buf); 951987da915Sopenharmony_ci } else 952987da915Sopenharmony_ci return -ENOSYS; 953987da915Sopenharmony_ci} 954987da915Sopenharmony_ci 955987da915Sopenharmony_ciint fuse_fs_access(struct fuse_fs *fs, const char *path, int mask) 956987da915Sopenharmony_ci{ 957987da915Sopenharmony_ci fuse_get_context()->private_data = fs->user_data; 958987da915Sopenharmony_ci if (fs->op.access) 959987da915Sopenharmony_ci return fs->op.access(path, mask); 960987da915Sopenharmony_ci else 961987da915Sopenharmony_ci return -ENOSYS; 962987da915Sopenharmony_ci} 963987da915Sopenharmony_ci 964987da915Sopenharmony_ciint fuse_fs_readlink(struct fuse_fs *fs, const char *path, char *buf, 965987da915Sopenharmony_ci size_t len) 966987da915Sopenharmony_ci{ 967987da915Sopenharmony_ci fuse_get_context()->private_data = fs->user_data; 968987da915Sopenharmony_ci if (fs->op.readlink) 969987da915Sopenharmony_ci return fs->op.readlink(path, buf, len); 970987da915Sopenharmony_ci else 971987da915Sopenharmony_ci return -ENOSYS; 972987da915Sopenharmony_ci} 973987da915Sopenharmony_ci 974987da915Sopenharmony_ciint fuse_fs_mknod(struct fuse_fs *fs, const char *path, mode_t mode, 975987da915Sopenharmony_ci dev_t rdev) 976987da915Sopenharmony_ci{ 977987da915Sopenharmony_ci fuse_get_context()->private_data = fs->user_data; 978987da915Sopenharmony_ci if (fs->op.mknod) 979987da915Sopenharmony_ci return fs->op.mknod(path, mode, rdev); 980987da915Sopenharmony_ci else 981987da915Sopenharmony_ci return -ENOSYS; 982987da915Sopenharmony_ci} 983987da915Sopenharmony_ci 984987da915Sopenharmony_ciint fuse_fs_mkdir(struct fuse_fs *fs, const char *path, mode_t mode) 985987da915Sopenharmony_ci{ 986987da915Sopenharmony_ci fuse_get_context()->private_data = fs->user_data; 987987da915Sopenharmony_ci if (fs->op.mkdir) 988987da915Sopenharmony_ci return fs->op.mkdir(path, mode); 989987da915Sopenharmony_ci else 990987da915Sopenharmony_ci return -ENOSYS; 991987da915Sopenharmony_ci} 992987da915Sopenharmony_ci 993987da915Sopenharmony_ciint fuse_fs_setxattr(struct fuse_fs *fs, const char *path, const char *name, 994987da915Sopenharmony_ci const char *value, size_t size, int flags) 995987da915Sopenharmony_ci{ 996987da915Sopenharmony_ci fuse_get_context()->private_data = fs->user_data; 997987da915Sopenharmony_ci if (fs->op.setxattr) 998987da915Sopenharmony_ci return fs->op.setxattr(path, name, value, size, flags); 999987da915Sopenharmony_ci else 1000987da915Sopenharmony_ci return -ENOSYS; 1001987da915Sopenharmony_ci} 1002987da915Sopenharmony_ci 1003987da915Sopenharmony_ciint fuse_fs_getxattr(struct fuse_fs *fs, const char *path, const char *name, 1004987da915Sopenharmony_ci char *value, size_t size) 1005987da915Sopenharmony_ci{ 1006987da915Sopenharmony_ci fuse_get_context()->private_data = fs->user_data; 1007987da915Sopenharmony_ci if (fs->op.getxattr) 1008987da915Sopenharmony_ci return fs->op.getxattr(path, name, value, size); 1009987da915Sopenharmony_ci else 1010987da915Sopenharmony_ci return -ENOSYS; 1011987da915Sopenharmony_ci} 1012987da915Sopenharmony_ci 1013987da915Sopenharmony_ciint fuse_fs_listxattr(struct fuse_fs *fs, const char *path, char *list, 1014987da915Sopenharmony_ci size_t size) 1015987da915Sopenharmony_ci{ 1016987da915Sopenharmony_ci fuse_get_context()->private_data = fs->user_data; 1017987da915Sopenharmony_ci if (fs->op.listxattr) 1018987da915Sopenharmony_ci return fs->op.listxattr(path, list, size); 1019987da915Sopenharmony_ci else 1020987da915Sopenharmony_ci return -ENOSYS; 1021987da915Sopenharmony_ci} 1022987da915Sopenharmony_ci 1023987da915Sopenharmony_ciint fuse_fs_bmap(struct fuse_fs *fs, const char *path, size_t blocksize, 1024987da915Sopenharmony_ci uint64_t *idx) 1025987da915Sopenharmony_ci{ 1026987da915Sopenharmony_ci fuse_get_context()->private_data = fs->user_data; 1027987da915Sopenharmony_ci if (fs->op.bmap) 1028987da915Sopenharmony_ci return fs->op.bmap(path, blocksize, idx); 1029987da915Sopenharmony_ci else 1030987da915Sopenharmony_ci return -ENOSYS; 1031987da915Sopenharmony_ci} 1032987da915Sopenharmony_ci 1033987da915Sopenharmony_ciint fuse_fs_removexattr(struct fuse_fs *fs, const char *path, const char *name) 1034987da915Sopenharmony_ci{ 1035987da915Sopenharmony_ci fuse_get_context()->private_data = fs->user_data; 1036987da915Sopenharmony_ci if (fs->op.removexattr) 1037987da915Sopenharmony_ci return fs->op.removexattr(path, name); 1038987da915Sopenharmony_ci else 1039987da915Sopenharmony_ci return -ENOSYS; 1040987da915Sopenharmony_ci} 1041987da915Sopenharmony_ci 1042987da915Sopenharmony_ciint fuse_fs_ioctl(struct fuse_fs *fs, const char *path, int cmd, void *arg, 1043987da915Sopenharmony_ci struct fuse_file_info *fi, unsigned int flags, void *data) 1044987da915Sopenharmony_ci{ 1045987da915Sopenharmony_ci fuse_get_context()->private_data = fs->user_data; 1046987da915Sopenharmony_ci if (fs->op.ioctl) { 1047987da915Sopenharmony_ci/* 1048987da915Sopenharmony_ci if (fs->debug) 1049987da915Sopenharmony_ci fprintf(stderr, "ioctl[%llu] 0x%x flags: 0x%x\n", 1050987da915Sopenharmony_ci (unsigned long long) fi->fh, cmd, flags); 1051987da915Sopenharmony_ci*/ 1052987da915Sopenharmony_ci return fs->op.ioctl(path, cmd, arg, fi, flags, data); 1053987da915Sopenharmony_ci } else 1054987da915Sopenharmony_ci return -ENOSYS; 1055987da915Sopenharmony_ci} 1056987da915Sopenharmony_ci 1057987da915Sopenharmony_cistatic int is_open(struct fuse *f, fuse_ino_t dir, const char *name) 1058987da915Sopenharmony_ci{ 1059987da915Sopenharmony_ci struct node *node; 1060987da915Sopenharmony_ci int isopen = 0; 1061987da915Sopenharmony_ci pthread_mutex_lock(&f->lock); 1062987da915Sopenharmony_ci node = lookup_node(f, dir, name); 1063987da915Sopenharmony_ci if (node && node->open_count > 0) 1064987da915Sopenharmony_ci isopen = 1; 1065987da915Sopenharmony_ci pthread_mutex_unlock(&f->lock); 1066987da915Sopenharmony_ci return isopen; 1067987da915Sopenharmony_ci} 1068987da915Sopenharmony_ci 1069987da915Sopenharmony_cistatic char *hidden_name(struct fuse *f, fuse_ino_t dir, const char *oldname, 1070987da915Sopenharmony_ci char *newname, size_t bufsize) 1071987da915Sopenharmony_ci{ 1072987da915Sopenharmony_ci struct stat buf; 1073987da915Sopenharmony_ci struct node *node; 1074987da915Sopenharmony_ci struct node *newnode; 1075987da915Sopenharmony_ci char *newpath; 1076987da915Sopenharmony_ci int res; 1077987da915Sopenharmony_ci int failctr = 10; 1078987da915Sopenharmony_ci 1079987da915Sopenharmony_ci do { 1080987da915Sopenharmony_ci pthread_mutex_lock(&f->lock); 1081987da915Sopenharmony_ci node = lookup_node(f, dir, oldname); 1082987da915Sopenharmony_ci if (node == NULL) { 1083987da915Sopenharmony_ci pthread_mutex_unlock(&f->lock); 1084987da915Sopenharmony_ci return NULL; 1085987da915Sopenharmony_ci } 1086987da915Sopenharmony_ci do { 1087987da915Sopenharmony_ci f->hidectr ++; 1088987da915Sopenharmony_ci snprintf(newname, bufsize, ".fuse_hidden%08x%08x", 1089987da915Sopenharmony_ci (unsigned int) node->nodeid, f->hidectr); 1090987da915Sopenharmony_ci newnode = lookup_node(f, dir, newname); 1091987da915Sopenharmony_ci } while(newnode); 1092987da915Sopenharmony_ci pthread_mutex_unlock(&f->lock); 1093987da915Sopenharmony_ci 1094987da915Sopenharmony_ci newpath = get_path_name(f, dir, newname); 1095987da915Sopenharmony_ci if (!newpath) 1096987da915Sopenharmony_ci break; 1097987da915Sopenharmony_ci 1098987da915Sopenharmony_ci res = fuse_fs_getattr(f->fs, newpath, &buf); 1099987da915Sopenharmony_ci if (res == -ENOENT) 1100987da915Sopenharmony_ci break; 1101987da915Sopenharmony_ci free(newpath); 1102987da915Sopenharmony_ci newpath = NULL; 1103987da915Sopenharmony_ci } while(res == 0 && --failctr); 1104987da915Sopenharmony_ci 1105987da915Sopenharmony_ci return newpath; 1106987da915Sopenharmony_ci} 1107987da915Sopenharmony_ci 1108987da915Sopenharmony_cistatic int hide_node(struct fuse *f, const char *oldpath, 1109987da915Sopenharmony_ci fuse_ino_t dir, const char *oldname) 1110987da915Sopenharmony_ci{ 1111987da915Sopenharmony_ci char newname[64]; 1112987da915Sopenharmony_ci char *newpath; 1113987da915Sopenharmony_ci int err = -EBUSY; 1114987da915Sopenharmony_ci 1115987da915Sopenharmony_ci newpath = hidden_name(f, dir, oldname, newname, sizeof(newname)); 1116987da915Sopenharmony_ci if (newpath) { 1117987da915Sopenharmony_ci err = fuse_fs_rename(f->fs, oldpath, newpath); 1118987da915Sopenharmony_ci if (!err) 1119987da915Sopenharmony_ci err = rename_node(f, dir, oldname, dir, newname, 1); 1120987da915Sopenharmony_ci free(newpath); 1121987da915Sopenharmony_ci } 1122987da915Sopenharmony_ci return err; 1123987da915Sopenharmony_ci} 1124987da915Sopenharmony_ci 1125987da915Sopenharmony_ci#ifdef __SOLARIS__ 1126987da915Sopenharmony_ci 1127987da915Sopenharmony_cistatic int mtime_eq(const struct stat *stbuf, const struct timespec *ts) 1128987da915Sopenharmony_ci{ 1129987da915Sopenharmony_ci return stbuf->st_mtime == ts->tv_sec && ST_MTIM_NSEC(stbuf) == ts->tv_nsec; 1130987da915Sopenharmony_ci} 1131987da915Sopenharmony_ci 1132987da915Sopenharmony_ci#ifndef CLOCK_MONOTONIC 1133987da915Sopenharmony_ci#define CLOCK_MONOTONIC CLOCK_REALTIME 1134987da915Sopenharmony_ci#endif 1135987da915Sopenharmony_ci 1136987da915Sopenharmony_cistatic void curr_time(struct timespec *now) 1137987da915Sopenharmony_ci{ 1138987da915Sopenharmony_ci static clockid_t clockid = CLOCK_MONOTONIC; 1139987da915Sopenharmony_ci int res = clock_gettime(clockid, now); 1140987da915Sopenharmony_ci if (res == -1 && errno == EINVAL) { 1141987da915Sopenharmony_ci clockid = CLOCK_REALTIME; 1142987da915Sopenharmony_ci res = clock_gettime(clockid, now); 1143987da915Sopenharmony_ci } 1144987da915Sopenharmony_ci if (res == -1) { 1145987da915Sopenharmony_ci perror("fuse: clock_gettime"); 1146987da915Sopenharmony_ci abort(); 1147987da915Sopenharmony_ci } 1148987da915Sopenharmony_ci} 1149987da915Sopenharmony_ci 1150987da915Sopenharmony_cistatic void update_stat(struct node *node, const struct stat *stbuf) 1151987da915Sopenharmony_ci{ 1152987da915Sopenharmony_ci if (node->cache_valid && (!mtime_eq(stbuf, &node->mtime) || 1153987da915Sopenharmony_ci stbuf->st_size != node->size)) 1154987da915Sopenharmony_ci node->cache_valid = 0; 1155987da915Sopenharmony_ci node->mtime.tv_sec = stbuf->st_mtime; 1156987da915Sopenharmony_ci node->mtime.tv_nsec = ST_MTIM_NSEC(stbuf); 1157987da915Sopenharmony_ci node->size = stbuf->st_size; 1158987da915Sopenharmony_ci curr_time(&node->stat_updated); 1159987da915Sopenharmony_ci} 1160987da915Sopenharmony_ci 1161987da915Sopenharmony_ci#endif /* __SOLARIS__ */ 1162987da915Sopenharmony_ci 1163987da915Sopenharmony_cistatic int lookup_path(struct fuse *f, fuse_ino_t nodeid, 1164987da915Sopenharmony_ci const char *name, const char *path, 1165987da915Sopenharmony_ci struct fuse_entry_param *e, struct fuse_file_info *fi) 1166987da915Sopenharmony_ci{ 1167987da915Sopenharmony_ci int res; 1168987da915Sopenharmony_ci 1169987da915Sopenharmony_ci memset(e, 0, sizeof(struct fuse_entry_param)); 1170987da915Sopenharmony_ci if (fi) 1171987da915Sopenharmony_ci res = fuse_fs_fgetattr(f->fs, path, &e->attr, fi); 1172987da915Sopenharmony_ci else 1173987da915Sopenharmony_ci res = fuse_fs_getattr(f->fs, path, &e->attr); 1174987da915Sopenharmony_ci if (res == 0) { 1175987da915Sopenharmony_ci struct node *node; 1176987da915Sopenharmony_ci 1177987da915Sopenharmony_ci node = find_node(f, nodeid, name); 1178987da915Sopenharmony_ci if (node == NULL) 1179987da915Sopenharmony_ci res = -ENOMEM; 1180987da915Sopenharmony_ci else { 1181987da915Sopenharmony_ci e->ino = node->nodeid; 1182987da915Sopenharmony_ci e->generation = node->generation; 1183987da915Sopenharmony_ci e->entry_timeout = f->conf.entry_timeout; 1184987da915Sopenharmony_ci e->attr_timeout = f->conf.attr_timeout; 1185987da915Sopenharmony_ci#ifdef __SOLARIS__ 1186987da915Sopenharmony_ci if (f->conf.auto_cache) { 1187987da915Sopenharmony_ci pthread_mutex_lock(&f->lock); 1188987da915Sopenharmony_ci update_stat(node, &e->attr); 1189987da915Sopenharmony_ci pthread_mutex_unlock(&f->lock); 1190987da915Sopenharmony_ci } 1191987da915Sopenharmony_ci#endif /* __SOLARIS__ */ 1192987da915Sopenharmony_ci set_stat(f, e->ino, &e->attr); 1193987da915Sopenharmony_ci if (f->conf.debug) 1194987da915Sopenharmony_ci fprintf(stderr, " NODEID: %lu\n", (unsigned long) e->ino); 1195987da915Sopenharmony_ci } 1196987da915Sopenharmony_ci } 1197987da915Sopenharmony_ci return res; 1198987da915Sopenharmony_ci} 1199987da915Sopenharmony_ci 1200987da915Sopenharmony_cistatic struct fuse_context_i *fuse_get_context_internal(void) 1201987da915Sopenharmony_ci{ 1202987da915Sopenharmony_ci struct fuse_context_i *c; 1203987da915Sopenharmony_ci 1204987da915Sopenharmony_ci c = (struct fuse_context_i *) pthread_getspecific(fuse_context_key); 1205987da915Sopenharmony_ci if (c == NULL) { 1206987da915Sopenharmony_ci c = (struct fuse_context_i *) malloc(sizeof(struct fuse_context_i)); 1207987da915Sopenharmony_ci if (c == NULL) { 1208987da915Sopenharmony_ci /* This is hard to deal with properly, so just abort. If 1209987da915Sopenharmony_ci memory is so low that the context cannot be allocated, 1210987da915Sopenharmony_ci there's not much hope for the filesystem anyway */ 1211987da915Sopenharmony_ci fprintf(stderr, "fuse: failed to allocate thread specific data\n"); 1212987da915Sopenharmony_ci abort(); 1213987da915Sopenharmony_ci } 1214987da915Sopenharmony_ci pthread_setspecific(fuse_context_key, c); 1215987da915Sopenharmony_ci } 1216987da915Sopenharmony_ci return c; 1217987da915Sopenharmony_ci} 1218987da915Sopenharmony_ci 1219987da915Sopenharmony_cistatic void fuse_freecontext(void *data) 1220987da915Sopenharmony_ci{ 1221987da915Sopenharmony_ci free(data); 1222987da915Sopenharmony_ci} 1223987da915Sopenharmony_ci 1224987da915Sopenharmony_cistatic int fuse_create_context_key(void) 1225987da915Sopenharmony_ci{ 1226987da915Sopenharmony_ci int err = 0; 1227987da915Sopenharmony_ci pthread_mutex_lock(&fuse_context_lock); 1228987da915Sopenharmony_ci if (!fuse_context_ref) { 1229987da915Sopenharmony_ci err = pthread_key_create(&fuse_context_key, fuse_freecontext); 1230987da915Sopenharmony_ci if (err) { 1231987da915Sopenharmony_ci fprintf(stderr, "fuse: failed to create thread specific key: %s\n", 1232987da915Sopenharmony_ci strerror(err)); 1233987da915Sopenharmony_ci pthread_mutex_unlock(&fuse_context_lock); 1234987da915Sopenharmony_ci return -1; 1235987da915Sopenharmony_ci } 1236987da915Sopenharmony_ci } 1237987da915Sopenharmony_ci fuse_context_ref++; 1238987da915Sopenharmony_ci pthread_mutex_unlock(&fuse_context_lock); 1239987da915Sopenharmony_ci return 0; 1240987da915Sopenharmony_ci} 1241987da915Sopenharmony_ci 1242987da915Sopenharmony_cistatic void fuse_delete_context_key(void) 1243987da915Sopenharmony_ci{ 1244987da915Sopenharmony_ci pthread_mutex_lock(&fuse_context_lock); 1245987da915Sopenharmony_ci fuse_context_ref--; 1246987da915Sopenharmony_ci if (!fuse_context_ref) { 1247987da915Sopenharmony_ci free(pthread_getspecific(fuse_context_key)); 1248987da915Sopenharmony_ci pthread_key_delete(fuse_context_key); 1249987da915Sopenharmony_ci } 1250987da915Sopenharmony_ci pthread_mutex_unlock(&fuse_context_lock); 1251987da915Sopenharmony_ci} 1252987da915Sopenharmony_ci 1253987da915Sopenharmony_cistatic struct fuse *req_fuse_prepare(fuse_req_t req) 1254987da915Sopenharmony_ci{ 1255987da915Sopenharmony_ci struct fuse_context_i *c = fuse_get_context_internal(); 1256987da915Sopenharmony_ci const struct fuse_ctx *ctx = fuse_req_ctx(req); 1257987da915Sopenharmony_ci c->req = req; 1258987da915Sopenharmony_ci c->ctx.fuse = req_fuse(req); 1259987da915Sopenharmony_ci c->ctx.uid = ctx->uid; 1260987da915Sopenharmony_ci c->ctx.gid = ctx->gid; 1261987da915Sopenharmony_ci c->ctx.pid = ctx->pid; 1262987da915Sopenharmony_ci#ifdef POSIXACLS 1263987da915Sopenharmony_ci c->ctx.umask = ctx->umask; 1264987da915Sopenharmony_ci#endif 1265987da915Sopenharmony_ci return c->ctx.fuse; 1266987da915Sopenharmony_ci} 1267987da915Sopenharmony_ci 1268987da915Sopenharmony_ci#ifndef __SOLARIS__ 1269987da915Sopenharmony_cistatic void reply_err(fuse_req_t req, int err) 1270987da915Sopenharmony_ci#else /* __SOLARIS__ */ 1271987da915Sopenharmony_cistatic inline void reply_err(fuse_req_t req, int err) 1272987da915Sopenharmony_ci#endif /* __SOLARIS__ */ 1273987da915Sopenharmony_ci{ 1274987da915Sopenharmony_ci /* fuse_reply_err() uses non-negated errno values */ 1275987da915Sopenharmony_ci fuse_reply_err(req, -err); 1276987da915Sopenharmony_ci} 1277987da915Sopenharmony_ci 1278987da915Sopenharmony_cistatic void reply_entry(fuse_req_t req, const struct fuse_entry_param *e, 1279987da915Sopenharmony_ci int err) 1280987da915Sopenharmony_ci{ 1281987da915Sopenharmony_ci if (!err) { 1282987da915Sopenharmony_ci struct fuse *f = req_fuse(req); 1283987da915Sopenharmony_ci#ifdef __SOLARIS__ 1284987da915Sopenharmony_ci /* Skip forget for negative result */ 1285987da915Sopenharmony_ci if ((fuse_reply_entry(req, e) == -ENOENT) 1286987da915Sopenharmony_ci && (e->ino != 0)) 1287987da915Sopenharmony_ci forget_node(f, e->ino, 1); 1288987da915Sopenharmony_ci#else /* __SOLARIS__ */ 1289987da915Sopenharmony_ci if (fuse_reply_entry(req, e) == -ENOENT) 1290987da915Sopenharmony_ci forget_node(f, e->ino, 1); 1291987da915Sopenharmony_ci#endif 1292987da915Sopenharmony_ci } else 1293987da915Sopenharmony_ci reply_err(req, err); 1294987da915Sopenharmony_ci} 1295987da915Sopenharmony_ci 1296987da915Sopenharmony_civoid fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn) 1297987da915Sopenharmony_ci{ 1298987da915Sopenharmony_ci fuse_get_context()->private_data = fs->user_data; 1299987da915Sopenharmony_ci if (fs->op.init) 1300987da915Sopenharmony_ci fs->user_data = fs->op.init(conn); 1301987da915Sopenharmony_ci} 1302987da915Sopenharmony_ci 1303987da915Sopenharmony_cistatic void fuse_lib_init(void *data, struct fuse_conn_info *conn) 1304987da915Sopenharmony_ci{ 1305987da915Sopenharmony_ci struct fuse *f = (struct fuse *) data; 1306987da915Sopenharmony_ci struct fuse_context_i *c = fuse_get_context_internal(); 1307987da915Sopenharmony_ci 1308987da915Sopenharmony_ci memset(c, 0, sizeof(*c)); 1309987da915Sopenharmony_ci c->ctx.fuse = f; 1310987da915Sopenharmony_ci fuse_fs_init(f->fs, conn); 1311987da915Sopenharmony_ci} 1312987da915Sopenharmony_ci 1313987da915Sopenharmony_civoid fuse_fs_destroy(struct fuse_fs *fs) 1314987da915Sopenharmony_ci{ 1315987da915Sopenharmony_ci fuse_get_context()->private_data = fs->user_data; 1316987da915Sopenharmony_ci if (fs->op.destroy) 1317987da915Sopenharmony_ci fs->op.destroy(fs->user_data); 1318987da915Sopenharmony_ci#ifdef __SOLARIS__ 1319987da915Sopenharmony_ci if (fs->m) 1320987da915Sopenharmony_ci fuse_put_module(fs->m); 1321987da915Sopenharmony_ci#endif /* __SOLARIS__ */ 1322987da915Sopenharmony_ci free(fs); 1323987da915Sopenharmony_ci} 1324987da915Sopenharmony_ci 1325987da915Sopenharmony_cistatic void fuse_lib_destroy(void *data) 1326987da915Sopenharmony_ci{ 1327987da915Sopenharmony_ci struct fuse *f = (struct fuse *) data; 1328987da915Sopenharmony_ci struct fuse_context_i *c = fuse_get_context_internal(); 1329987da915Sopenharmony_ci 1330987da915Sopenharmony_ci memset(c, 0, sizeof(*c)); 1331987da915Sopenharmony_ci c->ctx.fuse = f; 1332987da915Sopenharmony_ci fuse_fs_destroy(f->fs); 1333987da915Sopenharmony_ci f->fs = NULL; 1334987da915Sopenharmony_ci} 1335987da915Sopenharmony_ci 1336987da915Sopenharmony_cistatic void fuse_lib_lookup(fuse_req_t req, fuse_ino_t parent, 1337987da915Sopenharmony_ci const char *name) 1338987da915Sopenharmony_ci{ 1339987da915Sopenharmony_ci struct fuse *f = req_fuse_prepare(req); 1340987da915Sopenharmony_ci struct fuse_entry_param e; 1341987da915Sopenharmony_ci char *path; 1342987da915Sopenharmony_ci int err; 1343987da915Sopenharmony_ci 1344987da915Sopenharmony_ci err = -ENOENT; 1345987da915Sopenharmony_ci pthread_rwlock_rdlock(&f->tree_lock); 1346987da915Sopenharmony_ci path = get_path_name(f, parent, name); 1347987da915Sopenharmony_ci if (path != NULL) { 1348987da915Sopenharmony_ci struct fuse_intr_data d; 1349987da915Sopenharmony_ci if (f->conf.debug) 1350987da915Sopenharmony_ci fprintf(stderr, "LOOKUP %s\n", path); 1351987da915Sopenharmony_ci fuse_prepare_interrupt(f, req, &d); 1352987da915Sopenharmony_ci err = lookup_path(f, parent, name, path, &e, NULL); 1353987da915Sopenharmony_ci if (err == -ENOENT && f->conf.negative_timeout != 0.0) { 1354987da915Sopenharmony_ci e.ino = 0; 1355987da915Sopenharmony_ci e.entry_timeout = f->conf.negative_timeout; 1356987da915Sopenharmony_ci err = 0; 1357987da915Sopenharmony_ci } 1358987da915Sopenharmony_ci fuse_finish_interrupt(f, req, &d); 1359987da915Sopenharmony_ci free(path); 1360987da915Sopenharmony_ci } 1361987da915Sopenharmony_ci pthread_rwlock_unlock(&f->tree_lock); 1362987da915Sopenharmony_ci reply_entry(req, &e, err); 1363987da915Sopenharmony_ci} 1364987da915Sopenharmony_ci 1365987da915Sopenharmony_cistatic void fuse_lib_forget(fuse_req_t req, fuse_ino_t ino, 1366987da915Sopenharmony_ci unsigned long nlookup) 1367987da915Sopenharmony_ci{ 1368987da915Sopenharmony_ci struct fuse *f = req_fuse(req); 1369987da915Sopenharmony_ci if (f->conf.debug) 1370987da915Sopenharmony_ci fprintf(stderr, "FORGET %llu/%lu\n", (unsigned long long)ino, nlookup); 1371987da915Sopenharmony_ci forget_node(f, ino, nlookup); 1372987da915Sopenharmony_ci fuse_reply_none(req); 1373987da915Sopenharmony_ci} 1374987da915Sopenharmony_ci 1375987da915Sopenharmony_cistatic void fuse_lib_getattr(fuse_req_t req, fuse_ino_t ino, 1376987da915Sopenharmony_ci struct fuse_file_info *fi) 1377987da915Sopenharmony_ci{ 1378987da915Sopenharmony_ci struct fuse *f = req_fuse_prepare(req); 1379987da915Sopenharmony_ci struct stat buf; 1380987da915Sopenharmony_ci char *path; 1381987da915Sopenharmony_ci int err; 1382987da915Sopenharmony_ci 1383987da915Sopenharmony_ci (void) fi; 1384987da915Sopenharmony_ci memset(&buf, 0, sizeof(buf)); 1385987da915Sopenharmony_ci 1386987da915Sopenharmony_ci err = -ENOENT; 1387987da915Sopenharmony_ci pthread_rwlock_rdlock(&f->tree_lock); 1388987da915Sopenharmony_ci path = get_path(f, ino); 1389987da915Sopenharmony_ci if (path != NULL) { 1390987da915Sopenharmony_ci struct fuse_intr_data d; 1391987da915Sopenharmony_ci fuse_prepare_interrupt(f, req, &d); 1392987da915Sopenharmony_ci err = fuse_fs_getattr(f->fs, path, &buf); 1393987da915Sopenharmony_ci fuse_finish_interrupt(f, req, &d); 1394987da915Sopenharmony_ci free(path); 1395987da915Sopenharmony_ci } 1396987da915Sopenharmony_ci pthread_rwlock_unlock(&f->tree_lock); 1397987da915Sopenharmony_ci if (!err) { 1398987da915Sopenharmony_ci#ifdef __SOLARIS__ 1399987da915Sopenharmony_ci if (f->conf.auto_cache) { 1400987da915Sopenharmony_ci pthread_mutex_lock(&f->lock); 1401987da915Sopenharmony_ci update_stat(get_node(f, ino), &buf); 1402987da915Sopenharmony_ci pthread_mutex_unlock(&f->lock); 1403987da915Sopenharmony_ci } 1404987da915Sopenharmony_ci#endif /* __SOLARIS__ */ 1405987da915Sopenharmony_ci set_stat(f, ino, &buf); 1406987da915Sopenharmony_ci fuse_reply_attr(req, &buf, f->conf.attr_timeout); 1407987da915Sopenharmony_ci } else 1408987da915Sopenharmony_ci reply_err(req, err); 1409987da915Sopenharmony_ci} 1410987da915Sopenharmony_ci 1411987da915Sopenharmony_ciint fuse_fs_chmod(struct fuse_fs *fs, const char *path, mode_t mode) 1412987da915Sopenharmony_ci{ 1413987da915Sopenharmony_ci fuse_get_context()->private_data = fs->user_data; 1414987da915Sopenharmony_ci if (fs->op.chmod) 1415987da915Sopenharmony_ci return fs->op.chmod(path, mode); 1416987da915Sopenharmony_ci else 1417987da915Sopenharmony_ci return -ENOSYS; 1418987da915Sopenharmony_ci} 1419987da915Sopenharmony_ci 1420987da915Sopenharmony_cistatic void fuse_lib_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr, 1421987da915Sopenharmony_ci int valid, struct fuse_file_info *fi) 1422987da915Sopenharmony_ci{ 1423987da915Sopenharmony_ci struct fuse *f = req_fuse_prepare(req); 1424987da915Sopenharmony_ci struct stat buf; 1425987da915Sopenharmony_ci char *path; 1426987da915Sopenharmony_ci int err; 1427987da915Sopenharmony_ci 1428987da915Sopenharmony_ci err = -ENOENT; 1429987da915Sopenharmony_ci pthread_rwlock_rdlock(&f->tree_lock); 1430987da915Sopenharmony_ci path = get_path(f, ino); 1431987da915Sopenharmony_ci if (path != NULL) { 1432987da915Sopenharmony_ci struct fuse_intr_data d; 1433987da915Sopenharmony_ci fuse_prepare_interrupt(f, req, &d); 1434987da915Sopenharmony_ci err = 0; 1435987da915Sopenharmony_ci if (!err && (valid & FUSE_SET_ATTR_MODE)) 1436987da915Sopenharmony_ci err = fuse_fs_chmod(f->fs, path, attr->st_mode); 1437987da915Sopenharmony_ci if (!err && (valid & (FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID))) { 1438987da915Sopenharmony_ci uid_t uid = 1439987da915Sopenharmony_ci (valid & FUSE_SET_ATTR_UID) ? attr->st_uid : (uid_t) -1; 1440987da915Sopenharmony_ci gid_t gid = 1441987da915Sopenharmony_ci (valid & FUSE_SET_ATTR_GID) ? attr->st_gid : (gid_t) -1; 1442987da915Sopenharmony_ci err = fuse_fs_chown(f->fs, path, uid, gid); 1443987da915Sopenharmony_ci } 1444987da915Sopenharmony_ci if (!err && (valid & FUSE_SET_ATTR_SIZE)) { 1445987da915Sopenharmony_ci if (fi) 1446987da915Sopenharmony_ci err = fuse_fs_ftruncate(f->fs, path, attr->st_size, fi); 1447987da915Sopenharmony_ci else 1448987da915Sopenharmony_ci err = fuse_fs_truncate(f->fs, path, attr->st_size); 1449987da915Sopenharmony_ci } 1450987da915Sopenharmony_ci#ifdef HAVE_UTIMENSAT 1451987da915Sopenharmony_ci if (!err && 1452987da915Sopenharmony_ci (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME))) { 1453987da915Sopenharmony_ci struct timespec tv[2]; 1454987da915Sopenharmony_ci 1455987da915Sopenharmony_ci tv[0].tv_sec = 0; 1456987da915Sopenharmony_ci tv[1].tv_sec = 0; 1457987da915Sopenharmony_ci tv[0].tv_nsec = UTIME_OMIT; 1458987da915Sopenharmony_ci tv[1].tv_nsec = UTIME_OMIT; 1459987da915Sopenharmony_ci 1460987da915Sopenharmony_ci if (valid & FUSE_SET_ATTR_ATIME_NOW) 1461987da915Sopenharmony_ci tv[0].tv_nsec = UTIME_NOW; 1462987da915Sopenharmony_ci else if (valid & FUSE_SET_ATTR_ATIME) 1463987da915Sopenharmony_ci tv[0] = attr->st_atim; 1464987da915Sopenharmony_ci 1465987da915Sopenharmony_ci if (valid & FUSE_SET_ATTR_MTIME_NOW) 1466987da915Sopenharmony_ci tv[1].tv_nsec = UTIME_NOW; 1467987da915Sopenharmony_ci else if (valid & FUSE_SET_ATTR_MTIME) 1468987da915Sopenharmony_ci tv[1] = attr->st_mtim; 1469987da915Sopenharmony_ci 1470987da915Sopenharmony_ci err = fuse_fs_utimens(f->fs, path, tv); 1471987da915Sopenharmony_ci } else 1472987da915Sopenharmony_ci#endif 1473987da915Sopenharmony_ci if (!err && (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) == 1474987da915Sopenharmony_ci (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) { 1475987da915Sopenharmony_ci struct timespec tv[2]; 1476987da915Sopenharmony_ci tv[0].tv_sec = attr->st_atime; 1477987da915Sopenharmony_ci tv[0].tv_nsec = ST_ATIM_NSEC(attr); 1478987da915Sopenharmony_ci tv[1].tv_sec = attr->st_mtime; 1479987da915Sopenharmony_ci tv[1].tv_nsec = ST_MTIM_NSEC(attr); 1480987da915Sopenharmony_ci err = fuse_fs_utimens(f->fs, path, tv); 1481987da915Sopenharmony_ci } 1482987da915Sopenharmony_ci if (!err) 1483987da915Sopenharmony_ci err = fuse_fs_getattr(f->fs, path, &buf); 1484987da915Sopenharmony_ci fuse_finish_interrupt(f, req, &d); 1485987da915Sopenharmony_ci free(path); 1486987da915Sopenharmony_ci } 1487987da915Sopenharmony_ci pthread_rwlock_unlock(&f->tree_lock); 1488987da915Sopenharmony_ci if (!err) { 1489987da915Sopenharmony_ci#ifdef __SOLARIS__ 1490987da915Sopenharmony_ci if (f->conf.auto_cache) { 1491987da915Sopenharmony_ci pthread_mutex_lock(&f->lock); 1492987da915Sopenharmony_ci update_stat(get_node(f, ino), &buf); 1493987da915Sopenharmony_ci pthread_mutex_unlock(&f->lock); 1494987da915Sopenharmony_ci } 1495987da915Sopenharmony_ci#endif /* __SOLARIS__ */ 1496987da915Sopenharmony_ci set_stat(f, ino, &buf); 1497987da915Sopenharmony_ci fuse_reply_attr(req, &buf, f->conf.attr_timeout); 1498987da915Sopenharmony_ci } else 1499987da915Sopenharmony_ci reply_err(req, err); 1500987da915Sopenharmony_ci} 1501987da915Sopenharmony_ci 1502987da915Sopenharmony_cistatic void fuse_lib_access(fuse_req_t req, fuse_ino_t ino, int mask) 1503987da915Sopenharmony_ci{ 1504987da915Sopenharmony_ci struct fuse *f = req_fuse_prepare(req); 1505987da915Sopenharmony_ci char *path; 1506987da915Sopenharmony_ci int err; 1507987da915Sopenharmony_ci 1508987da915Sopenharmony_ci err = -ENOENT; 1509987da915Sopenharmony_ci pthread_rwlock_rdlock(&f->tree_lock); 1510987da915Sopenharmony_ci path = get_path(f, ino); 1511987da915Sopenharmony_ci if (path != NULL) { 1512987da915Sopenharmony_ci struct fuse_intr_data d; 1513987da915Sopenharmony_ci if (f->conf.debug) 1514987da915Sopenharmony_ci fprintf(stderr, "ACCESS %s 0%o\n", path, mask); 1515987da915Sopenharmony_ci fuse_prepare_interrupt(f, req, &d); 1516987da915Sopenharmony_ci err = fuse_fs_access(f->fs, path, mask); 1517987da915Sopenharmony_ci fuse_finish_interrupt(f, req, &d); 1518987da915Sopenharmony_ci free(path); 1519987da915Sopenharmony_ci } 1520987da915Sopenharmony_ci pthread_rwlock_unlock(&f->tree_lock); 1521987da915Sopenharmony_ci reply_err(req, err); 1522987da915Sopenharmony_ci} 1523987da915Sopenharmony_ci 1524987da915Sopenharmony_cistatic void fuse_lib_readlink(fuse_req_t req, fuse_ino_t ino) 1525987da915Sopenharmony_ci{ 1526987da915Sopenharmony_ci struct fuse *f = req_fuse_prepare(req); 1527987da915Sopenharmony_ci char linkname[PATH_MAX + 1]; 1528987da915Sopenharmony_ci char *path; 1529987da915Sopenharmony_ci int err; 1530987da915Sopenharmony_ci 1531987da915Sopenharmony_ci err = -ENOENT; 1532987da915Sopenharmony_ci pthread_rwlock_rdlock(&f->tree_lock); 1533987da915Sopenharmony_ci path = get_path(f, ino); 1534987da915Sopenharmony_ci if (path != NULL) { 1535987da915Sopenharmony_ci struct fuse_intr_data d; 1536987da915Sopenharmony_ci fuse_prepare_interrupt(f, req, &d); 1537987da915Sopenharmony_ci err = fuse_fs_readlink(f->fs, path, linkname, sizeof(linkname)); 1538987da915Sopenharmony_ci fuse_finish_interrupt(f, req, &d); 1539987da915Sopenharmony_ci free(path); 1540987da915Sopenharmony_ci } 1541987da915Sopenharmony_ci pthread_rwlock_unlock(&f->tree_lock); 1542987da915Sopenharmony_ci if (!err) { 1543987da915Sopenharmony_ci linkname[PATH_MAX] = '\0'; 1544987da915Sopenharmony_ci fuse_reply_readlink(req, linkname); 1545987da915Sopenharmony_ci } else 1546987da915Sopenharmony_ci reply_err(req, err); 1547987da915Sopenharmony_ci} 1548987da915Sopenharmony_ci 1549987da915Sopenharmony_cistatic void fuse_lib_mknod(fuse_req_t req, fuse_ino_t parent, const char *name, 1550987da915Sopenharmony_ci mode_t mode, dev_t rdev) 1551987da915Sopenharmony_ci{ 1552987da915Sopenharmony_ci struct fuse *f = req_fuse_prepare(req); 1553987da915Sopenharmony_ci struct fuse_entry_param e; 1554987da915Sopenharmony_ci char *path; 1555987da915Sopenharmony_ci int err; 1556987da915Sopenharmony_ci 1557987da915Sopenharmony_ci err = -ENOENT; 1558987da915Sopenharmony_ci pthread_rwlock_rdlock(&f->tree_lock); 1559987da915Sopenharmony_ci path = get_path_name(f, parent, name); 1560987da915Sopenharmony_ci if (path) { 1561987da915Sopenharmony_ci struct fuse_intr_data d; 1562987da915Sopenharmony_ci if (f->conf.debug) 1563987da915Sopenharmony_ci fprintf(stderr, "MKNOD %s\n", path); 1564987da915Sopenharmony_ci fuse_prepare_interrupt(f, req, &d); 1565987da915Sopenharmony_ci err = -ENOSYS; 1566987da915Sopenharmony_ci if (S_ISREG(mode)) { 1567987da915Sopenharmony_ci struct fuse_file_info fi; 1568987da915Sopenharmony_ci 1569987da915Sopenharmony_ci memset(&fi, 0, sizeof(fi)); 1570987da915Sopenharmony_ci fi.flags = O_CREAT | O_EXCL | O_WRONLY; 1571987da915Sopenharmony_ci err = fuse_fs_create(f->fs, path, mode, &fi); 1572987da915Sopenharmony_ci if (!err) { 1573987da915Sopenharmony_ci err = lookup_path(f, parent, name, path, &e, &fi); 1574987da915Sopenharmony_ci fuse_fs_release(f->fs, path, &fi); 1575987da915Sopenharmony_ci } 1576987da915Sopenharmony_ci } 1577987da915Sopenharmony_ci if (err == -ENOSYS) { 1578987da915Sopenharmony_ci err = fuse_fs_mknod(f->fs, path, mode, rdev); 1579987da915Sopenharmony_ci if (!err) 1580987da915Sopenharmony_ci err = lookup_path(f, parent, name, path, &e, NULL); 1581987da915Sopenharmony_ci } 1582987da915Sopenharmony_ci fuse_finish_interrupt(f, req, &d); 1583987da915Sopenharmony_ci free(path); 1584987da915Sopenharmony_ci } 1585987da915Sopenharmony_ci pthread_rwlock_unlock(&f->tree_lock); 1586987da915Sopenharmony_ci reply_entry(req, &e, err); 1587987da915Sopenharmony_ci} 1588987da915Sopenharmony_ci 1589987da915Sopenharmony_cistatic void fuse_lib_mkdir(fuse_req_t req, fuse_ino_t parent, const char *name, 1590987da915Sopenharmony_ci mode_t mode) 1591987da915Sopenharmony_ci{ 1592987da915Sopenharmony_ci struct fuse *f = req_fuse_prepare(req); 1593987da915Sopenharmony_ci struct fuse_entry_param e; 1594987da915Sopenharmony_ci char *path; 1595987da915Sopenharmony_ci int err; 1596987da915Sopenharmony_ci 1597987da915Sopenharmony_ci err = -ENOENT; 1598987da915Sopenharmony_ci pthread_rwlock_rdlock(&f->tree_lock); 1599987da915Sopenharmony_ci path = get_path_name(f, parent, name); 1600987da915Sopenharmony_ci if (path != NULL) { 1601987da915Sopenharmony_ci struct fuse_intr_data d; 1602987da915Sopenharmony_ci if (f->conf.debug) 1603987da915Sopenharmony_ci fprintf(stderr, "MKDIR %s\n", path); 1604987da915Sopenharmony_ci fuse_prepare_interrupt(f, req, &d); 1605987da915Sopenharmony_ci err = fuse_fs_mkdir(f->fs, path, mode); 1606987da915Sopenharmony_ci if (!err) 1607987da915Sopenharmony_ci err = lookup_path(f, parent, name, path, &e, NULL); 1608987da915Sopenharmony_ci fuse_finish_interrupt(f, req, &d); 1609987da915Sopenharmony_ci free(path); 1610987da915Sopenharmony_ci } 1611987da915Sopenharmony_ci pthread_rwlock_unlock(&f->tree_lock); 1612987da915Sopenharmony_ci reply_entry(req, &e, err); 1613987da915Sopenharmony_ci} 1614987da915Sopenharmony_ci 1615987da915Sopenharmony_cistatic void fuse_lib_unlink(fuse_req_t req, fuse_ino_t parent, 1616987da915Sopenharmony_ci const char *name) 1617987da915Sopenharmony_ci{ 1618987da915Sopenharmony_ci struct fuse *f = req_fuse_prepare(req); 1619987da915Sopenharmony_ci char *path; 1620987da915Sopenharmony_ci int err; 1621987da915Sopenharmony_ci 1622987da915Sopenharmony_ci err = -ENOENT; 1623987da915Sopenharmony_ci pthread_rwlock_wrlock(&f->tree_lock); 1624987da915Sopenharmony_ci path = get_path_name(f, parent, name); 1625987da915Sopenharmony_ci if (path != NULL) { 1626987da915Sopenharmony_ci struct fuse_intr_data d; 1627987da915Sopenharmony_ci if (f->conf.debug) 1628987da915Sopenharmony_ci fprintf(stderr, "UNLINK %s\n", path); 1629987da915Sopenharmony_ci fuse_prepare_interrupt(f, req, &d); 1630987da915Sopenharmony_ci if (!f->conf.hard_remove && is_open(f, parent, name)) 1631987da915Sopenharmony_ci err = hide_node(f, path, parent, name); 1632987da915Sopenharmony_ci else { 1633987da915Sopenharmony_ci err = fuse_fs_unlink(f->fs, path); 1634987da915Sopenharmony_ci if (!err) 1635987da915Sopenharmony_ci remove_node(f, parent, name); 1636987da915Sopenharmony_ci } 1637987da915Sopenharmony_ci fuse_finish_interrupt(f, req, &d); 1638987da915Sopenharmony_ci free(path); 1639987da915Sopenharmony_ci } 1640987da915Sopenharmony_ci pthread_rwlock_unlock(&f->tree_lock); 1641987da915Sopenharmony_ci reply_err(req, err); 1642987da915Sopenharmony_ci} 1643987da915Sopenharmony_ci 1644987da915Sopenharmony_cistatic void fuse_lib_rmdir(fuse_req_t req, fuse_ino_t parent, const char *name) 1645987da915Sopenharmony_ci{ 1646987da915Sopenharmony_ci struct fuse *f = req_fuse_prepare(req); 1647987da915Sopenharmony_ci char *path; 1648987da915Sopenharmony_ci int err; 1649987da915Sopenharmony_ci 1650987da915Sopenharmony_ci err = -ENOENT; 1651987da915Sopenharmony_ci pthread_rwlock_wrlock(&f->tree_lock); 1652987da915Sopenharmony_ci path = get_path_name(f, parent, name); 1653987da915Sopenharmony_ci if (path != NULL) { 1654987da915Sopenharmony_ci struct fuse_intr_data d; 1655987da915Sopenharmony_ci if (f->conf.debug) 1656987da915Sopenharmony_ci fprintf(stderr, "RMDIR %s\n", path); 1657987da915Sopenharmony_ci fuse_prepare_interrupt(f, req, &d); 1658987da915Sopenharmony_ci err = fuse_fs_rmdir(f->fs, path); 1659987da915Sopenharmony_ci fuse_finish_interrupt(f, req, &d); 1660987da915Sopenharmony_ci if (!err) 1661987da915Sopenharmony_ci remove_node(f, parent, name); 1662987da915Sopenharmony_ci free(path); 1663987da915Sopenharmony_ci } 1664987da915Sopenharmony_ci pthread_rwlock_unlock(&f->tree_lock); 1665987da915Sopenharmony_ci reply_err(req, err); 1666987da915Sopenharmony_ci} 1667987da915Sopenharmony_ci 1668987da915Sopenharmony_cistatic void fuse_lib_symlink(fuse_req_t req, const char *linkname, 1669987da915Sopenharmony_ci fuse_ino_t parent, const char *name) 1670987da915Sopenharmony_ci{ 1671987da915Sopenharmony_ci struct fuse *f = req_fuse_prepare(req); 1672987da915Sopenharmony_ci struct fuse_entry_param e; 1673987da915Sopenharmony_ci char *path; 1674987da915Sopenharmony_ci int err; 1675987da915Sopenharmony_ci 1676987da915Sopenharmony_ci err = -ENOENT; 1677987da915Sopenharmony_ci pthread_rwlock_rdlock(&f->tree_lock); 1678987da915Sopenharmony_ci path = get_path_name(f, parent, name); 1679987da915Sopenharmony_ci if (path != NULL) { 1680987da915Sopenharmony_ci struct fuse_intr_data d; 1681987da915Sopenharmony_ci if (f->conf.debug) 1682987da915Sopenharmony_ci fprintf(stderr, "SYMLINK %s\n", path); 1683987da915Sopenharmony_ci fuse_prepare_interrupt(f, req, &d); 1684987da915Sopenharmony_ci err = fuse_fs_symlink(f->fs, linkname, path); 1685987da915Sopenharmony_ci if (!err) 1686987da915Sopenharmony_ci err = lookup_path(f, parent, name, path, &e, NULL); 1687987da915Sopenharmony_ci fuse_finish_interrupt(f, req, &d); 1688987da915Sopenharmony_ci free(path); 1689987da915Sopenharmony_ci } 1690987da915Sopenharmony_ci pthread_rwlock_unlock(&f->tree_lock); 1691987da915Sopenharmony_ci reply_entry(req, &e, err); 1692987da915Sopenharmony_ci} 1693987da915Sopenharmony_ci 1694987da915Sopenharmony_cistatic void fuse_lib_rename(fuse_req_t req, fuse_ino_t olddir, 1695987da915Sopenharmony_ci const char *oldname, fuse_ino_t newdir, 1696987da915Sopenharmony_ci const char *newname) 1697987da915Sopenharmony_ci{ 1698987da915Sopenharmony_ci struct fuse *f = req_fuse_prepare(req); 1699987da915Sopenharmony_ci char *oldpath; 1700987da915Sopenharmony_ci char *newpath; 1701987da915Sopenharmony_ci int err; 1702987da915Sopenharmony_ci 1703987da915Sopenharmony_ci err = -ENOENT; 1704987da915Sopenharmony_ci pthread_rwlock_wrlock(&f->tree_lock); 1705987da915Sopenharmony_ci oldpath = get_path_name(f, olddir, oldname); 1706987da915Sopenharmony_ci if (oldpath != NULL) { 1707987da915Sopenharmony_ci newpath = get_path_name(f, newdir, newname); 1708987da915Sopenharmony_ci if (newpath != NULL) { 1709987da915Sopenharmony_ci struct fuse_intr_data d; 1710987da915Sopenharmony_ci if (f->conf.debug) 1711987da915Sopenharmony_ci fprintf(stderr, "RENAME %s -> %s\n", oldpath, newpath); 1712987da915Sopenharmony_ci err = 0; 1713987da915Sopenharmony_ci fuse_prepare_interrupt(f, req, &d); 1714987da915Sopenharmony_ci if (!f->conf.hard_remove && is_open(f, newdir, newname)) 1715987da915Sopenharmony_ci err = hide_node(f, newpath, newdir, newname); 1716987da915Sopenharmony_ci if (!err) { 1717987da915Sopenharmony_ci err = fuse_fs_rename(f->fs, oldpath, newpath); 1718987da915Sopenharmony_ci if (!err) 1719987da915Sopenharmony_ci err = rename_node(f, olddir, oldname, newdir, newname, 0); 1720987da915Sopenharmony_ci } 1721987da915Sopenharmony_ci fuse_finish_interrupt(f, req, &d); 1722987da915Sopenharmony_ci free(newpath); 1723987da915Sopenharmony_ci } 1724987da915Sopenharmony_ci free(oldpath); 1725987da915Sopenharmony_ci } 1726987da915Sopenharmony_ci pthread_rwlock_unlock(&f->tree_lock); 1727987da915Sopenharmony_ci reply_err(req, err); 1728987da915Sopenharmony_ci} 1729987da915Sopenharmony_ci 1730987da915Sopenharmony_cistatic void fuse_lib_link(fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent, 1731987da915Sopenharmony_ci const char *newname) 1732987da915Sopenharmony_ci{ 1733987da915Sopenharmony_ci struct fuse *f = req_fuse_prepare(req); 1734987da915Sopenharmony_ci struct fuse_entry_param e; 1735987da915Sopenharmony_ci char *oldpath; 1736987da915Sopenharmony_ci char *newpath; 1737987da915Sopenharmony_ci int err; 1738987da915Sopenharmony_ci 1739987da915Sopenharmony_ci err = -ENOENT; 1740987da915Sopenharmony_ci pthread_rwlock_rdlock(&f->tree_lock); 1741987da915Sopenharmony_ci oldpath = get_path(f, ino); 1742987da915Sopenharmony_ci if (oldpath != NULL) { 1743987da915Sopenharmony_ci newpath = get_path_name(f, newparent, newname); 1744987da915Sopenharmony_ci if (newpath != NULL) { 1745987da915Sopenharmony_ci struct fuse_intr_data d; 1746987da915Sopenharmony_ci if (f->conf.debug) 1747987da915Sopenharmony_ci fprintf(stderr, "LINK %s\n", newpath); 1748987da915Sopenharmony_ci fuse_prepare_interrupt(f, req, &d); 1749987da915Sopenharmony_ci err = fuse_fs_link(f->fs, oldpath, newpath); 1750987da915Sopenharmony_ci if (!err) 1751987da915Sopenharmony_ci err = lookup_path(f, newparent, newname, newpath, &e, NULL); 1752987da915Sopenharmony_ci fuse_finish_interrupt(f, req, &d); 1753987da915Sopenharmony_ci free(newpath); 1754987da915Sopenharmony_ci } 1755987da915Sopenharmony_ci free(oldpath); 1756987da915Sopenharmony_ci } 1757987da915Sopenharmony_ci pthread_rwlock_unlock(&f->tree_lock); 1758987da915Sopenharmony_ci reply_entry(req, &e, err); 1759987da915Sopenharmony_ci} 1760987da915Sopenharmony_ci 1761987da915Sopenharmony_cistatic void fuse_do_release(struct fuse *f, fuse_ino_t ino, const char *path, 1762987da915Sopenharmony_ci struct fuse_file_info *fi) 1763987da915Sopenharmony_ci{ 1764987da915Sopenharmony_ci struct node *node; 1765987da915Sopenharmony_ci int unlink_hidden = 0; 1766987da915Sopenharmony_ci 1767987da915Sopenharmony_ci fuse_fs_release(f->fs, path ? path : "-", fi); 1768987da915Sopenharmony_ci 1769987da915Sopenharmony_ci pthread_mutex_lock(&f->lock); 1770987da915Sopenharmony_ci node = get_node(f, ino); 1771987da915Sopenharmony_ci assert(node->open_count > 0); 1772987da915Sopenharmony_ci --node->open_count; 1773987da915Sopenharmony_ci if (node->is_hidden && !node->open_count) { 1774987da915Sopenharmony_ci unlink_hidden = 1; 1775987da915Sopenharmony_ci node->is_hidden = 0; 1776987da915Sopenharmony_ci } 1777987da915Sopenharmony_ci pthread_mutex_unlock(&f->lock); 1778987da915Sopenharmony_ci 1779987da915Sopenharmony_ci if(unlink_hidden && path) 1780987da915Sopenharmony_ci fuse_fs_unlink(f->fs, path); 1781987da915Sopenharmony_ci} 1782987da915Sopenharmony_ci 1783987da915Sopenharmony_cistatic void fuse_lib_create(fuse_req_t req, fuse_ino_t parent, 1784987da915Sopenharmony_ci const char *name, mode_t mode, 1785987da915Sopenharmony_ci struct fuse_file_info *fi) 1786987da915Sopenharmony_ci{ 1787987da915Sopenharmony_ci struct fuse *f = req_fuse_prepare(req); 1788987da915Sopenharmony_ci struct fuse_intr_data d; 1789987da915Sopenharmony_ci struct fuse_entry_param e; 1790987da915Sopenharmony_ci char *path; 1791987da915Sopenharmony_ci int err; 1792987da915Sopenharmony_ci 1793987da915Sopenharmony_ci err = -ENOENT; 1794987da915Sopenharmony_ci pthread_rwlock_rdlock(&f->tree_lock); 1795987da915Sopenharmony_ci path = get_path_name(f, parent, name); 1796987da915Sopenharmony_ci if (path) { 1797987da915Sopenharmony_ci fuse_prepare_interrupt(f, req, &d); 1798987da915Sopenharmony_ci err = fuse_fs_create(f->fs, path, mode, fi); 1799987da915Sopenharmony_ci if (!err) { 1800987da915Sopenharmony_ci err = lookup_path(f, parent, name, path, &e, fi); 1801987da915Sopenharmony_ci if (err) 1802987da915Sopenharmony_ci fuse_fs_release(f->fs, path, fi); 1803987da915Sopenharmony_ci else if (!S_ISREG(e.attr.st_mode)) { 1804987da915Sopenharmony_ci err = -EIO; 1805987da915Sopenharmony_ci fuse_fs_release(f->fs, path, fi); 1806987da915Sopenharmony_ci forget_node(f, e.ino, 1); 1807987da915Sopenharmony_ci } else { 1808987da915Sopenharmony_ci if (f->conf.direct_io) 1809987da915Sopenharmony_ci fi->direct_io = 1; 1810987da915Sopenharmony_ci if (f->conf.kernel_cache) 1811987da915Sopenharmony_ci fi->keep_cache = 1; 1812987da915Sopenharmony_ci 1813987da915Sopenharmony_ci } 1814987da915Sopenharmony_ci } 1815987da915Sopenharmony_ci fuse_finish_interrupt(f, req, &d); 1816987da915Sopenharmony_ci } 1817987da915Sopenharmony_ci if (!err) { 1818987da915Sopenharmony_ci pthread_mutex_lock(&f->lock); 1819987da915Sopenharmony_ci get_node(f, e.ino)->open_count++; 1820987da915Sopenharmony_ci pthread_mutex_unlock(&f->lock); 1821987da915Sopenharmony_ci if (fuse_reply_create(req, &e, fi) == -ENOENT) { 1822987da915Sopenharmony_ci /* The open syscall was interrupted, so it must be cancelled */ 1823987da915Sopenharmony_ci fuse_prepare_interrupt(f, req, &d); 1824987da915Sopenharmony_ci fuse_do_release(f, e.ino, path, fi); 1825987da915Sopenharmony_ci fuse_finish_interrupt(f, req, &d); 1826987da915Sopenharmony_ci forget_node(f, e.ino, 1); 1827987da915Sopenharmony_ci } else if (f->conf.debug) { 1828987da915Sopenharmony_ci fprintf(stderr, " CREATE[%llu] flags: 0x%x %s\n", 1829987da915Sopenharmony_ci (unsigned long long) fi->fh, fi->flags, path); 1830987da915Sopenharmony_ci } 1831987da915Sopenharmony_ci } else 1832987da915Sopenharmony_ci reply_err(req, err); 1833987da915Sopenharmony_ci 1834987da915Sopenharmony_ci if (path) 1835987da915Sopenharmony_ci free(path); 1836987da915Sopenharmony_ci 1837987da915Sopenharmony_ci pthread_rwlock_unlock(&f->tree_lock); 1838987da915Sopenharmony_ci} 1839987da915Sopenharmony_ci 1840987da915Sopenharmony_ci#ifdef __SOLARIS__ 1841987da915Sopenharmony_ci 1842987da915Sopenharmony_cistatic double diff_timespec(const struct timespec *t1, 1843987da915Sopenharmony_ci const struct timespec *t2) 1844987da915Sopenharmony_ci{ 1845987da915Sopenharmony_ci return (t1->tv_sec - t2->tv_sec) + 1846987da915Sopenharmony_ci ((double) t1->tv_nsec - (double) t2->tv_nsec) / 1000000000.0; 1847987da915Sopenharmony_ci} 1848987da915Sopenharmony_ci 1849987da915Sopenharmony_cistatic void open_auto_cache(struct fuse *f, fuse_ino_t ino, const char *path, 1850987da915Sopenharmony_ci struct fuse_file_info *fi) 1851987da915Sopenharmony_ci{ 1852987da915Sopenharmony_ci struct node *node; 1853987da915Sopenharmony_ci 1854987da915Sopenharmony_ci pthread_mutex_lock(&f->lock); 1855987da915Sopenharmony_ci node = get_node(f, ino); 1856987da915Sopenharmony_ci if (node->cache_valid) { 1857987da915Sopenharmony_ci struct timespec now; 1858987da915Sopenharmony_ci 1859987da915Sopenharmony_ci curr_time(&now); 1860987da915Sopenharmony_ci if (diff_timespec(&now, &node->stat_updated) > f->conf.ac_attr_timeout) { 1861987da915Sopenharmony_ci struct stat stbuf; 1862987da915Sopenharmony_ci int err; 1863987da915Sopenharmony_ci pthread_mutex_unlock(&f->lock); 1864987da915Sopenharmony_ci err = fuse_fs_fgetattr(f->fs, path, &stbuf, fi); 1865987da915Sopenharmony_ci pthread_mutex_lock(&f->lock); 1866987da915Sopenharmony_ci if (!err) 1867987da915Sopenharmony_ci update_stat(node, &stbuf); 1868987da915Sopenharmony_ci else 1869987da915Sopenharmony_ci node->cache_valid = 0; 1870987da915Sopenharmony_ci } 1871987da915Sopenharmony_ci } 1872987da915Sopenharmony_ci if (node->cache_valid) 1873987da915Sopenharmony_ci fi->keep_cache = 1; 1874987da915Sopenharmony_ci 1875987da915Sopenharmony_ci node->cache_valid = 1; 1876987da915Sopenharmony_ci pthread_mutex_unlock(&f->lock); 1877987da915Sopenharmony_ci} 1878987da915Sopenharmony_ci 1879987da915Sopenharmony_ci#endif /* __SOLARIS__ */ 1880987da915Sopenharmony_ci 1881987da915Sopenharmony_cistatic void fuse_lib_open(fuse_req_t req, fuse_ino_t ino, 1882987da915Sopenharmony_ci struct fuse_file_info *fi) 1883987da915Sopenharmony_ci{ 1884987da915Sopenharmony_ci struct fuse *f = req_fuse_prepare(req); 1885987da915Sopenharmony_ci struct fuse_intr_data d; 1886987da915Sopenharmony_ci char *path = NULL; 1887987da915Sopenharmony_ci int err = 0; 1888987da915Sopenharmony_ci 1889987da915Sopenharmony_ci err = -ENOENT; 1890987da915Sopenharmony_ci pthread_rwlock_rdlock(&f->tree_lock); 1891987da915Sopenharmony_ci path = get_path(f, ino); 1892987da915Sopenharmony_ci if (path) { 1893987da915Sopenharmony_ci fuse_prepare_interrupt(f, req, &d); 1894987da915Sopenharmony_ci err = fuse_fs_open(f->fs, path, fi); 1895987da915Sopenharmony_ci if (!err) { 1896987da915Sopenharmony_ci if (f->conf.direct_io) 1897987da915Sopenharmony_ci fi->direct_io = 1; 1898987da915Sopenharmony_ci if (f->conf.kernel_cache) 1899987da915Sopenharmony_ci fi->keep_cache = 1; 1900987da915Sopenharmony_ci#ifdef __SOLARIS__ 1901987da915Sopenharmony_ci 1902987da915Sopenharmony_ci if (f->conf.auto_cache) 1903987da915Sopenharmony_ci open_auto_cache(f, ino, path, fi); 1904987da915Sopenharmony_ci#endif /* __SOLARIS__ */ 1905987da915Sopenharmony_ci } 1906987da915Sopenharmony_ci fuse_finish_interrupt(f, req, &d); 1907987da915Sopenharmony_ci } 1908987da915Sopenharmony_ci if (!err) { 1909987da915Sopenharmony_ci pthread_mutex_lock(&f->lock); 1910987da915Sopenharmony_ci get_node(f, ino)->open_count++; 1911987da915Sopenharmony_ci pthread_mutex_unlock(&f->lock); 1912987da915Sopenharmony_ci if (fuse_reply_open(req, fi) == -ENOENT) { 1913987da915Sopenharmony_ci /* The open syscall was interrupted, so it must be cancelled */ 1914987da915Sopenharmony_ci fuse_prepare_interrupt(f, req, &d); 1915987da915Sopenharmony_ci fuse_do_release(f, ino, path, fi); 1916987da915Sopenharmony_ci fuse_finish_interrupt(f, req, &d); 1917987da915Sopenharmony_ci } else if (f->conf.debug) { 1918987da915Sopenharmony_ci fprintf(stderr, "OPEN[%llu] flags: 0x%x %s\n", 1919987da915Sopenharmony_ci (unsigned long long) fi->fh, fi->flags, path); 1920987da915Sopenharmony_ci } 1921987da915Sopenharmony_ci } else 1922987da915Sopenharmony_ci reply_err(req, err); 1923987da915Sopenharmony_ci 1924987da915Sopenharmony_ci if (path) 1925987da915Sopenharmony_ci free(path); 1926987da915Sopenharmony_ci pthread_rwlock_unlock(&f->tree_lock); 1927987da915Sopenharmony_ci} 1928987da915Sopenharmony_ci 1929987da915Sopenharmony_cistatic void fuse_lib_read(fuse_req_t req, fuse_ino_t ino, size_t size, 1930987da915Sopenharmony_ci off_t off, struct fuse_file_info *fi) 1931987da915Sopenharmony_ci{ 1932987da915Sopenharmony_ci struct fuse *f = req_fuse_prepare(req); 1933987da915Sopenharmony_ci char *path; 1934987da915Sopenharmony_ci char *buf; 1935987da915Sopenharmony_ci int res; 1936987da915Sopenharmony_ci 1937987da915Sopenharmony_ci buf = (char *) malloc(size); 1938987da915Sopenharmony_ci if (buf == NULL) { 1939987da915Sopenharmony_ci reply_err(req, -ENOMEM); 1940987da915Sopenharmony_ci return; 1941987da915Sopenharmony_ci } 1942987da915Sopenharmony_ci 1943987da915Sopenharmony_ci res = -ENOENT; 1944987da915Sopenharmony_ci pthread_rwlock_rdlock(&f->tree_lock); 1945987da915Sopenharmony_ci path = get_path(f, ino); 1946987da915Sopenharmony_ci if (path != NULL) { 1947987da915Sopenharmony_ci struct fuse_intr_data d; 1948987da915Sopenharmony_ci if (f->conf.debug) 1949987da915Sopenharmony_ci fprintf(stderr, "READ[%llu] %lu bytes from %llu\n", 1950987da915Sopenharmony_ci (unsigned long long) fi->fh, (unsigned long) size, 1951987da915Sopenharmony_ci (unsigned long long) off); 1952987da915Sopenharmony_ci 1953987da915Sopenharmony_ci fuse_prepare_interrupt(f, req, &d); 1954987da915Sopenharmony_ci res = fuse_fs_read(f->fs, path, buf, size, off, fi); 1955987da915Sopenharmony_ci fuse_finish_interrupt(f, req, &d); 1956987da915Sopenharmony_ci free(path); 1957987da915Sopenharmony_ci } 1958987da915Sopenharmony_ci pthread_rwlock_unlock(&f->tree_lock); 1959987da915Sopenharmony_ci 1960987da915Sopenharmony_ci if (res >= 0) { 1961987da915Sopenharmony_ci if (f->conf.debug) 1962987da915Sopenharmony_ci fprintf(stderr, " READ[%llu] %u bytes\n", 1963987da915Sopenharmony_ci (unsigned long long)fi->fh, res); 1964987da915Sopenharmony_ci if ((size_t) res > size) 1965987da915Sopenharmony_ci fprintf(stderr, "fuse: read too many bytes"); 1966987da915Sopenharmony_ci fuse_reply_buf(req, buf, res); 1967987da915Sopenharmony_ci } else 1968987da915Sopenharmony_ci reply_err(req, res); 1969987da915Sopenharmony_ci 1970987da915Sopenharmony_ci free(buf); 1971987da915Sopenharmony_ci} 1972987da915Sopenharmony_ci 1973987da915Sopenharmony_cistatic void fuse_lib_write(fuse_req_t req, fuse_ino_t ino, const char *buf, 1974987da915Sopenharmony_ci size_t size, off_t off, struct fuse_file_info *fi) 1975987da915Sopenharmony_ci{ 1976987da915Sopenharmony_ci struct fuse *f = req_fuse_prepare(req); 1977987da915Sopenharmony_ci char *path; 1978987da915Sopenharmony_ci int res; 1979987da915Sopenharmony_ci 1980987da915Sopenharmony_ci res = -ENOENT; 1981987da915Sopenharmony_ci pthread_rwlock_rdlock(&f->tree_lock); 1982987da915Sopenharmony_ci path = get_path(f, ino); 1983987da915Sopenharmony_ci if (path != NULL) { 1984987da915Sopenharmony_ci struct fuse_intr_data d; 1985987da915Sopenharmony_ci if (f->conf.debug) 1986987da915Sopenharmony_ci fprintf(stderr, "WRITE%s[%llu] %lu bytes to %llu\n", 1987987da915Sopenharmony_ci fi->writepage ? "PAGE" : "", (unsigned long long) fi->fh, 1988987da915Sopenharmony_ci (unsigned long) size, (unsigned long long) off); 1989987da915Sopenharmony_ci 1990987da915Sopenharmony_ci fuse_prepare_interrupt(f, req, &d); 1991987da915Sopenharmony_ci res = fuse_fs_write(f->fs, path, buf, size, off, fi); 1992987da915Sopenharmony_ci fuse_finish_interrupt(f, req, &d); 1993987da915Sopenharmony_ci free(path); 1994987da915Sopenharmony_ci } 1995987da915Sopenharmony_ci pthread_rwlock_unlock(&f->tree_lock); 1996987da915Sopenharmony_ci 1997987da915Sopenharmony_ci if (res >= 0) { 1998987da915Sopenharmony_ci if (f->conf.debug) 1999987da915Sopenharmony_ci fprintf(stderr, " WRITE%s[%llu] %u bytes\n", 2000987da915Sopenharmony_ci fi->writepage ? "PAGE" : "", (unsigned long long) fi->fh, 2001987da915Sopenharmony_ci res); 2002987da915Sopenharmony_ci if ((size_t) res > size) 2003987da915Sopenharmony_ci fprintf(stderr, "fuse: wrote too many bytes"); 2004987da915Sopenharmony_ci fuse_reply_write(req, res); 2005987da915Sopenharmony_ci } else 2006987da915Sopenharmony_ci reply_err(req, res); 2007987da915Sopenharmony_ci} 2008987da915Sopenharmony_ci 2009987da915Sopenharmony_cistatic void fuse_lib_fsync(fuse_req_t req, fuse_ino_t ino, int datasync, 2010987da915Sopenharmony_ci struct fuse_file_info *fi) 2011987da915Sopenharmony_ci{ 2012987da915Sopenharmony_ci struct fuse *f = req_fuse_prepare(req); 2013987da915Sopenharmony_ci char *path; 2014987da915Sopenharmony_ci int err; 2015987da915Sopenharmony_ci 2016987da915Sopenharmony_ci err = -ENOENT; 2017987da915Sopenharmony_ci pthread_rwlock_rdlock(&f->tree_lock); 2018987da915Sopenharmony_ci path = get_path(f, ino); 2019987da915Sopenharmony_ci if (path != NULL) { 2020987da915Sopenharmony_ci struct fuse_intr_data d; 2021987da915Sopenharmony_ci if (f->conf.debug) 2022987da915Sopenharmony_ci fprintf(stderr, "FSYNC[%llu]\n", (unsigned long long) fi->fh); 2023987da915Sopenharmony_ci fuse_prepare_interrupt(f, req, &d); 2024987da915Sopenharmony_ci err = fuse_fs_fsync(f->fs, path, datasync, fi); 2025987da915Sopenharmony_ci fuse_finish_interrupt(f, req, &d); 2026987da915Sopenharmony_ci free(path); 2027987da915Sopenharmony_ci } 2028987da915Sopenharmony_ci pthread_rwlock_unlock(&f->tree_lock); 2029987da915Sopenharmony_ci reply_err(req, err); 2030987da915Sopenharmony_ci} 2031987da915Sopenharmony_ci 2032987da915Sopenharmony_cistatic struct fuse_dh *get_dirhandle(const struct fuse_file_info *llfi, 2033987da915Sopenharmony_ci struct fuse_file_info *fi) 2034987da915Sopenharmony_ci{ 2035987da915Sopenharmony_ci struct fuse_dh *dh = (struct fuse_dh *) (uintptr_t) llfi->fh; 2036987da915Sopenharmony_ci memset(fi, 0, sizeof(struct fuse_file_info)); 2037987da915Sopenharmony_ci fi->fh = dh->fh; 2038987da915Sopenharmony_ci fi->fh_old = dh->fh; 2039987da915Sopenharmony_ci return dh; 2040987da915Sopenharmony_ci} 2041987da915Sopenharmony_ci 2042987da915Sopenharmony_cistatic void fuse_lib_opendir(fuse_req_t req, fuse_ino_t ino, 2043987da915Sopenharmony_ci struct fuse_file_info *llfi) 2044987da915Sopenharmony_ci{ 2045987da915Sopenharmony_ci struct fuse *f = req_fuse_prepare(req); 2046987da915Sopenharmony_ci struct fuse_intr_data d; 2047987da915Sopenharmony_ci struct fuse_dh *dh; 2048987da915Sopenharmony_ci struct fuse_file_info fi; 2049987da915Sopenharmony_ci char *path; 2050987da915Sopenharmony_ci int err; 2051987da915Sopenharmony_ci 2052987da915Sopenharmony_ci dh = (struct fuse_dh *) malloc(sizeof(struct fuse_dh)); 2053987da915Sopenharmony_ci if (dh == NULL) { 2054987da915Sopenharmony_ci reply_err(req, -ENOMEM); 2055987da915Sopenharmony_ci return; 2056987da915Sopenharmony_ci } 2057987da915Sopenharmony_ci memset(dh, 0, sizeof(struct fuse_dh)); 2058987da915Sopenharmony_ci dh->fuse = f; 2059987da915Sopenharmony_ci dh->contents = NULL; 2060987da915Sopenharmony_ci dh->len = 0; 2061987da915Sopenharmony_ci dh->filled = 0; 2062987da915Sopenharmony_ci dh->nodeid = ino; 2063987da915Sopenharmony_ci fuse_mutex_init(&dh->lock); 2064987da915Sopenharmony_ci 2065987da915Sopenharmony_ci llfi->fh = (uintptr_t) dh; 2066987da915Sopenharmony_ci 2067987da915Sopenharmony_ci memset(&fi, 0, sizeof(fi)); 2068987da915Sopenharmony_ci fi.flags = llfi->flags; 2069987da915Sopenharmony_ci 2070987da915Sopenharmony_ci err = -ENOENT; 2071987da915Sopenharmony_ci pthread_rwlock_rdlock(&f->tree_lock); 2072987da915Sopenharmony_ci path = get_path(f, ino); 2073987da915Sopenharmony_ci if (path != NULL) { 2074987da915Sopenharmony_ci fuse_prepare_interrupt(f, req, &d); 2075987da915Sopenharmony_ci err = fuse_fs_opendir(f->fs, path, &fi); 2076987da915Sopenharmony_ci fuse_finish_interrupt(f, req, &d); 2077987da915Sopenharmony_ci dh->fh = fi.fh; 2078987da915Sopenharmony_ci } 2079987da915Sopenharmony_ci if (!err) { 2080987da915Sopenharmony_ci if (fuse_reply_open(req, llfi) == -ENOENT) { 2081987da915Sopenharmony_ci /* The opendir syscall was interrupted, so it must be cancelled */ 2082987da915Sopenharmony_ci fuse_prepare_interrupt(f, req, &d); 2083987da915Sopenharmony_ci fuse_fs_releasedir(f->fs, path, &fi); 2084987da915Sopenharmony_ci fuse_finish_interrupt(f, req, &d); 2085987da915Sopenharmony_ci pthread_mutex_destroy(&dh->lock); 2086987da915Sopenharmony_ci free(dh); 2087987da915Sopenharmony_ci } 2088987da915Sopenharmony_ci } else { 2089987da915Sopenharmony_ci reply_err(req, err); 2090987da915Sopenharmony_ci pthread_mutex_destroy(&dh->lock); 2091987da915Sopenharmony_ci free(dh); 2092987da915Sopenharmony_ci } 2093987da915Sopenharmony_ci free(path); 2094987da915Sopenharmony_ci pthread_rwlock_unlock(&f->tree_lock); 2095987da915Sopenharmony_ci} 2096987da915Sopenharmony_ci 2097987da915Sopenharmony_cistatic int extend_contents(struct fuse_dh *dh, unsigned minsize) 2098987da915Sopenharmony_ci{ 2099987da915Sopenharmony_ci if (minsize > dh->size) { 2100987da915Sopenharmony_ci char *newptr; 2101987da915Sopenharmony_ci unsigned newsize = dh->size; 2102987da915Sopenharmony_ci if (!newsize) 2103987da915Sopenharmony_ci newsize = 1024; 2104987da915Sopenharmony_ci#ifndef __SOLARIS__ 2105987da915Sopenharmony_ci while (newsize < minsize) { 2106987da915Sopenharmony_ci if (newsize >= 0x80000000) 2107987da915Sopenharmony_ci newsize = 0xffffffff; 2108987da915Sopenharmony_ci else 2109987da915Sopenharmony_ci newsize *= 2; 2110987da915Sopenharmony_ci } 2111987da915Sopenharmony_ci#else /* __SOLARIS__ */ 2112987da915Sopenharmony_ci while (newsize < minsize) 2113987da915Sopenharmony_ci newsize *= 2; 2114987da915Sopenharmony_ci#endif /* __SOLARIS__ */ 2115987da915Sopenharmony_ci 2116987da915Sopenharmony_ci newptr = (char *) realloc(dh->contents, newsize); 2117987da915Sopenharmony_ci if (!newptr) { 2118987da915Sopenharmony_ci dh->error = -ENOMEM; 2119987da915Sopenharmony_ci return -1; 2120987da915Sopenharmony_ci } 2121987da915Sopenharmony_ci dh->contents = newptr; 2122987da915Sopenharmony_ci dh->size = newsize; 2123987da915Sopenharmony_ci } 2124987da915Sopenharmony_ci return 0; 2125987da915Sopenharmony_ci} 2126987da915Sopenharmony_ci 2127987da915Sopenharmony_cistatic int fill_dir(void *dh_, const char *name, const struct stat *statp, 2128987da915Sopenharmony_ci off_t off) 2129987da915Sopenharmony_ci{ 2130987da915Sopenharmony_ci struct fuse_dh *dh = (struct fuse_dh *) dh_; 2131987da915Sopenharmony_ci struct stat stbuf; 2132987da915Sopenharmony_ci size_t newlen; 2133987da915Sopenharmony_ci 2134987da915Sopenharmony_ci if (statp) 2135987da915Sopenharmony_ci stbuf = *statp; 2136987da915Sopenharmony_ci else { 2137987da915Sopenharmony_ci memset(&stbuf, 0, sizeof(stbuf)); 2138987da915Sopenharmony_ci stbuf.st_ino = FUSE_UNKNOWN_INO; 2139987da915Sopenharmony_ci } 2140987da915Sopenharmony_ci 2141987da915Sopenharmony_ci if (!dh->fuse->conf.use_ino) { 2142987da915Sopenharmony_ci stbuf.st_ino = FUSE_UNKNOWN_INO; 2143987da915Sopenharmony_ci if (dh->fuse->conf.readdir_ino) { 2144987da915Sopenharmony_ci struct node *node; 2145987da915Sopenharmony_ci pthread_mutex_lock(&dh->fuse->lock); 2146987da915Sopenharmony_ci node = lookup_node(dh->fuse, dh->nodeid, name); 2147987da915Sopenharmony_ci if (node) 2148987da915Sopenharmony_ci stbuf.st_ino = (ino_t) node->nodeid; 2149987da915Sopenharmony_ci pthread_mutex_unlock(&dh->fuse->lock); 2150987da915Sopenharmony_ci } 2151987da915Sopenharmony_ci } 2152987da915Sopenharmony_ci 2153987da915Sopenharmony_ci if (off) { 2154987da915Sopenharmony_ci if (extend_contents(dh, dh->needlen) == -1) 2155987da915Sopenharmony_ci return 1; 2156987da915Sopenharmony_ci 2157987da915Sopenharmony_ci dh->filled = 0; 2158987da915Sopenharmony_ci newlen = dh->len + fuse_add_direntry(dh->req, dh->contents + dh->len, 2159987da915Sopenharmony_ci dh->needlen - dh->len, name, 2160987da915Sopenharmony_ci &stbuf, off); 2161987da915Sopenharmony_ci if (newlen > dh->needlen) 2162987da915Sopenharmony_ci return 1; 2163987da915Sopenharmony_ci } else { 2164987da915Sopenharmony_ci newlen = dh->len + fuse_add_direntry(dh->req, NULL, 0, name, NULL, 0); 2165987da915Sopenharmony_ci if (extend_contents(dh, newlen) == -1) 2166987da915Sopenharmony_ci return 1; 2167987da915Sopenharmony_ci 2168987da915Sopenharmony_ci fuse_add_direntry(dh->req, dh->contents + dh->len, dh->size - dh->len, 2169987da915Sopenharmony_ci name, &stbuf, newlen); 2170987da915Sopenharmony_ci } 2171987da915Sopenharmony_ci dh->len = newlen; 2172987da915Sopenharmony_ci return 0; 2173987da915Sopenharmony_ci} 2174987da915Sopenharmony_ci 2175987da915Sopenharmony_cistatic int readdir_fill(struct fuse *f, fuse_req_t req, fuse_ino_t ino, 2176987da915Sopenharmony_ci size_t size, off_t off, struct fuse_dh *dh, 2177987da915Sopenharmony_ci struct fuse_file_info *fi) 2178987da915Sopenharmony_ci{ 2179987da915Sopenharmony_ci int err = -ENOENT; 2180987da915Sopenharmony_ci char *path; 2181987da915Sopenharmony_ci pthread_rwlock_rdlock(&f->tree_lock); 2182987da915Sopenharmony_ci path = get_path(f, ino); 2183987da915Sopenharmony_ci if (path != NULL) { 2184987da915Sopenharmony_ci struct fuse_intr_data d; 2185987da915Sopenharmony_ci 2186987da915Sopenharmony_ci dh->len = 0; 2187987da915Sopenharmony_ci dh->error = 0; 2188987da915Sopenharmony_ci dh->needlen = size; 2189987da915Sopenharmony_ci dh->filled = 1; 2190987da915Sopenharmony_ci dh->req = req; 2191987da915Sopenharmony_ci fuse_prepare_interrupt(f, req, &d); 2192987da915Sopenharmony_ci err = fuse_fs_readdir(f->fs, path, dh, fill_dir, off, fi); 2193987da915Sopenharmony_ci fuse_finish_interrupt(f, req, &d); 2194987da915Sopenharmony_ci dh->req = NULL; 2195987da915Sopenharmony_ci if (!err) 2196987da915Sopenharmony_ci err = dh->error; 2197987da915Sopenharmony_ci if (err) 2198987da915Sopenharmony_ci dh->filled = 0; 2199987da915Sopenharmony_ci free(path); 2200987da915Sopenharmony_ci } 2201987da915Sopenharmony_ci pthread_rwlock_unlock(&f->tree_lock); 2202987da915Sopenharmony_ci return err; 2203987da915Sopenharmony_ci} 2204987da915Sopenharmony_ci 2205987da915Sopenharmony_cistatic void fuse_lib_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, 2206987da915Sopenharmony_ci off_t off, struct fuse_file_info *llfi) 2207987da915Sopenharmony_ci{ 2208987da915Sopenharmony_ci struct fuse *f = req_fuse_prepare(req); 2209987da915Sopenharmony_ci struct fuse_file_info fi; 2210987da915Sopenharmony_ci struct fuse_dh *dh = get_dirhandle(llfi, &fi); 2211987da915Sopenharmony_ci 2212987da915Sopenharmony_ci pthread_mutex_lock(&dh->lock); 2213987da915Sopenharmony_ci /* According to SUS, directory contents need to be refreshed on 2214987da915Sopenharmony_ci rewinddir() */ 2215987da915Sopenharmony_ci if (!off) 2216987da915Sopenharmony_ci dh->filled = 0; 2217987da915Sopenharmony_ci 2218987da915Sopenharmony_ci if (!dh->filled) { 2219987da915Sopenharmony_ci int err = readdir_fill(f, req, ino, size, off, dh, &fi); 2220987da915Sopenharmony_ci if (err) { 2221987da915Sopenharmony_ci reply_err(req, err); 2222987da915Sopenharmony_ci goto out; 2223987da915Sopenharmony_ci } 2224987da915Sopenharmony_ci } 2225987da915Sopenharmony_ci if (dh->filled) { 2226987da915Sopenharmony_ci if ((off >= 0) && (off < dh->len)) { 2227987da915Sopenharmony_ci if (off + size > dh->len) 2228987da915Sopenharmony_ci size = dh->len - off; 2229987da915Sopenharmony_ci } else 2230987da915Sopenharmony_ci size = 0; 2231987da915Sopenharmony_ci } else { 2232987da915Sopenharmony_ci size = dh->len; 2233987da915Sopenharmony_ci off = 0; 2234987da915Sopenharmony_ci } 2235987da915Sopenharmony_ci fuse_reply_buf(req, dh->contents + off, size); 2236987da915Sopenharmony_ci out: 2237987da915Sopenharmony_ci pthread_mutex_unlock(&dh->lock); 2238987da915Sopenharmony_ci} 2239987da915Sopenharmony_ci 2240987da915Sopenharmony_cistatic void fuse_lib_releasedir(fuse_req_t req, fuse_ino_t ino, 2241987da915Sopenharmony_ci struct fuse_file_info *llfi) 2242987da915Sopenharmony_ci{ 2243987da915Sopenharmony_ci struct fuse *f = req_fuse_prepare(req); 2244987da915Sopenharmony_ci struct fuse_intr_data d; 2245987da915Sopenharmony_ci struct fuse_file_info fi; 2246987da915Sopenharmony_ci struct fuse_dh *dh = get_dirhandle(llfi, &fi); 2247987da915Sopenharmony_ci char *path; 2248987da915Sopenharmony_ci 2249987da915Sopenharmony_ci pthread_rwlock_rdlock(&f->tree_lock); 2250987da915Sopenharmony_ci path = get_path(f, ino); 2251987da915Sopenharmony_ci fuse_prepare_interrupt(f, req, &d); 2252987da915Sopenharmony_ci fuse_fs_releasedir(f->fs, path ? path : "-", &fi); 2253987da915Sopenharmony_ci fuse_finish_interrupt(f, req, &d); 2254987da915Sopenharmony_ci if (path) 2255987da915Sopenharmony_ci free(path); 2256987da915Sopenharmony_ci pthread_rwlock_unlock(&f->tree_lock); 2257987da915Sopenharmony_ci pthread_mutex_lock(&dh->lock); 2258987da915Sopenharmony_ci pthread_mutex_unlock(&dh->lock); 2259987da915Sopenharmony_ci pthread_mutex_destroy(&dh->lock); 2260987da915Sopenharmony_ci free(dh->contents); 2261987da915Sopenharmony_ci free(dh); 2262987da915Sopenharmony_ci reply_err(req, 0); 2263987da915Sopenharmony_ci} 2264987da915Sopenharmony_ci 2265987da915Sopenharmony_cistatic void fuse_lib_fsyncdir(fuse_req_t req, fuse_ino_t ino, int datasync, 2266987da915Sopenharmony_ci struct fuse_file_info *llfi) 2267987da915Sopenharmony_ci{ 2268987da915Sopenharmony_ci struct fuse *f = req_fuse_prepare(req); 2269987da915Sopenharmony_ci struct fuse_file_info fi; 2270987da915Sopenharmony_ci char *path; 2271987da915Sopenharmony_ci int err; 2272987da915Sopenharmony_ci 2273987da915Sopenharmony_ci get_dirhandle(llfi, &fi); 2274987da915Sopenharmony_ci 2275987da915Sopenharmony_ci err = -ENOENT; 2276987da915Sopenharmony_ci pthread_rwlock_rdlock(&f->tree_lock); 2277987da915Sopenharmony_ci path = get_path(f, ino); 2278987da915Sopenharmony_ci if (path != NULL) { 2279987da915Sopenharmony_ci struct fuse_intr_data d; 2280987da915Sopenharmony_ci fuse_prepare_interrupt(f, req, &d); 2281987da915Sopenharmony_ci err = fuse_fs_fsyncdir(f->fs, path, datasync, &fi); 2282987da915Sopenharmony_ci fuse_finish_interrupt(f, req, &d); 2283987da915Sopenharmony_ci free(path); 2284987da915Sopenharmony_ci } 2285987da915Sopenharmony_ci pthread_rwlock_unlock(&f->tree_lock); 2286987da915Sopenharmony_ci reply_err(req, err); 2287987da915Sopenharmony_ci} 2288987da915Sopenharmony_ci 2289987da915Sopenharmony_cistatic void fuse_lib_statfs(fuse_req_t req, fuse_ino_t ino) 2290987da915Sopenharmony_ci{ 2291987da915Sopenharmony_ci struct fuse *f = req_fuse_prepare(req); 2292987da915Sopenharmony_ci struct statvfs buf; 2293987da915Sopenharmony_ci char *path; 2294987da915Sopenharmony_ci int err; 2295987da915Sopenharmony_ci 2296987da915Sopenharmony_ci memset(&buf, 0, sizeof(buf)); 2297987da915Sopenharmony_ci pthread_rwlock_rdlock(&f->tree_lock); 2298987da915Sopenharmony_ci if (!ino) { 2299987da915Sopenharmony_ci err = -ENOMEM; 2300987da915Sopenharmony_ci path = strdup("/"); 2301987da915Sopenharmony_ci } else { 2302987da915Sopenharmony_ci err = -ENOENT; 2303987da915Sopenharmony_ci path = get_path(f, ino); 2304987da915Sopenharmony_ci } 2305987da915Sopenharmony_ci if (path) { 2306987da915Sopenharmony_ci struct fuse_intr_data d; 2307987da915Sopenharmony_ci fuse_prepare_interrupt(f, req, &d); 2308987da915Sopenharmony_ci err = fuse_fs_statfs(f->fs, path, &buf); 2309987da915Sopenharmony_ci fuse_finish_interrupt(f, req, &d); 2310987da915Sopenharmony_ci free(path); 2311987da915Sopenharmony_ci } 2312987da915Sopenharmony_ci pthread_rwlock_unlock(&f->tree_lock); 2313987da915Sopenharmony_ci 2314987da915Sopenharmony_ci if (!err) 2315987da915Sopenharmony_ci fuse_reply_statfs(req, &buf); 2316987da915Sopenharmony_ci else 2317987da915Sopenharmony_ci reply_err(req, err); 2318987da915Sopenharmony_ci} 2319987da915Sopenharmony_ci 2320987da915Sopenharmony_cistatic void fuse_lib_setxattr(fuse_req_t req, fuse_ino_t ino, const char *name, 2321987da915Sopenharmony_ci const char *value, size_t size, int flags) 2322987da915Sopenharmony_ci{ 2323987da915Sopenharmony_ci struct fuse *f = req_fuse_prepare(req); 2324987da915Sopenharmony_ci char *path; 2325987da915Sopenharmony_ci int err; 2326987da915Sopenharmony_ci 2327987da915Sopenharmony_ci err = -ENOENT; 2328987da915Sopenharmony_ci pthread_rwlock_rdlock(&f->tree_lock); 2329987da915Sopenharmony_ci path = get_path(f, ino); 2330987da915Sopenharmony_ci if (path != NULL) { 2331987da915Sopenharmony_ci struct fuse_intr_data d; 2332987da915Sopenharmony_ci fuse_prepare_interrupt(f, req, &d); 2333987da915Sopenharmony_ci err = fuse_fs_setxattr(f->fs, path, name, value, size, flags); 2334987da915Sopenharmony_ci fuse_finish_interrupt(f, req, &d); 2335987da915Sopenharmony_ci free(path); 2336987da915Sopenharmony_ci } 2337987da915Sopenharmony_ci pthread_rwlock_unlock(&f->tree_lock); 2338987da915Sopenharmony_ci reply_err(req, err); 2339987da915Sopenharmony_ci} 2340987da915Sopenharmony_ci 2341987da915Sopenharmony_cistatic int common_getxattr(struct fuse *f, fuse_req_t req, fuse_ino_t ino, 2342987da915Sopenharmony_ci const char *name, char *value, size_t size) 2343987da915Sopenharmony_ci{ 2344987da915Sopenharmony_ci int err; 2345987da915Sopenharmony_ci char *path; 2346987da915Sopenharmony_ci 2347987da915Sopenharmony_ci err = -ENOENT; 2348987da915Sopenharmony_ci pthread_rwlock_rdlock(&f->tree_lock); 2349987da915Sopenharmony_ci path = get_path(f, ino); 2350987da915Sopenharmony_ci if (path != NULL) { 2351987da915Sopenharmony_ci struct fuse_intr_data d; 2352987da915Sopenharmony_ci fuse_prepare_interrupt(f, req, &d); 2353987da915Sopenharmony_ci err = fuse_fs_getxattr(f->fs, path, name, value, size); 2354987da915Sopenharmony_ci fuse_finish_interrupt(f, req, &d); 2355987da915Sopenharmony_ci free(path); 2356987da915Sopenharmony_ci } 2357987da915Sopenharmony_ci pthread_rwlock_unlock(&f->tree_lock); 2358987da915Sopenharmony_ci return err; 2359987da915Sopenharmony_ci} 2360987da915Sopenharmony_ci 2361987da915Sopenharmony_cistatic void fuse_lib_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name, 2362987da915Sopenharmony_ci size_t size) 2363987da915Sopenharmony_ci{ 2364987da915Sopenharmony_ci struct fuse *f = req_fuse_prepare(req); 2365987da915Sopenharmony_ci int res; 2366987da915Sopenharmony_ci 2367987da915Sopenharmony_ci if (size) { 2368987da915Sopenharmony_ci char *value = (char *) malloc(size); 2369987da915Sopenharmony_ci if (value == NULL) { 2370987da915Sopenharmony_ci reply_err(req, -ENOMEM); 2371987da915Sopenharmony_ci return; 2372987da915Sopenharmony_ci } 2373987da915Sopenharmony_ci res = common_getxattr(f, req, ino, name, value, size); 2374987da915Sopenharmony_ci if (res > 0) 2375987da915Sopenharmony_ci fuse_reply_buf(req, value, res); 2376987da915Sopenharmony_ci else 2377987da915Sopenharmony_ci reply_err(req, res); 2378987da915Sopenharmony_ci free(value); 2379987da915Sopenharmony_ci } else { 2380987da915Sopenharmony_ci res = common_getxattr(f, req, ino, name, NULL, 0); 2381987da915Sopenharmony_ci if (res >= 0) 2382987da915Sopenharmony_ci fuse_reply_xattr(req, res); 2383987da915Sopenharmony_ci else 2384987da915Sopenharmony_ci reply_err(req, res); 2385987da915Sopenharmony_ci } 2386987da915Sopenharmony_ci} 2387987da915Sopenharmony_ci 2388987da915Sopenharmony_cistatic int common_listxattr(struct fuse *f, fuse_req_t req, fuse_ino_t ino, 2389987da915Sopenharmony_ci char *list, size_t size) 2390987da915Sopenharmony_ci{ 2391987da915Sopenharmony_ci char *path; 2392987da915Sopenharmony_ci int err; 2393987da915Sopenharmony_ci 2394987da915Sopenharmony_ci err = -ENOENT; 2395987da915Sopenharmony_ci pthread_rwlock_rdlock(&f->tree_lock); 2396987da915Sopenharmony_ci path = get_path(f, ino); 2397987da915Sopenharmony_ci if (path != NULL) { 2398987da915Sopenharmony_ci struct fuse_intr_data d; 2399987da915Sopenharmony_ci fuse_prepare_interrupt(f, req, &d); 2400987da915Sopenharmony_ci err = fuse_fs_listxattr(f->fs, path, list, size); 2401987da915Sopenharmony_ci fuse_finish_interrupt(f, req, &d); 2402987da915Sopenharmony_ci free(path); 2403987da915Sopenharmony_ci } 2404987da915Sopenharmony_ci pthread_rwlock_unlock(&f->tree_lock); 2405987da915Sopenharmony_ci return err; 2406987da915Sopenharmony_ci} 2407987da915Sopenharmony_ci 2408987da915Sopenharmony_cistatic void fuse_lib_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size) 2409987da915Sopenharmony_ci{ 2410987da915Sopenharmony_ci struct fuse *f = req_fuse_prepare(req); 2411987da915Sopenharmony_ci int res; 2412987da915Sopenharmony_ci 2413987da915Sopenharmony_ci if (size) { 2414987da915Sopenharmony_ci char *list = (char *) malloc(size); 2415987da915Sopenharmony_ci if (list == NULL) { 2416987da915Sopenharmony_ci reply_err(req, -ENOMEM); 2417987da915Sopenharmony_ci return; 2418987da915Sopenharmony_ci } 2419987da915Sopenharmony_ci res = common_listxattr(f, req, ino, list, size); 2420987da915Sopenharmony_ci if (res > 0) 2421987da915Sopenharmony_ci fuse_reply_buf(req, list, res); 2422987da915Sopenharmony_ci else 2423987da915Sopenharmony_ci reply_err(req, res); 2424987da915Sopenharmony_ci free(list); 2425987da915Sopenharmony_ci } else { 2426987da915Sopenharmony_ci res = common_listxattr(f, req, ino, NULL, 0); 2427987da915Sopenharmony_ci if (res >= 0) 2428987da915Sopenharmony_ci fuse_reply_xattr(req, res); 2429987da915Sopenharmony_ci else 2430987da915Sopenharmony_ci reply_err(req, res); 2431987da915Sopenharmony_ci } 2432987da915Sopenharmony_ci} 2433987da915Sopenharmony_ci 2434987da915Sopenharmony_cistatic void fuse_lib_removexattr(fuse_req_t req, fuse_ino_t ino, 2435987da915Sopenharmony_ci const char *name) 2436987da915Sopenharmony_ci{ 2437987da915Sopenharmony_ci struct fuse *f = req_fuse_prepare(req); 2438987da915Sopenharmony_ci char *path; 2439987da915Sopenharmony_ci int err; 2440987da915Sopenharmony_ci 2441987da915Sopenharmony_ci err = -ENOENT; 2442987da915Sopenharmony_ci pthread_rwlock_rdlock(&f->tree_lock); 2443987da915Sopenharmony_ci path = get_path(f, ino); 2444987da915Sopenharmony_ci if (path != NULL) { 2445987da915Sopenharmony_ci struct fuse_intr_data d; 2446987da915Sopenharmony_ci fuse_prepare_interrupt(f, req, &d); 2447987da915Sopenharmony_ci err = fuse_fs_removexattr(f->fs, path, name); 2448987da915Sopenharmony_ci fuse_finish_interrupt(f, req, &d); 2449987da915Sopenharmony_ci free(path); 2450987da915Sopenharmony_ci } 2451987da915Sopenharmony_ci pthread_rwlock_unlock(&f->tree_lock); 2452987da915Sopenharmony_ci reply_err(req, err); 2453987da915Sopenharmony_ci} 2454987da915Sopenharmony_ci 2455987da915Sopenharmony_cistatic struct lock *locks_conflict(struct node *node, const struct lock *lock) 2456987da915Sopenharmony_ci{ 2457987da915Sopenharmony_ci struct lock *l; 2458987da915Sopenharmony_ci 2459987da915Sopenharmony_ci for (l = node->locks; l; l = l->next) 2460987da915Sopenharmony_ci if (l->owner != lock->owner && 2461987da915Sopenharmony_ci lock->start <= l->end && l->start <= lock->end && 2462987da915Sopenharmony_ci (l->type == F_WRLCK || lock->type == F_WRLCK)) 2463987da915Sopenharmony_ci break; 2464987da915Sopenharmony_ci 2465987da915Sopenharmony_ci return l; 2466987da915Sopenharmony_ci} 2467987da915Sopenharmony_ci 2468987da915Sopenharmony_cistatic void delete_lock(struct lock **lockp) 2469987da915Sopenharmony_ci{ 2470987da915Sopenharmony_ci struct lock *l = *lockp; 2471987da915Sopenharmony_ci *lockp = l->next; 2472987da915Sopenharmony_ci free(l); 2473987da915Sopenharmony_ci} 2474987da915Sopenharmony_ci 2475987da915Sopenharmony_cistatic void insert_lock(struct lock **pos, struct lock *lock) 2476987da915Sopenharmony_ci{ 2477987da915Sopenharmony_ci lock->next = *pos; 2478987da915Sopenharmony_ci *pos = lock; 2479987da915Sopenharmony_ci} 2480987da915Sopenharmony_ci 2481987da915Sopenharmony_cistatic int locks_insert(struct node *node, struct lock *lock) 2482987da915Sopenharmony_ci{ 2483987da915Sopenharmony_ci struct lock **lp; 2484987da915Sopenharmony_ci struct lock *newl1 = NULL; 2485987da915Sopenharmony_ci struct lock *newl2 = NULL; 2486987da915Sopenharmony_ci 2487987da915Sopenharmony_ci if (lock->type != F_UNLCK || lock->start != 0 || lock->end != OFFSET_MAX) { 2488987da915Sopenharmony_ci newl1 = malloc(sizeof(struct lock)); 2489987da915Sopenharmony_ci newl2 = malloc(sizeof(struct lock)); 2490987da915Sopenharmony_ci 2491987da915Sopenharmony_ci if (!newl1 || !newl2) { 2492987da915Sopenharmony_ci free(newl1); 2493987da915Sopenharmony_ci free(newl2); 2494987da915Sopenharmony_ci return -ENOLCK; 2495987da915Sopenharmony_ci } 2496987da915Sopenharmony_ci } 2497987da915Sopenharmony_ci 2498987da915Sopenharmony_ci for (lp = &node->locks; *lp;) { 2499987da915Sopenharmony_ci struct lock *l = *lp; 2500987da915Sopenharmony_ci if (l->owner != lock->owner) 2501987da915Sopenharmony_ci goto skip; 2502987da915Sopenharmony_ci 2503987da915Sopenharmony_ci if (lock->type == l->type) { 2504987da915Sopenharmony_ci if (l->end < lock->start - 1) 2505987da915Sopenharmony_ci goto skip; 2506987da915Sopenharmony_ci if (lock->end < l->start - 1) 2507987da915Sopenharmony_ci break; 2508987da915Sopenharmony_ci if (l->start <= lock->start && lock->end <= l->end) 2509987da915Sopenharmony_ci goto out; 2510987da915Sopenharmony_ci if (l->start < lock->start) 2511987da915Sopenharmony_ci lock->start = l->start; 2512987da915Sopenharmony_ci if (lock->end < l->end) 2513987da915Sopenharmony_ci lock->end = l->end; 2514987da915Sopenharmony_ci goto delete; 2515987da915Sopenharmony_ci } else { 2516987da915Sopenharmony_ci if (l->end < lock->start) 2517987da915Sopenharmony_ci goto skip; 2518987da915Sopenharmony_ci if (lock->end < l->start) 2519987da915Sopenharmony_ci break; 2520987da915Sopenharmony_ci if (lock->start <= l->start && l->end <= lock->end) 2521987da915Sopenharmony_ci goto delete; 2522987da915Sopenharmony_ci if (l->end <= lock->end) { 2523987da915Sopenharmony_ci l->end = lock->start - 1; 2524987da915Sopenharmony_ci goto skip; 2525987da915Sopenharmony_ci } 2526987da915Sopenharmony_ci if (lock->start <= l->start) { 2527987da915Sopenharmony_ci l->start = lock->end + 1; 2528987da915Sopenharmony_ci break; 2529987da915Sopenharmony_ci } 2530987da915Sopenharmony_ci *newl2 = *l; 2531987da915Sopenharmony_ci newl2->start = lock->end + 1; 2532987da915Sopenharmony_ci l->end = lock->start - 1; 2533987da915Sopenharmony_ci insert_lock(&l->next, newl2); 2534987da915Sopenharmony_ci newl2 = NULL; 2535987da915Sopenharmony_ci } 2536987da915Sopenharmony_ci skip: 2537987da915Sopenharmony_ci lp = &l->next; 2538987da915Sopenharmony_ci continue; 2539987da915Sopenharmony_ci 2540987da915Sopenharmony_ci delete: 2541987da915Sopenharmony_ci delete_lock(lp); 2542987da915Sopenharmony_ci } 2543987da915Sopenharmony_ci if (lock->type != F_UNLCK) { 2544987da915Sopenharmony_ci *newl1 = *lock; 2545987da915Sopenharmony_ci insert_lock(lp, newl1); 2546987da915Sopenharmony_ci newl1 = NULL; 2547987da915Sopenharmony_ci } 2548987da915Sopenharmony_ciout: 2549987da915Sopenharmony_ci free(newl1); 2550987da915Sopenharmony_ci free(newl2); 2551987da915Sopenharmony_ci return 0; 2552987da915Sopenharmony_ci} 2553987da915Sopenharmony_ci 2554987da915Sopenharmony_cistatic void flock_to_lock(struct flock *flock, struct lock *lock) 2555987da915Sopenharmony_ci{ 2556987da915Sopenharmony_ci memset(lock, 0, sizeof(struct lock)); 2557987da915Sopenharmony_ci lock->type = flock->l_type; 2558987da915Sopenharmony_ci lock->start = flock->l_start; 2559987da915Sopenharmony_ci lock->end = flock->l_len ? flock->l_start + flock->l_len - 1 : OFFSET_MAX; 2560987da915Sopenharmony_ci lock->pid = flock->l_pid; 2561987da915Sopenharmony_ci} 2562987da915Sopenharmony_ci 2563987da915Sopenharmony_cistatic void lock_to_flock(struct lock *lock, struct flock *flock) 2564987da915Sopenharmony_ci{ 2565987da915Sopenharmony_ci flock->l_type = lock->type; 2566987da915Sopenharmony_ci flock->l_start = lock->start; 2567987da915Sopenharmony_ci flock->l_len = (lock->end == OFFSET_MAX) ? 0 : lock->end - lock->start + 1; 2568987da915Sopenharmony_ci flock->l_pid = lock->pid; 2569987da915Sopenharmony_ci} 2570987da915Sopenharmony_ci 2571987da915Sopenharmony_cistatic int fuse_flush_common(struct fuse *f, fuse_req_t req, fuse_ino_t ino, 2572987da915Sopenharmony_ci const char *path, struct fuse_file_info *fi) 2573987da915Sopenharmony_ci{ 2574987da915Sopenharmony_ci struct fuse_intr_data d; 2575987da915Sopenharmony_ci struct flock lock; 2576987da915Sopenharmony_ci struct lock l; 2577987da915Sopenharmony_ci int err; 2578987da915Sopenharmony_ci int errlock; 2579987da915Sopenharmony_ci 2580987da915Sopenharmony_ci fuse_prepare_interrupt(f, req, &d); 2581987da915Sopenharmony_ci memset(&lock, 0, sizeof(lock)); 2582987da915Sopenharmony_ci lock.l_type = F_UNLCK; 2583987da915Sopenharmony_ci lock.l_whence = SEEK_SET; 2584987da915Sopenharmony_ci err = fuse_fs_flush(f->fs, path, fi); 2585987da915Sopenharmony_ci errlock = fuse_fs_lock(f->fs, path, fi, F_SETLK, &lock); 2586987da915Sopenharmony_ci fuse_finish_interrupt(f, req, &d); 2587987da915Sopenharmony_ci 2588987da915Sopenharmony_ci if (errlock != -ENOSYS) { 2589987da915Sopenharmony_ci flock_to_lock(&lock, &l); 2590987da915Sopenharmony_ci l.owner = fi->lock_owner; 2591987da915Sopenharmony_ci pthread_mutex_lock(&f->lock); 2592987da915Sopenharmony_ci locks_insert(get_node(f, ino), &l); 2593987da915Sopenharmony_ci pthread_mutex_unlock(&f->lock); 2594987da915Sopenharmony_ci 2595987da915Sopenharmony_ci /* if op.lock() is defined FLUSH is needed regardless of op.flush() */ 2596987da915Sopenharmony_ci if (err == -ENOSYS) 2597987da915Sopenharmony_ci err = 0; 2598987da915Sopenharmony_ci } 2599987da915Sopenharmony_ci return err; 2600987da915Sopenharmony_ci} 2601987da915Sopenharmony_ci 2602987da915Sopenharmony_cistatic void fuse_lib_release(fuse_req_t req, fuse_ino_t ino, 2603987da915Sopenharmony_ci struct fuse_file_info *fi) 2604987da915Sopenharmony_ci{ 2605987da915Sopenharmony_ci struct fuse *f = req_fuse_prepare(req); 2606987da915Sopenharmony_ci struct fuse_intr_data d; 2607987da915Sopenharmony_ci char *path; 2608987da915Sopenharmony_ci int err = 0; 2609987da915Sopenharmony_ci 2610987da915Sopenharmony_ci pthread_rwlock_rdlock(&f->tree_lock); 2611987da915Sopenharmony_ci path = get_path(f, ino); 2612987da915Sopenharmony_ci if (f->conf.debug) 2613987da915Sopenharmony_ci fprintf(stderr, "RELEASE%s[%llu] flags: 0x%x\n", 2614987da915Sopenharmony_ci fi->flush ? "+FLUSH" : "", 2615987da915Sopenharmony_ci (unsigned long long) fi->fh, fi->flags); 2616987da915Sopenharmony_ci 2617987da915Sopenharmony_ci if (fi->flush) { 2618987da915Sopenharmony_ci err = fuse_flush_common(f, req, ino, path, fi); 2619987da915Sopenharmony_ci if (err == -ENOSYS) 2620987da915Sopenharmony_ci err = 0; 2621987da915Sopenharmony_ci } 2622987da915Sopenharmony_ci 2623987da915Sopenharmony_ci fuse_prepare_interrupt(f, req, &d); 2624987da915Sopenharmony_ci fuse_do_release(f, ino, path, fi); 2625987da915Sopenharmony_ci fuse_finish_interrupt(f, req, &d); 2626987da915Sopenharmony_ci free(path); 2627987da915Sopenharmony_ci pthread_rwlock_unlock(&f->tree_lock); 2628987da915Sopenharmony_ci 2629987da915Sopenharmony_ci reply_err(req, err); 2630987da915Sopenharmony_ci} 2631987da915Sopenharmony_ci 2632987da915Sopenharmony_cistatic void fuse_lib_flush(fuse_req_t req, fuse_ino_t ino, 2633987da915Sopenharmony_ci struct fuse_file_info *fi) 2634987da915Sopenharmony_ci{ 2635987da915Sopenharmony_ci struct fuse *f = req_fuse_prepare(req); 2636987da915Sopenharmony_ci char *path; 2637987da915Sopenharmony_ci int err; 2638987da915Sopenharmony_ci 2639987da915Sopenharmony_ci pthread_rwlock_rdlock(&f->tree_lock); 2640987da915Sopenharmony_ci path = get_path(f, ino); 2641987da915Sopenharmony_ci if (path && f->conf.debug) 2642987da915Sopenharmony_ci fprintf(stderr, "FLUSH[%llu]\n", (unsigned long long) fi->fh); 2643987da915Sopenharmony_ci err = fuse_flush_common(f, req, ino, path, fi); 2644987da915Sopenharmony_ci free(path); 2645987da915Sopenharmony_ci pthread_rwlock_unlock(&f->tree_lock); 2646987da915Sopenharmony_ci reply_err(req, err); 2647987da915Sopenharmony_ci} 2648987da915Sopenharmony_ci 2649987da915Sopenharmony_cistatic int fuse_lock_common(fuse_req_t req, fuse_ino_t ino, 2650987da915Sopenharmony_ci struct fuse_file_info *fi, struct flock *lock, 2651987da915Sopenharmony_ci int cmd) 2652987da915Sopenharmony_ci{ 2653987da915Sopenharmony_ci struct fuse *f = req_fuse_prepare(req); 2654987da915Sopenharmony_ci char *path; 2655987da915Sopenharmony_ci int err; 2656987da915Sopenharmony_ci 2657987da915Sopenharmony_ci err = -ENOENT; 2658987da915Sopenharmony_ci pthread_rwlock_rdlock(&f->tree_lock); 2659987da915Sopenharmony_ci path = get_path(f, ino); 2660987da915Sopenharmony_ci if (path != NULL) { 2661987da915Sopenharmony_ci struct fuse_intr_data d; 2662987da915Sopenharmony_ci fuse_prepare_interrupt(f, req, &d); 2663987da915Sopenharmony_ci err = fuse_fs_lock(f->fs, path, fi, cmd, lock); 2664987da915Sopenharmony_ci fuse_finish_interrupt(f, req, &d); 2665987da915Sopenharmony_ci free(path); 2666987da915Sopenharmony_ci } 2667987da915Sopenharmony_ci pthread_rwlock_unlock(&f->tree_lock); 2668987da915Sopenharmony_ci return err; 2669987da915Sopenharmony_ci} 2670987da915Sopenharmony_ci 2671987da915Sopenharmony_cistatic void fuse_lib_getlk(fuse_req_t req, fuse_ino_t ino, 2672987da915Sopenharmony_ci struct fuse_file_info *fi, struct flock *lock) 2673987da915Sopenharmony_ci{ 2674987da915Sopenharmony_ci int err; 2675987da915Sopenharmony_ci struct lock l; 2676987da915Sopenharmony_ci struct lock *conflict; 2677987da915Sopenharmony_ci struct fuse *f = req_fuse(req); 2678987da915Sopenharmony_ci 2679987da915Sopenharmony_ci flock_to_lock(lock, &l); 2680987da915Sopenharmony_ci l.owner = fi->lock_owner; 2681987da915Sopenharmony_ci pthread_mutex_lock(&f->lock); 2682987da915Sopenharmony_ci conflict = locks_conflict(get_node(f, ino), &l); 2683987da915Sopenharmony_ci if (conflict) 2684987da915Sopenharmony_ci lock_to_flock(conflict, lock); 2685987da915Sopenharmony_ci pthread_mutex_unlock(&f->lock); 2686987da915Sopenharmony_ci if (!conflict) 2687987da915Sopenharmony_ci err = fuse_lock_common(req, ino, fi, lock, F_GETLK); 2688987da915Sopenharmony_ci else 2689987da915Sopenharmony_ci err = 0; 2690987da915Sopenharmony_ci 2691987da915Sopenharmony_ci if (!err) 2692987da915Sopenharmony_ci fuse_reply_lock(req, lock); 2693987da915Sopenharmony_ci else 2694987da915Sopenharmony_ci reply_err(req, err); 2695987da915Sopenharmony_ci} 2696987da915Sopenharmony_ci 2697987da915Sopenharmony_cistatic void fuse_lib_setlk(fuse_req_t req, fuse_ino_t ino, 2698987da915Sopenharmony_ci struct fuse_file_info *fi, struct flock *lock, 2699987da915Sopenharmony_ci int should_sleep) 2700987da915Sopenharmony_ci{ 2701987da915Sopenharmony_ci int err = fuse_lock_common(req, ino, fi, lock, should_sleep ? F_SETLKW : F_SETLK); 2702987da915Sopenharmony_ci if (!err) { 2703987da915Sopenharmony_ci struct fuse *f = req_fuse(req); 2704987da915Sopenharmony_ci struct lock l; 2705987da915Sopenharmony_ci flock_to_lock(lock, &l); 2706987da915Sopenharmony_ci l.owner = fi->lock_owner; 2707987da915Sopenharmony_ci pthread_mutex_lock(&f->lock); 2708987da915Sopenharmony_ci locks_insert(get_node(f, ino), &l); 2709987da915Sopenharmony_ci pthread_mutex_unlock(&f->lock); 2710987da915Sopenharmony_ci } 2711987da915Sopenharmony_ci reply_err(req, err); 2712987da915Sopenharmony_ci} 2713987da915Sopenharmony_ci 2714987da915Sopenharmony_cistatic void fuse_lib_bmap(fuse_req_t req, fuse_ino_t ino, size_t blocksize, 2715987da915Sopenharmony_ci uint64_t idx) 2716987da915Sopenharmony_ci{ 2717987da915Sopenharmony_ci struct fuse *f = req_fuse_prepare(req); 2718987da915Sopenharmony_ci struct fuse_intr_data d; 2719987da915Sopenharmony_ci char *path; 2720987da915Sopenharmony_ci int err; 2721987da915Sopenharmony_ci 2722987da915Sopenharmony_ci err = -ENOENT; 2723987da915Sopenharmony_ci pthread_rwlock_rdlock(&f->tree_lock); 2724987da915Sopenharmony_ci path = get_path(f, ino); 2725987da915Sopenharmony_ci if (path != NULL) { 2726987da915Sopenharmony_ci fuse_prepare_interrupt(f, req, &d); 2727987da915Sopenharmony_ci err = fuse_fs_bmap(f->fs, path, blocksize, &idx); 2728987da915Sopenharmony_ci fuse_finish_interrupt(f, req, &d); 2729987da915Sopenharmony_ci free(path); 2730987da915Sopenharmony_ci } 2731987da915Sopenharmony_ci pthread_rwlock_unlock(&f->tree_lock); 2732987da915Sopenharmony_ci if (!err) 2733987da915Sopenharmony_ci fuse_reply_bmap(req, idx); 2734987da915Sopenharmony_ci else 2735987da915Sopenharmony_ci reply_err(req, err); 2736987da915Sopenharmony_ci} 2737987da915Sopenharmony_ci 2738987da915Sopenharmony_cistatic void fuse_lib_ioctl(fuse_req_t req, fuse_ino_t ino, int cmd, void *arg, 2739987da915Sopenharmony_ci struct fuse_file_info *llfi, unsigned int flags, 2740987da915Sopenharmony_ci const void *in_buf, size_t in_bufsz, 2741987da915Sopenharmony_ci size_t out_bufsz) 2742987da915Sopenharmony_ci{ 2743987da915Sopenharmony_ci struct fuse *f = req_fuse_prepare(req); 2744987da915Sopenharmony_ci struct fuse_intr_data d; 2745987da915Sopenharmony_ci struct fuse_file_info fi; 2746987da915Sopenharmony_ci char *path, *out_buf = NULL; 2747987da915Sopenharmony_ci int err; 2748987da915Sopenharmony_ci 2749987da915Sopenharmony_ci err = -EPERM; 2750987da915Sopenharmony_ci if (flags & FUSE_IOCTL_UNRESTRICTED) 2751987da915Sopenharmony_ci goto err; 2752987da915Sopenharmony_ci 2753987da915Sopenharmony_ci if (flags & FUSE_IOCTL_DIR) 2754987da915Sopenharmony_ci get_dirhandle(llfi, &fi); 2755987da915Sopenharmony_ci else 2756987da915Sopenharmony_ci fi = *llfi; 2757987da915Sopenharmony_ci 2758987da915Sopenharmony_ci if (out_bufsz) { 2759987da915Sopenharmony_ci err = -ENOMEM; 2760987da915Sopenharmony_ci out_buf = malloc(out_bufsz); 2761987da915Sopenharmony_ci if (!out_buf) 2762987da915Sopenharmony_ci goto err; 2763987da915Sopenharmony_ci } 2764987da915Sopenharmony_ci 2765987da915Sopenharmony_ci assert(!in_bufsz || !out_bufsz || in_bufsz == out_bufsz); 2766987da915Sopenharmony_ci if (out_buf) 2767987da915Sopenharmony_ci memcpy(out_buf, in_buf, in_bufsz); 2768987da915Sopenharmony_ci 2769987da915Sopenharmony_ci path = get_path(f, ino); /* Should be get_path_nullok() */ 2770987da915Sopenharmony_ci if (!path) { 2771987da915Sopenharmony_ci err = ENOENT; 2772987da915Sopenharmony_ci goto err; 2773987da915Sopenharmony_ci } 2774987da915Sopenharmony_ci 2775987da915Sopenharmony_ci fuse_prepare_interrupt(f, req, &d); 2776987da915Sopenharmony_ci 2777987da915Sopenharmony_ci /* Note : const qualifier dropped */ 2778987da915Sopenharmony_ci err = fuse_fs_ioctl(f->fs, path, cmd, arg, &fi, flags, 2779987da915Sopenharmony_ci out_buf ? (void*)out_buf : (void*)(uintptr_t)in_buf); 2780987da915Sopenharmony_ci 2781987da915Sopenharmony_ci fuse_finish_interrupt(f, req, &d); 2782987da915Sopenharmony_ci free(path); 2783987da915Sopenharmony_ci 2784987da915Sopenharmony_ci if (err >= 0) { /* not an error */ 2785987da915Sopenharmony_ci fuse_reply_ioctl(req, err, out_buf, out_bufsz); 2786987da915Sopenharmony_ci goto out; 2787987da915Sopenharmony_ci } 2788987da915Sopenharmony_cierr: 2789987da915Sopenharmony_ci reply_err(req, err); 2790987da915Sopenharmony_ciout: 2791987da915Sopenharmony_ci free(out_buf); 2792987da915Sopenharmony_ci} 2793987da915Sopenharmony_ci 2794987da915Sopenharmony_cistatic struct fuse_lowlevel_ops fuse_path_ops = { 2795987da915Sopenharmony_ci .init = fuse_lib_init, 2796987da915Sopenharmony_ci .destroy = fuse_lib_destroy, 2797987da915Sopenharmony_ci .lookup = fuse_lib_lookup, 2798987da915Sopenharmony_ci .forget = fuse_lib_forget, 2799987da915Sopenharmony_ci .getattr = fuse_lib_getattr, 2800987da915Sopenharmony_ci .setattr = fuse_lib_setattr, 2801987da915Sopenharmony_ci .access = fuse_lib_access, 2802987da915Sopenharmony_ci .readlink = fuse_lib_readlink, 2803987da915Sopenharmony_ci .mknod = fuse_lib_mknod, 2804987da915Sopenharmony_ci .mkdir = fuse_lib_mkdir, 2805987da915Sopenharmony_ci .unlink = fuse_lib_unlink, 2806987da915Sopenharmony_ci .rmdir = fuse_lib_rmdir, 2807987da915Sopenharmony_ci .symlink = fuse_lib_symlink, 2808987da915Sopenharmony_ci .rename = fuse_lib_rename, 2809987da915Sopenharmony_ci .link = fuse_lib_link, 2810987da915Sopenharmony_ci .create = fuse_lib_create, 2811987da915Sopenharmony_ci .open = fuse_lib_open, 2812987da915Sopenharmony_ci .read = fuse_lib_read, 2813987da915Sopenharmony_ci .write = fuse_lib_write, 2814987da915Sopenharmony_ci .flush = fuse_lib_flush, 2815987da915Sopenharmony_ci .release = fuse_lib_release, 2816987da915Sopenharmony_ci .fsync = fuse_lib_fsync, 2817987da915Sopenharmony_ci .opendir = fuse_lib_opendir, 2818987da915Sopenharmony_ci .readdir = fuse_lib_readdir, 2819987da915Sopenharmony_ci .releasedir = fuse_lib_releasedir, 2820987da915Sopenharmony_ci .fsyncdir = fuse_lib_fsyncdir, 2821987da915Sopenharmony_ci .statfs = fuse_lib_statfs, 2822987da915Sopenharmony_ci .setxattr = fuse_lib_setxattr, 2823987da915Sopenharmony_ci .getxattr = fuse_lib_getxattr, 2824987da915Sopenharmony_ci .listxattr = fuse_lib_listxattr, 2825987da915Sopenharmony_ci .removexattr = fuse_lib_removexattr, 2826987da915Sopenharmony_ci .getlk = fuse_lib_getlk, 2827987da915Sopenharmony_ci .setlk = fuse_lib_setlk, 2828987da915Sopenharmony_ci .bmap = fuse_lib_bmap, 2829987da915Sopenharmony_ci .ioctl = fuse_lib_ioctl, 2830987da915Sopenharmony_ci}; 2831987da915Sopenharmony_ci 2832987da915Sopenharmony_cistruct fuse_session *fuse_get_session(struct fuse *f) 2833987da915Sopenharmony_ci{ 2834987da915Sopenharmony_ci return f->se; 2835987da915Sopenharmony_ci} 2836987da915Sopenharmony_ci 2837987da915Sopenharmony_ciint fuse_loop(struct fuse *f) 2838987da915Sopenharmony_ci{ 2839987da915Sopenharmony_ci if (f) 2840987da915Sopenharmony_ci return fuse_session_loop(f->se); 2841987da915Sopenharmony_ci else 2842987da915Sopenharmony_ci return -1; 2843987da915Sopenharmony_ci} 2844987da915Sopenharmony_ci 2845987da915Sopenharmony_civoid fuse_exit(struct fuse *f) 2846987da915Sopenharmony_ci{ 2847987da915Sopenharmony_ci fuse_session_exit(f->se); 2848987da915Sopenharmony_ci} 2849987da915Sopenharmony_ci 2850987da915Sopenharmony_cistruct fuse_context *fuse_get_context(void) 2851987da915Sopenharmony_ci{ 2852987da915Sopenharmony_ci return &fuse_get_context_internal()->ctx; 2853987da915Sopenharmony_ci} 2854987da915Sopenharmony_ci 2855987da915Sopenharmony_ciint fuse_interrupted(void) 2856987da915Sopenharmony_ci{ 2857987da915Sopenharmony_ci return fuse_req_interrupted(fuse_get_context_internal()->req); 2858987da915Sopenharmony_ci} 2859987da915Sopenharmony_ci 2860987da915Sopenharmony_cienum { 2861987da915Sopenharmony_ci KEY_HELP, 2862987da915Sopenharmony_ci}; 2863987da915Sopenharmony_ci 2864987da915Sopenharmony_ci#define FUSE_LIB_OPT(t, p, v) { t, offsetof(struct fuse_config, p), v } 2865987da915Sopenharmony_ci 2866987da915Sopenharmony_cistatic const struct fuse_opt fuse_lib_opts[] = { 2867987da915Sopenharmony_ci FUSE_OPT_KEY("-h", KEY_HELP), 2868987da915Sopenharmony_ci FUSE_OPT_KEY("--help", KEY_HELP), 2869987da915Sopenharmony_ci FUSE_OPT_KEY("debug", FUSE_OPT_KEY_KEEP), 2870987da915Sopenharmony_ci FUSE_OPT_KEY("-d", FUSE_OPT_KEY_KEEP), 2871987da915Sopenharmony_ci FUSE_LIB_OPT("debug", debug, 1), 2872987da915Sopenharmony_ci FUSE_LIB_OPT("-d", debug, 1), 2873987da915Sopenharmony_ci FUSE_LIB_OPT("hard_remove", hard_remove, 1), 2874987da915Sopenharmony_ci FUSE_LIB_OPT("use_ino", use_ino, 1), 2875987da915Sopenharmony_ci FUSE_LIB_OPT("readdir_ino", readdir_ino, 1), 2876987da915Sopenharmony_ci FUSE_LIB_OPT("direct_io", direct_io, 1), 2877987da915Sopenharmony_ci FUSE_LIB_OPT("kernel_cache", kernel_cache, 1), 2878987da915Sopenharmony_ci#ifdef __SOLARIS__ 2879987da915Sopenharmony_ci FUSE_LIB_OPT("auto_cache", auto_cache, 1), 2880987da915Sopenharmony_ci FUSE_LIB_OPT("noauto_cache", auto_cache, 0), 2881987da915Sopenharmony_ci#endif /* __SOLARIS__ */ 2882987da915Sopenharmony_ci FUSE_LIB_OPT("umask=", set_mode, 1), 2883987da915Sopenharmony_ci FUSE_LIB_OPT("umask=%o", umask, 0), 2884987da915Sopenharmony_ci FUSE_LIB_OPT("uid=", set_uid, 1), 2885987da915Sopenharmony_ci FUSE_LIB_OPT("uid=%d", uid, 0), 2886987da915Sopenharmony_ci FUSE_LIB_OPT("gid=", set_gid, 1), 2887987da915Sopenharmony_ci FUSE_LIB_OPT("gid=%d", gid, 0), 2888987da915Sopenharmony_ci FUSE_LIB_OPT("entry_timeout=%lf", entry_timeout, 0), 2889987da915Sopenharmony_ci FUSE_LIB_OPT("attr_timeout=%lf", attr_timeout, 0), 2890987da915Sopenharmony_ci FUSE_LIB_OPT("ac_attr_timeout=%lf", ac_attr_timeout, 0), 2891987da915Sopenharmony_ci FUSE_LIB_OPT("ac_attr_timeout=", ac_attr_timeout_set, 1), 2892987da915Sopenharmony_ci FUSE_LIB_OPT("negative_timeout=%lf", negative_timeout, 0), 2893987da915Sopenharmony_ci FUSE_LIB_OPT("intr", intr, 1), 2894987da915Sopenharmony_ci FUSE_LIB_OPT("intr_signal=%d", intr_signal, 0), 2895987da915Sopenharmony_ci#ifdef __SOLARIS__ 2896987da915Sopenharmony_ci FUSE_LIB_OPT("modules=%s", modules, 0), 2897987da915Sopenharmony_ci#endif /* __SOLARIS__ */ 2898987da915Sopenharmony_ci FUSE_OPT_END 2899987da915Sopenharmony_ci}; 2900987da915Sopenharmony_ci 2901987da915Sopenharmony_cistatic void fuse_lib_help(void) 2902987da915Sopenharmony_ci{ 2903987da915Sopenharmony_ci fprintf(stderr, 2904987da915Sopenharmony_ci" -o hard_remove immediate removal (don't hide files)\n" 2905987da915Sopenharmony_ci" -o use_ino let filesystem set inode numbers\n" 2906987da915Sopenharmony_ci" -o readdir_ino try to fill in d_ino in readdir\n" 2907987da915Sopenharmony_ci" -o direct_io use direct I/O\n" 2908987da915Sopenharmony_ci" -o kernel_cache cache files in kernel\n" 2909987da915Sopenharmony_ci#ifdef __SOLARIS__ 2910987da915Sopenharmony_ci" -o [no]auto_cache enable caching based on modification times (off)\n" 2911987da915Sopenharmony_ci#endif /* __SOLARIS__ */ 2912987da915Sopenharmony_ci" -o umask=M set file permissions (octal)\n" 2913987da915Sopenharmony_ci" -o uid=N set file owner\n" 2914987da915Sopenharmony_ci" -o gid=N set file group\n" 2915987da915Sopenharmony_ci" -o entry_timeout=T cache timeout for names (1.0s)\n" 2916987da915Sopenharmony_ci" -o negative_timeout=T cache timeout for deleted names (0.0s)\n" 2917987da915Sopenharmony_ci" -o attr_timeout=T cache timeout for attributes (1.0s)\n" 2918987da915Sopenharmony_ci" -o ac_attr_timeout=T auto cache timeout for attributes (attr_timeout)\n" 2919987da915Sopenharmony_ci" -o intr allow requests to be interrupted\n" 2920987da915Sopenharmony_ci" -o intr_signal=NUM signal to send on interrupt (%i)\n" 2921987da915Sopenharmony_ci#ifdef __SOLARIS__ 2922987da915Sopenharmony_ci" -o modules=M1[:M2...] names of modules to push onto filesystem stack\n" 2923987da915Sopenharmony_ci#endif /* __SOLARIS__ */ 2924987da915Sopenharmony_ci"\n", FUSE_DEFAULT_INTR_SIGNAL); 2925987da915Sopenharmony_ci} 2926987da915Sopenharmony_ci 2927987da915Sopenharmony_ci#ifdef __SOLARIS__ 2928987da915Sopenharmony_ci 2929987da915Sopenharmony_cistatic void fuse_lib_help_modules(void) 2930987da915Sopenharmony_ci{ 2931987da915Sopenharmony_ci struct fuse_module *m; 2932987da915Sopenharmony_ci fprintf(stderr, "\nModule options:\n"); 2933987da915Sopenharmony_ci pthread_mutex_lock(&fuse_context_lock); 2934987da915Sopenharmony_ci for (m = fuse_modules; m; m = m->next) { 2935987da915Sopenharmony_ci struct fuse_fs *fs = NULL; 2936987da915Sopenharmony_ci struct fuse_fs *newfs; 2937987da915Sopenharmony_ci struct fuse_args args = FUSE_ARGS_INIT(0, NULL); 2938987da915Sopenharmony_ci if (fuse_opt_add_arg(&args, "") != -1 && 2939987da915Sopenharmony_ci fuse_opt_add_arg(&args, "-h") != -1) { 2940987da915Sopenharmony_ci fprintf(stderr, "\n[%s]\n", m->name); 2941987da915Sopenharmony_ci newfs = m->factory(&args, &fs); 2942987da915Sopenharmony_ci assert(newfs == NULL); 2943987da915Sopenharmony_ci } 2944987da915Sopenharmony_ci fuse_opt_free_args(&args); 2945987da915Sopenharmony_ci } 2946987da915Sopenharmony_ci pthread_mutex_unlock(&fuse_context_lock); 2947987da915Sopenharmony_ci} 2948987da915Sopenharmony_ci 2949987da915Sopenharmony_ciint fuse_is_lib_option(const char *opt) 2950987da915Sopenharmony_ci{ 2951987da915Sopenharmony_ci return fuse_lowlevel_is_lib_option(opt) || 2952987da915Sopenharmony_ci fuse_opt_match(fuse_lib_opts, opt); 2953987da915Sopenharmony_ci} 2954987da915Sopenharmony_ci 2955987da915Sopenharmony_ci#endif /* __SOLARIS__ */ 2956987da915Sopenharmony_ci 2957987da915Sopenharmony_cistatic int fuse_lib_opt_proc(void *data, const char *arg, int key, 2958987da915Sopenharmony_ci struct fuse_args *outargs) 2959987da915Sopenharmony_ci{ 2960987da915Sopenharmony_ci (void) arg; (void) outargs; 2961987da915Sopenharmony_ci 2962987da915Sopenharmony_ci if (key == KEY_HELP) { 2963987da915Sopenharmony_ci struct fuse_config *conf = (struct fuse_config *) data; 2964987da915Sopenharmony_ci fuse_lib_help(); 2965987da915Sopenharmony_ci conf->help = 1; 2966987da915Sopenharmony_ci } 2967987da915Sopenharmony_ci 2968987da915Sopenharmony_ci return 1; 2969987da915Sopenharmony_ci} 2970987da915Sopenharmony_ci 2971987da915Sopenharmony_cistatic int fuse_init_intr_signal(int signum, int *installed) 2972987da915Sopenharmony_ci{ 2973987da915Sopenharmony_ci struct sigaction old_sa; 2974987da915Sopenharmony_ci 2975987da915Sopenharmony_ci if (sigaction(signum, NULL, &old_sa) == -1) { 2976987da915Sopenharmony_ci perror("fuse: cannot get old signal handler"); 2977987da915Sopenharmony_ci return -1; 2978987da915Sopenharmony_ci } 2979987da915Sopenharmony_ci 2980987da915Sopenharmony_ci if (old_sa.sa_handler == SIG_DFL) { 2981987da915Sopenharmony_ci struct sigaction sa; 2982987da915Sopenharmony_ci 2983987da915Sopenharmony_ci memset(&sa, 0, sizeof(struct sigaction)); 2984987da915Sopenharmony_ci sa.sa_handler = fuse_intr_sighandler; 2985987da915Sopenharmony_ci sigemptyset(&sa.sa_mask); 2986987da915Sopenharmony_ci 2987987da915Sopenharmony_ci if (sigaction(signum, &sa, NULL) == -1) { 2988987da915Sopenharmony_ci perror("fuse: cannot set interrupt signal handler"); 2989987da915Sopenharmony_ci return -1; 2990987da915Sopenharmony_ci } 2991987da915Sopenharmony_ci *installed = 1; 2992987da915Sopenharmony_ci } 2993987da915Sopenharmony_ci return 0; 2994987da915Sopenharmony_ci} 2995987da915Sopenharmony_ci 2996987da915Sopenharmony_cistatic void fuse_restore_intr_signal(int signum) 2997987da915Sopenharmony_ci{ 2998987da915Sopenharmony_ci struct sigaction sa; 2999987da915Sopenharmony_ci 3000987da915Sopenharmony_ci memset(&sa, 0, sizeof(struct sigaction)); 3001987da915Sopenharmony_ci sa.sa_handler = SIG_DFL; 3002987da915Sopenharmony_ci sigaction(signum, &sa, NULL); 3003987da915Sopenharmony_ci} 3004987da915Sopenharmony_ci 3005987da915Sopenharmony_ci#ifdef __SOLARIS__ 3006987da915Sopenharmony_ci 3007987da915Sopenharmony_cistatic int fuse_push_module(struct fuse *f, const char *module, 3008987da915Sopenharmony_ci struct fuse_args *args) 3009987da915Sopenharmony_ci{ 3010987da915Sopenharmony_ci struct fuse_fs *newfs; 3011987da915Sopenharmony_ci struct fuse_module *m = fuse_get_module(module); 3012987da915Sopenharmony_ci struct fuse_fs *fs[2]; 3013987da915Sopenharmony_ci 3014987da915Sopenharmony_ci fs[0] = f->fs; 3015987da915Sopenharmony_ci fs[1] = NULL; 3016987da915Sopenharmony_ci if (!m) 3017987da915Sopenharmony_ci return -1; 3018987da915Sopenharmony_ci 3019987da915Sopenharmony_ci newfs = m->factory(args, fs); 3020987da915Sopenharmony_ci if (!newfs) { 3021987da915Sopenharmony_ci fuse_put_module(m); 3022987da915Sopenharmony_ci return -1; 3023987da915Sopenharmony_ci } 3024987da915Sopenharmony_ci newfs->m = m; 3025987da915Sopenharmony_ci f->fs = newfs; 3026987da915Sopenharmony_ci return 0; 3027987da915Sopenharmony_ci} 3028987da915Sopenharmony_ci 3029987da915Sopenharmony_ci#endif /* __SOLARIS__ */ 3030987da915Sopenharmony_ci 3031987da915Sopenharmony_cistruct fuse_fs *fuse_fs_new(const struct fuse_operations *op, size_t op_size, 3032987da915Sopenharmony_ci void *user_data) 3033987da915Sopenharmony_ci{ 3034987da915Sopenharmony_ci struct fuse_fs *fs; 3035987da915Sopenharmony_ci 3036987da915Sopenharmony_ci if (sizeof(struct fuse_operations) < op_size) { 3037987da915Sopenharmony_ci fprintf(stderr, "fuse: warning: library too old, some operations may not not work\n"); 3038987da915Sopenharmony_ci op_size = sizeof(struct fuse_operations); 3039987da915Sopenharmony_ci } 3040987da915Sopenharmony_ci 3041987da915Sopenharmony_ci fs = (struct fuse_fs *) calloc(1, sizeof(struct fuse_fs)); 3042987da915Sopenharmony_ci if (!fs) { 3043987da915Sopenharmony_ci fprintf(stderr, "fuse: failed to allocate fuse_fs object\n"); 3044987da915Sopenharmony_ci return NULL; 3045987da915Sopenharmony_ci } 3046987da915Sopenharmony_ci 3047987da915Sopenharmony_ci fs->user_data = user_data; 3048987da915Sopenharmony_ci if (op) 3049987da915Sopenharmony_ci memcpy(&fs->op, op, op_size); 3050987da915Sopenharmony_ci return fs; 3051987da915Sopenharmony_ci} 3052987da915Sopenharmony_ci 3053987da915Sopenharmony_cistruct fuse *fuse_new(struct fuse_chan *ch, struct fuse_args *args, 3054987da915Sopenharmony_ci const struct fuse_operations *op, size_t op_size, 3055987da915Sopenharmony_ci void *user_data) 3056987da915Sopenharmony_ci{ 3057987da915Sopenharmony_ci struct fuse *f; 3058987da915Sopenharmony_ci struct node *root; 3059987da915Sopenharmony_ci struct fuse_fs *fs; 3060987da915Sopenharmony_ci struct fuse_lowlevel_ops llop = fuse_path_ops; 3061987da915Sopenharmony_ci 3062987da915Sopenharmony_ci if (fuse_create_context_key() == -1) 3063987da915Sopenharmony_ci goto out; 3064987da915Sopenharmony_ci 3065987da915Sopenharmony_ci f = (struct fuse *) calloc(1, sizeof(struct fuse)); 3066987da915Sopenharmony_ci if (f == NULL) { 3067987da915Sopenharmony_ci fprintf(stderr, "fuse: failed to allocate fuse object\n"); 3068987da915Sopenharmony_ci goto out_delete_context_key; 3069987da915Sopenharmony_ci } 3070987da915Sopenharmony_ci 3071987da915Sopenharmony_ci fs = fuse_fs_new(op, op_size, user_data); 3072987da915Sopenharmony_ci if (!fs) 3073987da915Sopenharmony_ci goto out_free; 3074987da915Sopenharmony_ci 3075987da915Sopenharmony_ci f->fs = fs; 3076987da915Sopenharmony_ci 3077987da915Sopenharmony_ci /* Oh f**k, this is ugly! */ 3078987da915Sopenharmony_ci if (!fs->op.lock) { 3079987da915Sopenharmony_ci llop.getlk = NULL; 3080987da915Sopenharmony_ci llop.setlk = NULL; 3081987da915Sopenharmony_ci } 3082987da915Sopenharmony_ci 3083987da915Sopenharmony_ci f->conf.entry_timeout = 1.0; 3084987da915Sopenharmony_ci f->conf.attr_timeout = 1.0; 3085987da915Sopenharmony_ci f->conf.negative_timeout = 0.0; 3086987da915Sopenharmony_ci f->conf.hard_remove = 1; 3087987da915Sopenharmony_ci f->conf.intr_signal = FUSE_DEFAULT_INTR_SIGNAL; 3088987da915Sopenharmony_ci 3089987da915Sopenharmony_ci if (fuse_opt_parse(args, &f->conf, fuse_lib_opts, fuse_lib_opt_proc) == -1) 3090987da915Sopenharmony_ci goto out_free_fs; 3091987da915Sopenharmony_ci 3092987da915Sopenharmony_ci#ifdef __SOLARIS__ 3093987da915Sopenharmony_ci if (f->conf.modules) { 3094987da915Sopenharmony_ci char *module; 3095987da915Sopenharmony_ci char *next; 3096987da915Sopenharmony_ci 3097987da915Sopenharmony_ci for (module = f->conf.modules; module; module = next) { 3098987da915Sopenharmony_ci char *p; 3099987da915Sopenharmony_ci for (p = module; *p && *p != ':'; p++); 3100987da915Sopenharmony_ci next = *p ? p + 1 : NULL; 3101987da915Sopenharmony_ci *p = '\0'; 3102987da915Sopenharmony_ci if (module[0] && fuse_push_module(f, module, args) == -1) 3103987da915Sopenharmony_ci goto out_free_fs; 3104987da915Sopenharmony_ci } 3105987da915Sopenharmony_ci } 3106987da915Sopenharmony_ci#endif /* __SOLARIS__ */ 3107987da915Sopenharmony_ci 3108987da915Sopenharmony_ci if (!f->conf.ac_attr_timeout_set) 3109987da915Sopenharmony_ci f->conf.ac_attr_timeout = f->conf.attr_timeout; 3110987da915Sopenharmony_ci 3111987da915Sopenharmony_ci#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) 3112987da915Sopenharmony_ci /* 3113987da915Sopenharmony_ci * In FreeBSD, we always use these settings as inode numbers are needed to 3114987da915Sopenharmony_ci * make getcwd(3) work. 3115987da915Sopenharmony_ci */ 3116987da915Sopenharmony_ci f->conf.readdir_ino = 1; 3117987da915Sopenharmony_ci#endif 3118987da915Sopenharmony_ci 3119987da915Sopenharmony_ci f->se = fuse_lowlevel_new(args, &llop, sizeof(llop), f); 3120987da915Sopenharmony_ci 3121987da915Sopenharmony_ci if (f->se == NULL) { 3122987da915Sopenharmony_ci#ifdef __SOLARIS__ 3123987da915Sopenharmony_ci if (f->conf.help) 3124987da915Sopenharmony_ci fuse_lib_help_modules(); 3125987da915Sopenharmony_ci#endif /* __SOLARIS__ */ 3126987da915Sopenharmony_ci goto out_free_fs; 3127987da915Sopenharmony_ci } 3128987da915Sopenharmony_ci 3129987da915Sopenharmony_ci fuse_session_add_chan(f->se, ch); 3130987da915Sopenharmony_ci 3131987da915Sopenharmony_ci f->ctr = 0; 3132987da915Sopenharmony_ci f->generation = 0; 3133987da915Sopenharmony_ci /* FIXME: Dynamic hash table */ 3134987da915Sopenharmony_ci f->name_table_size = 14057; 3135987da915Sopenharmony_ci f->name_table = (struct node **) 3136987da915Sopenharmony_ci calloc(1, sizeof(struct node *) * f->name_table_size); 3137987da915Sopenharmony_ci if (f->name_table == NULL) { 3138987da915Sopenharmony_ci fprintf(stderr, "fuse: memory allocation failed\n"); 3139987da915Sopenharmony_ci goto out_free_session; 3140987da915Sopenharmony_ci } 3141987da915Sopenharmony_ci 3142987da915Sopenharmony_ci f->id_table_size = 14057; 3143987da915Sopenharmony_ci f->id_table = (struct node **) 3144987da915Sopenharmony_ci calloc(1, sizeof(struct node *) * f->id_table_size); 3145987da915Sopenharmony_ci if (f->id_table == NULL) { 3146987da915Sopenharmony_ci fprintf(stderr, "fuse: memory allocation failed\n"); 3147987da915Sopenharmony_ci goto out_free_name_table; 3148987da915Sopenharmony_ci } 3149987da915Sopenharmony_ci 3150987da915Sopenharmony_ci fuse_mutex_init(&f->lock); 3151987da915Sopenharmony_ci pthread_rwlock_init(&f->tree_lock, NULL); 3152987da915Sopenharmony_ci 3153987da915Sopenharmony_ci root = (struct node *) calloc(1, sizeof(struct node)); 3154987da915Sopenharmony_ci if (root == NULL) { 3155987da915Sopenharmony_ci fprintf(stderr, "fuse: memory allocation failed\n"); 3156987da915Sopenharmony_ci goto out_free_id_table; 3157987da915Sopenharmony_ci } 3158987da915Sopenharmony_ci 3159987da915Sopenharmony_ci root->name = strdup("/"); 3160987da915Sopenharmony_ci if (root->name == NULL) { 3161987da915Sopenharmony_ci fprintf(stderr, "fuse: memory allocation failed\n"); 3162987da915Sopenharmony_ci goto out_free_root; 3163987da915Sopenharmony_ci } 3164987da915Sopenharmony_ci 3165987da915Sopenharmony_ci if (f->conf.intr && 3166987da915Sopenharmony_ci fuse_init_intr_signal(f->conf.intr_signal, &f->intr_installed) == -1) 3167987da915Sopenharmony_ci goto out_free_root_name; 3168987da915Sopenharmony_ci 3169987da915Sopenharmony_ci root->parent = NULL; 3170987da915Sopenharmony_ci root->nodeid = FUSE_ROOT_ID; 3171987da915Sopenharmony_ci root->generation = 0; 3172987da915Sopenharmony_ci root->refctr = 1; 3173987da915Sopenharmony_ci root->nlookup = 1; 3174987da915Sopenharmony_ci hash_id(f, root); 3175987da915Sopenharmony_ci 3176987da915Sopenharmony_ci return f; 3177987da915Sopenharmony_ci 3178987da915Sopenharmony_ci out_free_root_name: 3179987da915Sopenharmony_ci free(root->name); 3180987da915Sopenharmony_ci out_free_root: 3181987da915Sopenharmony_ci free(root); 3182987da915Sopenharmony_ci out_free_id_table: 3183987da915Sopenharmony_ci free(f->id_table); 3184987da915Sopenharmony_ci out_free_name_table: 3185987da915Sopenharmony_ci free(f->name_table); 3186987da915Sopenharmony_ci out_free_session: 3187987da915Sopenharmony_ci fuse_session_destroy(f->se); 3188987da915Sopenharmony_ci out_free_fs: 3189987da915Sopenharmony_ci /* Horrible compatibility hack to stop the destructor from being 3190987da915Sopenharmony_ci called on the filesystem without init being called first */ 3191987da915Sopenharmony_ci fs->op.destroy = NULL; 3192987da915Sopenharmony_ci fuse_fs_destroy(f->fs); 3193987da915Sopenharmony_ci#ifdef __SOLARIS__ 3194987da915Sopenharmony_ci free(f->conf.modules); 3195987da915Sopenharmony_ci#endif /* __SOLARIS__ */ 3196987da915Sopenharmony_ci out_free: 3197987da915Sopenharmony_ci free(f); 3198987da915Sopenharmony_ci out_delete_context_key: 3199987da915Sopenharmony_ci fuse_delete_context_key(); 3200987da915Sopenharmony_ci out: 3201987da915Sopenharmony_ci return NULL; 3202987da915Sopenharmony_ci} 3203987da915Sopenharmony_ci 3204987da915Sopenharmony_civoid fuse_destroy(struct fuse *f) 3205987da915Sopenharmony_ci{ 3206987da915Sopenharmony_ci size_t i; 3207987da915Sopenharmony_ci 3208987da915Sopenharmony_ci if (f->conf.intr && f->intr_installed) 3209987da915Sopenharmony_ci fuse_restore_intr_signal(f->conf.intr_signal); 3210987da915Sopenharmony_ci 3211987da915Sopenharmony_ci if (f->fs) { 3212987da915Sopenharmony_ci struct fuse_context_i *c = fuse_get_context_internal(); 3213987da915Sopenharmony_ci 3214987da915Sopenharmony_ci memset(c, 0, sizeof(*c)); 3215987da915Sopenharmony_ci c->ctx.fuse = f; 3216987da915Sopenharmony_ci 3217987da915Sopenharmony_ci for (i = 0; i < f->id_table_size; i++) { 3218987da915Sopenharmony_ci struct node *node; 3219987da915Sopenharmony_ci 3220987da915Sopenharmony_ci for (node = f->id_table[i]; node != NULL; node = node->id_next) { 3221987da915Sopenharmony_ci if (node->is_hidden) { 3222987da915Sopenharmony_ci char *path = get_path(f, node->nodeid); 3223987da915Sopenharmony_ci if (path) { 3224987da915Sopenharmony_ci fuse_fs_unlink(f->fs, path); 3225987da915Sopenharmony_ci free(path); 3226987da915Sopenharmony_ci } 3227987da915Sopenharmony_ci } 3228987da915Sopenharmony_ci } 3229987da915Sopenharmony_ci } 3230987da915Sopenharmony_ci } 3231987da915Sopenharmony_ci for (i = 0; i < f->id_table_size; i++) { 3232987da915Sopenharmony_ci struct node *node; 3233987da915Sopenharmony_ci struct node *next; 3234987da915Sopenharmony_ci 3235987da915Sopenharmony_ci for (node = f->id_table[i]; node != NULL; node = next) { 3236987da915Sopenharmony_ci next = node->id_next; 3237987da915Sopenharmony_ci free_node(node); 3238987da915Sopenharmony_ci } 3239987da915Sopenharmony_ci } 3240987da915Sopenharmony_ci free(f->id_table); 3241987da915Sopenharmony_ci free(f->name_table); 3242987da915Sopenharmony_ci pthread_mutex_destroy(&f->lock); 3243987da915Sopenharmony_ci pthread_rwlock_destroy(&f->tree_lock); 3244987da915Sopenharmony_ci fuse_session_destroy(f->se); 3245987da915Sopenharmony_ci#ifdef __SOLARIS__ 3246987da915Sopenharmony_ci free(f->conf.modules); 3247987da915Sopenharmony_ci#endif /* __SOLARIS__ */ 3248987da915Sopenharmony_ci free(f); 3249987da915Sopenharmony_ci fuse_delete_context_key(); 3250987da915Sopenharmony_ci} 3251