puffs.c revision 1.15
1/* $NetBSD: puffs.c,v 1.15 2006/12/07 16:59:14 pooka Exp $ */ 2 3/* 4 * Copyright (c) 2005, 2006 Antti Kantee. All Rights Reserved. 5 * 6 * Development of this software was supported by the 7 * Google Summer of Code program and the Ulla Tuominen Foundation. 8 * The Google SoC project was mentored by Bill Studenmund. 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 * 3. The name of the company nor the name of the author may be used to 19 * endorse or promote products derived from this software without specific 20 * prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 23 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35#include <sys/cdefs.h> 36#if !defined(lint) 37__RCSID("$NetBSD: puffs.c,v 1.15 2006/12/07 16:59:14 pooka Exp $"); 38#endif /* !lint */ 39 40#include <sys/param.h> 41#include <sys/mount.h> 42 43#include <assert.h> 44#include <err.h> 45#include <errno.h> 46#include <fcntl.h> 47#include <puffs.h> 48#include <puffsdump.h> 49#include <stdio.h> 50#include <stdlib.h> 51#include <string.h> 52#include <syslog.h> 53#include <unistd.h> 54 55static int puffcall(struct puffs_usermount *, struct puffs_req *, size_t *); 56 57#define FILLOP(lower, upper) \ 58do { \ 59 if (pops->puffs_node_##lower) \ 60 opmask[PUFFS_VN_##upper] = 1; \ 61} while (/*CONSTCOND*/0) 62static void 63fillvnopmask(struct puffs_ops *pops, uint8_t *opmask) 64{ 65 66 memset(opmask, 0, PUFFS_VN_MAX); 67 68 FILLOP(create, CREATE); 69 FILLOP(mknod, MKNOD); 70 FILLOP(open, OPEN); 71 FILLOP(close, CLOSE); 72 FILLOP(access, ACCESS); 73 FILLOP(getattr, GETATTR); 74 FILLOP(setattr, SETATTR); 75 FILLOP(poll, POLL); /* XXX: not ready in kernel */ 76 FILLOP(revoke, REVOKE); 77 FILLOP(mmap, MMAP); /* XXX: not called currently */ 78 FILLOP(fsync, FSYNC); 79 FILLOP(seek, SEEK); 80 FILLOP(remove, REMOVE); 81 FILLOP(link, LINK); 82 FILLOP(rename, RENAME); 83 FILLOP(mkdir, MKDIR); 84 FILLOP(rmdir, RMDIR); 85 FILLOP(symlink, SYMLINK); 86 FILLOP(readdir, READDIR); 87 FILLOP(readlink, READLINK); 88 FILLOP(reclaim, RECLAIM); 89 FILLOP(inactive, INACTIVE); 90 FILLOP(print, PRINT); 91 FILLOP(read, READ); 92 FILLOP(write, WRITE); 93 94 /* XXX: not implemented in the kernel */ 95 FILLOP(getextattr, GETEXTATTR); 96 FILLOP(setextattr, SETEXTATTR); 97 FILLOP(listextattr, LISTEXTATTR); 98 99 /* XXX */ 100 FILLOP(ioctl1, IOCTL); 101 FILLOP(fcntl1, FCNTL); 102} 103#undef FILLOP 104 105struct puffs_usermount * 106puffs_mount(struct puffs_ops *pops, const char *dir, int mntflags, 107 const char *puffsname, uint32_t pflags, size_t maxreqlen) 108{ 109 struct puffs_startreq sreq; 110 struct puffs_args pargs; 111 struct puffs_usermount *pu; 112 int fd = 0, rv; 113 114 if (pops->puffs_fs_mount == NULL) { 115 errno = EINVAL; 116 return NULL; 117 } 118 119 fd = open("/dev/puffs", O_RDONLY); 120 if (fd == -1) 121 return NULL; 122 if (fd <= 2) 123 warnx("puffs_mount: device fd %d (<= 2), sure this is " 124 "what you want?", fd); 125 126 pargs.pa_vers = 0; /* XXX: for now */ 127 pargs.pa_flags = PUFFS_FLAG_KERN(pflags); 128 pargs.pa_fd = fd; 129 pargs.pa_maxreqlen = maxreqlen; 130 fillvnopmask(pops, pargs.pa_vnopmask); 131 (void)strlcpy(pargs.pa_name, puffsname, sizeof(pargs.pa_name)); 132 133 pu = malloc(sizeof(struct puffs_usermount)); 134 if (!pu) 135 return NULL; 136 137 pu->pu_flags = pflags; 138 pu->pu_ops = *pops; 139 pu->pu_fd = fd; 140 if ((pu->pu_rootpath = strdup(dir)) == NULL) 141 goto failfree; 142 LIST_INIT(&pu->pu_pnodelst); 143 144 if (mount(MOUNT_PUFFS, dir, mntflags, &pargs) == -1) 145 goto failfree; 146 pu->pu_maxreqlen = pargs.pa_maxreqlen; 147 148 if ((rv = pops->puffs_fs_mount(pu, &sreq.psr_cookie)) != 0) { 149 errno = rv; 150 goto failfree; 151 } 152 153 if ((rv = pops->puffs_fs_statvfs(pu, &sreq.psr_sb, 0)) != 0) { 154 errno = rv; 155 goto failfree; 156 } 157 158 /* tell kernel we're flying */ 159 if (ioctl(pu->pu_fd, PUFFSSTARTOP, &sreq) == -1) 160 goto failfree; 161 162 return pu; 163 164 failfree: 165 /* can't unmount() from here for obvious reasons */ 166 if (fd) 167 close(fd); 168 free(pu); 169 return NULL; 170} 171 172int 173puffs_mainloop(struct puffs_usermount *pu, int flags) 174{ 175 uint8_t *buf; 176 int rv; 177 178 buf = malloc(pu->pu_maxreqlen); 179 if (!buf) 180 return -1; 181 182 if ((flags & PUFFSLOOP_NODAEMON) == 0) 183 if (daemon(0, 0) == -1) 184 return -1; 185 186 for (;;) 187 if ((rv = puffs_oneop(pu, buf, pu->pu_maxreqlen)) != 0) 188 return rv; 189} 190 191enum {PUFFCALL_ANSWER, PUFFCALL_IGNORE, PUFFCALL_UNMOUNT}; 192int 193puffs_oneop(struct puffs_usermount *pu, uint8_t *buf, size_t buflen) 194{ 195 struct puffs_reqh_get phg; 196 struct puffs_reqh_put php; 197 struct puffs_req *preq; 198 uint64_t *resp_idp; 199 void **resp_bufp; 200 size_t handler_blen, *resp_blenp; 201 int rv, unmounting = 0; 202 203 /* setup fetch */ 204 phg.phg_buf = buf; 205 phg.phg_buflen = buflen; 206 phg.phg_nops = 0; 207 208 /* setup reply essentials */ 209 php.php_nops = 0; 210 resp_bufp = &php.php_buf; 211 resp_blenp = &php.php_buflen; 212 resp_idp = &php.php_id; 213 214 /* get op from kernel */ 215 if (ioctl(pu->pu_fd, PUFFSGETOP, &phg) == -1) 216 return -1; 217 preq = phg.phg_buf; 218 219 while (phg.phg_nops-- && unmounting == 0) { 220 /* deal with it */ 221 handler_blen = preq->preq_buflen; 222 rv = puffcall(pu, preq, &handler_blen); 223 224 /* check if we need to store this reply */ 225 switch (rv) { 226 case PUFFCALL_UNMOUNT: 227 unmounting = 1; 228 /* FALLTHROUGH */ 229 case PUFFCALL_ANSWER: 230 php.php_nops++; 231 232 /* store data */ 233 *resp_bufp = preq; 234 *resp_blenp = handler_blen; 235 *resp_idp = preq->preq_id; 236 237 /* and roll pointers forward */ 238 resp_bufp = &preq->preq_nextbuf; 239 resp_blenp = &preq->preq_buflen; 240 resp_idp = &preq->preq_id; 241 242 break; 243 case PUFFCALL_IGNORE: 244 break; 245 246 default: 247 return -1; 248 } 249 250 /* roll buffer forward */ 251 /* LINTED */ 252 preq = (struct puffs_req *)((uint8_t *)preq+preq->preq_buflen); 253 } 254 255 if (php.php_nops) 256 if (ioctl(pu->pu_fd, PUFFSPUTOP, &php) == -1) 257 return -1; 258 259 return 0; 260} 261 262int 263puffs_getselectable(struct puffs_usermount *pu) 264{ 265 266 return pu->pu_fd; 267} 268 269int 270puffs_setblockingmode(struct puffs_usermount *pu, int mode) 271{ 272 int x; 273 274 x = mode; 275 return ioctl(pu->pu_fd, FIONBIO, &x); 276} 277 278static int 279puffcall(struct puffs_usermount *pu, struct puffs_req *preq, size_t *blenp) 280{ 281 struct puffs_ops *pops = &pu->pu_ops; 282 struct puffs_sizeop pop; 283 void *auxbuf; 284 int error, rv; 285 286 if (PUFFSOP_WANTREPLY(preq->preq_opclass)) 287 rv = PUFFCALL_ANSWER; 288 else 289 rv = PUFFCALL_IGNORE; 290 auxbuf = preq; 291 292 if (pu->pu_flags & PUFFS_FLAG_OPDUMP) 293 puffsdump_req(preq); 294 295 *blenp = 0; /* default: "let kernel decide" */ 296 297 if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VFS) { 298 switch (preq->preq_optype) { 299 case PUFFS_VFS_UNMOUNT: 300 { 301 struct puffs_vfsreq_unmount *auxt = auxbuf; 302 303 error = pops->puffs_fs_unmount(pu, 304 auxt->pvfsr_flags, auxt->pvfsr_pid); 305 rv = PUFFCALL_UNMOUNT; 306 break; 307 } 308 case PUFFS_VFS_STATVFS: 309 { 310 struct puffs_vfsreq_statvfs *auxt = auxbuf; 311 312 error = pops->puffs_fs_statvfs(pu, 313 &auxt->pvfsr_sb, auxt->pvfsr_pid); 314 break; 315 } 316 case PUFFS_VFS_SYNC: 317 { 318 struct puffs_vfsreq_sync *auxt = auxbuf; 319 320 error = pops->puffs_fs_sync(pu, 321 auxt->pvfsr_waitfor, &auxt->pvfsr_cred, 322 auxt->pvfsr_pid); 323 break; 324 } 325 default: 326 /* 327 * I guess the kernel sees this one coming 328 */ 329 error = EINVAL; 330 break; 331 } 332 333 /* XXX: audit return values */ 334 /* XXX: sync with kernel */ 335 } else if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VN) { 336 switch (preq->preq_optype) { 337 case PUFFS_VN_LOOKUP: 338 { 339 struct puffs_vnreq_lookup *auxt = auxbuf; 340 341 /* lookup *must* be present */ 342 error = pops->puffs_node_lookup(pu, preq->preq_cookie, 343 &auxt->pvnr_newnode, &auxt->pvnr_vtype, 344 &auxt->pvnr_size, &auxt->pvnr_rdev, 345 &auxt->pvnr_cn); 346 break; 347 } 348 349 case PUFFS_VN_CREATE: 350 { 351 struct puffs_vnreq_create *auxt = auxbuf; 352 if (pops->puffs_node_create == NULL) { 353 error = 0; 354 break; 355 } 356 357 error = pops->puffs_node_create(pu, 358 preq->preq_cookie, &auxt->pvnr_newnode, 359 &auxt->pvnr_cn, &auxt->pvnr_va); 360 break; 361 } 362 363 case PUFFS_VN_MKNOD: 364 { 365 struct puffs_vnreq_mknod *auxt = auxbuf; 366 if (pops->puffs_node_mknod == NULL) { 367 error = 0; 368 break; 369 } 370 371 error = pops->puffs_node_mknod(pu, 372 preq->preq_cookie, &auxt->pvnr_newnode, 373 &auxt->pvnr_cn, &auxt->pvnr_va); 374 break; 375 } 376 377 case PUFFS_VN_OPEN: 378 { 379 struct puffs_vnreq_open *auxt = auxbuf; 380 if (pops->puffs_node_open == NULL) { 381 error = 0; 382 break; 383 } 384 385 error = pops->puffs_node_open(pu, 386 preq->preq_cookie, auxt->pvnr_mode, 387 &auxt->pvnr_cred, auxt->pvnr_pid); 388 break; 389 } 390 391 case PUFFS_VN_CLOSE: 392 { 393 struct puffs_vnreq_close *auxt = auxbuf; 394 if (pops->puffs_node_close == NULL) { 395 error = 0; 396 break; 397 } 398 399 error = pops->puffs_node_close(pu, 400 preq->preq_cookie, auxt->pvnr_fflag, 401 &auxt->pvnr_cred, auxt->pvnr_pid); 402 break; 403 } 404 405 case PUFFS_VN_ACCESS: 406 { 407 struct puffs_vnreq_access *auxt = auxbuf; 408 if (pops->puffs_node_access == NULL) { 409 error = 0; 410 break; 411 } 412 413 error = pops->puffs_node_access(pu, 414 preq->preq_cookie, auxt->pvnr_mode, 415 &auxt->pvnr_cred, auxt->pvnr_pid); 416 break; 417 } 418 419 case PUFFS_VN_GETATTR: 420 { 421 struct puffs_vnreq_getattr *auxt = auxbuf; 422 if (pops->puffs_node_getattr == NULL) { 423 error = EOPNOTSUPP; 424 break; 425 } 426 427 error = pops->puffs_node_getattr(pu, 428 preq->preq_cookie, &auxt->pvnr_va, 429 &auxt->pvnr_cred, auxt->pvnr_pid); 430 break; 431 } 432 433 case PUFFS_VN_SETATTR: 434 { 435 struct puffs_vnreq_setattr *auxt = auxbuf; 436 if (pops->puffs_node_setattr == NULL) { 437 error = EOPNOTSUPP; 438 break; 439 } 440 441 error = pops->puffs_node_setattr(pu, 442 preq->preq_cookie, &auxt->pvnr_va, 443 &auxt->pvnr_cred, auxt->pvnr_pid); 444 break; 445 } 446 447 case PUFFS_VN_MMAP: 448 { 449 struct puffs_vnreq_mmap *auxt = auxbuf; 450 if (pops->puffs_node_mmap == NULL) { 451 error = 0; 452 break; 453 } 454 455 error = pops->puffs_node_mmap(pu, 456 preq->preq_cookie, auxt->pvnr_fflags, 457 &auxt->pvnr_cred, auxt->pvnr_pid); 458 break; 459 } 460 461 case PUFFS_VN_REVOKE: 462 { 463 struct puffs_vnreq_revoke *auxt = auxbuf; 464 if (pops->puffs_node_revoke == NULL) { 465 error = 0; 466 break; 467 } 468 469 error = pops->puffs_node_revoke(pu, 470 preq->preq_cookie, auxt->pvnr_flags); 471 break; 472 } 473 474 case PUFFS_VN_FSYNC: 475 { 476 struct puffs_vnreq_fsync *auxt = auxbuf; 477 if (pops->puffs_node_fsync == NULL) { 478 error = 0; 479 break; 480 } 481 482 error = pops->puffs_node_fsync(pu, 483 preq->preq_cookie, &auxt->pvnr_cred, 484 auxt->pvnr_flags, auxt->pvnr_offlo, 485 auxt->pvnr_offhi, auxt->pvnr_pid); 486 break; 487 } 488 489 case PUFFS_VN_SEEK: 490 { 491 struct puffs_vnreq_seek *auxt = auxbuf; 492 if (pops->puffs_node_seek == NULL) { 493 error = 0; 494 break; 495 } 496 497 error = pops->puffs_node_seek(pu, 498 preq->preq_cookie, auxt->pvnr_oldoff, 499 auxt->pvnr_newoff, &auxt->pvnr_cred); 500 break; 501 } 502 503 case PUFFS_VN_REMOVE: 504 { 505 struct puffs_vnreq_remove *auxt = auxbuf; 506 if (pops->puffs_node_remove == NULL) { 507 error = 0; 508 break; 509 } 510 511 error = pops->puffs_node_remove(pu, 512 preq->preq_cookie, auxt->pvnr_cookie_targ, 513 &auxt->pvnr_cn); 514 break; 515 } 516 517 case PUFFS_VN_LINK: 518 { 519 struct puffs_vnreq_link *auxt = auxbuf; 520 if (pops->puffs_node_link == NULL) { 521 error = 0; 522 break; 523 } 524 525 error = pops->puffs_node_link(pu, 526 preq->preq_cookie, auxt->pvnr_cookie_targ, 527 &auxt->pvnr_cn); 528 break; 529 } 530 531 case PUFFS_VN_RENAME: 532 { 533 struct puffs_vnreq_rename *auxt = auxbuf; 534 if (pops->puffs_node_rename == NULL) { 535 error = 0; 536 break; 537 } 538 539 error = pops->puffs_node_rename(pu, 540 preq->preq_cookie, auxt->pvnr_cookie_src, 541 &auxt->pvnr_cn_src, auxt->pvnr_cookie_targdir, 542 auxt->pvnr_cookie_targ, &auxt->pvnr_cn_targ); 543 break; 544 } 545 546 case PUFFS_VN_MKDIR: 547 { 548 struct puffs_vnreq_mkdir *auxt = auxbuf; 549 if (pops->puffs_node_mkdir == NULL) { 550 error = 0; 551 break; 552 } 553 554 error = pops->puffs_node_mkdir(pu, 555 preq->preq_cookie, &auxt->pvnr_newnode, 556 &auxt->pvnr_cn, &auxt->pvnr_va); 557 break; 558 } 559 560 case PUFFS_VN_RMDIR: 561 { 562 struct puffs_vnreq_rmdir *auxt = auxbuf; 563 if (pops->puffs_node_rmdir == NULL) { 564 error = 0; 565 break; 566 } 567 568 error = pops->puffs_node_rmdir(pu, 569 preq->preq_cookie, auxt->pvnr_cookie_targ, 570 &auxt->pvnr_cn); 571 break; 572 } 573 574 case PUFFS_VN_SYMLINK: 575 { 576 struct puffs_vnreq_symlink *auxt = auxbuf; 577 if (pops->puffs_node_symlink == NULL) { 578 error = 0; 579 break; 580 } 581 582 error = pops->puffs_node_symlink(pu, 583 preq->preq_cookie, &auxt->pvnr_newnode, 584 &auxt->pvnr_cn, &auxt->pvnr_va, auxt->pvnr_link); 585 break; 586 } 587 588 case PUFFS_VN_READDIR: 589 { 590 struct puffs_vnreq_readdir *auxt = auxbuf; 591 size_t res; 592 593 if (pops->puffs_node_readdir == NULL) { 594 error = 0; 595 break; 596 } 597 598 res = auxt->pvnr_resid; 599 error = pops->puffs_node_readdir(pu, 600 preq->preq_cookie, auxt->pvnr_dent, 601 &auxt->pvnr_cred, &auxt->pvnr_offset, 602 &auxt->pvnr_resid); 603 604 /* need to move a bit more */ 605 *blenp = sizeof(struct puffs_vnreq_readdir) 606 + (res - auxt->pvnr_resid); 607 break; 608 } 609 610 case PUFFS_VN_READLINK: 611 { 612 struct puffs_vnreq_readlink *auxt = auxbuf; 613 if (pops->puffs_node_readlink == NULL) { 614 error = EOPNOTSUPP; 615 break; 616 } 617 618 error = pops->puffs_node_readlink(pu, 619 preq->preq_cookie, &auxt->pvnr_cred, 620 auxt->pvnr_link, &auxt->pvnr_linklen); 621 break; 622 } 623 624 case PUFFS_VN_RECLAIM: 625 { 626 struct puffs_vnreq_reclaim *auxt = auxbuf; 627 if (pops->puffs_node_reclaim == NULL) { 628 error = 0; 629 break; 630 } 631 632 error = pops->puffs_node_reclaim(pu, 633 preq->preq_cookie, auxt->pvnr_pid); 634 break; 635 } 636 637 case PUFFS_VN_INACTIVE: 638 { 639 struct puffs_vnreq_inactive *auxt = auxbuf; 640 if (pops->puffs_node_inactive == NULL) { 641 error = EOPNOTSUPP; 642 break; 643 } 644 645 error = pops->puffs_node_inactive(pu, 646 preq->preq_cookie, auxt->pvnr_pid, 647 &auxt->pvnr_backendrefs); 648 break; 649 } 650 651 case PUFFS_VN_PATHCONF: 652 { 653 struct puffs_vnreq_pathconf *auxt = auxbuf; 654 if (pops->puffs_node_pathconf == NULL) { 655 error = 0; 656 break; 657 } 658 659 error = pops->puffs_node_pathconf(pu, 660 preq->preq_cookie, auxt->pvnr_name, 661 &auxt->pvnr_retval); 662 break; 663 } 664 665 case PUFFS_VN_ADVLOCK: 666 { 667 struct puffs_vnreq_advlock *auxt = auxbuf; 668 if (pops->puffs_node_advlock == NULL) { 669 error = 0; 670 break; 671 } 672 673 error = pops->puffs_node_advlock(pu, 674 preq->preq_cookie, auxt->pvnr_id, auxt->pvnr_op, 675 &auxt->pvnr_fl, auxt->pvnr_flags); 676 break; 677 } 678 679 case PUFFS_VN_PRINT: 680 { 681 if (pops->puffs_node_print == NULL) { 682 error = 0; 683 break; 684 } 685 686 error = pops->puffs_node_print(pu, 687 preq->preq_cookie); 688 break; 689 } 690 691 case PUFFS_VN_READ: 692 { 693 struct puffs_vnreq_read *auxt = auxbuf; 694 size_t res; 695 696 if (pops->puffs_node_read == NULL) { 697 error = EIO; 698 break; 699 } 700 701 res = auxt->pvnr_resid; 702 error = pops->puffs_node_read(pu, 703 preq->preq_cookie, auxt->pvnr_data, 704 auxt->pvnr_offset, &auxt->pvnr_resid, 705 &auxt->pvnr_cred, auxt->pvnr_ioflag); 706 707 /* need to move a bit more */ 708 *blenp = sizeof(struct puffs_vnreq_read) 709 + (res - auxt->pvnr_resid); 710 break; 711 } 712 713 case PUFFS_VN_WRITE: 714 { 715 struct puffs_vnreq_write *auxt = auxbuf; 716 717 if (pops->puffs_node_write == NULL) { 718 error = EIO; 719 break; 720 } 721 722 error = pops->puffs_node_write(pu, 723 preq->preq_cookie, auxt->pvnr_data, 724 auxt->pvnr_offset, &auxt->pvnr_resid, 725 &auxt->pvnr_cred, auxt->pvnr_ioflag); 726 727 /* don't need to move data back to the kernel */ 728 *blenp = sizeof(struct puffs_vnreq_write); 729 break; 730 } 731 732 case PUFFS_VN_IOCTL: 733 error = pops->puffs_node_ioctl1(pu, preq->preq_cookie, 734 (struct puffs_vnreq_ioctl *)auxbuf, &pop); 735 if (error != 0) 736 break; 737 pop.pso_reqid = preq->preq_id; 738 739 /* let the kernel do it's intermediate duty */ 740 error = ioctl(pu->pu_fd, PUFFSSIZEOP, &pop); 741 /* 742 * XXX: I don't actually know what the correct 743 * thing to do in case of an error is, so I'll 744 * just ignore it for the time being. 745 */ 746 error = pops->puffs_node_ioctl2(pu, preq->preq_cookie, 747 (struct puffs_vnreq_ioctl *)auxbuf, &pop); 748 break; 749 750 case PUFFS_VN_FCNTL: 751 error = pops->puffs_node_fcntl1(pu, preq->preq_cookie, 752 (struct puffs_vnreq_fcntl *)auxbuf, &pop); 753 if (error != 0) 754 break; 755 pop.pso_reqid = preq->preq_id; 756 757 /* let the kernel do it's intermediate duty */ 758 error = ioctl(pu->pu_fd, PUFFSSIZEOP, &pop); 759 /* 760 * XXX: I don't actually know what the correct 761 * thing to do in case of an error is, so I'll 762 * just ignore it for the time being. 763 */ 764 error = pops->puffs_node_fcntl2(pu, preq->preq_cookie, 765 (struct puffs_vnreq_fcntl *)auxbuf, &pop); 766 break; 767 768 default: 769 printf("inval op %d\n", preq->preq_optype); 770 error = EINVAL; 771 break; 772 } 773 } else { 774 /* 775 * this one also 776 */ 777 error = EINVAL; 778 } 779 780 preq->preq_rv = error; 781 return rv; 782} 783 784 785#if 0 786 case PUFFS_VN_POLL: 787 { 788 struct puffs_vnreq_poll *auxt = auxbuf; 789 if (pops->puffs_node_poll == NULL) { 790 error = 0; 791 break; 792 } 793 794 error = pops->puffs_node_poll(pu, 795 preq->preq_cookie, preq-); 796 break; 797 } 798 799 case PUFFS_VN_KQFILTER: 800 { 801 struct puffs_vnreq_kqfilter *auxt = auxbuf; 802 if (pops->puffs_node_kqfilter == NULL) { 803 error = 0; 804 break; 805 } 806 807 error = pops->puffs_node_kqfilter(pu, 808 preq->preq_cookie, ); 809 break; 810 } 811 812 case PUFFS_VN_CLOSEEXTATTR: 813 { 814 struct puffs_vnreq_closeextattr *auxt = auxbuf; 815 if (pops->puffs_closeextattr == NULL) { 816 error = 0; 817 break; 818 } 819 820 error = pops->puffs_closeextattr(pu, 821 preq->preq_cookie, ); 822 break; 823 } 824 825 case PUFFS_VN_GETEXTATTR: 826 { 827 struct puffs_vnreq_getextattr *auxt = auxbuf; 828 if (pops->puffs_getextattr == NULL) { 829 error = 0; 830 break; 831 } 832 833 error = pops->puffs_getextattr(pu, 834 preq->preq_cookie, ); 835 break; 836 } 837 838 case PUFFS_VN_LISTEXTATTR: 839 { 840 struct puffs_vnreq_listextattr *auxt = auxbuf; 841 if (pops->puffs_listextattr == NULL) { 842 error = 0; 843 break; 844 } 845 846 error = pops->puffs_listextattr(pu, 847 preq->preq_cookie, ); 848 break; 849 } 850 851 case PUFFS_VN_OPENEXTATTR: 852 { 853 struct puffs_vnreq_openextattr *auxt = auxbuf; 854 if (pops->puffs_openextattr == NULL) { 855 error = 0; 856 break; 857 } 858 859 error = pops->puffs_openextattr(pu, 860 preq->preq_cookie, ); 861 break; 862 } 863 864 case PUFFS_VN_DELETEEXTATTR: 865 { 866 struct puffs_vnreq_deleteextattr *auxt = auxbuf; 867 if (pops->puffs_deleteextattr == NULL) { 868 error = 0; 869 break; 870 } 871 872 error = pops->puffs_deleteextattr(pu, 873 preq->preq_cookie, ); 874 break; 875 } 876 877 case PUFFS_VN_SETEXTATTR: 878 { 879 struct puffs_vnreq_setextattr *auxt = auxbuf; 880 if (pops->puffs_setextattr == NULL) { 881 error = 0; 882 break; 883 } 884 885 error = pops->puffs_setextattr(pu, 886 preq->preq_cookie, ); 887 break; 888 } 889 890#endif 891