kernel/msdosfs: Add pathconf(3) support for FILESIZEBITS.
[dragonfly.git] / lib / libpuffs / dispatcher.c
blob7242bd1881b90e13a779c1c772494440f82f4e96
1 /* $NetBSD: dispatcher.c,v 1.36 2011/07/04 08:07:30 manu Exp $ */
3 /*
4 * Copyright (c) 2006, 2007, 2008 Antti Kantee. All Rights Reserved.
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.
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.
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.
32 #include <sys/types.h>
33 #include <sys/poll.h>
35 #include <assert.h>
36 #include <errno.h>
37 #include <pthread.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <unistd.h>
42 #include "puffs.h"
43 #include "puffsdump.h"
44 #include "puffs_priv.h"
46 static void dispatch(struct puffs_cc *);
48 /* for our eyes only */
49 void
50 puffs__ml_dispatch(struct puffs_usermount *pu, struct puffs_framebuf *pb)
52 struct puffs_cc *pcc = puffs_cc_getcc(pu);
53 struct puffs_req *preq;
55 pcc->pcc_pb = pb;
56 pcc->pcc_flags |= PCC_MLCONT;
57 dispatch(pcc);
59 /* Put result to kernel sendqueue if necessary */
60 preq = puffs__framebuf_getdataptr(pcc->pcc_pb);
61 if (PUFFSOP_WANTREPLY(preq->preq_opclass)) {
62 if (pu->pu_flags & PUFFS_FLAG_OPDUMP)
63 puffsdump_rv(preq);
65 puffs_framev_enqueue_justsend(pu, pu->pu_fd,
66 pcc->pcc_pb, 0, 0);
67 } else {
68 puffs_framebuf_destroy(pcc->pcc_pb);
71 /* who needs information when you're living on borrowed time? */
72 if (pcc->pcc_flags & PCC_BORROWED) {
73 puffs_cc_yield(pcc); /* back to borrow source */
75 pcc->pcc_flags = 0;
78 /* public, but not really tested and only semi-supported */
79 int
80 puffs_dispatch_create(struct puffs_usermount *pu, struct puffs_framebuf *pb,
81 struct puffs_cc **pccp)
83 struct puffs_cc *pcc;
85 if (puffs__cc_create(pu, dispatch, &pcc) == -1)
86 return -1;
88 pcc->pcc_pb = pb;
89 *pccp = pcc;
91 return 0;
94 int
95 puffs_dispatch_exec(struct puffs_cc *pcc, struct puffs_framebuf **pbp)
97 int rv;
99 puffs_cc_continue(pcc);
101 if (pcc->pcc_flags & PCC_DONE) {
102 rv = 1;
103 *pbp = pcc->pcc_pb;
104 pcc->pcc_flags = 0;
105 puffs__cc_destroy(pcc, 0);
106 } else {
107 rv = 0;
110 return rv;
113 static void
114 dispatch(struct puffs_cc *pcc)
116 struct puffs_usermount *pu = pcc->pcc_pu;
117 struct puffs_ops *pops = &pu->pu_ops;
118 struct puffs_req *preq = puffs__framebuf_getdataptr(pcc->pcc_pb);
119 void *auxbuf; /* help with typecasting */
120 puffs_cookie_t opcookie;
121 int error = 0, buildpath;
123 /* XXX: smaller hammer, please */
124 if ((PUFFSOP_OPCLASS(preq->preq_opclass == PUFFSOP_VFS &&
125 preq->preq_optype == PUFFS_VFS_VPTOFH)) ||
126 (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VN &&
127 (preq->preq_optype == PUFFS_VN_READDIR
128 || preq->preq_optype == PUFFS_VN_READ))) {
129 if (puffs_framebuf_reserve_space(pcc->pcc_pb,
130 PUFFS_MSG_MAXSIZE) == -1)
131 error = errno;
132 preq = puffs__framebuf_getdataptr(pcc->pcc_pb);
135 auxbuf = preq;
136 opcookie = preq->preq_cookie;
138 assert((pcc->pcc_flags & PCC_DONE) == 0);
140 buildpath = pu->pu_flags & PUFFS_FLAG_BUILDPATH;
141 preq->preq_setbacks = 0;
143 if (pu->pu_flags & PUFFS_FLAG_OPDUMP)
144 puffsdump_req(preq);
146 puffs__cc_setcaller(pcc, preq->preq_pid, preq->preq_lid);
148 /* pre-operation */
149 if (pu->pu_oppre)
150 pu->pu_oppre(pu);
152 if (error)
153 goto out;
155 /* Execute actual operation */
156 if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VFS) {
157 switch (preq->preq_optype) {
158 case PUFFS_VFS_UNMOUNT:
160 struct puffs_vfsmsg_unmount *auxt = auxbuf;
162 PU_SETSTATE(pu, PUFFS_STATE_UNMOUNTING);
163 error = pops->puffs_fs_unmount(pu, auxt->pvfsr_flags);
164 if (!error)
165 PU_SETSTATE(pu, PUFFS_STATE_UNMOUNTED);
166 else
167 PU_SETSTATE(pu, PUFFS_STATE_RUNNING);
168 break;
171 case PUFFS_VFS_STATVFS:
173 struct puffs_vfsmsg_statvfs *auxt = auxbuf;
175 error = pops->puffs_fs_statvfs(pu, &auxt->pvfsr_sb);
176 break;
179 case PUFFS_VFS_SYNC:
181 struct puffs_vfsmsg_sync *auxt = auxbuf;
183 error = pops->puffs_fs_sync(pu,
184 auxt->pvfsr_waitfor);
185 break;
188 case PUFFS_VFS_FHTOVP:
190 struct puffs_vfsmsg_fhtonode *auxt = auxbuf;
191 struct puffs_newinfo pni;
193 pni.pni_cookie = &auxt->pvfsr_fhcookie;
194 pni.pni_vtype = &auxt->pvfsr_vtype;
195 pni.pni_size = &auxt->pvfsr_size;
197 error = pops->puffs_fs_fhtonode(pu, auxt->pvfsr_data,
198 auxt->pvfsr_dsize, &pni);
200 break;
203 case PUFFS_VFS_VPTOFH:
205 struct puffs_vfsmsg_nodetofh *auxt = auxbuf;
207 error = pops->puffs_fs_nodetofh(pu,
208 auxt->pvfsr_fhcookie, auxt->pvfsr_data,
209 &auxt->pvfsr_dsize);
211 break;
214 case PUFFS_VFS_EXTATTRCTL:
216 struct puffs_vfsmsg_extattrctl *auxt = auxbuf;
217 const char *attrname;
218 int flags;
220 if (pops->puffs_fs_extattrctl == NULL) {
221 error = EOPNOTSUPP;
222 break;
225 if (auxt->pvfsr_flags & PUFFS_EXTATTRCTL_HASATTRNAME)
226 attrname = auxt->pvfsr_attrname;
227 else
228 attrname = NULL;
230 flags = auxt->pvfsr_flags & PUFFS_EXTATTRCTL_HASNODE;
231 error = pops->puffs_fs_extattrctl(pu, auxt->pvfsr_cmd,
232 opcookie, flags,
233 auxt->pvfsr_attrnamespace, attrname);
234 break;
237 default:
239 * I guess the kernel sees this one coming
241 error = EINVAL;
242 break;
245 /* XXX: audit return values */
246 /* XXX: sync with kernel */
247 } else if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VN) {
248 switch (preq->preq_optype) {
249 case PUFFS_VN_LOOKUP:
251 struct puffs_vnmsg_lookup *auxt = auxbuf;
252 struct puffs_newinfo pni;
253 struct puffs_cn pcn;
255 pcn.pcn_pkcnp = &auxt->pvnr_cn;
256 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
257 pni.pni_cookie = &auxt->pvnr_newnode;
258 pni.pni_vtype = &auxt->pvnr_vtype;
259 pni.pni_size = &auxt->pvnr_size;
261 if (buildpath) {
262 error = puffs_path_pcnbuild(pu, &pcn, opcookie);
263 if (error)
264 break;
267 /* lookup *must* be present */
268 error = pops->puffs_node_lookup(pu, opcookie,
269 &pni, &pcn);
271 if (buildpath) {
272 if (error) {
273 pu->pu_pathfree(pu, &pcn.pcn_po_full);
274 } else {
275 struct puffs_node *pn;
278 * did we get a new node or a
279 * recycled node?
281 pn = PU_CMAP(pu, auxt->pvnr_newnode);
282 if (pn->pn_po.po_path == NULL)
283 pn->pn_po = pcn.pcn_po_full;
284 else
285 pu->pu_pathfree(pu,
286 &pcn.pcn_po_full);
290 break;
293 case PUFFS_VN_LOOKUPDOTDOT:
295 struct puffs_kcn kcn = {
296 .pkcn_name = "..",
297 .pkcn_namelen = 2,
299 struct puffs_vnmsg_lookupdotdot *auxt = auxbuf;
300 struct puffs_newinfo pni;
301 struct puffs_cn pcn;
303 pcn.pcn_pkcnp = &kcn;
304 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cred);
305 pni.pni_cookie = &auxt->pvnr_newnode;
306 pni.pni_vtype = NULL;
307 pni.pni_size = NULL;
309 if (buildpath) {
310 error = puffs_path_pcnbuild(pu, &pcn, opcookie);
311 if (error)
312 break;
315 /* lookup *must* be present */
316 error = pops->puffs_node_lookupdotdot(pu, opcookie,
317 &pni, &pcn);
319 if (buildpath) {
320 if (error) {
321 pu->pu_pathfree(pu, &pcn.pcn_po_full);
322 } else {
323 struct puffs_node *pn;
326 * did we get a new node or a
327 * recycled node?
329 pn = PU_CMAP(pu, auxt->pvnr_newnode);
330 if (pn->pn_po.po_path == NULL)
331 pn->pn_po = pcn.pcn_po_full;
332 else
333 pu->pu_pathfree(pu,
334 &pcn.pcn_po_full);
337 break;
340 case PUFFS_VN_CREATE:
342 struct puffs_vnmsg_create *auxt = auxbuf;
343 struct puffs_newinfo pni;
344 struct puffs_cn pcn;
346 if (pops->puffs_node_create == NULL) {
347 error = 0;
348 break;
351 pcn.pcn_pkcnp = &auxt->pvnr_cn;
352 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
354 memset(&pni, 0, sizeof(pni));
355 pni.pni_cookie = &auxt->pvnr_newnode;
357 if (buildpath) {
358 error = puffs_path_pcnbuild(pu, &pcn, opcookie);
359 if (error)
360 break;
363 error = pops->puffs_node_create(pu,
364 opcookie, &pni, &pcn, &auxt->pvnr_va);
366 if (buildpath) {
367 if (error) {
368 pu->pu_pathfree(pu, &pcn.pcn_po_full);
369 } else {
370 struct puffs_node *pn;
372 pn = PU_CMAP(pu, auxt->pvnr_newnode);
373 pn->pn_po = pcn.pcn_po_full;
377 break;
380 case PUFFS_VN_MKNOD:
382 struct puffs_vnmsg_mknod *auxt = auxbuf;
383 struct puffs_newinfo pni;
384 struct puffs_cn pcn;
386 if (pops->puffs_node_mknod == NULL) {
387 error = 0;
388 break;
391 pcn.pcn_pkcnp = &auxt->pvnr_cn;
392 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
394 memset(&pni, 0, sizeof(pni));
395 pni.pni_cookie = &auxt->pvnr_newnode;
397 if (buildpath) {
398 error = puffs_path_pcnbuild(pu, &pcn, opcookie);
399 if (error)
400 break;
403 error = pops->puffs_node_mknod(pu,
404 opcookie, &pni, &pcn, &auxt->pvnr_va);
406 if (buildpath) {
407 if (error) {
408 pu->pu_pathfree(pu, &pcn.pcn_po_full);
409 } else {
410 struct puffs_node *pn;
412 pn = PU_CMAP(pu, auxt->pvnr_newnode);
413 pn->pn_po = pcn.pcn_po_full;
417 break;
420 case PUFFS_VN_OPEN:
422 struct puffs_vnmsg_open *auxt = auxbuf;
423 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
425 if (pops->puffs_node_open == NULL) {
426 error = 0;
427 break;
430 error = pops->puffs_node_open(pu,
431 opcookie, auxt->pvnr_mode, pcr);
432 break;
435 case PUFFS_VN_CLOSE:
437 struct puffs_vnmsg_close *auxt = auxbuf;
439 if (pops->puffs_node_close == NULL) {
440 error = 0;
441 break;
444 error = pops->puffs_node_close(pu,
445 opcookie, auxt->pvnr_fflag);
446 break;
449 case PUFFS_VN_ACCESS:
451 struct puffs_vnmsg_access *auxt = auxbuf;
452 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
454 if (pops->puffs_node_access == NULL) {
455 error = 0;
456 break;
459 error = pops->puffs_node_access(pu,
460 opcookie, auxt->pvnr_mode, pcr);
461 break;
464 case PUFFS_VN_GETATTR:
466 struct puffs_vnmsg_getattr *auxt = auxbuf;
467 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
469 if (pops->puffs_node_getattr == NULL) {
470 error = EOPNOTSUPP;
471 break;
474 error = pops->puffs_node_getattr(pu,
475 opcookie, &auxt->pvnr_va, pcr);
476 break;
479 case PUFFS_VN_SETATTR:
481 struct puffs_vnmsg_setattr *auxt = auxbuf;
482 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
484 if (pops->puffs_node_setattr == NULL) {
485 error = EOPNOTSUPP;
486 break;
489 error = pops->puffs_node_setattr(pu,
490 opcookie, &auxt->pvnr_va, pcr);
491 break;
494 case PUFFS_VN_MMAP:
496 struct puffs_vnmsg_mmap *auxt = auxbuf;
497 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
499 if (pops->puffs_node_mmap == NULL) {
500 error = 0;
501 break;
504 error = pops->puffs_node_mmap(pu,
505 opcookie, auxt->pvnr_prot, pcr);
506 break;
509 case PUFFS_VN_FSYNC:
511 struct puffs_vnmsg_fsync *auxt = auxbuf;
513 if (pops->puffs_node_fsync == NULL) {
514 error = 0;
515 break;
518 error = pops->puffs_node_fsync(pu, opcookie,
519 auxt->pvnr_flags);
520 break;
523 case PUFFS_VN_SEEK:
525 struct puffs_vnmsg_seek *auxt = auxbuf;
526 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
528 if (pops->puffs_node_seek == NULL) {
529 error = 0;
530 break;
533 error = pops->puffs_node_seek(pu,
534 opcookie, auxt->pvnr_oldoff,
535 auxt->pvnr_newoff, pcr);
536 break;
539 case PUFFS_VN_REMOVE:
541 struct puffs_vnmsg_remove *auxt = auxbuf;
542 struct puffs_cn pcn;
543 if (pops->puffs_node_remove == NULL) {
544 error = 0;
545 break;
548 pcn.pcn_pkcnp = &auxt->pvnr_cn;
549 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
551 error = pops->puffs_node_remove(pu,
552 opcookie, auxt->pvnr_cookie_targ, &pcn);
553 break;
556 case PUFFS_VN_LINK:
558 struct puffs_vnmsg_link *auxt = auxbuf;
559 struct puffs_cn pcn;
560 if (pops->puffs_node_link == NULL) {
561 error = 0;
562 break;
565 pcn.pcn_pkcnp = &auxt->pvnr_cn;
566 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
568 if (buildpath) {
569 error = puffs_path_pcnbuild(pu, &pcn, opcookie);
570 if (error)
571 break;
574 error = pops->puffs_node_link(pu,
575 opcookie, auxt->pvnr_cookie_targ, &pcn);
576 if (buildpath)
577 pu->pu_pathfree(pu, &pcn.pcn_po_full);
579 break;
582 case PUFFS_VN_RENAME:
584 struct puffs_vnmsg_rename *auxt = auxbuf;
585 struct puffs_cn pcn_src, pcn_targ;
586 struct puffs_node *pn_src;
588 if (pops->puffs_node_rename == NULL) {
589 error = 0;
590 break;
593 pcn_src.pcn_pkcnp = &auxt->pvnr_cn_src;
594 PUFFS_KCREDTOCRED(pcn_src.pcn_cred,
595 &auxt->pvnr_cn_src_cred);
597 pcn_targ.pcn_pkcnp = &auxt->pvnr_cn_targ;
598 PUFFS_KCREDTOCRED(pcn_targ.pcn_cred,
599 &auxt->pvnr_cn_targ_cred);
601 if (buildpath) {
602 pn_src = auxt->pvnr_cookie_src;
603 pcn_src.pcn_po_full = pn_src->pn_po;
605 error = puffs_path_pcnbuild(pu, &pcn_targ,
606 auxt->pvnr_cookie_targdir);
607 if (error)
608 break;
611 error = pops->puffs_node_rename(pu,
612 opcookie, auxt->pvnr_cookie_src,
613 &pcn_src, auxt->pvnr_cookie_targdir,
614 auxt->pvnr_cookie_targ, &pcn_targ);
616 if (buildpath) {
617 if (error) {
618 pu->pu_pathfree(pu,
619 &pcn_targ.pcn_po_full);
620 } else {
621 struct puffs_pathinfo pi;
622 struct puffs_pathobj po_old;
624 /* handle this node */
625 po_old = pn_src->pn_po;
626 pn_src->pn_po = pcn_targ.pcn_po_full;
628 if (pn_src->pn_va.va_type != VDIR) {
629 pu->pu_pathfree(pu, &po_old);
630 break;
633 /* handle all child nodes for DIRs */
634 pi.pi_old = &pcn_src.pcn_po_full;
635 pi.pi_new = &pcn_targ.pcn_po_full;
637 PU_LOCK();
638 if (puffs_pn_nodewalk(pu,
639 puffs_path_prefixadj, &pi) != NULL)
640 error = ENOMEM;
641 PU_UNLOCK();
642 pu->pu_pathfree(pu, &po_old);
645 break;
648 case PUFFS_VN_MKDIR:
650 struct puffs_vnmsg_mkdir *auxt = auxbuf;
651 struct puffs_newinfo pni;
652 struct puffs_cn pcn;
654 if (pops->puffs_node_mkdir == NULL) {
655 error = 0;
656 break;
659 pcn.pcn_pkcnp = &auxt->pvnr_cn;
660 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
662 memset(&pni, 0, sizeof(pni));
663 pni.pni_cookie = &auxt->pvnr_newnode;
665 if (buildpath) {
666 error = puffs_path_pcnbuild(pu, &pcn, opcookie);
667 if (error)
668 break;
671 error = pops->puffs_node_mkdir(pu,
672 opcookie, &pni, &pcn, &auxt->pvnr_va);
674 if (buildpath) {
675 if (error) {
676 pu->pu_pathfree(pu, &pcn.pcn_po_full);
677 } else {
678 struct puffs_node *pn;
680 pn = PU_CMAP(pu, auxt->pvnr_newnode);
681 pn->pn_po = pcn.pcn_po_full;
685 break;
688 case PUFFS_VN_RMDIR:
690 struct puffs_vnmsg_rmdir *auxt = auxbuf;
691 struct puffs_cn pcn;
692 if (pops->puffs_node_rmdir == NULL) {
693 error = 0;
694 break;
697 pcn.pcn_pkcnp = &auxt->pvnr_cn;
698 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
700 error = pops->puffs_node_rmdir(pu,
701 opcookie, auxt->pvnr_cookie_targ, &pcn);
702 break;
705 case PUFFS_VN_SYMLINK:
707 struct puffs_vnmsg_symlink *auxt = auxbuf;
708 struct puffs_newinfo pni;
709 struct puffs_cn pcn;
711 if (pops->puffs_node_symlink == NULL) {
712 error = 0;
713 break;
716 pcn.pcn_pkcnp = &auxt->pvnr_cn;
717 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
719 memset(&pni, 0, sizeof(pni));
720 pni.pni_cookie = &auxt->pvnr_newnode;
722 if (buildpath) {
723 error = puffs_path_pcnbuild(pu, &pcn, opcookie);
724 if (error)
725 break;
728 error = pops->puffs_node_symlink(pu,
729 opcookie, &pni, &pcn,
730 &auxt->pvnr_va, auxt->pvnr_link);
732 if (buildpath) {
733 if (error) {
734 pu->pu_pathfree(pu, &pcn.pcn_po_full);
735 } else {
736 struct puffs_node *pn;
738 pn = PU_CMAP(pu, auxt->pvnr_newnode);
739 pn->pn_po = pcn.pcn_po_full;
743 break;
746 case PUFFS_VN_READDIR:
748 struct puffs_vnmsg_readdir *auxt = auxbuf;
749 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
750 struct dirent *dent;
751 off_t *cookies;
752 size_t res, origcookies;
754 if (pops->puffs_node_readdir == NULL) {
755 error = 0;
756 break;
759 if (auxt->pvnr_ncookies) {
760 /* LINTED: pvnr_data is __aligned() */
761 cookies = (off_t *)auxt->pvnr_data;
762 origcookies = auxt->pvnr_ncookies;
763 } else {
764 cookies = NULL;
765 origcookies = 0;
767 /* LINTED: dentoff is aligned in the kernel */
768 dent = (struct dirent *)
769 (auxt->pvnr_data + auxt->pvnr_dentoff);
771 res = auxt->pvnr_resid;
772 error = pops->puffs_node_readdir(pu,
773 opcookie, dent, &auxt->pvnr_offset,
774 &auxt->pvnr_resid, pcr, &auxt->pvnr_eofflag,
775 cookies, &auxt->pvnr_ncookies);
777 /* much easier to track non-working NFS */
778 assert(auxt->pvnr_ncookies <= origcookies);
780 /* need to move a bit more */
781 preq->preq_buflen = sizeof(struct puffs_vnmsg_readdir)
782 + auxt->pvnr_dentoff + (res - auxt->pvnr_resid);
783 break;
786 case PUFFS_VN_READLINK:
788 struct puffs_vnmsg_readlink *auxt = auxbuf;
789 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
791 if (pops->puffs_node_readlink == NULL) {
792 error = EOPNOTSUPP;
793 break;
796 /*LINTED*/
797 error = pops->puffs_node_readlink(pu, opcookie, pcr,
798 auxt->pvnr_link, &auxt->pvnr_linklen);
799 break;
802 case PUFFS_VN_RECLAIM:
805 if (pops->puffs_node_reclaim == NULL) {
806 error = 0;
807 break;
810 error = pops->puffs_node_reclaim(pu, opcookie);
811 break;
814 case PUFFS_VN_INACTIVE:
817 if (pops->puffs_node_inactive == NULL) {
818 error = EOPNOTSUPP;
819 break;
822 error = pops->puffs_node_inactive(pu, opcookie);
823 break;
826 case PUFFS_VN_PATHCONF:
828 struct puffs_vnmsg_pathconf *auxt = auxbuf;
829 if (pops->puffs_node_pathconf == NULL) {
830 error = 0;
831 break;
834 error = pops->puffs_node_pathconf(pu,
835 opcookie, auxt->pvnr_name,
836 &auxt->pvnr_retval);
837 break;
840 case PUFFS_VN_ADVLOCK:
842 struct puffs_vnmsg_advlock *auxt = auxbuf;
843 if (pops->puffs_node_advlock == NULL) {
844 error = 0;
845 break;
848 error = pops->puffs_node_advlock(pu,
849 opcookie, auxt->pvnr_id, auxt->pvnr_op,
850 &auxt->pvnr_fl, auxt->pvnr_flags);
851 break;
854 case PUFFS_VN_PRINT:
856 if (pops->puffs_node_print == NULL) {
857 error = 0;
858 break;
861 error = pops->puffs_node_print(pu,
862 opcookie);
863 break;
866 case PUFFS_VN_ABORTOP:
868 struct puffs_vnmsg_abortop *auxt = auxbuf;
869 struct puffs_cn pcn;
871 if (pops->puffs_node_abortop == NULL) {
872 error = 0;
873 break;
876 pcn.pcn_pkcnp = &auxt->pvnr_cn;
877 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
879 error = pops->puffs_node_abortop(pu, opcookie, &pcn);
881 break;
884 case PUFFS_VN_READ:
886 struct puffs_vnmsg_read *auxt = auxbuf;
887 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
888 size_t res;
890 if (pops->puffs_node_read == NULL) {
891 error = EIO;
892 break;
895 res = auxt->pvnr_resid;
896 error = pops->puffs_node_read(pu,
897 opcookie, auxt->pvnr_data,
898 auxt->pvnr_offset, &auxt->pvnr_resid,
899 pcr, auxt->pvnr_ioflag);
901 /* need to move a bit more */
902 preq->preq_buflen = sizeof(struct puffs_vnmsg_read)
903 + (res - auxt->pvnr_resid);
904 break;
907 case PUFFS_VN_WRITE:
909 struct puffs_vnmsg_write *auxt = auxbuf;
910 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
912 if (pops->puffs_node_write == NULL) {
913 error = EIO;
914 break;
917 error = pops->puffs_node_write(pu,
918 opcookie, auxt->pvnr_data,
919 auxt->pvnr_offset, &auxt->pvnr_resid,
920 pcr, auxt->pvnr_ioflag);
922 /* don't need to move data back to the kernel */
923 preq->preq_buflen = sizeof(struct puffs_vnmsg_write);
924 break;
927 case PUFFS_VN_POLL:
929 struct puffs_vnmsg_poll *auxt = auxbuf;
931 if (pops->puffs_node_poll == NULL) {
932 error = 0;
934 /* emulate genfs_poll() */
935 auxt->pvnr_events &= (POLLIN | POLLOUT
936 | POLLRDNORM | POLLWRNORM);
938 break;
941 error = pops->puffs_node_poll(pu,
942 opcookie, &auxt->pvnr_events);
943 break;
946 case PUFFS_VN_GETEXTATTR:
948 struct puffs_vnmsg_getextattr *auxt = auxbuf;
949 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
950 size_t res, *resp, *sizep;
951 uint8_t *data;
953 if (pops->puffs_node_getextattr == NULL) {
954 error = EOPNOTSUPP;
955 break;
958 if (auxt->pvnr_datasize)
959 sizep = &auxt->pvnr_datasize;
960 else
961 sizep = NULL;
963 res = auxt->pvnr_resid;
964 if (res > 0) {
965 data = auxt->pvnr_data;
966 resp = &auxt->pvnr_resid;
967 } else {
968 data = NULL;
969 resp = NULL;
972 error = pops->puffs_node_getextattr(pu,
973 opcookie, auxt->pvnr_attrnamespace,
974 auxt->pvnr_attrname, sizep, data, resp, pcr);
976 /* need to move a bit more? */
977 preq->preq_buflen =
978 sizeof(struct puffs_vnmsg_getextattr)
979 + (res - auxt->pvnr_resid);
980 break;
983 case PUFFS_VN_SETEXTATTR:
985 struct puffs_vnmsg_setextattr *auxt = auxbuf;
986 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
987 size_t *resp;
988 uint8_t *data;
990 if (pops->puffs_node_setextattr == NULL) {
991 error = EOPNOTSUPP;
992 break;
995 if (auxt->pvnr_resid > 0) {
996 data = auxt->pvnr_data;
997 resp = &auxt->pvnr_resid;
998 } else {
999 data = NULL;
1000 resp = NULL;
1003 error = pops->puffs_node_setextattr(pu,
1004 opcookie, auxt->pvnr_attrnamespace,
1005 auxt->pvnr_attrname, data, resp, pcr);
1006 break;
1009 case PUFFS_VN_LISTEXTATTR:
1011 struct puffs_vnmsg_listextattr *auxt = auxbuf;
1012 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
1013 size_t res, *resp, *sizep;
1014 int flag;
1015 uint8_t *data;
1017 if (pops->puffs_node_listextattr == NULL) {
1018 error = EOPNOTSUPP;
1019 break;
1022 if (auxt->pvnr_datasize)
1023 sizep = &auxt->pvnr_datasize;
1024 else
1025 sizep = NULL;
1027 res = auxt->pvnr_resid;
1028 if (res > 0) {
1029 data = auxt->pvnr_data;
1030 resp = &auxt->pvnr_resid;
1031 } else {
1032 data = NULL;
1033 resp = NULL;
1036 res = auxt->pvnr_resid;
1037 flag = auxt->pvnr_flag;
1038 error = pops->puffs_node_listextattr(pu,
1039 opcookie, auxt->pvnr_attrnamespace,
1040 sizep, data, resp, flag, pcr);
1042 /* need to move a bit more? */
1043 preq->preq_buflen =
1044 sizeof(struct puffs_vnmsg_listextattr)
1045 + (res - auxt->pvnr_resid);
1046 break;
1049 case PUFFS_VN_DELETEEXTATTR:
1051 struct puffs_vnmsg_deleteextattr *auxt = auxbuf;
1052 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
1054 if (pops->puffs_node_deleteextattr == NULL) {
1055 error = EOPNOTSUPP;
1056 break;
1059 error = pops->puffs_node_deleteextattr(pu,
1060 opcookie, auxt->pvnr_attrnamespace,
1061 auxt->pvnr_attrname, pcr);
1062 break;
1065 default:
1066 printf("inval op %d\n", preq->preq_optype);
1067 error = EINVAL;
1068 break;
1071 #if 0
1072 /* not issued by kernel currently */
1073 } else if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_CACHE) {
1074 struct puffs_cacheinfo *pci = (void *)preq;
1076 if (pu->pu_ops.puffs_cache_write) {
1077 pu->pu_ops.puffs_cache_write(pu, preq->preq_cookie,
1078 pci->pcache_nruns, pci->pcache_runs);
1080 error = 0;
1081 #endif
1083 } else if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_ERROR) {
1084 struct puffs_error *perr = (void *)preq;
1086 pu->pu_errnotify(pu, preq->preq_optype,
1087 perr->perr_error, perr->perr_str, preq->preq_cookie);
1088 error = 0;
1089 } else {
1091 * I guess the kernel sees this one coming also
1093 error = EINVAL;
1096 out:
1097 preq->preq_rv = error;
1099 if (pu->pu_oppost)
1100 pu->pu_oppost(pu);
1102 pcc->pcc_flags |= PCC_DONE;