[BACK]Return to kernfs_vnops.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / miscfs / kernfs

Annotation of src/sys/miscfs/kernfs/kernfs_vnops.c, Revision 1.102

1.102   ! cl          1: /*     $NetBSD: kernfs_vnops.c,v 1.101 2004/05/07 15:06:15 cl Exp $    */
1.27      cgd         2:
1.1       cgd         3: /*
1.23      mycroft     4:  * Copyright (c) 1992, 1993
                      5:  *     The Regents of the University of California.  All rights reserved.
1.1       cgd         6:  *
1.17      cgd         7:  * This code is derived from software donated to Berkeley by
1.1       cgd         8:  * Jan-Simon Pendry.
                      9:  *
1.2       cgd        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.
1.89      agc        18:  * 3. Neither the name of the University nor the names of its contributors
1.2       cgd        19:  *    may be used to endorse or promote products derived from this software
                     20:  *    without specific prior written permission.
1.1       cgd        21:  *
1.2       cgd        22:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     23:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     24:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     25:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS 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
                     28:  * OR 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.
1.1       cgd        33:  *
1.57      fvdl       34:  *     @(#)kernfs_vnops.c      8.15 (Berkeley) 5/21/95
1.1       cgd        35:  */
                     36:
                     37: /*
1.23      mycroft    38:  * Kernel parameter filesystem (/kern)
1.1       cgd        39:  */
1.77      lukem      40:
                     41: #include <sys/cdefs.h>
1.102   ! cl         42: __KERNEL_RCSID(0, "$NetBSD: kernfs_vnops.c,v 1.101 2004/05/07 15:06:15 cl Exp $");
1.90      itojun     43:
                     44: #ifdef _KERNEL_OPT
                     45: #include "opt_ipsec.h"
                     46: #endif
1.55      mrg        47:
1.14      mycroft    48: #include <sys/param.h>
                     49: #include <sys/systm.h>
                     50: #include <sys/kernel.h>
1.23      mycroft    51: #include <sys/vmmeter.h>
1.14      mycroft    52: #include <sys/time.h>
                     53: #include <sys/proc.h>
1.23      mycroft    54: #include <sys/vnode.h>
                     55: #include <sys/malloc.h>
1.14      mycroft    56: #include <sys/file.h>
                     57: #include <sys/stat.h>
                     58: #include <sys/mount.h>
                     59: #include <sys/namei.h>
                     60: #include <sys/buf.h>
1.23      mycroft    61: #include <sys/dirent.h>
1.28      mycroft    62: #include <sys/msgbuf.h>
1.44      mycroft    63:
                     64: #include <miscfs/genfs/genfs.h>
1.17      cgd        65: #include <miscfs/kernfs/kernfs.h>
1.63      mrg        66:
1.90      itojun     67: #ifdef IPSEC
                     68: #include <sys/mbuf.h>
                     69: #include <net/route.h>
                     70: #include <netinet/in.h>
                     71: #include <netinet6/ipsec.h>
                     72: #include <netkey/key.h>
                     73: #endif
                     74:
1.54      mrg        75: #include <uvm/uvm_extern.h>
                     76:
1.17      cgd        77: #define KSTRING        256             /* Largest I/O available via this filesystem */
                     78: #define        UIO_MX 32
1.1       cgd        79:
1.23      mycroft    80: #define        READ_MODE       (S_IRUSR|S_IRGRP|S_IROTH)
                     81: #define        WRITE_MODE      (S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH)
1.101     cl         82: #define        UREAD_MODE      (S_IRUSR)
1.102   ! cl         83: #define        DIR_MODE        (S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
        !            84: #define        UDIR_MODE       (S_IRUSR|S_IXUSR)
1.23      mycroft    85:
1.90      itojun     86: #define N(s) sizeof(s)-1, s
1.75      jdolecek   87: const struct kern_target kern_targets[] = {
1.1       cgd        88: /* NOTE: The name must be less than UIO_MX-16 chars in length */
1.23      mycroft    89:      /*        name            data          tag           type  ro/rw */
1.98      darcy      90:      { DT_DIR, N("."),         0,            KFSkern,        VDIR, DIR_MODE   },
                     91:      { DT_DIR, N(".."),        0,            KFSroot,        VDIR, DIR_MODE   },
                     92:      { DT_REG, N("boottime"),  &boottime.tv_sec, KFSint,     VREG, READ_MODE  },
1.69      thorpej    93:                        /* XXX cast away const */
                     94:      { DT_REG, N("copyright"), (void *)copyright,
1.98      darcy      95:                                             KFSstring,      VREG, READ_MODE  },
                     96:      { DT_REG, N("hostname"),  0,            KFShostname,    VREG, WRITE_MODE },
                     97:      { DT_REG, N("hz"),        &hz,          KFSint,         VREG, READ_MODE  },
1.90      itojun     98: #ifdef IPSEC
1.98      darcy      99:      { DT_DIR, N("ipsecsa"),   0,           KFSipsecsadir,  VDIR, UDIR_MODE  },
                    100:      { DT_DIR, N("ipsecsp"),   0,           KFSipsecspdir,  VDIR, UDIR_MODE  },
1.90      itojun    101: #endif
1.98      darcy     102:      { DT_REG, N("loadavg"),   0,            KFSavenrun,     VREG, READ_MODE  },
                    103:      { DT_REG, N("msgbuf"),    0,           KFSmsgbuf,      VREG, READ_MODE  },
                    104:      { DT_REG, N("pagesize"),  &uvmexp.pagesize, KFSint,     VREG, READ_MODE  },
                    105:      { DT_REG, N("physmem"),   &physmem,     KFSint,         VREG, READ_MODE  },
1.17      cgd       106: #if 0
1.98      darcy     107:      { DT_DIR, N("root"),      0,            KFSnull,        VDIR, DIR_MODE   },
1.17      cgd       108: #endif
1.98      darcy     109:      { DT_BLK, N("rootdev"),   &rootdev,     KFSdevice,      VBLK, READ_MODE  },
                    110:      { DT_CHR, N("rrootdev"),  &rrootdev,    KFSdevice,      VCHR, READ_MODE  },
                    111:      { DT_REG, N("time"),      0,            KFStime,        VREG, READ_MODE  },
1.69      thorpej   112:                        /* XXX cast away const */
                    113:      { DT_REG, N("version"),   (void *)version,
1.98      darcy     114:                                             KFSstring,      VREG, READ_MODE  },
1.90      itojun    115: };
1.102   ! cl        116: const struct kern_target subdir_targets[] = {
        !           117: /* NOTE: The name must be less than UIO_MX-16 chars in length */
        !           118:      /*        name            data          tag           type  ro/rw */
        !           119:      { DT_DIR, N("."),         0,            KFSsubdir,      VDIR, DIR_MODE   },
        !           120:      { DT_DIR, N(".."),        0,            KFSkern,        VDIR, DIR_MODE   },
        !           121: };
1.90      itojun    122: #ifdef IPSEC
                    123: const struct kern_target ipsecsa_targets[] = {
                    124: /* NOTE: The name must be less than UIO_MX-16 chars in length */
                    125:      /*        name            data          tag           type  ro/rw */
1.98      darcy     126:      { DT_DIR, N("."),         0,            KFSipsecsadir,  VDIR, DIR_MODE   },
                    127:      { DT_DIR, N(".."),        0,            KFSkern,        VDIR, DIR_MODE   },
1.90      itojun    128: };
                    129: const struct kern_target ipsecsp_targets[] = {
                    130: /* NOTE: The name must be less than UIO_MX-16 chars in length */
                    131:      /*        name            data          tag           type  ro/rw */
1.98      darcy     132:      { DT_DIR, N("."),         0,            KFSipsecspdir,  VDIR, DIR_MODE   },
                    133:      { DT_DIR, N(".."),        0,            KFSkern,        VDIR, DIR_MODE   },
1.90      itojun    134: };
1.101     cl        135: const struct kern_target ipsecsa_kt =
                    136:      { DT_DIR, N(""),          0,            KFSipsecsa,     VREG, UREAD_MODE };
                    137: const struct kern_target ipsecsp_kt =
                    138:      { DT_DIR, N(""),          0,            KFSipsecsp,     VREG, UREAD_MODE };
1.90      itojun    139: #endif
1.23      mycroft   140: #undef N
1.102   ! cl        141: SIMPLEQ_HEAD(,dyn_kern_target) dyn_kern_targets =
        !           142:        SIMPLEQ_HEAD_INITIALIZER(dyn_kern_targets);
1.90      itojun    143: int nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]);
1.102   ! cl        144: const int static_nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]);
1.90      itojun    145: #ifdef IPSEC
                    146: int nipsecsa_targets = sizeof(ipsecsa_targets) / sizeof(ipsecsa_targets[0]);
                    147: int nipsecsp_targets = sizeof(ipsecsp_targets) / sizeof(ipsecsp_targets[0]);
1.102   ! cl        148: int nkern_dirs = 4; /* 2 extra subdirs */
        !           149: #else
        !           150: int nkern_dirs = 2;
1.90      itojun    151: #endif
                    152:
1.102   ! cl        153: int kernfs_try_fileop(kfstype, kfsfileop, void *, int);
        !           154: int kernfs_try_xwrite(kfstype, const struct kernfs_node *, char *,
        !           155:     size_t, int);
        !           156:
        !           157: static int kernfs_default_xwrite(void *v);
        !           158: static int kernfs_default_fileop_getattr(void *);
        !           159:
        !           160: /* must include all fileop's */
        !           161: const struct kernfs_fileop kernfs_default_fileops[] = {
        !           162:   { .kf_fileop = KERNFS_XWRITE },
        !           163:   { .kf_fileop = KERNFS_FILEOP_OPEN },
        !           164:   { .kf_fileop = KERNFS_FILEOP_GETATTR,
        !           165:     .kf_vop = kernfs_default_fileop_getattr },
        !           166:   { .kf_fileop = KERNFS_FILEOP_IOCTL },
        !           167:   { .kf_fileop = KERNFS_FILEOP_MMAP },
        !           168:   { .kf_fileop = KERNFS_FILEOP_CLOSE },
        !           169:   { .kf_fileop = KERNFS_FILEOP_WRITE, .kf_vop = kernfs_default_xwrite },
        !           170: };
1.1       cgd       171:
1.41      christos  172: int    kernfs_lookup   __P((void *));
1.85      jdolecek  173: #define        kernfs_create   genfs_eopnotsupp
                    174: #define        kernfs_mknod    genfs_eopnotsupp
1.90      itojun    175: int    kernfs_open     __P((void *));
                    176: int    kernfs_close    __P((void *));
1.41      christos  177: int    kernfs_access   __P((void *));
                    178: int    kernfs_getattr  __P((void *));
                    179: int    kernfs_setattr  __P((void *));
                    180: int    kernfs_read     __P((void *));
                    181: int    kernfs_write    __P((void *));
1.65      wrstuden  182: #define        kernfs_fcntl    genfs_fcntl
1.102   ! cl        183: int    kernfs_ioctl    __P((void *));
1.45      mycroft   184: #define        kernfs_poll     genfs_poll
1.57      fvdl      185: #define kernfs_revoke  genfs_revoke
1.102   ! cl        186: int    kernfs_mmap     __P((void *));
1.44      mycroft   187: #define        kernfs_fsync    genfs_nullop
                    188: #define        kernfs_seek     genfs_nullop
1.85      jdolecek  189: #define        kernfs_remove   genfs_eopnotsupp
1.41      christos  190: int    kernfs_link     __P((void *));
1.85      jdolecek  191: #define        kernfs_rename   genfs_eopnotsupp
                    192: #define        kernfs_mkdir    genfs_eopnotsupp
                    193: #define        kernfs_rmdir    genfs_eopnotsupp
1.41      christos  194: int    kernfs_symlink  __P((void *));
                    195: int    kernfs_readdir  __P((void *));
1.44      mycroft   196: #define        kernfs_readlink genfs_eopnotsupp
                    197: #define        kernfs_abortop  genfs_abortop
1.41      christos  198: int    kernfs_inactive __P((void *));
                    199: int    kernfs_reclaim  __P((void *));
1.64      wrstuden  200: #define        kernfs_lock     genfs_lock
                    201: #define        kernfs_unlock   genfs_unlock
1.44      mycroft   202: #define        kernfs_bmap     genfs_badop
                    203: #define        kernfs_strategy genfs_badop
1.41      christos  204: int    kernfs_print    __P((void *));
1.64      wrstuden  205: #define        kernfs_islocked genfs_islocked
1.41      christos  206: int    kernfs_pathconf __P((void *));
1.62      kleink    207: #define        kernfs_advlock  genfs_einval
1.44      mycroft   208: #define        kernfs_blkatoff genfs_eopnotsupp
                    209: #define        kernfs_valloc   genfs_eopnotsupp
                    210: #define        kernfs_vfree    genfs_nullop
                    211: #define        kernfs_truncate genfs_eopnotsupp
                    212: #define        kernfs_update   genfs_nullop
                    213: #define        kernfs_bwrite   genfs_eopnotsupp
1.79      chs       214: #define        kernfs_putpages genfs_putpages
1.41      christos  215:
1.90      itojun    216: static int     kernfs_xread __P((struct kernfs_node *, int, char **, size_t, size_t *));
                    217: static int     kernfs_xwrite __P((const struct kernfs_node *, char *, size_t));
1.41      christos  218:
                    219: int (**kernfs_vnodeop_p) __P((void *));
1.71      jdolecek  220: const struct vnodeopv_entry_desc kernfs_vnodeop_entries[] = {
1.41      christos  221:        { &vop_default_desc, vn_default_error },
1.44      mycroft   222:        { &vop_lookup_desc, kernfs_lookup },            /* lookup */
                    223:        { &vop_create_desc, kernfs_create },            /* create */
                    224:        { &vop_mknod_desc, kernfs_mknod },              /* mknod */
                    225:        { &vop_open_desc, kernfs_open },                /* open */
                    226:        { &vop_close_desc, kernfs_close },              /* close */
                    227:        { &vop_access_desc, kernfs_access },            /* access */
                    228:        { &vop_getattr_desc, kernfs_getattr },          /* getattr */
                    229:        { &vop_setattr_desc, kernfs_setattr },          /* setattr */
                    230:        { &vop_read_desc, kernfs_read },                /* read */
                    231:        { &vop_write_desc, kernfs_write },              /* write */
1.65      wrstuden  232:        { &vop_fcntl_desc, kernfs_fcntl },              /* fcntl */
1.44      mycroft   233:        { &vop_ioctl_desc, kernfs_ioctl },              /* ioctl */
1.45      mycroft   234:        { &vop_poll_desc, kernfs_poll },                /* poll */
1.57      fvdl      235:        { &vop_revoke_desc, kernfs_revoke },            /* revoke */
1.102   ! cl        236:        { &vop_mmap_desc, kernfs_mmap },                /* mmap */
1.44      mycroft   237:        { &vop_fsync_desc, kernfs_fsync },              /* fsync */
                    238:        { &vop_seek_desc, kernfs_seek },                /* seek */
                    239:        { &vop_remove_desc, kernfs_remove },            /* remove */
                    240:        { &vop_link_desc, kernfs_link },                /* link */
                    241:        { &vop_rename_desc, kernfs_rename },            /* rename */
                    242:        { &vop_mkdir_desc, kernfs_mkdir },              /* mkdir */
                    243:        { &vop_rmdir_desc, kernfs_rmdir },              /* rmdir */
                    244:        { &vop_symlink_desc, kernfs_symlink },          /* symlink */
                    245:        { &vop_readdir_desc, kernfs_readdir },          /* readdir */
                    246:        { &vop_readlink_desc, kernfs_readlink },        /* readlink */
                    247:        { &vop_abortop_desc, kernfs_abortop },          /* abortop */
                    248:        { &vop_inactive_desc, kernfs_inactive },        /* inactive */
                    249:        { &vop_reclaim_desc, kernfs_reclaim },          /* reclaim */
                    250:        { &vop_lock_desc, kernfs_lock },                /* lock */
                    251:        { &vop_unlock_desc, kernfs_unlock },            /* unlock */
                    252:        { &vop_bmap_desc, kernfs_bmap },                /* bmap */
                    253:        { &vop_strategy_desc, kernfs_strategy },        /* strategy */
                    254:        { &vop_print_desc, kernfs_print },              /* print */
                    255:        { &vop_islocked_desc, kernfs_islocked },        /* islocked */
                    256:        { &vop_pathconf_desc, kernfs_pathconf },        /* pathconf */
                    257:        { &vop_advlock_desc, kernfs_advlock },          /* advlock */
                    258:        { &vop_blkatoff_desc, kernfs_blkatoff },        /* blkatoff */
                    259:        { &vop_valloc_desc, kernfs_valloc },            /* valloc */
                    260:        { &vop_vfree_desc, kernfs_vfree },              /* vfree */
                    261:        { &vop_truncate_desc, kernfs_truncate },        /* truncate */
                    262:        { &vop_update_desc, kernfs_update },            /* update */
                    263:        { &vop_bwrite_desc, kernfs_bwrite },            /* bwrite */
1.79      chs       264:        { &vop_putpages_desc, kernfs_putpages },        /* putpages */
1.76      chs       265:        { NULL, NULL }
1.41      christos  266: };
1.71      jdolecek  267: const struct vnodeopv_desc kernfs_vnodeop_opv_desc =
1.41      christos  268:        { &kernfs_vnodeop_p, kernfs_vnodeop_entries };
                    269:
1.102   ! cl        270: static __inline int
        !           271: kernfs_fileop_compare(struct kernfs_fileop *a, struct kernfs_fileop *b)
        !           272: {
        !           273:        if (a->kf_type < b->kf_type)
        !           274:                return -1;
        !           275:        if (a->kf_type > b->kf_type)
        !           276:                return 1;
        !           277:        if (a->kf_fileop < b->kf_fileop)
        !           278:                return -1;
        !           279:        if (a->kf_fileop > b->kf_fileop)
        !           280:                return 1;
        !           281:        return (0);
        !           282: }
        !           283:
        !           284: SPLAY_HEAD(kfsfileoptree, kernfs_fileop) kfsfileoptree =
        !           285:        SPLAY_INITIALIZER(kfsfileoptree);
        !           286: SPLAY_PROTOTYPE(kfsfileoptree, kernfs_fileop, kf_node, kernfs_fileop_compare);
        !           287: SPLAY_GENERATE(kfsfileoptree, kernfs_fileop, kf_node, kernfs_fileop_compare);
        !           288:
        !           289: kfstype
        !           290: kernfs_alloctype(int nkf, const struct kernfs_fileop *kf)
        !           291: {
        !           292:        static u_char nextfreetype = KFSlasttype;
        !           293:        struct kernfs_fileop *dkf, *fkf, skf;
        !           294:        int i;
        !           295:
        !           296:        /* XXX need to keep track of dkf's memory if we support
        !           297:            deallocating types */
        !           298:        dkf = malloc(sizeof(kernfs_default_fileops), M_TEMP, M_WAITOK);
        !           299:        memcpy(dkf, kernfs_default_fileops, sizeof(kernfs_default_fileops));
        !           300:
        !           301:        for (i = 0; i < sizeof(kernfs_default_fileops) /
        !           302:                     sizeof(kernfs_default_fileops[0]); i++) {
        !           303:                dkf[i].kf_type = nextfreetype;
        !           304:                SPLAY_INSERT(kfsfileoptree, &kfsfileoptree, &dkf[i]);
        !           305:        }
        !           306:
        !           307:        for (i = 0; i < nkf; i++) {
        !           308:                skf.kf_type = nextfreetype;
        !           309:                skf.kf_fileop = kf[i].kf_fileop;
        !           310:                if ((fkf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf)))
        !           311:                        fkf->kf_genop = kf[i].kf_genop;
        !           312:        }
        !           313:
        !           314:        return nextfreetype++;
        !           315: }
        !           316:
        !           317: int
        !           318: kernfs_try_fileop(kfstype type, kfsfileop fileop, void *v, int error)
        !           319: {
        !           320:        struct kernfs_fileop *kf, skf;
        !           321:
        !           322:        skf.kf_type = type;
        !           323:        skf.kf_fileop = fileop;
        !           324:        if ((kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf)))
        !           325:                if (kf->kf_vop)
        !           326:                        return kf->kf_vop(v);
        !           327:        return error;
        !           328: }
        !           329:
        !           330: int
        !           331: kernfs_try_xwrite(kfstype type, const struct kernfs_node *kfs, char *buf,
        !           332:     size_t len, int error)
        !           333: {
        !           334:        struct kernfs_fileop *kf, skf;
        !           335:
        !           336:        skf.kf_type = type;
        !           337:        skf.kf_fileop = KERNFS_XWRITE;
        !           338:        if ((kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf)))
        !           339:                if (kf->kf_xwrite)
        !           340:                        return kf->kf_xwrite(kfs, buf, len);
        !           341:        return error;
        !           342: }
        !           343:
        !           344: int
        !           345: kernfs_addentry(kernfs_parentdir_t *pkt, kernfs_entry_t *dkt)
        !           346: {
        !           347:        struct kernfs_subdir *ks, *parent;
        !           348:
        !           349:        if (pkt == NULL) {
        !           350:                SIMPLEQ_INSERT_TAIL(&dyn_kern_targets, dkt, dkt_queue);
        !           351:                nkern_targets++;
        !           352:                if (dkt->dkt_kt.kt_vtype == VDIR)
        !           353:                        nkern_dirs++;
        !           354:        } else {
        !           355:                parent = (struct kernfs_subdir *)pkt->kt_data;
        !           356:                SIMPLEQ_INSERT_TAIL(&parent->ks_entries, dkt, dkt_queue);
        !           357:                parent->ks_nentries++;
        !           358:                if (dkt->dkt_kt.kt_vtype == VDIR)
        !           359:                        parent->ks_dirs++;
        !           360:        }
        !           361:        if (dkt->dkt_kt.kt_vtype == VDIR && dkt->dkt_kt.kt_data == NULL) {
        !           362:                ks = malloc(sizeof(struct kernfs_subdir),
        !           363:                    M_TEMP, M_WAITOK);
        !           364:                SIMPLEQ_INIT(&ks->ks_entries);
        !           365:                ks->ks_nentries = 2; /* . and .. */
        !           366:                ks->ks_dirs = 2;
        !           367:                ks->ks_parent = pkt ? pkt : &kern_targets[0];
        !           368:                dkt->dkt_kt.kt_data = ks;
        !           369:        }
        !           370:        return 0;
        !           371: }
        !           372:
1.82      jdolecek  373: static int
1.90      itojun    374: kernfs_xread(kfs, off, bufp, len, wrlen)
                    375:        struct kernfs_node *kfs;
1.28      mycroft   376:        int off;
                    377:        char **bufp;
1.82      jdolecek  378:        size_t len;
                    379:        size_t *wrlen;
1.1       cgd       380: {
1.90      itojun    381:        const struct kern_target *kt;
                    382: #ifdef IPSEC
                    383:        struct mbuf *m;
                    384: #endif
                    385:
                    386:        kt = kfs->kfs_kt;
1.1       cgd       387:
1.90      itojun    388:        switch (kfs->kfs_type) {
1.98      darcy     389:        case KFStime: {
1.1       cgd       390:                struct timeval tv;
1.28      mycroft   391:
1.1       cgd       392:                microtime(&tv);
1.90      itojun    393:                snprintf(*bufp, len, "%ld %ld\n", tv.tv_sec, tv.tv_usec);
1.1       cgd       394:                break;
                    395:        }
                    396:
1.98      darcy     397:        case KFSint: {
1.1       cgd       398:                int *ip = kt->kt_data;
1.28      mycroft   399:
1.90      itojun    400:                snprintf(*bufp, len, "%d\n", *ip);
1.1       cgd       401:                break;
                    402:        }
                    403:
1.98      darcy     404:        case KFSstring: {
1.1       cgd       405:                char *cp = kt->kt_data;
                    406:
1.28      mycroft   407:                *bufp = cp;
                    408:                break;
                    409:        }
1.1       cgd       410:
1.98      darcy     411:        case KFSmsgbuf: {
1.28      mycroft   412:                long n;
                    413:
1.52      leo       414:                /*
                    415:                 * deal with cases where the message buffer has
                    416:                 * become corrupted.
                    417:                 */
                    418:                if (!msgbufenabled || msgbufp->msg_magic != MSG_MAGIC) {
                    419:                        msgbufenabled = 0;
                    420:                        return (ENXIO);
                    421:                }
                    422:
                    423:                /*
                    424:                 * Note that reads of /kern/msgbuf won't necessarily yield
                    425:                 * consistent results, if the message buffer is modified
                    426:                 * while the read is in progress.  The worst that can happen
                    427:                 * is that incorrect data will be read.  There's no way
                    428:                 * that this can crash the system unless the values in the
                    429:                 * message buffer header are corrupted, but that'll cause
                    430:                 * the system to die anyway.
                    431:                 */
1.82      jdolecek  432:                if (off >= msgbufp->msg_bufs) {
                    433:                        *wrlen = 0;
1.28      mycroft   434:                        return (0);
1.82      jdolecek  435:                }
1.28      mycroft   436:                n = msgbufp->msg_bufx + off;
1.52      leo       437:                if (n >= msgbufp->msg_bufs)
                    438:                        n -= msgbufp->msg_bufs;
                    439:                len = min(msgbufp->msg_bufs - n, msgbufp->msg_bufs - off);
1.28      mycroft   440:                *bufp = msgbufp->msg_bufc + n;
1.82      jdolecek  441:                *wrlen = len;
                    442:                return (0);
1.1       cgd       443:        }
                    444:
1.98      darcy     445:        case KFShostname: {
1.1       cgd       446:                char *cp = hostname;
                    447:                int xlen = hostnamelen;
                    448:
1.90      itojun    449:                if (xlen >= (len - 2))
1.1       cgd       450:                        return (EINVAL);
                    451:
1.60      perry     452:                memcpy(*bufp, cp, xlen);
1.28      mycroft   453:                (*bufp)[xlen] = '\n';
                    454:                (*bufp)[xlen+1] = '\0';
1.90      itojun    455:                len = strlen(*bufp);
1.1       cgd       456:                break;
                    457:        }
                    458:
1.98      darcy     459:        case KFSavenrun:
1.31      mycroft   460:                averunnable.fscale = FSCALE;
1.90      itojun    461:                snprintf(*bufp, len, "%d %d %d %ld\n",
1.23      mycroft   462:                    averunnable.ldavg[0], averunnable.ldavg[1],
                    463:                    averunnable.ldavg[2], averunnable.fscale);
1.1       cgd       464:                break;
                    465:
1.90      itojun    466: #ifdef IPSEC
1.98      darcy     467:        case KFSipsecsa:
1.90      itojun    468:                /*
                    469:                 * Note that SA configuration could be changed during the
                    470:                 * read operation, resulting in garbled output.
                    471:                 */
                    472:                m = key_setdumpsa_spi(htonl(kfs->kfs_value));
                    473:                if (!m)
                    474:                        return (ENOBUFS);
                    475:                if (off >= m->m_pkthdr.len) {
                    476:                        *wrlen = 0;
                    477:                        m_freem(m);
                    478:                        return (0);
                    479:                }
                    480:                if (len > m->m_pkthdr.len - off)
                    481:                        len = m->m_pkthdr.len - off;
                    482:                m_copydata(m, off, len, *bufp);
                    483:                *wrlen = len;
                    484:                m_freem(m);
                    485:                return (0);
                    486:
1.98      darcy     487:        case KFSipsecsp:
1.90      itojun    488:                /*
                    489:                 * Note that SP configuration could be changed during the
                    490:                 * read operation, resulting in garbled output.
                    491:                 */
                    492:                if (!kfs->kfs_v) {
                    493:                        struct secpolicy *sp;
                    494:
                    495:                        sp = key_getspbyid(kfs->kfs_value);
                    496:                        if (sp)
                    497:                                kfs->kfs_v = sp;
                    498:                        else
                    499:                                return (ENOENT);
                    500:                }
                    501:                m = key_setdumpsp((struct secpolicy *)kfs->kfs_v,
                    502:                    SADB_X_SPDGET, 0, 0);
                    503:                if (!m)
                    504:                        return (ENOBUFS);
                    505:                if (off >= m->m_pkthdr.len) {
                    506:                        *wrlen = 0;
                    507:                        m_freem(m);
                    508:                        return (0);
                    509:                }
                    510:                if (len > m->m_pkthdr.len - off)
                    511:                        len = m->m_pkthdr.len - off;
                    512:                m_copydata(m, off, len, *bufp);
                    513:                *wrlen = len;
                    514:                m_freem(m);
                    515:                return (0);
                    516: #endif
                    517:
1.1       cgd       518:        default:
1.82      jdolecek  519:                *wrlen = 0;
1.28      mycroft   520:                return (0);
1.1       cgd       521:        }
                    522:
1.28      mycroft   523:        len = strlen(*bufp);
                    524:        if (len <= off)
1.82      jdolecek  525:                *wrlen = 0;
                    526:        else {
                    527:                *bufp += off;
                    528:                *wrlen = len - off;
                    529:        }
                    530:        return (0);
1.1       cgd       531: }
                    532:
1.82      jdolecek  533: static int
1.90      itojun    534: kernfs_xwrite(kfs, buf, len)
                    535:        const struct kernfs_node *kfs;
1.1       cgd       536:        char *buf;
1.82      jdolecek  537:        size_t len;
1.1       cgd       538: {
1.23      mycroft   539:
1.90      itojun    540:        switch (kfs->kfs_type) {
1.98      darcy     541:        case KFShostname:
1.1       cgd       542:                if (buf[len-1] == '\n')
                    543:                        --len;
1.60      perry     544:                memcpy(hostname, buf, len);
1.17      cgd       545:                hostname[len] = '\0';
1.82      jdolecek  546:                hostnamelen = (size_t) len;
1.1       cgd       547:                return (0);
                    548:
                    549:        default:
1.102   ! cl        550:                return kernfs_try_xwrite(kfs->kfs_type, kfs, buf, len, EIO);
1.1       cgd       551:        }
                    552: }
                    553:
1.17      cgd       554:
                    555: /*
1.1       cgd       556:  * vp is the current namei directory
                    557:  * ndp is the name to locate in that directory...
                    558:  */
1.41      christos  559: int
                    560: kernfs_lookup(v)
                    561:        void *v;
                    562: {
1.23      mycroft   563:        struct vop_lookup_args /* {
                    564:                struct vnode * a_dvp;
                    565:                struct vnode ** a_vpp;
                    566:                struct componentname * a_cnp;
1.41      christos  567:        } */ *ap = v;
1.23      mycroft   568:        struct componentname *cnp = ap->a_cnp;
                    569:        struct vnode **vpp = ap->a_vpp;
                    570:        struct vnode *dvp = ap->a_dvp;
1.48      cgd       571:        const char *pname = cnp->cn_nameptr;
1.90      itojun    572:        const struct kernfs_node *kfs;
1.75      jdolecek  573:        const struct kern_target *kt;
1.102   ! cl        574:        const struct dyn_kern_target *dkt;
        !           575:        const struct kernfs_subdir *ks;
1.64      wrstuden  576:        int error, i, wantpunlock;
1.90      itojun    577: #ifdef IPSEC
                    578:        char *ep;
                    579:        u_int32_t id;
1.1       cgd       580: #endif
1.23      mycroft   581:
1.35      mycroft   582:        *vpp = NULLVP;
1.64      wrstuden  583:        cnp->cn_flags &= ~PDIRUNLOCK;
1.35      mycroft   584:
                    585:        if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)
                    586:                return (EROFS);
                    587:
1.23      mycroft   588:        if (cnp->cn_namelen == 1 && *pname == '.') {
                    589:                *vpp = dvp;
1.1       cgd       590:                VREF(dvp);
                    591:                return (0);
                    592:        }
1.13      cgd       593:
1.90      itojun    594:        wantpunlock = (~cnp->cn_flags & (LOCKPARENT | ISLASTCN));
                    595:        kfs = VTOKERN(dvp);
                    596:        switch (kfs->kfs_type) {
1.98      darcy     597:        case KFSkern:
1.90      itojun    598:                /*
                    599:                 * Shouldn't get here with .. in the root node.
                    600:                 */
                    601:                if (cnp->cn_flags & ISDOTDOT)
                    602:                        return (EIO);
1.64      wrstuden  603:
1.102   ! cl        604:                for (i = 0; i < static_nkern_targets; i++) {
1.90      itojun    605:                        kt = &kern_targets[i];
                    606:                        if (cnp->cn_namelen == kt->kt_namlen &&
                    607:                            memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
                    608:                                goto found;
                    609:                }
1.102   ! cl        610:                SIMPLEQ_FOREACH(dkt, &dyn_kern_targets, dkt_queue) {
        !           611:                        if (cnp->cn_namelen == dkt->dkt_kt.kt_namlen &&
        !           612:                            memcmp(dkt->dkt_kt.kt_name, pname, cnp->cn_namelen) == 0) {
        !           613:                                kt = &dkt->dkt_kt;
        !           614:                                goto found;
        !           615:                        }
        !           616:                }
1.90      itojun    617:                break;
1.25      mycroft   618:
1.90      itojun    619:        found:
                    620:                error = kernfs_allocvp(dvp->v_mount, vpp, kt->kt_tag, kt, 0);
                    621:                if ((error == 0) && wantpunlock) {
                    622:                        VOP_UNLOCK(dvp, 0);
                    623:                        cnp->cn_flags |= PDIRUNLOCK;
                    624:                }
                    625:                return (error);
1.64      wrstuden  626:
1.102   ! cl        627:        case KFSsubdir:
        !           628:                ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data;
        !           629:                if (cnp->cn_flags & ISDOTDOT) {
        !           630:                        kt = ks->ks_parent;
        !           631:                        goto found;
        !           632:                }
        !           633:
        !           634:                SIMPLEQ_FOREACH(dkt, &ks->ks_entries, dkt_queue) {
        !           635:                        if (cnp->cn_namelen == dkt->dkt_kt.kt_namlen &&
        !           636:                            memcmp(dkt->dkt_kt.kt_name, pname, cnp->cn_namelen) == 0) {
        !           637:                                kt = &dkt->dkt_kt;
        !           638:                                goto found;
        !           639:                        }
        !           640:                }
        !           641:                break;
        !           642:
1.90      itojun    643: #ifdef IPSEC
1.98      darcy     644:        case KFSipsecsadir:
1.100     cl        645:                if (cnp->cn_flags & ISDOTDOT) {
                    646:                        kt = &kern_targets[0];
                    647:                        goto found;
                    648:                }
                    649:
                    650:                for (i = 2; i < nipsecsa_targets; i++) {
1.90      itojun    651:                        kt = &ipsecsa_targets[i];
                    652:                        if (cnp->cn_namelen == kt->kt_namlen &&
1.100     cl        653:                            memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
                    654:                                goto found;
1.90      itojun    655:                }
1.1       cgd       656:
1.90      itojun    657:                ep = NULL;
                    658:                id = strtoul(pname, &ep, 10);
                    659:                if (!ep || *ep || ep == pname)
                    660:                        break;
1.1       cgd       661:
1.101     cl        662:                error = kernfs_allocvp(dvp->v_mount, vpp, KFSipsecsa, &ipsecsa_kt, id);
1.90      itojun    663:                if ((error == 0) && wantpunlock) {
                    664:                        VOP_UNLOCK(dvp, 0);
                    665:                        cnp->cn_flags |= PDIRUNLOCK;
                    666:                }
                    667:                return (error);
1.23      mycroft   668:
1.98      darcy     669:        case KFSipsecspdir:
1.100     cl        670:                if (cnp->cn_flags & ISDOTDOT) {
                    671:                        kt = &kern_targets[0];
                    672:                        goto found;
                    673:                }
                    674:
                    675:                for (i = 2; i < nipsecsp_targets; i++) {
1.90      itojun    676:                        kt = &ipsecsp_targets[i];
                    677:                        if (cnp->cn_namelen == kt->kt_namlen &&
1.100     cl        678:                            memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
                    679:                                goto found;
1.57      fvdl      680:                }
1.90      itojun    681:
                    682:                ep = NULL;
                    683:                id = strtoul(pname, &ep, 10);
                    684:                if (!ep || *ep || ep == pname)
                    685:                        break;
                    686:
1.101     cl        687:                error = kernfs_allocvp(dvp->v_mount, vpp, KFSipsecsp, &ipsecsp_kt, id);
1.90      itojun    688:                if ((error == 0) && wantpunlock) {
1.64      wrstuden  689:                        VOP_UNLOCK(dvp, 0);
                    690:                        cnp->cn_flags |= PDIRUNLOCK;
                    691:                }
1.90      itojun    692:                return (error);
                    693: #endif
                    694:
                    695:        default:
                    696:                return (ENOTDIR);
                    697:        }
                    698:
                    699:        return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS);
                    700: }
                    701:
                    702: int
                    703: kernfs_open(v)
                    704:        void *v;
                    705: {
                    706:        struct vop_open_args /* {
                    707:                struct vnode *a_vp;
                    708:                int a_mode;
                    709:                struct ucred *a_cred;
                    710:                struct proc *a_p;
                    711:        } */ *ap = v;
                    712:        struct kernfs_node *kfs = VTOKERN(ap->a_vp);
                    713: #ifdef IPSEC
                    714:        struct mbuf *m;
                    715:        struct secpolicy *sp;
                    716: #endif
                    717:
                    718:        switch (kfs->kfs_type) {
                    719: #ifdef IPSEC
1.98      darcy     720:        case KFSipsecsa:
1.90      itojun    721:                m = key_setdumpsa_spi(htonl(kfs->kfs_value));
                    722:                if (m) {
                    723:                        m_freem(m);
                    724:                        return (0);
                    725:                } else
                    726:                        return (ENOENT);
                    727:
1.98      darcy     728:        case KFSipsecsp:
1.90      itojun    729:                sp = key_getspbyid(kfs->kfs_value);
                    730:                if (sp) {
                    731:                        kfs->kfs_v = sp;
                    732:                        return (0);
                    733:                } else
                    734:                        return (ENOENT);
                    735: #endif
                    736:
                    737:        default:
1.102   ! cl        738:                return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_OPEN,
        !           739:                    v, 0);
1.23      mycroft   740:        }
1.90      itojun    741: }
1.1       cgd       742:
1.90      itojun    743: int
                    744: kernfs_close(v)
                    745:        void *v;
                    746: {
                    747:        struct vop_close_args /* {
                    748:                struct vnode *a_vp;
                    749:                int a_fflag;
                    750:                struct ucred *a_cred;
                    751:                struct proc *a_p;
                    752:        } */ *ap = v;
                    753:        struct kernfs_node *kfs = VTOKERN(ap->a_vp);
                    754:
                    755:        switch (kfs->kfs_type) {
                    756: #ifdef IPSEC
1.98      darcy     757:        case KFSipsecsp:
1.90      itojun    758:                key_freesp((struct secpolicy *)kfs->kfs_v);
                    759:                break;
1.1       cgd       760: #endif
1.90      itojun    761:
                    762:        default:
1.102   ! cl        763:                return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_CLOSE,
        !           764:                    v, 0);
1.57      fvdl      765:        }
1.23      mycroft   766:
1.1       cgd       767:        return (0);
                    768: }
                    769:
1.28      mycroft   770: int
1.41      christos  771: kernfs_access(v)
                    772:        void *v;
                    773: {
1.23      mycroft   774:        struct vop_access_args /* {
                    775:                struct vnode *a_vp;
1.34      mycroft   776:                int a_mode;
1.23      mycroft   777:                struct ucred *a_cred;
                    778:                struct proc *a_p;
1.41      christos  779:        } */ *ap = v;
1.90      itojun    780:        struct vattr va;
                    781:        int error;
1.17      cgd       782:
1.90      itojun    783:        if ((error = VOP_GETATTR(ap->a_vp, &va, ap->a_cred, ap->a_p)) != 0)
                    784:                return (error);
1.49      mycroft   785:
1.90      itojun    786:        return (vaccess(va.va_type, va.va_mode, va.va_uid, va.va_gid,
                    787:            ap->a_mode, ap->a_cred));
1.23      mycroft   788: }
                    789:
1.102   ! cl        790: static int
        !           791: kernfs_default_fileop_getattr(v)
        !           792:        void *v;
        !           793: {
        !           794:        struct vop_getattr_args /* {
        !           795:                struct vnode *a_vp;
        !           796:                struct vattr *a_vap;
        !           797:                struct ucred *a_cred;
        !           798:                struct proc *a_p;
        !           799:        } */ *ap = v;
        !           800:        struct vattr *vap = ap->a_vap;
        !           801:
        !           802:        vap->va_nlink = 1;
        !           803:        vap->va_bytes = vap->va_size = 0;
        !           804:
        !           805:        return 0;
        !           806: }
        !           807:
1.41      christos  808: int
                    809: kernfs_getattr(v)
                    810:        void *v;
                    811: {
1.23      mycroft   812:        struct vop_getattr_args /* {
                    813:                struct vnode *a_vp;
                    814:                struct vattr *a_vap;
                    815:                struct ucred *a_cred;
                    816:                struct proc *a_p;
1.41      christos  817:        } */ *ap = v;
1.90      itojun    818:        struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1.102   ! cl        819:        struct kernfs_subdir *ks;
1.23      mycroft   820:        struct vattr *vap = ap->a_vap;
1.1       cgd       821:        int error = 0;
1.28      mycroft   822:        char strbuf[KSTRING], *buf;
1.90      itojun    823:        size_t nread, total;
1.1       cgd       824:
1.90      itojun    825:        VATTR_NULL(vap);
                    826:        vap->va_type = ap->a_vp->v_type;
1.17      cgd       827:        vap->va_uid = 0;
                    828:        vap->va_gid = 0;
1.90      itojun    829:        vap->va_mode = kfs->kfs_mode;
                    830:        vap->va_fileid = kfs->kfs_fileno;
                    831:        vap->va_flags = 0;
1.23      mycroft   832:        vap->va_size = 0;
1.1       cgd       833:        vap->va_blocksize = DEV_BSIZE;
1.81      lukem     834:        /*
1.92      dan       835:         * Make all times be current TOD, except for the "boottime" node.
1.93      simonb    836:         * Avoid microtime(9), it's slow.
1.83      simonb    837:         * We don't guard the read from time(9) with splclock(9) since we
                    838:         * don't actually need to be THAT sure the access is atomic.
1.81      lukem     839:         */
1.96      itojun    840:        if (kfs->kfs_kt && kfs->kfs_kt->kt_namlen == 8 &&
1.92      dan       841:            !memcmp(kfs->kfs_kt->kt_name, "boottime", 8)) {
                    842:                TIMEVAL_TO_TIMESPEC(&boottime, &vap->va_ctime);
                    843:        } else {
                    844:                TIMEVAL_TO_TIMESPEC(&time, &vap->va_ctime);
                    845:        }
1.81      lukem     846:        vap->va_atime = vap->va_mtime = vap->va_ctime;
1.1       cgd       847:        vap->va_gen = 0;
                    848:        vap->va_flags = 0;
                    849:        vap->va_rdev = 0;
                    850:        vap->va_bytes = 0;
                    851:
1.90      itojun    852:        switch (kfs->kfs_type) {
1.98      darcy     853:        case KFSkern:
1.102   ! cl        854:                vap->va_nlink = nkern_dirs;
1.90      itojun    855:                vap->va_bytes = vap->va_size = DEV_BSIZE;
                    856:                break;
                    857:
1.98      darcy     858:        case KFSroot:
1.90      itojun    859:                vap->va_nlink = 1;
                    860:                vap->va_bytes = vap->va_size = DEV_BSIZE;
                    861:                break;
                    862:
1.102   ! cl        863:        case KFSsubdir:
        !           864:                ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data;
        !           865:                vap->va_nlink = ks->ks_dirs;
        !           866:                vap->va_bytes = vap->va_size = DEV_BSIZE;
        !           867:                break;
        !           868:
1.98      darcy     869:        case KFSnull:
                    870:        case KFStime:
                    871:        case KFSint:
                    872:        case KFSstring:
                    873:        case KFShostname:
                    874:        case KFSavenrun:
                    875:        case KFSdevice:
                    876:        case KFSmsgbuf:
1.90      itojun    877: #ifdef IPSEC
1.98      darcy     878:        case KFSipsecsa:
                    879:        case KFSipsecsp:
1.1       cgd       880: #endif
                    881:                vap->va_nlink = 1;
1.84      jdolecek  882:                total = 0;
                    883:                do {
                    884:                        buf = strbuf;
1.90      itojun    885:                        error = kernfs_xread(kfs, total, &buf,
                    886:                            sizeof(strbuf), &nread);
1.84      jdolecek  887:                        total += nread;
                    888:                } while (error == 0 && nread != 0);
1.90      itojun    889:                vap->va_bytes = vap->va_size = total;
                    890:                break;
                    891:
                    892: #ifdef IPSEC
1.98      darcy     893:        case KFSipsecsadir:
                    894:        case KFSipsecspdir:
1.90      itojun    895:                vap->va_nlink = 2;
                    896:                vap->va_bytes = vap->va_size = DEV_BSIZE;
                    897:                break;
                    898: #endif
                    899:
                    900:        default:
1.102   ! cl        901:                error = kernfs_try_fileop(kfs->kfs_type,
        !           902:                    KERNFS_FILEOP_GETATTR, v, EINVAL);
1.90      itojun    903:                break;
1.1       cgd       904:        }
                    905:
                    906:        return (error);
                    907: }
                    908:
1.41      christos  909: /*ARGSUSED*/
                    910: int
                    911: kernfs_setattr(v)
                    912:        void *v;
1.1       cgd       913: {
1.90      itojun    914:
1.1       cgd       915:        /*
1.17      cgd       916:         * Silently ignore attribute changes.
                    917:         * This allows for open with truncate to have no
                    918:         * effect until some data is written.  I want to
                    919:         * do it this way because all writes are atomic.
1.1       cgd       920:         */
1.17      cgd       921:        return (0);
1.1       cgd       922: }
                    923:
1.28      mycroft   924: int
1.41      christos  925: kernfs_read(v)
                    926:        void *v;
                    927: {
1.23      mycroft   928:        struct vop_read_args /* {
                    929:                struct vnode *a_vp;
                    930:                struct uio *a_uio;
                    931:                int  a_ioflag;
                    932:                struct ucred *a_cred;
1.41      christos  933:        } */ *ap = v;
1.23      mycroft   934:        struct uio *uio = ap->a_uio;
1.90      itojun    935:        struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1.28      mycroft   936:        char strbuf[KSTRING], *buf;
1.82      jdolecek  937:        off_t off;
                    938:        size_t len;
1.28      mycroft   939:        int error;
1.23      mycroft   940:
1.90      itojun    941:        if (ap->a_vp->v_type == VDIR)
1.23      mycroft   942:                return (EOPNOTSUPP);
                    943:
1.28      mycroft   944:        off = uio->uio_offset;
1.82      jdolecek  945:        buf = strbuf;
1.90      itojun    946:        if ((error = kernfs_xread(kfs, off, &buf, sizeof(strbuf), &len)) == 0)
1.82      jdolecek  947:                error = uiomove(buf, len, uio);
                    948:        return (error);
1.1       cgd       949: }
                    950:
1.102   ! cl        951: static int
        !           952: kernfs_default_xwrite(v)
1.41      christos  953:        void *v;
                    954: {
1.23      mycroft   955:        struct vop_write_args /* {
                    956:                struct vnode *a_vp;
                    957:                struct uio *a_uio;
                    958:                int  a_ioflag;
                    959:                struct ucred *a_cred;
1.41      christos  960:        } */ *ap = v;
1.90      itojun    961:        struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1.23      mycroft   962:        struct uio *uio = ap->a_uio;
                    963:        int error, xlen;
1.1       cgd       964:        char strbuf[KSTRING];
1.23      mycroft   965:
1.1       cgd       966:        if (uio->uio_offset != 0)
                    967:                return (EINVAL);
                    968:
                    969:        xlen = min(uio->uio_resid, KSTRING-1);
1.41      christos  970:        if ((error = uiomove(strbuf, xlen, uio)) != 0)
1.1       cgd       971:                return (error);
                    972:
                    973:        if (uio->uio_resid != 0)
                    974:                return (EIO);
                    975:
                    976:        strbuf[xlen] = '\0';
1.17      cgd       977:        xlen = strlen(strbuf);
1.90      itojun    978:        return (kernfs_xwrite(kfs, strbuf, xlen));
1.1       cgd       979: }
                    980:
1.102   ! cl        981: int
        !           982: kernfs_write(v)
        !           983:        void *v;
        !           984: {
        !           985:        struct vop_write_args /* {
        !           986:                struct vnode *a_vp;
        !           987:                struct uio *a_uio;
        !           988:                int  a_ioflag;
        !           989:                struct ucred *a_cred;
        !           990:        } */ *ap = v;
        !           991:        struct kernfs_node *kfs = VTOKERN(ap->a_vp);
        !           992:
        !           993:        return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_WRITE, v, 0);
        !           994: }
        !           995:
        !           996: int
        !           997: kernfs_ioctl(v)
        !           998:        void *v;
        !           999: {
        !          1000:        struct vop_ioctl_args /* {
        !          1001:                const struct vnodeop_desc *a_desc;
        !          1002:                struct vnode *a_vp;
        !          1003:                u_long a_command;
        !          1004:                void *a_data;
        !          1005:                int a_fflag;
        !          1006:                struct ucred *a_cred;
        !          1007:                struct proc *a_p;
        !          1008:        } */ *ap = v;
        !          1009:        struct kernfs_node *kfs = VTOKERN(ap->a_vp);
        !          1010:
        !          1011:        return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_IOCTL, v,
        !          1012:            EPASSTHROUGH);
        !          1013: }
        !          1014:
        !          1015: int
        !          1016: kernfs_mmap(v)
        !          1017:        void *v;
        !          1018: {
        !          1019:        struct vop_mmap_args /* {
        !          1020:                const struct vnodeop_desc *a_desc;
        !          1021:                struct vnode *a_vp;
        !          1022:                int a_fflags;
        !          1023:                struct ucred *a_cred;
        !          1024:                struct proc *a_p;
        !          1025:        } */ *ap = v;
        !          1026:        struct kernfs_node *kfs = VTOKERN(ap->a_vp);
        !          1027:
        !          1028:        return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_MMAP, v, 0);
        !          1029: }
        !          1030:
1.101     cl       1031: static int
                   1032: kernfs_setdirentfileno_kt(struct dirent *d, const struct kern_target *kt,
                   1033:     u_int32_t value, struct vop_readdir_args *ap)
                   1034: {
                   1035:        struct kernfs_node *kfs;
                   1036:        struct vnode *vp;
                   1037:        int error;
                   1038:
                   1039:        if ((error = kernfs_allocvp(ap->a_vp->v_mount, &vp, kt->kt_tag, kt,
                   1040:            value)) != 0)
                   1041:                return error;
                   1042:        if (kt->kt_tag == KFSdevice) {
                   1043:                struct vattr va;
                   1044:                if ((error = VOP_GETATTR(vp, &va, ap->a_cred,
                   1045:                    ap->a_uio->uio_segflg == UIO_USERSPACE ?
                   1046:                    ap->a_uio->uio_procp : &proc0)) != 0)
                   1047:                        return (error);
                   1048:                d->d_fileno = va.va_fileid;
                   1049:        } else {
                   1050:                kfs = VTOKERN(vp);
                   1051:                d->d_fileno = kfs->kfs_fileno;
                   1052:        }
                   1053:        vput(vp);
                   1054:        return 0;
                   1055: }
                   1056:
                   1057: static int
                   1058: kernfs_setdirentfileno(struct dirent *d, off_t entry,
                   1059:     struct kernfs_node *thisdir_kfs, const struct kern_target *parent_kt,
                   1060:     const struct kern_target *kt, struct vop_readdir_args *ap)
                   1061: {
                   1062:        const struct kern_target *ikt;
                   1063:        int error;
                   1064:
                   1065:        switch (entry) {
                   1066:        case 0:
                   1067:                d->d_fileno = thisdir_kfs->kfs_fileno;
                   1068:                return 0;
                   1069:        case 1:
                   1070:                ikt = parent_kt;
                   1071:                break;
                   1072:        default:
                   1073:                ikt = kt;
                   1074:                break;
                   1075:        }
                   1076:        if (ikt != thisdir_kfs->kfs_kt) {
                   1077:                if ((error = kernfs_setdirentfileno_kt(d, ikt, 0, ap)) != 0)
                   1078:                        return error;
                   1079:        } else
                   1080:                d->d_fileno = thisdir_kfs->kfs_fileno;
                   1081:        return 0;
                   1082: }
                   1083:
1.41      christos 1084: int
                   1085: kernfs_readdir(v)
                   1086:        void *v;
                   1087: {
1.23      mycroft  1088:        struct vop_readdir_args /* {
                   1089:                struct vnode *a_vp;
                   1090:                struct uio *a_uio;
                   1091:                struct ucred *a_cred;
1.26      mycroft  1092:                int *a_eofflag;
1.57      fvdl     1093:                off_t **a_cookies;
                   1094:                int a_*ncookies;
1.41      christos 1095:        } */ *ap = v;
1.23      mycroft  1096:        struct uio *uio = ap->a_uio;
1.37      mycroft  1097:        struct dirent d;
1.90      itojun   1098:        struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1.75      jdolecek 1099:        const struct kern_target *kt;
1.102   ! cl       1100:        const struct dyn_kern_target *dkt = NULL;
        !          1101:        const struct kernfs_subdir *ks;
        !          1102:        off_t i, j;
1.1       cgd      1103:        int error;
1.57      fvdl     1104:        off_t *cookies = NULL;
1.90      itojun   1105:        int ncookies = 0, n;
                   1106: #ifdef IPSEC
                   1107:        struct secasvar *sav, *sav2;
                   1108:        struct secpolicy *sp;
                   1109: #endif
1.23      mycroft  1110:
1.37      mycroft  1111:        if (uio->uio_resid < UIO_MX)
                   1112:                return (EINVAL);
1.38      mycroft  1113:        if (uio->uio_offset < 0)
1.37      mycroft  1114:                return (EINVAL);
1.26      mycroft  1115:
1.1       cgd      1116:        error = 0;
1.38      mycroft  1117:        i = uio->uio_offset;
1.90      itojun   1118:        memset(&d, 0, sizeof(d));
                   1119:        d.d_reclen = UIO_MX;
                   1120:        ncookies = uio->uio_resid / UIO_MX;
                   1121:
                   1122:        switch (kfs->kfs_type) {
1.98      darcy    1123:        case KFSkern:
1.90      itojun   1124:                if (i >= nkern_targets)
                   1125:                        return (0);
1.66      sommerfe 1126:
1.90      itojun   1127:                if (ap->a_ncookies) {
                   1128:                        ncookies = min(ncookies, (nkern_targets - i));
                   1129:                        cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
                   1130:                            M_WAITOK);
                   1131:                        *ap->a_cookies = cookies;
                   1132:                }
                   1133:
                   1134:                n = 0;
                   1135:                for (; i < nkern_targets && uio->uio_resid >= UIO_MX; i++) {
1.102   ! cl       1136:                        if (i < static_nkern_targets)
        !          1137:                                kt = &kern_targets[i];
        !          1138:                        else {
        !          1139:                                if (dkt == NULL) {
        !          1140:                                        dkt = SIMPLEQ_FIRST(&dyn_kern_targets);
        !          1141:                                        for (j = static_nkern_targets; j < i &&
        !          1142:                                                     dkt != NULL; j++)
        !          1143:                                                dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
        !          1144:                                        if (j != i)
        !          1145:                                                break;
        !          1146:                                } else {
        !          1147:                                        dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
        !          1148:                                        if (dkt == NULL)
        !          1149:                                                break;
        !          1150:                                }
        !          1151:                                kt = &dkt->dkt_kt;
        !          1152:                        }
1.98      darcy    1153:                        if (kt->kt_tag == KFSdevice) {
1.94      itojun   1154:                                dev_t *dp = kt->kt_data;
                   1155:                                struct vnode *fvp;
                   1156:
                   1157:                                if (*dp == NODEV ||
                   1158:                                    !vfinddev(*dp, kt->kt_vtype, &fvp))
                   1159:                                        continue;
                   1160:                        }
1.90      itojun   1161:                        d.d_namlen = kt->kt_namlen;
1.101     cl       1162:                        if ((error = kernfs_setdirentfileno(&d, i, kfs,
                   1163:                            &kern_targets[0], kt, ap)) != 0)
                   1164:                                break;
1.90      itojun   1165:                        memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
                   1166:                        d.d_type = kt->kt_type;
1.99      jrf      1167:                        if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1.90      itojun   1168:                                break;
                   1169:                        if (cookies)
                   1170:                                *cookies++ = i + 1;
                   1171:                        n++;
                   1172:                }
                   1173:                ncookies = n;
                   1174:                break;
                   1175:
1.98      darcy    1176:        case KFSroot:
1.90      itojun   1177:                if (i >= 2)
                   1178:                        return 0;
                   1179:
                   1180:                if (ap->a_ncookies) {
                   1181:                        ncookies = min(ncookies, (2 - i));
                   1182:                        cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
                   1183:                            M_WAITOK);
                   1184:                        *ap->a_cookies = cookies;
                   1185:                }
                   1186:
                   1187:                n = 0;
                   1188:                for (; i < 2 && uio->uio_resid >= UIO_MX; i++) {
                   1189:                        kt = &kern_targets[i];
                   1190:                        d.d_namlen = kt->kt_namlen;
                   1191:                        d.d_fileno = KERNFS_FILENO(kt, kt->kt_tag, 0);
                   1192:                        memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
                   1193:                        d.d_type = kt->kt_type;
1.99      jrf      1194:                        if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1.90      itojun   1195:                                break;
                   1196:                        if (cookies)
                   1197:                                *cookies++ = i + 1;
                   1198:                        n++;
                   1199:                }
                   1200:                ncookies = n;
                   1201:                break;
                   1202:
1.102   ! cl       1203:        case KFSsubdir:
        !          1204:                ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data;
        !          1205:                if (i >= ks->ks_nentries)
        !          1206:                        return (0);
        !          1207:
        !          1208:                if (ap->a_ncookies) {
        !          1209:                        ncookies = min(ncookies, (ks->ks_nentries - i));
        !          1210:                        cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
        !          1211:                            M_WAITOK);
        !          1212:                        *ap->a_cookies = cookies;
        !          1213:                }
        !          1214:
        !          1215:                dkt = SIMPLEQ_FIRST(&ks->ks_entries);
        !          1216:                for (j = 0; j < i && dkt != NULL; j++)
        !          1217:                        dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
        !          1218:                n = 0;
        !          1219:                for (; i < ks->ks_nentries && uio->uio_resid >= UIO_MX; i++) {
        !          1220:                        if (i < 2)
        !          1221:                                kt = &subdir_targets[i];
        !          1222:                        else {
        !          1223:                                /* check if ks_nentries lied to us */
        !          1224:                                if (dkt == NULL)
        !          1225:                                        break;
        !          1226:                                kt = &dkt->dkt_kt;
        !          1227:                                dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
        !          1228:                        }
        !          1229:                        if (kt->kt_tag == KFSdevice) {
        !          1230:                                dev_t *dp = kt->kt_data;
        !          1231:                                struct vnode *fvp;
        !          1232:
        !          1233:                                if (*dp == NODEV ||
        !          1234:                                    !vfinddev(*dp, kt->kt_vtype, &fvp))
        !          1235:                                        continue;
        !          1236:                        }
        !          1237:                        d.d_namlen = kt->kt_namlen;
        !          1238:                        if ((error = kernfs_setdirentfileno(&d, i, kfs,
        !          1239:                            ks->ks_parent, kt, ap)) != 0)
        !          1240:                                break;
        !          1241:                        memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
        !          1242:                        d.d_type = kt->kt_type;
        !          1243:                        if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
        !          1244:                                break;
        !          1245:                        if (cookies)
        !          1246:                                *cookies++ = i + 1;
        !          1247:                        n++;
        !          1248:                }
        !          1249:                ncookies = n;
        !          1250:                break;
        !          1251:
1.90      itojun   1252: #ifdef IPSEC
1.98      darcy    1253:        case KFSipsecsadir:
1.90      itojun   1254:                /* count SA in the system */
                   1255:                n = 0;
                   1256:                TAILQ_FOREACH(sav, &satailq, tailq) {
                   1257:                        for (sav2 = TAILQ_FIRST(&satailq);
                   1258:                            sav2 != sav;
                   1259:                            sav2 = TAILQ_NEXT(sav2, tailq)) {
                   1260:                                if (sav->spi == sav2->spi) {
                   1261:                                        /* multiple SA with same SPI */
                   1262:                                        break;
                   1263:                                }
                   1264:                        }
                   1265:                        if (sav == sav2 || sav->spi != sav2->spi)
                   1266:                                n++;
                   1267:                }
1.37      mycroft  1268:
1.90      itojun   1269:                if (i >= nipsecsa_targets + n)
                   1270:                        return (0);
1.57      fvdl     1271:
1.90      itojun   1272:                if (ap->a_ncookies) {
                   1273:                        ncookies = min(ncookies, (n - i));
                   1274:                        cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
                   1275:                            M_WAITOK);
                   1276:                        *ap->a_cookies = cookies;
                   1277:                }
1.26      mycroft  1278:
1.90      itojun   1279:                n = 0;
                   1280:                for (; i < nipsecsa_targets && uio->uio_resid >= UIO_MX; i++) {
                   1281:                        kt = &ipsecsa_targets[i];
                   1282:                        d.d_namlen = kt->kt_namlen;
1.101     cl       1283:                        if ((error = kernfs_setdirentfileno(&d, i, kfs,
                   1284:                            &kern_targets[0], kt, ap)) != 0)
                   1285:                                break;
1.90      itojun   1286:                        memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
                   1287:                        d.d_type = kt->kt_type;
1.99      jrf      1288:                        if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1.90      itojun   1289:                                break;
                   1290:                        if (cookies)
                   1291:                                *cookies++ = i + 1;
                   1292:                        n++;
                   1293:                }
                   1294:                if (error) {
                   1295:                        ncookies = n;
                   1296:                        break;
                   1297:                }
1.26      mycroft  1298:
1.90      itojun   1299:                TAILQ_FOREACH(sav, &satailq, tailq) {
                   1300:                        for (sav2 = TAILQ_FIRST(&satailq);
                   1301:                            sav2 != sav;
                   1302:                            sav2 = TAILQ_NEXT(sav2, tailq)) {
                   1303:                                if (sav->spi == sav2->spi) {
                   1304:                                        /* multiple SA with same SPI */
                   1305:                                        break;
                   1306:                                }
                   1307:                        }
                   1308:                        if (sav != sav2 && sav->spi == sav2->spi)
1.23      mycroft  1309:                                continue;
1.90      itojun   1310:                        if (uio->uio_resid < UIO_MX)
                   1311:                                break;
1.101     cl       1312:                        if ((error = kernfs_setdirentfileno_kt(&d, &ipsecsa_kt,
                   1313:                            sav->spi, ap)) != 0)
                   1314:                                break;
1.90      itojun   1315:                        d.d_namlen = snprintf(d.d_name, sizeof(d.d_name),
                   1316:                            "%u", ntohl(sav->spi));
                   1317:                        d.d_type = DT_REG;
1.99      jrf      1318:                        if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1.90      itojun   1319:                                break;
                   1320:                        if (cookies)
                   1321:                                *cookies++ = i + 1;
                   1322:                        n++;
                   1323:                        i++;
1.23      mycroft  1324:                }
1.90      itojun   1325:                ncookies = n;
                   1326:                break;
                   1327:
1.98      darcy    1328:        case KFSipsecspdir:
1.90      itojun   1329:                /* count SP in the system */
                   1330:                n = 0;
                   1331:                TAILQ_FOREACH(sp, &sptailq, tailq)
                   1332:                        n++;
1.26      mycroft  1333:
1.102   ! cl       1334:                if (i >= nipsecsp_targets + n)
1.90      itojun   1335:                        return (0);
                   1336:
                   1337:                if (ap->a_ncookies) {
                   1338:                        ncookies = min(ncookies, (n - i));
                   1339:                        cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
                   1340:                            M_WAITOK);
                   1341:                        *ap->a_cookies = cookies;
                   1342:                }
1.26      mycroft  1343:
1.90      itojun   1344:                n = 0;
                   1345:                for (; i < nipsecsp_targets && uio->uio_resid >= UIO_MX; i++) {
                   1346:                        kt = &ipsecsp_targets[i];
                   1347:                        d.d_namlen = kt->kt_namlen;
1.101     cl       1348:                        if ((error = kernfs_setdirentfileno(&d, i, kfs,
                   1349:                            &kern_targets[0], kt, ap)) != 0)
                   1350:                                break;
1.90      itojun   1351:                        memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
                   1352:                        d.d_type = kt->kt_type;
1.99      jrf      1353:                        if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1.90      itojun   1354:                                break;
                   1355:                        if (cookies)
                   1356:                                *cookies++ = i + 1;
                   1357:                        n++;
                   1358:                }
                   1359:                if (error) {
                   1360:                        ncookies = n;
1.1       cgd      1361:                        break;
1.57      fvdl     1362:                }
1.90      itojun   1363:
                   1364:                TAILQ_FOREACH(sp, &sptailq, tailq) {
                   1365:                        if (uio->uio_resid < UIO_MX)
                   1366:                                break;
1.101     cl       1367:                        if ((error = kernfs_setdirentfileno_kt(&d, &ipsecsp_kt,
                   1368:                            sp->id, ap)) != 0)
                   1369:                                break;
1.90      itojun   1370:                        d.d_namlen = snprintf(d.d_name, sizeof(d.d_name),
                   1371:                            "%u", sp->id);
                   1372:                        d.d_type = DT_REG;
1.99      jrf      1373:                        if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1.90      itojun   1374:                                break;
                   1375:                        if (cookies)
                   1376:                                *cookies++ = i + 1;
                   1377:                        n++;
                   1378:                        i++;
                   1379:                }
                   1380:                ncookies = n;
                   1381:                break;
                   1382: #endif
                   1383:
                   1384:        default:
                   1385:                error = ENOTDIR;
                   1386:                break;
1.57      fvdl     1387:        }
                   1388:
                   1389:        if (ap->a_ncookies) {
                   1390:                if (error) {
1.90      itojun   1391:                        if (cookies)
                   1392:                                free(*ap->a_cookies, M_TEMP);
1.57      fvdl     1393:                        *ap->a_ncookies = 0;
                   1394:                        *ap->a_cookies = NULL;
                   1395:                } else
                   1396:                        *ap->a_ncookies = ncookies;
1.1       cgd      1397:        }
                   1398:
1.38      mycroft  1399:        uio->uio_offset = i;
1.1       cgd      1400:        return (error);
                   1401: }
                   1402:
1.41      christos 1403: int
                   1404: kernfs_inactive(v)
                   1405:        void *v;
                   1406: {
1.23      mycroft  1407:        struct vop_inactive_args /* {
                   1408:                struct vnode *a_vp;
1.57      fvdl     1409:                struct proc *a_p;
1.41      christos 1410:        } */ *ap = v;
1.23      mycroft  1411:        struct vnode *vp = ap->a_vp;
1.90      itojun   1412:        const struct kernfs_node *kfs = VTOKERN(ap->a_vp);
                   1413: #ifdef IPSEC
                   1414:        struct mbuf *m;
                   1415:        struct secpolicy *sp;
                   1416: #endif
1.23      mycroft  1417:
1.90      itojun   1418:        VOP_UNLOCK(vp, 0);
                   1419:        switch (kfs->kfs_type) {
                   1420: #ifdef IPSEC
1.98      darcy    1421:        case KFSipsecsa:
1.90      itojun   1422:                m = key_setdumpsa_spi(htonl(kfs->kfs_value));
                   1423:                if (m)
                   1424:                        m_freem(m);
1.91      itojun   1425:                else
1.90      itojun   1426:                        vgone(vp);
                   1427:                break;
1.98      darcy    1428:        case KFSipsecsp:
1.90      itojun   1429:                sp = key_getspbyid(kfs->kfs_value);
                   1430:                if (sp)
                   1431:                        key_freesp(sp);
                   1432:                else {
                   1433:                        /* should never happen as we hold a refcnt */
                   1434:                        vgone(vp);
                   1435:                }
                   1436:                break;
1.23      mycroft  1437: #endif
1.90      itojun   1438:        default:
                   1439:                break;
                   1440:        }
1.23      mycroft  1441:        return (0);
                   1442: }
                   1443:
1.41      christos 1444: int
                   1445: kernfs_reclaim(v)
                   1446:        void *v;
                   1447: {
1.23      mycroft  1448:        struct vop_reclaim_args /* {
                   1449:                struct vnode *a_vp;
1.41      christos 1450:        } */ *ap = v;
1.23      mycroft  1451:
1.90      itojun   1452:        return (kernfs_freevp(ap->a_vp));
1.1       cgd      1453: }
                   1454:
                   1455: /*
1.23      mycroft  1456:  * Return POSIX pathconf information applicable to special devices.
                   1457:  */
1.41      christos 1458: int
                   1459: kernfs_pathconf(v)
                   1460:        void *v;
                   1461: {
1.23      mycroft  1462:        struct vop_pathconf_args /* {
                   1463:                struct vnode *a_vp;
                   1464:                int a_name;
1.29      cgd      1465:                register_t *a_retval;
1.41      christos 1466:        } */ *ap = v;
1.23      mycroft  1467:
                   1468:        switch (ap->a_name) {
                   1469:        case _PC_LINK_MAX:
                   1470:                *ap->a_retval = LINK_MAX;
                   1471:                return (0);
                   1472:        case _PC_MAX_CANON:
                   1473:                *ap->a_retval = MAX_CANON;
                   1474:                return (0);
                   1475:        case _PC_MAX_INPUT:
                   1476:                *ap->a_retval = MAX_INPUT;
                   1477:                return (0);
                   1478:        case _PC_PIPE_BUF:
                   1479:                *ap->a_retval = PIPE_BUF;
                   1480:                return (0);
                   1481:        case _PC_CHOWN_RESTRICTED:
                   1482:                *ap->a_retval = 1;
                   1483:                return (0);
                   1484:        case _PC_VDISABLE:
                   1485:                *ap->a_retval = _POSIX_VDISABLE;
1.59      kleink   1486:                return (0);
                   1487:        case _PC_SYNC_IO:
                   1488:                *ap->a_retval = 1;
1.23      mycroft  1489:                return (0);
                   1490:        default:
                   1491:                return (EINVAL);
                   1492:        }
                   1493:        /* NOTREACHED */
                   1494: }
                   1495:
                   1496: /*
                   1497:  * Print out the contents of a /dev/fd vnode.
1.1       cgd      1498:  */
                   1499: /* ARGSUSED */
1.41      christos 1500: int
                   1501: kernfs_print(v)
                   1502:        void *v;
1.23      mycroft  1503: {
                   1504:
1.47      christos 1505:        printf("tag VT_KERNFS, kernfs vnode\n");
1.23      mycroft  1506:        return (0);
                   1507: }
                   1508:
1.40      mycroft  1509: int
1.41      christos 1510: kernfs_link(v)
                   1511:        void *v;
                   1512: {
1.40      mycroft  1513:        struct vop_link_args /* {
                   1514:                struct vnode *a_dvp;
                   1515:                struct vnode *a_vp;
                   1516:                struct componentname *a_cnp;
1.41      christos 1517:        } */ *ap = v;
1.40      mycroft  1518:
                   1519:        VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
                   1520:        vput(ap->a_dvp);
                   1521:        return (EROFS);
                   1522: }
                   1523:
                   1524: int
1.41      christos 1525: kernfs_symlink(v)
                   1526:        void *v;
                   1527: {
1.40      mycroft  1528:        struct vop_symlink_args /* {
                   1529:                struct vnode *a_dvp;
                   1530:                struct vnode **a_vpp;
                   1531:                struct componentname *a_cnp;
                   1532:                struct vattr *a_vap;
                   1533:                char *a_target;
1.41      christos 1534:        } */ *ap = v;
1.40      mycroft  1535:
                   1536:        VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
                   1537:        vput(ap->a_dvp);
                   1538:        return (EROFS);
1.1       cgd      1539: }

CVSweb <webmaster@jp.NetBSD.org>