]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/miscfs/synthfs/synthfs_vnops.c
xnu-1456.1.26.tar.gz
[apple/xnu.git] / bsd / miscfs / synthfs / synthfs_vnops.c
diff --git a/bsd/miscfs/synthfs/synthfs_vnops.c b/bsd/miscfs/synthfs/synthfs_vnops.c
deleted file mode 100644 (file)
index d409494..0000000
+++ /dev/null
@@ -1,1327 +0,0 @@
-/*
- * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- * 
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- * 
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-/*
- * Copyright (c) 1998-1999 Apple Computer, Inc. All Rights Reserved.
- *
- *     Modification History:
- *
- *     02-Feb-2000     Clark Warner    Added copyfile to table 
- *     17-Aug-1999     Pat Dirks       New today.
- */
-
-#include <mach/mach_types.h>
-#include <mach/machine/boolean.h>
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/file.h>
-#include <sys/stat.h>
-#include <sys/proc.h>
-#include <sys/kauth.h>
-#include <sys/conf.h>
-#include <sys/mount_internal.h>
-#include <sys/vnode_internal.h>
-#include <sys/malloc.h>
-#include <sys/dirent.h>
-#include <sys/namei.h>
-#include <sys/attr.h>
-#include <sys/uio_internal.h>
-
-#include <sys/vm.h>
-#include <sys/errno.h>
-#include <vfs/vfs_support.h>
-
-#include "synthfs.h"
-
-#define RWSUPPORT 0
-
-#if RWSUPPORT
-#error NOT PORTED FOR UBC
-#include <sys/ubc.h>
-#endif
-
-static int synthfs_remove_internal(struct vnode *dvp, struct vnode *vp,
-                                   struct componentname *cnp, vfs_context_t context);
-
-
-#define VOPFUNC int (*)(void *)
-
-/* Global vfs data structures for synthfs. */
-int (**synthfs_vnodeop_p) (void *);
-struct vnodeopv_entry_desc synthfs_vnodeop_entries[] = {
-    {&vnop_default_desc, (VOPFUNC)vn_default_error},
-    {&vnop_strategy_desc, (VOPFUNC)err_strategy},              /* strategy             - not supported  */
-    {&vnop_bwrite_desc, (VOPFUNC)err_bwrite},                  /* bwrite               - not supported  */
-    {&vnop_lookup_desc, (VOPFUNC)synthfs_cached_lookup},       /* cached lookup */
-    {&vnop_create_desc, (VOPFUNC)synthfs_create},              /* create               - DEBUGGER */
-    {&vnop_whiteout_desc, (VOPFUNC)err_whiteout},              /* whiteout             - not supported  */
-    {&vnop_mknod_desc, (VOPFUNC)err_mknod},                    /* mknod                - not supported  */
-    {&vnop_open_desc, (VOPFUNC)synthfs_open},                  /* open                 - DEBUGGER */
-    {&vnop_close_desc, (VOPFUNC)nop_close},                    /* close                - NOP */
-    {&vnop_getattr_desc, (VOPFUNC)synthfs_getattr},            /* getattr */
-    {&vnop_setattr_desc, (VOPFUNC)synthfs_setattr},            /* setattr */
-    {&vnop_getattrlist_desc, (VOPFUNC)err_getattrlist},        /* getattrlist  - not supported  */
-    {&vnop_setattrlist_desc, (VOPFUNC)err_setattrlist},        /* setattrlist  - not supported  */
-    {&vnop_read_desc, (VOPFUNC)err_read},                      /* read                 - not supported  */
-    {&vnop_write_desc, (VOPFUNC)err_write},                    /* write                - not supported  */
-    {&vnop_ioctl_desc, (VOPFUNC)err_ioctl},                    /* ioctl                - not supported  */
-    {&vnop_select_desc, (VOPFUNC)synthfs_select},              /* select */
-    {&vnop_exchange_desc, (VOPFUNC)err_exchange},              /* exchange             - not supported  */
-    {&vnop_revoke_desc, (VOPFUNC)nop_revoke},                  /* revoke               - NOP */
-    {&vnop_mmap_desc, (VOPFUNC)synthfs_mmap},                  /* mmap                 - DEBUGGER */
-    {&vnop_fsync_desc, (VOPFUNC)nop_fsync},                    /* fsync                - NOP */
-    {&vnop_remove_desc, (VOPFUNC)synthfs_remove},              /* remove */
-    {&vnop_link_desc, (VOPFUNC)err_link},                      /* link                 - not supported  */
-    {&vnop_rename_desc, (VOPFUNC)synthfs_rename},              /* rename */
-    {&vnop_mkdir_desc, (VOPFUNC)synthfs_mkdir},                        /* mkdir */
-    {&vnop_rmdir_desc, (VOPFUNC)synthfs_rmdir},                        /* rmdir */
-    {&vnop_symlink_desc, (VOPFUNC)synthfs_symlink},            /* symlink */
-    {&vnop_readdir_desc, (VOPFUNC)synthfs_readdir},            /* readdir */
-    {&vnop_readdirattr_desc, (VOPFUNC)err_readdirattr},        /* readdirattr  - not supported  */
-    {&vnop_readlink_desc, (VOPFUNC)synthfs_readlink},          /* readlink */
-    {&vnop_inactive_desc, (VOPFUNC)synthfs_inactive},          /* inactive */
-    {&vnop_reclaim_desc, (VOPFUNC)synthfs_reclaim},            /* reclaim */
-    {&vnop_pathconf_desc, (VOPFUNC)synthfs_pathconf},          /* pathconf */
-    {&vnop_advlock_desc, (VOPFUNC)err_advlock},                        /* advlock              - not supported  */
-    {&vnop_allocate_desc, (VOPFUNC)err_allocate},              /* allocate             - not supported  */
-       {&vnop_pagein_desc, (VOPFUNC)err_pagein},               /* pagein               - not supported  */
-       {&vnop_pageout_desc, (VOPFUNC)err_pageout},             /* pageout              - not supported  */
-       {&vnop_searchfs_desc, (VOPFUNC)err_searchfs},           /* searchfs             - not supported */
-       {&vnop_copyfile_desc, (VOPFUNC)err_copyfile},           /* copyfile - not supported */
-       { &vnop_blktooff_desc, (VOPFUNC)err_blktooff },         /* blktooff not supported */
-       { &vnop_offtoblk_desc, (VOPFUNC)err_offtoblk },         /* offtoblk  not supported */
-       { &vnop_blockmap_desc, (VOPFUNC)err_blockmap },         /* blockmap  not supported */
-   {(struct vnodeop_desc *) NULL, (int (*) ()) NULL}
-};
-
-/*
- * Oh what a tangled web we weave.  This structure will be used by
- * bsd/vfs/vfs_conf.c to actually do the initialization of synthfs_vnodeop_p
- */
-struct vnodeopv_desc synthfs_vnodeop_opv_desc =
-{&synthfs_vnodeop_p, synthfs_vnodeop_entries};
-
-
-
-/*
- * Create a regular file
-#% create      dvp     L U U
-#% create      vpp     - L -
-#
- vnop_create {
-     IN WILLRELE struct vnode *dvp;
-     OUT struct vnode **vpp;
-     IN struct componentname *cnp;
-     IN struct vnode_attr *vap;
-       
-     We are responsible for freeing the namei buffer, it is done in hfs_makenode(), unless there is
-       a previous error.
-
-*/
-
-int
-synthfs_create(ap)
-struct vnop_create_args /* {
-    struct vnode *a_dvp;
-    struct vnode **a_vpp;
-    struct componentname *a_cnp;
-    struct vnode_attr *a_vap;
-    vfs_context_t a_context;
-} */ *ap;
-{
-#if DEBUG
-       struct vnode *dvp = ap->a_dvp;
-       char debugmsg[255];
-       
-       sprintf(debugmsg, "synthfs_create: attempt to create '%s' in '%s' ?!", ap->a_cnp->cn_nameptr, VTOS(dvp)->s_name);
-       Debugger(debugmsg);
-#endif
-
-       return err_create(ap);
-}
-
-
-
-/*
- * Open called.
-#% open                vp      L L L
-#
- vnop_open {
-     IN struct vnode *vp;
-     IN int mode;
-     IN vfs_context_t a_context;
- */
-
-int
-synthfs_open(ap)
-struct vnop_open_args /* {
-    struct vnode *a_vp;
-    int  a_mode;
-    vfs_context_t a_context;
-} */ *ap;
-{
-       struct vnode *vp = ap->a_vp;
-
-       if (vp->v_type == VDIR) {
-         return 0;
-       } else {
-#if DEBUG
-               struct synthfsnode *sp = VTOS(vp);
-               char debugmsg[255];
-       
-               sprintf(debugmsg, "synthfs_open: attempt to open '/%s' ?!", sp->s_name);
-               Debugger(debugmsg);
-#endif
-       };
-
-       return 0;
-}
-
-
-
-/*
- * Mmap a file
- *
- * NB Currently unsupported.
-# XXX - not used
-#
- vnop_mmap {
-     IN struct vnode *vp;
-     IN int fflags;
-     IN kauth_cred_t cred;
-     IN struct proc *p;
-
-     */
-
-/* ARGSUSED */
-
-int
-synthfs_mmap(__unused struct vnop_mmap_args *ap)
-{
-    return EINVAL;
-}
-
-
-
-/*
-#% getattr     vp      = = =
-#
- vnop_getattr {
-     IN struct vnode *vp;
-     IN struct vnode_attr *vap;
-     IN vfs_context_t context;
-
-*/
-int
-synthfs_getattr(ap)
-struct vnop_getattr_args /* {
-    struct vnode *a_vp;
-    struct vnode_attr *a_vap;
-    vfs_context_t a_context;
-} */ *ap;
-{
-       struct vnode *vp     = ap->a_vp;
-       struct vnode_attr *vap    = ap->a_vap;
-       struct synthfsnode *sp = VTOS(vp);
-
-       VATTR_RETURN(vap, va_type, vp->v_type);
-       VATTR_RETURN(vap, va_mode, sp->s_mode);
-       VATTR_RETURN(vap, va_nlink, sp->s_linkcount);
-       VATTR_RETURN(vap, va_uid, sp->s_uid);
-       VATTR_RETURN(vap, va_gid, sp->s_gid);
-       VATTR_RETURN(vap, va_fsid, VTOVFS(vp)->mnt_vfsstat.f_fsid.val[0]);
-       VATTR_RETURN(vap, va_fileid, sp->s_nodeid);
-       switch (vp->v_type) {
-       case VDIR:
-               VATTR_RETURN(vap, va_data_size, (sp->s_u.d.d_entrycount + 2) * sizeof(struct dirent));
-               break;
-         
-       case VREG:
-               VATTR_RETURN(vap, va_data_size, sp->s_u.f.f_size);
-               break;
-       
-       case VLNK:
-               VATTR_RETURN(vap, va_data_size, sp->s_u.s.s_length);
-               break;
-       
-       default:
-               VATTR_RETURN(vap, va_data_size, 0);
-       };
-       VATTR_RETURN(vap, va_iosize, 512);
-       vap->va_access_time.tv_sec = sp->s_accesstime.tv_sec;
-       vap->va_access_time.tv_nsec = sp->s_accesstime.tv_usec * 1000;
-       VATTR_SET_SUPPORTED(vap, va_access_time);
-       vap->va_modify_time.tv_sec = sp->s_modificationtime.tv_sec;
-       vap->va_modify_time.tv_nsec = sp->s_modificationtime.tv_usec * 1000;
-       VATTR_SET_SUPPORTED(vap, va_modify_time);
-       vap->va_change_time.tv_sec = sp->s_changetime.tv_sec;
-       vap->va_change_time.tv_nsec = sp->s_changetime.tv_usec * 1000;
-       VATTR_SET_SUPPORTED(vap, va_change_time);
-       VATTR_RETURN(vap, va_gen, sp->s_generation);
-       VATTR_RETURN(vap, va_flags, sp->s_flags);
-       VATTR_RETURN(vap, va_rdev, sp->s_rdev);
-       VATTR_RETURN(vap, va_filerev, 0);
-       VATTR_RETURN(vap, va_acl, NULL);
-
-       return (0);
-}
-
-
-
-/*
- * Change the mode on a file or directory.
- * vnode vp must be locked on entry.
- */
-int synthfs_chmod(struct vnode *vp, int mode, kauth_cred_t cred, struct proc *p)
-{
-    struct synthfsnode *sp = VTOS(vp);
-    int result;
-
-    sp->s_mode &= ~ALLPERMS;
-    sp->s_mode |= (mode & ALLPERMS);
-    sp->s_nodeflags |= IN_CHANGE;
-#if RWSUPPORT
-    if ((vp->v_flag & VTEXT) && (sp->s_mode & S_ISTXT) == 0) (void) vnode_uncache(vp);
-#endif
-
-    return 0;
-}
-
-
-
-/*
- * Change the flags on a file or directory.
- * vnode vp must be locked on entry.
- */
-int synthfs_chflags(struct vnode *vp, u_long flags, kauth_cred_t cred, struct proc *p)
-{
-    struct synthfsnode *sp = VTOS(vp);
-
-    sp->s_flags = flags;
-    sp->s_nodeflags |= IN_CHANGE;
-
-    return 0;
-}
-
-
-
-/*
- * Perform chown operation on vnode vp;
- * vnode vp must be locked on entry.
- */
-int synthfs_chown(struct vnode *vp, uid_t uid, gid_t gid, kauth_cred_t cred, struct proc *p)
-{
-    struct synthfsnode *sp = VTOS(vp);
-    uid_t ouid;
-    gid_t ogid;
-    int result = 0;
-    int is_member;
-
-    if (uid == (uid_t)VNOVAL) uid = sp->s_uid;
-    if (gid == (gid_t)VNOVAL) gid = sp->s_gid;
-
-    ogid = sp->s_gid;
-    ouid = sp->s_uid;
-
-    sp->s_gid = gid;
-    sp->s_uid = uid;
-
-    if (ouid != uid || ogid != gid) sp->s_nodeflags |= IN_CHANGE;
-    if (ouid != uid && suser(cred, NULL)) sp->s_mode &= ~S_ISUID;
-    if (ogid != gid && suser(cred, NULL)) sp->s_mode &= ~S_ISGID;
-
-    return 0;
-}
-
-
-
-/*
- * Set attribute vnode op. called from several syscalls
-#% setattr      vp      L L L
-#
- vnop_setattr {
-     IN struct vnode *vp;
-     IN struct vnode_attr *vap;
-     IN vfs_context_t context;
-     */
-
-int
-synthfs_setattr(ap)
-struct vnop_setattr_args /* {
-struct vnode *a_vp;
-struct vnode_attr *a_vap;
-vfs_context_t a_context;
-} */ *ap;
-{
-       struct vnode *vp = ap->a_vp;
-       struct synthfsnode *sp = VTOS(vp);
-       struct vnode_attr *vap = ap->a_vap;
-       kauth_cred_t cred = vfs_context_ucred(ap->a_context);
-       struct proc *p = vfs_context_proc(ap->a_context);
-       struct timeval atimeval, mtimeval;
-       uid_t nuid;
-       gid_t ngid;
-       int result;
-
-       result = 0;
-
-       if (VATTR_IS_ACTIVE(vap, va_flags)) {
-               if ((result = synthfs_chflags(vp, vap->va_flags, cred, p))) {
-                       goto Err_Exit;
-               }
-       }
-       VATTR_SET_SUPPORTED(vap, va_flags);
-
-       nuid = (uid_t)ngid = (gid_t)VNOVAL;
-       if (VATTR_IS_ACTIVE(vap, va_uid))
-               nuid = vap->va_uid;
-       if (VATTR_IS_ACTIVE(vap, va_gid))
-               ngid = vap->va_gid;
-       if (nuid != (uid_t)VNOVAL || ngid != (gid_t)VNOVAL) {
-               if ((result = synthfs_chown(vp, nuid, ngid, cred, p))) {
-                       goto Err_Exit;
-               }
-       }
-       VATTR_SET_SUPPORTED(vap, va_uid);
-       VATTR_SET_SUPPORTED(vap, va_gid);
-
-       if (VATTR_IS_ACTIVE(vap, va_data_size)) {
-#if RWSUPPORT
-               if ((result = vnode_setsize(vp, vap->va_data_size, 0, ap->a_context))) {
-                       goto Err_Exit;
-               };
-               VATTR_SET_SUPPORTED(vap, va_data_size);
-#else
-               result = EINVAL;
-               goto Err_Exit;
-#endif
-       }
-
-       sp = VTOS(vp);
-       if (VATTR_IS_ACTIVE(vap, va_access_time) || VATTR_IS_ACTIVE(vap, va_modify_time)) {
-               if (VATTR_IS_ACTIVE(vap, va_access_time)) {
-                       sp->s_nodeflags |= IN_ACCESS;
-                       atimeval.tv_sec = vap->va_access_time.tv_sec;
-                       atimeval.tv_usec = vap->va_access_time.tv_nsec / 1000;
-               }
-               if (VATTR_IS_ACTIVE(vap, va_modify_time)) {
-                       sp->s_nodeflags |= IN_CHANGE | IN_UPDATE;
-                       mtimeval.tv_sec = vap->va_modify_time.tv_sec;
-                       mtimeval.tv_usec = vap->va_modify_time.tv_nsec / 1000;
-               }
-               if ((result = synthfs_update(vp, &atimeval, &mtimeval, 1))) {
-                       goto Err_Exit;
-               }
-       }
-       VATTR_SET_SUPPORTED(vap, va_access_time);
-       VATTR_SET_SUPPORTED(vap, va_modify_time);
-
-       if (VATTR_IS_ACTIVE(vap, va_mode))
-               result = synthfs_chmod(vp, (int)vap->va_mode, cred, p);
-       VATTR_SET_SUPPORTED(vap, va_mode);
-
-       Err_Exit:
-
-       DBG_VOP(("synthfs_setattr: returning %d...\n", result));
-
-       return (result);
-}
-
-
-
-/*
-
-#% rename      sourcePar_vp    U U U
-#% rename      source_vp               U U U
-#% rename      targetPar_vp    L U U
-#% rename      target_vp               X U U
-#
- vnop_rename {
-     IN WILLRELE struct vnode *sourcePar_vp;
-     IN WILLRELE struct vnode *source_vp;
-     IN struct componentname *source_cnp;
-     IN WILLRELE struct vnode *targetPar_vp;
-     IN WILLRELE struct vnode *target_vp;
-     IN struct componentname *target_cnp;
-
-
- */
-/*
- * On entry:
- *     source's parent directory is unlocked
- *     source file or directory is unlocked
- *     destination's parent directory is locked
- *     destination file or directory is locked if it exists
- *
- * On exit:
- *     all denodes should be released
- *
- */
-
-int
-synthfs_rename(ap)
-struct vnop_rename_args  /* {
-    struct vnode *a_fdvp;
-    struct vnode *a_fvp;
-    struct componentname *a_fcnp;
-    struct vnode *a_tdvp;
-    struct vnode *a_tvp;
-    struct componentname *a_tcnp;
-    vfs_context_t a_context;
-} */ *ap;
-{
-       struct vnode                    *target_vp = ap->a_tvp;
-       struct vnode                    *targetPar_vp = ap->a_tdvp;
-       struct vnode                    *source_vp = ap->a_fvp;
-       struct vnode                    *sourcePar_vp = ap->a_fdvp;
-       struct componentname    *target_cnp = ap->a_tcnp;
-       struct componentname    *source_cnp = ap->a_fcnp;
-       struct synthfsnode              *target_sp, *targetPar_sp, *source_sp, *sourcePar_sp;
-       u_short                                 doingdirectory = 0, oldparent = 0, newparent = 0;
-       int                                             retval = 0;
-       struct timeval                  tv;
-
-#if SYNTHFS_DIAGNOSTIC
-    if ((target_cnp->cn_flags & HASBUF) == 0 ||
-        (source_cnp->cn_flags & HASBUF) == 0)
-        panic("synthfs_rename: no name");
-#endif
-
-       DBG_ASSERT((ap->a_fdvp->v_type == VDIR) && (ap->a_tdvp->v_type == VDIR));
-       target_sp = targetPar_sp = source_sp = sourcePar_sp = NULL;
-
-
-       sourcePar_sp = VTOS(sourcePar_vp);
-       source_sp = VTOS(source_vp);
-       oldparent = sourcePar_sp->s_nodeid;
-
-       /*
-        * Be sure we are not renaming ".", "..", or an alias of ".". This
-        * leads to a crippled directory tree.  It's pretty tough to do a
-        * "ls" or "pwd" with the "." directory entry missing, and "cd .."
-        * doesn't work if the ".." entry is missing.
-        */
-       if (source_sp->s_type == SYNTHFS_DIRECTORY) {
-               if ((source_cnp->cn_namelen == 1 && source_cnp->cn_nameptr[0] == '.')
-                       || sourcePar_sp == source_sp
-                       || (source_cnp->cn_flags & ISDOTDOT)
-                       || (source_sp->s_nodeflags & IN_RENAME)) {
-                       retval = EINVAL;
-                       goto abortit;
-               }
-               source_sp->s_nodeflags |= IN_RENAME;
-               doingdirectory = TRUE;
-       }
-
-       /* Transit between abort and bad */
-
-    targetPar_sp = VTOS(targetPar_vp);
-    target_sp = target_vp ? VTOS(target_vp) : NULL;
-    newparent = targetPar_sp->s_nodeid;
-
-
-       /*
-        * If the destination exists, then be sure its type (file or dir)
-        * matches that of the source.  And, if it is a directory make sure
-        * it is empty.  Then delete the destination.
-        */
-       if (target_vp) {
-
-#if RWSUPPORT
-               if (target_vp->v_type == VREG) {
-                       (void) vnode_uncache(target_vp);
-               };
-#endif
-               cache_purge(target_vp);
-            
-               retval = synthfs_remove_internal(targetPar_vp, target_vp, target_cnp, ap->a_context);
-
-               target_vp = NULL;
-               target_sp = NULL;               
-               
-               if (retval) goto bad;
-       };
-
-
-       /* remove the existing entry from the namei cache: */
-       if (source_vp->v_type == VREG) cache_purge(source_vp);
-
-       retval = synthfs_move_rename_entry( source_vp, targetPar_vp, target_cnp->cn_nameptr);
-
-       if (retval) goto bad;
-
-       source_sp->s_nodeflags &= ~IN_RENAME;
-
-       /*
-        * Timestamp both parent directories.
-        * Note that if this is a rename within the same directory,
-        * (where targetPar_hp == sourcePar_hp)
-        * the code below is still safe and correct.
-        */
-       targetPar_sp->s_nodeflags |= IN_UPDATE;
-       sourcePar_sp->s_nodeflags |= IN_UPDATE;
-       
-       microtime(&tv);
-       SYNTHFSTIMES(targetPar_sp, &tv, &tv);
-       SYNTHFSTIMES(sourcePar_sp, &tv, &tv);
-
-       return (retval);
-
-bad:;
-       if (retval && doingdirectory)
-               source_sp->s_nodeflags &= ~IN_RENAME;
-
-       return (retval);
-
-abortit:;
-       return (retval);
-}
-
-
-
-/*
- * Mkdir system call
-
-#% mkdir       dvp     L U U
-#% mkdir       vpp     - L -
-#
- vnop_mkdir {
-     IN WILLRELE struct vnode *dvp;
-     OUT struct vnode **vpp;
-     IN struct componentname *cnp;
-     IN struct vnode_attr *vap;
-     IN vfs_context_t context;
-
-     We are responsible for freeing the namei buffer, it is done in synthfs_makenode(), unless there is
-    a previous error.
-
-*/
-
-int
-synthfs_mkdir(ap)
-struct vnop_mkdir_args /* {
-    struct vnode *a_dvp;
-    struct vnode **a_vpp;
-    struct componentname *a_cnp;
-    struct vnode_attr *a_vap;
-    vfs_context_t a_context;
-} */ *ap;
-{
-       int retval;
-       struct vnode *dvp = ap->a_dvp;
-       struct componentname *cnp = ap->a_cnp;
-       int mode = MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode);
-       struct vnode *vp = NULL;
-
-       *ap->a_vpp = NULL;
-
-       retval = synthfs_new_directory(VTOVFS(dvp), dvp, cnp->cn_nameptr, VTOSFS(dvp)->synthfs_nextid++, mode, vfs_context_proc(cnp->cn_context), &vp);
-       if (retval) goto Error_Exit;
-
-       *ap->a_vpp = vp;
-
-       retval = vnode_setattr(vp, ap->a_vap, ap->a_context);
-       if (retval != 0) goto Error_Exit;
-
-       Error_Exit:;
-       if (retval != 0) {
-               if (vp) synthfs_remove_directory(vp);
-       }
-
-       return retval;
-}
-
-
-
-/*
-
-#% remove      dvp     L U U
-#% remove      vp      L U U
-#
- vnop_remove {
-     IN WILLRELE struct vnode *dvp;
-     IN WILLRELE struct vnode *vp;
-     IN struct componentname *cnp;
-     IN vfs_context_t context;
-    
-     */
-
-int
-synthfs_remove(ap)
-struct vnop_remove_args /* {
-    struct vnode *a_dvp;
-    struct vnode *a_vp;
-    struct componentname *a_cnp;
-    vfs_context_t a_context;
-} */ *ap;
-{
-       return synthfs_remove_internal(ap->a_dvp, ap->a_vp, ap->a_cnp, ap->a_context);
-}
-
-static int
-synthfs_remove_internal(struct vnode *dvp, struct vnode *vp,
-                       __unused struct componentname *cnp,
-                       __unused vfs_context_t context)
-{
-       struct synthfsnode *sp = VTOS(vp);
-       struct timeval tv;
-       int retval = 0;
-
-       /* This is sort of silly right now but someday it may make sense... */
-       if (sp->s_nodeflags & IN_MODIFIED) {
-               microtime(&tv);
-               synthfs_update(vp, &tv, &tv, 0);
-       };
-       
-       /* remove the entry from the namei cache: */
-       cache_purge(vp);
-
-       /* remove entry from tree and reclaim any resources consumed: */
-       switch (sp->s_type) {
-               case SYNTHFS_DIRECTORY:
-                       synthfs_remove_directory(vp);
-                       break;
-               
-               
-               case SYNTHFS_SYMLINK:
-                       synthfs_remove_symlink(vp);
-                       break;
-               
-               case SYNTHFS_FILE:
-                       /* Fall through to default case */
-               
-               default:
-                       synthfs_remove_entry(vp);
-       };
-
-out:
-
-       if (! retval)
-               VTOS(dvp)->s_nodeflags |= IN_CHANGE | IN_UPDATE;
-
-       return (retval);
-}
-
-
-
-/*
-#% rmdir       dvp     L U U
-#% rmdir       vp      L U U
-#
- vnop_rmdir {
-     IN WILLRELE struct vnode *dvp;
-     IN WILLRELE struct vnode *vp;
-     IN struct componentname *cnp;
-     IN vfs_context_t context;
-
-     */
-
-int
-synthfs_rmdir(ap)
-    struct vnop_rmdir_args /* {
-       struct vnode *a_dvp;
-       struct vnode *a_vp;
-        struct componentname *a_cnp;
-       vfs_context_t a_context;
-} */ *ap;
-{
-       return synthfs_remove((struct vnop_remove_args *)ap);
-}
-
-
-
-/*
- * synthfs_select - just say OK.  Only possible op is readdir
- *
- * Locking policy: ignore
- */
-int
-synthfs_select(__unused
-struct vnop_select_args /* {
-    struct vnode *a_vp;
-    int  a_which;
-    int  a_fflags;
-    kauth_cred_t a_cred;
-       void *a_wql;
-    struct proc *a_p;
-} */ *ap)
-{
-    DBG_VOP(("synthfs_select called\n"));
-
-    return (1);
-}
-
-/*
-#
-#% symlink     dvp     L U U
-#% symlink     vpp     - U -
-#
-# XXX - note that the return vnode has already been vnode_put'ed
-#      by the filesystem layer.  To use it you must use vnode_get,
-#      possibly with a further namei.
-#
- vnop_symlink {
-     IN WILLRELE struct vnode *dvp;
-     OUT WILLRELE struct vnode **vpp;
-     IN struct componentname *cnp;
-     IN struct vnode_attr *vap;
-     IN char *target;
-
-     We are responsible for freeing the namei buffer, it is done in synthfs_makenode(), unless there is
-    a previous error.
-
-
-*/
-
-int
-synthfs_symlink(ap)
-    struct vnop_symlink_args /* {
-        struct vnode *a_dvp;
-        struct vnode **a_vpp;
-        struct componentname *a_cnp;
-        struct vnode_attr *a_vap;
-        char *a_target;
-       vfs_context_t a_context;
-    } */ *ap;
-{
-    struct vnode *dvp = ap->a_dvp;
-    struct vnode **vpp = ap->a_vpp;
-    struct componentname *cnp = ap->a_cnp;
-    int retval;
-
-    *vpp = NULL;
-
-    retval = synthfs_new_symlink(VTOVFS(dvp), dvp, cnp->cn_nameptr, VTOSFS(dvp)->synthfs_nextid++, ap->a_target, vfs_context_proc(cnp->cn_context), vpp);
-
-    return (retval);
-}
-
-
-
-/*
-#
-#% readlink    vp      L L L
-#
- vnop_readlink {
-     IN struct vnode *vp;
-     INOUT struct uio *uio;
-     IN kauth_cred_t cred;
-     */
-
-int
-synthfs_readlink(ap)
-struct vnop_readlink_args /* {
-       struct vnode *a_vp;
-       struct uio *a_uio;
-       vfs_context_t a_context;
-} */ *ap;
-{
-       struct vnode *vp = ap->a_vp;
-       struct synthfsnode *sp = VTOS(vp);
-    struct uio *uio = ap->a_uio;
-    int retval;
-    unsigned long count;
-    
-    if (ap->a_uio->uio_offset > sp->s_u.s.s_length) {
-        return 0;
-    };
-
-       // LP64todo - fix this!
-    if (uio->uio_offset + uio_resid(uio) <= sp->s_u.s.s_length) {
-       count = uio_resid(uio);
-    } else {
-       count = sp->s_u.s.s_length - uio->uio_offset;
-    };
-    retval = uiomove((void *)((unsigned char *)sp->s_u.s.s_symlinktarget + uio->uio_offset), count, uio);
-    return (retval);
-
-}
-
-
-
-
-
-
-/*                     
- * Read directory entries.
- */
-int
-synthfs_readdir(ap)
-struct vnop_readdir_args /* {
-       struct vnode *a_vp;
-       struct uio *a_uio;
-       int a_flags;
-       int *a_eofflag;
-       int *a_numdirent;
-       vfs_context_t a_context;
-} */ *ap;
-{
-    struct synthfsnode *sp = VTOS(ap->a_vp);
-    register struct uio *uio = ap->a_uio;
-    off_t diroffset;                                           /* Offset into simulated directory file */
-    struct synthfsnode *entry;
-
-    DBG_VOP(("\tuio_offset = %d, uio_resid = %lld\n", (int) uio->uio_offset, uio_resid(uio)));
-
-       if (ap->a_flags & (VNODE_READDIR_EXTENDED | VNODE_READDIR_REQSEEKOFF))
-               return (EINVAL);
-       
-       /* We assume it's all one big buffer... */
-    if (uio->uio_iovcnt > 1) {
-       DBG_VOP(("\tuio->uio_iovcnt = %d?\n", uio->uio_iovcnt));
-       return EINVAL;
-    };
-       
-       diroffset = 0;
-       
-    /*
-     * We must synthesize . and ..
-     */
-    DBG_VOP(("\tstarting ... uio_offset = %d, uio_resid = %lld\n", (int) uio->uio_offset, uio_resid(uio)));
-    if (uio->uio_offset == diroffset)
-      {
-        DBG_VOP(("\tAdding .\n"));
-               diroffset += synthfs_adddirentry(sp->s_nodeid, DT_DIR, ".", uio);
-        DBG_VOP(("\t   after adding ., uio_offset = %d, uio_resid = %lld\n", (int) uio->uio_offset, uio_resid(uio)));
-      }
-    if ((uio_resid(uio) > 0) && (diroffset > uio->uio_offset)) {
-       /* Oops - we skipped over a partial entry: at best, diroffset should've just matched uio->uio_offset */
-               return EINVAL;
-       };
-       
-    if (uio->uio_offset == diroffset)
-      {
-        DBG_VOP(("\tAdding ..\n"));
-        if (sp->s_parent != NULL) {
-            diroffset += synthfs_adddirentry(sp->s_parent->s_nodeid, DT_DIR, "..", uio);
-        } else {
-            diroffset += synthfs_adddirentry(sp->s_nodeid, DT_DIR, "..", uio);
-        }
-        DBG_VOP(("\t   after adding .., uio_offset = %d, uio_resid = %lld\n", (int) uio->uio_offset, uio_resid(uio)));
-      }
-    if ((uio_resid(uio) > 0) && (diroffset > uio->uio_offset)) {
-       /* Oops - we skipped over a partial entry: at best, diroffset should've just matched uio->uio_offset */
-               return EINVAL;
-       };
-
-       /* OK, so much for the fakes.  Now for the "real thing": */
-       TAILQ_FOREACH(entry, &sp->s_u.d.d_subnodes, s_sibling) {
-               if (diroffset == uio->uio_offset) {
-                       /* Return this entry */
-                       diroffset += synthfs_adddirentry(entry->s_nodeid, VTTOIF(STOV(entry)->v_type), entry->s_name, uio);
-               };
-       if ((uio_resid(uio) > 0) && (diroffset > uio->uio_offset)) {
-               /* Oops - we skipped over a partial entry: at best, diroffset should've just matched uio->uio_offset */
-                       return EINVAL;
-               };
-       };
-    
-    if (ap->a_eofflag)
-        *ap->a_eofflag = (entry == NULL);              /* If we ran all the way through the list, there is no more */
-
-    return 0;
-}
-
-
-
-/*     
-
-#% lookup      dvp L ? ?
-#% lookup      vpp - L -
-
- */
-
-int
-synthfs_cached_lookup(ap)
-       struct vnop_lookup_args /* {
-               struct vnode *a_dvp;
-               struct vnode **a_vpp;
-               struct componentname *a_cnp;
-       } */ *ap;
-{
-    struct vnode *dp = ap->a_dvp;
-    struct componentname *cnp = ap->a_cnp;
-    u_long nameiop = cnp->cn_nameiop;
-    u_long flags = cnp->cn_flags;
-    struct vnode **vpp = ap->a_vpp;
-    int result = 0;
-
-    DBG_VOP(("synthfs_cached_lookup called, name = %s, namelen = %ld\n", ap->a_cnp->cn_nameptr, ap->a_cnp->cn_namelen));
-#if DEBUG
-    if (flags & ISLASTCN) DBG_VOP(("\tISLASTCN is set\n"));
-#endif
-
-    *vpp = NULL;
-
-       /*
-        * Look up an entry in the namei cache
-        */
-       
-       result = cache_lookup(dp, vpp, cnp);
-       if (result == 0) {
-               /* There was no entry in the cache for this parent vnode/name pair:
-                  do the full-blown pathname lookup
-                */
-               return synthfs_lookup(ap);
-       };
-       if (result == ENOENT) return result;
-       
-       /* An entry matching the parent vnode/name was found in the cache: */
-       
-       return (0);
-       
-Err_Exit:;
-       return result;
-}
-
-
-
-int
-synthfs_lookup(ap)
-       struct vnop_lookup_args /* {
-               struct vnode *a_dvp;
-               struct vnode **a_vpp;
-               struct componentname *a_cnp;
-               vfs_context_t a_context;
-       } */ *ap;
-{
-    struct vnode *dp = ap->a_dvp;
-    struct synthfsnode *dsp = VTOS(dp);
-    struct componentname *cnp = ap->a_cnp;
-    u_long nameiop = cnp->cn_nameiop;
-//  char *nameptr = cnp->cn_nameptr;
-    u_long flags = cnp->cn_flags;
-    long namelen = cnp->cn_namelen;
-//  struct proc *p = cnp->cn_proc;
-    vfs_context_t ctx = cnp->cn_context;
-    kauth_cred_t cred = vfs_context_ucred(ctx);
-    struct synthfsnode *entry;
-    struct vnode *target_vp = NULL;
-    int result = 0;
-    boolean_t found = FALSE;
-    boolean_t isDot = FALSE;
-    boolean_t isDotDot = FALSE;
-       struct vnode *starting_parent = dp;
-       
-    DBG_VOP(("synthfs_lookup called, name = %s, namelen = %ld\n", ap->a_cnp->cn_nameptr, ap->a_cnp->cn_namelen));
-#if DEBUG
-    if (flags & LOCKPARENT) DBG_VOP(("\tLOCKPARENT is set\n"));
-    if (flags & ISLASTCN) DBG_VOP(("\tISLASTCN is set\n"));
-#endif
-
-    *ap->a_vpp = NULL;
-
-       /* first check for "." and ".." */
-       if (cnp->cn_nameptr[0] == '.') {
-               if (namelen == 1) {
-                       /*
-                          "." requested
-                        */
-            isDot = TRUE;
-            found = TRUE;
-
-            target_vp = dp;
-            vnode_get(target_vp);
-            
-            result = 0;
-            
-            goto Std_Exit;
-        } else if ((namelen == 2) && (cnp->cn_nameptr[1] == '.')) {
-                       /* 
-                          ".." requested
-                        */
-            isDotDot = TRUE;
-            found = TRUE;
-
-            if ((dsp->s_parent != NULL) && (dsp->s_parent != VTOS(dp))) {
-                target_vp = STOV(dsp->s_parent);
-                /*
-                 * Special case for ".." to prevent deadlock:
-                 * always release the parent vnode BEFORE trying to acquire
-                 * ITS parent.  This avoids deadlocking with another lookup
-                 * starting from the target_vp trying to vnode_get() this directory.
-                 */
-                result = vnode_get(target_vp);
-
-            } else {
-                target_vp = dp;
-                /* dp is alread locked and ref'ed */
-                result = 0;
-            }
-            
-            goto Std_Exit;
-               }
-       }
-
-       /* finally, just look for entries by name (making sure the entry's length
-          matches the cnp's namelen... */
-    TAILQ_FOREACH(entry, &dsp->s_u.d.d_subnodes, s_sibling) {
-       if ((bcmp(cnp->cn_nameptr, entry->s_name, (unsigned)namelen) == 0) &&
-               (*(entry->s_name + namelen) == (char)0)) {
-            found = TRUE;
-                       target_vp = STOV(entry);
-            result = vnode_getwithref(target_vp);              /* refcount is always > 0 for any vnode in this list... */
-                       if (result != 0) {
-                               goto Err_Exit;
-                       };
-
-            /* The specified entry was found and successfully acquired: */
-                       goto Std_Exit;
-        };
-       };
-
-    found = FALSE;
-
-Std_Exit:;
-    if (found) {
-        if ((nameiop == DELETE) && (flags & ISLASTCN)) {
-
-            /*
-             * If the parent directory is "sticky" then the user must own
-             * the directory, or the file in it, in order to be allowed to
-             * delete it (unless the user is root).  This implements
-             * append-only directories
-             */
-            if ((dsp->s_mode & S_ISVTX) &&
-                suser(cred, NULL) &&
-                (kauth_cred_getuid(cred) != dsp->s_uid) &&
-                (target_vp != NULL) &&
-                (target_vp->v_type != VLNK) &&
-                (VTOS(target_vp)->s_uid != kauth_cred_getuid(cred))) {
-                vnode_put(target_vp);
-                result = EPERM;
-                goto Err_Exit;
-            };
-        };
-
-        if ((nameiop == RENAME) && (flags & WANTPARENT) && (flags * ISLASTCN)) {
-
-            if (isDot) {
-                vnode_put(target_vp);
-                result = EISDIR;
-                goto Err_Exit;
-            };
-        };
-    } else {
-        /* The specified entry wasn't found: */
-        result = ENOENT;
-
-        if ((flags & ISLASTCN) &&
-            ((nameiop == CREATE) ||
-             (nameiop == RENAME) ||
-             ((nameiop == DELETE) && (flags & DOWHITEOUT) && (flags & ISWHITEOUT)))) {
-               /* create a new entry */
-            result = EJUSTRETURN;
-        }
-    };
-
-    *ap->a_vpp = target_vp;
-
-Err_Exit:;
-       DBG_VOP(("synthfs_lookup: result = %d.\n", result));
-       if (found) {
-               if (target_vp) {
-                               DBG_VOP(("synthfs_lookup: target_vp = 0x%08X \n", (u_long)target_vp));
-               } else {
-                       DBG_VOP(("synthfs_lookup: found = true but target_vp = NULL?\n"));
-               };
-       } else {
-               DBG_VOP(("synthf_lookup: target not found.\n"));
-       };
-               DBG_VOP(("synthfs_lookup: dp = %08X; starting_parent = 0x%08X .\n", (u_long)dp, (u_long)starting_parent));
-       
-   return result;
-}
-
-
-
-/*
-
-#% pathconf    vp      L L L
-#
- vnop_pathconf {
-     IN struct vnode *vp;
-     IN int name;
-     OUT register_t *retval;
-*/
-int
-synthfs_pathconf(ap)
-struct vnop_pathconf_args /* {
-    struct vnode *a_vp;
-    int a_name;
-    int *a_retval;
-    vfs_context_t a_context;
-} */ *ap;
-{
-    DBG_VOP(("synthfs_pathconf called\n"));
-
-    switch (ap->a_name)
-      {
-        case _PC_LINK_MAX:
-            *ap->a_retval = LINK_MAX;
-            return (0);
-        case _PC_NAME_MAX:
-            *ap->a_retval = NAME_MAX;
-            return (0);
-        case _PC_PATH_MAX:
-            *ap->a_retval = PATH_MAX;
-            return (0);
-        case _PC_PIPE_BUF:
-            *ap->a_retval = PIPE_BUF;
-            return (0);
-        case _PC_CHOWN_RESTRICTED:
-           *ap->a_retval = 200112;             /* _POSIX_CHOWN_RESTRICTED */
-            return (0);
-        case _PC_NO_TRUNC:
-            *ap->a_retval = 200112;            /* _POSIX_NO_TRUNC */
-            return (0);
-        default:
-            return (EINVAL);
-      }
-    /* NOTREACHED */
-}
-
-
-/*
- * Update the access, modified, and node change times as specified by the
- * IACCESS, IUPDATE, and ICHANGE flags respectively. The IMODIFIED flag is
- * used to specify that the node needs to be updated but that the times have
- * already been set. The access and modified times are taken from the second
- * and third parameters; the node change time is always taken from the current
- * time. If waitfor is set, then wait for the disk write of the node to
- * complete.
- */
-
-int
-synthfs_update(struct vnode *vp, struct timeval *access, struct timeval *modify, __unused int waitfor)
-{
-       struct synthfsnode *sp = VTOS(vp);
-       struct timeval tv;
-
-       DBG_ASSERT(sp != NULL);
-
-       if (((sp->s_nodeflags & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) != 0) &&
-               !(VTOVFS(vp)->mnt_flag & MNT_RDONLY)) {
-               if (sp->s_nodeflags & IN_ACCESS) sp->s_accesstime = *access;
-               if (sp->s_nodeflags & IN_UPDATE) sp->s_modificationtime = *modify;
-               if (sp->s_nodeflags & IN_CHANGE) {
-
-                       microtime(&tv);
-                       sp->s_changetime = tv;
-               }
-       };
-       
-       /* After the updates are finished, clear the flags */
-       sp->s_nodeflags &= ~(IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE);
-
-       return 0;
-}
-
-
-
-/*******************************************************************************************
-
-       Utility/housekeeping vnode operations:
-       
- ******************************************************************************************/
-
-
-/*
-#
-#% inactive    vp      L U U
-#
- vnop_inactive {
-     IN struct vnode *vp;
-     IN struct proc *p;
-
-*/
-
-int
-synthfs_inactive(ap)
-struct vnop_inactive_args /* {
-    struct vnode *a_vp;
-    vfs_context_t a_context;
-} */ *ap;
-{
-       struct vnode *vp = ap->a_vp;
-       struct synthfsnode *sp = VTOS(vp);
-       struct timeval tv;
-
-#if DEBUG
-       if (vp->v_usecount != 0)
-        DBG_VOP(("synthfs_inactive: bad usecount = %d\n", vp->v_usecount ));
-#endif
-
-       /*
-        * Ignore nodes related to stale file handles.
-        */
-       if (vp->v_type == VNON)
-               goto out;
-       
-       /* This is sort of silly but might make sense in the future: */
-       if (sp->s_nodeflags & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) {
-               microtime(&tv);
-               synthfs_update(vp, &tv, &tv, 0);
-       }
-
-out:
-       /*
-        * If we are done with the inode, reclaim it
-        * so that it can be reused immediately.
-        */
-       if (vp->v_type == VNON) {
-               vnode_recycle(vp);
-       };
-       
-       return 0;
-}
-
-
-
-/*
- * synthfs_reclaim - Reclaim a vnode so that it can be used for other purposes.
- *
- * Locking policy: ignored
- */
-int
-synthfs_reclaim(ap)
-    struct vnop_reclaim_args /* { struct vnode *a_vp; struct proc *a_p; } */ *ap;
-{
-    struct vnode *vp = ap->a_vp;
-    struct synthfsnode *sp = VTOS(vp);
-    void *name = sp->s_name;
-    
-    sp->s_name = NULL;
-    FREE(name, M_TEMP);
-
-       vp->v_data = NULL;
-    FREE((void *)sp, M_SYNTHFS);
-
-    return (0);
-}