The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/vfs_syscalls.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 1989, 1993
    3  *      The Regents of the University of California.  All rights reserved.
    4  * (c) UNIX System Laboratories, Inc.
    5  * All or some portions of this file are derived from material licensed
    6  * to the University of California by American Telephone and Telegraph
    7  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
    8  * the permission of UNIX System Laboratories, Inc.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *      This product includes software developed by the University of
   21  *      California, Berkeley and its contributors.
   22  * 4. Neither the name of the University nor the names of its contributors
   23  *    may be used to endorse or promote products derived from this software
   24  *    without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   36  * SUCH DAMAGE.
   37  *
   38  *      @(#)vfs_syscalls.c      8.13 (Berkeley) 4/15/94
   39  * $FreeBSD$
   40  */
   41 
   42 /* For 4.3 integer FS ID compatibility */
   43 #include "opt_compat.h"
   44 
   45 #include <sys/param.h>
   46 #include <sys/systm.h>
   47 #include <sys/buf.h>
   48 #include <sys/sysent.h>
   49 #include <sys/malloc.h>
   50 #include <sys/mount.h>
   51 #include <sys/sysproto.h>
   52 #include <sys/namei.h>
   53 #include <sys/filedesc.h>
   54 #include <sys/kernel.h>
   55 #include <sys/fcntl.h>
   56 #include <sys/file.h>
   57 #include <sys/linker.h>
   58 #include <sys/stat.h>
   59 #include <sys/unistd.h>
   60 #include <sys/vnode.h>
   61 #include <sys/proc.h>
   62 #include <sys/dirent.h>
   63 #include <sys/extattr.h>
   64 
   65 #include <machine/limits.h>
   66 #include <miscfs/union/union.h>
   67 #include <sys/sysctl.h>
   68 #include <vm/vm.h>
   69 #include <vm/vm_object.h>
   70 #include <vm/vm_zone.h>
   71 #include <vm/vm_page.h>
   72 
   73 static int change_dir __P((struct nameidata *ndp, struct proc *p));
   74 static void checkdirs __P((struct vnode *olddp));
   75 static int chroot_refuse_vdir_fds __P((struct filedesc *fdp));
   76 static int getutimes __P((const struct timeval *, struct timespec *));
   77 static int setfown __P((struct proc *, struct vnode *, uid_t, gid_t));
   78 static int setfmode __P((struct proc *, struct vnode *, int));
   79 static int setfflags __P((struct proc *, struct vnode *, int));
   80 static int setutimes __P((struct proc *, struct vnode *,
   81     const struct timespec *, int));
   82 static int      usermount = 0;  /* if 1, non-root can mount fs. */
   83 
   84 int (*union_dircheckp) __P((struct proc *, struct vnode **, struct file *));
   85 
   86 SYSCTL_INT(_vfs, OID_AUTO, usermount, CTLFLAG_RW, &usermount, 0, "");
   87 
   88 /*
   89  * Virtual File System System Calls
   90  */
   91 
   92 /*
   93  * Mount a file system.
   94  */
   95 #ifndef _SYS_SYSPROTO_H_
   96 struct mount_args {
   97         char    *type;
   98         char    *path;
   99         int     flags;
  100         caddr_t data;
  101 };
  102 #endif
  103 /* ARGSUSED */
  104 int
  105 mount(p, uap)
  106         struct proc *p;
  107         register struct mount_args /* {
  108                 syscallarg(char *) type;
  109                 syscallarg(char *) path;
  110                 syscallarg(int) flags;
  111                 syscallarg(caddr_t) data;
  112         } */ *uap;
  113 {
  114         struct vnode *vp;
  115         struct mount *mp;
  116         struct vfsconf *vfsp;
  117         int error, flag = 0, flag2 = 0;
  118         struct vattr va;
  119 #ifdef COMPAT_43
  120         u_long fstypenum;
  121 #endif
  122         struct nameidata nd;
  123         char fstypename[MFSNAMELEN];
  124 
  125         if (p->p_prison != NULL)
  126                 return (EPERM);
  127         if (usermount == 0 && (error = suser(p)))
  128                 return (error);
  129         /*
  130          * Do not allow NFS export by non-root users.
  131          */
  132         if (SCARG(uap, flags) & MNT_EXPORTED) {
  133                 error = suser(p);
  134                 if (error)
  135                         return (error);
  136         }
  137         /*
  138          * Silently enforce MNT_NOSUID and MNT_NODEV for non-root users
  139          */
  140         if (suser_xxx(p->p_ucred, 0, 0)) 
  141                 SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV;
  142         /*
  143          * Get vnode to be covered
  144          */
  145         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
  146             SCARG(uap, path), p);
  147         if ((error = namei(&nd)) != 0)
  148                 return (error);
  149         NDFREE(&nd, NDF_ONLY_PNBUF);
  150         vp = nd.ni_vp;
  151         if (SCARG(uap, flags) & MNT_UPDATE) {
  152                 if ((vp->v_flag & VROOT) == 0) {
  153                         vput(vp);
  154                         return (EINVAL);
  155                 }
  156                 mp = vp->v_mount;
  157                 flag = mp->mnt_flag;
  158                 flag2 = mp->mnt_kern_flag;
  159                 /*
  160                  * We only allow the filesystem to be reloaded if it
  161                  * is currently mounted read-only.
  162                  */
  163                 if ((SCARG(uap, flags) & MNT_RELOAD) &&
  164                     ((mp->mnt_flag & MNT_RDONLY) == 0)) {
  165                         vput(vp);
  166                         return (EOPNOTSUPP);    /* Needs translation */
  167                 }
  168                 /*
  169                  * Only root, or the user that did the original mount is
  170                  * permitted to update it.
  171                  */
  172                 if (mp->mnt_stat.f_owner != p->p_ucred->cr_uid &&
  173                     (error = suser(p))) {
  174                         vput(vp);
  175                         return (error);
  176                 }
  177                 if (vfs_busy(mp, LK_NOWAIT, 0, p)) {
  178                         vput(vp);
  179                         return (EBUSY);
  180                 }
  181                 simple_lock(&vp->v_interlock);
  182                 if ((vp->v_flag & VMOUNT) != 0 ||
  183                     vp->v_mountedhere != NULL) {
  184                         simple_unlock(&vp->v_interlock);
  185                         vfs_unbusy(mp, p);
  186                         vput(vp);
  187                         return (EBUSY);
  188                 }
  189                 vp->v_flag |= VMOUNT;
  190                 simple_unlock(&vp->v_interlock);
  191                 mp->mnt_flag |=
  192                     SCARG(uap, flags) & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE);
  193                 VOP_UNLOCK(vp, 0, p);
  194                 goto update;
  195         }
  196         /*
  197          * If the user is not root, ensure that they own the directory
  198          * onto which we are attempting to mount.
  199          */
  200         if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) ||
  201             (va.va_uid != p->p_ucred->cr_uid &&
  202              (error = suser(p)))) {
  203                 vput(vp);
  204                 return (error);
  205         }
  206         if ((error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0)) != 0) {
  207                 vput(vp);
  208                 return (error);
  209         }
  210         if (vp->v_type != VDIR) {
  211                 vput(vp);
  212                 return (ENOTDIR);
  213         }
  214 #ifdef COMPAT_43
  215         /*
  216          * Historically filesystem types were identified by number. If we
  217          * get an integer for the filesystem type instead of a string, we
  218          * check to see if it matches one of the historic filesystem types.
  219          */
  220         fstypenum = (uintptr_t)SCARG(uap, type);
  221         if (fstypenum < maxvfsconf) {
  222                 for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
  223                         if (vfsp->vfc_typenum == fstypenum)
  224                                 break;
  225                 if (vfsp == NULL) {
  226                         vput(vp);
  227                         return (ENODEV);
  228                 }
  229                 strncpy(fstypename, vfsp->vfc_name, MFSNAMELEN);
  230         } else
  231 #endif /* COMPAT_43 */
  232         if ((error = copyinstr(SCARG(uap, type), fstypename, MFSNAMELEN, NULL)) != 0) {
  233                 vput(vp);
  234                 return (error);
  235         }
  236         for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
  237                 if (!strcmp(vfsp->vfc_name, fstypename))
  238                         break;
  239         if (vfsp == NULL) {
  240                 linker_file_t lf;
  241 
  242                 /* Only load modules for root (very important!) */
  243                 if ((error = suser(p)) != 0) {
  244                         vput(vp);
  245                         return error;
  246                 }
  247                 error = linker_load_file(fstypename, &lf);
  248                 if (error || lf == NULL) {
  249                         vput(vp);
  250                         if (lf == NULL)
  251                                 error = ENODEV;
  252                         return error;
  253                 }
  254                 lf->userrefs++;
  255                 /* lookup again, see if the VFS was loaded */
  256                 for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
  257                         if (!strcmp(vfsp->vfc_name, fstypename))
  258                                 break;
  259                 if (vfsp == NULL) {
  260                         lf->userrefs--;
  261                         linker_file_unload(lf);
  262                         vput(vp);
  263                         return (ENODEV);
  264                 }
  265         }
  266         simple_lock(&vp->v_interlock);
  267         if ((vp->v_flag & VMOUNT) != 0 ||
  268             vp->v_mountedhere != NULL) {
  269                 simple_unlock(&vp->v_interlock);
  270                 vput(vp);
  271                 return (EBUSY);
  272         }
  273         vp->v_flag |= VMOUNT;
  274         simple_unlock(&vp->v_interlock);
  275 
  276         /*
  277          * Allocate and initialize the filesystem.
  278          */
  279         mp = malloc(sizeof(struct mount), M_MOUNT, M_WAITOK);
  280         bzero((char *)mp, (u_long)sizeof(struct mount));
  281         TAILQ_INIT(&mp->mnt_nvnodelist);
  282         TAILQ_INIT(&mp->mnt_reservedvnlist);
  283         mp->mnt_nvnodelistsize = 0;
  284         lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, LK_NOPAUSE);
  285         (void)vfs_busy(mp, LK_NOWAIT, 0, p);
  286         mp->mnt_op = vfsp->vfc_vfsops;
  287         mp->mnt_vfc = vfsp;
  288         vfsp->vfc_refcount++;
  289         mp->mnt_stat.f_type = vfsp->vfc_typenum;
  290         mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK;
  291         strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN);
  292         mp->mnt_vnodecovered = vp;
  293         mp->mnt_stat.f_owner = p->p_ucred->cr_uid;
  294         mp->mnt_iosize_max = DFLTPHYS;
  295         VOP_UNLOCK(vp, 0, p);
  296 update:
  297         /*
  298          * Set the mount level flags.
  299          */
  300         if (SCARG(uap, flags) & MNT_RDONLY)
  301                 mp->mnt_flag |= MNT_RDONLY;
  302         else if (mp->mnt_flag & MNT_RDONLY)
  303                 mp->mnt_kern_flag |= MNTK_WANTRDWR;
  304         mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV |
  305             MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_NOATIME |
  306             MNT_NOSYMFOLLOW | MNT_IGNORE |
  307             MNT_NOCLUSTERR | MNT_NOCLUSTERW | MNT_SUIDDIR);
  308         mp->mnt_flag |= SCARG(uap, flags) & (MNT_NOSUID | MNT_NOEXEC |
  309             MNT_NODEV | MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_FORCE |
  310             MNT_NOSYMFOLLOW | MNT_IGNORE |
  311             MNT_NOATIME | MNT_NOCLUSTERR | MNT_NOCLUSTERW | MNT_SUIDDIR);
  312         /*
  313          * Mount the filesystem.
  314          * XXX The final recipients of VFS_MOUNT just overwrite the ndp they
  315          * get.  No freeing of cn_pnbuf.
  316          */
  317         error = VFS_MOUNT(mp, SCARG(uap, path), SCARG(uap, data), &nd, p);
  318         if (mp->mnt_flag & MNT_UPDATE) {
  319                 if (mp->mnt_kern_flag & MNTK_WANTRDWR)
  320                         mp->mnt_flag &= ~MNT_RDONLY;
  321                 mp->mnt_flag &=~ (MNT_UPDATE | MNT_RELOAD | MNT_FORCE);
  322                 mp->mnt_kern_flag &=~ MNTK_WANTRDWR;
  323                 if (error) {
  324                         mp->mnt_flag = flag;
  325                         mp->mnt_kern_flag = flag2;
  326                 }
  327                 if ((mp->mnt_flag & MNT_RDONLY) == 0) {
  328                         if (mp->mnt_syncer == NULL)
  329                                 error = vfs_allocate_syncvnode(mp);
  330                 } else {
  331                         if (mp->mnt_syncer != NULL)
  332                                 vrele(mp->mnt_syncer);
  333                         mp->mnt_syncer = NULL;
  334                 }
  335                 vfs_unbusy(mp, p);
  336                 simple_lock(&vp->v_interlock);
  337                 vp->v_flag &= ~VMOUNT;
  338                 simple_unlock(&vp->v_interlock);
  339                 vrele(vp);
  340                 return (error);
  341         }
  342         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
  343         /*
  344          * Put the new filesystem on the mount list after root.
  345          */
  346         cache_purge(vp);
  347         if (!error) {
  348                 simple_lock(&vp->v_interlock);
  349                 vp->v_flag &= ~VMOUNT;
  350                 vp->v_mountedhere = mp;
  351                 simple_unlock(&vp->v_interlock);
  352                 simple_lock(&mountlist_slock);
  353                 TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list);
  354                 simple_unlock(&mountlist_slock);
  355                 checkdirs(vp);
  356                 VOP_UNLOCK(vp, 0, p);
  357                 if ((mp->mnt_flag & MNT_RDONLY) == 0)
  358                         error = vfs_allocate_syncvnode(mp);
  359                 vfs_unbusy(mp, p);
  360                 if ((error = VFS_START(mp, 0, p)) != 0)
  361                         vrele(vp);
  362         } else {
  363                 simple_lock(&vp->v_interlock);
  364                 vp->v_flag &= ~VMOUNT;
  365                 simple_unlock(&vp->v_interlock);
  366                 mp->mnt_vfc->vfc_refcount--;
  367                 vfs_unbusy(mp, p);
  368                 free((caddr_t)mp, M_MOUNT);
  369                 vput(vp);
  370         }
  371         return (error);
  372 }
  373 
  374 /*
  375  * Scan all active processes to see if any of them have a current
  376  * or root directory onto which the new filesystem has just been
  377  * mounted. If so, replace them with the new mount point.
  378  */
  379 static void
  380 checkdirs(olddp)
  381         struct vnode *olddp;
  382 {
  383         struct filedesc *fdp;
  384         struct vnode *newdp;
  385         struct proc *p;
  386 
  387         if (olddp->v_usecount == 1)
  388                 return;
  389         if (VFS_ROOT(olddp->v_mountedhere, &newdp))
  390                 panic("mount: lost mount");
  391         LIST_FOREACH(p, &allproc, p_list) {
  392                 fdp = p->p_fd;
  393                 if (fdp->fd_cdir == olddp) {
  394                         vrele(fdp->fd_cdir);
  395                         VREF(newdp);
  396                         fdp->fd_cdir = newdp;
  397                 }
  398                 if (fdp->fd_rdir == olddp) {
  399                         vrele(fdp->fd_rdir);
  400                         VREF(newdp);
  401                         fdp->fd_rdir = newdp;
  402                 }
  403         }
  404         if (rootvnode == olddp) {
  405                 vrele(rootvnode);
  406                 VREF(newdp);
  407                 rootvnode = newdp;
  408         }
  409         vput(newdp);
  410 }
  411 
  412 /*
  413  * Unmount a file system.
  414  *
  415  * Note: unmount takes a path to the vnode mounted on as argument,
  416  * not special file (as before).
  417  */
  418 #ifndef _SYS_SYSPROTO_H_
  419 struct unmount_args {
  420         char    *path;
  421         int     flags;
  422 };
  423 #endif
  424 /* ARGSUSED */
  425 int
  426 unmount(p, uap)
  427         struct proc *p;
  428         register struct unmount_args /* {
  429                 syscallarg(char *) path;
  430                 syscallarg(int) flags;
  431         } */ *uap;
  432 {
  433         register struct vnode *vp;
  434         struct mount *mp;
  435         int error;
  436         struct nameidata nd;
  437 
  438         if (p->p_prison != NULL)
  439                 return (EPERM);
  440         if (usermount == 0 && (error = suser(p)))
  441                 return (error);
  442         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
  443             SCARG(uap, path), p);
  444         if ((error = namei(&nd)) != 0)
  445                 return (error);
  446         vp = nd.ni_vp;
  447         NDFREE(&nd, NDF_ONLY_PNBUF);
  448         mp = vp->v_mount;
  449 
  450         /*
  451          * Only root, or the user that did the original mount is
  452          * permitted to unmount this filesystem.
  453          */
  454         if ((mp->mnt_stat.f_owner != p->p_ucred->cr_uid) &&
  455             (error = suser(p))) {
  456                 vput(vp);
  457                 return (error);
  458         }
  459 
  460         /*
  461          * Don't allow unmounting the root file system.
  462          */
  463         if (mp->mnt_flag & MNT_ROOTFS) {
  464                 vput(vp);
  465                 return (EINVAL);
  466         }
  467 
  468         /*
  469          * Must be the root of the filesystem
  470          */
  471         if ((vp->v_flag & VROOT) == 0) {
  472                 vput(vp);
  473                 return (EINVAL);
  474         }
  475         vput(vp);
  476         return (dounmount(mp, SCARG(uap, flags), p));
  477 }
  478 
  479 /*
  480  * Do the actual file system unmount.
  481  */
  482 int
  483 dounmount(mp, flags, p)
  484         register struct mount *mp;
  485         int flags;
  486         struct proc *p;
  487 {
  488         struct vnode *coveredvp;
  489         int error;
  490         int async_flag;
  491 
  492         simple_lock(&mountlist_slock);
  493         if (mp->mnt_kern_flag & MNTK_UNMOUNT) {
  494                 simple_unlock(&mountlist_slock);
  495                 return (EBUSY);
  496         }
  497         mp->mnt_kern_flag |= MNTK_UNMOUNT;
  498         /* Allow filesystems to detect that a forced unmount is in progress. */
  499         if (flags & MNT_FORCE)
  500                 mp->mnt_kern_flag |= MNTK_UNMOUNTF;
  501         error = lockmgr(&mp->mnt_lock, LK_DRAIN | LK_INTERLOCK |
  502             ((flags & MNT_FORCE) ? 0 : LK_NOWAIT), &mountlist_slock, p);
  503         if (error) {
  504                 mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_UNMOUNTF);
  505                 if (mp->mnt_kern_flag & MNTK_MWAIT)
  506                         wakeup((caddr_t)mp);
  507                 return (error);
  508         }
  509 
  510         if (mp->mnt_flag & MNT_EXPUBLIC)
  511                 vfs_setpublicfs(NULL, NULL, NULL);
  512 
  513         vfs_msync(mp, MNT_WAIT);
  514         async_flag = mp->mnt_flag & MNT_ASYNC;
  515         mp->mnt_flag &=~ MNT_ASYNC;
  516         cache_purgevfs(mp);     /* remove cache entries for this file sys */
  517         if (mp->mnt_syncer != NULL)
  518                 vrele(mp->mnt_syncer);
  519         if (((mp->mnt_flag & MNT_RDONLY) ||
  520              (error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0) ||
  521             (flags & MNT_FORCE))
  522                 error = VFS_UNMOUNT(mp, flags, p);
  523         simple_lock(&mountlist_slock);
  524         if (error) {
  525                 if ((mp->mnt_flag & MNT_RDONLY) == 0 && mp->mnt_syncer == NULL)
  526                         (void) vfs_allocate_syncvnode(mp);
  527                 mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_UNMOUNTF);
  528                 mp->mnt_flag |= async_flag;
  529                 lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK | LK_REENABLE,
  530                     &mountlist_slock, p);
  531                 if (mp->mnt_kern_flag & MNTK_MWAIT)
  532                         wakeup((caddr_t)mp);
  533                 return (error);
  534         }
  535         TAILQ_REMOVE(&mountlist, mp, mnt_list);
  536         if ((coveredvp = mp->mnt_vnodecovered) != NULLVP) {
  537                 coveredvp->v_mountedhere = (struct mount *)0;
  538                 vrele(coveredvp);
  539         }
  540         mp->mnt_vfc->vfc_refcount--;
  541         if (!TAILQ_EMPTY(&mp->mnt_nvnodelist))
  542                 panic("unmount: dangling vnode");
  543         lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK, &mountlist_slock, p);
  544         if (mp->mnt_kern_flag & MNTK_MWAIT)
  545                 wakeup((caddr_t)mp);
  546         free((caddr_t)mp, M_MOUNT);
  547         return (0);
  548 }
  549 
  550 /*
  551  * Sync each mounted filesystem.
  552  */
  553 #ifndef _SYS_SYSPROTO_H_
  554 struct sync_args {
  555         int     dummy;
  556 };
  557 #endif
  558 
  559 #ifdef DEBUG
  560 static int syncprt = 0;
  561 SYSCTL_INT(_debug, OID_AUTO, syncprt, CTLFLAG_RW, &syncprt, 0, "");
  562 #endif
  563 
  564 /* ARGSUSED */
  565 int
  566 sync(p, uap)
  567         struct proc *p;
  568         struct sync_args *uap;
  569 {
  570         register struct mount *mp, *nmp;
  571         int asyncflag;
  572 
  573         simple_lock(&mountlist_slock);
  574         for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
  575                 if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
  576                         nmp = TAILQ_NEXT(mp, mnt_list);
  577                         continue;
  578                 }
  579                 if ((mp->mnt_flag & MNT_RDONLY) == 0) {
  580                         asyncflag = mp->mnt_flag & MNT_ASYNC;
  581                         mp->mnt_flag &= ~MNT_ASYNC;
  582                         vfs_msync(mp, MNT_NOWAIT);
  583                         VFS_SYNC(mp, MNT_NOWAIT,
  584                                 ((p != NULL) ? p->p_ucred : NOCRED), p);
  585                         mp->mnt_flag |= asyncflag;
  586                 }
  587                 simple_lock(&mountlist_slock);
  588                 nmp = TAILQ_NEXT(mp, mnt_list);
  589                 vfs_unbusy(mp, p);
  590         }
  591         simple_unlock(&mountlist_slock);
  592 #if 0
  593 /*
  594  * XXX don't call vfs_bufstats() yet because that routine
  595  * was not imported in the Lite2 merge.
  596  */
  597 #ifdef DIAGNOSTIC
  598         if (syncprt)
  599                 vfs_bufstats();
  600 #endif /* DIAGNOSTIC */
  601 #endif
  602         return (0);
  603 }
  604 
  605 /* XXX PRISON: could be per prison flag */
  606 static int prison_quotas;
  607 #if 0
  608 SYSCTL_INT(_kern_prison, OID_AUTO, quotas, CTLFLAG_RW, &prison_quotas, 0, "");
  609 #endif
  610 
  611 /*
  612  * Change filesystem quotas.
  613  */
  614 #ifndef _SYS_SYSPROTO_H_
  615 struct quotactl_args {
  616         char *path;
  617         int cmd;
  618         int uid;
  619         caddr_t arg;
  620 };
  621 #endif
  622 /* ARGSUSED */
  623 int
  624 quotactl(p, uap)
  625         struct proc *p;
  626         register struct quotactl_args /* {
  627                 syscallarg(char *) path;
  628                 syscallarg(int) cmd;
  629                 syscallarg(int) uid;
  630                 syscallarg(caddr_t) arg;
  631         } */ *uap;
  632 {
  633         register struct mount *mp;
  634         int error;
  635         struct nameidata nd;
  636 
  637         if (p->p_prison && !prison_quotas)
  638                 return (EPERM);
  639         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
  640         if ((error = namei(&nd)) != 0)
  641                 return (error);
  642         mp = nd.ni_vp->v_mount;
  643         NDFREE(&nd, NDF_ONLY_PNBUF);
  644         vrele(nd.ni_vp);
  645         return (VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid),
  646             SCARG(uap, arg), p));
  647 }
  648 
  649 /*
  650  * Get filesystem statistics.
  651  */
  652 #ifndef _SYS_SYSPROTO_H_
  653 struct statfs_args {
  654         char *path;
  655         struct statfs *buf;
  656 };
  657 #endif
  658 /* ARGSUSED */
  659 int
  660 statfs(p, uap)
  661         struct proc *p;
  662         register struct statfs_args /* {
  663                 syscallarg(char *) path;
  664                 syscallarg(struct statfs *) buf;
  665         } */ *uap;
  666 {
  667         register struct mount *mp;
  668         register struct statfs *sp;
  669         int error;
  670         struct nameidata nd;
  671         struct statfs sb;
  672 
  673         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
  674         if ((error = namei(&nd)) != 0)
  675                 return (error);
  676         mp = nd.ni_vp->v_mount;
  677         sp = &mp->mnt_stat;
  678         NDFREE(&nd, NDF_ONLY_PNBUF);
  679         vrele(nd.ni_vp);
  680         error = VFS_STATFS(mp, sp, p);
  681         if (error)
  682                 return (error);
  683         sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
  684         if (suser_xxx(p->p_ucred, 0, 0)) {
  685                 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
  686                 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
  687                 sp = &sb;
  688         }
  689         return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp)));
  690 }
  691 
  692 /*
  693  * Get filesystem statistics.
  694  */
  695 #ifndef _SYS_SYSPROTO_H_
  696 struct fstatfs_args {
  697         int fd;
  698         struct statfs *buf;
  699 };
  700 #endif
  701 /* ARGSUSED */
  702 int
  703 fstatfs(p, uap)
  704         struct proc *p;
  705         register struct fstatfs_args /* {
  706                 syscallarg(int) fd;
  707                 syscallarg(struct statfs *) buf;
  708         } */ *uap;
  709 {
  710         struct file *fp;
  711         struct mount *mp;
  712         register struct statfs *sp;
  713         int error;
  714         struct statfs sb;
  715 
  716         if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
  717                 return (error);
  718         mp = ((struct vnode *)fp->f_data)->v_mount;
  719         if (mp == NULL)
  720                 return (EBADF);
  721         sp = &mp->mnt_stat;
  722         error = VFS_STATFS(mp, sp, p);
  723         if (error)
  724                 return (error);
  725         sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
  726         if (suser_xxx(p->p_ucred, 0, 0)) {
  727                 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
  728                 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
  729                 sp = &sb;
  730         }
  731         return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp)));
  732 }
  733 
  734 /*
  735  * Get statistics on all filesystems.
  736  */
  737 #ifndef _SYS_SYSPROTO_H_
  738 struct getfsstat_args {
  739         struct statfs *buf;
  740         long bufsize;
  741         int flags;
  742 };
  743 #endif
  744 int
  745 getfsstat(p, uap)
  746         struct proc *p;
  747         register struct getfsstat_args /* {
  748                 syscallarg(struct statfs *) buf;
  749                 syscallarg(long) bufsize;
  750                 syscallarg(int) flags;
  751         } */ *uap;
  752 {
  753         register struct mount *mp, *nmp;
  754         register struct statfs *sp;
  755         caddr_t sfsp;
  756         long count, maxcount, error;
  757 
  758         maxcount = SCARG(uap, bufsize) / sizeof(struct statfs);
  759         sfsp = (caddr_t)SCARG(uap, buf);
  760         count = 0;
  761         simple_lock(&mountlist_slock);
  762         for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
  763                 if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
  764                         nmp = TAILQ_NEXT(mp, mnt_list);
  765                         continue;
  766                 }
  767                 if (sfsp && count < maxcount) {
  768                         sp = &mp->mnt_stat;
  769                         /*
  770                          * If MNT_NOWAIT or MNT_LAZY is specified, do not
  771                          * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY
  772                          * overrides MNT_WAIT.
  773                          */
  774                         if (((SCARG(uap, flags) & (MNT_LAZY|MNT_NOWAIT)) == 0 ||
  775                             (SCARG(uap, flags) & MNT_WAIT)) &&
  776                             (error = VFS_STATFS(mp, sp, p))) {
  777                                 simple_lock(&mountlist_slock);
  778                                 nmp = TAILQ_NEXT(mp, mnt_list);
  779                                 vfs_unbusy(mp, p);
  780                                 continue;
  781                         }
  782                         sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
  783                         error = copyout((caddr_t)sp, sfsp, sizeof(*sp));
  784                         if (error) {
  785                                 vfs_unbusy(mp, p);
  786                                 return (error);
  787                         }
  788                         sfsp += sizeof(*sp);
  789                 }
  790                 count++;
  791                 simple_lock(&mountlist_slock);
  792                 nmp = TAILQ_NEXT(mp, mnt_list);
  793                 vfs_unbusy(mp, p);
  794         }
  795         simple_unlock(&mountlist_slock);
  796         if (sfsp && count > maxcount)
  797                 p->p_retval[0] = maxcount;
  798         else
  799                 p->p_retval[0] = count;
  800         return (0);
  801 }
  802 
  803 /*
  804  * Change current working directory to a given file descriptor.
  805  */
  806 #ifndef _SYS_SYSPROTO_H_
  807 struct fchdir_args {
  808         int     fd;
  809 };
  810 #endif
  811 /* ARGSUSED */
  812 int
  813 fchdir(p, uap)
  814         struct proc *p;
  815         struct fchdir_args /* {
  816                 syscallarg(int) fd;
  817         } */ *uap;
  818 {
  819         register struct filedesc *fdp = p->p_fd;
  820         struct vnode *vp, *tdp;
  821         struct mount *mp;
  822         struct file *fp;
  823         int error;
  824 
  825         if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0)
  826                 return (error);
  827         vp = (struct vnode *)fp->f_data;
  828         VREF(vp);
  829         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
  830         if (vp->v_type != VDIR)
  831                 error = ENOTDIR;
  832         else
  833                 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
  834         while (!error && (mp = vp->v_mountedhere) != NULL) {
  835                 if (vfs_busy(mp, 0, 0, p))
  836                         continue;
  837                 error = VFS_ROOT(mp, &tdp);
  838                 vfs_unbusy(mp, p);
  839                 if (error)
  840                         break;
  841                 vput(vp);
  842                 vp = tdp;
  843         }
  844         if (error) {
  845                 vput(vp);
  846                 return (error);
  847         }
  848         VOP_UNLOCK(vp, 0, p);
  849         vrele(fdp->fd_cdir);
  850         fdp->fd_cdir = vp;
  851         return (0);
  852 }
  853 
  854 /*
  855  * Change current working directory (``.'').
  856  */
  857 #ifndef _SYS_SYSPROTO_H_
  858 struct chdir_args {
  859         char    *path;
  860 };
  861 #endif
  862 /* ARGSUSED */
  863 int
  864 chdir(p, uap)
  865         struct proc *p;
  866         struct chdir_args /* {
  867                 syscallarg(char *) path;
  868         } */ *uap;
  869 {
  870         register struct filedesc *fdp = p->p_fd;
  871         int error;
  872         struct nameidata nd;
  873 
  874         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
  875             SCARG(uap, path), p);
  876         if ((error = change_dir(&nd, p)) != 0)
  877                 return (error);
  878         NDFREE(&nd, NDF_ONLY_PNBUF);
  879         vrele(fdp->fd_cdir);
  880         fdp->fd_cdir = nd.ni_vp;
  881         return (0);
  882 }
  883 
  884 /*
  885  * Helper function for raised chroot(2) security function:  Refuse if
  886  * any filedescriptors are open directories.
  887  */
  888 static int
  889 chroot_refuse_vdir_fds(fdp)
  890         struct filedesc *fdp;
  891 {
  892         struct vnode *vp;
  893         struct file *fp;
  894         int error;
  895         int fd;
  896 
  897         for (fd = 0; fd < fdp->fd_nfiles ; fd++) {
  898                 error = getvnode(fdp, fd, &fp);
  899                 if (error)
  900                         continue;
  901                 vp = (struct vnode *)fp->f_data;
  902                 if (vp->v_type != VDIR)
  903                         continue;
  904                 return(EPERM);
  905         }
  906         return (0);
  907 }
  908 
  909 /*
  910  * This sysctl determines if we will allow a process to chroot(2) if it
  911  * has a directory open:
  912  *      0: disallowed for all processes.
  913  *      1: allowed for processes that were not already chroot(2)'ed.
  914  *      2: allowed for all processes.
  915  */
  916 
  917 static int chroot_allow_open_directories = 1;
  918 
  919 SYSCTL_INT(_kern, OID_AUTO, chroot_allow_open_directories, CTLFLAG_RW,
  920      &chroot_allow_open_directories, 0, "");
  921 
  922 /*
  923  * Change notion of root (``/'') directory.
  924  */
  925 #ifndef _SYS_SYSPROTO_H_
  926 struct chroot_args {
  927         char    *path;
  928 };
  929 #endif
  930 /* ARGSUSED */
  931 int
  932 chroot(p, uap)
  933         struct proc *p;
  934         struct chroot_args /* {
  935                 syscallarg(char *) path;
  936         } */ *uap;
  937 {
  938         register struct filedesc *fdp = p->p_fd;
  939         int error;
  940         struct nameidata nd;
  941 
  942         error = suser_xxx(0, p, PRISON_ROOT);
  943         if (error)
  944                 return (error);
  945         if (chroot_allow_open_directories == 0 ||
  946             (chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode))
  947                 error = chroot_refuse_vdir_fds(fdp);
  948         if (error)
  949                 return (error);
  950         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
  951             SCARG(uap, path), p);
  952         if ((error = change_dir(&nd, p)) != 0)
  953                 return (error);
  954         NDFREE(&nd, NDF_ONLY_PNBUF);
  955         vrele(fdp->fd_rdir);
  956         fdp->fd_rdir = nd.ni_vp;
  957         if (!fdp->fd_jdir) {
  958                 fdp->fd_jdir = nd.ni_vp;
  959                 VREF(fdp->fd_jdir);
  960         }
  961         return (0);
  962 }
  963 
  964 /*
  965  * Common routine for chroot and chdir.
  966  */
  967 static int
  968 change_dir(ndp, p)
  969         register struct nameidata *ndp;
  970         struct proc *p;
  971 {
  972         struct vnode *vp;
  973         int error;
  974 
  975         error = namei(ndp);
  976         if (error)
  977                 return (error);
  978         vp = ndp->ni_vp;
  979         if (vp->v_type != VDIR)
  980                 error = ENOTDIR;
  981         else
  982                 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
  983         if (error)
  984                 vput(vp);
  985         else
  986                 VOP_UNLOCK(vp, 0, p);
  987         return (error);
  988 }
  989 
  990 /*
  991  * Check permissions, allocate an open file structure,
  992  * and call the device open routine if any.
  993  */
  994 #ifndef _SYS_SYSPROTO_H_
  995 struct open_args {
  996         char    *path;
  997         int     flags;
  998         int     mode;
  999 };
 1000 #endif
 1001 int
 1002 open(p, uap)
 1003         struct proc *p;
 1004         register struct open_args /* {
 1005                 syscallarg(char *) path;
 1006                 syscallarg(int) flags;
 1007                 syscallarg(int) mode;
 1008         } */ *uap;
 1009 {
 1010         register struct filedesc *fdp = p->p_fd;
 1011         register struct file *fp;
 1012         register struct vnode *vp;
 1013         int cmode, flags, oflags;
 1014         struct file *nfp;
 1015         int type, indx, error;
 1016         struct flock lf;
 1017         struct nameidata nd;
 1018 
 1019         oflags = SCARG(uap, flags);
 1020         if ((oflags & O_ACCMODE) == O_ACCMODE)
 1021                 return (EINVAL);
 1022         flags = FFLAGS(oflags);
 1023         error = falloc(p, &nfp, &indx);
 1024         if (error)
 1025                 return (error);
 1026         fp = nfp;
 1027         cmode = ((SCARG(uap, mode) &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
 1028         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
 1029         p->p_dupfd = -indx - 1;                 /* XXX check for fdopen */
 1030         /*
 1031          * Bump the ref count to prevent another process from closing
 1032          * the descriptor while we are blocked in vn_open()
 1033          */
 1034         fhold(fp);
 1035         error = vn_open(&nd, flags, cmode);
 1036         if (error) {
 1037                 /*
 1038                  * release our own reference
 1039                  */
 1040                 fdrop(fp, p);
 1041 
 1042                 /*
 1043                  * handle special fdopen() case.  bleh.  dupfdopen() is
 1044                  * responsible for dropping the old contents of ofiles[indx]
 1045                  * if it succeeds.
 1046                  */
 1047                 if ((error == ENODEV || error == ENXIO) &&
 1048                     p->p_dupfd >= 0 &&                  /* XXX from fdopen */
 1049                     (error =
 1050                         dupfdopen(p, fdp, indx, p->p_dupfd, flags, error)) == 0) {
 1051                         p->p_retval[0] = indx;
 1052                         return (0);
 1053                 }
 1054                 /*
 1055                  * Clean up the descriptor, but only if another thread hadn't
 1056                  * replaced or closed it.
 1057                  */
 1058                 if (fdp->fd_ofiles[indx] == fp) {
 1059                         fdp->fd_ofiles[indx] = NULL;
 1060                         fdrop(fp, p);
 1061                 }
 1062 
 1063                 if (error == ERESTART)
 1064                         error = EINTR;
 1065                 return (error);
 1066         }
 1067         p->p_dupfd = 0;
 1068         NDFREE(&nd, NDF_ONLY_PNBUF);
 1069         vp = nd.ni_vp;
 1070 
 1071         /*
 1072          * There should be 2 references on the file, one from the descriptor
 1073          * table, and one for us.
 1074          *
 1075          * Handle the case where someone closed the file (via its file
 1076          * descriptor) while we were blocked.  The end result should look
 1077          * like opening the file succeeded but it was immediately closed.
 1078          */
 1079         if (fp->f_count == 1) {
 1080                 KASSERT(fdp->fd_ofiles[indx] != fp,
 1081                     ("Open file descriptor lost all refs"));
 1082                 VOP_UNLOCK(vp, 0, p);
 1083                 vn_close(vp, flags & FMASK, fp->f_cred, p);
 1084                 fdrop(fp, p);
 1085                 p->p_retval[0] = indx;
 1086                 return 0;
 1087         }
 1088 
 1089         fp->f_data = (caddr_t)vp;
 1090         fp->f_flag = flags & FMASK;
 1091         fp->f_ops = &vnops;
 1092         fp->f_type = (vp->v_type == VFIFO ? DTYPE_FIFO : DTYPE_VNODE);
 1093         if (flags & (O_EXLOCK | O_SHLOCK)) {
 1094                 lf.l_whence = SEEK_SET;
 1095                 lf.l_start = 0;
 1096                 lf.l_len = 0;
 1097                 if (flags & O_EXLOCK)
 1098                         lf.l_type = F_WRLCK;
 1099                 else
 1100                         lf.l_type = F_RDLCK;
 1101                 type = F_FLOCK;
 1102                 if ((flags & FNONBLOCK) == 0)
 1103                         type |= F_WAIT;
 1104                 VOP_UNLOCK(vp, 0, p);
 1105                 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0) {
 1106                         /*
 1107                          * lock request failed.  Normally close the descriptor
 1108                          * but handle the case where someone might have dup()d
 1109                          * it when we weren't looking.  One reference is
 1110                          * owned by the descriptor array, the other by us.
 1111                          */
 1112                         if (fdp->fd_ofiles[indx] == fp) {
 1113                                 fdp->fd_ofiles[indx] = NULL;
 1114                                 fdrop(fp, p);
 1115                         }
 1116                         fdrop(fp, p);
 1117                         return (error);
 1118                 }
 1119                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
 1120                 fp->f_flag |= FHASLOCK;
 1121         }
 1122         /* assert that vn_open created a backing object if one is needed */
 1123         KASSERT(!vn_canvmio(vp) || VOP_GETVOBJECT(vp, NULL) == 0,
 1124                 ("open: vmio vnode has no backing object after vn_open"));
 1125         VOP_UNLOCK(vp, 0, p);
 1126 
 1127         /*
 1128          * release our private reference, leaving the one associated with the
 1129          * descriptor table intact.
 1130          */
 1131         fdrop(fp, p);
 1132         p->p_retval[0] = indx;
 1133         return (0);
 1134 }
 1135 
 1136 #ifdef COMPAT_43
 1137 /*
 1138  * Create a file.
 1139  */
 1140 #ifndef _SYS_SYSPROTO_H_
 1141 struct ocreat_args {
 1142         char    *path;
 1143         int     mode;
 1144 };
 1145 #endif
 1146 int
 1147 ocreat(p, uap)
 1148         struct proc *p;
 1149         register struct ocreat_args /* {
 1150                 syscallarg(char *) path;
 1151                 syscallarg(int) mode;
 1152         } */ *uap;
 1153 {
 1154         struct open_args /* {
 1155                 syscallarg(char *) path;
 1156                 syscallarg(int) flags;
 1157                 syscallarg(int) mode;
 1158         } */ nuap;
 1159 
 1160         SCARG(&nuap, path) = SCARG(uap, path);
 1161         SCARG(&nuap, mode) = SCARG(uap, mode);
 1162         SCARG(&nuap, flags) = O_WRONLY | O_CREAT | O_TRUNC;
 1163         return (open(p, &nuap));
 1164 }
 1165 #endif /* COMPAT_43 */
 1166 
 1167 /*
 1168  * Create a special file.
 1169  */
 1170 #ifndef _SYS_SYSPROTO_H_
 1171 struct mknod_args {
 1172         char    *path;
 1173         int     mode;
 1174         int     dev;
 1175 };
 1176 #endif
 1177 /* ARGSUSED */
 1178 int
 1179 mknod(p, uap)
 1180         struct proc *p;
 1181         register struct mknod_args /* {
 1182                 syscallarg(char *) path;
 1183                 syscallarg(int) mode;
 1184                 syscallarg(int) dev;
 1185         } */ *uap;
 1186 {
 1187         register struct vnode *vp;
 1188         struct vattr vattr;
 1189         int error;
 1190         int whiteout = 0;
 1191         struct nameidata nd;
 1192 
 1193         switch (SCARG(uap, mode) & S_IFMT) {
 1194         case S_IFCHR:
 1195         case S_IFBLK:
 1196                 error = suser(p);
 1197                 break;
 1198         default:
 1199                 error = suser_xxx(0, p, PRISON_ROOT);
 1200                 break;
 1201         }
 1202         if (error)
 1203                 return (error);
 1204         bwillwrite();
 1205         NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
 1206         if ((error = namei(&nd)) != 0)
 1207                 return (error);
 1208         vp = nd.ni_vp;
 1209         if (vp != NULL)
 1210                 error = EEXIST;
 1211         else {
 1212                 VATTR_NULL(&vattr);
 1213                 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
 1214                 vattr.va_rdev = SCARG(uap, dev);
 1215                 whiteout = 0;
 1216 
 1217                 switch (SCARG(uap, mode) & S_IFMT) {
 1218                 case S_IFMT:    /* used by badsect to flag bad sectors */
 1219                         vattr.va_type = VBAD;
 1220                         break;
 1221                 case S_IFCHR:
 1222                         vattr.va_type = VCHR;
 1223                         break;
 1224                 case S_IFBLK:
 1225                         vattr.va_type = VBLK;
 1226                         break;
 1227                 case S_IFWHT:
 1228                         whiteout = 1;
 1229                         break;
 1230                 default:
 1231                         error = EINVAL;
 1232                         break;
 1233                 }
 1234         }
 1235         if (!error) {
 1236                 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
 1237                 if (whiteout)
 1238                         error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE);
 1239                 else {
 1240                         error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp,
 1241                                                 &nd.ni_cnd, &vattr);
 1242                         if (error == 0)
 1243                                 vput(nd.ni_vp);
 1244                 }
 1245                 NDFREE(&nd, NDF_ONLY_PNBUF);
 1246                 vput(nd.ni_dvp);
 1247         } else {
 1248                 NDFREE(&nd, NDF_ONLY_PNBUF);
 1249                 if (nd.ni_dvp == vp)
 1250                         vrele(nd.ni_dvp);
 1251                 else
 1252                         vput(nd.ni_dvp);
 1253                 if (vp)
 1254                         vrele(vp);
 1255         }
 1256         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mknod");
 1257         ASSERT_VOP_UNLOCKED(nd.ni_vp, "mknod");
 1258         return (error);
 1259 }
 1260 
 1261 /*
 1262  * Create a named pipe.
 1263  */
 1264 #ifndef _SYS_SYSPROTO_H_
 1265 struct mkfifo_args {
 1266         char    *path;
 1267         int     mode;
 1268 };
 1269 #endif
 1270 /* ARGSUSED */
 1271 int
 1272 mkfifo(p, uap)
 1273         struct proc *p;
 1274         register struct mkfifo_args /* {
 1275                 syscallarg(char *) path;
 1276                 syscallarg(int) mode;
 1277         } */ *uap;
 1278 {
 1279         struct vattr vattr;
 1280         int error;
 1281         struct nameidata nd;
 1282 
 1283         bwillwrite();
 1284         NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
 1285         if ((error = namei(&nd)) != 0)
 1286                 return (error);
 1287         if (nd.ni_vp != NULL) {
 1288                 NDFREE(&nd, NDF_ONLY_PNBUF);
 1289                 if (nd.ni_dvp == nd.ni_vp)
 1290                         vrele(nd.ni_dvp);
 1291                 else
 1292                         vput(nd.ni_dvp);
 1293                 vrele(nd.ni_vp);
 1294                 return (EEXIST);
 1295         }
 1296         VATTR_NULL(&vattr);
 1297         vattr.va_type = VFIFO;
 1298         vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
 1299         VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
 1300         error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
 1301         if (error == 0)
 1302                 vput(nd.ni_vp);
 1303         NDFREE(&nd, NDF_ONLY_PNBUF);
 1304         vput(nd.ni_dvp);
 1305         return (error);
 1306 }
 1307 
 1308 /*
 1309  * Make a hard file link.
 1310  */
 1311 #ifndef _SYS_SYSPROTO_H_
 1312 struct link_args {
 1313         char    *path;
 1314         char    *link;
 1315 };
 1316 #endif
 1317 /* ARGSUSED */
 1318 int
 1319 link(p, uap)
 1320         struct proc *p;
 1321         register struct link_args /* {
 1322                 syscallarg(char *) path;
 1323                 syscallarg(char *) link;
 1324         } */ *uap;
 1325 {
 1326         register struct vnode *vp;
 1327         struct nameidata nd;
 1328         int error;
 1329 
 1330         bwillwrite();
 1331         NDINIT(&nd, LOOKUP, FOLLOW|NOOBJ, UIO_USERSPACE, SCARG(uap, path), p);
 1332         if ((error = namei(&nd)) != 0)
 1333                 return (error);
 1334         NDFREE(&nd, NDF_ONLY_PNBUF);
 1335         vp = nd.ni_vp;
 1336         if (vp->v_type == VDIR)
 1337                 error = EPERM;          /* POSIX */
 1338         else {
 1339                 NDINIT(&nd, CREATE, LOCKPARENT|NOOBJ, UIO_USERSPACE, SCARG(uap, link), p);
 1340                 error = namei(&nd);
 1341                 if (!error) {
 1342                         if (nd.ni_vp != NULL) {
 1343                                 if (nd.ni_vp)
 1344                                         vrele(nd.ni_vp);
 1345                                 error = EEXIST;
 1346                         } else {
 1347                                 VOP_LEASE(nd.ni_dvp, p, p->p_ucred,
 1348                                     LEASE_WRITE);
 1349                                 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
 1350                                 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
 1351                         }
 1352                         NDFREE(&nd, NDF_ONLY_PNBUF);
 1353                         if (nd.ni_dvp == nd.ni_vp)
 1354                                 vrele(nd.ni_dvp);
 1355                         else
 1356                                 vput(nd.ni_dvp);
 1357                 }
 1358         }
 1359         vrele(vp);
 1360         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "link");
 1361         ASSERT_VOP_UNLOCKED(nd.ni_vp, "link");
 1362         return (error);
 1363 }
 1364 
 1365 /*
 1366  * Make a symbolic link.
 1367  */
 1368 #ifndef _SYS_SYSPROTO_H_
 1369 struct symlink_args {
 1370         char    *path;
 1371         char    *link;
 1372 };
 1373 #endif
 1374 /* ARGSUSED */
 1375 int
 1376 symlink(p, uap)
 1377         struct proc *p;
 1378         register struct symlink_args /* {
 1379                 syscallarg(char *) path;
 1380                 syscallarg(char *) link;
 1381         } */ *uap;
 1382 {
 1383         struct vattr vattr;
 1384         char *path;
 1385         int error;
 1386         struct nameidata nd;
 1387 
 1388         path = zalloc(namei_zone);
 1389         if ((error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL)) != 0)
 1390                 goto out;
 1391         bwillwrite();
 1392         NDINIT(&nd, CREATE, LOCKPARENT|NOOBJ, UIO_USERSPACE, SCARG(uap, link), p);
 1393         if ((error = namei(&nd)) != 0)
 1394                 goto out;
 1395         if (nd.ni_vp) {
 1396                 NDFREE(&nd, NDF_ONLY_PNBUF);
 1397                 if (nd.ni_dvp == nd.ni_vp)
 1398                         vrele(nd.ni_dvp);
 1399                 else
 1400                         vput(nd.ni_dvp);
 1401                 vrele(nd.ni_vp);
 1402                 error = EEXIST;
 1403                 goto out;
 1404         }
 1405         VATTR_NULL(&vattr);
 1406         vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask;
 1407         VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
 1408         error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path);
 1409         NDFREE(&nd, NDF_ONLY_PNBUF);
 1410         if (error == 0)
 1411                 vput(nd.ni_vp);
 1412         vput(nd.ni_dvp);
 1413         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "symlink");
 1414         ASSERT_VOP_UNLOCKED(nd.ni_vp, "symlink");
 1415 out:
 1416         zfree(namei_zone, path);
 1417         return (error);
 1418 }
 1419 
 1420 /*
 1421  * Delete a whiteout from the filesystem.
 1422  */
 1423 /* ARGSUSED */
 1424 int
 1425 undelete(p, uap)
 1426         struct proc *p;
 1427         register struct undelete_args /* {
 1428                 syscallarg(char *) path;
 1429         } */ *uap;
 1430 {
 1431         int error;
 1432         struct nameidata nd;
 1433 
 1434         bwillwrite();
 1435         NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE,
 1436             SCARG(uap, path), p);
 1437         error = namei(&nd);
 1438         if (error)
 1439                 return (error);
 1440 
 1441         if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) {
 1442                 NDFREE(&nd, NDF_ONLY_PNBUF);
 1443                 if (nd.ni_dvp == nd.ni_vp)
 1444                         vrele(nd.ni_dvp);
 1445                 else
 1446                         vput(nd.ni_dvp);
 1447                 if (nd.ni_vp)
 1448                         vrele(nd.ni_vp);
 1449                 return (EEXIST);
 1450         }
 1451 
 1452         VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
 1453         error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE);
 1454         NDFREE(&nd, NDF_ONLY_PNBUF);
 1455         vput(nd.ni_dvp);
 1456         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "undelete");
 1457         ASSERT_VOP_UNLOCKED(nd.ni_vp, "undelete");
 1458         return (error);
 1459 }
 1460 
 1461 /*
 1462  * Delete a name from the filesystem.
 1463  */
 1464 #ifndef _SYS_SYSPROTO_H_
 1465 struct unlink_args {
 1466         char    *path;
 1467 };
 1468 #endif
 1469 /* ARGSUSED */
 1470 int
 1471 unlink(p, uap)
 1472         struct proc *p;
 1473         struct unlink_args /* {
 1474                 syscallarg(char *) path;
 1475         } */ *uap;
 1476 {
 1477         register struct vnode *vp;
 1478         int error;
 1479         struct nameidata nd;
 1480 
 1481         bwillwrite();
 1482         NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
 1483         if ((error = namei(&nd)) != 0)
 1484                 return (error);
 1485         vp = nd.ni_vp;
 1486         VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
 1487         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
 1488 
 1489         if (vp->v_type == VDIR)
 1490                 error = EPERM;          /* POSIX */
 1491         else {
 1492                 /*
 1493                  * The root of a mounted filesystem cannot be deleted.
 1494                  *
 1495                  * XXX: can this only be a VDIR case?
 1496                  */
 1497                 if (vp->v_flag & VROOT)
 1498                         error = EBUSY;
 1499         }
 1500 
 1501         if (!error) {
 1502                 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
 1503                 error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd);
 1504         }
 1505         NDFREE(&nd, NDF_ONLY_PNBUF);
 1506         if (nd.ni_dvp == vp)
 1507                 vrele(nd.ni_dvp);
 1508         else
 1509                 vput(nd.ni_dvp);
 1510         if (vp != NULLVP)
 1511                 vput(vp);
 1512         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "unlink");
 1513         ASSERT_VOP_UNLOCKED(nd.ni_vp, "unlink");
 1514         return (error);
 1515 }
 1516 
 1517 /*
 1518  * Reposition read/write file offset.
 1519  */
 1520 #ifndef _SYS_SYSPROTO_H_
 1521 struct lseek_args {
 1522         int     fd;
 1523         int     pad;
 1524         off_t   offset;
 1525         int     whence;
 1526 };
 1527 #endif
 1528 int
 1529 lseek(p, uap)
 1530         struct proc *p;
 1531         register struct lseek_args /* {
 1532                 syscallarg(int) fd;
 1533                 syscallarg(int) pad;
 1534                 syscallarg(off_t) offset;
 1535                 syscallarg(int) whence;
 1536         } */ *uap;
 1537 {
 1538         struct ucred *cred = p->p_ucred;
 1539         register struct filedesc *fdp = p->p_fd;
 1540         register struct file *fp;
 1541         struct vattr vattr;
 1542         int error;
 1543 
 1544         if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles ||
 1545             (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL)
 1546                 return (EBADF);
 1547         if (fp->f_type != DTYPE_VNODE)
 1548                 return (ESPIPE);
 1549         switch (SCARG(uap, whence)) {
 1550         case L_INCR:
 1551                 fp->f_offset += SCARG(uap, offset);
 1552                 break;
 1553         case L_XTND:
 1554                 error=VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p);
 1555                 if (error)
 1556                         return (error);
 1557                 fp->f_offset = SCARG(uap, offset) + vattr.va_size;
 1558                 break;
 1559         case L_SET:
 1560                 fp->f_offset = SCARG(uap, offset);
 1561                 break;
 1562         default:
 1563                 return (EINVAL);
 1564         }
 1565         *(off_t *)(p->p_retval) = fp->f_offset;
 1566         return (0);
 1567 }
 1568 
 1569 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
 1570 /*
 1571  * Reposition read/write file offset.
 1572  */
 1573 #ifndef _SYS_SYSPROTO_H_
 1574 struct olseek_args {
 1575         int     fd;
 1576         long    offset;
 1577         int     whence;
 1578 };
 1579 #endif
 1580 int
 1581 olseek(p, uap)
 1582         struct proc *p;
 1583         register struct olseek_args /* {
 1584                 syscallarg(int) fd;
 1585                 syscallarg(long) offset;
 1586                 syscallarg(int) whence;
 1587         } */ *uap;
 1588 {
 1589         struct lseek_args /* {
 1590                 syscallarg(int) fd;
 1591                 syscallarg(int) pad;
 1592                 syscallarg(off_t) offset;
 1593                 syscallarg(int) whence;
 1594         } */ nuap;
 1595         int error;
 1596 
 1597         SCARG(&nuap, fd) = SCARG(uap, fd);
 1598         SCARG(&nuap, offset) = SCARG(uap, offset);
 1599         SCARG(&nuap, whence) = SCARG(uap, whence);
 1600         error = lseek(p, &nuap);
 1601         return (error);
 1602 }
 1603 #endif /* COMPAT_43 */
 1604 
 1605 /*
 1606  * Check access permissions.
 1607  */
 1608 #ifndef _SYS_SYSPROTO_H_
 1609 struct access_args {
 1610         char    *path;
 1611         int     flags;
 1612 };
 1613 #endif
 1614 int
 1615 access(p, uap)
 1616         struct proc *p;
 1617         register struct access_args /* {
 1618                 syscallarg(char *) path;
 1619                 syscallarg(int) flags;
 1620         } */ *uap;
 1621 {
 1622         struct ucred *cred, *tmpcred;
 1623         register struct vnode *vp;
 1624         int error, flags;
 1625         struct nameidata nd;
 1626 
 1627         cred = p->p_ucred;
 1628         /*
 1629          * Create and modify a temporary credential instead of one that
 1630          * is potentially shared.  This could also mess up socket
 1631          * buffer accounting which can run in an interrupt context.
 1632          */
 1633         tmpcred = crdup(cred);
 1634         tmpcred->cr_uid = p->p_cred->p_ruid;
 1635         tmpcred->cr_groups[0] = p->p_cred->p_rgid;
 1636         p->p_ucred = tmpcred;
 1637         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
 1638             SCARG(uap, path), p);
 1639         if ((error = namei(&nd)) != 0)
 1640                 goto out1;
 1641         vp = nd.ni_vp;
 1642 
 1643         /* Flags == 0 means only check for existence. */
 1644         if (SCARG(uap, flags)) {
 1645                 flags = 0;
 1646                 if (SCARG(uap, flags) & R_OK)
 1647                         flags |= VREAD;
 1648                 if (SCARG(uap, flags) & W_OK)
 1649                         flags |= VWRITE;
 1650                 if (SCARG(uap, flags) & X_OK)
 1651                         flags |= VEXEC;
 1652                 if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
 1653                         error = VOP_ACCESS(vp, flags, tmpcred, p);
 1654         }
 1655         NDFREE(&nd, NDF_ONLY_PNBUF);
 1656         vput(vp);
 1657 out1:
 1658         p->p_ucred = cred;
 1659         crfree(tmpcred);
 1660         return (error);
 1661 }
 1662 
 1663 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
 1664 /*
 1665  * Get file status; this version follows links.
 1666  */
 1667 #ifndef _SYS_SYSPROTO_H_
 1668 struct ostat_args {
 1669         char    *path;
 1670         struct ostat *ub;
 1671 };
 1672 #endif
 1673 /* ARGSUSED */
 1674 int
 1675 ostat(p, uap)
 1676         struct proc *p;
 1677         register struct ostat_args /* {
 1678                 syscallarg(char *) path;
 1679                 syscallarg(struct ostat *) ub;
 1680         } */ *uap;
 1681 {
 1682         struct stat sb;
 1683         struct ostat osb;
 1684         int error;
 1685         struct nameidata nd;
 1686 
 1687         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
 1688             SCARG(uap, path), p);
 1689         if ((error = namei(&nd)) != 0)
 1690                 return (error);
 1691         NDFREE(&nd, NDF_ONLY_PNBUF);
 1692         error = vn_stat(nd.ni_vp, &sb, p);
 1693         vput(nd.ni_vp);
 1694         if (error)
 1695                 return (error);
 1696         cvtstat(&sb, &osb);
 1697         error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb));
 1698         return (error);
 1699 }
 1700 
 1701 /*
 1702  * Get file status; this version does not follow links.
 1703  */
 1704 #ifndef _SYS_SYSPROTO_H_
 1705 struct olstat_args {
 1706         char    *path;
 1707         struct ostat *ub;
 1708 };
 1709 #endif
 1710 /* ARGSUSED */
 1711 int
 1712 olstat(p, uap)
 1713         struct proc *p;
 1714         register struct olstat_args /* {
 1715                 syscallarg(char *) path;
 1716                 syscallarg(struct ostat *) ub;
 1717         } */ *uap;
 1718 {
 1719         struct vnode *vp;
 1720         struct stat sb;
 1721         struct ostat osb;
 1722         int error;
 1723         struct nameidata nd;
 1724 
 1725         NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
 1726             SCARG(uap, path), p);
 1727         if ((error = namei(&nd)) != 0)
 1728                 return (error);
 1729         vp = nd.ni_vp;
 1730         error = vn_stat(vp, &sb, p);
 1731         NDFREE(&nd, NDF_ONLY_PNBUF);
 1732         vput(vp);
 1733         if (error)
 1734                 return (error);
 1735         cvtstat(&sb, &osb);
 1736         error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb));
 1737         return (error);
 1738 }
 1739 
 1740 /*
 1741  * Convert from an old to a new stat structure.
 1742  */
 1743 void
 1744 cvtstat(st, ost)
 1745         struct stat *st;
 1746         struct ostat *ost;
 1747 {
 1748 
 1749         ost->st_dev = st->st_dev;
 1750         ost->st_ino = st->st_ino;
 1751         ost->st_mode = st->st_mode;
 1752         ost->st_nlink = st->st_nlink;
 1753         ost->st_uid = st->st_uid;
 1754         ost->st_gid = st->st_gid;
 1755         ost->st_rdev = st->st_rdev;
 1756         if (st->st_size < (quad_t)1 << 32)
 1757                 ost->st_size = st->st_size;
 1758         else
 1759                 ost->st_size = -2;
 1760         ost->st_atime = st->st_atime;
 1761         ost->st_mtime = st->st_mtime;
 1762         ost->st_ctime = st->st_ctime;
 1763         ost->st_blksize = st->st_blksize;
 1764         ost->st_blocks = st->st_blocks;
 1765         ost->st_flags = st->st_flags;
 1766         ost->st_gen = st->st_gen;
 1767 }
 1768 #endif /* COMPAT_43 || COMPAT_SUNOS */
 1769 
 1770 /*
 1771  * Get file status; this version follows links.
 1772  */
 1773 #ifndef _SYS_SYSPROTO_H_
 1774 struct stat_args {
 1775         char    *path;
 1776         struct stat *ub;
 1777 };
 1778 #endif
 1779 /* ARGSUSED */
 1780 int
 1781 stat(p, uap)
 1782         struct proc *p;
 1783         register struct stat_args /* {
 1784                 syscallarg(char *) path;
 1785                 syscallarg(struct stat *) ub;
 1786         } */ *uap;
 1787 {
 1788         struct stat sb;
 1789         int error;
 1790         struct nameidata nd;
 1791 
 1792         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
 1793             SCARG(uap, path), p);
 1794         if ((error = namei(&nd)) != 0)
 1795                 return (error);
 1796         error = vn_stat(nd.ni_vp, &sb, p);
 1797         NDFREE(&nd, NDF_ONLY_PNBUF);
 1798         vput(nd.ni_vp);
 1799         if (error)
 1800                 return (error);
 1801         error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb));
 1802         return (error);
 1803 }
 1804 
 1805 /*
 1806  * Get file status; this version does not follow links.
 1807  */
 1808 #ifndef _SYS_SYSPROTO_H_
 1809 struct lstat_args {
 1810         char    *path;
 1811         struct stat *ub;
 1812 };
 1813 #endif
 1814 /* ARGSUSED */
 1815 int
 1816 lstat(p, uap)
 1817         struct proc *p;
 1818         register struct lstat_args /* {
 1819                 syscallarg(char *) path;
 1820                 syscallarg(struct stat *) ub;
 1821         } */ *uap;
 1822 {
 1823         int error;
 1824         struct vnode *vp;
 1825         struct stat sb;
 1826         struct nameidata nd;
 1827 
 1828         NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
 1829             SCARG(uap, path), p);
 1830         if ((error = namei(&nd)) != 0)
 1831                 return (error);
 1832         vp = nd.ni_vp;
 1833         error = vn_stat(vp, &sb, p);
 1834         NDFREE(&nd, NDF_ONLY_PNBUF);
 1835         vput(vp);
 1836         if (error)
 1837                 return (error);
 1838         error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb));
 1839         return (error);
 1840 }
 1841 
 1842 void
 1843 cvtnstat(sb, nsb)
 1844         struct stat *sb;
 1845         struct nstat *nsb;
 1846 {
 1847         nsb->st_dev = sb->st_dev;
 1848         nsb->st_ino = sb->st_ino;
 1849         nsb->st_mode = sb->st_mode;
 1850         nsb->st_nlink = sb->st_nlink;
 1851         nsb->st_uid = sb->st_uid;
 1852         nsb->st_gid = sb->st_gid;
 1853         nsb->st_rdev = sb->st_rdev;
 1854         nsb->st_atimespec = sb->st_atimespec;
 1855         nsb->st_mtimespec = sb->st_mtimespec;
 1856         nsb->st_ctimespec = sb->st_ctimespec;
 1857         nsb->st_size = sb->st_size;
 1858         nsb->st_blocks = sb->st_blocks;
 1859         nsb->st_blksize = sb->st_blksize;
 1860         nsb->st_flags = sb->st_flags;
 1861         nsb->st_gen = sb->st_gen;
 1862         nsb->st_qspare[0] = sb->st_qspare[0];
 1863         nsb->st_qspare[1] = sb->st_qspare[1];
 1864 }
 1865 
 1866 #ifndef _SYS_SYSPROTO_H_
 1867 struct nstat_args {
 1868         char    *path;
 1869         struct nstat *ub;
 1870 };
 1871 #endif
 1872 /* ARGSUSED */
 1873 int
 1874 nstat(p, uap)
 1875         struct proc *p;
 1876         register struct nstat_args /* {
 1877                 syscallarg(char *) path;
 1878                 syscallarg(struct nstat *) ub;
 1879         } */ *uap;
 1880 {
 1881         struct stat sb;
 1882         struct nstat nsb;
 1883         int error;
 1884         struct nameidata nd;
 1885 
 1886         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
 1887             SCARG(uap, path), p);
 1888         if ((error = namei(&nd)) != 0)
 1889                 return (error);
 1890         NDFREE(&nd, NDF_ONLY_PNBUF);
 1891         error = vn_stat(nd.ni_vp, &sb, p);
 1892         vput(nd.ni_vp);
 1893         if (error)
 1894                 return (error);
 1895         cvtnstat(&sb, &nsb);
 1896         error = copyout((caddr_t)&nsb, (caddr_t)SCARG(uap, ub), sizeof (nsb));
 1897         return (error);
 1898 }
 1899 
 1900 /*
 1901  * Get file status; this version does not follow links.
 1902  */
 1903 #ifndef _SYS_SYSPROTO_H_
 1904 struct lstat_args {
 1905         char    *path;
 1906         struct stat *ub;
 1907 };
 1908 #endif
 1909 /* ARGSUSED */
 1910 int
 1911 nlstat(p, uap)
 1912         struct proc *p;
 1913         register struct nlstat_args /* {
 1914                 syscallarg(char *) path;
 1915                 syscallarg(struct nstat *) ub;
 1916         } */ *uap;
 1917 {
 1918         int error;
 1919         struct vnode *vp;
 1920         struct stat sb;
 1921         struct nstat nsb;
 1922         struct nameidata nd;
 1923 
 1924         NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
 1925             SCARG(uap, path), p);
 1926         if ((error = namei(&nd)) != 0)
 1927                 return (error);
 1928         vp = nd.ni_vp;
 1929         NDFREE(&nd, NDF_ONLY_PNBUF);
 1930         error = vn_stat(vp, &sb, p);
 1931         vput(vp);
 1932         if (error)
 1933                 return (error);
 1934         cvtnstat(&sb, &nsb);
 1935         error = copyout((caddr_t)&nsb, (caddr_t)SCARG(uap, ub), sizeof (nsb));
 1936         return (error);
 1937 }
 1938 
 1939 /*
 1940  * Get configurable pathname variables.
 1941  */
 1942 #ifndef _SYS_SYSPROTO_H_
 1943 struct pathconf_args {
 1944         char    *path;
 1945         int     name;
 1946 };
 1947 #endif
 1948 /* ARGSUSED */
 1949 int
 1950 pathconf(p, uap)
 1951         struct proc *p;
 1952         register struct pathconf_args /* {
 1953                 syscallarg(char *) path;
 1954                 syscallarg(int) name;
 1955         } */ *uap;
 1956 {
 1957         int error;
 1958         struct nameidata nd;
 1959 
 1960         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
 1961             SCARG(uap, path), p);
 1962         if ((error = namei(&nd)) != 0)
 1963                 return (error);
 1964         NDFREE(&nd, NDF_ONLY_PNBUF);
 1965         error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), p->p_retval);
 1966         vput(nd.ni_vp);
 1967         return (error);
 1968 }
 1969 
 1970 /*
 1971  * Return target name of a symbolic link.
 1972  */
 1973 #ifndef _SYS_SYSPROTO_H_
 1974 struct readlink_args {
 1975         char    *path;
 1976         char    *buf;
 1977         int     count;
 1978 };
 1979 #endif
 1980 /* ARGSUSED */
 1981 int
 1982 readlink(p, uap)
 1983         struct proc *p;
 1984         register struct readlink_args /* {
 1985                 syscallarg(char *) path;
 1986                 syscallarg(char *) buf;
 1987                 syscallarg(int) count;
 1988         } */ *uap;
 1989 {
 1990         register struct vnode *vp;
 1991         struct iovec aiov;
 1992         struct uio auio;
 1993         int error;
 1994         struct nameidata nd;
 1995 
 1996         NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
 1997             SCARG(uap, path), p);
 1998         if ((error = namei(&nd)) != 0)
 1999                 return (error);
 2000         NDFREE(&nd, NDF_ONLY_PNBUF);
 2001         vp = nd.ni_vp;
 2002         if (vp->v_type != VLNK)
 2003                 error = EINVAL;
 2004         else {
 2005                 aiov.iov_base = SCARG(uap, buf);
 2006                 aiov.iov_len = SCARG(uap, count);
 2007                 auio.uio_iov = &aiov;
 2008                 auio.uio_iovcnt = 1;
 2009                 auio.uio_offset = 0;
 2010                 auio.uio_rw = UIO_READ;
 2011                 auio.uio_segflg = UIO_USERSPACE;
 2012                 auio.uio_procp = p;
 2013                 auio.uio_resid = SCARG(uap, count);
 2014                 error = VOP_READLINK(vp, &auio, p->p_ucred);
 2015         }
 2016         vput(vp);
 2017         p->p_retval[0] = SCARG(uap, count) - auio.uio_resid;
 2018         return (error);
 2019 }
 2020 
 2021 static int
 2022 setfflags(p, vp, flags)
 2023         struct proc *p;
 2024         struct vnode *vp;
 2025         int flags;
 2026 {
 2027         int error;
 2028         struct vattr vattr;
 2029 
 2030         /*
 2031          * Prevent non-root users from setting flags on devices.  When
 2032          * a device is reused, users can retain ownership of the device
 2033          * if they are allowed to set flags and programs assume that
 2034          * chown can't fail when done as root.
 2035          */
 2036         if ((vp->v_type == VCHR || vp->v_type == VBLK) && 
 2037             ((error = suser_xxx(p->p_ucred, p, PRISON_ROOT)) != 0))
 2038                 return (error);
 2039 
 2040         VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
 2041         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
 2042         VATTR_NULL(&vattr);
 2043         vattr.va_flags = flags;
 2044         error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
 2045         VOP_UNLOCK(vp, 0, p);
 2046         return (error);
 2047 }
 2048 
 2049 /*
 2050  * Change flags of a file given a path name.
 2051  */
 2052 #ifndef _SYS_SYSPROTO_H_
 2053 struct chflags_args {
 2054         char    *path;
 2055         int     flags;
 2056 };
 2057 #endif
 2058 /* ARGSUSED */
 2059 int
 2060 chflags(p, uap)
 2061         struct proc *p;
 2062         register struct chflags_args /* {
 2063                 syscallarg(char *) path;
 2064                 syscallarg(int) flags;
 2065         } */ *uap;
 2066 {
 2067         int error;
 2068         struct nameidata nd;
 2069 
 2070         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
 2071         if ((error = namei(&nd)) != 0)
 2072                 return (error);
 2073         NDFREE(&nd, NDF_ONLY_PNBUF);
 2074         error = setfflags(p, nd.ni_vp, SCARG(uap, flags));
 2075         vrele(nd.ni_vp);
 2076         return error;
 2077 }
 2078 
 2079 /*
 2080  * Change flags of a file given a file descriptor.
 2081  */
 2082 #ifndef _SYS_SYSPROTO_H_
 2083 struct fchflags_args {
 2084         int     fd;
 2085         int     flags;
 2086 };
 2087 #endif
 2088 /* ARGSUSED */
 2089 int
 2090 fchflags(p, uap)
 2091         struct proc *p;
 2092         register struct fchflags_args /* {
 2093                 syscallarg(int) fd;
 2094                 syscallarg(int) flags;
 2095         } */ *uap;
 2096 {
 2097         struct file *fp;
 2098         int error;
 2099 
 2100         if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
 2101                 return (error);
 2102         return setfflags(p, (struct vnode *) fp->f_data, SCARG(uap, flags));
 2103 }
 2104 
 2105 static int
 2106 setfmode(p, vp, mode)
 2107         struct proc *p;
 2108         struct vnode *vp;
 2109         int mode;
 2110 {
 2111         int error;
 2112         struct vattr vattr;
 2113 
 2114         VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
 2115         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
 2116         VATTR_NULL(&vattr);
 2117         vattr.va_mode = mode & ALLPERMS;
 2118         error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
 2119         VOP_UNLOCK(vp, 0, p);
 2120         return error;
 2121 }
 2122 
 2123 /*
 2124  * Change mode of a file given path name.
 2125  */
 2126 #ifndef _SYS_SYSPROTO_H_
 2127 struct chmod_args {
 2128         char    *path;
 2129         int     mode;
 2130 };
 2131 #endif
 2132 /* ARGSUSED */
 2133 int
 2134 chmod(p, uap)
 2135         struct proc *p;
 2136         register struct chmod_args /* {
 2137                 syscallarg(char *) path;
 2138                 syscallarg(int) mode;
 2139         } */ *uap;
 2140 {
 2141         int error;
 2142         struct nameidata nd;
 2143 
 2144         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
 2145         if ((error = namei(&nd)) != 0)
 2146                 return (error);
 2147         NDFREE(&nd, NDF_ONLY_PNBUF);
 2148         error = setfmode(p, nd.ni_vp, SCARG(uap, mode));
 2149         vrele(nd.ni_vp);
 2150         return error;
 2151 }
 2152 
 2153 /*
 2154  * Change mode of a file given path name (don't follow links.)
 2155  */
 2156 #ifndef _SYS_SYSPROTO_H_
 2157 struct lchmod_args {
 2158         char    *path;
 2159         int     mode;
 2160 };
 2161 #endif
 2162 /* ARGSUSED */
 2163 int
 2164 lchmod(p, uap)
 2165         struct proc *p;
 2166         register struct lchmod_args /* {
 2167                 syscallarg(char *) path;
 2168                 syscallarg(int) mode;
 2169         } */ *uap;
 2170 {
 2171         int error;
 2172         struct nameidata nd;
 2173 
 2174         NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
 2175         if ((error = namei(&nd)) != 0)
 2176                 return (error);
 2177         NDFREE(&nd, NDF_ONLY_PNBUF);
 2178         error = setfmode(p, nd.ni_vp, SCARG(uap, mode));
 2179         vrele(nd.ni_vp);
 2180         return error;
 2181 }
 2182 
 2183 /*
 2184  * Change mode of a file given a file descriptor.
 2185  */
 2186 #ifndef _SYS_SYSPROTO_H_
 2187 struct fchmod_args {
 2188         int     fd;
 2189         int     mode;
 2190 };
 2191 #endif
 2192 /* ARGSUSED */
 2193 int
 2194 fchmod(p, uap)
 2195         struct proc *p;
 2196         register struct fchmod_args /* {
 2197                 syscallarg(int) fd;
 2198                 syscallarg(int) mode;
 2199         } */ *uap;
 2200 {
 2201         struct file *fp;
 2202         int error;
 2203 
 2204         if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
 2205                 return (error);
 2206         return setfmode(p, (struct vnode *)fp->f_data, SCARG(uap, mode));
 2207 }
 2208 
 2209 static int
 2210 setfown(p, vp, uid, gid)
 2211         struct proc *p;
 2212         struct vnode *vp;
 2213         uid_t uid;
 2214         gid_t gid;
 2215 {
 2216         int error;
 2217         struct vattr vattr;
 2218 
 2219         VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
 2220         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
 2221         VATTR_NULL(&vattr);
 2222         vattr.va_uid = uid;
 2223         vattr.va_gid = gid;
 2224         error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
 2225         VOP_UNLOCK(vp, 0, p);
 2226         return error;
 2227 }
 2228 
 2229 /*
 2230  * Set ownership given a path name.
 2231  */
 2232 #ifndef _SYS_SYSPROTO_H_
 2233 struct chown_args {
 2234         char    *path;
 2235         int     uid;
 2236         int     gid;
 2237 };
 2238 #endif
 2239 /* ARGSUSED */
 2240 int
 2241 chown(p, uap)
 2242         struct proc *p;
 2243         register struct chown_args /* {
 2244                 syscallarg(char *) path;
 2245                 syscallarg(int) uid;
 2246                 syscallarg(int) gid;
 2247         } */ *uap;
 2248 {
 2249         int error;
 2250         struct nameidata nd;
 2251 
 2252         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
 2253         if ((error = namei(&nd)) != 0)
 2254                 return (error);
 2255         NDFREE(&nd, NDF_ONLY_PNBUF);
 2256         error = setfown(p, nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid));
 2257         vrele(nd.ni_vp);
 2258         return (error);
 2259 }
 2260 
 2261 /*
 2262  * Set ownership given a path name, do not cross symlinks.
 2263  */
 2264 #ifndef _SYS_SYSPROTO_H_
 2265 struct lchown_args {
 2266         char    *path;
 2267         int     uid;
 2268         int     gid;
 2269 };
 2270 #endif
 2271 /* ARGSUSED */
 2272 int
 2273 lchown(p, uap)
 2274         struct proc *p;
 2275         register struct lchown_args /* {
 2276                 syscallarg(char *) path;
 2277                 syscallarg(int) uid;
 2278                 syscallarg(int) gid;
 2279         } */ *uap;
 2280 {
 2281         int error;
 2282         struct nameidata nd;
 2283 
 2284         NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
 2285         if ((error = namei(&nd)) != 0)
 2286                 return (error);
 2287         NDFREE(&nd, NDF_ONLY_PNBUF);
 2288         error = setfown(p, nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid));
 2289         vrele(nd.ni_vp);
 2290         return (error);
 2291 }
 2292 
 2293 /*
 2294  * Set ownership given a file descriptor.
 2295  */
 2296 #ifndef _SYS_SYSPROTO_H_
 2297 struct fchown_args {
 2298         int     fd;
 2299         int     uid;
 2300         int     gid;
 2301 };
 2302 #endif
 2303 /* ARGSUSED */
 2304 int
 2305 fchown(p, uap)
 2306         struct proc *p;
 2307         register struct fchown_args /* {
 2308                 syscallarg(int) fd;
 2309                 syscallarg(int) uid;
 2310                 syscallarg(int) gid;
 2311         } */ *uap;
 2312 {
 2313         struct file *fp;
 2314         int error;
 2315 
 2316         if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
 2317                 return (error);
 2318         return setfown(p, (struct vnode *)fp->f_data,
 2319                 SCARG(uap, uid), SCARG(uap, gid));
 2320 }
 2321 
 2322 static int
 2323 getutimes(usrtvp, tsp)
 2324         const struct timeval *usrtvp;
 2325         struct timespec *tsp;
 2326 {
 2327         struct timeval tv[2];
 2328         int error;
 2329 
 2330         if (usrtvp == NULL) {
 2331                 microtime(&tv[0]);
 2332                 TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]);
 2333                 tsp[1] = tsp[0];
 2334         } else {
 2335                 if ((error = copyin(usrtvp, tv, sizeof (tv))) != 0)
 2336                         return (error);
 2337                 if (tv[0].tv_usec < 0 || tv[0].tv_usec >= 1000000 ||
 2338                     tv[1].tv_usec < 0 || tv[1].tv_usec >= 1000000)
 2339                         return (EINVAL);
 2340                 TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]);
 2341                 TIMEVAL_TO_TIMESPEC(&tv[1], &tsp[1]);
 2342         }
 2343         return 0;
 2344 }
 2345 
 2346 static int
 2347 setutimes(p, vp, ts, nullflag)
 2348         struct proc *p;
 2349         struct vnode *vp;
 2350         const struct timespec *ts;
 2351         int nullflag;
 2352 {
 2353         int error;
 2354         struct vattr vattr;
 2355 
 2356         VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
 2357         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
 2358         VATTR_NULL(&vattr);
 2359         vattr.va_atime = ts[0];
 2360         vattr.va_mtime = ts[1];
 2361         if (nullflag)
 2362                 vattr.va_vaflags |= VA_UTIMES_NULL;
 2363         error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
 2364         VOP_UNLOCK(vp, 0, p);
 2365         return error;
 2366 }
 2367 
 2368 /*
 2369  * Set the access and modification times of a file.
 2370  */
 2371 #ifndef _SYS_SYSPROTO_H_
 2372 struct utimes_args {
 2373         char    *path;
 2374         struct  timeval *tptr;
 2375 };
 2376 #endif
 2377 /* ARGSUSED */
 2378 int
 2379 utimes(p, uap)
 2380         struct proc *p;
 2381         register struct utimes_args /* {
 2382                 syscallarg(char *) path;
 2383                 syscallarg(struct timeval *) tptr;
 2384         } */ *uap;
 2385 {
 2386         struct timespec ts[2];
 2387         struct timeval *usrtvp;
 2388         int error;
 2389         struct nameidata nd;
 2390 
 2391         usrtvp = SCARG(uap, tptr);
 2392         if ((error = getutimes(usrtvp, ts)) != 0)
 2393                 return (error);
 2394         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
 2395         if ((error = namei(&nd)) != 0)
 2396                 return (error);
 2397         NDFREE(&nd, NDF_ONLY_PNBUF);
 2398         error = setutimes(p, nd.ni_vp, ts, usrtvp == NULL);
 2399         vrele(nd.ni_vp);
 2400         return (error);
 2401 }
 2402 
 2403 /*
 2404  * Set the access and modification times of a file.
 2405  */
 2406 #ifndef _SYS_SYSPROTO_H_
 2407 struct lutimes_args {
 2408         char    *path;
 2409         struct  timeval *tptr;
 2410 };
 2411 #endif
 2412 /* ARGSUSED */
 2413 int
 2414 lutimes(p, uap)
 2415         struct proc *p;
 2416         register struct lutimes_args /* {
 2417                 syscallarg(char *) path;
 2418                 syscallarg(struct timeval *) tptr;
 2419         } */ *uap;
 2420 {
 2421         struct timespec ts[2];
 2422         struct timeval *usrtvp;
 2423         int error;
 2424         struct nameidata nd;
 2425 
 2426         usrtvp = SCARG(uap, tptr);
 2427         if ((error = getutimes(usrtvp, ts)) != 0)
 2428                 return (error);
 2429         NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
 2430         if ((error = namei(&nd)) != 0)
 2431                 return (error);
 2432         NDFREE(&nd, NDF_ONLY_PNBUF);
 2433         error = setutimes(p, nd.ni_vp, ts, usrtvp == NULL);
 2434         vrele(nd.ni_vp);
 2435         return (error);
 2436 }
 2437 
 2438 /*
 2439  * Set the access and modification times of a file.
 2440  */
 2441 #ifndef _SYS_SYSPROTO_H_
 2442 struct futimes_args {
 2443         int     fd;
 2444         struct  timeval *tptr;
 2445 };
 2446 #endif
 2447 /* ARGSUSED */
 2448 int
 2449 futimes(p, uap)
 2450         struct proc *p;
 2451         register struct futimes_args /* {
 2452                 syscallarg(int ) fd;
 2453                 syscallarg(struct timeval *) tptr;
 2454         } */ *uap;
 2455 {
 2456         struct timespec ts[2];
 2457         struct file *fp;
 2458         struct timeval *usrtvp;
 2459         int error;
 2460 
 2461         usrtvp = SCARG(uap, tptr);
 2462         if ((error = getutimes(usrtvp, ts)) != 0)
 2463                 return (error);
 2464         if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
 2465                 return (error);
 2466         return setutimes(p, (struct vnode *)fp->f_data, ts, usrtvp == NULL);
 2467 }
 2468 
 2469 /*
 2470  * Truncate a file given its path name.
 2471  */
 2472 #ifndef _SYS_SYSPROTO_H_
 2473 struct truncate_args {
 2474         char    *path;
 2475         int     pad;
 2476         off_t   length;
 2477 };
 2478 #endif
 2479 /* ARGSUSED */
 2480 int
 2481 truncate(p, uap)
 2482         struct proc *p;
 2483         register struct truncate_args /* {
 2484                 syscallarg(char *) path;
 2485                 syscallarg(int) pad;
 2486                 syscallarg(off_t) length;
 2487         } */ *uap;
 2488 {
 2489         register struct vnode *vp;
 2490         struct vattr vattr;
 2491         int error;
 2492         struct nameidata nd;
 2493 
 2494         if (uap->length < 0)
 2495                 return(EINVAL);
 2496         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
 2497         if ((error = namei(&nd)) != 0)
 2498                 return (error);
 2499         vp = nd.ni_vp;
 2500         NDFREE(&nd, NDF_ONLY_PNBUF);
 2501         VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
 2502         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
 2503         if (vp->v_type == VDIR)
 2504                 error = EISDIR;
 2505         else if ((error = vn_writechk(vp)) == 0 &&
 2506             (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) {
 2507                 VATTR_NULL(&vattr);
 2508                 vattr.va_size = SCARG(uap, length);
 2509                 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
 2510         }
 2511         vput(vp);
 2512         return (error);
 2513 }
 2514 
 2515 /*
 2516  * Truncate a file given a file descriptor.
 2517  */
 2518 #ifndef _SYS_SYSPROTO_H_
 2519 struct ftruncate_args {
 2520         int     fd;
 2521         int     pad;
 2522         off_t   length;
 2523 };
 2524 #endif
 2525 /* ARGSUSED */
 2526 int
 2527 ftruncate(p, uap)
 2528         struct proc *p;
 2529         register struct ftruncate_args /* {
 2530                 syscallarg(int) fd;
 2531                 syscallarg(int) pad;
 2532                 syscallarg(off_t) length;
 2533         } */ *uap;
 2534 {
 2535         struct vattr vattr;
 2536         struct vnode *vp;
 2537         struct file *fp;
 2538         int error;
 2539 
 2540         if (uap->length < 0)
 2541                 return(EINVAL);
 2542         if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
 2543                 return (error);
 2544         if ((fp->f_flag & FWRITE) == 0)
 2545                 return (EINVAL);
 2546         vp = (struct vnode *)fp->f_data;
 2547         VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
 2548         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
 2549         if (vp->v_type == VDIR)
 2550                 error = EISDIR;
 2551         else if ((error = vn_writechk(vp)) == 0) {
 2552                 VATTR_NULL(&vattr);
 2553                 vattr.va_size = SCARG(uap, length);
 2554                 error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
 2555         }
 2556         VOP_UNLOCK(vp, 0, p);
 2557         return (error);
 2558 }
 2559 
 2560 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
 2561 /*
 2562  * Truncate a file given its path name.
 2563  */
 2564 #ifndef _SYS_SYSPROTO_H_
 2565 struct otruncate_args {
 2566         char    *path;
 2567         long    length;
 2568 };
 2569 #endif
 2570 /* ARGSUSED */
 2571 int
 2572 otruncate(p, uap)
 2573         struct proc *p;
 2574         register struct otruncate_args /* {
 2575                 syscallarg(char *) path;
 2576                 syscallarg(long) length;
 2577         } */ *uap;
 2578 {
 2579         struct truncate_args /* {
 2580                 syscallarg(char *) path;
 2581                 syscallarg(int) pad;
 2582                 syscallarg(off_t) length;
 2583         } */ nuap;
 2584 
 2585         SCARG(&nuap, path) = SCARG(uap, path);
 2586         SCARG(&nuap, length) = SCARG(uap, length);
 2587         return (truncate(p, &nuap));
 2588 }
 2589 
 2590 /*
 2591  * Truncate a file given a file descriptor.
 2592  */
 2593 #ifndef _SYS_SYSPROTO_H_
 2594 struct oftruncate_args {
 2595         int     fd;
 2596         long    length;
 2597 };
 2598 #endif
 2599 /* ARGSUSED */
 2600 int
 2601 oftruncate(p, uap)
 2602         struct proc *p;
 2603         register struct oftruncate_args /* {
 2604                 syscallarg(int) fd;
 2605                 syscallarg(long) length;
 2606         } */ *uap;
 2607 {
 2608         struct ftruncate_args /* {
 2609                 syscallarg(int) fd;
 2610                 syscallarg(int) pad;
 2611                 syscallarg(off_t) length;
 2612         } */ nuap;
 2613 
 2614         SCARG(&nuap, fd) = SCARG(uap, fd);
 2615         SCARG(&nuap, length) = SCARG(uap, length);
 2616         return (ftruncate(p, &nuap));
 2617 }
 2618 #endif /* COMPAT_43 || COMPAT_SUNOS */
 2619 
 2620 /*
 2621  * Sync an open file.
 2622  */
 2623 #ifndef _SYS_SYSPROTO_H_
 2624 struct fsync_args {
 2625         int     fd;
 2626 };
 2627 #endif
 2628 /* ARGSUSED */
 2629 int
 2630 fsync(p, uap)
 2631         struct proc *p;
 2632         struct fsync_args /* {
 2633                 syscallarg(int) fd;
 2634         } */ *uap;
 2635 {
 2636         register struct vnode *vp;
 2637         struct file *fp;
 2638         vm_object_t obj;
 2639         int error;
 2640 
 2641         if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
 2642                 return (error);
 2643         vp = (struct vnode *)fp->f_data;
 2644         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
 2645         if (VOP_GETVOBJECT(vp, &obj) == 0)
 2646                 vm_object_page_clean(obj, 0, 0, 0);
 2647         if ((error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p)) == 0 &&
 2648             vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP) &&
 2649             bioops.io_fsync)
 2650                 error = (*bioops.io_fsync)(vp);
 2651         VOP_UNLOCK(vp, 0, p);
 2652         return (error);
 2653 }
 2654 
 2655 /*
 2656  * Rename files.  Source and destination must either both be directories,
 2657  * or both not be directories.  If target is a directory, it must be empty.
 2658  */
 2659 #ifndef _SYS_SYSPROTO_H_
 2660 struct rename_args {
 2661         char    *from;
 2662         char    *to;
 2663 };
 2664 #endif
 2665 /* ARGSUSED */
 2666 int
 2667 rename(p, uap)
 2668         struct proc *p;
 2669         register struct rename_args /* {
 2670                 syscallarg(char *) from;
 2671                 syscallarg(char *) to;
 2672         } */ *uap;
 2673 {
 2674         register struct vnode *tvp, *fvp, *tdvp;
 2675         struct nameidata fromnd, tond;
 2676         int error;
 2677 
 2678         bwillwrite();
 2679         NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
 2680             SCARG(uap, from), p);
 2681         if ((error = namei(&fromnd)) != 0)
 2682                 return (error);
 2683         fvp = fromnd.ni_vp;
 2684         NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART | NOOBJ,
 2685             UIO_USERSPACE, SCARG(uap, to), p);
 2686         if (fromnd.ni_vp->v_type == VDIR)
 2687                 tond.ni_cnd.cn_flags |= WILLBEDIR;
 2688         if ((error = namei(&tond)) != 0) {
 2689                 /* Translate error code for rename("dir1", "dir2/."). */
 2690                 if (error == EISDIR && fvp->v_type == VDIR)
 2691                         error = EINVAL;
 2692                 NDFREE(&fromnd, NDF_ONLY_PNBUF);
 2693                 vrele(fromnd.ni_dvp);
 2694                 vrele(fvp);
 2695                 goto out1;
 2696         }
 2697         tdvp = tond.ni_dvp;
 2698         tvp = tond.ni_vp;
 2699         if (tvp != NULL) {
 2700                 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
 2701                         error = ENOTDIR;
 2702                         goto out;
 2703                 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
 2704                         error = EISDIR;
 2705                         goto out;
 2706                 }
 2707         }
 2708         if (fvp == tdvp)
 2709                 error = EINVAL;
 2710         /*
 2711          * If the source is the same as the destination (that is, if they
 2712          * are links to the same vnode), then there is nothing to do.
 2713          */
 2714         if (fvp == tvp)
 2715                 error = -1;
 2716 out:
 2717         if (!error) {
 2718                 VOP_LEASE(tdvp, p, p->p_ucred, LEASE_WRITE);
 2719                 if (fromnd.ni_dvp != tdvp) {
 2720                         VOP_LEASE(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
 2721                 }
 2722                 if (tvp) {
 2723                         VOP_LEASE(tvp, p, p->p_ucred, LEASE_WRITE);
 2724                 }
 2725                 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
 2726                                    tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
 2727                 NDFREE(&fromnd, NDF_ONLY_PNBUF);
 2728                 NDFREE(&tond, NDF_ONLY_PNBUF);
 2729         } else {
 2730                 NDFREE(&fromnd, NDF_ONLY_PNBUF);
 2731                 NDFREE(&tond, NDF_ONLY_PNBUF);
 2732                 if (tdvp == tvp)
 2733                         vrele(tdvp);
 2734                 else
 2735                         vput(tdvp);
 2736                 if (tvp)
 2737                         vput(tvp);
 2738                 vrele(fromnd.ni_dvp);
 2739                 vrele(fvp);
 2740         }
 2741         vrele(tond.ni_startdir);
 2742         ASSERT_VOP_UNLOCKED(fromnd.ni_dvp, "rename");
 2743         ASSERT_VOP_UNLOCKED(fromnd.ni_vp, "rename");
 2744         ASSERT_VOP_UNLOCKED(tond.ni_dvp, "rename");
 2745         ASSERT_VOP_UNLOCKED(tond.ni_vp, "rename");
 2746 out1:
 2747         if (fromnd.ni_startdir)
 2748                 vrele(fromnd.ni_startdir);
 2749         if (error == -1)
 2750                 return (0);
 2751         return (error);
 2752 }
 2753 
 2754 /*
 2755  * Make a directory file.
 2756  */
 2757 #ifndef _SYS_SYSPROTO_H_
 2758 struct mkdir_args {
 2759         char    *path;
 2760         int     mode;
 2761 };
 2762 #endif
 2763 /* ARGSUSED */
 2764 int
 2765 mkdir(p, uap)
 2766         struct proc *p;
 2767         register struct mkdir_args /* {
 2768                 syscallarg(char *) path;
 2769                 syscallarg(int) mode;
 2770         } */ *uap;
 2771 {
 2772         register struct vnode *vp;
 2773         struct vattr vattr;
 2774         int error;
 2775         struct nameidata nd;
 2776 
 2777         bwillwrite();
 2778         NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
 2779         nd.ni_cnd.cn_flags |= WILLBEDIR;
 2780         if ((error = namei(&nd)) != 0)
 2781                 return (error);
 2782         vp = nd.ni_vp;
 2783         if (vp != NULL) {
 2784                 NDFREE(&nd, NDF_ONLY_PNBUF);
 2785                 if (nd.ni_dvp == vp)
 2786                         vrele(nd.ni_dvp);
 2787                 else
 2788                         vput(nd.ni_dvp);
 2789                 vrele(vp);
 2790                 return (EEXIST);
 2791         }
 2792         VATTR_NULL(&vattr);
 2793         vattr.va_type = VDIR;
 2794         vattr.va_mode = (SCARG(uap, mode) & ACCESSPERMS) &~ p->p_fd->fd_cmask;
 2795         VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
 2796         error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
 2797         NDFREE(&nd, NDF_ONLY_PNBUF);
 2798         vput(nd.ni_dvp);
 2799         if (!error)
 2800                 vput(nd.ni_vp);
 2801         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mkdir");
 2802         ASSERT_VOP_UNLOCKED(nd.ni_vp, "mkdir");
 2803         return (error);
 2804 }
 2805 
 2806 /*
 2807  * Remove a directory file.
 2808  */
 2809 #ifndef _SYS_SYSPROTO_H_
 2810 struct rmdir_args {
 2811         char    *path;
 2812 };
 2813 #endif
 2814 /* ARGSUSED */
 2815 int
 2816 rmdir(p, uap)
 2817         struct proc *p;
 2818         struct rmdir_args /* {
 2819                 syscallarg(char *) path;
 2820         } */ *uap;
 2821 {
 2822         register struct vnode *vp;
 2823         int error;
 2824         struct nameidata nd;
 2825 
 2826         bwillwrite();
 2827         NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
 2828             SCARG(uap, path), p);
 2829         if ((error = namei(&nd)) != 0)
 2830                 return (error);
 2831         vp = nd.ni_vp;
 2832         if (vp->v_type != VDIR) {
 2833                 error = ENOTDIR;
 2834                 goto out;
 2835         }
 2836         /*
 2837          * No rmdir "." please.
 2838          */
 2839         if (nd.ni_dvp == vp) {
 2840                 error = EINVAL;
 2841                 goto out;
 2842         }
 2843         /*
 2844          * The root of a mounted filesystem cannot be deleted.
 2845          */
 2846         if (vp->v_flag & VROOT)
 2847                 error = EBUSY;
 2848         else {
 2849                 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
 2850                 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
 2851                 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
 2852         }
 2853 out:
 2854         NDFREE(&nd, NDF_ONLY_PNBUF);
 2855         if (nd.ni_dvp == vp)
 2856                 vrele(nd.ni_dvp);
 2857         else
 2858                 vput(nd.ni_dvp);
 2859         if (vp != NULLVP)
 2860                 vput(vp);
 2861         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "rmdir");
 2862         ASSERT_VOP_UNLOCKED(nd.ni_vp, "rmdir");
 2863         return (error);
 2864 }
 2865 
 2866 #ifdef COMPAT_43
 2867 /*
 2868  * Read a block of directory entries in a file system independent format.
 2869  */
 2870 #ifndef _SYS_SYSPROTO_H_
 2871 struct ogetdirentries_args {
 2872         int     fd;
 2873         char    *buf;
 2874         u_int   count;
 2875         long    *basep;
 2876 };
 2877 #endif
 2878 int
 2879 ogetdirentries(p, uap)
 2880         struct proc *p;
 2881         register struct ogetdirentries_args /* {
 2882                 syscallarg(int) fd;
 2883                 syscallarg(char *) buf;
 2884                 syscallarg(u_int) count;
 2885                 syscallarg(long *) basep;
 2886         } */ *uap;
 2887 {
 2888         struct vnode *vp;
 2889         struct file *fp;
 2890         struct uio auio, kuio;
 2891         struct iovec aiov, kiov;
 2892         struct dirent *dp, *edp;
 2893         caddr_t dirbuf;
 2894         int error, eofflag, readcnt;
 2895         long loff;
 2896 
 2897         /* XXX arbitrary sanity limit on `count'. */
 2898         if (SCARG(uap, count) > 64 * 1024)
 2899                 return (EINVAL);
 2900         if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
 2901                 return (error);
 2902         if ((fp->f_flag & FREAD) == 0)
 2903                 return (EBADF);
 2904         vp = (struct vnode *)fp->f_data;
 2905 unionread:
 2906         if (vp->v_type != VDIR)
 2907                 return (EINVAL);
 2908         aiov.iov_base = SCARG(uap, buf);
 2909         aiov.iov_len = SCARG(uap, count);
 2910         auio.uio_iov = &aiov;
 2911         auio.uio_iovcnt = 1;
 2912         auio.uio_rw = UIO_READ;
 2913         auio.uio_segflg = UIO_USERSPACE;
 2914         auio.uio_procp = p;
 2915         auio.uio_resid = SCARG(uap, count);
 2916         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
 2917         loff = auio.uio_offset = fp->f_offset;
 2918 #       if (BYTE_ORDER != LITTLE_ENDIAN)
 2919                 if (vp->v_mount->mnt_maxsymlinklen <= 0) {
 2920                         error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
 2921                             NULL, NULL);
 2922                         fp->f_offset = auio.uio_offset;
 2923                 } else
 2924 #       endif
 2925         {
 2926                 kuio = auio;
 2927                 kuio.uio_iov = &kiov;
 2928                 kuio.uio_segflg = UIO_SYSSPACE;
 2929                 kiov.iov_len = SCARG(uap, count);
 2930                 MALLOC(dirbuf, caddr_t, SCARG(uap, count), M_TEMP, M_WAITOK);
 2931                 kiov.iov_base = dirbuf;
 2932                 error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag,
 2933                             NULL, NULL);
 2934                 fp->f_offset = kuio.uio_offset;
 2935                 if (error == 0) {
 2936                         readcnt = SCARG(uap, count) - kuio.uio_resid;
 2937                         edp = (struct dirent *)&dirbuf[readcnt];
 2938                         for (dp = (struct dirent *)dirbuf; dp < edp; ) {
 2939 #                               if (BYTE_ORDER == LITTLE_ENDIAN)
 2940                                         /*
 2941                                          * The expected low byte of
 2942                                          * dp->d_namlen is our dp->d_type.
 2943                                          * The high MBZ byte of dp->d_namlen
 2944                                          * is our dp->d_namlen.
 2945                                          */
 2946                                         dp->d_type = dp->d_namlen;
 2947                                         dp->d_namlen = 0;
 2948 #                               else
 2949                                         /*
 2950                                          * The dp->d_type is the high byte
 2951                                          * of the expected dp->d_namlen,
 2952                                          * so must be zero'ed.
 2953                                          */
 2954                                         dp->d_type = 0;
 2955 #                               endif
 2956                                 if (dp->d_reclen > 0) {
 2957                                         dp = (struct dirent *)
 2958                                             ((char *)dp + dp->d_reclen);
 2959                                 } else {
 2960                                         error = EIO;
 2961                                         break;
 2962                                 }
 2963                         }
 2964                         if (dp >= edp)
 2965                                 error = uiomove(dirbuf, readcnt, &auio);
 2966                 }
 2967                 FREE(dirbuf, M_TEMP);
 2968         }
 2969         VOP_UNLOCK(vp, 0, p);
 2970         if (error)
 2971                 return (error);
 2972         if (SCARG(uap, count) == auio.uio_resid) {
 2973                 if (union_dircheckp) {
 2974                         error = union_dircheckp(p, &vp, fp);
 2975                         if (error == -1)
 2976                                 goto unionread;
 2977                         if (error)
 2978                                 return (error);
 2979                 }
 2980                 if ((vp->v_flag & VROOT) &&
 2981                     (vp->v_mount->mnt_flag & MNT_UNION)) {
 2982                         struct vnode *tvp = vp;
 2983                         vp = vp->v_mount->mnt_vnodecovered;
 2984                         VREF(vp);
 2985                         fp->f_data = (caddr_t) vp;
 2986                         fp->f_offset = 0;
 2987                         vrele(tvp);
 2988                         goto unionread;
 2989                 }
 2990         }
 2991         error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep),
 2992             sizeof(long));
 2993         p->p_retval[0] = SCARG(uap, count) - auio.uio_resid;
 2994         return (error);
 2995 }
 2996 #endif /* COMPAT_43 */
 2997 
 2998 /*
 2999  * Read a block of directory entries in a file system independent format.
 3000  */
 3001 #ifndef _SYS_SYSPROTO_H_
 3002 struct getdirentries_args {
 3003         int     fd;
 3004         char    *buf;
 3005         u_int   count;
 3006         long    *basep;
 3007 };
 3008 #endif
 3009 int
 3010 getdirentries(p, uap)
 3011         struct proc *p;
 3012         register struct getdirentries_args /* {
 3013                 syscallarg(int) fd;
 3014                 syscallarg(char *) buf;
 3015                 syscallarg(u_int) count;
 3016                 syscallarg(long *) basep;
 3017         } */ *uap;
 3018 {
 3019         struct vnode *vp;
 3020         struct file *fp;
 3021         struct uio auio;
 3022         struct iovec aiov;
 3023         long loff;
 3024         int error, eofflag;
 3025 
 3026         if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
 3027                 return (error);
 3028         if ((fp->f_flag & FREAD) == 0)
 3029                 return (EBADF);
 3030         vp = (struct vnode *)fp->f_data;
 3031 unionread:
 3032         if (vp->v_type != VDIR)
 3033                 return (EINVAL);
 3034         aiov.iov_base = SCARG(uap, buf);
 3035         aiov.iov_len = SCARG(uap, count);
 3036         auio.uio_iov = &aiov;
 3037         auio.uio_iovcnt = 1;
 3038         auio.uio_rw = UIO_READ;
 3039         auio.uio_segflg = UIO_USERSPACE;
 3040         auio.uio_procp = p;
 3041         auio.uio_resid = SCARG(uap, count);
 3042         /* vn_lock(vp, LK_SHARED | LK_RETRY, p); */
 3043         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
 3044         loff = auio.uio_offset = fp->f_offset;
 3045         error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL, NULL);
 3046         fp->f_offset = auio.uio_offset;
 3047         VOP_UNLOCK(vp, 0, p);
 3048         if (error)
 3049                 return (error);
 3050         if (SCARG(uap, count) == auio.uio_resid) {
 3051                 if (union_dircheckp) {
 3052                         error = union_dircheckp(p, &vp, fp);
 3053                         if (error == -1)
 3054                                 goto unionread;
 3055                         if (error)
 3056                                 return (error);
 3057                 }
 3058                 if ((vp->v_flag & VROOT) &&
 3059                     (vp->v_mount->mnt_flag & MNT_UNION)) {
 3060                         struct vnode *tvp = vp;
 3061                         vp = vp->v_mount->mnt_vnodecovered;
 3062                         VREF(vp);
 3063                         fp->f_data = (caddr_t) vp;
 3064                         fp->f_offset = 0;
 3065                         vrele(tvp);
 3066                         goto unionread;
 3067                 }
 3068         }
 3069         if (SCARG(uap, basep) != NULL) {
 3070                 error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep),
 3071                     sizeof(long));
 3072         }
 3073         p->p_retval[0] = SCARG(uap, count) - auio.uio_resid;
 3074         return (error);
 3075 }
 3076 #ifndef _SYS_SYSPROTO_H_
 3077 struct getdents_args {
 3078         int fd;
 3079         char *buf;
 3080         size_t count;
 3081 };
 3082 #endif
 3083 int
 3084 getdents(p, uap)
 3085         struct proc *p;
 3086         register struct getdents_args /* {
 3087                 syscallarg(int) fd;
 3088                 syscallarg(char *) buf;
 3089                 syscallarg(u_int) count;
 3090         } */ *uap;
 3091 {
 3092         struct getdirentries_args ap;
 3093         ap.fd = uap->fd;
 3094         ap.buf = uap->buf;
 3095         ap.count = uap->count;
 3096         ap.basep = NULL;
 3097         return getdirentries(p, &ap);
 3098 }
 3099 
 3100 /*
 3101  * Set the mode mask for creation of filesystem nodes.
 3102  *
 3103  * MP SAFE
 3104  */
 3105 #ifndef _SYS_SYSPROTO_H_
 3106 struct umask_args {
 3107         int     newmask;
 3108 };
 3109 #endif
 3110 int
 3111 umask(p, uap)
 3112         struct proc *p;
 3113         struct umask_args /* {
 3114                 syscallarg(int) newmask;
 3115         } */ *uap;
 3116 {
 3117         register struct filedesc *fdp;
 3118 
 3119         fdp = p->p_fd;
 3120         p->p_retval[0] = fdp->fd_cmask;
 3121         fdp->fd_cmask = SCARG(uap, newmask) & ALLPERMS;
 3122         return (0);
 3123 }
 3124 
 3125 /*
 3126  * Void all references to file by ripping underlying filesystem
 3127  * away from vnode.
 3128  */
 3129 #ifndef _SYS_SYSPROTO_H_
 3130 struct revoke_args {
 3131         char    *path;
 3132 };
 3133 #endif
 3134 /* ARGSUSED */
 3135 int
 3136 revoke(p, uap)
 3137         struct proc *p;
 3138         register struct revoke_args /* {
 3139                 syscallarg(char *) path;
 3140         } */ *uap;
 3141 {
 3142         register struct vnode *vp;
 3143         struct vattr vattr;
 3144         int error;
 3145         struct nameidata nd;
 3146 
 3147         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
 3148         if ((error = namei(&nd)) != 0)
 3149                 return (error);
 3150         vp = nd.ni_vp;
 3151         NDFREE(&nd, NDF_ONLY_PNBUF);
 3152         if (vp->v_type != VCHR && vp->v_type != VBLK) {
 3153                 error = EINVAL;
 3154                 goto out;
 3155         }
 3156         if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0)
 3157                 goto out;
 3158         if (p->p_ucred->cr_uid != vattr.va_uid &&
 3159             (error = suser_xxx(0, p, PRISON_ROOT)))
 3160                 goto out;
 3161         if (vcount(vp) > 1)
 3162                 VOP_REVOKE(vp, REVOKEALL);
 3163 out:
 3164         vrele(vp);
 3165         return (error);
 3166 }
 3167 
 3168 /*
 3169  * Convert a user file descriptor to a kernel file entry.
 3170  */
 3171 int
 3172 getvnode(fdp, fd, fpp)
 3173         struct filedesc *fdp;
 3174         int fd;
 3175         struct file **fpp;
 3176 {
 3177         struct file *fp;
 3178 
 3179         if ((u_int)fd >= fdp->fd_nfiles ||
 3180             (fp = fdp->fd_ofiles[fd]) == NULL)
 3181                 return (EBADF);
 3182         if (fp->f_type != DTYPE_VNODE && fp->f_type != DTYPE_FIFO)
 3183                 return (EINVAL);
 3184         *fpp = fp;
 3185         return (0);
 3186 }
 3187 /*
 3188  * Get (NFS) file handle
 3189  */
 3190 #ifndef _SYS_SYSPROTO_H_
 3191 struct getfh_args {
 3192         char    *fname;
 3193         fhandle_t *fhp;
 3194 };
 3195 #endif
 3196 int
 3197 getfh(p, uap)
 3198         struct proc *p;
 3199         register struct getfh_args *uap;
 3200 {
 3201         struct nameidata nd;
 3202         fhandle_t fh;
 3203         register struct vnode *vp;
 3204         int error;
 3205 
 3206         /*
 3207          * Must be super user
 3208          */
 3209         error = suser(p);
 3210         if (error)
 3211                 return (error);
 3212         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p);
 3213         error = namei(&nd);
 3214         if (error)
 3215                 return (error);
 3216         NDFREE(&nd, NDF_ONLY_PNBUF);
 3217         vp = nd.ni_vp;
 3218         bzero(&fh, sizeof(fh));
 3219         fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;
 3220         error = VFS_VPTOFH(vp, &fh.fh_fid);
 3221         vput(vp);
 3222         if (error)
 3223                 return (error);
 3224         error = copyout(&fh, uap->fhp, sizeof (fh));
 3225         return (error);
 3226 }
 3227 
 3228 /*
 3229  * syscall for the rpc.lockd to use to translate a NFS file handle into
 3230  * an open descriptor.
 3231  *
 3232  * warning: do not remove the suser() call or this becomes one giant
 3233  * security hole.
 3234  */
 3235 #ifndef _SYS_SYSPROTO_H_
 3236 struct fhopen_args {
 3237         const struct fhandle *u_fhp;
 3238         int flags;
 3239 };
 3240 #endif
 3241 int
 3242 fhopen(p, uap)
 3243         struct proc *p;
 3244         struct fhopen_args /* {
 3245                 syscallarg(const struct fhandle *) u_fhp;
 3246                 syscallarg(int) flags;
 3247         } */ *uap;
 3248 {
 3249         struct mount *mp;
 3250         struct vnode *vp;
 3251         struct fhandle fhp;
 3252         struct vattr vat;
 3253         struct vattr *vap = &vat;
 3254         struct flock lf;
 3255         struct file *fp;
 3256         register struct filedesc *fdp = p->p_fd;
 3257         int fmode, mode, error, type;
 3258         struct file *nfp; 
 3259         int indx;
 3260 
 3261         /*
 3262          * Must be super user
 3263          */
 3264         error = suser(p);
 3265         if (error)
 3266                 return (error);
 3267 
 3268         fmode = FFLAGS(SCARG(uap, flags));
 3269         /* why not allow a non-read/write open for our lockd? */
 3270         if (((fmode & (FREAD | FWRITE)) == 0) || (fmode & O_CREAT))
 3271                 return (EINVAL);
 3272         error = copyin(SCARG(uap,u_fhp), &fhp, sizeof(fhp));
 3273         if (error)
 3274                 return(error);
 3275         /* find the mount point */
 3276         mp = vfs_getvfs(&fhp.fh_fsid);
 3277         if (mp == NULL)
 3278                 return (ESTALE);
 3279         /* now give me my vnode, it gets returned to me locked */
 3280         error = VFS_FHTOVP(mp, &fhp.fh_fid, &vp);
 3281         if (error)
 3282                 return (error);
 3283         /*
 3284          * from now on we have to make sure not
 3285          * to forget about the vnode
 3286          * any error that causes an abort must vput(vp) 
 3287          * just set error = err and 'goto bad;'.
 3288          */
 3289 
 3290         /* 
 3291          * from vn_open 
 3292          */
 3293         if (vp->v_type == VLNK) {
 3294                 error = EMLINK;
 3295                 goto bad;
 3296         }
 3297         if (vp->v_type == VSOCK) {
 3298                 error = EOPNOTSUPP;
 3299                 goto bad;
 3300         }
 3301         mode = 0;
 3302         if (fmode & (FWRITE | O_TRUNC)) {
 3303                 if (vp->v_type == VDIR) {
 3304                         error = EISDIR;
 3305                         goto bad;
 3306                 }
 3307                 error = vn_writechk(vp);
 3308                 if (error)
 3309                         goto bad;
 3310                 mode |= VWRITE;
 3311         }
 3312         if (fmode & FREAD)
 3313                 mode |= VREAD;
 3314         if (mode) {
 3315                 error = VOP_ACCESS(vp, mode, p->p_ucred, p);
 3316                 if (error)
 3317                         goto bad;
 3318         }
 3319         if (fmode & O_TRUNC) {
 3320                 VOP_UNLOCK(vp, 0, p);                           /* XXX */
 3321                 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
 3322                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);        /* XXX */
 3323                 VATTR_NULL(vap);
 3324                 vap->va_size = 0;
 3325                 error = VOP_SETATTR(vp, vap, p->p_ucred, p);
 3326                 if (error)
 3327                         goto bad;
 3328         }
 3329         error = VOP_OPEN(vp, fmode, p->p_ucred, p);
 3330         if (error)
 3331                 goto bad;
 3332         /*
 3333          * Make sure that a VM object is created for VMIO support.
 3334          */
 3335         if (vn_canvmio(vp) == TRUE) {
 3336                 if ((error = vfs_object_create(vp, p, p->p_ucred)) != 0)
 3337                         goto bad;
 3338         }
 3339         if (fmode & FWRITE)
 3340                 vp->v_writecount++;
 3341 
 3342         /*
 3343          * end of vn_open code 
 3344          */
 3345 
 3346         if ((error = falloc(p, &nfp, &indx)) != 0) {
 3347                 if (fmode & FWRITE)
 3348                         vp->v_writecount--;
 3349                 goto bad;
 3350         }
 3351         fp = nfp;       
 3352 
 3353         /*
 3354          * hold an extra reference to avoid having fp ripped out
 3355          * from under us while we block in the lock op.
 3356          */
 3357         fhold(fp);
 3358         nfp->f_data = (caddr_t)vp;
 3359         nfp->f_flag = fmode & FMASK;
 3360         nfp->f_ops = &vnops;
 3361         nfp->f_type = DTYPE_VNODE;
 3362         if (fmode & (O_EXLOCK | O_SHLOCK)) {
 3363                 lf.l_whence = SEEK_SET;
 3364                 lf.l_start = 0;
 3365                 lf.l_len = 0;
 3366                 if (fmode & O_EXLOCK)
 3367                         lf.l_type = F_WRLCK;
 3368                 else
 3369                         lf.l_type = F_RDLCK;
 3370                 type = F_FLOCK;
 3371                 if ((fmode & FNONBLOCK) == 0)
 3372                         type |= F_WAIT;
 3373                 VOP_UNLOCK(vp, 0, p);
 3374                 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0) {
 3375                         /*
 3376                          * lock request failed.  Normally close the descriptor
 3377                          * but handle the case where someone might have dup()d
 3378                          * or close()d it when we weren't looking.
 3379                          */
 3380                         if (fdp->fd_ofiles[indx] == fp) {
 3381                                 fdp->fd_ofiles[indx] = NULL;
 3382                                 fdrop(fp, p);
 3383                         }
 3384 
 3385                         /*
 3386                          * release our private reference.
 3387                          */
 3388                         fdrop(fp, p);
 3389                         return (error);
 3390                 }
 3391                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
 3392                 fp->f_flag |= FHASLOCK;
 3393         }
 3394         if ((vp->v_type == VREG) && (VOP_GETVOBJECT(vp, NULL) != 0))
 3395                 vfs_object_create(vp, p, p->p_ucred);
 3396 
 3397         VOP_UNLOCK(vp, 0, p);
 3398         fdrop(fp, p);
 3399         p->p_retval[0] = indx;
 3400         return (0);
 3401 
 3402 bad:
 3403         vput(vp);
 3404         return (error);
 3405 }
 3406 
 3407 #ifndef _SYS_SYSPROTO_H_
 3408 struct fhstat_args {
 3409         struct fhandle *u_fhp;
 3410         struct stat *sb;
 3411 };
 3412 #endif
 3413 int
 3414 fhstat(p, uap)
 3415         struct proc *p;
 3416         register struct fhstat_args /* {
 3417                 syscallarg(struct fhandle *) u_fhp;
 3418                 syscallarg(struct stat *) sb;
 3419         } */ *uap;
 3420 {
 3421         struct stat sb;
 3422         fhandle_t fh;
 3423         struct mount *mp;
 3424         struct vnode *vp;
 3425         int error;
 3426 
 3427         /*
 3428          * Must be super user
 3429          */
 3430         error = suser(p);
 3431         if (error)
 3432                 return (error);
 3433         
 3434         error = copyin(SCARG(uap, u_fhp), &fh, sizeof(fhandle_t));
 3435         if (error)
 3436                 return (error);
 3437 
 3438         if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
 3439                 return (ESTALE);
 3440         if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
 3441                 return (error);
 3442         error = vn_stat(vp, &sb, p);
 3443         vput(vp);
 3444         if (error)
 3445                 return (error);
 3446         error = copyout(&sb, SCARG(uap, sb), sizeof(sb));
 3447         return (error);
 3448 }
 3449 
 3450 #ifndef _SYS_SYSPROTO_H_
 3451 struct fhstatfs_args {
 3452         struct fhandle *u_fhp;
 3453         struct statfs *buf;
 3454 };
 3455 #endif
 3456 int
 3457 fhstatfs(p, uap)
 3458         struct proc *p;
 3459         struct fhstatfs_args /* {
 3460                 syscallarg(struct fhandle) *u_fhp;
 3461                 syscallarg(struct statfs) *buf;
 3462         } */ *uap;
 3463 {
 3464         struct statfs *sp;
 3465         struct mount *mp;
 3466         struct vnode *vp;
 3467         struct statfs sb;
 3468         fhandle_t fh;
 3469         int error;
 3470 
 3471         /*
 3472          * Must be super user
 3473          */
 3474         if ((error = suser(p)))
 3475                 return (error);
 3476 
 3477         if ((error = copyin(SCARG(uap, u_fhp), &fh, sizeof(fhandle_t))) != 0)
 3478                 return (error);
 3479 
 3480         if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
 3481                 return (ESTALE);
 3482         if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
 3483                 return (error);
 3484         mp = vp->v_mount;
 3485         sp = &mp->mnt_stat;
 3486         vput(vp);
 3487         if ((error = VFS_STATFS(mp, sp, p)) != 0)
 3488                 return (error);
 3489         sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
 3490         if (suser_xxx(p->p_ucred, 0, 0)) {
 3491                 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
 3492                 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
 3493                 sp = &sb;
 3494         }
 3495         return (copyout(sp, SCARG(uap, buf), sizeof(*sp)));
 3496 }
 3497 
 3498 /*
 3499  * Syscall to push extended attribute configuration information into the
 3500  * VFS.  Accepts a path, which it converts to a mountpoint, as well as
 3501  * a command (int cmd), and attribute name and misc data.  For now, the
 3502  * attribute name is left in userspace for consumption by the VFS_op.
 3503  * It will probably be changed to be copied into sysspace by the
 3504  * syscall in the future, once issues with various consumers of the
 3505  * attribute code have raised their hands.
 3506  *
 3507  * Currently this is used only by UFS Extended Attributes.
 3508  */
 3509 int
 3510 extattrctl(p, uap)
 3511         struct proc *p;
 3512         struct extattrctl_args *uap;
 3513 {
 3514         struct nameidata nd;
 3515         struct mount *mp;
 3516         int error;
 3517 
 3518         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
 3519         if ((error = namei(&nd)) != 0)
 3520                 return (error);
 3521         mp = nd.ni_vp->v_mount;
 3522         NDFREE(&nd, 0);
 3523         return (VFS_EXTATTRCTL(mp, SCARG(uap, cmd), SCARG(uap, attrname),
 3524             SCARG(uap, arg), p));
 3525 }
 3526 
 3527 /*
 3528  * Syscall to set a named extended attribute on a file or directory.
 3529  * Accepts attribute name, and a uio structure pointing to the data to set.
 3530  * The uio is consumed in the style of writev().  The real work happens
 3531  * in VOP_SETEXTATTR().
 3532  */
 3533 int
 3534 extattr_set_file(p, uap)
 3535         struct proc *p;
 3536         struct extattr_set_file_args *uap;
 3537 {
 3538         struct nameidata nd;
 3539         struct uio auio;
 3540         struct iovec *iov, *needfree = NULL, aiov[UIO_SMALLIOV];
 3541         char attrname[EXTATTR_MAXNAMELEN];
 3542         u_int iovlen, cnt;
 3543         int error, i;
 3544 
 3545         error = copyin(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN);
 3546         if (error)
 3547                 return (error);
 3548         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
 3549             SCARG(uap, path), p);
 3550         if ((error = namei(&nd)) != 0)
 3551                 return(error);
 3552         iovlen = uap->iovcnt * sizeof(struct iovec);
 3553         if (uap->iovcnt > UIO_SMALLIOV) {
 3554                 if (uap->iovcnt > UIO_MAXIOV) {
 3555                         error = EINVAL;
 3556                         goto done;
 3557                 }
 3558                 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
 3559                 needfree = iov;
 3560         } else
 3561                 iov = aiov;
 3562         auio.uio_iov = iov;
 3563         auio.uio_iovcnt = uap->iovcnt;
 3564         auio.uio_rw = UIO_WRITE;
 3565         auio.uio_segflg = UIO_USERSPACE;
 3566         auio.uio_procp = p;
 3567         auio.uio_offset = 0;
 3568         if ((error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen)))
 3569                 goto done;
 3570         auio.uio_resid = 0;
 3571         for (i = 0; i < uap->iovcnt; i++) {
 3572                 if (iov->iov_len > INT_MAX - auio.uio_resid) {
 3573                         error = EINVAL;
 3574                         goto done;
 3575                 }
 3576                 auio.uio_resid += iov->iov_len;
 3577                 iov++;
 3578         }
 3579         cnt = auio.uio_resid;
 3580         error = VOP_SETEXTATTR(nd.ni_vp, attrname, &auio, p->p_cred->pc_ucred,
 3581             p);
 3582         cnt -= auio.uio_resid;
 3583         p->p_retval[0] = cnt;
 3584 done:
 3585         if (needfree)
 3586                 FREE(needfree, M_IOV);
 3587         NDFREE(&nd, 0);
 3588         return (error);
 3589 }
 3590 
 3591 /*
 3592  * Syscall to get a named extended attribute on a file or directory.
 3593  * Accepts attribute name, and a uio structure pointing to a buffer for the
 3594  * data.  The uio is consumed in the style of readv().  The real work
 3595  * happens in VOP_GETEXTATTR();
 3596  */
 3597 int
 3598 extattr_get_file(p, uap)
 3599         struct proc *p;
 3600         struct extattr_get_file_args *uap;
 3601 {
 3602         struct nameidata nd;
 3603         struct uio auio;
 3604         struct iovec *iov, *needfree, aiov[UIO_SMALLIOV];
 3605         char attrname[EXTATTR_MAXNAMELEN];
 3606         u_int iovlen, cnt;
 3607         int error, i;
 3608 
 3609         error = copyin(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN);
 3610         if (error)
 3611                 return (error);
 3612         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
 3613             SCARG(uap, path), p);
 3614         if ((error = namei(&nd)) != 0)
 3615                 return (error);
 3616         iovlen = uap->iovcnt * sizeof (struct iovec);
 3617         if (uap->iovcnt > UIO_SMALLIOV) {
 3618                 if (uap->iovcnt > UIO_MAXIOV) {
 3619                         NDFREE(&nd, 0);
 3620                         return (EINVAL);
 3621                 }
 3622                 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
 3623                 needfree = iov;
 3624         } else {
 3625                 iov = aiov;
 3626                 needfree = NULL;
 3627         }
 3628         auio.uio_iov = iov;
 3629         auio.uio_iovcnt = uap->iovcnt;
 3630         auio.uio_rw = UIO_READ;
 3631         auio.uio_segflg = UIO_USERSPACE;
 3632         auio.uio_procp = p;
 3633         auio.uio_offset = 0;
 3634         if ((error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen)))
 3635                 goto done;
 3636         auio.uio_resid = 0;
 3637         for (i = 0; i < uap->iovcnt; i++) {
 3638                 if (iov->iov_len > INT_MAX - auio.uio_resid) {
 3639                         error = EINVAL;
 3640                         goto done;
 3641                 }
 3642                 auio.uio_resid += iov->iov_len;
 3643                 iov++;
 3644         }
 3645         cnt = auio.uio_resid;
 3646         error = VOP_GETEXTATTR(nd.ni_vp, attrname, &auio, p->p_cred->pc_ucred,
 3647             p);
 3648         cnt -= auio.uio_resid;
 3649         p->p_retval[0] = cnt;
 3650 done:
 3651         if (needfree)
 3652                 FREE(needfree, M_IOV);
 3653         NDFREE(&nd, 0);
 3654         return(error);
 3655 }
 3656 
 3657 /*
 3658  * Syscall to delete a named extended attribute from a file or directory.
 3659  * Accepts attribute name.  The real work happens in VOP_SETEXTATTR().
 3660  */
 3661 int
 3662 extattr_delete_file(p, uap)
 3663         struct proc *p;
 3664         struct extattr_delete_file_args *uap;
 3665 {
 3666         struct nameidata nd;
 3667         char attrname[EXTATTR_MAXNAMELEN];
 3668         int     error;
 3669 
 3670         error = copyin(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN);
 3671         if (error)
 3672                 return(error);
 3673         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
 3674             SCARG(uap, path), p);
 3675         if ((error = namei(&nd)) != 0)
 3676                 return(error);
 3677         error = VOP_SETEXTATTR(nd.ni_vp, attrname, NULL, p->p_cred->pc_ucred,
 3678             p);
 3679         NDFREE(&nd, 0);
 3680         return(error);
 3681 }

Cache object: 3e1f229b2f6dbef484ecf50b0fac407e


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.