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