1 /* $OpenBSD: fuse_ops.c,v 1.26 2016/09/07 17:53:35 natano Exp $ */ 2 /* 3 * Copyright (c) 2013 Sylvestre Gallon <ccna.syl@gmail.com> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <errno.h> 19 #include <string.h> 20 #include <stdlib.h> 21 22 #include "fuse_private.h" 23 #include "debug.h" 24 25 #define CHECK_OPT(opname) DPRINTF("Opcode:\t%s\n", #opname); \ 26 DPRINTF("Inode:\t%llu\n", \ 27 (unsigned long long)fbuf->fb_ino); \ 28 if (!f->op.opname) { \ 29 fbuf->fb_err = -ENOSYS; \ 30 return (0); \ 31 } 32 33 static int 34 update_attr(struct fuse *f, struct stat *attr, const char *realname, 35 struct fuse_vnode *vn) 36 { 37 int ret; 38 39 memset(attr, 0, sizeof(struct stat)); 40 ret = f->op.getattr(realname, attr); 41 42 if (attr->st_blksize == 0) 43 attr->st_blksize = 512; 44 if (attr->st_blocks == 0) 45 attr->st_blocks = 4; 46 47 attr->st_ino = vn->ino; 48 49 if (f->conf.set_mode) 50 attr->st_mode = (attr->st_mode & S_IFMT) | (0777 & ~f->conf.umask); 51 52 if (f->conf.set_uid) 53 attr->st_uid = f->conf.uid; 54 55 if (f->conf.set_gid) 56 attr->st_gid = f->conf.gid; 57 58 return (ret); 59 } 60 61 static int 62 ifuse_ops_init(struct fuse *f) 63 { 64 struct fuse_conn_info fci; 65 66 DPRINTF("Opcode:\tinit\n"); 67 68 if (f->op.init) { 69 bzero(&fci, sizeof fci); 70 fci.proto_minor = FUSE_MINOR_VERSION; 71 fci.proto_major = FUSE_MAJOR_VERSION; 72 73 f->op.init(&fci); 74 } 75 return (0); 76 } 77 78 static int 79 ifuse_ops_getattr(struct fuse *f, struct fusebuf *fbuf) 80 { 81 struct fuse_vnode *vn; 82 char *realname; 83 84 DPRINTF("Opcode:\tgetattr\n"); 85 DPRINTF("Inode:\t%llu\n", (unsigned long long)fbuf->fb_ino); 86 87 memset(&fbuf->fb_attr, 0, sizeof(struct stat)); 88 89 vn = tree_get(&f->vnode_tree, fbuf->fb_ino); 90 if (vn == NULL) { 91 fbuf->fb_err = -errno; 92 return (0); 93 } 94 95 realname = build_realname(f, vn->ino); 96 if (realname == NULL) { 97 fbuf->fb_err = -errno; 98 return (0); 99 } 100 101 fbuf->fb_err = update_attr(f, &fbuf->fb_attr, realname, vn); 102 free(realname); 103 104 return (0); 105 } 106 107 static int 108 ifuse_ops_access(struct fuse *f, struct fusebuf *fbuf) 109 { 110 struct fuse_vnode *vn; 111 char *realname; 112 113 CHECK_OPT(access); 114 115 vn = tree_get(&f->vnode_tree, fbuf->fb_ino); 116 if (vn == NULL) { 117 fbuf->fb_err = -errno; 118 return (0); 119 } 120 121 realname = build_realname(f, vn->ino); 122 if (realname == NULL) { 123 fbuf->fb_err = -errno; 124 return (0); 125 } 126 127 fbuf->fb_err = f->op.access(realname, fbuf->fb_io_mode); 128 free(realname); 129 130 return (0); 131 } 132 133 static int 134 ifuse_ops_open(struct fuse *f, struct fusebuf *fbuf) 135 { 136 struct fuse_file_info ffi; 137 struct fuse_vnode *vn; 138 char *realname; 139 140 CHECK_OPT(open); 141 142 bzero(&ffi, sizeof(ffi)); 143 ffi.flags = fbuf->fb_io_flags; 144 145 vn = tree_get(&f->vnode_tree, fbuf->fb_ino); 146 if (vn == NULL) { 147 fbuf->fb_err = -errno; 148 return (0); 149 } 150 151 realname = build_realname(f, vn->ino); 152 if (realname == NULL) { 153 fbuf->fb_err = -errno; 154 return (0); 155 } 156 157 fbuf->fb_err = f->op.open(realname, &ffi); 158 free(realname); 159 160 if (!fbuf->fb_err) 161 fbuf->fb_io_fd = ffi.fh; 162 163 return (0); 164 } 165 166 static int 167 ifuse_ops_opendir(struct fuse *f, struct fusebuf *fbuf) 168 { 169 struct fuse_file_info ffi; 170 struct fuse_vnode *vn; 171 char *realname; 172 173 DPRINTF("Opcode:\topendir\n"); 174 DPRINTF("Inode:\t%llu\n", (unsigned long long)fbuf->fb_ino); 175 176 memset(&ffi, 0, sizeof(ffi)); 177 ffi.flags = fbuf->fb_io_flags; 178 179 vn = tree_get(&f->vnode_tree, fbuf->fb_ino); 180 if (vn == NULL) { 181 fbuf->fb_err = -errno; 182 return (0); 183 } 184 185 if (f->op.opendir) { 186 realname = build_realname(f, vn->ino); 187 if (realname == NULL) { 188 fbuf->fb_err = -errno; 189 return (0); 190 } 191 192 fbuf->fb_err = f->op.opendir(realname, &ffi); 193 free(realname); 194 } 195 196 if (!fbuf->fb_err) { 197 fbuf->fb_io_fd = ffi.fh; 198 199 vn->fd = calloc(1, sizeof(*vn->fd)); 200 if (vn->fd == NULL) { 201 fbuf->fb_err = -errno; 202 return (0); 203 } 204 205 vn->fd->filled = 0; 206 vn->fd->size = 0; 207 vn->fd->start = 0; 208 } 209 210 return (0); 211 } 212 213 #define GENERIC_DIRSIZ(NLEN) \ 214 ((sizeof (struct dirent) - (MAXNAMLEN+1)) + ((NLEN+1 + 7) &~ 7)) 215 216 static int 217 ifuse_fill_readdir(void *dh, const char *name, const struct stat *stbuf, 218 off_t off) 219 { 220 struct fuse_dirhandle *fd = dh; 221 struct fusebuf *fbuf; 222 struct dirent *dir; 223 uint32_t namelen; 224 uint32_t len; 225 226 fbuf = fd->buf; 227 namelen = strnlen(name, MAXNAMLEN); 228 len = GENERIC_DIRSIZ(namelen); 229 230 if (fd->full || (fbuf->fb_len + len > fd->size)) { 231 fd->full = 1; 232 return (0); 233 } 234 235 if (fd->start != 0 && fd->idx < fd->start) { 236 fd->idx += len; 237 return (0); 238 } 239 240 dir = (struct dirent *) &fbuf->fb_dat[fbuf->fb_len]; 241 242 if (off) 243 fd->filled = 0; 244 245 if (stbuf) { 246 dir->d_fileno = stbuf->st_ino; 247 dir->d_type = IFTODT(stbuf->st_mode); 248 } else { 249 dir->d_fileno = 0xffffffff; 250 dir->d_type = DT_UNKNOWN; 251 } 252 dir->d_reclen = len; 253 dir->d_off = off + len; /* XXX */ 254 strlcpy(dir->d_name, name, sizeof(dir->d_name)); 255 dir->d_namlen = strlen(dir->d_name); 256 257 fbuf->fb_len += len; 258 fd->start += len; 259 fd->idx += len; 260 261 return (0); 262 } 263 264 static int 265 ifuse_fill_getdir(fuse_dirh_t fd, const char *name, int type, ino_t ino) 266 { 267 struct stat st; 268 269 bzero(&st, sizeof(st)); 270 st.st_mode = type << 12; 271 if (ino == 0) 272 st.st_ino = 0xffffffff; 273 else 274 st.st_ino = ino; 275 276 return (fd->filler(fd, name, &st, 0)); 277 } 278 279 static int 280 ifuse_ops_readdir(struct fuse *f, struct fusebuf *fbuf) 281 { 282 struct fuse_file_info ffi; 283 struct fuse_vnode *vn; 284 char *realname; 285 uint64_t offset; 286 uint32_t size; 287 uint32_t startsave; 288 289 DPRINTF("Opcode:\treaddir\n"); 290 DPRINTF("Inode:\t%llu\n", (unsigned long long)fbuf->fb_ino); 291 DPRINTF("Offset:\t%llu\n", fbuf->fb_io_off); 292 DPRINTF("Size:\t%lu\n", fbuf->fb_io_len); 293 294 bzero(&ffi, sizeof(ffi)); 295 ffi.fh = fbuf->fb_io_fd; 296 offset = fbuf->fb_io_off; 297 size = fbuf->fb_io_len; 298 startsave = 0; 299 300 fbuf->fb_dat = calloc(1, size); 301 302 if (fbuf->fb_dat == NULL) { 303 fbuf->fb_err = -errno; 304 return (0); 305 } 306 307 vn = tree_get(&f->vnode_tree, fbuf->fb_ino); 308 if (vn == NULL) { 309 fbuf->fb_err = -errno; 310 free(fbuf->fb_dat); 311 return (0); 312 } 313 314 if (!vn->fd->filled) { 315 vn->fd->filler = ifuse_fill_readdir; 316 vn->fd->buf = fbuf; 317 vn->fd->filled = 0; 318 vn->fd->full = 0; 319 vn->fd->size = size; 320 vn->fd->off = offset; 321 vn->fd->idx = 0; 322 startsave = vn->fd->start; 323 324 realname = build_realname(f, vn->ino); 325 if (realname == NULL) { 326 fbuf->fb_err = -errno; 327 free(fbuf->fb_dat); 328 return (0); 329 } 330 331 if (f->op.readdir) 332 fbuf->fb_err = f->op.readdir(realname, vn->fd, 333 ifuse_fill_readdir, offset, &ffi); 334 else if (f->op.getdir) 335 fbuf->fb_err = f->op.getdir(realname, vn->fd, 336 ifuse_fill_getdir); 337 else 338 fbuf->fb_err = -ENOSYS; 339 free(realname); 340 } 341 342 if (!vn->fd->full && vn->fd->start == startsave) 343 vn->fd->filled = 1; 344 345 if (fbuf->fb_err) { 346 fbuf->fb_len = 0; 347 vn->fd->filled = 1; 348 } 349 350 if (fbuf->fb_len == 0) 351 free(fbuf->fb_dat); 352 353 return (0); 354 } 355 356 static int 357 ifuse_ops_releasedir(struct fuse *f, struct fusebuf *fbuf) 358 { 359 struct fuse_file_info ffi; 360 struct fuse_vnode *vn; 361 char *realname; 362 363 DPRINTF("Opcode:\treleasedir\n"); 364 DPRINTF("Inode:\t%llu\n", (unsigned long long)fbuf->fb_ino); 365 366 bzero(&ffi, sizeof(ffi)); 367 ffi.fh = fbuf->fb_io_fd; 368 ffi.fh_old = ffi.fh; 369 ffi.flags = fbuf->fb_io_flags; 370 371 vn = tree_get(&f->vnode_tree, fbuf->fb_ino); 372 if (vn == NULL) { 373 fbuf->fb_err = -errno; 374 return (0); 375 } 376 377 if (f->op.releasedir) { 378 realname = build_realname(f, vn->ino); 379 if (realname == NULL) { 380 fbuf->fb_err = -errno; 381 return (0); 382 } 383 384 fbuf->fb_err = f->op.releasedir(realname, &ffi); 385 free(realname); 386 } 387 388 if (!fbuf->fb_err) 389 free(vn->fd); 390 391 return (0); 392 } 393 394 static int 395 ifuse_ops_release(struct fuse *f, struct fusebuf *fbuf) 396 { 397 struct fuse_file_info ffi; 398 struct fuse_vnode *vn; 399 char *realname; 400 401 CHECK_OPT(release); 402 403 bzero(&ffi, sizeof(ffi)); 404 ffi.fh = fbuf->fb_io_fd; 405 ffi.fh_old = ffi.fh; 406 ffi.flags = fbuf->fb_io_flags; 407 408 vn = tree_get(&f->vnode_tree, fbuf->fb_ino); 409 if (vn == NULL) { 410 fbuf->fb_err = -errno; 411 return (0); 412 } 413 414 realname = build_realname(f, vn->ino); 415 if (realname == NULL) { 416 fbuf->fb_err = -errno; 417 return (0); 418 } 419 fbuf->fb_err = f->op.release(realname, &ffi); 420 free(realname); 421 422 return (0); 423 } 424 425 static int 426 ifuse_ops_lookup(struct fuse *f, struct fusebuf *fbuf) 427 { 428 struct fuse_vnode *vn; 429 char *realname; 430 431 DPRINTF("Opcode:\tlookup\n"); 432 DPRINTF("Inode:\t%llu\n", (unsigned long long)fbuf->fb_ino); 433 DPRINTF("For file %s\n", fbuf->fb_dat); 434 435 if (strcmp((const char *)fbuf->fb_dat, "..") == 0) { 436 vn = tree_get(&f->vnode_tree, fbuf->fb_ino); 437 if (vn == NULL || vn->parent == NULL) { 438 fbuf->fb_err = -ENOENT; 439 return (0); 440 } 441 vn = vn->parent; 442 if (vn->ino != FUSE_ROOT_INO) 443 ref_vn(vn); 444 } else { 445 vn = get_vn_by_name_and_parent(f, fbuf->fb_dat, fbuf->fb_ino); 446 if (vn == NULL) { 447 vn = alloc_vn(f, (const char *)fbuf->fb_dat, -1, 448 fbuf->fb_ino); 449 if (vn == NULL) { 450 fbuf->fb_err = -errno; 451 free(fbuf->fb_dat); 452 return (0); 453 } 454 set_vn(f, vn); /*XXX*/ 455 } else if (vn->ino != FUSE_ROOT_INO) 456 ref_vn(vn); 457 } 458 459 DPRINTF("new ino %llu\n", (unsigned long long)vn->ino); 460 realname = build_realname(f, vn->ino); 461 if (realname == NULL) { 462 fbuf->fb_err = -errno; 463 free(fbuf->fb_dat); 464 return (0); 465 } 466 467 fbuf->fb_err = update_attr(f, &fbuf->fb_attr, realname, vn); 468 free(fbuf->fb_dat); 469 free(realname); 470 471 return (0); 472 } 473 474 static int 475 ifuse_ops_read(struct fuse *f, struct fusebuf *fbuf) 476 { 477 struct fuse_file_info ffi; 478 struct fuse_vnode *vn; 479 char *realname; 480 uint64_t offset; 481 uint32_t size; 482 int ret; 483 484 CHECK_OPT(read); 485 486 bzero(&ffi, sizeof(ffi)); 487 ffi.fh = fbuf->fb_io_fd; 488 size = fbuf->fb_io_len; 489 offset = fbuf->fb_io_off; 490 491 fbuf->fb_dat = malloc(size); 492 if (fbuf->fb_dat == NULL) { 493 fbuf->fb_err = -errno; 494 return (0); 495 } 496 497 vn = tree_get(&f->vnode_tree, fbuf->fb_ino); 498 if (vn == NULL) { 499 fbuf->fb_err = -errno; 500 free(fbuf->fb_dat); 501 return (0); 502 } 503 504 realname = build_realname(f, vn->ino); 505 if (realname == NULL) { 506 fbuf->fb_err = -errno; 507 free(fbuf->fb_dat); 508 return (0); 509 } 510 511 ret = f->op.read(realname, (char *)fbuf->fb_dat, size, offset, &ffi); 512 free(realname); 513 if (ret >= 0) 514 fbuf->fb_len = ret; 515 else 516 fbuf->fb_err = ret; 517 518 if (fbuf->fb_len == 0) 519 free(fbuf->fb_dat); 520 521 return (0); 522 } 523 524 static int 525 ifuse_ops_write(struct fuse *f, struct fusebuf *fbuf) 526 { 527 struct fuse_file_info ffi; 528 struct fuse_vnode *vn; 529 char *realname; 530 uint64_t offset; 531 uint32_t size; 532 int ret; 533 534 CHECK_OPT(write); 535 536 bzero(&ffi, sizeof(ffi)); 537 ffi.fh = fbuf->fb_io_fd; 538 ffi.fh_old = ffi.fh; 539 ffi.writepage = fbuf->fb_io_flags & 1; 540 size = fbuf->fb_io_len; 541 offset = fbuf->fb_io_off; 542 543 vn = tree_get(&f->vnode_tree, fbuf->fb_ino); 544 if (vn == NULL) { 545 fbuf->fb_err = -errno; 546 free(fbuf->fb_dat); 547 return (0); 548 } 549 550 realname = build_realname(f, vn->ino); 551 if (realname == NULL) { 552 fbuf->fb_err = -errno; 553 free(fbuf->fb_dat); 554 return (0); 555 } 556 557 ret = f->op.write(realname, (char *)fbuf->fb_dat, size, offset, &ffi); 558 free(realname); 559 free(fbuf->fb_dat); 560 561 if (ret >= 0) 562 fbuf->fb_io_len = ret; 563 else 564 fbuf->fb_err = ret; 565 566 return (0); 567 } 568 569 static int 570 ifuse_ops_create(struct fuse *f, struct fusebuf *fbuf) 571 { 572 struct fuse_file_info ffi; 573 struct fuse_vnode *vn; 574 uint32_t mode; 575 576 char *realname; 577 578 DPRINTF("Opcode:\tcreate\n"); 579 DPRINTF("Inode:\t%llu\n", (unsigned long long)fbuf->fb_ino); 580 581 bzero(&ffi, sizeof(ffi)); 582 ffi.flags = fbuf->fb_io_flags; 583 mode = fbuf->fb_io_mode; 584 585 vn = get_vn_by_name_and_parent(f, fbuf->fb_dat, fbuf->fb_ino); 586 if (vn == NULL) { 587 fbuf->fb_err = -errno; 588 free(fbuf->fb_dat); 589 return (0); 590 } 591 592 free(fbuf->fb_dat); 593 realname = build_realname(f, vn->ino); 594 if (realname == NULL) { 595 fbuf->fb_err = -errno; 596 return (0); 597 } 598 599 if (f->op.create) 600 fbuf->fb_err = f->op.create(realname, mode, &ffi); 601 else if (f->op.mknod) 602 fbuf->fb_err = f->op.mknod(realname, S_IFREG | mode, 0); 603 else 604 fbuf->fb_err = -ENOSYS; 605 606 if (!fbuf->fb_err) { 607 fbuf->fb_err = update_attr(f, &fbuf->fb_attr, realname, vn); 608 fbuf->fb_ino = fbuf->fb_attr.st_ino; 609 fbuf->fb_io_mode = fbuf->fb_attr.st_mode; 610 } 611 free(realname); 612 613 return (0); 614 } 615 616 static int 617 ifuse_ops_mkdir(struct fuse *f, struct fusebuf *fbuf) 618 { 619 struct fuse_vnode *vn; 620 char *realname; 621 uint32_t mode; 622 623 CHECK_OPT(mkdir); 624 625 mode = fbuf->fb_io_mode; 626 vn = get_vn_by_name_and_parent(f, fbuf->fb_dat, fbuf->fb_ino); 627 if (vn == NULL) { 628 fbuf->fb_err = -errno; 629 free(fbuf->fb_dat); 630 return (0); 631 } 632 633 free(fbuf->fb_dat); 634 realname = build_realname(f, vn->ino); 635 if (realname == NULL) { 636 fbuf->fb_err = -errno; 637 return (0); 638 } 639 640 fbuf->fb_err = f->op.mkdir(realname, mode); 641 642 if (!fbuf->fb_err) { 643 fbuf->fb_err = update_attr(f, &fbuf->fb_attr, realname, vn); 644 fbuf->fb_io_mode = fbuf->fb_attr.st_mode; 645 fbuf->fb_ino = vn->ino; 646 } 647 free(realname); 648 649 return (0); 650 } 651 652 static int 653 ifuse_ops_rmdir(struct fuse *f, struct fusebuf *fbuf) 654 { 655 struct fuse_vnode *vn; 656 char *realname; 657 658 CHECK_OPT(rmdir); 659 vn = get_vn_by_name_and_parent(f, fbuf->fb_dat, fbuf->fb_ino); 660 if (vn == NULL) { 661 fbuf->fb_err = -errno; 662 free(fbuf->fb_dat); 663 return (0); 664 } 665 666 free(fbuf->fb_dat); 667 realname = build_realname(f, vn->ino); 668 if (realname == NULL) { 669 fbuf->fb_err = -errno; 670 return (0); 671 } 672 673 fbuf->fb_err = f->op.rmdir(realname); 674 free(realname); 675 676 return (0); 677 } 678 679 static int 680 ifuse_ops_readlink(struct fuse *f, struct fusebuf *fbuf) 681 { 682 struct fuse_vnode *vn; 683 char *realname; 684 char name[PATH_MAX + 1]; 685 int len, ret; 686 687 DPRINTF("Opcode:\treadlink\n"); 688 DPRINTF("Inode:\t%llu\n", (unsigned long long)fbuf->fb_ino); 689 690 vn = tree_get(&f->vnode_tree, fbuf->fb_ino); 691 if (vn == NULL) { 692 fbuf->fb_err = -errno; 693 return (0); 694 } 695 696 realname = build_realname(f, vn->ino); 697 if (realname == NULL) { 698 fbuf->fb_err = -errno; 699 return (0); 700 } 701 702 if (f->op.readlink) 703 ret = f->op.readlink(realname, name, sizeof(name)); 704 else 705 ret = -ENOSYS; 706 free(realname); 707 708 fbuf->fb_err = ret; 709 if (!ret) { 710 len = strnlen(name, PATH_MAX); 711 fbuf->fb_len = len; 712 fbuf->fb_dat = malloc(fbuf->fb_len); 713 if (fbuf->fb_dat == NULL) { 714 fbuf->fb_err = -errno; 715 return (0); 716 } 717 memcpy(fbuf->fb_dat, name, len); 718 } else 719 fbuf->fb_len = 0; 720 721 return (0); 722 } 723 724 static int 725 ifuse_ops_unlink(struct fuse *f, struct fusebuf *fbuf) 726 { 727 struct fuse_vnode *vn; 728 char *realname; 729 730 CHECK_OPT(unlink); 731 732 vn = get_vn_by_name_and_parent(f, fbuf->fb_dat, fbuf->fb_ino); 733 if (vn == NULL) { 734 free(fbuf->fb_dat); 735 fbuf->fb_err = -errno; 736 return (0); 737 } 738 739 free(fbuf->fb_dat); 740 realname = build_realname(f, vn->ino); 741 if (realname == NULL) { 742 fbuf->fb_err = -errno; 743 return (0); 744 } 745 746 fbuf->fb_err = f->op.unlink(realname); 747 free(realname); 748 749 return (0); 750 } 751 752 static int 753 ifuse_ops_statfs(struct fuse *f, struct fusebuf *fbuf) 754 { 755 struct fuse_vnode *vn; 756 char *realname; 757 758 bzero(&fbuf->fb_stat, sizeof(fbuf->fb_stat)); 759 760 CHECK_OPT(statfs); 761 762 vn = tree_get(&f->vnode_tree, fbuf->fb_ino); 763 if (vn == NULL) { 764 fbuf->fb_err = -errno; 765 return (0); 766 } 767 768 realname = build_realname(f, vn->ino); 769 if (realname == NULL) { 770 fbuf->fb_err = -errno; 771 return (0); 772 } 773 774 fbuf->fb_err = f->op.statfs(realname, &fbuf->fb_stat); 775 free(realname); 776 777 return (0); 778 } 779 780 static int 781 ifuse_ops_link(struct fuse *f, struct fusebuf *fbuf) 782 { 783 struct fuse_vnode *vn; 784 char *realname; 785 char *realname_ln; 786 ino_t oldnodeid; 787 788 CHECK_OPT(link); 789 oldnodeid = fbuf->fb_io_ino; 790 vn = get_vn_by_name_and_parent(f, fbuf->fb_dat, fbuf->fb_ino); 791 if (vn == NULL) { 792 fbuf->fb_err = -errno; 793 free(fbuf->fb_dat); 794 return (0); 795 } 796 797 free(fbuf->fb_dat); 798 realname = build_realname(f, oldnodeid); 799 if (realname == NULL) { 800 fbuf->fb_err = -errno; 801 return (0); 802 } 803 804 realname_ln = build_realname(f, vn->ino); 805 if (realname_ln == NULL) { 806 fbuf->fb_err = -errno; 807 free(realname); 808 return (0); 809 } 810 811 fbuf->fb_err = f->op.link(realname, realname_ln); 812 free(realname); 813 free(realname_ln); 814 815 return (0); 816 } 817 818 static int 819 ifuse_ops_setattr(struct fuse *f, struct fusebuf *fbuf) 820 { 821 struct fuse_vnode *vn; 822 struct timespec ts[2]; 823 struct utimbuf tbuf; 824 struct fb_io *io; 825 char *realname; 826 uid_t uid; 827 gid_t gid; 828 829 DPRINTF("Opcode:\tsetattr\n"); 830 DPRINTF("Inode:\t%llu\n", (unsigned long long)fbuf->fb_ino); 831 832 vn = tree_get(&f->vnode_tree, fbuf->fb_ino); 833 if (vn == NULL) { 834 fbuf->fb_err = -errno; 835 free(fbuf->fb_dat); 836 return (0); 837 } 838 839 realname = build_realname(f, vn->ino); 840 if (realname == NULL) { 841 fbuf->fb_err = -errno; 842 free(fbuf->fb_dat); 843 return (0); 844 } 845 io = fbtod(fbuf, struct fb_io *); 846 847 if (io->fi_flags & FUSE_FATTR_MODE) { 848 if (f->op.chmod) 849 fbuf->fb_err = f->op.chmod(realname, 850 fbuf->fb_attr.st_mode); 851 else 852 fbuf->fb_err = -ENOSYS; 853 } 854 855 if (!fbuf->fb_err && (io->fi_flags & FUSE_FATTR_UID || 856 io->fi_flags & FUSE_FATTR_GID) ) { 857 uid = (io->fi_flags & FUSE_FATTR_UID) ? 858 fbuf->fb_attr.st_uid : (gid_t)-1; 859 gid = (io->fi_flags & FUSE_FATTR_GID) ? 860 fbuf->fb_attr.st_gid : (uid_t)-1; 861 if (f->op.chown) 862 fbuf->fb_err = f->op.chown(realname, uid, gid); 863 else 864 fbuf->fb_err = -ENOSYS; 865 } 866 867 if (!fbuf->fb_err && ( io->fi_flags & FUSE_FATTR_MTIME || 868 io->fi_flags & FUSE_FATTR_ATIME)) { 869 ts[0] = fbuf->fb_attr.st_atim; 870 ts[1] = fbuf->fb_attr.st_mtim; 871 tbuf.actime = ts[0].tv_sec; 872 tbuf.modtime = ts[1].tv_sec; 873 874 if (f->op.utimens) 875 fbuf->fb_err = f->op.utimens(realname, ts); 876 else if (f->op.utime) 877 fbuf->fb_err = f->op.utime(realname, &tbuf); 878 else 879 fbuf->fb_err = -ENOSYS; 880 } 881 882 if (!fbuf->fb_err && (io->fi_flags & FUSE_FATTR_SIZE)) { 883 if (f->op.truncate) 884 fbuf->fb_err = f->op.truncate(realname, 885 fbuf->fb_attr.st_size); 886 else 887 fbuf->fb_err = -ENOSYS; 888 } 889 890 memset(&fbuf->fb_attr, 0, sizeof(struct stat)); 891 892 if (!fbuf->fb_err) 893 fbuf->fb_err = update_attr(f, &fbuf->fb_attr, realname, vn); 894 free(realname); 895 free(fbuf->fb_dat); 896 897 return (0); 898 } 899 900 static int 901 ifuse_ops_symlink(unused struct fuse *f, struct fusebuf *fbuf) 902 { 903 struct fuse_vnode *vn; 904 char *realname; 905 int len; 906 907 CHECK_OPT(symlink); 908 909 vn = get_vn_by_name_and_parent(f, fbuf->fb_dat, fbuf->fb_ino); 910 if (vn == NULL) { 911 fbuf->fb_err = -errno; 912 free(fbuf->fb_dat); 913 return (0); 914 } 915 916 len = strlen((char *)fbuf->fb_dat); 917 918 realname = build_realname(f, vn->ino); 919 if (realname == NULL) { 920 fbuf->fb_err = -errno; 921 free(fbuf->fb_dat); 922 return (0); 923 } 924 925 /* fuse invert the symlink params */ 926 fbuf->fb_err = f->op.symlink((const char *)&fbuf->fb_dat[len + 1], 927 realname); 928 fbuf->fb_ino = vn->ino; 929 free(fbuf->fb_dat); 930 free(realname); 931 932 return (0); 933 } 934 935 static int 936 ifuse_ops_rename(struct fuse *f, struct fusebuf *fbuf) 937 { 938 struct fuse_vnode *vnt; 939 struct fuse_vnode *vnf; 940 char *realnamef; 941 char *realnamet; 942 int len; 943 944 CHECK_OPT(rename); 945 946 len = strlen((char *)fbuf->fb_dat); 947 vnf = get_vn_by_name_and_parent(f, fbuf->fb_dat, fbuf->fb_ino); 948 if (vnf == NULL) { 949 fbuf->fb_err = -errno; 950 free(fbuf->fb_dat); 951 return (0); 952 } 953 954 vnt = get_vn_by_name_and_parent(f, &fbuf->fb_dat[len + 1], 955 fbuf->fb_io_ino); 956 if (vnt == NULL) { 957 fbuf->fb_err = -errno; 958 free(fbuf->fb_dat); 959 return (0); 960 } 961 962 free(fbuf->fb_dat); 963 964 realnamef = build_realname(f, vnf->ino); 965 if (realnamef == NULL) { 966 fbuf->fb_err = -errno; 967 return (0); 968 } 969 970 realnamet = build_realname(f, vnt->ino); 971 if (realnamet == NULL) { 972 fbuf->fb_err = -errno; 973 free(realnamef); 974 return (0); 975 } 976 977 fbuf->fb_err = f->op.rename(realnamef, realnamet); 978 free(realnamef); 979 free(realnamet); 980 981 return (0); 982 } 983 984 static int 985 ifuse_ops_destroy(struct fuse *f) 986 { 987 struct fuse_context *ctx; 988 989 DPRINTF("Opcode:\tdestroy\n"); 990 991 if (f->op.destroy) { 992 ctx = fuse_get_context(); 993 994 f->op.destroy((ctx)?ctx->private_data:NULL); 995 } 996 997 f->fc->dead = 1; 998 999 return (0); 1000 } 1001 1002 static int 1003 ifuse_ops_reclaim(struct fuse *f, struct fusebuf *fbuf) 1004 { 1005 struct fuse_vnode *vn; 1006 1007 vn = tree_get(&f->vnode_tree, fbuf->fb_ino); 1008 if (vn != NULL) 1009 unref_vn(f, vn); 1010 1011 return (0); 1012 } 1013 1014 static int 1015 ifuse_ops_mknod(struct fuse *f, struct fusebuf *fbuf) 1016 { 1017 struct fuse_vnode *vn; 1018 char *realname; 1019 uint32_t mode; 1020 dev_t dev; 1021 1022 CHECK_OPT(mknod); 1023 1024 mode = fbuf->fb_io_mode; 1025 dev = fbuf->fb_io_rdev; 1026 vn = get_vn_by_name_and_parent(f, fbuf->fb_dat, fbuf->fb_ino); 1027 if (vn == NULL) { 1028 fbuf->fb_err = -errno; 1029 free(fbuf->fb_dat); 1030 return (0); 1031 } 1032 1033 free(fbuf->fb_dat); 1034 realname = build_realname(f, vn->ino); 1035 if (realname == NULL) { 1036 fbuf->fb_err = -errno; 1037 return (0); 1038 } 1039 1040 fbuf->fb_err = f->op.mknod(realname, mode, dev); 1041 1042 if (!fbuf->fb_err) { 1043 fbuf->fb_err = update_attr(f, &fbuf->fb_attr, realname, vn); 1044 fbuf->fb_io_mode = fbuf->fb_attr.st_mode; 1045 fbuf->fb_ino = fbuf->fb_attr.st_ino; 1046 } 1047 free(realname); 1048 1049 return (0); 1050 } 1051 1052 int 1053 ifuse_exec_opcode(struct fuse *f, struct fusebuf *fbuf) 1054 { 1055 int ret = 0; 1056 1057 fbuf->fb_len = 0; 1058 fbuf->fb_err = 0; 1059 1060 switch (fbuf->fb_type) { 1061 case FBT_LOOKUP: 1062 ret = ifuse_ops_lookup(f, fbuf); 1063 break; 1064 case FBT_GETATTR: 1065 ret = ifuse_ops_getattr(f, fbuf); 1066 break; 1067 case FBT_SETATTR: 1068 ret = ifuse_ops_setattr(f, fbuf); 1069 break; 1070 case FBT_READLINK: 1071 ret = ifuse_ops_readlink(f, fbuf); 1072 break; 1073 case FBT_MKDIR: 1074 ret = ifuse_ops_mkdir(f, fbuf); 1075 break; 1076 case FBT_UNLINK: 1077 ret = ifuse_ops_unlink(f, fbuf); 1078 break; 1079 case FBT_RMDIR: 1080 ret = ifuse_ops_rmdir(f, fbuf); 1081 break; 1082 case FBT_LINK: 1083 ret = ifuse_ops_link(f, fbuf); 1084 break; 1085 case FBT_OPEN: 1086 ret = ifuse_ops_open(f, fbuf); 1087 break; 1088 case FBT_READ: 1089 ret = ifuse_ops_read(f, fbuf); 1090 break; 1091 case FBT_WRITE: 1092 ret = ifuse_ops_write(f, fbuf); 1093 break; 1094 case FBT_STATFS: 1095 ret = ifuse_ops_statfs(f, fbuf); 1096 break; 1097 case FBT_RELEASE: 1098 ret = ifuse_ops_release(f, fbuf); 1099 break; 1100 case FBT_INIT: 1101 ret = ifuse_ops_init(f); 1102 break; 1103 case FBT_OPENDIR: 1104 ret = ifuse_ops_opendir(f, fbuf); 1105 break; 1106 case FBT_READDIR: 1107 ret = ifuse_ops_readdir(f, fbuf); 1108 break; 1109 case FBT_RELEASEDIR: 1110 ret = ifuse_ops_releasedir(f, fbuf); 1111 break; 1112 case FBT_ACCESS: 1113 ret = ifuse_ops_access(f, fbuf); 1114 break; 1115 case FBT_CREATE: 1116 ret = ifuse_ops_create(f, fbuf); 1117 break; 1118 case FBT_SYMLINK: 1119 ret = ifuse_ops_symlink(f, fbuf); 1120 break; 1121 case FBT_RENAME: 1122 ret = ifuse_ops_rename(f, fbuf); 1123 break; 1124 case FBT_DESTROY: 1125 ret = ifuse_ops_destroy(f); 1126 break; 1127 case FBT_RECLAIM: 1128 ret = ifuse_ops_reclaim(f, fbuf); 1129 break; 1130 case FBT_MKNOD: 1131 ret = ifuse_ops_mknod(f, fbuf); 1132 break; 1133 default: 1134 DPRINTF("Opcode:\t%i not supported\n", fbuf->fb_type); 1135 DPRINTF("Inode:\t%llu\n", (unsigned long long)fbuf->fb_ino); 1136 1137 fbuf->fb_err = -ENOSYS; 1138 fbuf->fb_len = 0; 1139 } 1140 DPRINTF("\n"); 1141 1142 /* fuse api use negative errno */ 1143 fbuf->fb_err = -fbuf->fb_err; 1144 return (ret); 1145 } 1146