1 /* $OpenBSD: fuse_ops.c,v 1.25 2016/08/30 16:45:54 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 vn = get_vn_by_name_and_parent(f, fbuf->fb_dat, fbuf->fb_ino); 436 if (vn == NULL) { 437 vn = alloc_vn(f, (const char *)fbuf->fb_dat, -1, fbuf->fb_ino); 438 if (vn == NULL) { 439 fbuf->fb_err = -errno; 440 free(fbuf->fb_dat); 441 return (0); 442 } 443 set_vn(f, vn); /*XXX*/ 444 } 445 446 DPRINTF("new ino %llu\n", (unsigned long long)vn->ino); 447 realname = build_realname(f, vn->ino); 448 if (realname == NULL) { 449 fbuf->fb_err = -errno; 450 free(fbuf->fb_dat); 451 return (0); 452 } 453 454 fbuf->fb_err = update_attr(f, &fbuf->fb_attr, realname, vn); 455 free(fbuf->fb_dat); 456 free(realname); 457 458 return (0); 459 } 460 461 static int 462 ifuse_ops_read(struct fuse *f, struct fusebuf *fbuf) 463 { 464 struct fuse_file_info ffi; 465 struct fuse_vnode *vn; 466 char *realname; 467 uint64_t offset; 468 uint32_t size; 469 int ret; 470 471 CHECK_OPT(read); 472 473 bzero(&ffi, sizeof(ffi)); 474 ffi.fh = fbuf->fb_io_fd; 475 size = fbuf->fb_io_len; 476 offset = fbuf->fb_io_off; 477 478 fbuf->fb_dat = malloc(size); 479 if (fbuf->fb_dat == NULL) { 480 fbuf->fb_err = -errno; 481 return (0); 482 } 483 484 vn = tree_get(&f->vnode_tree, fbuf->fb_ino); 485 if (vn == NULL) { 486 fbuf->fb_err = -errno; 487 free(fbuf->fb_dat); 488 return (0); 489 } 490 491 realname = build_realname(f, vn->ino); 492 if (realname == NULL) { 493 fbuf->fb_err = -errno; 494 free(fbuf->fb_dat); 495 return (0); 496 } 497 498 ret = f->op.read(realname, (char *)fbuf->fb_dat, size, offset, &ffi); 499 free(realname); 500 if (ret >= 0) 501 fbuf->fb_len = ret; 502 else 503 fbuf->fb_err = ret; 504 505 if (fbuf->fb_len == 0) 506 free(fbuf->fb_dat); 507 508 return (0); 509 } 510 511 static int 512 ifuse_ops_write(struct fuse *f, struct fusebuf *fbuf) 513 { 514 struct fuse_file_info ffi; 515 struct fuse_vnode *vn; 516 char *realname; 517 uint64_t offset; 518 uint32_t size; 519 int ret; 520 521 CHECK_OPT(write); 522 523 bzero(&ffi, sizeof(ffi)); 524 ffi.fh = fbuf->fb_io_fd; 525 ffi.fh_old = ffi.fh; 526 ffi.writepage = fbuf->fb_io_flags & 1; 527 size = fbuf->fb_io_len; 528 offset = fbuf->fb_io_off; 529 530 vn = tree_get(&f->vnode_tree, fbuf->fb_ino); 531 if (vn == NULL) { 532 fbuf->fb_err = -errno; 533 free(fbuf->fb_dat); 534 return (0); 535 } 536 537 realname = build_realname(f, vn->ino); 538 if (realname == NULL) { 539 fbuf->fb_err = -errno; 540 free(fbuf->fb_dat); 541 return (0); 542 } 543 544 ret = f->op.write(realname, (char *)fbuf->fb_dat, size, offset, &ffi); 545 free(realname); 546 free(fbuf->fb_dat); 547 548 if (ret >= 0) 549 fbuf->fb_io_len = ret; 550 else 551 fbuf->fb_err = ret; 552 553 return (0); 554 } 555 556 static int 557 ifuse_ops_create(struct fuse *f, struct fusebuf *fbuf) 558 { 559 struct fuse_file_info ffi; 560 struct fuse_vnode *vn; 561 uint32_t mode; 562 563 char *realname; 564 565 DPRINTF("Opcode:\tcreate\n"); 566 DPRINTF("Inode:\t%llu\n", (unsigned long long)fbuf->fb_ino); 567 568 bzero(&ffi, sizeof(ffi)); 569 ffi.flags = fbuf->fb_io_flags; 570 mode = fbuf->fb_io_mode; 571 572 vn = get_vn_by_name_and_parent(f, fbuf->fb_dat, fbuf->fb_ino); 573 if (vn == NULL) { 574 fbuf->fb_err = -errno; 575 free(fbuf->fb_dat); 576 return (0); 577 } 578 579 free(fbuf->fb_dat); 580 realname = build_realname(f, vn->ino); 581 if (realname == NULL) { 582 fbuf->fb_err = -errno; 583 return (0); 584 } 585 586 if (f->op.create) 587 fbuf->fb_err = f->op.create(realname, mode, &ffi); 588 else if (f->op.mknod) 589 fbuf->fb_err = f->op.mknod(realname, S_IFREG | mode, 0); 590 else 591 fbuf->fb_err = -ENOSYS; 592 593 if (!fbuf->fb_err) { 594 fbuf->fb_err = update_attr(f, &fbuf->fb_attr, realname, vn); 595 fbuf->fb_ino = fbuf->fb_attr.st_ino; 596 fbuf->fb_io_mode = fbuf->fb_attr.st_mode; 597 } 598 free(realname); 599 600 return (0); 601 } 602 603 static int 604 ifuse_ops_mkdir(struct fuse *f, struct fusebuf *fbuf) 605 { 606 struct fuse_vnode *vn; 607 char *realname; 608 uint32_t mode; 609 610 CHECK_OPT(mkdir); 611 612 mode = fbuf->fb_io_mode; 613 vn = get_vn_by_name_and_parent(f, fbuf->fb_dat, fbuf->fb_ino); 614 if (vn == NULL) { 615 fbuf->fb_err = -errno; 616 free(fbuf->fb_dat); 617 return (0); 618 } 619 620 free(fbuf->fb_dat); 621 realname = build_realname(f, vn->ino); 622 if (realname == NULL) { 623 fbuf->fb_err = -errno; 624 return (0); 625 } 626 627 fbuf->fb_err = f->op.mkdir(realname, mode); 628 629 if (!fbuf->fb_err) { 630 fbuf->fb_err = update_attr(f, &fbuf->fb_attr, realname, vn); 631 fbuf->fb_io_mode = fbuf->fb_attr.st_mode; 632 fbuf->fb_ino = vn->ino; 633 } 634 free(realname); 635 636 return (0); 637 } 638 639 static int 640 ifuse_ops_rmdir(struct fuse *f, struct fusebuf *fbuf) 641 { 642 struct fuse_vnode *vn; 643 char *realname; 644 645 CHECK_OPT(rmdir); 646 vn = get_vn_by_name_and_parent(f, fbuf->fb_dat, fbuf->fb_ino); 647 if (vn == NULL) { 648 fbuf->fb_err = -errno; 649 free(fbuf->fb_dat); 650 return (0); 651 } 652 653 free(fbuf->fb_dat); 654 realname = build_realname(f, vn->ino); 655 if (realname == NULL) { 656 fbuf->fb_err = -errno; 657 return (0); 658 } 659 660 fbuf->fb_err = f->op.rmdir(realname); 661 free(realname); 662 663 return (0); 664 } 665 666 static int 667 ifuse_ops_readlink(struct fuse *f, struct fusebuf *fbuf) 668 { 669 struct fuse_vnode *vn; 670 char *realname; 671 char name[PATH_MAX + 1]; 672 int len, ret; 673 674 DPRINTF("Opcode:\treadlink\n"); 675 DPRINTF("Inode:\t%llu\n", (unsigned long long)fbuf->fb_ino); 676 677 vn = tree_get(&f->vnode_tree, fbuf->fb_ino); 678 if (vn == NULL) { 679 fbuf->fb_err = -errno; 680 return (0); 681 } 682 683 realname = build_realname(f, vn->ino); 684 if (realname == NULL) { 685 fbuf->fb_err = -errno; 686 return (0); 687 } 688 689 if (f->op.readlink) 690 ret = f->op.readlink(realname, name, sizeof(name)); 691 else 692 ret = -ENOSYS; 693 free(realname); 694 695 fbuf->fb_err = ret; 696 if (!ret) { 697 len = strnlen(name, PATH_MAX); 698 fbuf->fb_len = len; 699 fbuf->fb_dat = malloc(fbuf->fb_len); 700 if (fbuf->fb_dat == NULL) { 701 fbuf->fb_err = -errno; 702 return (0); 703 } 704 memcpy(fbuf->fb_dat, name, len); 705 } else 706 fbuf->fb_len = 0; 707 708 return (0); 709 } 710 711 static int 712 ifuse_ops_unlink(struct fuse *f, struct fusebuf *fbuf) 713 { 714 struct fuse_vnode *vn; 715 char *realname; 716 717 CHECK_OPT(unlink); 718 719 vn = get_vn_by_name_and_parent(f, fbuf->fb_dat, fbuf->fb_ino); 720 if (vn == NULL) { 721 free(fbuf->fb_dat); 722 fbuf->fb_err = -errno; 723 return (0); 724 } 725 726 free(fbuf->fb_dat); 727 realname = build_realname(f, vn->ino); 728 if (realname == NULL) { 729 fbuf->fb_err = -errno; 730 return (0); 731 } 732 733 fbuf->fb_err = f->op.unlink(realname); 734 free(realname); 735 736 return (0); 737 } 738 739 static int 740 ifuse_ops_statfs(struct fuse *f, struct fusebuf *fbuf) 741 { 742 struct fuse_vnode *vn; 743 char *realname; 744 745 bzero(&fbuf->fb_stat, sizeof(fbuf->fb_stat)); 746 747 CHECK_OPT(statfs); 748 749 vn = tree_get(&f->vnode_tree, fbuf->fb_ino); 750 if (vn == NULL) { 751 fbuf->fb_err = -errno; 752 return (0); 753 } 754 755 realname = build_realname(f, vn->ino); 756 if (realname == NULL) { 757 fbuf->fb_err = -errno; 758 return (0); 759 } 760 761 fbuf->fb_err = f->op.statfs(realname, &fbuf->fb_stat); 762 free(realname); 763 764 return (0); 765 } 766 767 static int 768 ifuse_ops_link(struct fuse *f, struct fusebuf *fbuf) 769 { 770 struct fuse_vnode *vn; 771 char *realname; 772 char *realname_ln; 773 ino_t oldnodeid; 774 775 CHECK_OPT(link); 776 oldnodeid = fbuf->fb_io_ino; 777 vn = get_vn_by_name_and_parent(f, fbuf->fb_dat, fbuf->fb_ino); 778 if (vn == NULL) { 779 fbuf->fb_err = -errno; 780 free(fbuf->fb_dat); 781 return (0); 782 } 783 784 free(fbuf->fb_dat); 785 realname = build_realname(f, oldnodeid); 786 if (realname == NULL) { 787 fbuf->fb_err = -errno; 788 return (0); 789 } 790 791 realname_ln = build_realname(f, vn->ino); 792 if (realname_ln == NULL) { 793 fbuf->fb_err = -errno; 794 free(realname); 795 return (0); 796 } 797 798 fbuf->fb_err = f->op.link(realname, realname_ln); 799 free(realname); 800 free(realname_ln); 801 802 return (0); 803 } 804 805 static int 806 ifuse_ops_setattr(struct fuse *f, struct fusebuf *fbuf) 807 { 808 struct fuse_vnode *vn; 809 struct timespec ts[2]; 810 struct utimbuf tbuf; 811 struct fb_io *io; 812 char *realname; 813 uid_t uid; 814 gid_t gid; 815 816 DPRINTF("Opcode:\tsetattr\n"); 817 DPRINTF("Inode:\t%llu\n", (unsigned long long)fbuf->fb_ino); 818 819 vn = tree_get(&f->vnode_tree, fbuf->fb_ino); 820 if (vn == NULL) { 821 fbuf->fb_err = -errno; 822 free(fbuf->fb_dat); 823 return (0); 824 } 825 826 realname = build_realname(f, vn->ino); 827 if (realname == NULL) { 828 fbuf->fb_err = -errno; 829 free(fbuf->fb_dat); 830 return (0); 831 } 832 io = fbtod(fbuf, struct fb_io *); 833 834 if (io->fi_flags & FUSE_FATTR_MODE) { 835 if (f->op.chmod) 836 fbuf->fb_err = f->op.chmod(realname, 837 fbuf->fb_attr.st_mode); 838 else 839 fbuf->fb_err = -ENOSYS; 840 } 841 842 if (!fbuf->fb_err && (io->fi_flags & FUSE_FATTR_UID || 843 io->fi_flags & FUSE_FATTR_GID) ) { 844 uid = (io->fi_flags & FUSE_FATTR_UID) ? 845 fbuf->fb_attr.st_uid : (gid_t)-1; 846 gid = (io->fi_flags & FUSE_FATTR_GID) ? 847 fbuf->fb_attr.st_gid : (uid_t)-1; 848 if (f->op.chown) 849 fbuf->fb_err = f->op.chown(realname, uid, gid); 850 else 851 fbuf->fb_err = -ENOSYS; 852 } 853 854 if (!fbuf->fb_err && ( io->fi_flags & FUSE_FATTR_MTIME || 855 io->fi_flags & FUSE_FATTR_ATIME)) { 856 ts[0] = fbuf->fb_attr.st_atim; 857 ts[1] = fbuf->fb_attr.st_mtim; 858 tbuf.actime = ts[0].tv_sec; 859 tbuf.modtime = ts[1].tv_sec; 860 861 if (f->op.utimens) 862 fbuf->fb_err = f->op.utimens(realname, ts); 863 else if (f->op.utime) 864 fbuf->fb_err = f->op.utime(realname, &tbuf); 865 else 866 fbuf->fb_err = -ENOSYS; 867 } 868 869 if (!fbuf->fb_err && (io->fi_flags & FUSE_FATTR_SIZE)) { 870 if (f->op.truncate) 871 fbuf->fb_err = f->op.truncate(realname, 872 fbuf->fb_attr.st_size); 873 else 874 fbuf->fb_err = -ENOSYS; 875 } 876 877 memset(&fbuf->fb_attr, 0, sizeof(struct stat)); 878 879 if (!fbuf->fb_err) 880 fbuf->fb_err = update_attr(f, &fbuf->fb_attr, realname, vn); 881 free(realname); 882 free(fbuf->fb_dat); 883 884 return (0); 885 } 886 887 static int 888 ifuse_ops_symlink(unused struct fuse *f, struct fusebuf *fbuf) 889 { 890 struct fuse_vnode *vn; 891 char *realname; 892 int len; 893 894 CHECK_OPT(symlink); 895 896 vn = get_vn_by_name_and_parent(f, fbuf->fb_dat, fbuf->fb_ino); 897 if (vn == NULL) { 898 fbuf->fb_err = -errno; 899 free(fbuf->fb_dat); 900 return (0); 901 } 902 903 len = strlen((char *)fbuf->fb_dat); 904 905 realname = build_realname(f, vn->ino); 906 if (realname == NULL) { 907 fbuf->fb_err = -errno; 908 free(fbuf->fb_dat); 909 return (0); 910 } 911 912 /* fuse invert the symlink params */ 913 fbuf->fb_err = f->op.symlink((const char *)&fbuf->fb_dat[len + 1], 914 realname); 915 fbuf->fb_ino = vn->ino; 916 free(fbuf->fb_dat); 917 free(realname); 918 919 return (0); 920 } 921 922 static int 923 ifuse_ops_rename(struct fuse *f, struct fusebuf *fbuf) 924 { 925 struct fuse_vnode *vnt; 926 struct fuse_vnode *vnf; 927 char *realnamef; 928 char *realnamet; 929 int len; 930 931 CHECK_OPT(rename); 932 933 len = strlen((char *)fbuf->fb_dat); 934 vnf = get_vn_by_name_and_parent(f, fbuf->fb_dat, fbuf->fb_ino); 935 if (vnf == NULL) { 936 fbuf->fb_err = -errno; 937 free(fbuf->fb_dat); 938 return (0); 939 } 940 941 vnt = get_vn_by_name_and_parent(f, &fbuf->fb_dat[len + 1], 942 fbuf->fb_io_ino); 943 if (vnt == NULL) { 944 fbuf->fb_err = -errno; 945 free(fbuf->fb_dat); 946 return (0); 947 } 948 949 free(fbuf->fb_dat); 950 951 realnamef = build_realname(f, vnf->ino); 952 if (realnamef == NULL) { 953 fbuf->fb_err = -errno; 954 return (0); 955 } 956 957 realnamet = build_realname(f, vnt->ino); 958 if (realnamet == NULL) { 959 fbuf->fb_err = -errno; 960 free(realnamef); 961 return (0); 962 } 963 964 fbuf->fb_err = f->op.rename(realnamef, realnamet); 965 free(realnamef); 966 free(realnamet); 967 968 return (0); 969 } 970 971 static int 972 ifuse_ops_destroy(struct fuse *f) 973 { 974 struct fuse_context *ctx; 975 976 DPRINTF("Opcode:\tdestroy\n"); 977 978 if (f->op.destroy) { 979 ctx = fuse_get_context(); 980 981 f->op.destroy((ctx)?ctx->private_data:NULL); 982 } 983 984 f->fc->dead = 1; 985 986 return (0); 987 } 988 989 static int 990 ifuse_ops_reclaim(struct fuse *f, struct fusebuf *fbuf) 991 { 992 struct fuse_vnode *vn; 993 994 vn = tree_pop(&f->vnode_tree, fbuf->fb_ino); 995 if (vn) { 996 remove_vnode_from_name_tree(f, vn); 997 free(vn); 998 } 999 1000 return (0); 1001 } 1002 1003 static int 1004 ifuse_ops_mknod(struct fuse *f, struct fusebuf *fbuf) 1005 { 1006 struct fuse_vnode *vn; 1007 char *realname; 1008 uint32_t mode; 1009 dev_t dev; 1010 1011 CHECK_OPT(mknod); 1012 1013 mode = fbuf->fb_io_mode; 1014 dev = fbuf->fb_io_rdev; 1015 vn = get_vn_by_name_and_parent(f, fbuf->fb_dat, fbuf->fb_ino); 1016 if (vn == NULL) { 1017 fbuf->fb_err = -errno; 1018 free(fbuf->fb_dat); 1019 return (0); 1020 } 1021 1022 free(fbuf->fb_dat); 1023 realname = build_realname(f, vn->ino); 1024 if (realname == NULL) { 1025 fbuf->fb_err = -errno; 1026 return (0); 1027 } 1028 1029 fbuf->fb_err = f->op.mknod(realname, mode, dev); 1030 1031 if (!fbuf->fb_err) { 1032 fbuf->fb_err = update_attr(f, &fbuf->fb_attr, realname, vn); 1033 fbuf->fb_io_mode = fbuf->fb_attr.st_mode; 1034 fbuf->fb_ino = fbuf->fb_attr.st_ino; 1035 } 1036 free(realname); 1037 1038 return (0); 1039 } 1040 1041 int 1042 ifuse_exec_opcode(struct fuse *f, struct fusebuf *fbuf) 1043 { 1044 int ret = 0; 1045 1046 fbuf->fb_len = 0; 1047 fbuf->fb_err = 0; 1048 1049 switch (fbuf->fb_type) { 1050 case FBT_LOOKUP: 1051 ret = ifuse_ops_lookup(f, fbuf); 1052 break; 1053 case FBT_GETATTR: 1054 ret = ifuse_ops_getattr(f, fbuf); 1055 break; 1056 case FBT_SETATTR: 1057 ret = ifuse_ops_setattr(f, fbuf); 1058 break; 1059 case FBT_READLINK: 1060 ret = ifuse_ops_readlink(f, fbuf); 1061 break; 1062 case FBT_MKDIR: 1063 ret = ifuse_ops_mkdir(f, fbuf); 1064 break; 1065 case FBT_UNLINK: 1066 ret = ifuse_ops_unlink(f, fbuf); 1067 break; 1068 case FBT_RMDIR: 1069 ret = ifuse_ops_rmdir(f, fbuf); 1070 break; 1071 case FBT_LINK: 1072 ret = ifuse_ops_link(f, fbuf); 1073 break; 1074 case FBT_OPEN: 1075 ret = ifuse_ops_open(f, fbuf); 1076 break; 1077 case FBT_READ: 1078 ret = ifuse_ops_read(f, fbuf); 1079 break; 1080 case FBT_WRITE: 1081 ret = ifuse_ops_write(f, fbuf); 1082 break; 1083 case FBT_STATFS: 1084 ret = ifuse_ops_statfs(f, fbuf); 1085 break; 1086 case FBT_RELEASE: 1087 ret = ifuse_ops_release(f, fbuf); 1088 break; 1089 case FBT_INIT: 1090 ret = ifuse_ops_init(f); 1091 break; 1092 case FBT_OPENDIR: 1093 ret = ifuse_ops_opendir(f, fbuf); 1094 break; 1095 case FBT_READDIR: 1096 ret = ifuse_ops_readdir(f, fbuf); 1097 break; 1098 case FBT_RELEASEDIR: 1099 ret = ifuse_ops_releasedir(f, fbuf); 1100 break; 1101 case FBT_ACCESS: 1102 ret = ifuse_ops_access(f, fbuf); 1103 break; 1104 case FBT_CREATE: 1105 ret = ifuse_ops_create(f, fbuf); 1106 break; 1107 case FBT_SYMLINK: 1108 ret = ifuse_ops_symlink(f, fbuf); 1109 break; 1110 case FBT_RENAME: 1111 ret = ifuse_ops_rename(f, fbuf); 1112 break; 1113 case FBT_DESTROY: 1114 ret = ifuse_ops_destroy(f); 1115 break; 1116 case FBT_RECLAIM: 1117 ret = ifuse_ops_reclaim(f, fbuf); 1118 break; 1119 case FBT_MKNOD: 1120 ret = ifuse_ops_mknod(f, fbuf); 1121 break; 1122 default: 1123 DPRINTF("Opcode:\t%i not supported\n", fbuf->fb_type); 1124 DPRINTF("Inode:\t%llu\n", (unsigned long long)fbuf->fb_ino); 1125 1126 fbuf->fb_err = -ENOSYS; 1127 fbuf->fb_len = 0; 1128 } 1129 DPRINTF("\n"); 1130 1131 /* fuse api use negative errno */ 1132 fbuf->fb_err = -fbuf->fb_err; 1133 return (ret); 1134 } 1135