1/* 2 FUSE: Filesystem in Userspace 3 Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu> 4 5 This program can be distributed under the terms of the GNU LGPLv2. 6 See the file COPYING.LIB 7*/ 8 9#include "config.h" 10#include "fuse_i.h" 11#include "fuse_lowlevel.h" 12#include "fuse_opt.h" 13#include "fuse_misc.h" 14 15#include <stdio.h> 16#include <string.h> 17#include <stdlib.h> 18#include <stddef.h> 19#include <unistd.h> 20#include <time.h> 21#include <fcntl.h> 22#include <limits.h> 23#include <errno.h> 24#include <signal.h> 25#include <dlfcn.h> 26#include <assert.h> 27#include <sys/param.h> 28#include <sys/uio.h> 29#include <sys/time.h> 30 31#define FUSE_DEFAULT_INTR_SIGNAL SIGUSR1 32 33#define FUSE_UNKNOWN_INO 0xffffffff 34#define OFFSET_MAX 0x7fffffffffffffffLL 35 36struct fuse_config { 37 unsigned int uid; 38 unsigned int gid; 39 unsigned int umask; 40 double entry_timeout; 41 double negative_timeout; 42 double attr_timeout; 43 double ac_attr_timeout; 44 int ac_attr_timeout_set; 45 int debug; 46 int hard_remove; 47 int use_ino; 48 int readdir_ino; 49 int set_mode; 50 int set_uid; 51 int set_gid; 52 int direct_io; 53 int kernel_cache; 54 int intr; 55 int intr_signal; 56 int help; 57}; 58 59struct fuse_fs { 60 struct fuse_operations op; 61 void *user_data; 62}; 63 64struct fuse { 65 struct fuse_session *se; 66 struct node **name_table; 67 size_t name_table_size; 68 struct node **id_table; 69 size_t id_table_size; 70 fuse_ino_t ctr; 71 unsigned int generation; 72 unsigned int hidectr; 73 pthread_mutex_t lock; 74 pthread_rwlock_t tree_lock; 75 struct fuse_config conf; 76 int intr_installed; 77 struct fuse_fs *fs; 78}; 79 80struct lock { 81 int type; 82 off_t start; 83 off_t end; 84 pid_t pid; 85 uint64_t owner; 86 struct lock *next; 87}; 88 89struct node { 90 struct node *name_next; 91 struct node *id_next; 92 fuse_ino_t nodeid; 93 unsigned int generation; 94 int refctr; 95 struct node *parent; 96 char *name; 97 uint64_t nlookup; 98 int open_count; 99 int is_hidden; 100 struct lock *locks; 101}; 102 103struct fuse_dh { 104 pthread_mutex_t lock; 105 struct fuse *fuse; 106 fuse_req_t req; 107 char *contents; 108 int allocated; 109 unsigned len; 110 unsigned size; 111 unsigned needlen; 112 int filled; 113 uint64_t fh; 114 int error; 115 fuse_ino_t nodeid; 116}; 117 118struct fuse_context_i { 119 struct fuse_context ctx; 120 fuse_req_t req; 121}; 122 123static pthread_key_t fuse_context_key; 124static pthread_mutex_t fuse_context_lock = PTHREAD_MUTEX_INITIALIZER; 125static int fuse_context_ref; 126 127static struct node *get_node_nocheck(struct fuse *f, fuse_ino_t nodeid) 128{ 129 size_t hash = nodeid % f->id_table_size; 130 struct node *node; 131 132 for (node = f->id_table[hash]; node != NULL; node = node->id_next) 133 if (node->nodeid == nodeid) 134 return node; 135 136 return NULL; 137} 138 139static struct node *get_node(struct fuse *f, fuse_ino_t nodeid) 140{ 141 struct node *node = get_node_nocheck(f, nodeid); 142 if (!node) { 143 fprintf(stderr, "fuse internal error: node %llu not found\n", 144 (unsigned long long) nodeid); 145 abort(); 146 } 147 return node; 148} 149 150static void free_node(struct node *node) 151{ 152 free(node->name); 153 free(node); 154} 155 156static void unhash_id(struct fuse *f, struct node *node) 157{ 158 size_t hash = node->nodeid % f->id_table_size; 159 struct node **nodep = &f->id_table[hash]; 160 161 for (; *nodep != NULL; nodep = &(*nodep)->id_next) 162 if (*nodep == node) { 163 *nodep = node->id_next; 164 return; 165 } 166} 167 168static void hash_id(struct fuse *f, struct node *node) 169{ 170 size_t hash = node->nodeid % f->id_table_size; 171 node->id_next = f->id_table[hash]; 172 f->id_table[hash] = node; 173} 174 175static unsigned int name_hash(struct fuse *f, fuse_ino_t parent, 176 const char *name) 177{ 178 unsigned int hash = *name; 179 180 if (hash) 181 for (name += 1; *name != '\0'; name++) 182 hash = (hash << 5) - hash + *name; 183 184 return (hash + parent) % f->name_table_size; 185} 186 187static void unref_node(struct fuse *f, struct node *node); 188 189static void unhash_name(struct fuse *f, struct node *node) 190{ 191 if (node->name) { 192 size_t hash = name_hash(f, node->parent->nodeid, node->name); 193 struct node **nodep = &f->name_table[hash]; 194 195 for (; *nodep != NULL; nodep = &(*nodep)->name_next) 196 if (*nodep == node) { 197 *nodep = node->name_next; 198 node->name_next = NULL; 199 unref_node(f, node->parent); 200 free(node->name); 201 node->name = NULL; 202 node->parent = NULL; 203 return; 204 } 205 fprintf(stderr, "fuse internal error: unable to unhash node: %llu\n", 206 (unsigned long long) node->nodeid); 207 abort(); 208 } 209} 210 211static int hash_name(struct fuse *f, struct node *node, fuse_ino_t parentid, 212 const char *name) 213{ 214 size_t hash = name_hash(f, parentid, name); 215 struct node *parent = get_node(f, parentid); 216 node->name = strdup(name); 217 if (node->name == NULL) 218 return -1; 219 220 parent->refctr ++; 221 node->parent = parent; 222 node->name_next = f->name_table[hash]; 223 f->name_table[hash] = node; 224 return 0; 225} 226 227static void delete_node(struct fuse *f, struct node *node) 228{ 229 if (f->conf.debug) 230 fprintf(stderr, "delete: %llu\n", (unsigned long long) node->nodeid); 231 232 assert(!node->name); 233 unhash_id(f, node); 234 free_node(node); 235} 236 237static void unref_node(struct fuse *f, struct node *node) 238{ 239 assert(node->refctr > 0); 240 node->refctr --; 241 if (!node->refctr) 242 delete_node(f, node); 243} 244 245static fuse_ino_t next_id(struct fuse *f) 246{ 247 do { 248 f->ctr = (f->ctr + 1) & 0xffffffff; 249 if (!f->ctr) 250 f->generation ++; 251 } while (f->ctr == 0 || f->ctr == FUSE_UNKNOWN_INO || 252 get_node_nocheck(f, f->ctr) != NULL); 253 return f->ctr; 254} 255 256static struct node *lookup_node(struct fuse *f, fuse_ino_t parent, 257 const char *name) 258{ 259 size_t hash = name_hash(f, parent, name); 260 struct node *node; 261 262 for (node = f->name_table[hash]; node != NULL; node = node->name_next) 263 if (node->parent->nodeid == parent && strcmp(node->name, name) == 0) 264 return node; 265 266 return NULL; 267} 268 269static struct node *find_node(struct fuse *f, fuse_ino_t parent, 270 const char *name) 271{ 272 struct node *node; 273 274 pthread_mutex_lock(&f->lock); 275 node = lookup_node(f, parent, name); 276 if (node == NULL) { 277 node = (struct node *) calloc(1, sizeof(struct node)); 278 if (node == NULL) 279 goto out_err; 280 281 node->refctr = 1; 282 node->nodeid = next_id(f); 283 node->open_count = 0; 284 node->is_hidden = 0; 285 node->generation = f->generation; 286 if (hash_name(f, node, parent, name) == -1) { 287 free(node); 288 node = NULL; 289 goto out_err; 290 } 291 hash_id(f, node); 292 } 293 node->nlookup ++; 294 out_err: 295 pthread_mutex_unlock(&f->lock); 296 return node; 297} 298 299static char *add_name(char **buf, unsigned *bufsize, char *s, const char *name) 300{ 301 size_t len = strlen(name); 302 303 if (s - len <= *buf) { 304 unsigned pathlen = *bufsize - (s - *buf); 305 unsigned newbufsize = *bufsize; 306 char *newbuf; 307 308 while (newbufsize < pathlen + len + 1) { 309 if (newbufsize >= 0x80000000) 310 newbufsize = 0xffffffff; 311 else 312 newbufsize *= 2; 313 } 314 315 newbuf = realloc(*buf, newbufsize); 316 if (newbuf == NULL) 317 return NULL; 318 319 *buf = newbuf; 320 s = newbuf + newbufsize - pathlen; 321 memmove(s, newbuf + *bufsize - pathlen, pathlen); 322 *bufsize = newbufsize; 323 } 324 s -= len; 325 strncpy(s, name, len); 326 s--; 327 *s = '/'; 328 329 return s; 330} 331 332static char *get_path_name(struct fuse *f, fuse_ino_t nodeid, const char *name) 333{ 334 unsigned bufsize = 256; 335 char *buf; 336 char *s; 337 struct node *node; 338 339 buf = malloc(bufsize); 340 if (buf == NULL) 341 return NULL; 342 343 s = buf + bufsize - 1; 344 *s = '\0'; 345 346 if (name != NULL) { 347 s = add_name(&buf, &bufsize, s, name); 348 if (s == NULL) 349 goto out_free; 350 } 351 352 pthread_mutex_lock(&f->lock); 353 for (node = get_node(f, nodeid); node && node->nodeid != FUSE_ROOT_ID; 354 node = node->parent) { 355 if (node->name == NULL) { 356 s = NULL; 357 break; 358 } 359 360 s = add_name(&buf, &bufsize, s, node->name); 361 if (s == NULL) 362 break; 363 } 364 pthread_mutex_unlock(&f->lock); 365 366 if (node == NULL || s == NULL) 367 goto out_free; 368 369 if (s[0]) 370 memmove(buf, s, bufsize - (s - buf)); 371 else 372 strcpy(buf, "/"); 373 return buf; 374 375out_free: 376 free(buf); 377 return NULL; 378} 379 380static char *get_path(struct fuse *f, fuse_ino_t nodeid) 381{ 382 return get_path_name(f, nodeid, NULL); 383} 384 385static void forget_node(struct fuse *f, fuse_ino_t nodeid, uint64_t nlookup) 386{ 387 struct node *node; 388 if (nodeid == FUSE_ROOT_ID) 389 return; 390 pthread_mutex_lock(&f->lock); 391 node = get_node(f, nodeid); 392 assert(node->nlookup >= nlookup); 393 node->nlookup -= nlookup; 394 if (!node->nlookup) { 395 unhash_name(f, node); 396 unref_node(f, node); 397 } 398 pthread_mutex_unlock(&f->lock); 399} 400 401static void remove_node(struct fuse *f, fuse_ino_t dir, const char *name) 402{ 403 struct node *node; 404 405 pthread_mutex_lock(&f->lock); 406 node = lookup_node(f, dir, name); 407 if (node != NULL) 408 unhash_name(f, node); 409 pthread_mutex_unlock(&f->lock); 410} 411 412static int rename_node(struct fuse *f, fuse_ino_t olddir, const char *oldname, 413 fuse_ino_t newdir, const char *newname, int hide) 414{ 415 struct node *node; 416 struct node *newnode; 417 int err = 0; 418 419 pthread_mutex_lock(&f->lock); 420 node = lookup_node(f, olddir, oldname); 421 newnode = lookup_node(f, newdir, newname); 422 if (node == NULL) 423 goto out; 424 425 if (newnode != NULL) { 426 if (hide) { 427 fprintf(stderr, "fuse: hidden file got created during hiding\n"); 428 err = -EBUSY; 429 goto out; 430 } 431 unhash_name(f, newnode); 432 } 433 434 unhash_name(f, node); 435 if (hash_name(f, node, newdir, newname) == -1) { 436 err = -ENOMEM; 437 goto out; 438 } 439 440 if (hide) 441 node->is_hidden = 1; 442 443 out: 444 pthread_mutex_unlock(&f->lock); 445 return err; 446} 447 448static void set_stat(struct fuse *f, fuse_ino_t nodeid, struct stat *stbuf) 449{ 450 if (!f->conf.use_ino) 451 stbuf->st_ino = nodeid; 452 if (f->conf.set_mode) 453 stbuf->st_mode = (stbuf->st_mode & S_IFMT) | (0777 & ~f->conf.umask); 454 if (f->conf.set_uid) 455 stbuf->st_uid = f->conf.uid; 456 if (f->conf.set_gid) 457 stbuf->st_gid = f->conf.gid; 458} 459 460static struct fuse *req_fuse(fuse_req_t req) 461{ 462 return (struct fuse *) fuse_req_userdata(req); 463} 464 465static void fuse_intr_sighandler(int sig) 466{ 467 (void) sig; 468 /* Nothing to do */ 469} 470 471struct fuse_intr_data { 472 pthread_t id; 473 pthread_cond_t cond; 474 int finished; 475}; 476 477static void fuse_interrupt(fuse_req_t req, void *d_) 478{ 479 struct fuse_intr_data *d = d_; 480 struct fuse *f = req_fuse(req); 481 482 if (d->id == pthread_self()) 483 return; 484 485 pthread_mutex_lock(&f->lock); 486 while (!d->finished) { 487 struct timeval now; 488 struct timespec timeout; 489 490 pthread_kill(d->id, f->conf.intr_signal); 491 gettimeofday(&now, NULL); 492 timeout.tv_sec = now.tv_sec + 1; 493 timeout.tv_nsec = now.tv_usec * 1000; 494 pthread_cond_timedwait(&d->cond, &f->lock, &timeout); 495 } 496 pthread_mutex_unlock(&f->lock); 497} 498 499static void fuse_do_finish_interrupt(struct fuse *f, fuse_req_t req, 500 struct fuse_intr_data *d) 501{ 502 pthread_mutex_lock(&f->lock); 503 d->finished = 1; 504 pthread_cond_broadcast(&d->cond); 505 pthread_mutex_unlock(&f->lock); 506 fuse_req_interrupt_func(req, NULL, NULL); 507 pthread_cond_destroy(&d->cond); 508} 509 510static void fuse_do_prepare_interrupt(fuse_req_t req, struct fuse_intr_data *d) 511{ 512 d->id = pthread_self(); 513 pthread_cond_init(&d->cond, NULL); 514 d->finished = 0; 515 fuse_req_interrupt_func(req, fuse_interrupt, d); 516} 517 518static void fuse_finish_interrupt(struct fuse *f, fuse_req_t req, 519 struct fuse_intr_data *d) 520{ 521 if (f->conf.intr) 522 fuse_do_finish_interrupt(f, req, d); 523} 524 525static void fuse_prepare_interrupt(struct fuse *f, fuse_req_t req, 526 struct fuse_intr_data *d) 527{ 528 if (f->conf.intr) 529 fuse_do_prepare_interrupt(req, d); 530} 531 532int fuse_fs_getattr(struct fuse_fs *fs, const char *path, struct stat *buf) 533{ 534 fuse_get_context()->private_data = fs->user_data; 535 if (fs->op.getattr) 536 return fs->op.getattr(path, buf); 537 else 538 return -ENOSYS; 539} 540 541int fuse_fs_fgetattr(struct fuse_fs *fs, const char *path, struct stat *buf, 542 struct fuse_file_info *fi) 543{ 544 fuse_get_context()->private_data = fs->user_data; 545 if (fs->op.fgetattr) 546 return fs->op.fgetattr(path, buf, fi); 547 else if (fs->op.getattr) 548 return fs->op.getattr(path, buf); 549 else 550 return -ENOSYS; 551} 552 553int fuse_fs_rename(struct fuse_fs *fs, const char *oldpath, 554 const char *newpath) 555{ 556 fuse_get_context()->private_data = fs->user_data; 557 if (fs->op.rename) 558 return fs->op.rename(oldpath, newpath); 559 else 560 return -ENOSYS; 561} 562 563int fuse_fs_unlink(struct fuse_fs *fs, const char *path) 564{ 565 fuse_get_context()->private_data = fs->user_data; 566 if (fs->op.unlink) 567 return fs->op.unlink(path); 568 else 569 return -ENOSYS; 570} 571 572int fuse_fs_rmdir(struct fuse_fs *fs, const char *path) 573{ 574 fuse_get_context()->private_data = fs->user_data; 575 if (fs->op.rmdir) 576 return fs->op.rmdir(path); 577 else 578 return -ENOSYS; 579} 580 581int fuse_fs_symlink(struct fuse_fs *fs, const char *linkname, const char *path) 582{ 583 fuse_get_context()->private_data = fs->user_data; 584 if (fs->op.symlink) 585 return fs->op.symlink(linkname, path); 586 else 587 return -ENOSYS; 588} 589 590int fuse_fs_link(struct fuse_fs *fs, const char *oldpath, const char *newpath) 591{ 592 fuse_get_context()->private_data = fs->user_data; 593 if (fs->op.link) 594 return fs->op.link(oldpath, newpath); 595 else 596 return -ENOSYS; 597} 598 599int fuse_fs_release(struct fuse_fs *fs, const char *path, 600 struct fuse_file_info *fi) 601{ 602 fuse_get_context()->private_data = fs->user_data; 603 if (fs->op.release) 604 return fs->op.release(path, fi); 605 else 606 return 0; 607} 608 609int fuse_fs_opendir(struct fuse_fs *fs, const char *path, 610 struct fuse_file_info *fi) 611{ 612 fuse_get_context()->private_data = fs->user_data; 613 if (fs->op.opendir) 614 return fs->op.opendir(path, fi); 615 else 616 return 0; 617} 618 619int fuse_fs_open(struct fuse_fs *fs, const char *path, 620 struct fuse_file_info *fi) 621{ 622 fuse_get_context()->private_data = fs->user_data; 623 if (fs->op.open) 624 return fs->op.open(path, fi); 625 else 626 return 0; 627} 628 629int fuse_fs_read(struct fuse_fs *fs, const char *path, char *buf, size_t size, 630 off_t off, struct fuse_file_info *fi) 631{ 632 fuse_get_context()->private_data = fs->user_data; 633 if (fs->op.read) 634 return fs->op.read(path, buf, size, off, fi); 635 else 636 return -ENOSYS; 637} 638 639int fuse_fs_write(struct fuse_fs *fs, const char *path, const char *buf, 640 size_t size, off_t off, struct fuse_file_info *fi) 641{ 642 fuse_get_context()->private_data = fs->user_data; 643 if (fs->op.write) 644 return fs->op.write(path, buf, size, off, fi); 645 else 646 return -ENOSYS; 647} 648 649int fuse_fs_fsync(struct fuse_fs *fs, const char *path, int datasync, 650 struct fuse_file_info *fi) 651{ 652 fuse_get_context()->private_data = fs->user_data; 653 if (fs->op.fsync) 654 return fs->op.fsync(path, datasync, fi); 655 else 656 return -ENOSYS; 657} 658 659int fuse_fs_fsyncdir(struct fuse_fs *fs, const char *path, int datasync, 660 struct fuse_file_info *fi) 661{ 662 fuse_get_context()->private_data = fs->user_data; 663 if (fs->op.fsyncdir) 664 return fs->op.fsyncdir(path, datasync, fi); 665 else 666 return -ENOSYS; 667} 668 669int fuse_fs_flush(struct fuse_fs *fs, const char *path, 670 struct fuse_file_info *fi) 671{ 672 fuse_get_context()->private_data = fs->user_data; 673 if (fs->op.flush) 674 return fs->op.flush(path, fi); 675 else 676 return -ENOSYS; 677} 678 679int fuse_fs_statfs(struct fuse_fs *fs, const char *path, struct statvfs *buf) 680{ 681 fuse_get_context()->private_data = fs->user_data; 682 if (fs->op.statfs) 683 return fs->op.statfs(path, buf); 684 else { 685 buf->f_namemax = 255; 686 buf->f_bsize = 512; 687 return 0; 688 } 689} 690 691int fuse_fs_releasedir(struct fuse_fs *fs, const char *path, 692 struct fuse_file_info *fi) 693{ 694 fuse_get_context()->private_data = fs->user_data; 695 if (fs->op.releasedir) 696 return fs->op.releasedir(path, fi); 697 else 698 return 0; 699} 700 701int fuse_fs_readdir(struct fuse_fs *fs, const char *path, void *buf, 702 fuse_fill_dir_t filler, off_t off, 703 struct fuse_file_info *fi) 704{ 705 fuse_get_context()->private_data = fs->user_data; 706 if (fs->op.readdir) 707 return fs->op.readdir(path, buf, filler, off, fi); 708 else 709 return -ENOSYS; 710} 711 712int fuse_fs_create(struct fuse_fs *fs, const char *path, mode_t mode, 713 struct fuse_file_info *fi) 714{ 715 fuse_get_context()->private_data = fs->user_data; 716 if (fs->op.create) 717 return fs->op.create(path, mode, fi); 718 else 719 return -ENOSYS; 720} 721 722int fuse_fs_lock(struct fuse_fs *fs, const char *path, 723 struct fuse_file_info *fi, int cmd, struct flock *lock) 724{ 725 fuse_get_context()->private_data = fs->user_data; 726 if (fs->op.lock) 727 return fs->op.lock(path, fi, cmd, lock); 728 else 729 return -ENOSYS; 730} 731 732int fuse_fs_chown(struct fuse_fs *fs, const char *path, uid_t uid, gid_t gid) 733{ 734 fuse_get_context()->private_data = fs->user_data; 735 if (fs->op.chown) 736 return fs->op.chown(path, uid, gid); 737 else 738 return -ENOSYS; 739} 740 741int fuse_fs_truncate(struct fuse_fs *fs, const char *path, off_t size) 742{ 743 fuse_get_context()->private_data = fs->user_data; 744 if (fs->op.truncate) 745 return fs->op.truncate(path, size); 746 else 747 return -ENOSYS; 748} 749 750int fuse_fs_ftruncate(struct fuse_fs *fs, const char *path, off_t size, 751 struct fuse_file_info *fi) 752{ 753 fuse_get_context()->private_data = fs->user_data; 754 if (fs->op.ftruncate) 755 return fs->op.ftruncate(path, size, fi); 756 else if (fs->op.truncate) 757 return fs->op.truncate(path, size); 758 else 759 return -ENOSYS; 760} 761 762int fuse_fs_utimens(struct fuse_fs *fs, const char *path, 763 const struct timespec tv[2]) 764{ 765 fuse_get_context()->private_data = fs->user_data; 766 if (fs->op.utimens) 767 return fs->op.utimens(path, tv); 768 else if(fs->op.utime) { 769 struct utimbuf buf; 770 buf.actime = tv[0].tv_sec; 771 buf.modtime = tv[1].tv_sec; 772 return fs->op.utime(path, &buf); 773 } else 774 return -ENOSYS; 775} 776 777int fuse_fs_access(struct fuse_fs *fs, const char *path, int mask) 778{ 779 fuse_get_context()->private_data = fs->user_data; 780 if (fs->op.access) 781 return fs->op.access(path, mask); 782 else 783 return -ENOSYS; 784} 785 786int fuse_fs_readlink(struct fuse_fs *fs, const char *path, char *buf, 787 size_t len) 788{ 789 fuse_get_context()->private_data = fs->user_data; 790 if (fs->op.readlink) 791 return fs->op.readlink(path, buf, len); 792 else 793 return -ENOSYS; 794} 795 796int fuse_fs_mknod(struct fuse_fs *fs, const char *path, mode_t mode, 797 dev_t rdev) 798{ 799 fuse_get_context()->private_data = fs->user_data; 800 if (fs->op.mknod) 801 return fs->op.mknod(path, mode, rdev); 802 else 803 return -ENOSYS; 804} 805 806int fuse_fs_mkdir(struct fuse_fs *fs, const char *path, mode_t mode) 807{ 808 fuse_get_context()->private_data = fs->user_data; 809 if (fs->op.mkdir) 810 return fs->op.mkdir(path, mode); 811 else 812 return -ENOSYS; 813} 814 815int fuse_fs_setxattr(struct fuse_fs *fs, const char *path, const char *name, 816 const char *value, size_t size, int flags) 817{ 818 fuse_get_context()->private_data = fs->user_data; 819 if (fs->op.setxattr) 820 return fs->op.setxattr(path, name, value, size, flags); 821 else 822 return -ENOSYS; 823} 824 825int fuse_fs_getxattr(struct fuse_fs *fs, const char *path, const char *name, 826 char *value, size_t size) 827{ 828 fuse_get_context()->private_data = fs->user_data; 829 if (fs->op.getxattr) 830 return fs->op.getxattr(path, name, value, size); 831 else 832 return -ENOSYS; 833} 834 835int fuse_fs_listxattr(struct fuse_fs *fs, const char *path, char *list, 836 size_t size) 837{ 838 fuse_get_context()->private_data = fs->user_data; 839 if (fs->op.listxattr) 840 return fs->op.listxattr(path, list, size); 841 else 842 return -ENOSYS; 843} 844 845int fuse_fs_bmap(struct fuse_fs *fs, const char *path, size_t blocksize, 846 uint64_t *idx) 847{ 848 fuse_get_context()->private_data = fs->user_data; 849 if (fs->op.bmap) 850 return fs->op.bmap(path, blocksize, idx); 851 else 852 return -ENOSYS; 853} 854 855int fuse_fs_removexattr(struct fuse_fs *fs, const char *path, const char *name) 856{ 857 fuse_get_context()->private_data = fs->user_data; 858 if (fs->op.removexattr) 859 return fs->op.removexattr(path, name); 860 else 861 return -ENOSYS; 862} 863 864static int is_open(struct fuse *f, fuse_ino_t dir, const char *name) 865{ 866 struct node *node; 867 int isopen = 0; 868 pthread_mutex_lock(&f->lock); 869 node = lookup_node(f, dir, name); 870 if (node && node->open_count > 0) 871 isopen = 1; 872 pthread_mutex_unlock(&f->lock); 873 return isopen; 874} 875 876static char *hidden_name(struct fuse *f, fuse_ino_t dir, const char *oldname, 877 char *newname, size_t bufsize) 878{ 879 struct stat buf; 880 struct node *node; 881 struct node *newnode; 882 char *newpath; 883 int res; 884 int failctr = 10; 885 886 do { 887 pthread_mutex_lock(&f->lock); 888 node = lookup_node(f, dir, oldname); 889 if (node == NULL) { 890 pthread_mutex_unlock(&f->lock); 891 return NULL; 892 } 893 do { 894 f->hidectr ++; 895 snprintf(newname, bufsize, ".fuse_hidden%08x%08x", 896 (unsigned int) node->nodeid, f->hidectr); 897 newnode = lookup_node(f, dir, newname); 898 } while(newnode); 899 pthread_mutex_unlock(&f->lock); 900 901 newpath = get_path_name(f, dir, newname); 902 if (!newpath) 903 break; 904 905 res = fuse_fs_getattr(f->fs, newpath, &buf); 906 if (res == -ENOENT) 907 break; 908 free(newpath); 909 newpath = NULL; 910 } while(res == 0 && --failctr); 911 912 return newpath; 913} 914 915static int hide_node(struct fuse *f, const char *oldpath, 916 fuse_ino_t dir, const char *oldname) 917{ 918 char newname[64]; 919 char *newpath; 920 int err = -EBUSY; 921 922 newpath = hidden_name(f, dir, oldname, newname, sizeof(newname)); 923 if (newpath) { 924 err = fuse_fs_rename(f->fs, oldpath, newpath); 925 if (!err) 926 err = rename_node(f, dir, oldname, dir, newname, 1); 927 free(newpath); 928 } 929 return err; 930} 931 932static int lookup_path(struct fuse *f, fuse_ino_t nodeid, 933 const char *name, const char *path, 934 struct fuse_entry_param *e, struct fuse_file_info *fi) 935{ 936 int res; 937 938 memset(e, 0, sizeof(struct fuse_entry_param)); 939 if (fi) 940 res = fuse_fs_fgetattr(f->fs, path, &e->attr, fi); 941 else 942 res = fuse_fs_getattr(f->fs, path, &e->attr); 943 if (res == 0) { 944 struct node *node; 945 946 node = find_node(f, nodeid, name); 947 if (node == NULL) 948 res = -ENOMEM; 949 else { 950 e->ino = node->nodeid; 951 e->generation = node->generation; 952 e->entry_timeout = f->conf.entry_timeout; 953 e->attr_timeout = f->conf.attr_timeout; 954 set_stat(f, e->ino, &e->attr); 955 if (f->conf.debug) 956 fprintf(stderr, " NODEID: %lu\n", (unsigned long) e->ino); 957 } 958 } 959 return res; 960} 961 962static struct fuse_context_i *fuse_get_context_internal(void) 963{ 964 struct fuse_context_i *c; 965 966 c = (struct fuse_context_i *) pthread_getspecific(fuse_context_key); 967 if (c == NULL) { 968 c = (struct fuse_context_i *) malloc(sizeof(struct fuse_context_i)); 969 if (c == NULL) { 970 /* This is hard to deal with properly, so just abort. If 971 memory is so low that the context cannot be allocated, 972 there's not much hope for the filesystem anyway */ 973 fprintf(stderr, "fuse: failed to allocate thread specific data\n"); 974 abort(); 975 } 976 pthread_setspecific(fuse_context_key, c); 977 } 978 return c; 979} 980 981static void fuse_freecontext(void *data) 982{ 983 free(data); 984} 985 986static int fuse_create_context_key(void) 987{ 988 int err = 0; 989 pthread_mutex_lock(&fuse_context_lock); 990 if (!fuse_context_ref) { 991 err = pthread_key_create(&fuse_context_key, fuse_freecontext); 992 if (err) { 993 fprintf(stderr, "fuse: failed to create thread specific key: %s\n", 994 strerror(err)); 995 pthread_mutex_unlock(&fuse_context_lock); 996 return -1; 997 } 998 } 999 fuse_context_ref++; 1000 pthread_mutex_unlock(&fuse_context_lock); 1001 return 0; 1002} 1003 1004static void fuse_delete_context_key(void) 1005{ 1006 pthread_mutex_lock(&fuse_context_lock); 1007 fuse_context_ref--; 1008 if (!fuse_context_ref) { 1009 free(pthread_getspecific(fuse_context_key)); 1010 pthread_key_delete(fuse_context_key); 1011 } 1012 pthread_mutex_unlock(&fuse_context_lock); 1013} 1014 1015static struct fuse *req_fuse_prepare(fuse_req_t req) 1016{ 1017 struct fuse_context_i *c = fuse_get_context_internal(); 1018 const struct fuse_ctx *ctx = fuse_req_ctx(req); 1019 c->req = req; 1020 c->ctx.fuse = req_fuse(req); 1021 c->ctx.uid = ctx->uid; 1022 c->ctx.gid = ctx->gid; 1023 c->ctx.pid = ctx->pid; 1024 return c->ctx.fuse; 1025} 1026 1027static void reply_err(fuse_req_t req, int err) 1028{ 1029 /* fuse_reply_err() uses non-negated errno values */ 1030 fuse_reply_err(req, -err); 1031} 1032 1033static void reply_entry(fuse_req_t req, const struct fuse_entry_param *e, 1034 int err) 1035{ 1036 if (!err) { 1037 struct fuse *f = req_fuse(req); 1038 if (fuse_reply_entry(req, e) == -ENOENT) 1039 forget_node(f, e->ino, 1); 1040 } else 1041 reply_err(req, err); 1042} 1043 1044void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn) 1045{ 1046 fuse_get_context()->private_data = fs->user_data; 1047 if (fs->op.init) 1048 fs->user_data = fs->op.init(conn); 1049} 1050 1051static void fuse_lib_init(void *data, struct fuse_conn_info *conn) 1052{ 1053 struct fuse *f = (struct fuse *) data; 1054 struct fuse_context_i *c = fuse_get_context_internal(); 1055 1056 memset(c, 0, sizeof(*c)); 1057 c->ctx.fuse = f; 1058 fuse_fs_init(f->fs, conn); 1059} 1060 1061void fuse_fs_destroy(struct fuse_fs *fs) 1062{ 1063 fuse_get_context()->private_data = fs->user_data; 1064 if (fs->op.destroy) 1065 fs->op.destroy(fs->user_data); 1066 free(fs); 1067} 1068 1069static void fuse_lib_destroy(void *data) 1070{ 1071 struct fuse *f = (struct fuse *) data; 1072 struct fuse_context_i *c = fuse_get_context_internal(); 1073 1074 memset(c, 0, sizeof(*c)); 1075 c->ctx.fuse = f; 1076 fuse_fs_destroy(f->fs); 1077 f->fs = NULL; 1078} 1079 1080static void fuse_lib_lookup(fuse_req_t req, fuse_ino_t parent, 1081 const char *name) 1082{ 1083 struct fuse *f = req_fuse_prepare(req); 1084 struct fuse_entry_param e; 1085 char *path; 1086 int err; 1087 1088 err = -ENOENT; 1089 pthread_rwlock_rdlock(&f->tree_lock); 1090 path = get_path_name(f, parent, name); 1091 if (path != NULL) { 1092 struct fuse_intr_data d; 1093 if (f->conf.debug) 1094 fprintf(stderr, "LOOKUP %s\n", path); 1095 fuse_prepare_interrupt(f, req, &d); 1096 err = lookup_path(f, parent, name, path, &e, NULL); 1097 if (err == -ENOENT && f->conf.negative_timeout != 0.0) { 1098 e.ino = 0; 1099 e.entry_timeout = f->conf.negative_timeout; 1100 err = 0; 1101 } 1102 fuse_finish_interrupt(f, req, &d); 1103 free(path); 1104 } 1105 pthread_rwlock_unlock(&f->tree_lock); 1106 reply_entry(req, &e, err); 1107} 1108 1109static void fuse_lib_forget(fuse_req_t req, fuse_ino_t ino, 1110 unsigned long nlookup) 1111{ 1112 struct fuse *f = req_fuse(req); 1113 if (f->conf.debug) 1114 fprintf(stderr, "FORGET %llu/%lu\n", (unsigned long long)ino, nlookup); 1115 forget_node(f, ino, nlookup); 1116 fuse_reply_none(req); 1117} 1118 1119static void fuse_lib_getattr(fuse_req_t req, fuse_ino_t ino, 1120 struct fuse_file_info *fi) 1121{ 1122 struct fuse *f = req_fuse_prepare(req); 1123 struct stat buf; 1124 char *path; 1125 int err; 1126 1127 (void) fi; 1128 memset(&buf, 0, sizeof(buf)); 1129 1130 err = -ENOENT; 1131 pthread_rwlock_rdlock(&f->tree_lock); 1132 path = get_path(f, ino); 1133 if (path != NULL) { 1134 struct fuse_intr_data d; 1135 fuse_prepare_interrupt(f, req, &d); 1136 err = fuse_fs_getattr(f->fs, path, &buf); 1137 fuse_finish_interrupt(f, req, &d); 1138 free(path); 1139 } 1140 pthread_rwlock_unlock(&f->tree_lock); 1141 if (!err) { 1142 set_stat(f, ino, &buf); 1143 fuse_reply_attr(req, &buf, f->conf.attr_timeout); 1144 } else 1145 reply_err(req, err); 1146} 1147 1148int fuse_fs_chmod(struct fuse_fs *fs, const char *path, mode_t mode) 1149{ 1150 fuse_get_context()->private_data = fs->user_data; 1151 if (fs->op.chmod) 1152 return fs->op.chmod(path, mode); 1153 else 1154 return -ENOSYS; 1155} 1156 1157static void fuse_lib_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr, 1158 int valid, struct fuse_file_info *fi) 1159{ 1160 struct fuse *f = req_fuse_prepare(req); 1161 struct stat buf; 1162 char *path; 1163 int err; 1164 1165 err = -ENOENT; 1166 pthread_rwlock_rdlock(&f->tree_lock); 1167 path = get_path(f, ino); 1168 if (path != NULL) { 1169 struct fuse_intr_data d; 1170 fuse_prepare_interrupt(f, req, &d); 1171 err = 0; 1172 if (!err && (valid & FUSE_SET_ATTR_MODE)) 1173 err = fuse_fs_chmod(f->fs, path, attr->st_mode); 1174 if (!err && (valid & (FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID))) { 1175 uid_t uid = 1176 (valid & FUSE_SET_ATTR_UID) ? attr->st_uid : (uid_t) -1; 1177 gid_t gid = 1178 (valid & FUSE_SET_ATTR_GID) ? attr->st_gid : (gid_t) -1; 1179 err = fuse_fs_chown(f->fs, path, uid, gid); 1180 } 1181 if (!err && (valid & FUSE_SET_ATTR_SIZE)) { 1182 if (fi) 1183 err = fuse_fs_ftruncate(f->fs, path, attr->st_size, fi); 1184 else 1185 err = fuse_fs_truncate(f->fs, path, attr->st_size); 1186 } 1187 if (!err && (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) == 1188 (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) { 1189 struct timespec tv[2]; 1190 tv[0].tv_sec = attr->st_atime; 1191 tv[0].tv_nsec = ST_ATIM_NSEC(attr); 1192 tv[1].tv_sec = attr->st_mtime; 1193 tv[1].tv_nsec = ST_MTIM_NSEC(attr); 1194 err = fuse_fs_utimens(f->fs, path, tv); 1195 } 1196 if (!err) 1197 err = fuse_fs_getattr(f->fs, path, &buf); 1198 fuse_finish_interrupt(f, req, &d); 1199 free(path); 1200 } 1201 pthread_rwlock_unlock(&f->tree_lock); 1202 if (!err) { 1203 set_stat(f, ino, &buf); 1204 fuse_reply_attr(req, &buf, f->conf.attr_timeout); 1205 } else 1206 reply_err(req, err); 1207} 1208 1209static void fuse_lib_access(fuse_req_t req, fuse_ino_t ino, int mask) 1210{ 1211 struct fuse *f = req_fuse_prepare(req); 1212 char *path; 1213 int err; 1214 1215 err = -ENOENT; 1216 pthread_rwlock_rdlock(&f->tree_lock); 1217 path = get_path(f, ino); 1218 if (path != NULL) { 1219 struct fuse_intr_data d; 1220 if (f->conf.debug) 1221 fprintf(stderr, "ACCESS %s 0%o\n", path, mask); 1222 fuse_prepare_interrupt(f, req, &d); 1223 err = fuse_fs_access(f->fs, path, mask); 1224 fuse_finish_interrupt(f, req, &d); 1225 free(path); 1226 } 1227 pthread_rwlock_unlock(&f->tree_lock); 1228 reply_err(req, err); 1229} 1230 1231static void fuse_lib_readlink(fuse_req_t req, fuse_ino_t ino) 1232{ 1233 struct fuse *f = req_fuse_prepare(req); 1234 char linkname[PATH_MAX + 1]; 1235 char *path; 1236 int err; 1237 1238 err = -ENOENT; 1239 pthread_rwlock_rdlock(&f->tree_lock); 1240 path = get_path(f, ino); 1241 if (path != NULL) { 1242 struct fuse_intr_data d; 1243 fuse_prepare_interrupt(f, req, &d); 1244 err = fuse_fs_readlink(f->fs, path, linkname, sizeof(linkname)); 1245 fuse_finish_interrupt(f, req, &d); 1246 free(path); 1247 } 1248 pthread_rwlock_unlock(&f->tree_lock); 1249 if (!err) { 1250 linkname[PATH_MAX] = '\0'; 1251 fuse_reply_readlink(req, linkname); 1252 } else 1253 reply_err(req, err); 1254} 1255 1256static void fuse_lib_mknod(fuse_req_t req, fuse_ino_t parent, const char *name, 1257 mode_t mode, dev_t rdev) 1258{ 1259 struct fuse *f = req_fuse_prepare(req); 1260 struct fuse_entry_param e; 1261 char *path; 1262 int err; 1263 1264 err = -ENOENT; 1265 pthread_rwlock_rdlock(&f->tree_lock); 1266 path = get_path_name(f, parent, name); 1267 if (path) { 1268 struct fuse_intr_data d; 1269 if (f->conf.debug) 1270 fprintf(stderr, "MKNOD %s\n", path); 1271 fuse_prepare_interrupt(f, req, &d); 1272 err = -ENOSYS; 1273 if (S_ISREG(mode)) { 1274 struct fuse_file_info fi; 1275 1276 memset(&fi, 0, sizeof(fi)); 1277 fi.flags = O_CREAT | O_EXCL | O_WRONLY; 1278 err = fuse_fs_create(f->fs, path, mode, &fi); 1279 if (!err) { 1280 err = lookup_path(f, parent, name, path, &e, &fi); 1281 fuse_fs_release(f->fs, path, &fi); 1282 } 1283 } 1284 if (err == -ENOSYS) { 1285 err = fuse_fs_mknod(f->fs, path, mode, rdev); 1286 if (!err) 1287 err = lookup_path(f, parent, name, path, &e, NULL); 1288 } 1289 fuse_finish_interrupt(f, req, &d); 1290 free(path); 1291 } 1292 pthread_rwlock_unlock(&f->tree_lock); 1293 reply_entry(req, &e, err); 1294} 1295 1296static void fuse_lib_mkdir(fuse_req_t req, fuse_ino_t parent, const char *name, 1297 mode_t mode) 1298{ 1299 struct fuse *f = req_fuse_prepare(req); 1300 struct fuse_entry_param e; 1301 char *path; 1302 int err; 1303 1304 err = -ENOENT; 1305 pthread_rwlock_rdlock(&f->tree_lock); 1306 path = get_path_name(f, parent, name); 1307 if (path != NULL) { 1308 struct fuse_intr_data d; 1309 if (f->conf.debug) 1310 fprintf(stderr, "MKDIR %s\n", path); 1311 fuse_prepare_interrupt(f, req, &d); 1312 err = fuse_fs_mkdir(f->fs, path, mode); 1313 if (!err) 1314 err = lookup_path(f, parent, name, path, &e, NULL); 1315 fuse_finish_interrupt(f, req, &d); 1316 free(path); 1317 } 1318 pthread_rwlock_unlock(&f->tree_lock); 1319 reply_entry(req, &e, err); 1320} 1321 1322static void fuse_lib_unlink(fuse_req_t req, fuse_ino_t parent, 1323 const char *name) 1324{ 1325 struct fuse *f = req_fuse_prepare(req); 1326 char *path; 1327 int err; 1328 1329 err = -ENOENT; 1330 pthread_rwlock_wrlock(&f->tree_lock); 1331 path = get_path_name(f, parent, name); 1332 if (path != NULL) { 1333 struct fuse_intr_data d; 1334 if (f->conf.debug) 1335 fprintf(stderr, "UNLINK %s\n", path); 1336 fuse_prepare_interrupt(f, req, &d); 1337 if (!f->conf.hard_remove && is_open(f, parent, name)) 1338 err = hide_node(f, path, parent, name); 1339 else { 1340 err = fuse_fs_unlink(f->fs, path); 1341 if (!err) 1342 remove_node(f, parent, name); 1343 } 1344 fuse_finish_interrupt(f, req, &d); 1345 free(path); 1346 } 1347 pthread_rwlock_unlock(&f->tree_lock); 1348 reply_err(req, err); 1349} 1350 1351static void fuse_lib_rmdir(fuse_req_t req, fuse_ino_t parent, const char *name) 1352{ 1353 struct fuse *f = req_fuse_prepare(req); 1354 char *path; 1355 int err; 1356 1357 err = -ENOENT; 1358 pthread_rwlock_wrlock(&f->tree_lock); 1359 path = get_path_name(f, parent, name); 1360 if (path != NULL) { 1361 struct fuse_intr_data d; 1362 if (f->conf.debug) 1363 fprintf(stderr, "RMDIR %s\n", path); 1364 fuse_prepare_interrupt(f, req, &d); 1365 err = fuse_fs_rmdir(f->fs, path); 1366 fuse_finish_interrupt(f, req, &d); 1367 if (!err) 1368 remove_node(f, parent, name); 1369 free(path); 1370 } 1371 pthread_rwlock_unlock(&f->tree_lock); 1372 reply_err(req, err); 1373} 1374 1375static void fuse_lib_symlink(fuse_req_t req, const char *linkname, 1376 fuse_ino_t parent, const char *name) 1377{ 1378 struct fuse *f = req_fuse_prepare(req); 1379 struct fuse_entry_param e; 1380 char *path; 1381 int err; 1382 1383 err = -ENOENT; 1384 pthread_rwlock_rdlock(&f->tree_lock); 1385 path = get_path_name(f, parent, name); 1386 if (path != NULL) { 1387 struct fuse_intr_data d; 1388 if (f->conf.debug) 1389 fprintf(stderr, "SYMLINK %s\n", path); 1390 fuse_prepare_interrupt(f, req, &d); 1391 err = fuse_fs_symlink(f->fs, linkname, path); 1392 if (!err) 1393 err = lookup_path(f, parent, name, path, &e, NULL); 1394 fuse_finish_interrupt(f, req, &d); 1395 free(path); 1396 } 1397 pthread_rwlock_unlock(&f->tree_lock); 1398 reply_entry(req, &e, err); 1399} 1400 1401static void fuse_lib_rename(fuse_req_t req, fuse_ino_t olddir, 1402 const char *oldname, fuse_ino_t newdir, 1403 const char *newname) 1404{ 1405 struct fuse *f = req_fuse_prepare(req); 1406 char *oldpath; 1407 char *newpath; 1408 int err; 1409 1410 err = -ENOENT; 1411 pthread_rwlock_wrlock(&f->tree_lock); 1412 oldpath = get_path_name(f, olddir, oldname); 1413 if (oldpath != NULL) { 1414 newpath = get_path_name(f, newdir, newname); 1415 if (newpath != NULL) { 1416 struct fuse_intr_data d; 1417 if (f->conf.debug) 1418 fprintf(stderr, "RENAME %s -> %s\n", oldpath, newpath); 1419 err = 0; 1420 fuse_prepare_interrupt(f, req, &d); 1421 if (!f->conf.hard_remove && is_open(f, newdir, newname)) 1422 err = hide_node(f, newpath, newdir, newname); 1423 if (!err) { 1424 err = fuse_fs_rename(f->fs, oldpath, newpath); 1425 if (!err) 1426 err = rename_node(f, olddir, oldname, newdir, newname, 0); 1427 } 1428 fuse_finish_interrupt(f, req, &d); 1429 free(newpath); 1430 } 1431 free(oldpath); 1432 } 1433 pthread_rwlock_unlock(&f->tree_lock); 1434 reply_err(req, err); 1435} 1436 1437static void fuse_lib_link(fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent, 1438 const char *newname) 1439{ 1440 struct fuse *f = req_fuse_prepare(req); 1441 struct fuse_entry_param e; 1442 char *oldpath; 1443 char *newpath; 1444 int err; 1445 1446 err = -ENOENT; 1447 pthread_rwlock_rdlock(&f->tree_lock); 1448 oldpath = get_path(f, ino); 1449 if (oldpath != NULL) { 1450 newpath = get_path_name(f, newparent, newname); 1451 if (newpath != NULL) { 1452 struct fuse_intr_data d; 1453 if (f->conf.debug) 1454 fprintf(stderr, "LINK %s\n", newpath); 1455 fuse_prepare_interrupt(f, req, &d); 1456 err = fuse_fs_link(f->fs, oldpath, newpath); 1457 if (!err) 1458 err = lookup_path(f, newparent, newname, newpath, &e, NULL); 1459 fuse_finish_interrupt(f, req, &d); 1460 free(newpath); 1461 } 1462 free(oldpath); 1463 } 1464 pthread_rwlock_unlock(&f->tree_lock); 1465 reply_entry(req, &e, err); 1466} 1467 1468static void fuse_do_release(struct fuse *f, fuse_ino_t ino, const char *path, 1469 struct fuse_file_info *fi) 1470{ 1471 struct node *node; 1472 int unlink_hidden = 0; 1473 1474 fuse_fs_release(f->fs, path ? path : "-", fi); 1475 1476 pthread_mutex_lock(&f->lock); 1477 node = get_node(f, ino); 1478 assert(node->open_count > 0); 1479 --node->open_count; 1480 if (node->is_hidden && !node->open_count) { 1481 unlink_hidden = 1; 1482 node->is_hidden = 0; 1483 } 1484 pthread_mutex_unlock(&f->lock); 1485 1486 if(unlink_hidden && path) 1487 fuse_fs_unlink(f->fs, path); 1488} 1489 1490static void fuse_lib_create(fuse_req_t req, fuse_ino_t parent, 1491 const char *name, mode_t mode, 1492 struct fuse_file_info *fi) 1493{ 1494 struct fuse *f = req_fuse_prepare(req); 1495 struct fuse_intr_data d; 1496 struct fuse_entry_param e; 1497 char *path; 1498 int err; 1499 1500 err = -ENOENT; 1501 pthread_rwlock_rdlock(&f->tree_lock); 1502 path = get_path_name(f, parent, name); 1503 if (path) { 1504 fuse_prepare_interrupt(f, req, &d); 1505 err = fuse_fs_create(f->fs, path, mode, fi); 1506 if (!err) { 1507 err = lookup_path(f, parent, name, path, &e, fi); 1508 if (err) 1509 fuse_fs_release(f->fs, path, fi); 1510 else if (!S_ISREG(e.attr.st_mode)) { 1511 err = -EIO; 1512 fuse_fs_release(f->fs, path, fi); 1513 forget_node(f, e.ino, 1); 1514 } else { 1515 if (f->conf.direct_io) 1516 fi->direct_io = 1; 1517 if (f->conf.kernel_cache) 1518 fi->keep_cache = 1; 1519 1520 } 1521 } 1522 fuse_finish_interrupt(f, req, &d); 1523 } 1524 if (!err) { 1525 pthread_mutex_lock(&f->lock); 1526 get_node(f, e.ino)->open_count++; 1527 pthread_mutex_unlock(&f->lock); 1528 if (fuse_reply_create(req, &e, fi) == -ENOENT) { 1529 /* The open syscall was interrupted, so it must be cancelled */ 1530 fuse_prepare_interrupt(f, req, &d); 1531 fuse_do_release(f, e.ino, path, fi); 1532 fuse_finish_interrupt(f, req, &d); 1533 forget_node(f, e.ino, 1); 1534 } else if (f->conf.debug) { 1535 fprintf(stderr, " CREATE[%llu] flags: 0x%x %s\n", 1536 (unsigned long long) fi->fh, fi->flags, path); 1537 } 1538 } else 1539 reply_err(req, err); 1540 1541 if (path) 1542 free(path); 1543 1544 pthread_rwlock_unlock(&f->tree_lock); 1545} 1546 1547static void fuse_lib_open(fuse_req_t req, fuse_ino_t ino, 1548 struct fuse_file_info *fi) 1549{ 1550 struct fuse *f = req_fuse_prepare(req); 1551 struct fuse_intr_data d; 1552 char *path = NULL; 1553 int err = 0; 1554 1555 err = -ENOENT; 1556 pthread_rwlock_rdlock(&f->tree_lock); 1557 path = get_path(f, ino); 1558 if (path) { 1559 fuse_prepare_interrupt(f, req, &d); 1560 err = fuse_fs_open(f->fs, path, fi); 1561 if (!err) { 1562 if (f->conf.direct_io) 1563 fi->direct_io = 1; 1564 if (f->conf.kernel_cache) 1565 fi->keep_cache = 1; 1566 } 1567 fuse_finish_interrupt(f, req, &d); 1568 } 1569 if (!err) { 1570 pthread_mutex_lock(&f->lock); 1571 get_node(f, ino)->open_count++; 1572 pthread_mutex_unlock(&f->lock); 1573 if (fuse_reply_open(req, fi) == -ENOENT) { 1574 /* The open syscall was interrupted, so it must be cancelled */ 1575 fuse_prepare_interrupt(f, req, &d); 1576 fuse_do_release(f, ino, path, fi); 1577 fuse_finish_interrupt(f, req, &d); 1578 } else if (f->conf.debug) { 1579 fprintf(stderr, "OPEN[%llu] flags: 0x%x %s\n", 1580 (unsigned long long) fi->fh, fi->flags, path); 1581 } 1582 } else 1583 reply_err(req, err); 1584 1585 if (path) 1586 free(path); 1587 pthread_rwlock_unlock(&f->tree_lock); 1588} 1589 1590static void fuse_lib_read(fuse_req_t req, fuse_ino_t ino, size_t size, 1591 off_t off, struct fuse_file_info *fi) 1592{ 1593 struct fuse *f = req_fuse_prepare(req); 1594 char *path; 1595 char *buf; 1596 int res; 1597 1598 buf = (char *) malloc(size); 1599 if (buf == NULL) { 1600 reply_err(req, -ENOMEM); 1601 return; 1602 } 1603 1604 res = -ENOENT; 1605 pthread_rwlock_rdlock(&f->tree_lock); 1606 path = get_path(f, ino); 1607 if (path != NULL) { 1608 struct fuse_intr_data d; 1609 /* Foxconn removed start pling 06/19/2009 */ 1610#if 0 1611 if (f->conf.debug) 1612 fprintf(stderr, "READ[%llu] %lu bytes from %llu\n", 1613 (unsigned long long) fi->fh, (unsigned long) size, 1614 (unsigned long long) off); 1615#endif 1616 /* Foxconn removed end pling 06/19/2009 */ 1617 1618 fuse_prepare_interrupt(f, req, &d); 1619 res = fuse_fs_read(f->fs, path, buf, size, off, fi); 1620 fuse_finish_interrupt(f, req, &d); 1621 free(path); 1622 } 1623 pthread_rwlock_unlock(&f->tree_lock); 1624 1625 if (res >= 0) { 1626 /* Foxconn removed start pling 06/19/2009 */ 1627#if 0 1628 if (f->conf.debug) 1629 fprintf(stderr, " READ[%llu] %u bytes\n", 1630 (unsigned long long)fi->fh, res); 1631#endif 1632 /* Foxconn removed end pling 06/19/2009 */ 1633 if ((size_t) res > size) 1634 fprintf(stderr, "fuse: read too many bytes"); 1635 fuse_reply_buf(req, buf, res); 1636 } else 1637 reply_err(req, res); 1638 1639 free(buf); 1640} 1641 1642static void fuse_lib_write(fuse_req_t req, fuse_ino_t ino, const char *buf, 1643 size_t size, off_t off, struct fuse_file_info *fi) 1644{ 1645 struct fuse *f = req_fuse_prepare(req); 1646 char *path; 1647 int res; 1648 1649 res = -ENOENT; 1650 pthread_rwlock_rdlock(&f->tree_lock); 1651 path = get_path(f, ino); 1652 if (path != NULL) { 1653 struct fuse_intr_data d; 1654 1655 /* Foxconn removed start pling 06/19/2009 */ 1656#if 0 1657 if (f->conf.debug) 1658 fprintf(stderr, "WRITE%s[%llu] %lu bytes to %llu\n", 1659 fi->writepage ? "PAGE" : "", (unsigned long long) fi->fh, 1660 (unsigned long) size, (unsigned long long) off); 1661#endif 1662 /* Foxconn removed end pling 06/19/2009 */ 1663 1664 fuse_prepare_interrupt(f, req, &d); 1665 res = fuse_fs_write(f->fs, path, buf, size, off, fi); 1666 fuse_finish_interrupt(f, req, &d); 1667 free(path); 1668 } 1669 pthread_rwlock_unlock(&f->tree_lock); 1670 1671 if (res >= 0) { 1672 /* Foxconn removed start pling 06/19/2009 */ 1673#if 0 1674 if (f->conf.debug) 1675 fprintf(stderr, " WRITE%s[%llu] %u bytes\n", 1676 fi->writepage ? "PAGE" : "", (unsigned long long) fi->fh, 1677 res); 1678#endif 1679 /* Foxconn removed end pling 06/19/2009 */ 1680 if ((size_t) res > size) 1681 fprintf(stderr, "fuse: wrote too many bytes"); 1682 fuse_reply_write(req, res); 1683 } else 1684 reply_err(req, res); 1685} 1686 1687static void fuse_lib_fsync(fuse_req_t req, fuse_ino_t ino, int datasync, 1688 struct fuse_file_info *fi) 1689{ 1690 struct fuse *f = req_fuse_prepare(req); 1691 char *path; 1692 int err; 1693 1694 err = -ENOENT; 1695 pthread_rwlock_rdlock(&f->tree_lock); 1696 path = get_path(f, ino); 1697 if (path != NULL) { 1698 struct fuse_intr_data d; 1699 if (f->conf.debug) 1700 fprintf(stderr, "FSYNC[%llu]\n", (unsigned long long) fi->fh); 1701 fuse_prepare_interrupt(f, req, &d); 1702 err = fuse_fs_fsync(f->fs, path, datasync, fi); 1703 fuse_finish_interrupt(f, req, &d); 1704 free(path); 1705 } 1706 pthread_rwlock_unlock(&f->tree_lock); 1707 reply_err(req, err); 1708} 1709 1710static struct fuse_dh *get_dirhandle(const struct fuse_file_info *llfi, 1711 struct fuse_file_info *fi) 1712{ 1713 struct fuse_dh *dh = (struct fuse_dh *) (uintptr_t) llfi->fh; 1714 memset(fi, 0, sizeof(struct fuse_file_info)); 1715 fi->fh = dh->fh; 1716 fi->fh_old = dh->fh; 1717 return dh; 1718} 1719 1720static void fuse_lib_opendir(fuse_req_t req, fuse_ino_t ino, 1721 struct fuse_file_info *llfi) 1722{ 1723 struct fuse *f = req_fuse_prepare(req); 1724 struct fuse_intr_data d; 1725 struct fuse_dh *dh; 1726 struct fuse_file_info fi; 1727 char *path; 1728 int err; 1729 1730 dh = (struct fuse_dh *) malloc(sizeof(struct fuse_dh)); 1731 if (dh == NULL) { 1732 reply_err(req, -ENOMEM); 1733 return; 1734 } 1735 memset(dh, 0, sizeof(struct fuse_dh)); 1736 dh->fuse = f; 1737 dh->contents = NULL; 1738 dh->len = 0; 1739 dh->filled = 0; 1740 dh->nodeid = ino; 1741 fuse_mutex_init(&dh->lock); 1742 1743 llfi->fh = (uintptr_t) dh; 1744 1745 memset(&fi, 0, sizeof(fi)); 1746 fi.flags = llfi->flags; 1747 1748 err = -ENOENT; 1749 pthread_rwlock_rdlock(&f->tree_lock); 1750 path = get_path(f, ino); 1751 if (path != NULL) { 1752 fuse_prepare_interrupt(f, req, &d); 1753 err = fuse_fs_opendir(f->fs, path, &fi); 1754 fuse_finish_interrupt(f, req, &d); 1755 dh->fh = fi.fh; 1756 } 1757 if (!err) { 1758 if (fuse_reply_open(req, llfi) == -ENOENT) { 1759 /* The opendir syscall was interrupted, so it must be cancelled */ 1760 fuse_prepare_interrupt(f, req, &d); 1761 fuse_fs_releasedir(f->fs, path, &fi); 1762 fuse_finish_interrupt(f, req, &d); 1763 pthread_mutex_destroy(&dh->lock); 1764 free(dh); 1765 } 1766 } else { 1767 reply_err(req, err); 1768 pthread_mutex_destroy(&dh->lock); 1769 free(dh); 1770 } 1771 free(path); 1772 pthread_rwlock_unlock(&f->tree_lock); 1773} 1774 1775static int extend_contents(struct fuse_dh *dh, unsigned minsize) 1776{ 1777 if (minsize > dh->size) { 1778 char *newptr; 1779 unsigned newsize = dh->size; 1780 if (!newsize) 1781 newsize = 1024; 1782 while (newsize < minsize) { 1783 if (newsize >= 0x80000000) 1784 newsize = 0xffffffff; 1785 else 1786 newsize *= 2; 1787 } 1788 1789 newptr = (char *) realloc(dh->contents, newsize); 1790 if (!newptr) { 1791 dh->error = -ENOMEM; 1792 return -1; 1793 } 1794 dh->contents = newptr; 1795 dh->size = newsize; 1796 } 1797 return 0; 1798} 1799 1800static int fill_dir(void *dh_, const char *name, const struct stat *statp, 1801 off_t off) 1802{ 1803 struct fuse_dh *dh = (struct fuse_dh *) dh_; 1804 struct stat stbuf; 1805 size_t newlen; 1806 1807 if (statp) 1808 stbuf = *statp; 1809 else { 1810 memset(&stbuf, 0, sizeof(stbuf)); 1811 stbuf.st_ino = FUSE_UNKNOWN_INO; 1812 } 1813 1814 if (!dh->fuse->conf.use_ino) { 1815 stbuf.st_ino = FUSE_UNKNOWN_INO; 1816 if (dh->fuse->conf.readdir_ino) { 1817 struct node *node; 1818 pthread_mutex_lock(&dh->fuse->lock); 1819 node = lookup_node(dh->fuse, dh->nodeid, name); 1820 if (node) 1821 stbuf.st_ino = (ino_t) node->nodeid; 1822 pthread_mutex_unlock(&dh->fuse->lock); 1823 } 1824 } 1825 1826 if (off) { 1827 if (extend_contents(dh, dh->needlen) == -1) 1828 return 1; 1829 1830 dh->filled = 0; 1831 newlen = dh->len + fuse_add_direntry(dh->req, dh->contents + dh->len, 1832 dh->needlen - dh->len, name, 1833 &stbuf, off); 1834 if (newlen > dh->needlen) 1835 return 1; 1836 } else { 1837 newlen = dh->len + fuse_add_direntry(dh->req, NULL, 0, name, NULL, 0); 1838 if (extend_contents(dh, newlen) == -1) 1839 return 1; 1840 1841 fuse_add_direntry(dh->req, dh->contents + dh->len, dh->size - dh->len, 1842 name, &stbuf, newlen); 1843 } 1844 dh->len = newlen; 1845 return 0; 1846} 1847 1848static int readdir_fill(struct fuse *f, fuse_req_t req, fuse_ino_t ino, 1849 size_t size, off_t off, struct fuse_dh *dh, 1850 struct fuse_file_info *fi) 1851{ 1852 int err = -ENOENT; 1853 char *path; 1854 pthread_rwlock_rdlock(&f->tree_lock); 1855 path = get_path(f, ino); 1856 if (path != NULL) { 1857 struct fuse_intr_data d; 1858 1859 dh->len = 0; 1860 dh->error = 0; 1861 dh->needlen = size; 1862 dh->filled = 1; 1863 dh->req = req; 1864 fuse_prepare_interrupt(f, req, &d); 1865 err = fuse_fs_readdir(f->fs, path, dh, fill_dir, off, fi); 1866 fuse_finish_interrupt(f, req, &d); 1867 dh->req = NULL; 1868 if (!err) 1869 err = dh->error; 1870 if (err) 1871 dh->filled = 0; 1872 free(path); 1873 } 1874 pthread_rwlock_unlock(&f->tree_lock); 1875 return err; 1876} 1877 1878static void fuse_lib_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, 1879 off_t off, struct fuse_file_info *llfi) 1880{ 1881 struct fuse *f = req_fuse_prepare(req); 1882 struct fuse_file_info fi; 1883 struct fuse_dh *dh = get_dirhandle(llfi, &fi); 1884 1885 pthread_mutex_lock(&dh->lock); 1886 /* According to SUS, directory contents need to be refreshed on 1887 rewinddir() */ 1888 if (!off) 1889 dh->filled = 0; 1890 1891 if (!dh->filled) { 1892 int err = readdir_fill(f, req, ino, size, off, dh, &fi); 1893 if (err) { 1894 reply_err(req, err); 1895 goto out; 1896 } 1897 } 1898 if (dh->filled) { 1899 if (off < dh->len) { 1900 if (off + size > dh->len) 1901 size = dh->len - off; 1902 } else 1903 size = 0; 1904 } else { 1905 size = dh->len; 1906 off = 0; 1907 } 1908 fuse_reply_buf(req, dh->contents + off, size); 1909 out: 1910 pthread_mutex_unlock(&dh->lock); 1911} 1912 1913static void fuse_lib_releasedir(fuse_req_t req, fuse_ino_t ino, 1914 struct fuse_file_info *llfi) 1915{ 1916 struct fuse *f = req_fuse_prepare(req); 1917 struct fuse_intr_data d; 1918 struct fuse_file_info fi; 1919 struct fuse_dh *dh = get_dirhandle(llfi, &fi); 1920 char *path; 1921 1922 pthread_rwlock_rdlock(&f->tree_lock); 1923 path = get_path(f, ino); 1924 fuse_prepare_interrupt(f, req, &d); 1925 fuse_fs_releasedir(f->fs, path ? path : "-", &fi); 1926 fuse_finish_interrupt(f, req, &d); 1927 if (path) 1928 free(path); 1929 pthread_rwlock_unlock(&f->tree_lock); 1930 pthread_mutex_lock(&dh->lock); 1931 pthread_mutex_unlock(&dh->lock); 1932 pthread_mutex_destroy(&dh->lock); 1933 free(dh->contents); 1934 free(dh); 1935 reply_err(req, 0); 1936} 1937 1938static void fuse_lib_fsyncdir(fuse_req_t req, fuse_ino_t ino, int datasync, 1939 struct fuse_file_info *llfi) 1940{ 1941 struct fuse *f = req_fuse_prepare(req); 1942 struct fuse_file_info fi; 1943 char *path; 1944 int err; 1945 1946 get_dirhandle(llfi, &fi); 1947 1948 err = -ENOENT; 1949 pthread_rwlock_rdlock(&f->tree_lock); 1950 path = get_path(f, ino); 1951 if (path != NULL) { 1952 struct fuse_intr_data d; 1953 fuse_prepare_interrupt(f, req, &d); 1954 err = fuse_fs_fsyncdir(f->fs, path, datasync, &fi); 1955 fuse_finish_interrupt(f, req, &d); 1956 free(path); 1957 } 1958 pthread_rwlock_unlock(&f->tree_lock); 1959 reply_err(req, err); 1960} 1961 1962static void fuse_lib_statfs(fuse_req_t req, fuse_ino_t ino) 1963{ 1964 struct fuse *f = req_fuse_prepare(req); 1965 struct statvfs buf; 1966 char *path; 1967 int err; 1968 1969 memset(&buf, 0, sizeof(buf)); 1970 pthread_rwlock_rdlock(&f->tree_lock); 1971 if (!ino) { 1972 err = -ENOMEM; 1973 path = strdup("/"); 1974 } else { 1975 err = -ENOENT; 1976 path = get_path(f, ino); 1977 } 1978 if (path) { 1979 struct fuse_intr_data d; 1980 fuse_prepare_interrupt(f, req, &d); 1981 err = fuse_fs_statfs(f->fs, path, &buf); 1982 fuse_finish_interrupt(f, req, &d); 1983 free(path); 1984 } 1985 pthread_rwlock_unlock(&f->tree_lock); 1986 1987 if (!err) 1988 fuse_reply_statfs(req, &buf); 1989 else 1990 reply_err(req, err); 1991} 1992 1993static void fuse_lib_setxattr(fuse_req_t req, fuse_ino_t ino, const char *name, 1994 const char *value, size_t size, int flags) 1995{ 1996 struct fuse *f = req_fuse_prepare(req); 1997 char *path; 1998 int err; 1999 2000 err = -ENOENT; 2001 pthread_rwlock_rdlock(&f->tree_lock); 2002 path = get_path(f, ino); 2003 if (path != NULL) { 2004 struct fuse_intr_data d; 2005 fuse_prepare_interrupt(f, req, &d); 2006 err = fuse_fs_setxattr(f->fs, path, name, value, size, flags); 2007 fuse_finish_interrupt(f, req, &d); 2008 free(path); 2009 } 2010 pthread_rwlock_unlock(&f->tree_lock); 2011 reply_err(req, err); 2012} 2013 2014static int common_getxattr(struct fuse *f, fuse_req_t req, fuse_ino_t ino, 2015 const char *name, char *value, size_t size) 2016{ 2017 int err; 2018 char *path; 2019 2020 err = -ENOENT; 2021 pthread_rwlock_rdlock(&f->tree_lock); 2022 path = get_path(f, ino); 2023 if (path != NULL) { 2024 struct fuse_intr_data d; 2025 fuse_prepare_interrupt(f, req, &d); 2026 err = fuse_fs_getxattr(f->fs, path, name, value, size); 2027 fuse_finish_interrupt(f, req, &d); 2028 free(path); 2029 } 2030 pthread_rwlock_unlock(&f->tree_lock); 2031 return err; 2032} 2033 2034static void fuse_lib_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name, 2035 size_t size) 2036{ 2037 struct fuse *f = req_fuse_prepare(req); 2038 int res; 2039 2040 if (size) { 2041 char *value = (char *) malloc(size); 2042 if (value == NULL) { 2043 reply_err(req, -ENOMEM); 2044 return; 2045 } 2046 res = common_getxattr(f, req, ino, name, value, size); 2047 if (res > 0) 2048 fuse_reply_buf(req, value, res); 2049 else 2050 reply_err(req, res); 2051 free(value); 2052 } else { 2053 res = common_getxattr(f, req, ino, name, NULL, 0); 2054 if (res >= 0) 2055 fuse_reply_xattr(req, res); 2056 else 2057 reply_err(req, res); 2058 } 2059} 2060 2061static int common_listxattr(struct fuse *f, fuse_req_t req, fuse_ino_t ino, 2062 char *list, size_t size) 2063{ 2064 char *path; 2065 int err; 2066 2067 err = -ENOENT; 2068 pthread_rwlock_rdlock(&f->tree_lock); 2069 path = get_path(f, ino); 2070 if (path != NULL) { 2071 struct fuse_intr_data d; 2072 fuse_prepare_interrupt(f, req, &d); 2073 err = fuse_fs_listxattr(f->fs, path, list, size); 2074 fuse_finish_interrupt(f, req, &d); 2075 free(path); 2076 } 2077 pthread_rwlock_unlock(&f->tree_lock); 2078 return err; 2079} 2080 2081static void fuse_lib_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size) 2082{ 2083 struct fuse *f = req_fuse_prepare(req); 2084 int res; 2085 2086 if (size) { 2087 char *list = (char *) malloc(size); 2088 if (list == NULL) { 2089 reply_err(req, -ENOMEM); 2090 return; 2091 } 2092 res = common_listxattr(f, req, ino, list, size); 2093 if (res > 0) 2094 fuse_reply_buf(req, list, res); 2095 else 2096 reply_err(req, res); 2097 free(list); 2098 } else { 2099 res = common_listxattr(f, req, ino, NULL, 0); 2100 if (res >= 0) 2101 fuse_reply_xattr(req, res); 2102 else 2103 reply_err(req, res); 2104 } 2105} 2106 2107static void fuse_lib_removexattr(fuse_req_t req, fuse_ino_t ino, 2108 const char *name) 2109{ 2110 struct fuse *f = req_fuse_prepare(req); 2111 char *path; 2112 int err; 2113 2114 err = -ENOENT; 2115 pthread_rwlock_rdlock(&f->tree_lock); 2116 path = get_path(f, ino); 2117 if (path != NULL) { 2118 struct fuse_intr_data d; 2119 fuse_prepare_interrupt(f, req, &d); 2120 err = fuse_fs_removexattr(f->fs, path, name); 2121 fuse_finish_interrupt(f, req, &d); 2122 free(path); 2123 } 2124 pthread_rwlock_unlock(&f->tree_lock); 2125 reply_err(req, err); 2126} 2127 2128static struct lock *locks_conflict(struct node *node, const struct lock *lock) 2129{ 2130 struct lock *l; 2131 2132 for (l = node->locks; l; l = l->next) 2133 if (l->owner != lock->owner && 2134 lock->start <= l->end && l->start <= lock->end && 2135 (l->type == F_WRLCK || lock->type == F_WRLCK)) 2136 break; 2137 2138 return l; 2139} 2140 2141static void delete_lock(struct lock **lockp) 2142{ 2143 struct lock *l = *lockp; 2144 *lockp = l->next; 2145 free(l); 2146} 2147 2148static void insert_lock(struct lock **pos, struct lock *lock) 2149{ 2150 lock->next = *pos; 2151 *pos = lock; 2152} 2153 2154static int locks_insert(struct node *node, struct lock *lock) 2155{ 2156 struct lock **lp; 2157 struct lock *newl1 = NULL; 2158 struct lock *newl2 = NULL; 2159 2160 if (lock->type != F_UNLCK || lock->start != 0 || lock->end != OFFSET_MAX) { 2161 newl1 = malloc(sizeof(struct lock)); 2162 newl2 = malloc(sizeof(struct lock)); 2163 2164 if (!newl1 || !newl2) { 2165 free(newl1); 2166 free(newl2); 2167 return -ENOLCK; 2168 } 2169 } 2170 2171 for (lp = &node->locks; *lp;) { 2172 struct lock *l = *lp; 2173 if (l->owner != lock->owner) 2174 goto skip; 2175 2176 if (lock->type == l->type) { 2177 if (l->end < lock->start - 1) 2178 goto skip; 2179 if (lock->end < l->start - 1) 2180 break; 2181 if (l->start <= lock->start && lock->end <= l->end) 2182 goto out; 2183 if (l->start < lock->start) 2184 lock->start = l->start; 2185 if (lock->end < l->end) 2186 lock->end = l->end; 2187 goto delete; 2188 } else { 2189 if (l->end < lock->start) 2190 goto skip; 2191 if (lock->end < l->start) 2192 break; 2193 if (lock->start <= l->start && l->end <= lock->end) 2194 goto delete; 2195 if (l->end <= lock->end) { 2196 l->end = lock->start - 1; 2197 goto skip; 2198 } 2199 if (lock->start <= l->start) { 2200 l->start = lock->end + 1; 2201 break; 2202 } 2203 *newl2 = *l; 2204 newl2->start = lock->end + 1; 2205 l->end = lock->start - 1; 2206 insert_lock(&l->next, newl2); 2207 newl2 = NULL; 2208 } 2209 skip: 2210 lp = &l->next; 2211 continue; 2212 2213 delete: 2214 delete_lock(lp); 2215 } 2216 if (lock->type != F_UNLCK) { 2217 *newl1 = *lock; 2218 insert_lock(lp, newl1); 2219 newl1 = NULL; 2220 } 2221out: 2222 free(newl1); 2223 free(newl2); 2224 return 0; 2225} 2226 2227static void flock_to_lock(struct flock *flock, struct lock *lock) 2228{ 2229 memset(lock, 0, sizeof(struct lock)); 2230 lock->type = flock->l_type; 2231 lock->start = flock->l_start; 2232 lock->end = flock->l_len ? flock->l_start + flock->l_len - 1 : OFFSET_MAX; 2233 lock->pid = flock->l_pid; 2234} 2235 2236static void lock_to_flock(struct lock *lock, struct flock *flock) 2237{ 2238 flock->l_type = lock->type; 2239 flock->l_start = lock->start; 2240 flock->l_len = (lock->end == OFFSET_MAX) ? 0 : lock->end - lock->start + 1; 2241 flock->l_pid = lock->pid; 2242} 2243 2244static int fuse_flush_common(struct fuse *f, fuse_req_t req, fuse_ino_t ino, 2245 const char *path, struct fuse_file_info *fi) 2246{ 2247 struct fuse_intr_data d; 2248 struct flock lock; 2249 struct lock l; 2250 int err; 2251 int errlock; 2252 2253 fuse_prepare_interrupt(f, req, &d); 2254 memset(&lock, 0, sizeof(lock)); 2255 lock.l_type = F_UNLCK; 2256 lock.l_whence = SEEK_SET; 2257 err = fuse_fs_flush(f->fs, path, fi); 2258 errlock = fuse_fs_lock(f->fs, path, fi, F_SETLK, &lock); 2259 fuse_finish_interrupt(f, req, &d); 2260 2261 if (errlock != -ENOSYS) { 2262 flock_to_lock(&lock, &l); 2263 l.owner = fi->lock_owner; 2264 pthread_mutex_lock(&f->lock); 2265 locks_insert(get_node(f, ino), &l); 2266 pthread_mutex_unlock(&f->lock); 2267 2268 /* if op.lock() is defined FLUSH is needed regardless of op.flush() */ 2269 if (err == -ENOSYS) 2270 err = 0; 2271 } 2272 return err; 2273} 2274 2275static void fuse_lib_release(fuse_req_t req, fuse_ino_t ino, 2276 struct fuse_file_info *fi) 2277{ 2278 struct fuse *f = req_fuse_prepare(req); 2279 struct fuse_intr_data d; 2280 char *path; 2281 int err = 0; 2282 2283 pthread_rwlock_rdlock(&f->tree_lock); 2284 path = get_path(f, ino); 2285 if (f->conf.debug) 2286 fprintf(stderr, "RELEASE%s[%llu] flags: 0x%x\n", 2287 fi->flush ? "+FLUSH" : "", 2288 (unsigned long long) fi->fh, fi->flags); 2289 2290 if (fi->flush) { 2291 err = fuse_flush_common(f, req, ino, path, fi); 2292 if (err == -ENOSYS) 2293 err = 0; 2294 } 2295 2296 fuse_prepare_interrupt(f, req, &d); 2297 fuse_do_release(f, ino, path, fi); 2298 fuse_finish_interrupt(f, req, &d); 2299 free(path); 2300 pthread_rwlock_unlock(&f->tree_lock); 2301 2302 reply_err(req, err); 2303} 2304 2305static void fuse_lib_flush(fuse_req_t req, fuse_ino_t ino, 2306 struct fuse_file_info *fi) 2307{ 2308 struct fuse *f = req_fuse_prepare(req); 2309 char *path; 2310 int err; 2311 2312 pthread_rwlock_rdlock(&f->tree_lock); 2313 path = get_path(f, ino); 2314 if (path && f->conf.debug) 2315 fprintf(stderr, "FLUSH[%llu]\n", (unsigned long long) fi->fh); 2316 err = fuse_flush_common(f, req, ino, path, fi); 2317 free(path); 2318 pthread_rwlock_unlock(&f->tree_lock); 2319 reply_err(req, err); 2320} 2321 2322static int fuse_lock_common(fuse_req_t req, fuse_ino_t ino, 2323 struct fuse_file_info *fi, struct flock *lock, 2324 int cmd) 2325{ 2326 struct fuse *f = req_fuse_prepare(req); 2327 char *path; 2328 int err; 2329 2330 err = -ENOENT; 2331 pthread_rwlock_rdlock(&f->tree_lock); 2332 path = get_path(f, ino); 2333 if (path != NULL) { 2334 struct fuse_intr_data d; 2335 fuse_prepare_interrupt(f, req, &d); 2336 err = fuse_fs_lock(f->fs, path, fi, cmd, lock); 2337 fuse_finish_interrupt(f, req, &d); 2338 free(path); 2339 } 2340 pthread_rwlock_unlock(&f->tree_lock); 2341 return err; 2342} 2343 2344static void fuse_lib_getlk(fuse_req_t req, fuse_ino_t ino, 2345 struct fuse_file_info *fi, struct flock *lock) 2346{ 2347 int err; 2348 struct lock l; 2349 struct lock *conflict; 2350 struct fuse *f = req_fuse(req); 2351 2352 flock_to_lock(lock, &l); 2353 l.owner = fi->lock_owner; 2354 pthread_mutex_lock(&f->lock); 2355 conflict = locks_conflict(get_node(f, ino), &l); 2356 if (conflict) 2357 lock_to_flock(conflict, lock); 2358 pthread_mutex_unlock(&f->lock); 2359 if (!conflict) 2360 err = fuse_lock_common(req, ino, fi, lock, F_GETLK); 2361 else 2362 err = 0; 2363 2364 if (!err) 2365 fuse_reply_lock(req, lock); 2366 else 2367 reply_err(req, err); 2368} 2369 2370static void fuse_lib_setlk(fuse_req_t req, fuse_ino_t ino, 2371 struct fuse_file_info *fi, struct flock *lock, 2372 int should_sleep) 2373{ 2374 int err = fuse_lock_common(req, ino, fi, lock, should_sleep ? F_SETLKW : F_SETLK); 2375 if (!err) { 2376 struct fuse *f = req_fuse(req); 2377 struct lock l; 2378 flock_to_lock(lock, &l); 2379 l.owner = fi->lock_owner; 2380 pthread_mutex_lock(&f->lock); 2381 locks_insert(get_node(f, ino), &l); 2382 pthread_mutex_unlock(&f->lock); 2383 } 2384 reply_err(req, err); 2385} 2386 2387static void fuse_lib_bmap(fuse_req_t req, fuse_ino_t ino, size_t blocksize, 2388 uint64_t idx) 2389{ 2390 struct fuse *f = req_fuse_prepare(req); 2391 struct fuse_intr_data d; 2392 char *path; 2393 int err; 2394 2395 err = -ENOENT; 2396 pthread_rwlock_rdlock(&f->tree_lock); 2397 path = get_path(f, ino); 2398 if (path != NULL) { 2399 fuse_prepare_interrupt(f, req, &d); 2400 err = fuse_fs_bmap(f->fs, path, blocksize, &idx); 2401 fuse_finish_interrupt(f, req, &d); 2402 free(path); 2403 } 2404 pthread_rwlock_unlock(&f->tree_lock); 2405 if (!err) 2406 fuse_reply_bmap(req, idx); 2407 else 2408 reply_err(req, err); 2409} 2410 2411static struct fuse_lowlevel_ops fuse_path_ops = { 2412 .init = fuse_lib_init, 2413 .destroy = fuse_lib_destroy, 2414 .lookup = fuse_lib_lookup, 2415 .forget = fuse_lib_forget, 2416 .getattr = fuse_lib_getattr, 2417 .setattr = fuse_lib_setattr, 2418 .access = fuse_lib_access, 2419 .readlink = fuse_lib_readlink, 2420 .mknod = fuse_lib_mknod, 2421 .mkdir = fuse_lib_mkdir, 2422 .unlink = fuse_lib_unlink, 2423 .rmdir = fuse_lib_rmdir, 2424 .symlink = fuse_lib_symlink, 2425 .rename = fuse_lib_rename, 2426 .link = fuse_lib_link, 2427 .create = fuse_lib_create, 2428 .open = fuse_lib_open, 2429 .read = fuse_lib_read, 2430 .write = fuse_lib_write, 2431 .flush = fuse_lib_flush, 2432 .release = fuse_lib_release, 2433 .fsync = fuse_lib_fsync, 2434 .opendir = fuse_lib_opendir, 2435 .readdir = fuse_lib_readdir, 2436 .releasedir = fuse_lib_releasedir, 2437 .fsyncdir = fuse_lib_fsyncdir, 2438 .statfs = fuse_lib_statfs, 2439 .setxattr = fuse_lib_setxattr, 2440 .getxattr = fuse_lib_getxattr, 2441 .listxattr = fuse_lib_listxattr, 2442 .removexattr = fuse_lib_removexattr, 2443 .getlk = fuse_lib_getlk, 2444 .setlk = fuse_lib_setlk, 2445 .bmap = fuse_lib_bmap, 2446}; 2447 2448struct fuse_session *fuse_get_session(struct fuse *f) 2449{ 2450 return f->se; 2451} 2452 2453int fuse_loop(struct fuse *f) 2454{ 2455 if (f) 2456 return fuse_session_loop(f->se); 2457 else 2458 return -1; 2459} 2460 2461void fuse_exit(struct fuse *f) 2462{ 2463 fuse_session_exit(f->se); 2464} 2465 2466struct fuse_context *fuse_get_context(void) 2467{ 2468 return &fuse_get_context_internal()->ctx; 2469} 2470 2471int fuse_interrupted(void) 2472{ 2473 return fuse_req_interrupted(fuse_get_context_internal()->req); 2474} 2475 2476enum { 2477 KEY_HELP, 2478}; 2479 2480#define FUSE_LIB_OPT(t, p, v) { t, offsetof(struct fuse_config, p), v } 2481 2482static const struct fuse_opt fuse_lib_opts[] = { 2483 FUSE_OPT_KEY("-h", KEY_HELP), 2484 FUSE_OPT_KEY("--help", KEY_HELP), 2485 FUSE_OPT_KEY("debug", FUSE_OPT_KEY_KEEP), 2486 FUSE_OPT_KEY("-d", FUSE_OPT_KEY_KEEP), 2487 FUSE_LIB_OPT("debug", debug, 1), 2488 FUSE_LIB_OPT("-d", debug, 1), 2489 FUSE_LIB_OPT("hard_remove", hard_remove, 1), 2490 FUSE_LIB_OPT("use_ino", use_ino, 1), 2491 FUSE_LIB_OPT("readdir_ino", readdir_ino, 1), 2492 FUSE_LIB_OPT("direct_io", direct_io, 1), 2493 FUSE_LIB_OPT("kernel_cache", kernel_cache, 1), 2494 FUSE_LIB_OPT("umask=", set_mode, 1), 2495 FUSE_LIB_OPT("umask=%o", umask, 0), 2496 FUSE_LIB_OPT("uid=", set_uid, 1), 2497 FUSE_LIB_OPT("uid=%d", uid, 0), 2498 FUSE_LIB_OPT("gid=", set_gid, 1), 2499 FUSE_LIB_OPT("gid=%d", gid, 0), 2500 FUSE_LIB_OPT("entry_timeout=%lf", entry_timeout, 0), 2501 FUSE_LIB_OPT("attr_timeout=%lf", attr_timeout, 0), 2502 FUSE_LIB_OPT("ac_attr_timeout=%lf", ac_attr_timeout, 0), 2503 FUSE_LIB_OPT("ac_attr_timeout=", ac_attr_timeout_set, 1), 2504 FUSE_LIB_OPT("negative_timeout=%lf", negative_timeout, 0), 2505 FUSE_LIB_OPT("intr", intr, 1), 2506 FUSE_LIB_OPT("intr_signal=%d", intr_signal, 0), 2507 FUSE_OPT_END 2508}; 2509 2510static void fuse_lib_help(void) 2511{ 2512 fprintf(stderr, 2513" -o hard_remove immediate removal (don't hide files)\n" 2514" -o use_ino let filesystem set inode numbers\n" 2515" -o readdir_ino try to fill in d_ino in readdir\n" 2516" -o direct_io use direct I/O\n" 2517" -o kernel_cache cache files in kernel\n" 2518" -o umask=M set file permissions (octal)\n" 2519" -o uid=N set file owner\n" 2520" -o gid=N set file group\n" 2521" -o entry_timeout=T cache timeout for names (1.0s)\n" 2522" -o negative_timeout=T cache timeout for deleted names (0.0s)\n" 2523" -o attr_timeout=T cache timeout for attributes (1.0s)\n" 2524" -o ac_attr_timeout=T auto cache timeout for attributes (attr_timeout)\n" 2525" -o intr allow requests to be interrupted\n" 2526" -o intr_signal=NUM signal to send on interrupt (%i)\n" 2527"\n", FUSE_DEFAULT_INTR_SIGNAL); 2528} 2529 2530static int fuse_lib_opt_proc(void *data, const char *arg, int key, 2531 struct fuse_args *outargs) 2532{ 2533 (void) arg; (void) outargs; 2534 2535 if (key == KEY_HELP) { 2536 struct fuse_config *conf = (struct fuse_config *) data; 2537 fuse_lib_help(); 2538 conf->help = 1; 2539 } 2540 2541 return 1; 2542} 2543 2544static int fuse_init_intr_signal(int signum, int *installed) 2545{ 2546 struct sigaction old_sa; 2547 2548 if (sigaction(signum, NULL, &old_sa) == -1) { 2549 perror("fuse: cannot get old signal handler"); 2550 return -1; 2551 } 2552 2553 if (old_sa.sa_handler == SIG_DFL) { 2554 struct sigaction sa; 2555 2556 memset(&sa, 0, sizeof(struct sigaction)); 2557 sa.sa_handler = fuse_intr_sighandler; 2558 sigemptyset(&sa.sa_mask); 2559 2560 if (sigaction(signum, &sa, NULL) == -1) { 2561 perror("fuse: cannot set interrupt signal handler"); 2562 return -1; 2563 } 2564 *installed = 1; 2565 } 2566 return 0; 2567} 2568 2569static void fuse_restore_intr_signal(int signum) 2570{ 2571 struct sigaction sa; 2572 2573 memset(&sa, 0, sizeof(struct sigaction)); 2574 sa.sa_handler = SIG_DFL; 2575 sigaction(signum, &sa, NULL); 2576} 2577 2578struct fuse_fs *fuse_fs_new(const struct fuse_operations *op, size_t op_size, 2579 void *user_data) 2580{ 2581 struct fuse_fs *fs; 2582 2583 if (sizeof(struct fuse_operations) < op_size) { 2584 fprintf(stderr, "fuse: warning: library too old, some operations may not not work\n"); 2585 op_size = sizeof(struct fuse_operations); 2586 } 2587 2588 fs = (struct fuse_fs *) calloc(1, sizeof(struct fuse_fs)); 2589 if (!fs) { 2590 fprintf(stderr, "fuse: failed to allocate fuse_fs object\n"); 2591 return NULL; 2592 } 2593 2594 fs->user_data = user_data; 2595 if (op) 2596 memcpy(&fs->op, op, op_size); 2597 return fs; 2598} 2599 2600struct fuse *fuse_new(struct fuse_chan *ch, struct fuse_args *args, 2601 const struct fuse_operations *op, size_t op_size, 2602 void *user_data) 2603{ 2604 struct fuse *f; 2605 struct node *root; 2606 struct fuse_fs *fs; 2607 struct fuse_lowlevel_ops llop = fuse_path_ops; 2608 2609 if (fuse_create_context_key() == -1) 2610 goto out; 2611 2612 f = (struct fuse *) calloc(1, sizeof(struct fuse)); 2613 if (f == NULL) { 2614 fprintf(stderr, "fuse: failed to allocate fuse object\n"); 2615 goto out_delete_context_key; 2616 } 2617 2618 fs = fuse_fs_new(op, op_size, user_data); 2619 if (!fs) 2620 goto out_free; 2621 2622 f->fs = fs; 2623 2624 /* Oh f**k, this is ugly! */ 2625 if (!fs->op.lock) { 2626 llop.getlk = NULL; 2627 llop.setlk = NULL; 2628 } 2629 2630 f->conf.entry_timeout = 1.0; 2631 f->conf.attr_timeout = 1.0; 2632 f->conf.negative_timeout = 0.0; 2633 f->conf.intr_signal = FUSE_DEFAULT_INTR_SIGNAL; 2634 2635 if (fuse_opt_parse(args, &f->conf, fuse_lib_opts, fuse_lib_opt_proc) == -1) 2636 goto out_free_fs; 2637 2638 if (!f->conf.ac_attr_timeout_set) 2639 f->conf.ac_attr_timeout = f->conf.attr_timeout; 2640 2641#ifdef __FreeBSD__ 2642 /* 2643 * In FreeBSD, we always use these settings as inode numbers are needed to 2644 * make getcwd(3) work. 2645 */ 2646 f->conf.readdir_ino = 1; 2647#endif 2648 2649 f->se = fuse_lowlevel_new(args, &llop, sizeof(llop), f); 2650 if (f->se == NULL) { 2651 goto out_free_fs; 2652 } 2653 2654 fuse_session_add_chan(f->se, ch); 2655 2656 f->ctr = 0; 2657 f->generation = 0; 2658 /* FIXME: Dynamic hash table */ 2659 f->name_table_size = 14057; 2660 f->name_table = (struct node **) 2661 calloc(1, sizeof(struct node *) * f->name_table_size); 2662 if (f->name_table == NULL) { 2663 fprintf(stderr, "fuse: memory allocation failed\n"); 2664 goto out_free_session; 2665 } 2666 2667 f->id_table_size = 14057; 2668 f->id_table = (struct node **) 2669 calloc(1, sizeof(struct node *) * f->id_table_size); 2670 if (f->id_table == NULL) { 2671 fprintf(stderr, "fuse: memory allocation failed\n"); 2672 goto out_free_name_table; 2673 } 2674 2675 fuse_mutex_init(&f->lock); 2676 pthread_rwlock_init(&f->tree_lock, NULL); 2677 2678 root = (struct node *) calloc(1, sizeof(struct node)); 2679 if (root == NULL) { 2680 fprintf(stderr, "fuse: memory allocation failed\n"); 2681 goto out_free_id_table; 2682 } 2683 2684 root->name = strdup("/"); 2685 if (root->name == NULL) { 2686 fprintf(stderr, "fuse: memory allocation failed\n"); 2687 goto out_free_root; 2688 } 2689 2690 if (f->conf.intr && 2691 fuse_init_intr_signal(f->conf.intr_signal, &f->intr_installed) == -1) 2692 goto out_free_root_name; 2693 2694 root->parent = NULL; 2695 root->nodeid = FUSE_ROOT_ID; 2696 root->generation = 0; 2697 root->refctr = 1; 2698 root->nlookup = 1; 2699 hash_id(f, root); 2700 2701 return f; 2702 2703 out_free_root_name: 2704 free(root->name); 2705 out_free_root: 2706 free(root); 2707 out_free_id_table: 2708 free(f->id_table); 2709 out_free_name_table: 2710 free(f->name_table); 2711 out_free_session: 2712 fuse_session_destroy(f->se); 2713 out_free_fs: 2714 /* Horrible compatibility hack to stop the destructor from being 2715 called on the filesystem without init being called first */ 2716 fs->op.destroy = NULL; 2717 fuse_fs_destroy(f->fs); 2718 out_free: 2719 free(f); 2720 out_delete_context_key: 2721 fuse_delete_context_key(); 2722 out: 2723 return NULL; 2724} 2725 2726void fuse_destroy(struct fuse *f) 2727{ 2728 size_t i; 2729 2730 if (f->conf.intr && f->intr_installed) 2731 fuse_restore_intr_signal(f->conf.intr_signal); 2732 2733 if (f->fs) { 2734 struct fuse_context_i *c = fuse_get_context_internal(); 2735 2736 memset(c, 0, sizeof(*c)); 2737 c->ctx.fuse = f; 2738 2739 for (i = 0; i < f->id_table_size; i++) { 2740 struct node *node; 2741 2742 for (node = f->id_table[i]; node != NULL; node = node->id_next) { 2743 if (node->is_hidden) { 2744 char *path = get_path(f, node->nodeid); 2745 if (path) { 2746 fuse_fs_unlink(f->fs, path); 2747 free(path); 2748 } 2749 } 2750 } 2751 } 2752 } 2753 for (i = 0; i < f->id_table_size; i++) { 2754 struct node *node; 2755 struct node *next; 2756 2757 for (node = f->id_table[i]; node != NULL; node = next) { 2758 next = node->id_next; 2759 free_node(node); 2760 } 2761 } 2762 free(f->id_table); 2763 free(f->name_table); 2764 pthread_mutex_destroy(&f->lock); 2765 pthread_rwlock_destroy(&f->tree_lock); 2766 fuse_session_destroy(f->se); 2767 free(f); 2768 fuse_delete_context_key(); 2769} 2770 2771