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/sysent.h>
   48 #include <sys/sysproto.h>
   49 #include <sys/namei.h>
   50 #include <sys/filedesc.h>
   51 #include <sys/kernel.h>
   52 #include <sys/fcntl.h>
   53 #include <sys/file.h>
   54 #include <sys/linker.h>
   55 #include <sys/stat.h>
   56 #include <sys/unistd.h>
   57 #include <sys/vnode.h>
   58 #include <sys/malloc.h>
   59 #include <sys/mount.h>
   60 #include <sys/proc.h>
   61 #include <sys/dirent.h>
   62 
   63 #include <miscfs/union/union.h>
   64 
   65 #include <vm/vm.h>
   66 #include <vm/vm_object.h>
   67 #include <vm/vm_extern.h>
   68 #include <vm/vm_zone.h>
   69 #include <sys/sysctl.h>
   70 
   71 static int change_dir __P((struct nameidata *ndp, struct proc *p));
   72 static void checkdirs __P((struct vnode *olddp));
   73 static int setfown __P((struct proc *, struct vnode *, uid_t, gid_t));
   74 static int setfmode __P((struct proc *, struct vnode *, int));
   75 static int setfflags __P((struct proc *, struct vnode *, int));
   76 static int setutimes __P((struct proc *, struct vnode *, struct timeval *, int));
   77 static int      usermount = 0;  /* if 1, non-root can mount fs. */
   78 
   79 int (*union_dircheckp) __P((struct proc *, struct vnode **, struct file *));
   80 
   81 SYSCTL_INT(_vfs, OID_AUTO, usermount, CTLFLAG_RW, &usermount, 0, "");
   82 
   83 /*
   84  * Virtual File System System Calls
   85  */
   86 
   87 /*
   88  * Mount a file system.
   89  */
   90 #ifndef _SYS_SYSPROTO_H_
   91 struct mount_args {
   92         char    *type;
   93         char    *path;
   94         int     flags;
   95         caddr_t data;
   96 };
   97 #endif
   98 /* ARGSUSED */
   99 int
  100 mount(p, uap)
  101         struct proc *p;
  102         register struct mount_args /* {
  103                 syscallarg(char *) type;
  104                 syscallarg(char *) path;
  105                 syscallarg(int) flags;
  106                 syscallarg(caddr_t) data;
  107         } */ *uap;
  108 {
  109         struct vnode *vp;
  110         struct mount *mp;
  111         struct vfsconf *vfsp;
  112         int error, flag = 0, flag2 = 0;
  113         struct vattr va;
  114         u_long fstypenum;
  115         struct nameidata nd;
  116         char fstypename[MFSNAMELEN];
  117 
  118         if (usermount == 0 && (error = suser(p->p_ucred, &p->p_acflag)))
  119                 return (error);
  120 
  121         /*
  122          * Get vnode to be covered
  123          */
  124         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
  125             SCARG(uap, path), p);
  126         if (error = namei(&nd))
  127                 return (error);
  128         vp = nd.ni_vp;
  129         if (SCARG(uap, flags) & MNT_UPDATE) {
  130                 if ((vp->v_flag & VROOT) == 0) {
  131                         vput(vp);
  132                         return (EINVAL);
  133                 }
  134                 mp = vp->v_mount;
  135                 flag = mp->mnt_flag;
  136                 flag2 = mp->mnt_kern_flag;
  137                 /*
  138                  * We only allow the filesystem to be reloaded if it
  139                  * is currently mounted read-only.
  140                  */
  141                 if ((SCARG(uap, flags) & MNT_RELOAD) &&
  142                     ((mp->mnt_flag & MNT_RDONLY) == 0)) {
  143                         vput(vp);
  144                         return (EOPNOTSUPP);    /* Needs translation */
  145                 }
  146                 mp->mnt_flag |=
  147                     SCARG(uap, flags) & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE);
  148                 /*
  149                  * Only root, or the user that did the original mount is
  150                  * permitted to update it.
  151                  */
  152                 if (mp->mnt_stat.f_owner != p->p_ucred->cr_uid &&
  153                     (error = suser(p->p_ucred, &p->p_acflag))) {
  154                         vput(vp);
  155                         return (error);
  156                 }
  157                 /*
  158                  * Do not allow NFS export by non-root users. Silently
  159                  * enforce MNT_NOSUID and MNT_NODEV for non-root users.
  160                  */
  161                 if (p->p_ucred->cr_uid != 0) {
  162                         if (SCARG(uap, flags) & MNT_EXPORTED) {
  163                                 vput(vp);
  164                                 return (EPERM);
  165                         }
  166                         SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV;
  167                 }
  168                 if (vfs_busy(mp, LK_NOWAIT, 0, p)) {
  169                         vput(vp);
  170                         return (EBUSY);
  171                 }
  172                 VOP_UNLOCK(vp, 0, p);
  173                 goto update;
  174         }
  175         /*
  176          * If the user is not root, ensure that they own the directory
  177          * onto which we are attempting to mount.
  178          */
  179         if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) ||
  180             (va.va_uid != p->p_ucred->cr_uid &&
  181              (error = suser(p->p_ucred, &p->p_acflag)))) {
  182                 vput(vp);
  183                 return (error);
  184         }
  185         /*
  186          * Do not allow NFS export by non-root users. Silently
  187          * enforce MNT_NOSUID and MNT_NODEV for non-root users.
  188          */
  189         if (p->p_ucred->cr_uid != 0) {
  190                 if (SCARG(uap, flags) & MNT_EXPORTED) {
  191                         vput(vp);
  192                         return (EPERM);
  193                 }
  194                 SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV;
  195         }
  196         if (error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0))
  197                 return (error);
  198         if (vp->v_type != VDIR) {
  199                 vput(vp);
  200                 return (ENOTDIR);
  201         }
  202 #ifdef COMPAT_43
  203         /*
  204          * Historically filesystem types were identified by number. If we
  205          * get an integer for the filesystem type instead of a string, we
  206          * check to see if it matches one of the historic filesystem types.
  207          */
  208         fstypenum = (uintptr_t)SCARG(uap, type);
  209         if (fstypenum < maxvfsconf) {
  210                 for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
  211                         if (vfsp->vfc_typenum == fstypenum)
  212                                 break;
  213                 if (vfsp == NULL) {
  214                         vput(vp);
  215                         return (ENODEV);
  216                 }
  217                 strncpy(fstypename, vfsp->vfc_name, MFSNAMELEN);
  218         } else
  219 #endif /* COMPAT_43 */
  220         if (error = copyinstr(SCARG(uap, type), fstypename, MFSNAMELEN, NULL)) {
  221                 vput(vp);
  222                 return (error);
  223         }
  224         for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
  225                 if (!strcmp(vfsp->vfc_name, fstypename))
  226                         break;
  227         if (vfsp == NULL) {
  228                 linker_file_t lf;
  229 
  230                 /* Refuse to load modules if securelevel raised */
  231                 if (securelevel > 0) {
  232                         vput(vp);
  233                         return EPERM; 
  234                 }
  235                 /* Only load modules for root (very important!) */
  236                 if (error = suser(p->p_ucred, &p->p_acflag)) {
  237                         vput(vp);
  238                         return error;
  239                 }
  240                 error = linker_load_file(fstypename, &lf);
  241                 if (error || lf == NULL) {
  242                         vput(vp);
  243                         if (lf == NULL)
  244                                 error = ENODEV;
  245                         return error;
  246                 }
  247                 lf->userrefs++;
  248                 /* lookup again, see if the VFS was loaded */
  249                 for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
  250                         if (!strcmp(vfsp->vfc_name, fstypename))
  251                                 break;
  252                 if (vfsp == NULL) {
  253                         lf->userrefs--;
  254                         linker_file_unload(lf);
  255                         vput(vp);
  256                         return (ENODEV);
  257                 }
  258         }
  259         simple_lock(&vp->v_interlock);
  260         if ((vp->v_flag & VMOUNT) != 0 ||
  261             vp->v_mountedhere != NULL) {
  262                 simple_unlock(&vp->v_interlock);
  263                 vput(vp);
  264                 return (EBUSY);
  265         }
  266         vp->v_flag |= VMOUNT;
  267         simple_unlock(&vp->v_interlock);
  268 
  269         /*
  270          * Allocate and initialize the filesystem.
  271          */
  272         mp = (struct mount *)malloc((u_long)sizeof(struct mount),
  273                 M_MOUNT, M_WAITOK);
  274         bzero((char *)mp, (u_long)sizeof(struct mount));
  275         lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, LK_NOPAUSE);
  276         (void)vfs_busy(mp, LK_NOWAIT, 0, p);
  277         mp->mnt_op = vfsp->vfc_vfsops;
  278         mp->mnt_vfc = vfsp;
  279         vfsp->vfc_refcount++;
  280         mp->mnt_stat.f_type = vfsp->vfc_typenum;
  281         mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK;
  282         strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN);
  283         mp->mnt_vnodecovered = vp;
  284         mp->mnt_stat.f_owner = p->p_ucred->cr_uid;
  285         VOP_UNLOCK(vp, 0, p);
  286 update:
  287         /*
  288          * Set the mount level flags.
  289          */
  290         if (SCARG(uap, flags) & MNT_RDONLY)
  291                 mp->mnt_flag |= MNT_RDONLY;
  292         else if (mp->mnt_flag & MNT_RDONLY)
  293                 mp->mnt_kern_flag |= MNTK_WANTRDWR;
  294         mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV |
  295             MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_NOATIME |
  296             MNT_NOSYMFOLLOW |
  297             MNT_NOCLUSTERR | MNT_NOCLUSTERW | MNT_SUIDDIR);
  298         mp->mnt_flag |= SCARG(uap, flags) & (MNT_NOSUID | MNT_NOEXEC |
  299             MNT_NODEV | MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_FORCE |
  300             MNT_NOSYMFOLLOW |
  301             MNT_NOATIME | MNT_NOCLUSTERR | MNT_NOCLUSTERW | MNT_SUIDDIR);
  302         /*
  303          * Mount the filesystem.
  304          */
  305         error = VFS_MOUNT(mp, SCARG(uap, path), SCARG(uap, data), &nd, p);
  306         if (mp->mnt_flag & MNT_UPDATE) {
  307                 vrele(vp);
  308                 if (mp->mnt_kern_flag & MNTK_WANTRDWR)
  309                         mp->mnt_flag &= ~MNT_RDONLY;
  310                 mp->mnt_flag &=~ (MNT_UPDATE | MNT_RELOAD | MNT_FORCE);
  311                 mp->mnt_kern_flag &=~ MNTK_WANTRDWR;
  312                 if (error) {
  313                         mp->mnt_flag = flag;
  314                         mp->mnt_kern_flag = flag2;
  315                 }
  316                 if ((mp->mnt_flag & MNT_RDONLY) == 0) {
  317                         if (mp->mnt_syncer == NULL)
  318                                 error = vfs_allocate_syncvnode(mp);
  319                 } else {
  320                         if (mp->mnt_syncer != NULL)
  321                                 vrele(mp->mnt_syncer);
  322                         mp->mnt_syncer = NULL;
  323                 }
  324                 vfs_unbusy(mp, p);
  325                 return (error);
  326         }
  327         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
  328         /*
  329          * Put the new filesystem on the mount list after root.
  330          */
  331         cache_purge(vp);
  332         if (!error) {
  333                 simple_lock(&vp->v_interlock);
  334                 vp->v_flag &= ~VMOUNT;
  335                 vp->v_mountedhere = mp;
  336                 simple_unlock(&vp->v_interlock);
  337                 simple_lock(&mountlist_slock);
  338                 CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
  339                 simple_unlock(&mountlist_slock);
  340                 checkdirs(vp);
  341                 VOP_UNLOCK(vp, 0, p);
  342                 if ((mp->mnt_flag & MNT_RDONLY) == 0)
  343                         error = vfs_allocate_syncvnode(mp);
  344                 vfs_unbusy(mp, p);
  345                 if (error = VFS_START(mp, 0, p))
  346                         vrele(vp);
  347         } else {
  348                 simple_lock(&vp->v_interlock);
  349                 vp->v_flag &= ~VMOUNT;
  350                 simple_unlock(&vp->v_interlock);
  351                 mp->mnt_vfc->vfc_refcount--;
  352                 vfs_unbusy(mp, p);
  353                 free((caddr_t)mp, M_MOUNT);
  354                 vput(vp);
  355         }
  356         return (error);
  357 }
  358 
  359 /*
  360  * Scan all active processes to see if any of them have a current
  361  * or root directory onto which the new filesystem has just been
  362  * mounted. If so, replace them with the new mount point.
  363  */
  364 static void
  365 checkdirs(olddp)
  366         struct vnode *olddp;
  367 {
  368         struct filedesc *fdp;
  369         struct vnode *newdp;
  370         struct proc *p;
  371 
  372         if (olddp->v_usecount == 1)
  373                 return;
  374         if (VFS_ROOT(olddp->v_mountedhere, &newdp))
  375                 panic("mount: lost mount");
  376         for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
  377                 fdp = p->p_fd;
  378                 if (fdp->fd_cdir == olddp) {
  379                         vrele(fdp->fd_cdir);
  380                         VREF(newdp);
  381                         fdp->fd_cdir = newdp;
  382                 }
  383                 if (fdp->fd_rdir == olddp) {
  384                         vrele(fdp->fd_rdir);
  385                         VREF(newdp);
  386                         fdp->fd_rdir = newdp;
  387                 }
  388         }
  389         if (rootvnode == olddp) {
  390                 vrele(rootvnode);
  391                 VREF(newdp);
  392                 rootvnode = newdp;
  393         }
  394         vput(newdp);
  395 }
  396 
  397 /*
  398  * Unmount a file system.
  399  *
  400  * Note: unmount takes a path to the vnode mounted on as argument,
  401  * not special file (as before).
  402  */
  403 #ifndef _SYS_SYSPROTO_H_
  404 struct unmount_args {
  405         char    *path;
  406         int     flags;
  407 };
  408 #endif
  409 /* ARGSUSED */
  410 int
  411 unmount(p, uap)
  412         struct proc *p;
  413         register struct unmount_args /* {
  414                 syscallarg(char *) path;
  415                 syscallarg(int) flags;
  416         } */ *uap;
  417 {
  418         register struct vnode *vp;
  419         struct mount *mp;
  420         int error;
  421         struct nameidata nd;
  422 
  423         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
  424             SCARG(uap, path), p);
  425         if (error = namei(&nd))
  426                 return (error);
  427         vp = nd.ni_vp;
  428         mp = vp->v_mount;
  429 
  430         /*
  431          * Only root, or the user that did the original mount is
  432          * permitted to unmount this filesystem.
  433          */
  434         if ((mp->mnt_stat.f_owner != p->p_ucred->cr_uid) &&
  435             (error = suser(p->p_ucred, &p->p_acflag))) {
  436                 vput(vp);
  437                 return (error);
  438         }
  439 
  440         /*
  441          * Don't allow unmounting the root file system.
  442          */
  443         if (mp->mnt_flag & MNT_ROOTFS) {
  444                 vput(vp);
  445                 return (EINVAL);
  446         }
  447 
  448         /*
  449          * Must be the root of the filesystem
  450          */
  451         if ((vp->v_flag & VROOT) == 0) {
  452                 vput(vp);
  453                 return (EINVAL);
  454         }
  455         vput(vp);
  456         return (dounmount(mp, SCARG(uap, flags), p));
  457 }
  458 
  459 /*
  460  * Do the actual file system unmount.
  461  */
  462 int
  463 dounmount(mp, flags, p)
  464         register struct mount *mp;
  465         int flags;
  466         struct proc *p;
  467 {
  468         struct vnode *coveredvp;
  469         int error;
  470         int async_flag;
  471 
  472         simple_lock(&mountlist_slock);
  473         mp->mnt_kern_flag |= MNTK_UNMOUNT;
  474         lockmgr(&mp->mnt_lock, LK_DRAIN | LK_INTERLOCK, &mountlist_slock, p);
  475 
  476         if (mp->mnt_flag & MNT_EXPUBLIC)
  477                 vfs_setpublicfs(NULL, NULL, NULL);
  478 
  479         vfs_msync(mp, MNT_WAIT);
  480         async_flag = mp->mnt_flag & MNT_ASYNC;
  481         mp->mnt_flag &=~ MNT_ASYNC;
  482         cache_purgevfs(mp);     /* remove cache entries for this file sys */
  483         if (mp->mnt_syncer != NULL)
  484                 vrele(mp->mnt_syncer);
  485         if (((mp->mnt_flag & MNT_RDONLY) ||
  486              (error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0) ||
  487             (flags & MNT_FORCE))
  488                 error = VFS_UNMOUNT(mp, flags, p);
  489         simple_lock(&mountlist_slock);
  490         if (error) {
  491                 if ((mp->mnt_flag & MNT_RDONLY) == 0 && mp->mnt_syncer == NULL)
  492                         (void) vfs_allocate_syncvnode(mp);
  493                 mp->mnt_kern_flag &= ~MNTK_UNMOUNT;
  494                 mp->mnt_flag |= async_flag;
  495                 lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK | LK_REENABLE,
  496                     &mountlist_slock, p);
  497                 if (mp->mnt_kern_flag & MNTK_MWAIT)
  498                         wakeup((caddr_t)mp);
  499                 return (error);
  500         }
  501         CIRCLEQ_REMOVE(&mountlist, mp, mnt_list);
  502         if ((coveredvp = mp->mnt_vnodecovered) != NULLVP) {
  503                 coveredvp->v_mountedhere = (struct mount *)0;
  504                 vrele(coveredvp);
  505         }
  506         mp->mnt_vfc->vfc_refcount--;
  507         if (mp->mnt_vnodelist.lh_first != NULL)
  508                 panic("unmount: dangling vnode");
  509         lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK, &mountlist_slock, p);
  510         if (mp->mnt_kern_flag & MNTK_MWAIT)
  511                 wakeup((caddr_t)mp);
  512         free((caddr_t)mp, M_MOUNT);
  513         return (0);
  514 }
  515 
  516 /*
  517  * Sync each mounted filesystem.
  518  */
  519 #ifndef _SYS_SYSPROTO_H_
  520 struct sync_args {
  521         int     dummy;
  522 };
  523 #endif
  524 
  525 #ifdef DEBUG
  526 static int syncprt = 0;
  527 SYSCTL_INT(_debug, OID_AUTO, syncprt, CTLFLAG_RW, &syncprt, 0, "");
  528 #endif
  529 
  530 /* ARGSUSED */
  531 int
  532 sync(p, uap)
  533         struct proc *p;
  534         struct sync_args *uap;
  535 {
  536         register struct mount *mp, *nmp;
  537         int asyncflag;
  538 
  539         simple_lock(&mountlist_slock);
  540         for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) {
  541                 if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
  542                         nmp = mp->mnt_list.cqe_next;
  543                         continue;
  544                 }
  545                 if ((mp->mnt_flag & MNT_RDONLY) == 0) {
  546                         asyncflag = mp->mnt_flag & MNT_ASYNC;
  547                         mp->mnt_flag &= ~MNT_ASYNC;
  548                         vfs_msync(mp, MNT_NOWAIT);
  549                         VFS_SYNC(mp, MNT_NOWAIT,
  550                                 ((p != NULL) ? p->p_ucred : NOCRED), p);
  551                         mp->mnt_flag |= asyncflag;
  552                 }
  553                 simple_lock(&mountlist_slock);
  554                 nmp = mp->mnt_list.cqe_next;
  555                 vfs_unbusy(mp, p);
  556         }
  557         simple_unlock(&mountlist_slock);
  558 #if 0
  559 /*
  560  * XXX don't call vfs_bufstats() yet because that routine
  561  * was not imported in the Lite2 merge.
  562  */
  563 #ifdef DIAGNOSTIC
  564         if (syncprt)
  565                 vfs_bufstats();
  566 #endif /* DIAGNOSTIC */
  567 #endif
  568         return (0);
  569 }
  570 
  571 /*
  572  * Change filesystem quotas.
  573  */
  574 #ifndef _SYS_SYSPROTO_H_
  575 struct quotactl_args {
  576         char *path;
  577         int cmd;
  578         int uid;
  579         caddr_t arg;
  580 };
  581 #endif
  582 /* ARGSUSED */
  583 int
  584 quotactl(p, uap)
  585         struct proc *p;
  586         register struct quotactl_args /* {
  587                 syscallarg(char *) path;
  588                 syscallarg(int) cmd;
  589                 syscallarg(int) uid;
  590                 syscallarg(caddr_t) arg;
  591         } */ *uap;
  592 {
  593         register struct mount *mp;
  594         int error;
  595         struct nameidata nd;
  596 
  597         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
  598         if (error = namei(&nd))
  599                 return (error);
  600         mp = nd.ni_vp->v_mount;
  601         vrele(nd.ni_vp);
  602         return (VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid),
  603             SCARG(uap, arg), p));
  604 }
  605 
  606 /*
  607  * Get filesystem statistics.
  608  */
  609 #ifndef _SYS_SYSPROTO_H_
  610 struct statfs_args {
  611         char *path;
  612         struct statfs *buf;
  613 };
  614 #endif
  615 /* ARGSUSED */
  616 int
  617 statfs(p, uap)
  618         struct proc *p;
  619         register struct statfs_args /* {
  620                 syscallarg(char *) path;
  621                 syscallarg(struct statfs *) buf;
  622         } */ *uap;
  623 {
  624         register struct mount *mp;
  625         register struct statfs *sp;
  626         int error;
  627         struct nameidata nd;
  628         struct statfs sb;
  629 
  630         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
  631         if (error = namei(&nd))
  632                 return (error);
  633         mp = nd.ni_vp->v_mount;
  634         sp = &mp->mnt_stat;
  635         vrele(nd.ni_vp);
  636         error = VFS_STATFS(mp, sp, p);
  637         if (error)
  638                 return (error);
  639         sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
  640         if (p->p_ucred->cr_uid != 0) {
  641                 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
  642                 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
  643                 sp = &sb;
  644         }
  645         return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp)));
  646 }
  647 
  648 /*
  649  * Get filesystem statistics.
  650  */
  651 #ifndef _SYS_SYSPROTO_H_
  652 struct fstatfs_args {
  653         int fd;
  654         struct statfs *buf;
  655 };
  656 #endif
  657 /* ARGSUSED */
  658 int
  659 fstatfs(p, uap)
  660         struct proc *p;
  661         register struct fstatfs_args /* {
  662                 syscallarg(int) fd;
  663                 syscallarg(struct statfs *) buf;
  664         } */ *uap;
  665 {
  666         struct file *fp;
  667         struct mount *mp;
  668         register struct statfs *sp;
  669         int error;
  670         struct statfs sb;
  671 
  672         if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
  673                 return (error);
  674         mp = ((struct vnode *)fp->f_data)->v_mount;
  675         sp = &mp->mnt_stat;
  676         error = VFS_STATFS(mp, sp, p);
  677         if (error)
  678                 return (error);
  679         sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
  680         if (p->p_ucred->cr_uid != 0) {
  681                 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
  682                 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
  683                 sp = &sb;
  684         }
  685         return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp)));
  686 }
  687 
  688 /*
  689  * Get statistics on all filesystems.
  690  */
  691 #ifndef _SYS_SYSPROTO_H_
  692 struct getfsstat_args {
  693         struct statfs *buf;
  694         long bufsize;
  695         int flags;
  696 };
  697 #endif
  698 int
  699 getfsstat(p, uap)
  700         struct proc *p;
  701         register struct getfsstat_args /* {
  702                 syscallarg(struct statfs *) buf;
  703                 syscallarg(long) bufsize;
  704                 syscallarg(int) flags;
  705         } */ *uap;
  706 {
  707         register struct mount *mp, *nmp;
  708         register struct statfs *sp;
  709         caddr_t sfsp;
  710         long count, maxcount, error;
  711 
  712         maxcount = SCARG(uap, bufsize) / sizeof(struct statfs);
  713         sfsp = (caddr_t)SCARG(uap, buf);
  714         count = 0;
  715         simple_lock(&mountlist_slock);
  716         for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) {
  717                 if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
  718                         nmp = mp->mnt_list.cqe_next;
  719                         continue;
  720                 }
  721                 if (sfsp && count < maxcount) {
  722                         sp = &mp->mnt_stat;
  723                         /*
  724                          * If MNT_NOWAIT or MNT_LAZY is specified, do not
  725                          * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY
  726                          * overrides MNT_WAIT.
  727                          */
  728                         if (((SCARG(uap, flags) & (MNT_LAZY|MNT_NOWAIT)) == 0 ||
  729                             (SCARG(uap, flags) & MNT_WAIT)) &&
  730                             (error = VFS_STATFS(mp, sp, p))) {
  731                                 simple_lock(&mountlist_slock);
  732                                 nmp = mp->mnt_list.cqe_next;
  733                                 vfs_unbusy(mp, p);
  734                                 continue;
  735                         }
  736                         sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
  737                         error = copyout((caddr_t)sp, sfsp, sizeof(*sp));
  738                         if (error) {
  739                                 vfs_unbusy(mp, p);
  740                                 return (error);
  741                         }
  742                         sfsp += sizeof(*sp);
  743                 }
  744                 count++;
  745                 simple_lock(&mountlist_slock);
  746                 nmp = mp->mnt_list.cqe_next;
  747                 vfs_unbusy(mp, p);
  748         }
  749         simple_unlock(&mountlist_slock);
  750         if (sfsp && count > maxcount)
  751                 p->p_retval[0] = maxcount;
  752         else
  753                 p->p_retval[0] = count;
  754         return (0);
  755 }
  756 
  757 /*
  758  * Change current working directory to a given file descriptor.
  759  */
  760 #ifndef _SYS_SYSPROTO_H_
  761 struct fchdir_args {
  762         int     fd;
  763 };
  764 #endif
  765 /* ARGSUSED */
  766 int
  767 fchdir(p, uap)
  768         struct proc *p;
  769         struct fchdir_args /* {
  770                 syscallarg(int) fd;
  771         } */ *uap;
  772 {
  773         register struct filedesc *fdp = p->p_fd;
  774         struct vnode *vp, *tdp;
  775         struct mount *mp;
  776         struct file *fp;
  777         int error;
  778 
  779         if (error = getvnode(fdp, SCARG(uap, fd), &fp))
  780                 return (error);
  781         vp = (struct vnode *)fp->f_data;
  782         VREF(vp);
  783         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
  784         if (vp->v_type != VDIR)
  785                 error = ENOTDIR;
  786         else
  787                 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
  788         while (!error && (mp = vp->v_mountedhere) != NULL) {
  789                 if (vfs_busy(mp, 0, 0, p))
  790                         continue;
  791                 error = VFS_ROOT(mp, &tdp);
  792                 vfs_unbusy(mp, p);
  793                 if (error)
  794                         break;
  795                 vput(vp);
  796                 vp = tdp;
  797         }
  798         if (error) {
  799                 vput(vp);
  800                 return (error);
  801         }
  802         VOP_UNLOCK(vp, 0, p);
  803         vrele(fdp->fd_cdir);
  804         fdp->fd_cdir = vp;
  805         return (0);
  806 }
  807 
  808 /*
  809  * Change current working directory (``.'').
  810  */
  811 #ifndef _SYS_SYSPROTO_H_
  812 struct chdir_args {
  813         char    *path;
  814 };
  815 #endif
  816 /* ARGSUSED */
  817 int
  818 chdir(p, uap)
  819         struct proc *p;
  820         struct chdir_args /* {
  821                 syscallarg(char *) path;
  822         } */ *uap;
  823 {
  824         register struct filedesc *fdp = p->p_fd;
  825         int error;
  826         struct nameidata nd;
  827 
  828         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
  829             SCARG(uap, path), p);
  830         if (error = change_dir(&nd, p))
  831                 return (error);
  832         vrele(fdp->fd_cdir);
  833         fdp->fd_cdir = nd.ni_vp;
  834         return (0);
  835 }
  836 
  837 /*
  838  * Change notion of root (``/'') directory.
  839  */
  840 #ifndef _SYS_SYSPROTO_H_
  841 struct chroot_args {
  842         char    *path;
  843 };
  844 #endif
  845 /* ARGSUSED */
  846 int
  847 chroot(p, uap)
  848         struct proc *p;
  849         struct chroot_args /* {
  850                 syscallarg(char *) path;
  851         } */ *uap;
  852 {
  853         register struct filedesc *fdp = p->p_fd;
  854         int error;
  855         struct nameidata nd;
  856 
  857         error = suser(p->p_ucred, &p->p_acflag);
  858         if (error)
  859                 return (error);
  860         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
  861             SCARG(uap, path), p);
  862         if (error = change_dir(&nd, p))
  863                 return (error);
  864         vrele(fdp->fd_rdir);
  865         fdp->fd_rdir = nd.ni_vp;
  866         return (0);
  867 }
  868 
  869 /*
  870  * Common routine for chroot and chdir.
  871  */
  872 static int
  873 change_dir(ndp, p)
  874         register struct nameidata *ndp;
  875         struct proc *p;
  876 {
  877         struct vnode *vp;
  878         int error;
  879 
  880         error = namei(ndp);
  881         if (error)
  882                 return (error);
  883         vp = ndp->ni_vp;
  884         if (vp->v_type != VDIR)
  885                 error = ENOTDIR;
  886         else
  887                 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
  888         if (error)
  889                 vput(vp);
  890         else
  891                 VOP_UNLOCK(vp, 0, p);
  892         return (error);
  893 }
  894 
  895 /*
  896  * Check permissions, allocate an open file structure,
  897  * and call the device open routine if any.
  898  */
  899 #ifndef _SYS_SYSPROTO_H_
  900 struct open_args {
  901         char    *path;
  902         int     flags;
  903         int     mode;
  904 };
  905 #endif
  906 int
  907 open(p, uap)
  908         struct proc *p;
  909         register struct open_args /* {
  910                 syscallarg(char *) path;
  911                 syscallarg(int) flags;
  912                 syscallarg(int) mode;
  913         } */ *uap;
  914 {
  915         register struct filedesc *fdp = p->p_fd;
  916         register struct file *fp;
  917         register struct vnode *vp;
  918         int cmode, flags, oflags;
  919         struct file *nfp;
  920         int type, indx, error;
  921         struct flock lf;
  922         struct nameidata nd;
  923 
  924         oflags = SCARG(uap, flags);
  925         if ((oflags & O_ACCMODE) == O_ACCMODE)
  926                 return (EINVAL);
  927         flags = FFLAGS(oflags);
  928         error = falloc(p, &nfp, &indx);
  929         if (error)
  930                 return (error);
  931         fp = nfp;
  932         cmode = ((SCARG(uap, mode) &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
  933         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
  934         p->p_dupfd = -indx - 1;                 /* XXX check for fdopen */
  935         error = vn_open(&nd, flags, cmode);
  936         if (error) {
  937                 ffree(fp);
  938                 if ((error == ENODEV || error == ENXIO) &&
  939                     p->p_dupfd >= 0 &&                  /* XXX from fdopen */
  940                     (error =
  941                         dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) {
  942                         p->p_retval[0] = indx;
  943                         return (0);
  944                 }
  945                 if (error == ERESTART)
  946                         error = EINTR;
  947                 fdp->fd_ofiles[indx] = NULL;
  948                 return (error);
  949         }
  950         p->p_dupfd = 0;
  951         vp = nd.ni_vp;
  952 
  953         fp->f_flag = flags & FMASK;
  954         fp->f_type = (vp->v_type == VFIFO ? DTYPE_FIFO : DTYPE_VNODE);
  955         fp->f_ops = &vnops;
  956         fp->f_data = (caddr_t)vp;
  957         if (flags & (O_EXLOCK | O_SHLOCK)) {
  958                 lf.l_whence = SEEK_SET;
  959                 lf.l_start = 0;
  960                 lf.l_len = 0;
  961                 if (flags & O_EXLOCK)
  962                         lf.l_type = F_WRLCK;
  963                 else
  964                         lf.l_type = F_RDLCK;
  965                 type = F_FLOCK;
  966                 if ((flags & FNONBLOCK) == 0)
  967                         type |= F_WAIT;
  968                 VOP_UNLOCK(vp, 0, p);
  969                 if (error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) {
  970                         (void) vn_close(vp, fp->f_flag, fp->f_cred, p);
  971                         ffree(fp);
  972                         fdp->fd_ofiles[indx] = NULL;
  973                         return (error);
  974                 }
  975                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
  976                 fp->f_flag |= FHASLOCK;
  977         }
  978         if ((vp->v_type == VREG) && (vp->v_object == NULL))
  979                 vfs_object_create(vp, p, p->p_ucred);
  980         VOP_UNLOCK(vp, 0, p);
  981         p->p_retval[0] = indx;
  982         return (0);
  983 }
  984 
  985 #ifdef COMPAT_43
  986 /*
  987  * Create a file.
  988  */
  989 #ifndef _SYS_SYSPROTO_H_
  990 struct ocreat_args {
  991         char    *path;
  992         int     mode;
  993 };
  994 #endif
  995 int
  996 ocreat(p, uap)
  997         struct proc *p;
  998         register struct ocreat_args /* {
  999                 syscallarg(char *) path;
 1000                 syscallarg(int) mode;
 1001         } */ *uap;
 1002 {
 1003         struct open_args /* {
 1004                 syscallarg(char *) path;
 1005                 syscallarg(int) flags;
 1006                 syscallarg(int) mode;
 1007         } */ nuap;
 1008 
 1009         SCARG(&nuap, path) = SCARG(uap, path);
 1010         SCARG(&nuap, mode) = SCARG(uap, mode);
 1011         SCARG(&nuap, flags) = O_WRONLY | O_CREAT | O_TRUNC;
 1012         return (open(p, &nuap));
 1013 }
 1014 #endif /* COMPAT_43 */
 1015 
 1016 /*
 1017  * Create a special file.
 1018  */
 1019 #ifndef _SYS_SYSPROTO_H_
 1020 struct mknod_args {
 1021         char    *path;
 1022         int     mode;
 1023         int     dev;
 1024 };
 1025 #endif
 1026 /* ARGSUSED */
 1027 int
 1028 mknod(p, uap)
 1029         struct proc *p;
 1030         register struct mknod_args /* {
 1031                 syscallarg(char *) path;
 1032                 syscallarg(int) mode;
 1033                 syscallarg(int) dev;
 1034         } */ *uap;
 1035 {
 1036         register struct vnode *vp;
 1037         struct vattr vattr;
 1038         int error;
 1039         int whiteout = 0;
 1040         struct nameidata nd;
 1041 
 1042         error = suser(p->p_ucred, &p->p_acflag);
 1043         if (error)
 1044                 return (error);
 1045         NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
 1046         if (error = namei(&nd))
 1047                 return (error);
 1048         vp = nd.ni_vp;
 1049         if (vp != NULL)
 1050                 error = EEXIST;
 1051         else {
 1052                 VATTR_NULL(&vattr);
 1053                 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
 1054                 vattr.va_rdev = SCARG(uap, dev);
 1055                 whiteout = 0;
 1056 
 1057                 switch (SCARG(uap, mode) & S_IFMT) {
 1058                 case S_IFMT:    /* used by badsect to flag bad sectors */
 1059                         vattr.va_type = VBAD;
 1060                         break;
 1061                 case S_IFCHR:
 1062                         vattr.va_type = VCHR;
 1063                         break;
 1064                 case S_IFBLK:
 1065                         vattr.va_type = VBLK;
 1066                         break;
 1067                 case S_IFWHT:
 1068                         whiteout = 1;
 1069                         break;
 1070                 default:
 1071                         error = EINVAL;
 1072                         break;
 1073                 }
 1074         }
 1075         if (!error) {
 1076                 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
 1077                 if (whiteout) {
 1078                         error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE);
 1079                         if (error)
 1080                                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
 1081                         vput(nd.ni_dvp);
 1082                 } else {
 1083                         error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp,
 1084                                                 &nd.ni_cnd, &vattr);
 1085                         vput(nd.ni_dvp);
 1086                 }
 1087         } else {
 1088                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
 1089                 if (nd.ni_dvp == vp)
 1090                         vrele(nd.ni_dvp);
 1091                 else
 1092                         vput(nd.ni_dvp);
 1093                 if (vp)
 1094                         vrele(vp);
 1095         }
 1096         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mknod");
 1097         ASSERT_VOP_UNLOCKED(nd.ni_vp, "mknod");
 1098         return (error);
 1099 }
 1100 
 1101 /*
 1102  * Create a named pipe.
 1103  */
 1104 #ifndef _SYS_SYSPROTO_H_
 1105 struct mkfifo_args {
 1106         char    *path;
 1107         int     mode;
 1108 };
 1109 #endif
 1110 /* ARGSUSED */
 1111 int
 1112 mkfifo(p, uap)
 1113         struct proc *p;
 1114         register struct mkfifo_args /* {
 1115                 syscallarg(char *) path;
 1116                 syscallarg(int) mode;
 1117         } */ *uap;
 1118 {
 1119         struct vattr vattr;
 1120         int error;
 1121         struct nameidata nd;
 1122 
 1123         NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
 1124         if (error = namei(&nd))
 1125                 return (error);
 1126         if (nd.ni_vp != NULL) {
 1127                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
 1128                 if (nd.ni_dvp == nd.ni_vp)
 1129                         vrele(nd.ni_dvp);
 1130                 else
 1131                         vput(nd.ni_dvp);
 1132                 vrele(nd.ni_vp);
 1133                 return (EEXIST);
 1134         }
 1135         VATTR_NULL(&vattr);
 1136         vattr.va_type = VFIFO;
 1137         vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
 1138         VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
 1139         error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
 1140         vput(nd.ni_dvp);
 1141         return (error);
 1142 }
 1143 
 1144 /*
 1145  * Make a hard file link.
 1146  */
 1147 #ifndef _SYS_SYSPROTO_H_
 1148 struct link_args {
 1149         char    *path;
 1150         char    *link;
 1151 };
 1152 #endif
 1153 /* ARGSUSED */
 1154 int
 1155 link(p, uap)
 1156         struct proc *p;
 1157         register struct link_args /* {
 1158                 syscallarg(char *) path;
 1159                 syscallarg(char *) link;
 1160         } */ *uap;
 1161 {
 1162         register struct vnode *vp;
 1163         struct nameidata nd;
 1164         int error;
 1165 
 1166         NDINIT(&nd, LOOKUP, FOLLOW|NOOBJ, UIO_USERSPACE, SCARG(uap, path), p);
 1167         if (error = namei(&nd))
 1168                 return (error);
 1169         vp = nd.ni_vp;
 1170         if (vp->v_type == VDIR)
 1171                 error = EPERM;          /* POSIX */
 1172         else {
 1173                 NDINIT(&nd, CREATE, LOCKPARENT|NOOBJ, UIO_USERSPACE, SCARG(uap, link), p);
 1174                 error = namei(&nd);
 1175                 if (!error) {
 1176                         if (nd.ni_vp != NULL) {
 1177                                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
 1178                                 if (nd.ni_vp)
 1179                                         vrele(nd.ni_vp);
 1180                                 error = EEXIST;
 1181                         } else {
 1182                                 VOP_LEASE(nd.ni_dvp, p, p->p_ucred,
 1183                                     LEASE_WRITE);
 1184                                 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
 1185                                 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
 1186                         }
 1187                         if (nd.ni_dvp == nd.ni_vp)
 1188                                 vrele(nd.ni_dvp);
 1189                         else
 1190                                 vput(nd.ni_dvp);
 1191                 }
 1192         }
 1193         vrele(vp);
 1194         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "link");
 1195         ASSERT_VOP_UNLOCKED(nd.ni_vp, "link");
 1196         return (error);
 1197 }
 1198 
 1199 /*
 1200  * Make a symbolic link.
 1201  */
 1202 #ifndef _SYS_SYSPROTO_H_
 1203 struct symlink_args {
 1204         char    *path;
 1205         char    *link;
 1206 };
 1207 #endif
 1208 /* ARGSUSED */
 1209 int
 1210 symlink(p, uap)
 1211         struct proc *p;
 1212         register struct symlink_args /* {
 1213                 syscallarg(char *) path;
 1214                 syscallarg(char *) link;
 1215         } */ *uap;
 1216 {
 1217         struct vattr vattr;
 1218         char *path;
 1219         int error;
 1220         struct nameidata nd;
 1221 
 1222         path = zalloc(namei_zone);
 1223         if (error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL))
 1224                 goto out;
 1225         NDINIT(&nd, CREATE, LOCKPARENT|NOOBJ, UIO_USERSPACE, SCARG(uap, link), p);
 1226         if (error = namei(&nd))
 1227                 goto out;
 1228         if (nd.ni_vp) {
 1229                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
 1230                 if (nd.ni_dvp == nd.ni_vp)
 1231                         vrele(nd.ni_dvp);
 1232                 else
 1233                         vput(nd.ni_dvp);
 1234                 vrele(nd.ni_vp);
 1235                 error = EEXIST;
 1236                 goto out;
 1237         }
 1238         VATTR_NULL(&vattr);
 1239         vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask;
 1240         VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
 1241         error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path);
 1242         vput(nd.ni_dvp);
 1243         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "symlink");
 1244         ASSERT_VOP_UNLOCKED(nd.ni_vp, "symlink");
 1245 out:
 1246         zfree(namei_zone, path);
 1247         return (error);
 1248 }
 1249 
 1250 /*
 1251  * Delete a whiteout from the filesystem.
 1252  */
 1253 /* ARGSUSED */
 1254 int
 1255 undelete(p, uap)
 1256         struct proc *p;
 1257         register struct undelete_args /* {
 1258                 syscallarg(char *) path;
 1259         } */ *uap;
 1260 {
 1261         int error;
 1262         struct nameidata nd;
 1263 
 1264         NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE,
 1265             SCARG(uap, path), p);
 1266         error = namei(&nd);
 1267         if (error)
 1268                 return (error);
 1269 
 1270         if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) {
 1271                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
 1272                 if (nd.ni_dvp == nd.ni_vp)
 1273                         vrele(nd.ni_dvp);
 1274                 else
 1275                         vput(nd.ni_dvp);
 1276                 if (nd.ni_vp)
 1277                         vrele(nd.ni_vp);
 1278                 return (EEXIST);
 1279         }
 1280 
 1281         VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
 1282         if (error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE))
 1283                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
 1284         vput(nd.ni_dvp);
 1285         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "undelete");
 1286         ASSERT_VOP_UNLOCKED(nd.ni_vp, "undelete");
 1287         return (error);
 1288 }
 1289 
 1290 /*
 1291  * Delete a name from the filesystem.
 1292  */
 1293 #ifndef _SYS_SYSPROTO_H_
 1294 struct unlink_args {
 1295         char    *path;
 1296 };
 1297 #endif
 1298 /* ARGSUSED */
 1299 int
 1300 unlink(p, uap)
 1301         struct proc *p;
 1302         struct unlink_args /* {
 1303                 syscallarg(char *) path;
 1304         } */ *uap;
 1305 {
 1306         register struct vnode *vp;
 1307         int error;
 1308         struct nameidata nd;
 1309 
 1310         NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
 1311         if (error = namei(&nd))
 1312                 return (error);
 1313         vp = nd.ni_vp;
 1314         VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
 1315         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
 1316 
 1317         if (vp->v_type == VDIR)
 1318                 error = EPERM;          /* POSIX */
 1319         else {
 1320                 /*
 1321                  * The root of a mounted filesystem cannot be deleted.
 1322                  *
 1323                  * XXX: can this only be a VDIR case?
 1324                  */
 1325                 if (vp->v_flag & VROOT)
 1326                         error = EBUSY;
 1327         }
 1328 
 1329         if (!error) {
 1330                 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
 1331                 error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd);
 1332         } else {
 1333                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
 1334         }
 1335         if (nd.ni_dvp == vp)
 1336                 vrele(nd.ni_dvp);
 1337         else
 1338                 vput(nd.ni_dvp);
 1339         if (vp != NULLVP)
 1340                 vput(vp);
 1341         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "unlink");
 1342         ASSERT_VOP_UNLOCKED(nd.ni_vp, "unlink");
 1343         return (error);
 1344 }
 1345 
 1346 /*
 1347  * Reposition read/write file offset.
 1348  */
 1349 #ifndef _SYS_SYSPROTO_H_
 1350 struct lseek_args {
 1351         int     fd;
 1352         int     pad;
 1353         off_t   offset;
 1354         int     whence;
 1355 };
 1356 #endif
 1357 int
 1358 lseek(p, uap)
 1359         struct proc *p;
 1360         register struct lseek_args /* {
 1361                 syscallarg(int) fd;
 1362                 syscallarg(int) pad;
 1363                 syscallarg(off_t) offset;
 1364                 syscallarg(int) whence;
 1365         } */ *uap;
 1366 {
 1367         struct ucred *cred = p->p_ucred;
 1368         register struct filedesc *fdp = p->p_fd;
 1369         register struct file *fp;
 1370         struct vattr vattr;
 1371         int error;
 1372 
 1373         if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles ||
 1374             (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL)
 1375                 return (EBADF);
 1376         if (fp->f_type != DTYPE_VNODE)
 1377                 return (ESPIPE);
 1378         switch (SCARG(uap, whence)) {
 1379         case L_INCR:
 1380                 fp->f_offset += SCARG(uap, offset);
 1381                 break;
 1382         case L_XTND:
 1383                 error=VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p);
 1384                 if (error)
 1385                         return (error);
 1386                 fp->f_offset = SCARG(uap, offset) + vattr.va_size;
 1387                 break;
 1388         case L_SET:
 1389                 fp->f_offset = SCARG(uap, offset);
 1390                 break;
 1391         default:
 1392                 return (EINVAL);
 1393         }
 1394         *(off_t *)(p->p_retval) = fp->f_offset;
 1395         return (0);
 1396 }
 1397 
 1398 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
 1399 /*
 1400  * Reposition read/write file offset.
 1401  */
 1402 #ifndef _SYS_SYSPROTO_H_
 1403 struct olseek_args {
 1404         int     fd;
 1405         long    offset;
 1406         int     whence;
 1407 };
 1408 #endif
 1409 int
 1410 olseek(p, uap)
 1411         struct proc *p;
 1412         register struct olseek_args /* {
 1413                 syscallarg(int) fd;
 1414                 syscallarg(long) offset;
 1415                 syscallarg(int) whence;
 1416         } */ *uap;
 1417 {
 1418         struct lseek_args /* {
 1419                 syscallarg(int) fd;
 1420                 syscallarg(int) pad;
 1421                 syscallarg(off_t) offset;
 1422                 syscallarg(int) whence;
 1423         } */ nuap;
 1424         int error;
 1425 
 1426         SCARG(&nuap, fd) = SCARG(uap, fd);
 1427         SCARG(&nuap, offset) = SCARG(uap, offset);
 1428         SCARG(&nuap, whence) = SCARG(uap, whence);
 1429         error = lseek(p, &nuap);
 1430         return (error);
 1431 }
 1432 #endif /* COMPAT_43 */
 1433 
 1434 /*
 1435  * Check access permissions.
 1436  */
 1437 #ifndef _SYS_SYSPROTO_H_
 1438 struct access_args {
 1439         char    *path;
 1440         int     flags;
 1441 };
 1442 #endif
 1443 int
 1444 access(p, uap)
 1445         struct proc *p;
 1446         register struct access_args /* {
 1447                 syscallarg(char *) path;
 1448                 syscallarg(int) flags;
 1449         } */ *uap;
 1450 {
 1451         register struct ucred *cred = p->p_ucred;
 1452         register struct vnode *vp;
 1453         int error, flags, t_gid, t_uid;
 1454         struct nameidata nd;
 1455 
 1456         t_uid = cred->cr_uid;
 1457         t_gid = cred->cr_groups[0];
 1458         cred->cr_uid = p->p_cred->p_ruid;
 1459         cred->cr_groups[0] = p->p_cred->p_rgid;
 1460         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
 1461             SCARG(uap, path), p);
 1462         if (error = namei(&nd))
 1463                 goto out1;
 1464         vp = nd.ni_vp;
 1465 
 1466         /* Flags == 0 means only check for existence. */
 1467         if (SCARG(uap, flags)) {
 1468                 flags = 0;
 1469                 if (SCARG(uap, flags) & R_OK)
 1470                         flags |= VREAD;
 1471                 if (SCARG(uap, flags) & W_OK)
 1472                         flags |= VWRITE;
 1473                 if (SCARG(uap, flags) & X_OK)
 1474                         flags |= VEXEC;
 1475                 if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
 1476                         error = VOP_ACCESS(vp, flags, cred, p);
 1477         }
 1478         vput(vp);
 1479 out1:
 1480         cred->cr_uid = t_uid;
 1481         cred->cr_groups[0] = t_gid;
 1482         return (error);
 1483 }
 1484 
 1485 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
 1486 /*
 1487  * Get file status; this version follows links.
 1488  */
 1489 #ifndef _SYS_SYSPROTO_H_
 1490 struct ostat_args {
 1491         char    *path;
 1492         struct ostat *ub;
 1493 };
 1494 #endif
 1495 /* ARGSUSED */
 1496 int
 1497 ostat(p, uap)
 1498         struct proc *p;
 1499         register struct ostat_args /* {
 1500                 syscallarg(char *) path;
 1501                 syscallarg(struct ostat *) ub;
 1502         } */ *uap;
 1503 {
 1504         struct stat sb;
 1505         struct ostat osb;
 1506         int error;
 1507         struct nameidata nd;
 1508 
 1509         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
 1510             SCARG(uap, path), p);
 1511         if (error = namei(&nd))
 1512                 return (error);
 1513         error = vn_stat(nd.ni_vp, &sb, p);
 1514         vput(nd.ni_vp);
 1515         if (error)
 1516                 return (error);
 1517         cvtstat(&sb, &osb);
 1518         error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb));
 1519         return (error);
 1520 }
 1521 
 1522 /*
 1523  * Get file status; this version does not follow links.
 1524  */
 1525 #ifndef _SYS_SYSPROTO_H_
 1526 struct olstat_args {
 1527         char    *path;
 1528         struct ostat *ub;
 1529 };
 1530 #endif
 1531 /* ARGSUSED */
 1532 int
 1533 olstat(p, uap)
 1534         struct proc *p;
 1535         register struct olstat_args /* {
 1536                 syscallarg(char *) path;
 1537                 syscallarg(struct ostat *) ub;
 1538         } */ *uap;
 1539 {
 1540         struct vnode *vp;
 1541         struct stat sb;
 1542         struct ostat osb;
 1543         int error;
 1544         struct nameidata nd;
 1545 
 1546         NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
 1547             SCARG(uap, path), p);
 1548         if (error = namei(&nd))
 1549                 return (error);
 1550         vp = nd.ni_vp;
 1551         error = vn_stat(vp, &sb, p);
 1552         vput(vp);
 1553         if (error)
 1554                 return (error);
 1555         cvtstat(&sb, &osb);
 1556         error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb));
 1557         return (error);
 1558 }
 1559 
 1560 /*
 1561  * Convert from an old to a new stat structure.
 1562  */
 1563 void
 1564 cvtstat(st, ost)
 1565         struct stat *st;
 1566         struct ostat *ost;
 1567 {
 1568 
 1569         ost->st_dev = st->st_dev;
 1570         ost->st_ino = st->st_ino;
 1571         ost->st_mode = st->st_mode;
 1572         ost->st_nlink = st->st_nlink;
 1573         ost->st_uid = st->st_uid;
 1574         ost->st_gid = st->st_gid;
 1575         ost->st_rdev = st->st_rdev;
 1576         if (st->st_size < (quad_t)1 << 32)
 1577                 ost->st_size = st->st_size;
 1578         else
 1579                 ost->st_size = -2;
 1580         ost->st_atime = st->st_atime;
 1581         ost->st_mtime = st->st_mtime;
 1582         ost->st_ctime = st->st_ctime;
 1583         ost->st_blksize = st->st_blksize;
 1584         ost->st_blocks = st->st_blocks;
 1585         ost->st_flags = st->st_flags;
 1586         ost->st_gen = st->st_gen;
 1587 }
 1588 #endif /* COMPAT_43 || COMPAT_SUNOS */
 1589 
 1590 /*
 1591  * Get file status; this version follows links.
 1592  */
 1593 #ifndef _SYS_SYSPROTO_H_
 1594 struct stat_args {
 1595         char    *path;
 1596         struct stat *ub;
 1597 };
 1598 #endif
 1599 /* ARGSUSED */
 1600 int
 1601 stat(p, uap)
 1602         struct proc *p;
 1603         register struct stat_args /* {
 1604                 syscallarg(char *) path;
 1605                 syscallarg(struct stat *) ub;
 1606         } */ *uap;
 1607 {
 1608         struct stat sb;
 1609         int error;
 1610         struct nameidata nd;
 1611 
 1612         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
 1613             SCARG(uap, path), p);
 1614         if (error = namei(&nd))
 1615                 return (error);
 1616         error = vn_stat(nd.ni_vp, &sb, p);
 1617         vput(nd.ni_vp);
 1618         if (error)
 1619                 return (error);
 1620         error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb));
 1621         return (error);
 1622 }
 1623 
 1624 /*
 1625  * Get file status; this version does not follow links.
 1626  */
 1627 #ifndef _SYS_SYSPROTO_H_
 1628 struct lstat_args {
 1629         char    *path;
 1630         struct stat *ub;
 1631 };
 1632 #endif
 1633 /* ARGSUSED */
 1634 int
 1635 lstat(p, uap)
 1636         struct proc *p;
 1637         register struct lstat_args /* {
 1638                 syscallarg(char *) path;
 1639                 syscallarg(struct stat *) ub;
 1640         } */ *uap;
 1641 {
 1642         int error;
 1643         struct vnode *vp;
 1644         struct stat sb;
 1645         struct nameidata nd;
 1646 
 1647         NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
 1648             SCARG(uap, path), p);
 1649         if (error = namei(&nd))
 1650                 return (error);
 1651         vp = nd.ni_vp;
 1652         error = vn_stat(vp, &sb, p);
 1653         vput(vp);
 1654         if (error)
 1655                 return (error);
 1656         error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb));
 1657         return (error);
 1658 }
 1659 
 1660 void
 1661 cvtnstat(sb, nsb)
 1662         struct stat *sb;
 1663         struct nstat *nsb;
 1664 {
 1665         nsb->st_dev = sb->st_dev;
 1666         nsb->st_ino = sb->st_ino;
 1667         nsb->st_mode = sb->st_mode;
 1668         nsb->st_nlink = sb->st_nlink;
 1669         nsb->st_uid = sb->st_uid;
 1670         nsb->st_gid = sb->st_gid;
 1671         nsb->st_rdev = sb->st_rdev;
 1672         nsb->st_atimespec = sb->st_atimespec;
 1673         nsb->st_mtimespec = sb->st_mtimespec;
 1674         nsb->st_ctimespec = sb->st_ctimespec;
 1675         nsb->st_size = sb->st_size;
 1676         nsb->st_blocks = sb->st_blocks;
 1677         nsb->st_blksize = sb->st_blksize;
 1678         nsb->st_flags = sb->st_flags;
 1679         nsb->st_gen = sb->st_gen;
 1680         nsb->st_qspare[0] = sb->st_qspare[0];
 1681         nsb->st_qspare[1] = sb->st_qspare[1];
 1682 }
 1683 
 1684 #ifndef _SYS_SYSPROTO_H_
 1685 struct nstat_args {
 1686         char    *path;
 1687         struct nstat *ub;
 1688 };
 1689 #endif
 1690 /* ARGSUSED */
 1691 int
 1692 nstat(p, uap)
 1693         struct proc *p;
 1694         register struct nstat_args /* {
 1695                 syscallarg(char *) path;
 1696                 syscallarg(struct nstat *) ub;
 1697         } */ *uap;
 1698 {
 1699         struct stat sb;
 1700         struct nstat nsb;
 1701         int error;
 1702         struct nameidata nd;
 1703 
 1704         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
 1705             SCARG(uap, path), p);
 1706         if (error = namei(&nd))
 1707                 return (error);
 1708         error = vn_stat(nd.ni_vp, &sb, p);
 1709         vput(nd.ni_vp);
 1710         if (error)
 1711                 return (error);
 1712         cvtnstat(&sb, &nsb);
 1713         error = copyout((caddr_t)&nsb, (caddr_t)SCARG(uap, ub), sizeof (nsb));
 1714         return (error);
 1715 }
 1716 
 1717 /*
 1718  * Get file status; this version does not follow links.
 1719  */
 1720 #ifndef _SYS_SYSPROTO_H_
 1721 struct lstat_args {
 1722         char    *path;
 1723         struct stat *ub;
 1724 };
 1725 #endif
 1726 /* ARGSUSED */
 1727 int
 1728 nlstat(p, uap)
 1729         struct proc *p;
 1730         register struct nlstat_args /* {
 1731                 syscallarg(char *) path;
 1732                 syscallarg(struct nstat *) ub;
 1733         } */ *uap;
 1734 {
 1735         int error;
 1736         struct vnode *vp;
 1737         struct stat sb;
 1738         struct nstat nsb;
 1739         struct nameidata nd;
 1740 
 1741         NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
 1742             SCARG(uap, path), p);
 1743         if (error = namei(&nd))
 1744                 return (error);
 1745         vp = nd.ni_vp;
 1746         error = vn_stat(vp, &sb, p);
 1747         vput(vp);
 1748         if (error)
 1749                 return (error);
 1750         cvtnstat(&sb, &nsb);
 1751         error = copyout((caddr_t)&nsb, (caddr_t)SCARG(uap, ub), sizeof (nsb));
 1752         return (error);
 1753 }
 1754 
 1755 /*
 1756  * Get configurable pathname variables.
 1757  */
 1758 #ifndef _SYS_SYSPROTO_H_
 1759 struct pathconf_args {
 1760         char    *path;
 1761         int     name;
 1762 };
 1763 #endif
 1764 /* ARGSUSED */
 1765 int
 1766 pathconf(p, uap)
 1767         struct proc *p;
 1768         register struct pathconf_args /* {
 1769                 syscallarg(char *) path;
 1770                 syscallarg(int) name;
 1771         } */ *uap;
 1772 {
 1773         int error;
 1774         struct nameidata nd;
 1775 
 1776         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
 1777             SCARG(uap, path), p);
 1778         if (error = namei(&nd))
 1779                 return (error);
 1780         error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), p->p_retval);
 1781         vput(nd.ni_vp);
 1782         return (error);
 1783 }
 1784 
 1785 /*
 1786  * Return target name of a symbolic link.
 1787  */
 1788 #ifndef _SYS_SYSPROTO_H_
 1789 struct readlink_args {
 1790         char    *path;
 1791         char    *buf;
 1792         int     count;
 1793 };
 1794 #endif
 1795 /* ARGSUSED */
 1796 int
 1797 readlink(p, uap)
 1798         struct proc *p;
 1799         register struct readlink_args /* {
 1800                 syscallarg(char *) path;
 1801                 syscallarg(char *) buf;
 1802                 syscallarg(int) count;
 1803         } */ *uap;
 1804 {
 1805         register struct vnode *vp;
 1806         struct iovec aiov;
 1807         struct uio auio;
 1808         int error;
 1809         struct nameidata nd;
 1810 
 1811         NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
 1812             SCARG(uap, path), p);
 1813         if (error = namei(&nd))
 1814                 return (error);
 1815         vp = nd.ni_vp;
 1816         if (vp->v_type != VLNK)
 1817                 error = EINVAL;
 1818         else {
 1819                 aiov.iov_base = SCARG(uap, buf);
 1820                 aiov.iov_len = SCARG(uap, count);
 1821                 auio.uio_iov = &aiov;
 1822                 auio.uio_iovcnt = 1;
 1823                 auio.uio_offset = 0;
 1824                 auio.uio_rw = UIO_READ;
 1825                 auio.uio_segflg = UIO_USERSPACE;
 1826                 auio.uio_procp = p;
 1827                 auio.uio_resid = SCARG(uap, count);
 1828                 error = VOP_READLINK(vp, &auio, p->p_ucred);
 1829         }
 1830         vput(vp);
 1831         p->p_retval[0] = SCARG(uap, count) - auio.uio_resid;
 1832         return (error);
 1833 }
 1834 
 1835 static int
 1836 setfflags(p, vp, flags)
 1837         struct proc *p;
 1838         struct vnode *vp;
 1839         int flags;
 1840 {
 1841         int error;
 1842         struct vattr vattr;
 1843 
 1844         /*
 1845          * Prevent non-root users from setting flags on devices.  When
 1846          * a device is reused, users can retain ownership of the device
 1847          * if they are allowed to set flags and programs assume that
 1848          * chown can't fail when done as root.
 1849          */
 1850         if ((vp->v_type == VCHR || vp->v_type == VBLK) && 
 1851             ((error = suser(p->p_ucred, &p->p_acflag)) != 0))
 1852                 return (error);
 1853 
 1854         VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
 1855         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
 1856         VATTR_NULL(&vattr);
 1857         vattr.va_flags = flags;
 1858         error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
 1859         VOP_UNLOCK(vp, 0, p);
 1860         return (error);
 1861 }
 1862 
 1863 /*
 1864  * Change flags of a file given a path name.
 1865  */
 1866 #ifndef _SYS_SYSPROTO_H_
 1867 struct chflags_args {
 1868         char    *path;
 1869         int     flags;
 1870 };
 1871 #endif
 1872 /* ARGSUSED */
 1873 int
 1874 chflags(p, uap)
 1875         struct proc *p;
 1876         register struct chflags_args /* {
 1877                 syscallarg(char *) path;
 1878                 syscallarg(int) flags;
 1879         } */ *uap;
 1880 {
 1881         int error;
 1882         struct nameidata nd;
 1883 
 1884         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
 1885         if (error = namei(&nd))
 1886                 return (error);
 1887         error = setfflags(p, nd.ni_vp, SCARG(uap, flags));
 1888         vrele(nd.ni_vp);
 1889         return error;
 1890 }
 1891 
 1892 /*
 1893  * Change flags of a file given a file descriptor.
 1894  */
 1895 #ifndef _SYS_SYSPROTO_H_
 1896 struct fchflags_args {
 1897         int     fd;
 1898         int     flags;
 1899 };
 1900 #endif
 1901 /* ARGSUSED */
 1902 int
 1903 fchflags(p, uap)
 1904         struct proc *p;
 1905         register struct fchflags_args /* {
 1906                 syscallarg(int) fd;
 1907                 syscallarg(int) flags;
 1908         } */ *uap;
 1909 {
 1910         struct file *fp;
 1911         int error;
 1912 
 1913         if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
 1914                 return (error);
 1915         return setfflags(p, (struct vnode *) fp->f_data, SCARG(uap, flags));
 1916 }
 1917 
 1918 static int
 1919 setfmode(p, vp, mode)
 1920         struct proc *p;
 1921         struct vnode *vp;
 1922         int mode;
 1923 {
 1924         int error;
 1925         struct vattr vattr;
 1926 
 1927         VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
 1928         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
 1929         VATTR_NULL(&vattr);
 1930         vattr.va_mode = mode & ALLPERMS;
 1931         error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
 1932         VOP_UNLOCK(vp, 0, p);
 1933         return error;
 1934 }
 1935 
 1936 /*
 1937  * Change mode of a file given path name.
 1938  */
 1939 #ifndef _SYS_SYSPROTO_H_
 1940 struct chmod_args {
 1941         char    *path;
 1942         int     mode;
 1943 };
 1944 #endif
 1945 /* ARGSUSED */
 1946 int
 1947 chmod(p, uap)
 1948         struct proc *p;
 1949         register struct chmod_args /* {
 1950                 syscallarg(char *) path;
 1951                 syscallarg(int) mode;
 1952         } */ *uap;
 1953 {
 1954         int error;
 1955         struct nameidata nd;
 1956 
 1957         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
 1958         if (error = namei(&nd))
 1959                 return (error);
 1960         error = setfmode(p, nd.ni_vp, SCARG(uap, mode));
 1961         vrele(nd.ni_vp);
 1962         return error;
 1963 }
 1964 
 1965 /*
 1966  * Change mode of a file given path name (don't follow links.)
 1967  */
 1968 #ifndef _SYS_SYSPROTO_H_
 1969 struct lchmod_args {
 1970         char    *path;
 1971         int     mode;
 1972 };
 1973 #endif
 1974 /* ARGSUSED */
 1975 int
 1976 lchmod(p, uap)
 1977         struct proc *p;
 1978         register struct lchmod_args /* {
 1979                 syscallarg(char *) path;
 1980                 syscallarg(int) mode;
 1981         } */ *uap;
 1982 {
 1983         int error;
 1984         struct nameidata nd;
 1985 
 1986         NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
 1987         if (error = namei(&nd))
 1988                 return (error);
 1989         error = setfmode(p, nd.ni_vp, SCARG(uap, mode));
 1990         vrele(nd.ni_vp);
 1991         return error;
 1992 }
 1993 
 1994 /*
 1995  * Change mode of a file given a file descriptor.
 1996  */
 1997 #ifndef _SYS_SYSPROTO_H_
 1998 struct fchmod_args {
 1999         int     fd;
 2000         int     mode;
 2001 };
 2002 #endif
 2003 /* ARGSUSED */
 2004 int
 2005 fchmod(p, uap)
 2006         struct proc *p;
 2007         register struct fchmod_args /* {
 2008                 syscallarg(int) fd;
 2009                 syscallarg(int) mode;
 2010         } */ *uap;
 2011 {
 2012         struct file *fp;
 2013         int error;
 2014 
 2015         if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
 2016                 return (error);
 2017         return setfmode(p, (struct vnode *)fp->f_data, SCARG(uap, mode));
 2018 }
 2019 
 2020 static int
 2021 setfown(p, vp, uid, gid)
 2022         struct proc *p;
 2023         struct vnode *vp;
 2024         uid_t uid;
 2025         gid_t gid;
 2026 {
 2027         int error;
 2028         struct vattr vattr;
 2029 
 2030         VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
 2031         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
 2032         VATTR_NULL(&vattr);
 2033         vattr.va_uid = uid;
 2034         vattr.va_gid = gid;
 2035         error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
 2036         VOP_UNLOCK(vp, 0, p);
 2037         return error;
 2038 }
 2039 
 2040 /*
 2041  * Set ownership given a path name.
 2042  */
 2043 #ifndef _SYS_SYSPROTO_H_
 2044 struct chown_args {
 2045         char    *path;
 2046         int     uid;
 2047         int     gid;
 2048 };
 2049 #endif
 2050 /* ARGSUSED */
 2051 int
 2052 chown(p, uap)
 2053         struct proc *p;
 2054         register struct chown_args /* {
 2055                 syscallarg(char *) path;
 2056                 syscallarg(int) uid;
 2057                 syscallarg(int) gid;
 2058         } */ *uap;
 2059 {
 2060         int error;
 2061         struct nameidata nd;
 2062 
 2063         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
 2064         if (error = namei(&nd))
 2065                 return (error);
 2066         error = setfown(p, nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid));
 2067         vrele(nd.ni_vp);
 2068 
 2069         return (error);
 2070 }
 2071 
 2072 /*
 2073  * Set ownership given a path name, do not cross symlinks.
 2074  */
 2075 #ifndef _SYS_SYSPROTO_H_
 2076 struct lchown_args {
 2077         char    *path;
 2078         int     uid;
 2079         int     gid;
 2080 };
 2081 #endif
 2082 /* ARGSUSED */
 2083 int
 2084 lchown(p, uap)
 2085         struct proc *p;
 2086         register struct lchown_args /* {
 2087                 syscallarg(char *) path;
 2088                 syscallarg(int) uid;
 2089                 syscallarg(int) gid;
 2090         } */ *uap;
 2091 {
 2092         int error;
 2093         struct nameidata nd;
 2094 
 2095         NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
 2096         if (error = namei(&nd))
 2097                 return (error);
 2098         error = setfown(p, nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid));
 2099         vrele(nd.ni_vp);
 2100         return (error);
 2101 }
 2102 
 2103 /*
 2104  * Set ownership given a file descriptor.
 2105  */
 2106 #ifndef _SYS_SYSPROTO_H_
 2107 struct fchown_args {
 2108         int     fd;
 2109         int     uid;
 2110         int     gid;
 2111 };
 2112 #endif
 2113 /* ARGSUSED */
 2114 int
 2115 fchown(p, uap)
 2116         struct proc *p;
 2117         register struct fchown_args /* {
 2118                 syscallarg(int) fd;
 2119                 syscallarg(int) uid;
 2120                 syscallarg(int) gid;
 2121         } */ *uap;
 2122 {
 2123         struct file *fp;
 2124         int error;
 2125 
 2126         if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
 2127                 return (error);
 2128         return setfown(p, (struct vnode *)fp->f_data,
 2129                 SCARG(uap, uid), SCARG(uap, gid));
 2130 }
 2131 
 2132 static int
 2133 setutimes(p, vp, tv, nullflag)
 2134         struct proc *p;
 2135         struct vnode *vp;
 2136         struct timeval *tv;
 2137         int nullflag;
 2138 {
 2139         int error;
 2140         struct vattr vattr;
 2141 
 2142         VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
 2143         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
 2144         VATTR_NULL(&vattr);
 2145         vattr.va_atime.tv_sec = tv[0].tv_sec;
 2146         vattr.va_atime.tv_nsec = tv[0].tv_usec * 1000;
 2147         vattr.va_mtime.tv_sec = tv[1].tv_sec;
 2148         vattr.va_mtime.tv_nsec = tv[1].tv_usec * 1000;
 2149         if (nullflag)
 2150                 vattr.va_vaflags |= VA_UTIMES_NULL;
 2151         error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
 2152         VOP_UNLOCK(vp, 0, p);
 2153         return error;
 2154 }
 2155 
 2156 /*
 2157  * Set the access and modification times of a file.
 2158  */
 2159 #ifndef _SYS_SYSPROTO_H_
 2160 struct utimes_args {
 2161         char    *path;
 2162         struct  timeval *tptr;
 2163 };
 2164 #endif
 2165 /* ARGSUSED */
 2166 int
 2167 utimes(p, uap)
 2168         struct proc *p;
 2169         register struct utimes_args /* {
 2170                 syscallarg(char *) path;
 2171                 syscallarg(struct timeval *) tptr;
 2172         } */ *uap;
 2173 {
 2174         struct timeval tv[2];
 2175         int error;
 2176         struct nameidata nd;
 2177         int nullflag;
 2178 
 2179         nullflag = 0;
 2180         if (SCARG(uap, tptr) == NULL) {
 2181                 microtime(&tv[0]);
 2182                 tv[1] = tv[0];
 2183                 nullflag = 1;
 2184         } else if (error = copyin((caddr_t)SCARG(uap, tptr), (caddr_t)tv,
 2185             sizeof (tv)))
 2186                 return (error);
 2187         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
 2188         if (error = namei(&nd))
 2189                 return (error);
 2190         error = setutimes(p, nd.ni_vp, tv, nullflag);
 2191         vrele(nd.ni_vp);
 2192         return (error);
 2193 }
 2194 
 2195 /*
 2196  * Set the access and modification times of a file.
 2197  */
 2198 #ifndef _SYS_SYSPROTO_H_
 2199 struct lutimes_args {
 2200         char    *path;
 2201         struct  timeval *tptr;
 2202 };
 2203 #endif
 2204 /* ARGSUSED */
 2205 int
 2206 lutimes(p, uap)
 2207         struct proc *p;
 2208         register struct lutimes_args /* {
 2209                 syscallarg(char *) path;
 2210                 syscallarg(struct timeval *) tptr;
 2211         } */ *uap;
 2212 {
 2213         struct timeval tv[2];
 2214         int error;
 2215         struct nameidata nd;
 2216         int nullflag;
 2217 
 2218         nullflag = 0;
 2219         if (SCARG(uap, tptr) == NULL) {
 2220                 microtime(&tv[0]);
 2221                 tv[1] = tv[0];
 2222                 nullflag = 1;
 2223         } else if (error = copyin((caddr_t)SCARG(uap, tptr), (caddr_t)tv,
 2224             sizeof (tv)))
 2225                 return (error);
 2226         NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
 2227         if (error = namei(&nd))
 2228                 return (error);
 2229 
 2230         error = setutimes(p, nd.ni_vp, tv, nullflag);
 2231         vrele(nd.ni_vp);
 2232         return (error);
 2233 }
 2234 
 2235 /*
 2236  * Set the access and modification times of a file.
 2237  */
 2238 #ifndef _SYS_SYSPROTO_H_
 2239 struct futimes_args {
 2240         int     fd;
 2241         struct  timeval *tptr;
 2242 };
 2243 #endif
 2244 /* ARGSUSED */
 2245 int
 2246 futimes(p, uap)
 2247         struct proc *p;
 2248         register struct futimes_args /* {
 2249                 syscallarg(int ) fd;
 2250                 syscallarg(struct timeval *) tptr;
 2251         } */ *uap;
 2252 {
 2253         struct timeval tv[2];
 2254         struct file *fp;
 2255         int error;
 2256         int nullflag;
 2257 
 2258         nullflag = 0;
 2259         if (SCARG(uap, tptr) == NULL) {
 2260                 microtime(&tv[0]);
 2261                 tv[1] = tv[0];
 2262                 nullflag = 1;
 2263         } else if (error = copyin((caddr_t)SCARG(uap, tptr), (caddr_t)tv,
 2264             sizeof (tv)))
 2265                 return (error);
 2266 
 2267         if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
 2268                 return (error);
 2269         return setutimes(p, (struct vnode *)fp->f_data, tv, nullflag);
 2270 }
 2271 
 2272 /*
 2273  * Truncate a file given its path name.
 2274  */
 2275 #ifndef _SYS_SYSPROTO_H_
 2276 struct truncate_args {
 2277         char    *path;
 2278         int     pad;
 2279         off_t   length;
 2280 };
 2281 #endif
 2282 /* ARGSUSED */
 2283 int
 2284 truncate(p, uap)
 2285         struct proc *p;
 2286         register struct truncate_args /* {
 2287                 syscallarg(char *) path;
 2288                 syscallarg(int) pad;
 2289                 syscallarg(off_t) length;
 2290         } */ *uap;
 2291 {
 2292         register struct vnode *vp;
 2293         struct vattr vattr;
 2294         int error;
 2295         struct nameidata nd;
 2296 
 2297         if (uap->length < 0)
 2298                 return(EINVAL);
 2299         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
 2300         if (error = namei(&nd))
 2301                 return (error);
 2302         vp = nd.ni_vp;
 2303         VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
 2304         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
 2305         if (vp->v_type == VDIR)
 2306                 error = EISDIR;
 2307         else if ((error = vn_writechk(vp)) == 0 &&
 2308             (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) {
 2309                 VATTR_NULL(&vattr);
 2310                 vattr.va_size = SCARG(uap, length);
 2311                 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
 2312         }
 2313         vput(vp);
 2314         return (error);
 2315 }
 2316 
 2317 /*
 2318  * Truncate a file given a file descriptor.
 2319  */
 2320 #ifndef _SYS_SYSPROTO_H_
 2321 struct ftruncate_args {
 2322         int     fd;
 2323         int     pad;
 2324         off_t   length;
 2325 };
 2326 #endif
 2327 /* ARGSUSED */
 2328 int
 2329 ftruncate(p, uap)
 2330         struct proc *p;
 2331         register struct ftruncate_args /* {
 2332                 syscallarg(int) fd;
 2333                 syscallarg(int) pad;
 2334                 syscallarg(off_t) length;
 2335         } */ *uap;
 2336 {
 2337         struct vattr vattr;
 2338         struct vnode *vp;
 2339         struct file *fp;
 2340         int error;
 2341 
 2342         if (uap->length < 0)
 2343                 return(EINVAL);
 2344         if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
 2345                 return (error);
 2346         if ((fp->f_flag & FWRITE) == 0)
 2347                 return (EINVAL);
 2348         vp = (struct vnode *)fp->f_data;
 2349         VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
 2350         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
 2351         if (vp->v_type == VDIR)
 2352                 error = EISDIR;
 2353         else if ((error = vn_writechk(vp)) == 0) {
 2354                 VATTR_NULL(&vattr);
 2355                 vattr.va_size = SCARG(uap, length);
 2356                 error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
 2357         }
 2358         VOP_UNLOCK(vp, 0, p);
 2359         return (error);
 2360 }
 2361 
 2362 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
 2363 /*
 2364  * Truncate a file given its path name.
 2365  */
 2366 #ifndef _SYS_SYSPROTO_H_
 2367 struct otruncate_args {
 2368         char    *path;
 2369         long    length;
 2370 };
 2371 #endif
 2372 /* ARGSUSED */
 2373 int
 2374 otruncate(p, uap)
 2375         struct proc *p;
 2376         register struct otruncate_args /* {
 2377                 syscallarg(char *) path;
 2378                 syscallarg(long) length;
 2379         } */ *uap;
 2380 {
 2381         struct truncate_args /* {
 2382                 syscallarg(char *) path;
 2383                 syscallarg(int) pad;
 2384                 syscallarg(off_t) length;
 2385         } */ nuap;
 2386 
 2387         SCARG(&nuap, path) = SCARG(uap, path);
 2388         SCARG(&nuap, length) = SCARG(uap, length);
 2389         return (truncate(p, &nuap));
 2390 }
 2391 
 2392 /*
 2393  * Truncate a file given a file descriptor.
 2394  */
 2395 #ifndef _SYS_SYSPROTO_H_
 2396 struct oftruncate_args {
 2397         int     fd;
 2398         long    length;
 2399 };
 2400 #endif
 2401 /* ARGSUSED */
 2402 int
 2403 oftruncate(p, uap)
 2404         struct proc *p;
 2405         register struct oftruncate_args /* {
 2406                 syscallarg(int) fd;
 2407                 syscallarg(long) length;
 2408         } */ *uap;
 2409 {
 2410         struct ftruncate_args /* {
 2411                 syscallarg(int) fd;
 2412                 syscallarg(int) pad;
 2413                 syscallarg(off_t) length;
 2414         } */ nuap;
 2415 
 2416         SCARG(&nuap, fd) = SCARG(uap, fd);
 2417         SCARG(&nuap, length) = SCARG(uap, length);
 2418         return (ftruncate(p, &nuap));
 2419 }
 2420 #endif /* COMPAT_43 || COMPAT_SUNOS */
 2421 
 2422 /*
 2423  * Sync an open file.
 2424  */
 2425 #ifndef _SYS_SYSPROTO_H_
 2426 struct fsync_args {
 2427         int     fd;
 2428 };
 2429 #endif
 2430 /* ARGSUSED */
 2431 int
 2432 fsync(p, uap)
 2433         struct proc *p;
 2434         struct fsync_args /* {
 2435                 syscallarg(int) fd;
 2436         } */ *uap;
 2437 {
 2438         register struct vnode *vp;
 2439         struct file *fp;
 2440         int error;
 2441 
 2442         if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
 2443                 return (error);
 2444         vp = (struct vnode *)fp->f_data;
 2445         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
 2446         if (vp->v_object)
 2447                 vm_object_page_clean(vp->v_object, 0, 0, 0);
 2448         if ((error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p)) == 0 &&
 2449             vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP) &&
 2450             bioops.io_fsync)
 2451                 error = (*bioops.io_fsync)(vp);
 2452         VOP_UNLOCK(vp, 0, p);
 2453         return (error);
 2454 }
 2455 
 2456 /*
 2457  * Rename files.  Source and destination must either both be directories,
 2458  * or both not be directories.  If target is a directory, it must be empty.
 2459  */
 2460 #ifndef _SYS_SYSPROTO_H_
 2461 struct rename_args {
 2462         char    *from;
 2463         char    *to;
 2464 };
 2465 #endif
 2466 /* ARGSUSED */
 2467 int
 2468 rename(p, uap)
 2469         struct proc *p;
 2470         register struct rename_args /* {
 2471                 syscallarg(char *) from;
 2472                 syscallarg(char *) to;
 2473         } */ *uap;
 2474 {
 2475         register struct vnode *tvp, *fvp, *tdvp;
 2476         struct nameidata fromnd, tond;
 2477         int error;
 2478 
 2479         NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
 2480             SCARG(uap, from), p);
 2481         if (error = namei(&fromnd))
 2482                 return (error);
 2483         fvp = fromnd.ni_vp;
 2484         NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART | NOOBJ,
 2485             UIO_USERSPACE, SCARG(uap, to), p);
 2486         if (fromnd.ni_vp->v_type == VDIR)
 2487                 tond.ni_cnd.cn_flags |= WILLBEDIR;
 2488         if (error = namei(&tond)) {
 2489                 /* Translate error code for rename("dir1", "dir2/."). */
 2490                 if (error == EISDIR && fvp->v_type == VDIR)
 2491                         error = EINVAL;
 2492                 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
 2493                 vrele(fromnd.ni_dvp);
 2494                 vrele(fvp);
 2495                 goto out1;
 2496         }
 2497         tdvp = tond.ni_dvp;
 2498         tvp = tond.ni_vp;
 2499         if (tvp != NULL) {
 2500                 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
 2501                         error = ENOTDIR;
 2502                         goto out;
 2503                 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
 2504                         error = EISDIR;
 2505                         goto out;
 2506                 }
 2507         }
 2508         if (fvp == tdvp)
 2509                 error = EINVAL;
 2510         /*
 2511          * If source is the same as the destination (that is the
 2512          * same inode number with the same name in the same directory),
 2513          * then there is nothing to do.
 2514          */
 2515         if (fvp == tvp && fromnd.ni_dvp == tdvp &&
 2516             fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
 2517             !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
 2518               fromnd.ni_cnd.cn_namelen))
 2519                 error = -1;
 2520 out:
 2521         if (!error) {
 2522                 VOP_LEASE(tdvp, p, p->p_ucred, LEASE_WRITE);
 2523                 if (fromnd.ni_dvp != tdvp) {
 2524                         VOP_LEASE(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
 2525                 }
 2526                 if (tvp) {
 2527                         VOP_LEASE(tvp, p, p->p_ucred, LEASE_WRITE);
 2528                 }
 2529                 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
 2530                                    tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
 2531         } else {
 2532                 VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
 2533                 if (tdvp == tvp)
 2534                         vrele(tdvp);
 2535                 else
 2536                         vput(tdvp);
 2537                 if (tvp)
 2538                         vput(tvp);
 2539                 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
 2540                 vrele(fromnd.ni_dvp);
 2541                 vrele(fvp);
 2542         }
 2543         vrele(tond.ni_startdir);
 2544         ASSERT_VOP_UNLOCKED(fromnd.ni_dvp, "rename");
 2545         ASSERT_VOP_UNLOCKED(fromnd.ni_vp, "rename");
 2546         ASSERT_VOP_UNLOCKED(tond.ni_dvp, "rename");
 2547         ASSERT_VOP_UNLOCKED(tond.ni_vp, "rename");
 2548         zfree(namei_zone, tond.ni_cnd.cn_pnbuf);
 2549 out1:
 2550         if (fromnd.ni_startdir)
 2551                 vrele(fromnd.ni_startdir);
 2552         zfree(namei_zone, fromnd.ni_cnd.cn_pnbuf);
 2553         if (error == -1)
 2554                 return (0);
 2555         return (error);
 2556 }
 2557 
 2558 /*
 2559  * Make a directory file.
 2560  */
 2561 #ifndef _SYS_SYSPROTO_H_
 2562 struct mkdir_args {
 2563         char    *path;
 2564         int     mode;
 2565 };
 2566 #endif
 2567 /* ARGSUSED */
 2568 int
 2569 mkdir(p, uap)
 2570         struct proc *p;
 2571         register struct mkdir_args /* {
 2572                 syscallarg(char *) path;
 2573                 syscallarg(int) mode;
 2574         } */ *uap;
 2575 {
 2576         register struct vnode *vp;
 2577         struct vattr vattr;
 2578         int error;
 2579         struct nameidata nd;
 2580 
 2581         NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
 2582         nd.ni_cnd.cn_flags |= WILLBEDIR;
 2583         if (error = namei(&nd))
 2584                 return (error);
 2585         vp = nd.ni_vp;
 2586         if (vp != NULL) {
 2587                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
 2588                 if (nd.ni_dvp == vp)
 2589                         vrele(nd.ni_dvp);
 2590                 else
 2591                         vput(nd.ni_dvp);
 2592                 vrele(vp);
 2593                 return (EEXIST);
 2594         }
 2595         VATTR_NULL(&vattr);
 2596         vattr.va_type = VDIR;
 2597         vattr.va_mode = (SCARG(uap, mode) & ACCESSPERMS) &~ p->p_fd->fd_cmask;
 2598         VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
 2599         error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
 2600         vput(nd.ni_dvp);
 2601         if (!error)
 2602                 vput(nd.ni_vp);
 2603         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mkdir");
 2604         ASSERT_VOP_UNLOCKED(nd.ni_vp, "mkdir");
 2605         return (error);
 2606 }
 2607 
 2608 /*
 2609  * Remove a directory file.
 2610  */
 2611 #ifndef _SYS_SYSPROTO_H_
 2612 struct rmdir_args {
 2613         char    *path;
 2614 };
 2615 #endif
 2616 /* ARGSUSED */
 2617 int
 2618 rmdir(p, uap)
 2619         struct proc *p;
 2620         struct rmdir_args /* {
 2621                 syscallarg(char *) path;
 2622         } */ *uap;
 2623 {
 2624         register struct vnode *vp;
 2625         int error;
 2626         struct nameidata nd;
 2627 
 2628         NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
 2629             SCARG(uap, path), p);
 2630         if (error = namei(&nd))
 2631                 return (error);
 2632         vp = nd.ni_vp;
 2633         if (vp->v_type != VDIR) {
 2634                 error = ENOTDIR;
 2635                 goto out;
 2636         }
 2637         /*
 2638          * No rmdir "." please.
 2639          */
 2640         if (nd.ni_dvp == vp) {
 2641                 error = EINVAL;
 2642                 goto out;
 2643         }
 2644         /*
 2645          * The root of a mounted filesystem cannot be deleted.
 2646          */
 2647         if (vp->v_flag & VROOT)
 2648                 error = EBUSY;
 2649 out:
 2650         if (!error) {
 2651                 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
 2652                 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
 2653                 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
 2654         } else {
 2655                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
 2656         }
 2657         if (nd.ni_dvp == vp)
 2658                 vrele(nd.ni_dvp);
 2659         else
 2660                 vput(nd.ni_dvp);
 2661         if (vp != NULLVP)
 2662                 vput(vp);
 2663         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "rmdir");
 2664         ASSERT_VOP_UNLOCKED(nd.ni_vp, "rmdir");
 2665         return (error);
 2666 }
 2667 
 2668 #ifdef COMPAT_43
 2669 /*
 2670  * Read a block of directory entries in a file system independent format.
 2671  */
 2672 #ifndef _SYS_SYSPROTO_H_
 2673 struct ogetdirentries_args {
 2674         int     fd;
 2675         char    *buf;
 2676         u_int   count;
 2677         long    *basep;
 2678 };
 2679 #endif
 2680 int
 2681 ogetdirentries(p, uap)
 2682         struct proc *p;
 2683         register struct ogetdirentries_args /* {
 2684                 syscallarg(int) fd;
 2685                 syscallarg(char *) buf;
 2686                 syscallarg(u_int) count;
 2687                 syscallarg(long *) basep;
 2688         } */ *uap;
 2689 {
 2690         struct vnode *vp;
 2691         struct file *fp;
 2692         struct uio auio, kuio;
 2693         struct iovec aiov, kiov;
 2694         struct dirent *dp, *edp;
 2695         caddr_t dirbuf;
 2696         int error, eofflag, readcnt;
 2697         long loff;
 2698 
 2699         if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
 2700                 return (error);
 2701         if ((fp->f_flag & FREAD) == 0)
 2702                 return (EBADF);
 2703         vp = (struct vnode *)fp->f_data;
 2704 unionread:
 2705         if (vp->v_type != VDIR)
 2706                 return (EINVAL);
 2707         aiov.iov_base = SCARG(uap, buf);
 2708         aiov.iov_len = SCARG(uap, count);
 2709         auio.uio_iov = &aiov;
 2710         auio.uio_iovcnt = 1;
 2711         auio.uio_rw = UIO_READ;
 2712         auio.uio_segflg = UIO_USERSPACE;
 2713         auio.uio_procp = p;
 2714         auio.uio_resid = SCARG(uap, count);
 2715         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
 2716         loff = auio.uio_offset = fp->f_offset;
 2717 #       if (BYTE_ORDER != LITTLE_ENDIAN)
 2718                 if (vp->v_mount->mnt_maxsymlinklen <= 0) {
 2719                         error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
 2720                             NULL, NULL);
 2721                         fp->f_offset = auio.uio_offset;
 2722                 } else
 2723 #       endif
 2724         {
 2725                 kuio = auio;
 2726                 kuio.uio_iov = &kiov;
 2727                 kuio.uio_segflg = UIO_SYSSPACE;
 2728                 kiov.iov_len = SCARG(uap, count);
 2729                 MALLOC(dirbuf, caddr_t, SCARG(uap, count), M_TEMP, M_WAITOK);
 2730                 kiov.iov_base = dirbuf;
 2731                 error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag,
 2732                             NULL, NULL);
 2733                 fp->f_offset = kuio.uio_offset;
 2734                 if (error == 0) {
 2735                         readcnt = SCARG(uap, count) - kuio.uio_resid;
 2736                         edp = (struct dirent *)&dirbuf[readcnt];
 2737                         for (dp = (struct dirent *)dirbuf; dp < edp; ) {
 2738 #                               if (BYTE_ORDER == LITTLE_ENDIAN)
 2739                                         /*
 2740                                          * The expected low byte of
 2741                                          * dp->d_namlen is our dp->d_type.
 2742                                          * The high MBZ byte of dp->d_namlen
 2743                                          * is our dp->d_namlen.
 2744                                          */
 2745                                         dp->d_type = dp->d_namlen;
 2746                                         dp->d_namlen = 0;
 2747 #                               else
 2748                                         /*
 2749                                          * The dp->d_type is the high byte
 2750                                          * of the expected dp->d_namlen,
 2751                                          * so must be zero'ed.
 2752                                          */
 2753                                         dp->d_type = 0;
 2754 #                               endif
 2755                                 if (dp->d_reclen > 0) {
 2756                                         dp = (struct dirent *)
 2757                                             ((char *)dp + dp->d_reclen);
 2758                                 } else {
 2759                                         error = EIO;
 2760                                         break;
 2761                                 }
 2762                         }
 2763                         if (dp >= edp)
 2764                                 error = uiomove(dirbuf, readcnt, &auio);
 2765                 }
 2766                 FREE(dirbuf, M_TEMP);
 2767         }
 2768         VOP_UNLOCK(vp, 0, p);
 2769         if (error)
 2770                 return (error);
 2771         if (union_dircheckp && SCARG(uap, count) == auio.uio_resid) {
 2772                 error = union_dircheckp(p, &vp, fp);
 2773                 if (error == -1)
 2774                         goto unionread;
 2775                 if (error)
 2776                         return (error);
 2777         }
 2778         if ((SCARG(uap, count) == auio.uio_resid) &&
 2779             (vp->v_flag & VROOT) &&
 2780             (vp->v_mount->mnt_flag & MNT_UNION)) {
 2781                 struct vnode *tvp = vp;
 2782                 vp = vp->v_mount->mnt_vnodecovered;
 2783                 VREF(vp);
 2784                 fp->f_data = (caddr_t) vp;
 2785                 fp->f_offset = 0;
 2786                 vrele(tvp);
 2787                 goto unionread;
 2788         }
 2789         error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep),
 2790             sizeof(long));
 2791         p->p_retval[0] = SCARG(uap, count) - auio.uio_resid;
 2792         return (error);
 2793 }
 2794 #endif /* COMPAT_43 */
 2795 
 2796 /*
 2797  * Read a block of directory entries in a file system independent format.
 2798  */
 2799 #ifndef _SYS_SYSPROTO_H_
 2800 struct getdirentries_args {
 2801         int     fd;
 2802         char    *buf;
 2803         u_int   count;
 2804         long    *basep;
 2805 };
 2806 #endif
 2807 int
 2808 getdirentries(p, uap)
 2809         struct proc *p;
 2810         register struct getdirentries_args /* {
 2811                 syscallarg(int) fd;
 2812                 syscallarg(char *) buf;
 2813                 syscallarg(u_int) count;
 2814                 syscallarg(long *) basep;
 2815         } */ *uap;
 2816 {
 2817         struct vnode *vp;
 2818         struct file *fp;
 2819         struct uio auio;
 2820         struct iovec aiov;
 2821         long loff;
 2822         int error, eofflag;
 2823 
 2824         if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
 2825                 return (error);
 2826         if ((fp->f_flag & FREAD) == 0)
 2827                 return (EBADF);
 2828         vp = (struct vnode *)fp->f_data;
 2829 unionread:
 2830         if (vp->v_type != VDIR)
 2831                 return (EINVAL);
 2832         aiov.iov_base = SCARG(uap, buf);
 2833         aiov.iov_len = SCARG(uap, count);
 2834         auio.uio_iov = &aiov;
 2835         auio.uio_iovcnt = 1;
 2836         auio.uio_rw = UIO_READ;
 2837         auio.uio_segflg = UIO_USERSPACE;
 2838         auio.uio_procp = p;
 2839         auio.uio_resid = SCARG(uap, count);
 2840         /* vn_lock(vp, LK_SHARED | LK_RETRY, p); */
 2841         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
 2842         loff = auio.uio_offset = fp->f_offset;
 2843         error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL, NULL);
 2844         fp->f_offset = auio.uio_offset;
 2845         VOP_UNLOCK(vp, 0, p);
 2846         if (error)
 2847                 return (error);
 2848         if (union_dircheckp && SCARG(uap, count) == auio.uio_resid) {
 2849                 error = union_dircheckp(p, &vp, fp);
 2850                 if (error == -1)
 2851                         goto unionread;
 2852                 if (error)
 2853                         return (error);
 2854         }
 2855         if ((SCARG(uap, count) == auio.uio_resid) &&
 2856             (vp->v_flag & VROOT) &&
 2857             (vp->v_mount->mnt_flag & MNT_UNION)) {
 2858                 struct vnode *tvp = vp;
 2859                 vp = vp->v_mount->mnt_vnodecovered;
 2860                 VREF(vp);
 2861                 fp->f_data = (caddr_t) vp;
 2862                 fp->f_offset = 0;
 2863                 vrele(tvp);
 2864                 goto unionread;
 2865         }
 2866         if (SCARG(uap, basep) != NULL) {
 2867                 error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep),
 2868                     sizeof(long));
 2869         }
 2870         p->p_retval[0] = SCARG(uap, count) - auio.uio_resid;
 2871         return (error);
 2872 }
 2873 #ifndef _SYS_SYSPROTO_H_
 2874 struct getdents_args {
 2875         int fd;
 2876         char *buf;
 2877         size_t count;
 2878 };
 2879 #endif
 2880 int
 2881 getdents(p, uap)
 2882         struct proc *p;
 2883         register struct getdents_args /* {
 2884                 syscallarg(int) fd;
 2885                 syscallarg(char *) buf;
 2886                 syscallarg(u_int) count;
 2887         } */ *uap;
 2888 {
 2889         struct getdirentries_args ap;
 2890         ap.fd = uap->fd;
 2891         ap.buf = uap->buf;
 2892         ap.count = uap->count;
 2893         ap.basep = NULL;
 2894         return getdirentries(p, &ap);
 2895 }
 2896 
 2897 /*
 2898  * Set the mode mask for creation of filesystem nodes.
 2899  */
 2900 #ifndef _SYS_SYSPROTO_H_
 2901 struct umask_args {
 2902         int     newmask;
 2903 };
 2904 #endif
 2905 int
 2906 umask(p, uap)
 2907         struct proc *p;
 2908         struct umask_args /* {
 2909                 syscallarg(int) newmask;
 2910         } */ *uap;
 2911 {
 2912         register struct filedesc *fdp;
 2913 
 2914         fdp = p->p_fd;
 2915         p->p_retval[0] = fdp->fd_cmask;
 2916         fdp->fd_cmask = SCARG(uap, newmask) & ALLPERMS;
 2917         return (0);
 2918 }
 2919 
 2920 /*
 2921  * Void all references to file by ripping underlying filesystem
 2922  * away from vnode.
 2923  */
 2924 #ifndef _SYS_SYSPROTO_H_
 2925 struct revoke_args {
 2926         char    *path;
 2927 };
 2928 #endif
 2929 /* ARGSUSED */
 2930 int
 2931 revoke(p, uap)
 2932         struct proc *p;
 2933         register struct revoke_args /* {
 2934                 syscallarg(char *) path;
 2935         } */ *uap;
 2936 {
 2937         register struct vnode *vp;
 2938         struct vattr vattr;
 2939         int error;
 2940         struct nameidata nd;
 2941 
 2942         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
 2943         if (error = namei(&nd))
 2944                 return (error);
 2945         vp = nd.ni_vp;
 2946         if (vp->v_type != VCHR && vp->v_type != VBLK) {
 2947                 error = EINVAL;
 2948                 goto out;
 2949         }
 2950         if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p))
 2951                 goto out;
 2952         if (p->p_ucred->cr_uid != vattr.va_uid &&
 2953             (error = suser(p->p_ucred, &p->p_acflag)))
 2954                 goto out;
 2955         if (vp->v_usecount > 1 || (vp->v_flag & VALIASED))
 2956                 VOP_REVOKE(vp, REVOKEALL);
 2957 out:
 2958         vrele(vp);
 2959         return (error);
 2960 }
 2961 
 2962 /*
 2963  * Convert a user file descriptor to a kernel file entry.
 2964  */
 2965 int
 2966 getvnode(fdp, fd, fpp)
 2967         struct filedesc *fdp;
 2968         int fd;
 2969         struct file **fpp;
 2970 {
 2971         struct file *fp;
 2972 
 2973         if ((u_int)fd >= fdp->fd_nfiles ||
 2974             (fp = fdp->fd_ofiles[fd]) == NULL)
 2975                 return (EBADF);
 2976         if (fp->f_type != DTYPE_VNODE && fp->f_type != DTYPE_FIFO)
 2977                 return (EINVAL);
 2978         *fpp = fp;
 2979         return (0);
 2980 }
 2981 #ifndef _SYS_SYSPROTO_H_
 2982 struct  __getcwd_args {
 2983         u_char  *buf;
 2984         u_int   buflen;
 2985 };
 2986 #endif
 2987 #define STATNODE(mode, name, var) \
 2988         SYSCTL_INT(_vfs_cache, OID_AUTO, name, mode, var, 0, "");
 2989 
 2990 static int disablecwd;
 2991 SYSCTL_INT(_debug, OID_AUTO, disablecwd, CTLFLAG_RW, &disablecwd, 0, "");
 2992 
 2993 static u_long numcwdcalls; STATNODE(CTLFLAG_RD, numcwdcalls, &numcwdcalls);
 2994 static u_long numcwdfail1; STATNODE(CTLFLAG_RD, numcwdfail1, &numcwdfail1);
 2995 static u_long numcwdfail2; STATNODE(CTLFLAG_RD, numcwdfail2, &numcwdfail2);
 2996 static u_long numcwdfail3; STATNODE(CTLFLAG_RD, numcwdfail3, &numcwdfail3);
 2997 static u_long numcwdfail4; STATNODE(CTLFLAG_RD, numcwdfail4, &numcwdfail4);
 2998 static u_long numcwdfound; STATNODE(CTLFLAG_RD, numcwdfound, &numcwdfound);
 2999 int
 3000 __getcwd(p, uap)
 3001         struct proc *p;
 3002         struct __getcwd_args *uap;
 3003 {
 3004         char *bp, *buf;
 3005         int error, i, slash_prefixed;
 3006         struct filedesc *fdp;
 3007         struct namecache *ncp;
 3008         struct vnode *vp;
 3009 
 3010         numcwdcalls++;
 3011         if (disablecwd)
 3012                 return (ENODEV);
 3013         if (uap->buflen < 2)
 3014                 return (EINVAL);
 3015         if (uap->buflen > MAXPATHLEN)
 3016                 uap->buflen = MAXPATHLEN;
 3017         buf = bp = malloc(uap->buflen, M_TEMP, M_WAITOK);
 3018         bp += uap->buflen - 1;
 3019         *bp = '\0';
 3020         fdp = p->p_fd;
 3021         slash_prefixed = 0;
 3022         for (vp = fdp->fd_cdir; vp != fdp->fd_rdir && vp != rootvnode;) {
 3023                 if (vp->v_flag & VROOT) {
 3024                         vp = vp->v_mount->mnt_vnodecovered;
 3025                         continue;
 3026                 }
 3027                 if (vp->v_dd->v_id != vp->v_ddid) {
 3028                         numcwdfail1++;
 3029                         free(buf, M_TEMP);
 3030                         return (ENOTDIR);
 3031                 }
 3032                 ncp = TAILQ_FIRST(&vp->v_cache_dst);
 3033                 if (!ncp) {
 3034                         numcwdfail2++;
 3035                         free(buf, M_TEMP);
 3036                         return (ENOENT);
 3037                 }
 3038                 if (ncp->nc_dvp != vp->v_dd) {
 3039                         numcwdfail3++;
 3040                         free(buf, M_TEMP);
 3041                         return (EBADF);
 3042                 }
 3043                 for (i = ncp->nc_nlen - 1; i >= 0; i--) {
 3044                         if (bp == buf) {
 3045                                 numcwdfail4++;
 3046                                 free(buf, M_TEMP);
 3047                                 return (ENOMEM);
 3048                         }
 3049                         *--bp = ncp->nc_name[i];
 3050                 }
 3051                 if (bp == buf) {
 3052                         numcwdfail4++;
 3053                         free(buf, M_TEMP);
 3054                         return (ENOMEM);
 3055                 }
 3056                 *--bp = '/';
 3057                 slash_prefixed = 1;
 3058                 vp = vp->v_dd;
 3059         }
 3060         if (!slash_prefixed) {
 3061                 if (bp == buf) {
 3062                         numcwdfail4++;
 3063                         free(buf, M_TEMP);
 3064                         return (ENOMEM);
 3065                 }
 3066                 *--bp = '/';
 3067         }
 3068         numcwdfound++;
 3069         error = copyout(bp, uap->buf, strlen(bp) + 1);
 3070         free(buf, M_TEMP);
 3071         return (error);
 3072 }

Cache object: 1847582f43b47a25216cfbb54c823915


[ 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.