1 /* $NetBSD: dispatcher.c,v 1.35 2010/12/06 14:50:34 pooka Exp $ */ 2 3 /* 4 * Copyright (c) 2006, 2007, 2008 Antti Kantee. All Rights Reserved. 5 * 6 * Development of this software was supported by the 7 * Ulla Tuominen Foundation, the Finnish Cultural Foundation and 8 * Research Foundation of Helsinki University of Technology. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 20 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 #if !defined(lint) 34 __RCSID("$NetBSD: dispatcher.c,v 1.35 2010/12/06 14:50:34 pooka Exp $"); 35 #endif /* !lint */ 36 37 #include <sys/types.h> 38 #include <sys/poll.h> 39 40 #include <assert.h> 41 #include <errno.h> 42 #include <pthread.h> 43 #include <puffs.h> 44 #include <puffsdump.h> 45 #include <stdio.h> 46 #include <stdlib.h> 47 #include <unistd.h> 48 49 #include "puffs_priv.h" 50 51 static void dispatch(struct puffs_cc *); 52 53 /* for our eyes only */ 54 void 55 puffs__ml_dispatch(struct puffs_usermount *pu, struct puffs_framebuf *pb) 56 { 57 struct puffs_cc *pcc = puffs_cc_getcc(pu); 58 struct puffs_req *preq; 59 60 pcc->pcc_pb = pb; 61 pcc->pcc_flags |= PCC_MLCONT; 62 dispatch(pcc); 63 64 /* Put result to kernel sendqueue if necessary */ 65 preq = puffs__framebuf_getdataptr(pcc->pcc_pb); 66 if (PUFFSOP_WANTREPLY(preq->preq_opclass)) { 67 if (pu->pu_flags & PUFFS_FLAG_OPDUMP) 68 puffsdump_rv(preq); 69 70 puffs_framev_enqueue_justsend(pu, pu->pu_fd, 71 pcc->pcc_pb, 0, 0); 72 } else { 73 puffs_framebuf_destroy(pcc->pcc_pb); 74 } 75 76 /* who needs information when you're living on borrowed time? */ 77 if (pcc->pcc_flags & PCC_BORROWED) { 78 puffs_cc_yield(pcc); /* back to borrow source */ 79 } 80 pcc->pcc_flags = 0; 81 } 82 83 /* public, but not really tested and only semi-supported */ 84 int 85 puffs_dispatch_create(struct puffs_usermount *pu, struct puffs_framebuf *pb, 86 struct puffs_cc **pccp) 87 { 88 struct puffs_cc *pcc; 89 90 if (puffs__cc_create(pu, dispatch, &pcc) == -1) 91 return -1; 92 93 pcc->pcc_pb = pb; 94 *pccp = pcc; 95 96 return 0; 97 } 98 99 int 100 puffs_dispatch_exec(struct puffs_cc *pcc, struct puffs_framebuf **pbp) 101 { 102 int rv; 103 104 puffs_cc_continue(pcc); 105 106 if (pcc->pcc_flags & PCC_DONE) { 107 rv = 1; 108 *pbp = pcc->pcc_pb; 109 pcc->pcc_flags = 0; 110 puffs__cc_destroy(pcc, 0); 111 } else { 112 rv = 0; 113 } 114 115 return rv; 116 } 117 118 static void 119 dispatch(struct puffs_cc *pcc) 120 { 121 struct puffs_usermount *pu = pcc->pcc_pu; 122 struct puffs_ops *pops = &pu->pu_ops; 123 struct puffs_req *preq = puffs__framebuf_getdataptr(pcc->pcc_pb); 124 void *auxbuf; /* help with typecasting */ 125 puffs_cookie_t opcookie; 126 int error = 0, buildpath; 127 128 /* XXX: smaller hammer, please */ 129 if ((PUFFSOP_OPCLASS(preq->preq_opclass == PUFFSOP_VFS && 130 preq->preq_optype == PUFFS_VFS_VPTOFH)) || 131 (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VN && 132 (preq->preq_optype == PUFFS_VN_READDIR 133 || preq->preq_optype == PUFFS_VN_READ))) { 134 if (puffs_framebuf_reserve_space(pcc->pcc_pb, 135 PUFFS_MSG_MAXSIZE) == -1) 136 error = errno; 137 preq = puffs__framebuf_getdataptr(pcc->pcc_pb); 138 } 139 140 auxbuf = preq; 141 opcookie = preq->preq_cookie; 142 143 assert((pcc->pcc_flags & PCC_DONE) == 0); 144 145 buildpath = pu->pu_flags & PUFFS_FLAG_BUILDPATH; 146 preq->preq_setbacks = 0; 147 148 if (pu->pu_flags & PUFFS_FLAG_OPDUMP) 149 puffsdump_req(preq); 150 151 puffs__cc_setcaller(pcc, preq->preq_pid, preq->preq_lid); 152 153 /* pre-operation */ 154 if (pu->pu_oppre) 155 pu->pu_oppre(pu); 156 157 if (error) 158 goto out; 159 160 /* Execute actual operation */ 161 if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VFS) { 162 switch (preq->preq_optype) { 163 case PUFFS_VFS_UNMOUNT: 164 { 165 struct puffs_vfsmsg_unmount *auxt = auxbuf; 166 167 PU_SETSTATE(pu, PUFFS_STATE_UNMOUNTING); 168 error = pops->puffs_fs_unmount(pu, auxt->pvfsr_flags); 169 if (!error) 170 PU_SETSTATE(pu, PUFFS_STATE_UNMOUNTED); 171 else 172 PU_SETSTATE(pu, PUFFS_STATE_RUNNING); 173 break; 174 } 175 176 case PUFFS_VFS_STATVFS: 177 { 178 struct puffs_vfsmsg_statvfs *auxt = auxbuf; 179 180 error = pops->puffs_fs_statvfs(pu, &auxt->pvfsr_sb); 181 break; 182 } 183 184 case PUFFS_VFS_SYNC: 185 { 186 struct puffs_vfsmsg_sync *auxt = auxbuf; 187 PUFFS_MAKECRED(pcr, &auxt->pvfsr_cred); 188 189 error = pops->puffs_fs_sync(pu, 190 auxt->pvfsr_waitfor, pcr); 191 break; 192 } 193 194 case PUFFS_VFS_FHTOVP: 195 { 196 struct puffs_vfsmsg_fhtonode *auxt = auxbuf; 197 struct puffs_newinfo pni; 198 199 pni.pni_cookie = &auxt->pvfsr_fhcookie; 200 pni.pni_vtype = &auxt->pvfsr_vtype; 201 pni.pni_size = &auxt->pvfsr_size; 202 pni.pni_rdev = &auxt->pvfsr_rdev; 203 204 error = pops->puffs_fs_fhtonode(pu, auxt->pvfsr_data, 205 auxt->pvfsr_dsize, &pni); 206 207 break; 208 } 209 210 case PUFFS_VFS_VPTOFH: 211 { 212 struct puffs_vfsmsg_nodetofh *auxt = auxbuf; 213 214 error = pops->puffs_fs_nodetofh(pu, 215 auxt->pvfsr_fhcookie, auxt->pvfsr_data, 216 &auxt->pvfsr_dsize); 217 218 break; 219 } 220 221 case PUFFS_VFS_EXTATTRCTL: 222 { 223 struct puffs_vfsmsg_extattrctl *auxt = auxbuf; 224 const char *attrname; 225 int flags; 226 227 if (pops->puffs_fs_extattrctl == NULL) { 228 error = EOPNOTSUPP; 229 break; 230 } 231 232 if (auxt->pvfsr_flags & PUFFS_EXTATTRCTL_HASATTRNAME) 233 attrname = auxt->pvfsr_attrname; 234 else 235 attrname = NULL; 236 237 flags = auxt->pvfsr_flags & PUFFS_EXTATTRCTL_HASNODE; 238 error = pops->puffs_fs_extattrctl(pu, auxt->pvfsr_cmd, 239 opcookie, flags, 240 auxt->pvfsr_attrnamespace, attrname); 241 break; 242 } 243 244 default: 245 /* 246 * I guess the kernel sees this one coming 247 */ 248 error = EINVAL; 249 break; 250 } 251 252 /* XXX: audit return values */ 253 /* XXX: sync with kernel */ 254 } else if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VN) { 255 switch (preq->preq_optype) { 256 case PUFFS_VN_LOOKUP: 257 { 258 struct puffs_vnmsg_lookup *auxt = auxbuf; 259 struct puffs_newinfo pni; 260 struct puffs_cn pcn; 261 262 pcn.pcn_pkcnp = &auxt->pvnr_cn; 263 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred); 264 pni.pni_cookie = &auxt->pvnr_newnode; 265 pni.pni_vtype = &auxt->pvnr_vtype; 266 pni.pni_size = &auxt->pvnr_size; 267 pni.pni_rdev = &auxt->pvnr_rdev; 268 269 if (buildpath) { 270 error = puffs_path_pcnbuild(pu, &pcn, opcookie); 271 if (error) 272 break; 273 } 274 275 /* lookup *must* be present */ 276 error = pops->puffs_node_lookup(pu, opcookie, 277 &pni, &pcn); 278 279 if (buildpath) { 280 if (error) { 281 pu->pu_pathfree(pu, &pcn.pcn_po_full); 282 } else { 283 struct puffs_node *pn; 284 285 /* 286 * did we get a new node or a 287 * recycled node? 288 */ 289 pn = PU_CMAP(pu, auxt->pvnr_newnode); 290 if (pn->pn_po.po_path == NULL) 291 pn->pn_po = pcn.pcn_po_full; 292 else 293 pu->pu_pathfree(pu, 294 &pcn.pcn_po_full); 295 } 296 } 297 298 break; 299 } 300 301 case PUFFS_VN_CREATE: 302 { 303 struct puffs_vnmsg_create *auxt = auxbuf; 304 struct puffs_newinfo pni; 305 struct puffs_cn pcn; 306 307 if (pops->puffs_node_create == NULL) { 308 error = 0; 309 break; 310 } 311 312 pcn.pcn_pkcnp = &auxt->pvnr_cn; 313 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred); 314 315 memset(&pni, 0, sizeof(pni)); 316 pni.pni_cookie = &auxt->pvnr_newnode; 317 318 if (buildpath) { 319 error = puffs_path_pcnbuild(pu, &pcn, opcookie); 320 if (error) 321 break; 322 } 323 324 error = pops->puffs_node_create(pu, 325 opcookie, &pni, &pcn, &auxt->pvnr_va); 326 327 if (buildpath) { 328 if (error) { 329 pu->pu_pathfree(pu, &pcn.pcn_po_full); 330 } else { 331 struct puffs_node *pn; 332 333 pn = PU_CMAP(pu, auxt->pvnr_newnode); 334 pn->pn_po = pcn.pcn_po_full; 335 } 336 } 337 338 break; 339 } 340 341 case PUFFS_VN_MKNOD: 342 { 343 struct puffs_vnmsg_mknod *auxt = auxbuf; 344 struct puffs_newinfo pni; 345 struct puffs_cn pcn; 346 347 if (pops->puffs_node_mknod == NULL) { 348 error = 0; 349 break; 350 } 351 352 pcn.pcn_pkcnp = &auxt->pvnr_cn; 353 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred); 354 355 memset(&pni, 0, sizeof(pni)); 356 pni.pni_cookie = &auxt->pvnr_newnode; 357 358 if (buildpath) { 359 error = puffs_path_pcnbuild(pu, &pcn, opcookie); 360 if (error) 361 break; 362 } 363 364 error = pops->puffs_node_mknod(pu, 365 opcookie, &pni, &pcn, &auxt->pvnr_va); 366 367 if (buildpath) { 368 if (error) { 369 pu->pu_pathfree(pu, &pcn.pcn_po_full); 370 } else { 371 struct puffs_node *pn; 372 373 pn = PU_CMAP(pu, auxt->pvnr_newnode); 374 pn->pn_po = pcn.pcn_po_full; 375 } 376 } 377 378 break; 379 } 380 381 case PUFFS_VN_OPEN: 382 { 383 struct puffs_vnmsg_open *auxt = auxbuf; 384 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred); 385 386 if (pops->puffs_node_open == NULL) { 387 error = 0; 388 break; 389 } 390 391 error = pops->puffs_node_open(pu, 392 opcookie, auxt->pvnr_mode, pcr); 393 break; 394 } 395 396 case PUFFS_VN_CLOSE: 397 { 398 struct puffs_vnmsg_close *auxt = auxbuf; 399 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred); 400 401 if (pops->puffs_node_close == NULL) { 402 error = 0; 403 break; 404 } 405 406 error = pops->puffs_node_close(pu, 407 opcookie, auxt->pvnr_fflag, pcr); 408 break; 409 } 410 411 case PUFFS_VN_ACCESS: 412 { 413 struct puffs_vnmsg_access *auxt = auxbuf; 414 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred); 415 416 if (pops->puffs_node_access == NULL) { 417 error = 0; 418 break; 419 } 420 421 error = pops->puffs_node_access(pu, 422 opcookie, auxt->pvnr_mode, pcr); 423 break; 424 } 425 426 case PUFFS_VN_GETATTR: 427 { 428 struct puffs_vnmsg_getattr *auxt = auxbuf; 429 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred); 430 431 if (pops->puffs_node_getattr == NULL) { 432 error = EOPNOTSUPP; 433 break; 434 } 435 436 error = pops->puffs_node_getattr(pu, 437 opcookie, &auxt->pvnr_va, pcr); 438 break; 439 } 440 441 case PUFFS_VN_SETATTR: 442 { 443 struct puffs_vnmsg_setattr *auxt = auxbuf; 444 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred); 445 446 if (pops->puffs_node_setattr == NULL) { 447 error = EOPNOTSUPP; 448 break; 449 } 450 451 error = pops->puffs_node_setattr(pu, 452 opcookie, &auxt->pvnr_va, pcr); 453 break; 454 } 455 456 case PUFFS_VN_MMAP: 457 { 458 struct puffs_vnmsg_mmap *auxt = auxbuf; 459 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred); 460 461 if (pops->puffs_node_mmap == NULL) { 462 error = 0; 463 break; 464 } 465 466 error = pops->puffs_node_mmap(pu, 467 opcookie, auxt->pvnr_prot, pcr); 468 break; 469 } 470 471 case PUFFS_VN_FSYNC: 472 { 473 struct puffs_vnmsg_fsync *auxt = auxbuf; 474 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred); 475 476 if (pops->puffs_node_fsync == NULL) { 477 error = 0; 478 break; 479 } 480 481 error = pops->puffs_node_fsync(pu, opcookie, pcr, 482 auxt->pvnr_flags, auxt->pvnr_offlo, 483 auxt->pvnr_offhi); 484 break; 485 } 486 487 case PUFFS_VN_SEEK: 488 { 489 struct puffs_vnmsg_seek *auxt = auxbuf; 490 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred); 491 492 if (pops->puffs_node_seek == NULL) { 493 error = 0; 494 break; 495 } 496 497 error = pops->puffs_node_seek(pu, 498 opcookie, auxt->pvnr_oldoff, 499 auxt->pvnr_newoff, pcr); 500 break; 501 } 502 503 case PUFFS_VN_REMOVE: 504 { 505 struct puffs_vnmsg_remove *auxt = auxbuf; 506 struct puffs_cn pcn; 507 if (pops->puffs_node_remove == NULL) { 508 error = 0; 509 break; 510 } 511 512 pcn.pcn_pkcnp = &auxt->pvnr_cn; 513 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred); 514 515 error = pops->puffs_node_remove(pu, 516 opcookie, auxt->pvnr_cookie_targ, &pcn); 517 break; 518 } 519 520 case PUFFS_VN_LINK: 521 { 522 struct puffs_vnmsg_link *auxt = auxbuf; 523 struct puffs_cn pcn; 524 if (pops->puffs_node_link == NULL) { 525 error = 0; 526 break; 527 } 528 529 pcn.pcn_pkcnp = &auxt->pvnr_cn; 530 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred); 531 532 if (buildpath) { 533 error = puffs_path_pcnbuild(pu, &pcn, opcookie); 534 if (error) 535 break; 536 } 537 538 error = pops->puffs_node_link(pu, 539 opcookie, auxt->pvnr_cookie_targ, &pcn); 540 if (buildpath) 541 pu->pu_pathfree(pu, &pcn.pcn_po_full); 542 543 break; 544 } 545 546 case PUFFS_VN_RENAME: 547 { 548 struct puffs_vnmsg_rename *auxt = auxbuf; 549 struct puffs_cn pcn_src, pcn_targ; 550 struct puffs_node *pn_src; 551 552 if (pops->puffs_node_rename == NULL) { 553 error = 0; 554 break; 555 } 556 557 pcn_src.pcn_pkcnp = &auxt->pvnr_cn_src; 558 PUFFS_KCREDTOCRED(pcn_src.pcn_cred, 559 &auxt->pvnr_cn_src_cred); 560 561 pcn_targ.pcn_pkcnp = &auxt->pvnr_cn_targ; 562 PUFFS_KCREDTOCRED(pcn_targ.pcn_cred, 563 &auxt->pvnr_cn_targ_cred); 564 565 if (buildpath) { 566 pn_src = auxt->pvnr_cookie_src; 567 pcn_src.pcn_po_full = pn_src->pn_po; 568 569 error = puffs_path_pcnbuild(pu, &pcn_targ, 570 auxt->pvnr_cookie_targdir); 571 if (error) 572 break; 573 } 574 575 error = pops->puffs_node_rename(pu, 576 opcookie, auxt->pvnr_cookie_src, 577 &pcn_src, auxt->pvnr_cookie_targdir, 578 auxt->pvnr_cookie_targ, &pcn_targ); 579 580 if (buildpath) { 581 if (error) { 582 pu->pu_pathfree(pu, 583 &pcn_targ.pcn_po_full); 584 } else { 585 struct puffs_pathinfo pi; 586 struct puffs_pathobj po_old; 587 588 /* handle this node */ 589 po_old = pn_src->pn_po; 590 pn_src->pn_po = pcn_targ.pcn_po_full; 591 592 if (pn_src->pn_va.va_type != VDIR) { 593 pu->pu_pathfree(pu, &po_old); 594 break; 595 } 596 597 /* handle all child nodes for DIRs */ 598 pi.pi_old = &pcn_src.pcn_po_full; 599 pi.pi_new = &pcn_targ.pcn_po_full; 600 601 PU_LOCK(); 602 if (puffs_pn_nodewalk(pu, 603 puffs_path_prefixadj, &pi) != NULL) 604 error = ENOMEM; 605 PU_UNLOCK(); 606 pu->pu_pathfree(pu, &po_old); 607 } 608 } 609 break; 610 } 611 612 case PUFFS_VN_MKDIR: 613 { 614 struct puffs_vnmsg_mkdir *auxt = auxbuf; 615 struct puffs_newinfo pni; 616 struct puffs_cn pcn; 617 618 if (pops->puffs_node_mkdir == NULL) { 619 error = 0; 620 break; 621 } 622 623 pcn.pcn_pkcnp = &auxt->pvnr_cn; 624 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred); 625 626 memset(&pni, 0, sizeof(pni)); 627 pni.pni_cookie = &auxt->pvnr_newnode; 628 629 if (buildpath) { 630 error = puffs_path_pcnbuild(pu, &pcn, opcookie); 631 if (error) 632 break; 633 } 634 635 error = pops->puffs_node_mkdir(pu, 636 opcookie, &pni, &pcn, &auxt->pvnr_va); 637 638 if (buildpath) { 639 if (error) { 640 pu->pu_pathfree(pu, &pcn.pcn_po_full); 641 } else { 642 struct puffs_node *pn; 643 644 pn = PU_CMAP(pu, auxt->pvnr_newnode); 645 pn->pn_po = pcn.pcn_po_full; 646 } 647 } 648 649 break; 650 } 651 652 case PUFFS_VN_RMDIR: 653 { 654 struct puffs_vnmsg_rmdir *auxt = auxbuf; 655 struct puffs_cn pcn; 656 if (pops->puffs_node_rmdir == NULL) { 657 error = 0; 658 break; 659 } 660 661 pcn.pcn_pkcnp = &auxt->pvnr_cn; 662 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred); 663 664 error = pops->puffs_node_rmdir(pu, 665 opcookie, auxt->pvnr_cookie_targ, &pcn); 666 break; 667 } 668 669 case PUFFS_VN_SYMLINK: 670 { 671 struct puffs_vnmsg_symlink *auxt = auxbuf; 672 struct puffs_newinfo pni; 673 struct puffs_cn pcn; 674 675 if (pops->puffs_node_symlink == NULL) { 676 error = 0; 677 break; 678 } 679 680 pcn.pcn_pkcnp = &auxt->pvnr_cn; 681 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred); 682 683 memset(&pni, 0, sizeof(pni)); 684 pni.pni_cookie = &auxt->pvnr_newnode; 685 686 if (buildpath) { 687 error = puffs_path_pcnbuild(pu, &pcn, opcookie); 688 if (error) 689 break; 690 } 691 692 error = pops->puffs_node_symlink(pu, 693 opcookie, &pni, &pcn, 694 &auxt->pvnr_va, auxt->pvnr_link); 695 696 if (buildpath) { 697 if (error) { 698 pu->pu_pathfree(pu, &pcn.pcn_po_full); 699 } else { 700 struct puffs_node *pn; 701 702 pn = PU_CMAP(pu, auxt->pvnr_newnode); 703 pn->pn_po = pcn.pcn_po_full; 704 } 705 } 706 707 break; 708 } 709 710 case PUFFS_VN_READDIR: 711 { 712 struct puffs_vnmsg_readdir *auxt = auxbuf; 713 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred); 714 struct dirent *dent; 715 off_t *cookies; 716 size_t res, origcookies; 717 718 if (pops->puffs_node_readdir == NULL) { 719 error = 0; 720 break; 721 } 722 723 if (auxt->pvnr_ncookies) { 724 /* LINTED: pvnr_data is __aligned() */ 725 cookies = (off_t *)auxt->pvnr_data; 726 origcookies = auxt->pvnr_ncookies; 727 } else { 728 cookies = NULL; 729 origcookies = 0; 730 } 731 /* LINTED: dentoff is aligned in the kernel */ 732 dent = (struct dirent *) 733 (auxt->pvnr_data + auxt->pvnr_dentoff); 734 735 res = auxt->pvnr_resid; 736 error = pops->puffs_node_readdir(pu, 737 opcookie, dent, &auxt->pvnr_offset, 738 &auxt->pvnr_resid, pcr, &auxt->pvnr_eofflag, 739 cookies, &auxt->pvnr_ncookies); 740 741 /* much easier to track non-working NFS */ 742 assert(auxt->pvnr_ncookies <= origcookies); 743 744 /* need to move a bit more */ 745 preq->preq_buflen = sizeof(struct puffs_vnmsg_readdir) 746 + auxt->pvnr_dentoff + (res - auxt->pvnr_resid); 747 break; 748 } 749 750 case PUFFS_VN_READLINK: 751 { 752 struct puffs_vnmsg_readlink *auxt = auxbuf; 753 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred); 754 755 if (pops->puffs_node_readlink == NULL) { 756 error = EOPNOTSUPP; 757 break; 758 } 759 760 /*LINTED*/ 761 error = pops->puffs_node_readlink(pu, opcookie, pcr, 762 auxt->pvnr_link, &auxt->pvnr_linklen); 763 break; 764 } 765 766 case PUFFS_VN_RECLAIM: 767 { 768 769 if (pops->puffs_node_reclaim == NULL) { 770 error = 0; 771 break; 772 } 773 774 error = pops->puffs_node_reclaim(pu, opcookie); 775 break; 776 } 777 778 case PUFFS_VN_INACTIVE: 779 { 780 781 if (pops->puffs_node_inactive == NULL) { 782 error = EOPNOTSUPP; 783 break; 784 } 785 786 error = pops->puffs_node_inactive(pu, opcookie); 787 break; 788 } 789 790 case PUFFS_VN_PATHCONF: 791 { 792 struct puffs_vnmsg_pathconf *auxt = auxbuf; 793 if (pops->puffs_node_pathconf == NULL) { 794 error = 0; 795 break; 796 } 797 798 error = pops->puffs_node_pathconf(pu, 799 opcookie, auxt->pvnr_name, 800 &auxt->pvnr_retval); 801 break; 802 } 803 804 case PUFFS_VN_ADVLOCK: 805 { 806 struct puffs_vnmsg_advlock *auxt = auxbuf; 807 if (pops->puffs_node_advlock == NULL) { 808 error = 0; 809 break; 810 } 811 812 error = pops->puffs_node_advlock(pu, 813 opcookie, auxt->pvnr_id, auxt->pvnr_op, 814 &auxt->pvnr_fl, auxt->pvnr_flags); 815 break; 816 } 817 818 case PUFFS_VN_PRINT: 819 { 820 if (pops->puffs_node_print == NULL) { 821 error = 0; 822 break; 823 } 824 825 error = pops->puffs_node_print(pu, 826 opcookie); 827 break; 828 } 829 830 case PUFFS_VN_ABORTOP: 831 { 832 struct puffs_vnmsg_abortop *auxt = auxbuf; 833 struct puffs_cn pcn; 834 835 if (pops->puffs_node_abortop == NULL) { 836 error = 0; 837 break; 838 } 839 840 pcn.pcn_pkcnp = &auxt->pvnr_cn; 841 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred); 842 843 error = pops->puffs_node_abortop(pu, opcookie, &pcn); 844 845 break; 846 } 847 848 case PUFFS_VN_READ: 849 { 850 struct puffs_vnmsg_read *auxt = auxbuf; 851 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred); 852 size_t res; 853 854 if (pops->puffs_node_read == NULL) { 855 error = EIO; 856 break; 857 } 858 859 res = auxt->pvnr_resid; 860 error = pops->puffs_node_read(pu, 861 opcookie, auxt->pvnr_data, 862 auxt->pvnr_offset, &auxt->pvnr_resid, 863 pcr, auxt->pvnr_ioflag); 864 865 /* need to move a bit more */ 866 preq->preq_buflen = sizeof(struct puffs_vnmsg_read) 867 + (res - auxt->pvnr_resid); 868 break; 869 } 870 871 case PUFFS_VN_WRITE: 872 { 873 struct puffs_vnmsg_write *auxt = auxbuf; 874 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred); 875 876 if (pops->puffs_node_write == NULL) { 877 error = EIO; 878 break; 879 } 880 881 error = pops->puffs_node_write(pu, 882 opcookie, auxt->pvnr_data, 883 auxt->pvnr_offset, &auxt->pvnr_resid, 884 pcr, auxt->pvnr_ioflag); 885 886 /* don't need to move data back to the kernel */ 887 preq->preq_buflen = sizeof(struct puffs_vnmsg_write); 888 break; 889 } 890 891 case PUFFS_VN_POLL: 892 { 893 struct puffs_vnmsg_poll *auxt = auxbuf; 894 895 if (pops->puffs_node_poll == NULL) { 896 error = 0; 897 898 /* emulate genfs_poll() */ 899 auxt->pvnr_events &= (POLLIN | POLLOUT 900 | POLLRDNORM | POLLWRNORM); 901 902 break; 903 } 904 905 error = pops->puffs_node_poll(pu, 906 opcookie, &auxt->pvnr_events); 907 break; 908 } 909 910 case PUFFS_VN_GETEXTATTR: 911 { 912 struct puffs_vnmsg_getextattr *auxt = auxbuf; 913 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred); 914 size_t res, *resp, *sizep; 915 uint8_t *data; 916 917 if (pops->puffs_node_getextattr == NULL) { 918 error = EOPNOTSUPP; 919 break; 920 } 921 922 if (auxt->pvnr_datasize) 923 sizep = &auxt->pvnr_datasize; 924 else 925 sizep = NULL; 926 927 res = auxt->pvnr_resid; 928 if (res > 0) { 929 data = auxt->pvnr_data; 930 resp = &auxt->pvnr_resid; 931 } else { 932 data = NULL; 933 resp = NULL; 934 } 935 936 error = pops->puffs_node_getextattr(pu, 937 opcookie, auxt->pvnr_attrnamespace, 938 auxt->pvnr_attrname, sizep, data, resp, pcr); 939 940 /* need to move a bit more? */ 941 preq->preq_buflen = 942 sizeof(struct puffs_vnmsg_getextattr) 943 + (res - auxt->pvnr_resid); 944 break; 945 } 946 947 case PUFFS_VN_SETEXTATTR: 948 { 949 struct puffs_vnmsg_setextattr *auxt = auxbuf; 950 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred); 951 size_t *resp; 952 uint8_t *data; 953 954 if (pops->puffs_node_setextattr == NULL) { 955 error = EOPNOTSUPP; 956 break; 957 } 958 959 if (auxt->pvnr_resid > 0) { 960 data = auxt->pvnr_data; 961 resp = &auxt->pvnr_resid; 962 } else { 963 data = NULL; 964 resp = NULL; 965 } 966 967 error = pops->puffs_node_setextattr(pu, 968 opcookie, auxt->pvnr_attrnamespace, 969 auxt->pvnr_attrname, data, resp, pcr); 970 break; 971 } 972 973 case PUFFS_VN_LISTEXTATTR: 974 { 975 struct puffs_vnmsg_listextattr *auxt = auxbuf; 976 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred); 977 size_t res, *resp, *sizep; 978 uint8_t *data; 979 980 if (pops->puffs_node_listextattr == NULL) { 981 error = EOPNOTSUPP; 982 break; 983 } 984 985 if (auxt->pvnr_datasize) 986 sizep = &auxt->pvnr_datasize; 987 else 988 sizep = NULL; 989 990 res = auxt->pvnr_resid; 991 if (res > 0) { 992 data = auxt->pvnr_data; 993 resp = &auxt->pvnr_resid; 994 } else { 995 data = NULL; 996 resp = NULL; 997 } 998 999 res = auxt->pvnr_resid; 1000 error = pops->puffs_node_listextattr(pu, 1001 opcookie, auxt->pvnr_attrnamespace, 1002 sizep, data, resp, pcr); 1003 1004 /* need to move a bit more? */ 1005 preq->preq_buflen = 1006 sizeof(struct puffs_vnmsg_listextattr) 1007 + (res - auxt->pvnr_resid); 1008 break; 1009 } 1010 1011 case PUFFS_VN_DELETEEXTATTR: 1012 { 1013 struct puffs_vnmsg_deleteextattr *auxt = auxbuf; 1014 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred); 1015 1016 if (pops->puffs_node_deleteextattr == NULL) { 1017 error = EOPNOTSUPP; 1018 break; 1019 } 1020 1021 error = pops->puffs_node_deleteextattr(pu, 1022 opcookie, auxt->pvnr_attrnamespace, 1023 auxt->pvnr_attrname, pcr); 1024 break; 1025 } 1026 1027 default: 1028 printf("inval op %d\n", preq->preq_optype); 1029 error = EINVAL; 1030 break; 1031 } 1032 1033 #if 0 1034 /* not issued by kernel currently */ 1035 } else if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_CACHE) { 1036 struct puffs_cacheinfo *pci = (void *)preq; 1037 1038 if (pu->pu_ops.puffs_cache_write) { 1039 pu->pu_ops.puffs_cache_write(pu, preq->preq_cookie, 1040 pci->pcache_nruns, pci->pcache_runs); 1041 } 1042 error = 0; 1043 #endif 1044 1045 } else if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_ERROR) { 1046 struct puffs_error *perr = (void *)preq; 1047 1048 pu->pu_errnotify(pu, preq->preq_optype, 1049 perr->perr_error, perr->perr_str, preq->preq_cookie); 1050 error = 0; 1051 } else { 1052 /* 1053 * I guess the kernel sees this one coming also 1054 */ 1055 error = EINVAL; 1056 } 1057 1058 out: 1059 preq->preq_rv = error; 1060 1061 if (pu->pu_oppost) 1062 pu->pu_oppost(pu); 1063 1064 pcc->pcc_flags |= PCC_DONE; 1065 } 1066