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: releng/5.1/sys/kern/vfs_syscalls.c 114216 2003-04-29 13:36:06Z kan $
   40  */
   41 
   42 /* For 4.3 integer FS ID compatibility */
   43 #include "opt_compat.h"
   44 #include "opt_mac.h"
   45 
   46 #include <sys/param.h>
   47 #include <sys/systm.h>
   48 #include <sys/bio.h>
   49 #include <sys/buf.h>
   50 #include <sys/sysent.h>
   51 #include <sys/mac.h>
   52 #include <sys/malloc.h>
   53 #include <sys/mount.h>
   54 #include <sys/mutex.h>
   55 #include <sys/sysproto.h>
   56 #include <sys/namei.h>
   57 #include <sys/filedesc.h>
   58 #include <sys/kernel.h>
   59 #include <sys/fcntl.h>
   60 #include <sys/file.h>
   61 #include <sys/limits.h>
   62 #include <sys/linker.h>
   63 #include <sys/stat.h>
   64 #include <sys/sx.h>
   65 #include <sys/unistd.h>
   66 #include <sys/vnode.h>
   67 #include <sys/proc.h>
   68 #include <sys/dirent.h>
   69 #include <sys/extattr.h>
   70 #include <sys/jail.h>
   71 #include <sys/syscallsubr.h>
   72 #include <sys/sysctl.h>
   73 
   74 #include <machine/stdarg.h>
   75 
   76 #include <vm/vm.h>
   77 #include <vm/vm_object.h>
   78 #include <vm/vm_page.h>
   79 #include <vm/uma.h>
   80 
   81 static int chroot_refuse_vdir_fds(struct filedesc *fdp);
   82 static int getutimes(const struct timeval *, enum uio_seg, struct timespec *);
   83 static int setfown(struct thread *td, struct vnode *, uid_t, gid_t);
   84 static int setfmode(struct thread *td, struct vnode *, int);
   85 static int setfflags(struct thread *td, struct vnode *, int);
   86 static int setutimes(struct thread *td, struct vnode *,
   87     const struct timespec *, int, int);
   88 static int vn_access(struct vnode *vp, int user_flags, struct ucred *cred,
   89     struct thread *td);
   90 
   91 int (*union_dircheckp)(struct thread *td, struct vnode **, struct file *);
   92 int (*softdep_fsync_hook)(struct vnode *);
   93 
   94 /*
   95  * The module initialization routine for POSIX asynchronous I/O will
   96  * set this to the version of AIO that it implements.  (Zero means
   97  * that it is not implemented.)  This value is used here by pathconf()
   98  * and in kern_descrip.c by fpathconf().
   99  */
  100 int async_io_version;
  101 
  102 /*
  103  * Sync each mounted filesystem.
  104  */
  105 #ifndef _SYS_SYSPROTO_H_
  106 struct sync_args {
  107         int     dummy;
  108 };
  109 #endif
  110 
  111 #ifdef DEBUG
  112 static int syncprt = 0;
  113 SYSCTL_INT(_debug, OID_AUTO, syncprt, CTLFLAG_RW, &syncprt, 0, "");
  114 #endif
  115 
  116 /* ARGSUSED */
  117 int
  118 sync(td, uap)
  119         struct thread *td;
  120         struct sync_args *uap;
  121 {
  122         struct mount *mp, *nmp;
  123         int asyncflag;
  124 
  125         mtx_lock(&mountlist_mtx);
  126         for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
  127                 if (vfs_busy(mp, LK_NOWAIT, &mountlist_mtx, td)) {
  128                         nmp = TAILQ_NEXT(mp, mnt_list);
  129                         continue;
  130                 }
  131                 if ((mp->mnt_flag & MNT_RDONLY) == 0 &&
  132                     vn_start_write(NULL, &mp, V_NOWAIT) == 0) {
  133                         asyncflag = mp->mnt_flag & MNT_ASYNC;
  134                         mp->mnt_flag &= ~MNT_ASYNC;
  135                         vfs_msync(mp, MNT_NOWAIT);
  136                         VFS_SYNC(mp, MNT_NOWAIT,
  137                             ((td != NULL) ? td->td_ucred : NOCRED), td);
  138                         mp->mnt_flag |= asyncflag;
  139                         vn_finished_write(mp);
  140                 }
  141                 mtx_lock(&mountlist_mtx);
  142                 nmp = TAILQ_NEXT(mp, mnt_list);
  143                 vfs_unbusy(mp, td);
  144         }
  145         mtx_unlock(&mountlist_mtx);
  146 #if 0
  147 /*
  148  * XXX don't call vfs_bufstats() yet because that routine
  149  * was not imported in the Lite2 merge.
  150  */
  151 #ifdef DIAGNOSTIC
  152         if (syncprt)
  153                 vfs_bufstats();
  154 #endif /* DIAGNOSTIC */
  155 #endif
  156         return (0);
  157 }
  158 
  159 /* XXX PRISON: could be per prison flag */
  160 static int prison_quotas;
  161 #if 0
  162 SYSCTL_INT(_kern_prison, OID_AUTO, quotas, CTLFLAG_RW, &prison_quotas, 0, "");
  163 #endif
  164 
  165 /*
  166  * Change filesystem quotas.
  167  */
  168 #ifndef _SYS_SYSPROTO_H_
  169 struct quotactl_args {
  170         char *path;
  171         int cmd;
  172         int uid;
  173         caddr_t arg;
  174 };
  175 #endif
  176 /* ARGSUSED */
  177 int
  178 quotactl(td, uap)
  179         struct thread *td;
  180         register struct quotactl_args /* {
  181                 char *path;
  182                 int cmd;
  183                 int uid;
  184                 caddr_t arg;
  185         } */ *uap;
  186 {
  187         struct mount *mp;
  188         int error;
  189         struct nameidata nd;
  190 
  191         if (jailed(td->td_ucred) && !prison_quotas)
  192                 return (EPERM);
  193         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
  194         if ((error = namei(&nd)) != 0)
  195                 return (error);
  196         NDFREE(&nd, NDF_ONLY_PNBUF);
  197         error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
  198         vrele(nd.ni_vp);
  199         if (error)
  200                 return (error);
  201         error = VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg, td);
  202         vn_finished_write(mp);
  203         return (error);
  204 }
  205 
  206 /*
  207  * Get filesystem statistics.
  208  */
  209 #ifndef _SYS_SYSPROTO_H_
  210 struct statfs_args {
  211         char *path;
  212         struct statfs *buf;
  213 };
  214 #endif
  215 /* ARGSUSED */
  216 int
  217 statfs(td, uap)
  218         struct thread *td;
  219         register struct statfs_args /* {
  220                 char *path;
  221                 struct statfs *buf;
  222         } */ *uap;
  223 {
  224         register struct mount *mp;
  225         register struct statfs *sp;
  226         int error;
  227         struct nameidata nd;
  228         struct statfs sb;
  229 
  230         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
  231         if ((error = namei(&nd)) != 0)
  232                 return (error);
  233         mp = nd.ni_vp->v_mount;
  234         sp = &mp->mnt_stat;
  235         NDFREE(&nd, NDF_ONLY_PNBUF);
  236         vrele(nd.ni_vp);
  237 #ifdef MAC
  238         error = mac_check_mount_stat(td->td_ucred, mp);
  239         if (error)
  240                 return (error);
  241 #endif
  242         error = VFS_STATFS(mp, sp, td);
  243         if (error)
  244                 return (error);
  245         sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
  246         if (suser(td)) {
  247                 bcopy(sp, &sb, sizeof(sb));
  248                 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
  249                 sp = &sb;
  250         }
  251         return (copyout(sp, uap->buf, sizeof(*sp)));
  252 }
  253 
  254 /*
  255  * Get filesystem statistics.
  256  */
  257 #ifndef _SYS_SYSPROTO_H_
  258 struct fstatfs_args {
  259         int fd;
  260         struct statfs *buf;
  261 };
  262 #endif
  263 /* ARGSUSED */
  264 int
  265 fstatfs(td, uap)
  266         struct thread *td;
  267         register struct fstatfs_args /* {
  268                 int fd;
  269                 struct statfs *buf;
  270         } */ *uap;
  271 {
  272         struct file *fp;
  273         struct mount *mp;
  274         register struct statfs *sp;
  275         int error;
  276         struct statfs sb;
  277 
  278         if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
  279                 return (error);
  280         mp = ((struct vnode *)fp->f_data)->v_mount;
  281         fdrop(fp, td);
  282         if (mp == NULL)
  283                 return (EBADF);
  284 #ifdef MAC
  285         error = mac_check_mount_stat(td->td_ucred, mp);
  286         if (error)
  287                 return (error);
  288 #endif
  289         sp = &mp->mnt_stat;
  290         error = VFS_STATFS(mp, sp, td);
  291         if (error)
  292                 return (error);
  293         sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
  294         if (suser(td)) {
  295                 bcopy(sp, &sb, sizeof(sb));
  296                 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
  297                 sp = &sb;
  298         }
  299         return (copyout(sp, uap->buf, sizeof(*sp)));
  300 }
  301 
  302 /*
  303  * Get statistics on all filesystems.
  304  */
  305 #ifndef _SYS_SYSPROTO_H_
  306 struct getfsstat_args {
  307         struct statfs *buf;
  308         long bufsize;
  309         int flags;
  310 };
  311 #endif
  312 int
  313 getfsstat(td, uap)
  314         struct thread *td;
  315         register struct getfsstat_args /* {
  316                 struct statfs *buf;
  317                 long bufsize;
  318                 int flags;
  319         } */ *uap;
  320 {
  321         register struct mount *mp, *nmp;
  322         register struct statfs *sp;
  323         caddr_t sfsp;
  324         long count, maxcount, error;
  325 
  326         maxcount = uap->bufsize / sizeof(struct statfs);
  327         sfsp = (caddr_t)uap->buf;
  328         count = 0;
  329         mtx_lock(&mountlist_mtx);
  330         for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
  331 #ifdef MAC
  332                 if (mac_check_mount_stat(td->td_ucred, mp) != 0) {
  333                         nmp = TAILQ_NEXT(mp, mnt_list);
  334                         continue;
  335                 }
  336 #endif
  337                 if (vfs_busy(mp, LK_NOWAIT, &mountlist_mtx, td)) {
  338                         nmp = TAILQ_NEXT(mp, mnt_list);
  339                         continue;
  340                 }
  341                 if (sfsp && count < maxcount) {
  342                         sp = &mp->mnt_stat;
  343                         /*
  344                          * If MNT_NOWAIT or MNT_LAZY is specified, do not
  345                          * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY
  346                          * overrides MNT_WAIT.
  347                          */
  348                         if (((uap->flags & (MNT_LAZY|MNT_NOWAIT)) == 0 ||
  349                             (uap->flags & MNT_WAIT)) &&
  350                             (error = VFS_STATFS(mp, sp, td))) {
  351                                 mtx_lock(&mountlist_mtx);
  352                                 nmp = TAILQ_NEXT(mp, mnt_list);
  353                                 vfs_unbusy(mp, td);
  354                                 continue;
  355                         }
  356                         sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
  357                         error = copyout(sp, sfsp, sizeof(*sp));
  358                         if (error) {
  359                                 vfs_unbusy(mp, td);
  360                                 return (error);
  361                         }
  362                         sfsp += sizeof(*sp);
  363                 }
  364                 count++;
  365                 mtx_lock(&mountlist_mtx);
  366                 nmp = TAILQ_NEXT(mp, mnt_list);
  367                 vfs_unbusy(mp, td);
  368         }
  369         mtx_unlock(&mountlist_mtx);
  370         if (sfsp && count > maxcount)
  371                 td->td_retval[0] = maxcount;
  372         else
  373                 td->td_retval[0] = count;
  374         return (0);
  375 }
  376 
  377 /*
  378  * Change current working directory to a given file descriptor.
  379  */
  380 #ifndef _SYS_SYSPROTO_H_
  381 struct fchdir_args {
  382         int     fd;
  383 };
  384 #endif
  385 /* ARGSUSED */
  386 int
  387 fchdir(td, uap)
  388         struct thread *td;
  389         struct fchdir_args /* {
  390                 int fd;
  391         } */ *uap;
  392 {
  393         register struct filedesc *fdp = td->td_proc->p_fd;
  394         struct vnode *vp, *tdp, *vpold;
  395         struct mount *mp;
  396         struct file *fp;
  397         int error;
  398 
  399         if ((error = getvnode(fdp, uap->fd, &fp)) != 0)
  400                 return (error);
  401         vp = fp->f_data;
  402         VREF(vp);
  403         fdrop(fp, td);
  404         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
  405         if (vp->v_type != VDIR)
  406                 error = ENOTDIR;
  407 #ifdef MAC
  408         else if ((error = mac_check_vnode_chdir(td->td_ucred, vp)) != 0) {
  409         }
  410 #endif
  411         else
  412                 error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td);
  413         while (!error && (mp = vp->v_mountedhere) != NULL) {
  414                 if (vfs_busy(mp, 0, 0, td))
  415                         continue;
  416                 error = VFS_ROOT(mp, &tdp);
  417                 vfs_unbusy(mp, td);
  418                 if (error)
  419                         break;
  420                 vput(vp);
  421                 vp = tdp;
  422         }
  423         if (error) {
  424                 vput(vp);
  425                 return (error);
  426         }
  427         VOP_UNLOCK(vp, 0, td);
  428         FILEDESC_LOCK(fdp);
  429         vpold = fdp->fd_cdir;
  430         fdp->fd_cdir = vp;
  431         FILEDESC_UNLOCK(fdp);
  432         vrele(vpold);
  433         return (0);
  434 }
  435 
  436 /*
  437  * Change current working directory (``.'').
  438  */
  439 #ifndef _SYS_SYSPROTO_H_
  440 struct chdir_args {
  441         char    *path;
  442 };
  443 #endif
  444 /* ARGSUSED */
  445 int
  446 chdir(td, uap)
  447         struct thread *td;
  448         struct chdir_args /* {
  449                 char *path;
  450         } */ *uap;
  451 {
  452 
  453         return (kern_chdir(td, uap->path, UIO_USERSPACE));
  454 }
  455 
  456 int
  457 kern_chdir(struct thread *td, char *path, enum uio_seg pathseg)
  458 {
  459         register struct filedesc *fdp = td->td_proc->p_fd;
  460         int error;
  461         struct nameidata nd;
  462         struct vnode *vp;
  463 
  464         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, pathseg, path, td);
  465         if ((error = namei(&nd)) != 0)
  466                 return (error);
  467         if ((error = change_dir(nd.ni_vp, td)) != 0) {
  468                 vput(nd.ni_vp);
  469                 NDFREE(&nd, NDF_ONLY_PNBUF);
  470                 return (error);
  471         }
  472         VOP_UNLOCK(nd.ni_vp, 0, td);
  473         NDFREE(&nd, NDF_ONLY_PNBUF);
  474         FILEDESC_LOCK(fdp);
  475         vp = fdp->fd_cdir;
  476         fdp->fd_cdir = nd.ni_vp;
  477         FILEDESC_UNLOCK(fdp);
  478         vrele(vp);
  479         return (0);
  480 }
  481 
  482 /*
  483  * Helper function for raised chroot(2) security function:  Refuse if
  484  * any filedescriptors are open directories.
  485  */
  486 static int
  487 chroot_refuse_vdir_fds(fdp)
  488         struct filedesc *fdp;
  489 {
  490         struct vnode *vp;
  491         struct file *fp;
  492         int fd;
  493 
  494         FILEDESC_LOCK_ASSERT(fdp, MA_OWNED);
  495         for (fd = 0; fd < fdp->fd_nfiles ; fd++) {
  496                 fp = fget_locked(fdp, fd);
  497                 if (fp == NULL)
  498                         continue;
  499                 if (fp->f_type == DTYPE_VNODE) {
  500                         vp = fp->f_data;
  501                         if (vp->v_type == VDIR)
  502                                 return (EPERM);
  503                 }
  504         }
  505         return (0);
  506 }
  507 
  508 /*
  509  * This sysctl determines if we will allow a process to chroot(2) if it
  510  * has a directory open:
  511  *      0: disallowed for all processes.
  512  *      1: allowed for processes that were not already chroot(2)'ed.
  513  *      2: allowed for all processes.
  514  */
  515 
  516 static int chroot_allow_open_directories = 1;
  517 
  518 SYSCTL_INT(_kern, OID_AUTO, chroot_allow_open_directories, CTLFLAG_RW,
  519      &chroot_allow_open_directories, 0, "");
  520 
  521 /*
  522  * Change notion of root (``/'') directory.
  523  */
  524 #ifndef _SYS_SYSPROTO_H_
  525 struct chroot_args {
  526         char    *path;
  527 };
  528 #endif
  529 /* ARGSUSED */
  530 int
  531 chroot(td, uap)
  532         struct thread *td;
  533         struct chroot_args /* {
  534                 char *path;
  535         } */ *uap;
  536 {
  537         int error;
  538         struct nameidata nd;
  539 
  540         error = suser_cred(td->td_ucred, PRISON_ROOT);
  541         if (error)
  542                 return (error);
  543         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, td);
  544         mtx_lock(&Giant);
  545         error = namei(&nd);
  546         if (error)
  547                 goto error;
  548         if ((error = change_dir(nd.ni_vp, td)) != 0)
  549                 goto e_vunlock;
  550 #ifdef MAC
  551         if ((error = mac_check_vnode_chroot(td->td_ucred, nd.ni_vp)))
  552                 goto e_vunlock;
  553 #endif
  554         VOP_UNLOCK(nd.ni_vp, 0, td);
  555         error = change_root(nd.ni_vp, td);
  556         vrele(nd.ni_vp);
  557         NDFREE(&nd, NDF_ONLY_PNBUF);
  558         mtx_unlock(&Giant);
  559         return (error);
  560 e_vunlock:
  561         vput(nd.ni_vp);
  562 error:
  563         mtx_unlock(&Giant);
  564         NDFREE(&nd, NDF_ONLY_PNBUF);
  565         return (error);
  566 }
  567 
  568 /*
  569  * Common routine for chroot and chdir.  Callers must provide a locked vnode
  570  * instance.
  571  */
  572 int
  573 change_dir(vp, td)
  574         struct vnode *vp;
  575         struct thread *td;
  576 {
  577         int error;
  578 
  579         ASSERT_VOP_LOCKED(vp, "change_dir(): vp not locked");
  580         if (vp->v_type != VDIR)
  581                 return (ENOTDIR);
  582 #ifdef MAC
  583         error = mac_check_vnode_chdir(td->td_ucred, vp);
  584         if (error)
  585                 return (error);
  586 #endif
  587         error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td);
  588         return (error);
  589 }
  590 
  591 /*
  592  * Common routine for kern_chroot() and jail_attach().  The caller is
  593  * responsible for invoking suser() and mac_check_chroot() to authorize this
  594  * operation.
  595  */
  596 int
  597 change_root(vp, td)
  598         struct vnode *vp;
  599         struct thread *td;
  600 {
  601         struct filedesc *fdp;
  602         struct vnode *oldvp;
  603         int error;
  604 
  605         mtx_assert(&Giant, MA_OWNED);
  606         fdp = td->td_proc->p_fd;
  607         FILEDESC_LOCK(fdp);
  608         if (chroot_allow_open_directories == 0 ||
  609             (chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode)) {
  610                 error = chroot_refuse_vdir_fds(fdp);
  611                 if (error) {
  612                         FILEDESC_UNLOCK(fdp);
  613                         return (error);
  614                 }
  615         }
  616         oldvp = fdp->fd_rdir;
  617         fdp->fd_rdir = vp;
  618         VREF(fdp->fd_rdir);
  619         if (!fdp->fd_jdir) {
  620                 fdp->fd_jdir = vp;
  621                 VREF(fdp->fd_jdir);
  622         }
  623         FILEDESC_UNLOCK(fdp);
  624         vrele(oldvp);
  625         return (0);
  626 }
  627 
  628 /*
  629  * Check permissions, allocate an open file structure,
  630  * and call the device open routine if any.
  631  */
  632 #ifndef _SYS_SYSPROTO_H_
  633 struct open_args {
  634         char    *path;
  635         int     flags;
  636         int     mode;
  637 };
  638 #endif
  639 int
  640 open(td, uap)
  641         struct thread *td;
  642         register struct open_args /* {
  643                 char *path;
  644                 int flags;
  645                 int mode;
  646         } */ *uap;
  647 {
  648 
  649         return (kern_open(td, uap->path, UIO_USERSPACE, uap->flags, uap->mode));
  650 }
  651 
  652 int
  653 kern_open(struct thread *td, char *path, enum uio_seg pathseg, int flags,
  654     int mode)
  655 {
  656         struct proc *p = td->td_proc;
  657         struct filedesc *fdp = p->p_fd;
  658         struct file *fp;
  659         struct vnode *vp;
  660         struct vattr vat;
  661         struct mount *mp;
  662         int cmode, oflags;
  663         struct file *nfp;
  664         int type, indx, error;
  665         struct flock lf;
  666         struct nameidata nd;
  667 
  668         if ((flags & O_ACCMODE) == O_ACCMODE)
  669                 return (EINVAL);
  670         oflags = flags;
  671         flags = FFLAGS(flags);
  672         error = falloc(td, &nfp, &indx);
  673         if (error)
  674                 return (error);
  675         fp = nfp;
  676         cmode = ((mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
  677         NDINIT(&nd, LOOKUP, FOLLOW, pathseg, path, td);
  678         td->td_dupfd = -indx - 1;               /* XXX check for fdopen */
  679         /*
  680          * Bump the ref count to prevent another process from closing
  681          * the descriptor while we are blocked in vn_open()
  682          */
  683         fhold(fp);
  684         error = vn_open(&nd, &flags, cmode);
  685         if (error) {
  686                 /*
  687                  * release our own reference
  688                  */
  689                 fdrop(fp, td);
  690 
  691                 /*
  692                  * handle special fdopen() case.  bleh.  dupfdopen() is
  693                  * responsible for dropping the old contents of ofiles[indx]
  694                  * if it succeeds.
  695                  */
  696                 if ((error == ENODEV || error == ENXIO) &&
  697                     td->td_dupfd >= 0 &&                /* XXX from fdopen */
  698                     (error =
  699                         dupfdopen(td, fdp, indx, td->td_dupfd, flags, error)) == 0) {
  700                         td->td_retval[0] = indx;
  701                         return (0);
  702                 }
  703                 /*
  704                  * Clean up the descriptor, but only if another thread hadn't
  705                  * replaced or closed it.
  706                  */
  707                 FILEDESC_LOCK(fdp);
  708                 if (fdp->fd_ofiles[indx] == fp) {
  709                         fdp->fd_ofiles[indx] = NULL;
  710                         FILEDESC_UNLOCK(fdp);
  711                         fdrop(fp, td);
  712                 } else
  713                         FILEDESC_UNLOCK(fdp);
  714 
  715                 if (error == ERESTART)
  716                         error = EINTR;
  717                 return (error);
  718         }
  719         td->td_dupfd = 0;
  720         NDFREE(&nd, NDF_ONLY_PNBUF);
  721         vp = nd.ni_vp;
  722 
  723         /*
  724          * There should be 2 references on the file, one from the descriptor
  725          * table, and one for us.
  726          *
  727          * Handle the case where someone closed the file (via its file
  728          * descriptor) while we were blocked.  The end result should look
  729          * like opening the file succeeded but it was immediately closed.
  730          */
  731         FILEDESC_LOCK(fdp);
  732         FILE_LOCK(fp);
  733         if (fp->f_count == 1) {
  734                 KASSERT(fdp->fd_ofiles[indx] != fp,
  735                     ("Open file descriptor lost all refs"));
  736                 FILEDESC_UNLOCK(fdp);
  737                 FILE_UNLOCK(fp);
  738                 VOP_UNLOCK(vp, 0, td);
  739                 vn_close(vp, flags & FMASK, fp->f_cred, td);
  740                 fdrop(fp, td);
  741                 td->td_retval[0] = indx;
  742                 return 0;
  743         }
  744 
  745         /* assert that vn_open created a backing object if one is needed */
  746         KASSERT(!vn_canvmio(vp) || VOP_GETVOBJECT(vp, NULL) == 0,
  747                 ("open: vmio vnode has no backing object after vn_open"));
  748 
  749         fp->f_data = vp;
  750         fp->f_flag = flags & FMASK;
  751         fp->f_ops = &vnops;
  752         fp->f_type = (vp->v_type == VFIFO ? DTYPE_FIFO : DTYPE_VNODE);
  753         FILEDESC_UNLOCK(fdp);
  754         FILE_UNLOCK(fp);
  755         VOP_UNLOCK(vp, 0, td);
  756         if (flags & (O_EXLOCK | O_SHLOCK)) {
  757                 lf.l_whence = SEEK_SET;
  758                 lf.l_start = 0;
  759                 lf.l_len = 0;
  760                 if (flags & O_EXLOCK)
  761                         lf.l_type = F_WRLCK;
  762                 else
  763                         lf.l_type = F_RDLCK;
  764                 type = F_FLOCK;
  765                 if ((flags & FNONBLOCK) == 0)
  766                         type |= F_WAIT;
  767                 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf,
  768                             type)) != 0)
  769                         goto bad;
  770                 fp->f_flag |= FHASLOCK;
  771         }
  772         if (flags & O_TRUNC) {
  773                 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
  774                         goto bad;
  775                 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
  776                 VATTR_NULL(&vat);
  777                 vat.va_size = 0;
  778                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
  779 #ifdef MAC
  780                 error = mac_check_vnode_write(td->td_ucred, fp->f_cred, vp);
  781                 if (error == 0)
  782 #endif
  783                         error = VOP_SETATTR(vp, &vat, td->td_ucred, td);
  784                 VOP_UNLOCK(vp, 0, td);
  785                 vn_finished_write(mp);
  786                 if (error)
  787                         goto bad;
  788         }
  789         /*
  790          * Release our private reference, leaving the one associated with
  791          * the descriptor table intact.
  792          */
  793         fdrop(fp, td);
  794         td->td_retval[0] = indx;
  795         return (0);
  796 bad:
  797         FILEDESC_LOCK(fdp);
  798         if (fdp->fd_ofiles[indx] == fp) {
  799                 fdp->fd_ofiles[indx] = NULL;
  800                 FILEDESC_UNLOCK(fdp);
  801                 fdrop(fp, td);
  802         } else
  803                 FILEDESC_UNLOCK(fdp);
  804         fdrop(fp, td);
  805         return (error);
  806 }
  807 
  808 #ifdef COMPAT_43
  809 /*
  810  * Create a file.
  811  */
  812 #ifndef _SYS_SYSPROTO_H_
  813 struct ocreat_args {
  814         char    *path;
  815         int     mode;
  816 };
  817 #endif
  818 int
  819 ocreat(td, uap)
  820         struct thread *td;
  821         register struct ocreat_args /* {
  822                 char *path;
  823                 int mode;
  824         } */ *uap;
  825 {
  826         struct open_args /* {
  827                 char *path;
  828                 int flags;
  829                 int mode;
  830         } */ nuap;
  831 
  832         nuap.path = uap->path;
  833         nuap.mode = uap->mode;
  834         nuap.flags = O_WRONLY | O_CREAT | O_TRUNC;
  835         return (open(td, &nuap));
  836 }
  837 #endif /* COMPAT_43 */
  838 
  839 /*
  840  * Create a special file.
  841  */
  842 #ifndef _SYS_SYSPROTO_H_
  843 struct mknod_args {
  844         char    *path;
  845         int     mode;
  846         int     dev;
  847 };
  848 #endif
  849 /* ARGSUSED */
  850 int
  851 mknod(td, uap)
  852         struct thread *td;
  853         register struct mknod_args /* {
  854                 char *path;
  855                 int mode;
  856                 int dev;
  857         } */ *uap;
  858 {
  859 
  860         return (kern_mknod(td, uap->path, UIO_USERSPACE, uap->mode, uap->dev));
  861 }
  862 
  863 int
  864 kern_mknod(struct thread *td, char *path, enum uio_seg pathseg, int mode,
  865     int dev)
  866 {
  867         struct vnode *vp;
  868         struct mount *mp;
  869         struct vattr vattr;
  870         int error;
  871         int whiteout = 0;
  872         struct nameidata nd;
  873 
  874         switch (mode & S_IFMT) {
  875         case S_IFCHR:
  876         case S_IFBLK:
  877                 error = suser(td);
  878                 break;
  879         default:
  880                 error = suser_cred(td->td_ucred, PRISON_ROOT);
  881                 break;
  882         }
  883         if (error)
  884                 return (error);
  885 restart:
  886         bwillwrite();
  887         NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME, pathseg, path, td);
  888         if ((error = namei(&nd)) != 0)
  889                 return (error);
  890         vp = nd.ni_vp;
  891         if (vp != NULL) {
  892                 vrele(vp);
  893                 error = EEXIST;
  894         } else {
  895                 VATTR_NULL(&vattr);
  896                 FILEDESC_LOCK(td->td_proc->p_fd);
  897                 vattr.va_mode = (mode & ALLPERMS) &
  898                     ~td->td_proc->p_fd->fd_cmask;
  899                 FILEDESC_UNLOCK(td->td_proc->p_fd);
  900                 vattr.va_rdev = dev;
  901                 whiteout = 0;
  902 
  903                 switch (mode & S_IFMT) {
  904                 case S_IFMT:    /* used by badsect to flag bad sectors */
  905                         vattr.va_type = VBAD;
  906                         break;
  907                 case S_IFCHR:
  908                         vattr.va_type = VCHR;
  909                         break;
  910                 case S_IFBLK:
  911                         vattr.va_type = VBLK;
  912                         break;
  913                 case S_IFWHT:
  914                         whiteout = 1;
  915                         break;
  916                 default:
  917                         error = EINVAL;
  918                         break;
  919                 }
  920         }
  921         if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
  922                 NDFREE(&nd, NDF_ONLY_PNBUF);
  923                 vput(nd.ni_dvp);
  924                 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
  925                         return (error);
  926                 goto restart;
  927         }
  928 #ifdef MAC
  929         if (error == 0 && !whiteout)
  930                 error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp,
  931                     &nd.ni_cnd, &vattr);
  932 #endif
  933         if (!error) {
  934                 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
  935                 if (whiteout)
  936                         error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE);
  937                 else {
  938                         error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp,
  939                                                 &nd.ni_cnd, &vattr);
  940                         if (error == 0)
  941                                 vput(nd.ni_vp);
  942                 }
  943         }
  944         NDFREE(&nd, NDF_ONLY_PNBUF);
  945         vput(nd.ni_dvp);
  946         vn_finished_write(mp);
  947         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mknod");
  948         ASSERT_VOP_UNLOCKED(nd.ni_vp, "mknod");
  949         return (error);
  950 }
  951 
  952 /*
  953  * Create a named pipe.
  954  */
  955 #ifndef _SYS_SYSPROTO_H_
  956 struct mkfifo_args {
  957         char    *path;
  958         int     mode;
  959 };
  960 #endif
  961 /* ARGSUSED */
  962 int
  963 mkfifo(td, uap)
  964         struct thread *td;
  965         register struct mkfifo_args /* {
  966                 char *path;
  967                 int mode;
  968         } */ *uap;
  969 {
  970 
  971         return (kern_mkfifo(td, uap->path, UIO_USERSPACE, uap->mode));
  972 }
  973 
  974 int
  975 kern_mkfifo(struct thread *td, char *path, enum uio_seg pathseg, int mode)
  976 {
  977         struct mount *mp;
  978         struct vattr vattr;
  979         int error;
  980         struct nameidata nd;
  981 
  982 restart:
  983         bwillwrite();
  984         NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME, pathseg, path, td);
  985         if ((error = namei(&nd)) != 0)
  986                 return (error);
  987         if (nd.ni_vp != NULL) {
  988                 NDFREE(&nd, NDF_ONLY_PNBUF);
  989                 vrele(nd.ni_vp);
  990                 vput(nd.ni_dvp);
  991                 return (EEXIST);
  992         }
  993         if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
  994                 NDFREE(&nd, NDF_ONLY_PNBUF);
  995                 vput(nd.ni_dvp);
  996                 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
  997                         return (error);
  998                 goto restart;
  999         }
 1000         VATTR_NULL(&vattr);
 1001         vattr.va_type = VFIFO;
 1002         FILEDESC_LOCK(td->td_proc->p_fd);
 1003         vattr.va_mode = (mode & ALLPERMS) & ~td->td_proc->p_fd->fd_cmask;
 1004         FILEDESC_UNLOCK(td->td_proc->p_fd);
 1005 #ifdef MAC
 1006         error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
 1007             &vattr);
 1008         if (error)
 1009                 goto out;
 1010 #endif
 1011         VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
 1012         error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
 1013         if (error == 0)
 1014                 vput(nd.ni_vp);
 1015 #ifdef MAC
 1016 out:
 1017 #endif
 1018         NDFREE(&nd, NDF_ONLY_PNBUF);
 1019         vput(nd.ni_dvp);
 1020         vn_finished_write(mp);
 1021         return (error);
 1022 }
 1023 
 1024 /*
 1025  * Make a hard file link.
 1026  */
 1027 #ifndef _SYS_SYSPROTO_H_
 1028 struct link_args {
 1029         char    *path;
 1030         char    *link;
 1031 };
 1032 #endif
 1033 /* ARGSUSED */
 1034 int
 1035 link(td, uap)
 1036         struct thread *td;
 1037         register struct link_args /* {
 1038                 char *path;
 1039                 char *link;
 1040         } */ *uap;
 1041 {
 1042 
 1043         return (kern_link(td, uap->path, uap->link, UIO_USERSPACE));
 1044 }
 1045 
 1046 int
 1047 kern_link(struct thread *td, char *path, char *link, enum uio_seg segflg)
 1048 {
 1049         struct vnode *vp;
 1050         struct mount *mp;
 1051         struct nameidata nd;
 1052         int error;
 1053 
 1054         bwillwrite();
 1055         NDINIT(&nd, LOOKUP, FOLLOW|NOOBJ, segflg, path, td);
 1056         if ((error = namei(&nd)) != 0)
 1057                 return (error);
 1058         NDFREE(&nd, NDF_ONLY_PNBUF);
 1059         vp = nd.ni_vp;
 1060         if (vp->v_type == VDIR) {
 1061                 vrele(vp);
 1062                 return (EPERM);         /* POSIX */
 1063         }
 1064         if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) {
 1065                 vrele(vp);
 1066                 return (error);
 1067         }
 1068         NDINIT(&nd, CREATE, LOCKPARENT | NOOBJ | SAVENAME, segflg, link, td);
 1069         if ((error = namei(&nd)) == 0) {
 1070                 if (nd.ni_vp != NULL) {
 1071                         vrele(nd.ni_vp);
 1072                         error = EEXIST;
 1073                 } else if ((error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td))
 1074                     == 0) {
 1075                         VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
 1076                         VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
 1077 #ifdef MAC
 1078                         error = mac_check_vnode_link(td->td_ucred, nd.ni_dvp,
 1079                             vp, &nd.ni_cnd);
 1080                         if (error == 0)
 1081 #endif
 1082                                 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
 1083                         VOP_UNLOCK(vp, 0, td);
 1084                 }
 1085                 NDFREE(&nd, NDF_ONLY_PNBUF);
 1086                 vput(nd.ni_dvp);
 1087         }
 1088         vrele(vp);
 1089         vn_finished_write(mp);
 1090         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "link");
 1091         ASSERT_VOP_UNLOCKED(nd.ni_vp, "link");
 1092         return (error);
 1093 }
 1094 
 1095 /*
 1096  * Make a symbolic link.
 1097  */
 1098 #ifndef _SYS_SYSPROTO_H_
 1099 struct symlink_args {
 1100         char    *path;
 1101         char    *link;
 1102 };
 1103 #endif
 1104 /* ARGSUSED */
 1105 int
 1106 symlink(td, uap)
 1107         struct thread *td;
 1108         register struct symlink_args /* {
 1109                 char *path;
 1110                 char *link;
 1111         } */ *uap;
 1112 {
 1113 
 1114         return (kern_symlink(td, uap->path, uap->link, UIO_USERSPACE));
 1115 }
 1116 
 1117 int
 1118 kern_symlink(struct thread *td, char *path, char *link, enum uio_seg segflg)
 1119 {
 1120         struct mount *mp;
 1121         struct vattr vattr;
 1122         char *syspath;
 1123         int error;
 1124         struct nameidata nd;
 1125 
 1126         if (segflg == UIO_SYSSPACE) {
 1127                 syspath = path;
 1128         } else {
 1129                 syspath = uma_zalloc(namei_zone, M_WAITOK);
 1130                 if ((error = copyinstr(path, syspath, MAXPATHLEN, NULL)) != 0)
 1131                         goto out;
 1132         }
 1133 restart:
 1134         bwillwrite();
 1135         NDINIT(&nd, CREATE, LOCKPARENT | NOOBJ | SAVENAME, segflg, link, td);
 1136         if ((error = namei(&nd)) != 0)
 1137                 goto out;
 1138         if (nd.ni_vp) {
 1139                 NDFREE(&nd, NDF_ONLY_PNBUF);
 1140                 vrele(nd.ni_vp);
 1141                 vput(nd.ni_dvp);
 1142                 error = EEXIST;
 1143                 goto out;
 1144         }
 1145         if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
 1146                 NDFREE(&nd, NDF_ONLY_PNBUF);
 1147                 vput(nd.ni_dvp);
 1148                 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
 1149                         return (error);
 1150                 goto restart;
 1151         }
 1152         VATTR_NULL(&vattr);
 1153         FILEDESC_LOCK(td->td_proc->p_fd);
 1154         vattr.va_mode = ACCESSPERMS &~ td->td_proc->p_fd->fd_cmask;
 1155         FILEDESC_UNLOCK(td->td_proc->p_fd);
 1156 #ifdef MAC
 1157         vattr.va_type = VLNK;
 1158         error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
 1159             &vattr);
 1160         if (error)
 1161                 goto out2;
 1162 #endif
 1163         VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
 1164         error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, syspath);
 1165         if (error == 0)
 1166                 vput(nd.ni_vp);
 1167 #ifdef MAC
 1168 out2:
 1169 #endif
 1170         NDFREE(&nd, NDF_ONLY_PNBUF);
 1171         vput(nd.ni_dvp);
 1172         vn_finished_write(mp);
 1173         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "symlink");
 1174         ASSERT_VOP_UNLOCKED(nd.ni_vp, "symlink");
 1175 out:
 1176         if (segflg != UIO_SYSSPACE)
 1177                 uma_zfree(namei_zone, syspath);
 1178         return (error);
 1179 }
 1180 
 1181 /*
 1182  * Delete a whiteout from the filesystem.
 1183  */
 1184 /* ARGSUSED */
 1185 int
 1186 undelete(td, uap)
 1187         struct thread *td;
 1188         register struct undelete_args /* {
 1189                 char *path;
 1190         } */ *uap;
 1191 {
 1192         int error;
 1193         struct mount *mp;
 1194         struct nameidata nd;
 1195 
 1196 restart:
 1197         bwillwrite();
 1198         NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE,
 1199             uap->path, td);
 1200         error = namei(&nd);
 1201         if (error)
 1202                 return (error);
 1203 
 1204         if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) {
 1205                 NDFREE(&nd, NDF_ONLY_PNBUF);
 1206                 if (nd.ni_vp)
 1207                         vrele(nd.ni_vp);
 1208                 vput(nd.ni_dvp);
 1209                 return (EEXIST);
 1210         }
 1211         if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
 1212                 NDFREE(&nd, NDF_ONLY_PNBUF);
 1213                 vput(nd.ni_dvp);
 1214                 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
 1215                         return (error);
 1216                 goto restart;
 1217         }
 1218         VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
 1219         error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE);
 1220         NDFREE(&nd, NDF_ONLY_PNBUF);
 1221         vput(nd.ni_dvp);
 1222         vn_finished_write(mp);
 1223         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "undelete");
 1224         ASSERT_VOP_UNLOCKED(nd.ni_vp, "undelete");
 1225         return (error);
 1226 }
 1227 
 1228 /*
 1229  * Delete a name from the filesystem.
 1230  */
 1231 #ifndef _SYS_SYSPROTO_H_
 1232 struct unlink_args {
 1233         char    *path;
 1234 };
 1235 #endif
 1236 /* ARGSUSED */
 1237 int
 1238 unlink(td, uap)
 1239         struct thread *td;
 1240         struct unlink_args /* {
 1241                 char *path;
 1242         } */ *uap;
 1243 {
 1244 
 1245         return (kern_unlink(td, uap->path, UIO_USERSPACE));
 1246 }
 1247 
 1248 int
 1249 kern_unlink(struct thread *td, char *path, enum uio_seg pathseg)
 1250 {
 1251         struct mount *mp;
 1252         struct vnode *vp;
 1253         int error;
 1254         struct nameidata nd;
 1255 
 1256 restart:
 1257         bwillwrite();
 1258         NDINIT(&nd, DELETE, LOCKPARENT|LOCKLEAF, pathseg, path, td);
 1259         if ((error = namei(&nd)) != 0)
 1260                 return (error);
 1261         vp = nd.ni_vp;
 1262         if (vp->v_type == VDIR)
 1263                 error = EPERM;          /* POSIX */
 1264         else {
 1265                 /*
 1266                  * The root of a mounted filesystem cannot be deleted.
 1267                  *
 1268                  * XXX: can this only be a VDIR case?
 1269                  */
 1270                 if (vp->v_vflag & VV_ROOT)
 1271                         error = EBUSY;
 1272         }
 1273         if (error == 0) {
 1274                 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
 1275                         NDFREE(&nd, NDF_ONLY_PNBUF);
 1276                         if (vp == nd.ni_dvp)
 1277                                 vrele(vp);
 1278                         else
 1279                                 vput(vp);
 1280                         vput(nd.ni_dvp);
 1281                         if ((error = vn_start_write(NULL, &mp,
 1282                             V_XSLEEP | PCATCH)) != 0)
 1283                                 return (error);
 1284                         goto restart;
 1285                 }
 1286 #ifdef MAC
 1287                 error = mac_check_vnode_delete(td->td_ucred, nd.ni_dvp, vp,
 1288                     &nd.ni_cnd);
 1289                 if (error)
 1290                         goto out;
 1291 #endif
 1292                 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
 1293                 error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd);
 1294 #ifdef MAC
 1295 out:
 1296 #endif
 1297                 vn_finished_write(mp);
 1298         }
 1299         NDFREE(&nd, NDF_ONLY_PNBUF);
 1300         if (vp == nd.ni_dvp)
 1301                 vrele(vp);
 1302         else
 1303                 vput(vp);
 1304         vput(nd.ni_dvp);
 1305         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "unlink");
 1306         ASSERT_VOP_UNLOCKED(nd.ni_vp, "unlink");
 1307         return (error);
 1308 }
 1309 
 1310 /*
 1311  * Reposition read/write file offset.
 1312  */
 1313 #ifndef _SYS_SYSPROTO_H_
 1314 struct lseek_args {
 1315         int     fd;
 1316         int     pad;
 1317         off_t   offset;
 1318         int     whence;
 1319 };
 1320 #endif
 1321 int
 1322 lseek(td, uap)
 1323         struct thread *td;
 1324         register struct lseek_args /* {
 1325                 int fd;
 1326                 int pad;
 1327                 off_t offset;
 1328                 int whence;
 1329         } */ *uap;
 1330 {
 1331         struct ucred *cred = td->td_ucred;
 1332         struct file *fp;
 1333         struct vnode *vp;
 1334         struct vattr vattr;
 1335         off_t offset;
 1336         int error, noneg;
 1337 
 1338         if ((error = fget(td, uap->fd, &fp)) != 0)
 1339                 return (error);
 1340         if (fp->f_type != DTYPE_VNODE) {
 1341                 fdrop(fp, td);
 1342                 return (ESPIPE);
 1343         }
 1344         vp = fp->f_data;
 1345         noneg = (vp->v_type != VCHR);
 1346         offset = uap->offset;
 1347         switch (uap->whence) {
 1348         case L_INCR:
 1349                 if (noneg &&
 1350                     (fp->f_offset < 0 ||
 1351                     (offset > 0 && fp->f_offset > OFF_MAX - offset))) {
 1352                         error = EOVERFLOW;
 1353                         break;
 1354                 }
 1355                 offset += fp->f_offset;
 1356                 break;
 1357         case L_XTND:
 1358                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
 1359                 error = VOP_GETATTR(vp, &vattr, cred, td);
 1360                 VOP_UNLOCK(vp, 0, td);
 1361                 if (error)
 1362                         break;
 1363                 if (noneg &&
 1364                     (vattr.va_size > OFF_MAX ||
 1365                     (offset > 0 && vattr.va_size > OFF_MAX - offset))) {
 1366                         error = EOVERFLOW;
 1367                         break;
 1368                 }
 1369                 offset += vattr.va_size;
 1370                 break;
 1371         case L_SET:
 1372                 break;
 1373         default:
 1374                 error = EINVAL;
 1375         }
 1376         if (error == 0 && noneg && offset < 0)
 1377                 error = EINVAL;
 1378         if (error != 0) {
 1379                 fdrop(fp, td);
 1380                 return (error);
 1381         }
 1382         fp->f_offset = offset;
 1383         *(off_t *)(td->td_retval) = fp->f_offset;
 1384         fdrop(fp, td);
 1385         return (0);
 1386 }
 1387 
 1388 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
 1389 /*
 1390  * Reposition read/write file offset.
 1391  */
 1392 #ifndef _SYS_SYSPROTO_H_
 1393 struct olseek_args {
 1394         int     fd;
 1395         long    offset;
 1396         int     whence;
 1397 };
 1398 #endif
 1399 int
 1400 olseek(td, uap)
 1401         struct thread *td;
 1402         register struct olseek_args /* {
 1403                 int fd;
 1404                 long offset;
 1405                 int whence;
 1406         } */ *uap;
 1407 {
 1408         struct lseek_args /* {
 1409                 int fd;
 1410                 int pad;
 1411                 off_t offset;
 1412                 int whence;
 1413         } */ nuap;
 1414         int error;
 1415 
 1416         nuap.fd = uap->fd;
 1417         nuap.offset = uap->offset;
 1418         nuap.whence = uap->whence;
 1419         error = lseek(td, &nuap);
 1420         return (error);
 1421 }
 1422 #endif /* COMPAT_43 */
 1423 
 1424 /*
 1425  * Check access permissions using passed credentials.
 1426  */
 1427 static int
 1428 vn_access(vp, user_flags, cred, td)
 1429         struct vnode    *vp;
 1430         int             user_flags;
 1431         struct ucred    *cred;
 1432         struct thread   *td;
 1433 {
 1434         int error, flags;
 1435 
 1436         /* Flags == 0 means only check for existence. */
 1437         error = 0;
 1438         if (user_flags) {
 1439                 flags = 0;
 1440                 if (user_flags & R_OK)
 1441                         flags |= VREAD;
 1442                 if (user_flags & W_OK)
 1443                         flags |= VWRITE;
 1444                 if (user_flags & X_OK)
 1445                         flags |= VEXEC;
 1446 #ifdef MAC
 1447                 error = mac_check_vnode_access(cred, vp, flags);
 1448                 if (error)
 1449                         return (error);
 1450 #endif
 1451                 if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
 1452                         error = VOP_ACCESS(vp, flags, cred, td);
 1453         }
 1454         return (error);
 1455 }
 1456 
 1457 /*
 1458  * Check access permissions using "real" credentials.
 1459  */
 1460 #ifndef _SYS_SYSPROTO_H_
 1461 struct access_args {
 1462         char    *path;
 1463         int     flags;
 1464 };
 1465 #endif
 1466 int
 1467 access(td, uap)
 1468         struct thread *td;
 1469         register struct access_args /* {
 1470                 char *path;
 1471                 int flags;
 1472         } */ *uap;
 1473 {
 1474 
 1475         return (kern_access(td, uap->path, UIO_USERSPACE, uap->flags));
 1476 }
 1477 
 1478 int
 1479 kern_access(struct thread *td, char *path, enum uio_seg pathseg, int flags)
 1480 {
 1481         struct ucred *cred, *tmpcred;
 1482         register struct vnode *vp;
 1483         int error;
 1484         struct nameidata nd;
 1485 
 1486         /*
 1487          * Create and modify a temporary credential instead of one that
 1488          * is potentially shared.  This could also mess up socket
 1489          * buffer accounting which can run in an interrupt context.
 1490          *
 1491          * XXX - Depending on how "threads" are finally implemented, it
 1492          * may be better to explicitly pass the credential to namei()
 1493          * rather than to modify the potentially shared process structure.
 1494          */
 1495         cred = td->td_ucred;
 1496         tmpcred = crdup(cred);
 1497         tmpcred->cr_uid = cred->cr_ruid;
 1498         tmpcred->cr_groups[0] = cred->cr_rgid;
 1499         td->td_ucred = tmpcred;
 1500         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, pathseg, path, td);
 1501         if ((error = namei(&nd)) != 0)
 1502                 goto out1;
 1503         vp = nd.ni_vp;
 1504 
 1505         error = vn_access(vp, flags, tmpcred, td);
 1506         NDFREE(&nd, NDF_ONLY_PNBUF);
 1507         vput(vp);
 1508 out1:
 1509         td->td_ucred = cred;
 1510         crfree(tmpcred);
 1511         return (error);
 1512 }
 1513 
 1514 /*
 1515  * Check access permissions using "effective" credentials.
 1516  */
 1517 #ifndef _SYS_SYSPROTO_H_
 1518 struct eaccess_args {
 1519         char    *path;
 1520         int     flags;
 1521 };
 1522 #endif
 1523 int
 1524 eaccess(td, uap)
 1525         struct thread *td;
 1526         register struct eaccess_args /* {
 1527                 char *path;
 1528                 int flags;
 1529         } */ *uap;
 1530 {
 1531         struct nameidata nd;
 1532         struct vnode *vp;
 1533         int error;
 1534 
 1535         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
 1536             uap->path, td);
 1537         if ((error = namei(&nd)) != 0)
 1538                 return (error);
 1539         vp = nd.ni_vp;
 1540 
 1541         error = vn_access(vp, uap->flags, td->td_ucred, td);
 1542         NDFREE(&nd, NDF_ONLY_PNBUF);
 1543         vput(vp);
 1544         return (error);
 1545 }
 1546 
 1547 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
 1548 /*
 1549  * Get file status; this version follows links.
 1550  */
 1551 #ifndef _SYS_SYSPROTO_H_
 1552 struct ostat_args {
 1553         char    *path;
 1554         struct ostat *ub;
 1555 };
 1556 #endif
 1557 /* ARGSUSED */
 1558 int
 1559 ostat(td, uap)
 1560         struct thread *td;
 1561         register struct ostat_args /* {
 1562                 char *path;
 1563                 struct ostat *ub;
 1564         } */ *uap;
 1565 {
 1566         struct stat sb;
 1567         struct ostat osb;
 1568         int error;
 1569         struct nameidata nd;
 1570 
 1571         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
 1572             uap->path, td);
 1573         if ((error = namei(&nd)) != 0)
 1574                 return (error);
 1575         NDFREE(&nd, NDF_ONLY_PNBUF);
 1576         error = vn_stat(nd.ni_vp, &sb, td->td_ucred, NOCRED, td);
 1577         vput(nd.ni_vp);
 1578         if (error)
 1579                 return (error);
 1580         cvtstat(&sb, &osb);
 1581         error = copyout(&osb, uap->ub, sizeof (osb));
 1582         return (error);
 1583 }
 1584 
 1585 /*
 1586  * Get file status; this version does not follow links.
 1587  */
 1588 #ifndef _SYS_SYSPROTO_H_
 1589 struct olstat_args {
 1590         char    *path;
 1591         struct ostat *ub;
 1592 };
 1593 #endif
 1594 /* ARGSUSED */
 1595 int
 1596 olstat(td, uap)
 1597         struct thread *td;
 1598         register struct olstat_args /* {
 1599                 char *path;
 1600                 struct ostat *ub;
 1601         } */ *uap;
 1602 {
 1603         struct vnode *vp;
 1604         struct stat sb;
 1605         struct ostat osb;
 1606         int error;
 1607         struct nameidata nd;
 1608 
 1609         NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
 1610             uap->path, td);
 1611         if ((error = namei(&nd)) != 0)
 1612                 return (error);
 1613         vp = nd.ni_vp;
 1614         error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td);
 1615         NDFREE(&nd, NDF_ONLY_PNBUF);
 1616         vput(vp);
 1617         if (error)
 1618                 return (error);
 1619         cvtstat(&sb, &osb);
 1620         error = copyout(&osb, uap->ub, sizeof (osb));
 1621         return (error);
 1622 }
 1623 
 1624 /*
 1625  * Convert from an old to a new stat structure.
 1626  */
 1627 void
 1628 cvtstat(st, ost)
 1629         struct stat *st;
 1630         struct ostat *ost;
 1631 {
 1632 
 1633         ost->st_dev = st->st_dev;
 1634         ost->st_ino = st->st_ino;
 1635         ost->st_mode = st->st_mode;
 1636         ost->st_nlink = st->st_nlink;
 1637         ost->st_uid = st->st_uid;
 1638         ost->st_gid = st->st_gid;
 1639         ost->st_rdev = st->st_rdev;
 1640         if (st->st_size < (quad_t)1 << 32)
 1641                 ost->st_size = st->st_size;
 1642         else
 1643                 ost->st_size = -2;
 1644         ost->st_atime = st->st_atime;
 1645         ost->st_mtime = st->st_mtime;
 1646         ost->st_ctime = st->st_ctime;
 1647         ost->st_blksize = st->st_blksize;
 1648         ost->st_blocks = st->st_blocks;
 1649         ost->st_flags = st->st_flags;
 1650         ost->st_gen = st->st_gen;
 1651 }
 1652 #endif /* COMPAT_43 || COMPAT_SUNOS */
 1653 
 1654 /*
 1655  * Get file status; this version follows links.
 1656  */
 1657 #ifndef _SYS_SYSPROTO_H_
 1658 struct stat_args {
 1659         char    *path;
 1660         struct stat *ub;
 1661 };
 1662 #endif
 1663 /* ARGSUSED */
 1664 int
 1665 stat(td, uap)
 1666         struct thread *td;
 1667         register struct stat_args /* {
 1668                 char *path;
 1669                 struct stat *ub;
 1670         } */ *uap;
 1671 {
 1672         struct stat sb;
 1673         int error;
 1674         struct nameidata nd;
 1675 
 1676 #ifdef LOOKUP_SHARED
 1677         NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | NOOBJ,
 1678             UIO_USERSPACE, uap->path, td);
 1679 #else
 1680         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
 1681             uap->path, td);
 1682 #endif
 1683         if ((error = namei(&nd)) != 0)
 1684                 return (error);
 1685         error = vn_stat(nd.ni_vp, &sb, td->td_ucred, NOCRED, td);
 1686         NDFREE(&nd, NDF_ONLY_PNBUF);
 1687         vput(nd.ni_vp);
 1688         if (error)
 1689                 return (error);
 1690         error = copyout(&sb, uap->ub, sizeof (sb));
 1691         return (error);
 1692 }
 1693 
 1694 /*
 1695  * Get file status; this version does not follow links.
 1696  */
 1697 #ifndef _SYS_SYSPROTO_H_
 1698 struct lstat_args {
 1699         char    *path;
 1700         struct stat *ub;
 1701 };
 1702 #endif
 1703 /* ARGSUSED */
 1704 int
 1705 lstat(td, uap)
 1706         struct thread *td;
 1707         register struct lstat_args /* {
 1708                 char *path;
 1709                 struct stat *ub;
 1710         } */ *uap;
 1711 {
 1712         int error;
 1713         struct vnode *vp;
 1714         struct stat sb;
 1715         struct nameidata nd;
 1716 
 1717         NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
 1718             uap->path, td);
 1719         if ((error = namei(&nd)) != 0)
 1720                 return (error);
 1721         vp = nd.ni_vp;
 1722         error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td);
 1723         NDFREE(&nd, NDF_ONLY_PNBUF);
 1724         vput(vp);
 1725         if (error)
 1726                 return (error);
 1727         error = copyout(&sb, uap->ub, sizeof (sb));
 1728         return (error);
 1729 }
 1730 
 1731 /*
 1732  * Implementation of the NetBSD stat() function.
 1733  * XXX This should probably be collapsed with the FreeBSD version,
 1734  * as the differences are only due to vn_stat() clearing spares at
 1735  * the end of the structures.  vn_stat could be split to avoid this,
 1736  * and thus collapse the following to close to zero code.
 1737  */
 1738 void
 1739 cvtnstat(sb, nsb)
 1740         struct stat *sb;
 1741         struct nstat *nsb;
 1742 {
 1743         bzero(nsb, sizeof *nsb);
 1744         nsb->st_dev = sb->st_dev;
 1745         nsb->st_ino = sb->st_ino;
 1746         nsb->st_mode = sb->st_mode;
 1747         nsb->st_nlink = sb->st_nlink;
 1748         nsb->st_uid = sb->st_uid;
 1749         nsb->st_gid = sb->st_gid;
 1750         nsb->st_rdev = sb->st_rdev;
 1751         nsb->st_atimespec = sb->st_atimespec;
 1752         nsb->st_mtimespec = sb->st_mtimespec;
 1753         nsb->st_ctimespec = sb->st_ctimespec;
 1754         nsb->st_size = sb->st_size;
 1755         nsb->st_blocks = sb->st_blocks;
 1756         nsb->st_blksize = sb->st_blksize;
 1757         nsb->st_flags = sb->st_flags;
 1758         nsb->st_gen = sb->st_gen;
 1759         nsb->st_birthtimespec = sb->st_birthtimespec;
 1760 }
 1761 
 1762 #ifndef _SYS_SYSPROTO_H_
 1763 struct nstat_args {
 1764         char    *path;
 1765         struct nstat *ub;
 1766 };
 1767 #endif
 1768 /* ARGSUSED */
 1769 int
 1770 nstat(td, uap)
 1771         struct thread *td;
 1772         register struct nstat_args /* {
 1773                 char *path;
 1774                 struct nstat *ub;
 1775         } */ *uap;
 1776 {
 1777         struct stat sb;
 1778         struct nstat nsb;
 1779         int error;
 1780         struct nameidata nd;
 1781 
 1782         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
 1783             uap->path, td);
 1784         if ((error = namei(&nd)) != 0)
 1785                 return (error);
 1786         NDFREE(&nd, NDF_ONLY_PNBUF);
 1787         error = vn_stat(nd.ni_vp, &sb, td->td_ucred, NOCRED, td);
 1788         vput(nd.ni_vp);
 1789         if (error)
 1790                 return (error);
 1791         cvtnstat(&sb, &nsb);
 1792         error = copyout(&nsb, uap->ub, sizeof (nsb));
 1793         return (error);
 1794 }
 1795 
 1796 /*
 1797  * NetBSD lstat.  Get file status; this version does not follow links.
 1798  */
 1799 #ifndef _SYS_SYSPROTO_H_
 1800 struct lstat_args {
 1801         char    *path;
 1802         struct stat *ub;
 1803 };
 1804 #endif
 1805 /* ARGSUSED */
 1806 int
 1807 nlstat(td, uap)
 1808         struct thread *td;
 1809         register struct nlstat_args /* {
 1810                 char *path;
 1811                 struct nstat *ub;
 1812         } */ *uap;
 1813 {
 1814         int error;
 1815         struct vnode *vp;
 1816         struct stat sb;
 1817         struct nstat nsb;
 1818         struct nameidata nd;
 1819 
 1820         NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
 1821             uap->path, td);
 1822         if ((error = namei(&nd)) != 0)
 1823                 return (error);
 1824         vp = nd.ni_vp;
 1825         NDFREE(&nd, NDF_ONLY_PNBUF);
 1826         error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td);
 1827         vput(vp);
 1828         if (error)
 1829                 return (error);
 1830         cvtnstat(&sb, &nsb);
 1831         error = copyout(&nsb, uap->ub, sizeof (nsb));
 1832         return (error);
 1833 }
 1834 
 1835 /*
 1836  * Get configurable pathname variables.
 1837  */
 1838 #ifndef _SYS_SYSPROTO_H_
 1839 struct pathconf_args {
 1840         char    *path;
 1841         int     name;
 1842 };
 1843 #endif
 1844 /* ARGSUSED */
 1845 int
 1846 pathconf(td, uap)
 1847         struct thread *td;
 1848         register struct pathconf_args /* {
 1849                 char *path;
 1850                 int name;
 1851         } */ *uap;
 1852 {
 1853         int error;
 1854         struct nameidata nd;
 1855 
 1856         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
 1857             uap->path, td);
 1858         if ((error = namei(&nd)) != 0)
 1859                 return (error);
 1860         NDFREE(&nd, NDF_ONLY_PNBUF);
 1861 
 1862         /* If asynchronous I/O is available, it works for all files. */
 1863         if (uap->name == _PC_ASYNC_IO)
 1864                 td->td_retval[0] = async_io_version;
 1865         else
 1866                 error = VOP_PATHCONF(nd.ni_vp, uap->name, td->td_retval);
 1867         vput(nd.ni_vp);
 1868         return (error);
 1869 }
 1870 
 1871 /*
 1872  * Return target name of a symbolic link.
 1873  */
 1874 #ifndef _SYS_SYSPROTO_H_
 1875 struct readlink_args {
 1876         char    *path;
 1877         char    *buf;
 1878         int     count;
 1879 };
 1880 #endif
 1881 /* ARGSUSED */
 1882 int
 1883 readlink(td, uap)
 1884         struct thread *td;
 1885         register struct readlink_args /* {
 1886                 char *path;
 1887                 char *buf;
 1888                 int count;
 1889         } */ *uap;
 1890 {
 1891 
 1892         return (kern_readlink(td, uap->path, UIO_USERSPACE, uap->buf,
 1893             UIO_USERSPACE, uap->count));
 1894 }
 1895 
 1896 int
 1897 kern_readlink(struct thread *td, char *path, enum uio_seg pathseg, char *buf,
 1898     enum uio_seg bufseg, int count)
 1899 {
 1900         register struct vnode *vp;
 1901         struct iovec aiov;
 1902         struct uio auio;
 1903         int error;
 1904         struct nameidata nd;
 1905 
 1906         NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, pathseg, path, td);
 1907         if ((error = namei(&nd)) != 0)
 1908                 return (error);
 1909         NDFREE(&nd, NDF_ONLY_PNBUF);
 1910         vp = nd.ni_vp;
 1911 #ifdef MAC
 1912         error = mac_check_vnode_readlink(td->td_ucred, vp);
 1913         if (error) {
 1914                 vput(vp);
 1915                 return (error);
 1916         }
 1917 #endif
 1918         if (vp->v_type != VLNK)
 1919                 error = EINVAL;
 1920         else {
 1921                 aiov.iov_base = buf;
 1922                 aiov.iov_len = count;
 1923                 auio.uio_iov = &aiov;
 1924                 auio.uio_iovcnt = 1;
 1925                 auio.uio_offset = 0;
 1926                 auio.uio_rw = UIO_READ;
 1927                 auio.uio_segflg = bufseg;
 1928                 auio.uio_td = td;
 1929                 auio.uio_resid = count;
 1930                 error = VOP_READLINK(vp, &auio, td->td_ucred);
 1931         }
 1932         vput(vp);
 1933         td->td_retval[0] = count - auio.uio_resid;
 1934         return (error);
 1935 }
 1936 
 1937 /*
 1938  * Common implementation code for chflags() and fchflags().
 1939  */
 1940 static int
 1941 setfflags(td, vp, flags)
 1942         struct thread *td;
 1943         struct vnode *vp;
 1944         int flags;
 1945 {
 1946         int error;
 1947         struct mount *mp;
 1948         struct vattr vattr;
 1949 
 1950         /*
 1951          * Prevent non-root users from setting flags on devices.  When
 1952          * a device is reused, users can retain ownership of the device
 1953          * if they are allowed to set flags and programs assume that
 1954          * chown can't fail when done as root.
 1955          */
 1956         if (vp->v_type == VCHR || vp->v_type == VBLK) {
 1957                 error = suser_cred(td->td_ucred, PRISON_ROOT);
 1958                 if (error)
 1959                         return (error);
 1960         }
 1961 
 1962         if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
 1963                 return (error);
 1964         VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
 1965         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
 1966         VATTR_NULL(&vattr);
 1967         vattr.va_flags = flags;
 1968 #ifdef MAC
 1969         error = mac_check_vnode_setflags(td->td_ucred, vp, vattr.va_flags);
 1970         if (error == 0)
 1971 #endif
 1972                 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
 1973         VOP_UNLOCK(vp, 0, td);
 1974         vn_finished_write(mp);
 1975         return (error);
 1976 }
 1977 
 1978 /*
 1979  * Change flags of a file given a path name.
 1980  */
 1981 #ifndef _SYS_SYSPROTO_H_
 1982 struct chflags_args {
 1983         char    *path;
 1984         int     flags;
 1985 };
 1986 #endif
 1987 /* ARGSUSED */
 1988 int
 1989 chflags(td, uap)
 1990         struct thread *td;
 1991         register struct chflags_args /* {
 1992                 char *path;
 1993                 int flags;
 1994         } */ *uap;
 1995 {
 1996         int error;
 1997         struct nameidata nd;
 1998 
 1999         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
 2000         if ((error = namei(&nd)) != 0)
 2001                 return (error);
 2002         NDFREE(&nd, NDF_ONLY_PNBUF);
 2003         error = setfflags(td, nd.ni_vp, uap->flags);
 2004         vrele(nd.ni_vp);
 2005         return error;
 2006 }
 2007 
 2008 /*
 2009  * Same as chflags() but doesn't follow symlinks.
 2010  */
 2011 int
 2012 lchflags(td, uap)
 2013         struct thread *td;
 2014         register struct lchflags_args /* {
 2015                 char *path;
 2016                 int flags;
 2017         } */ *uap;
 2018 {
 2019         int error;
 2020         struct nameidata nd;
 2021 
 2022         NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td);
 2023         if ((error = namei(&nd)) != 0)
 2024                 return (error);
 2025         NDFREE(&nd, NDF_ONLY_PNBUF);
 2026         error = setfflags(td, nd.ni_vp, uap->flags);
 2027         vrele(nd.ni_vp);
 2028         return error;
 2029 }
 2030 
 2031 /*
 2032  * Change flags of a file given a file descriptor.
 2033  */
 2034 #ifndef _SYS_SYSPROTO_H_
 2035 struct fchflags_args {
 2036         int     fd;
 2037         int     flags;
 2038 };
 2039 #endif
 2040 /* ARGSUSED */
 2041 int
 2042 fchflags(td, uap)
 2043         struct thread *td;
 2044         register struct fchflags_args /* {
 2045                 int fd;
 2046                 int flags;
 2047         } */ *uap;
 2048 {
 2049         struct file *fp;
 2050         int error;
 2051 
 2052         if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
 2053                 return (error);
 2054         error = setfflags(td, fp->f_data, uap->flags);
 2055         fdrop(fp, td);
 2056         return (error);
 2057 }
 2058 
 2059 /*
 2060  * Common implementation code for chmod(), lchmod() and fchmod().
 2061  */
 2062 static int
 2063 setfmode(td, vp, mode)
 2064         struct thread *td;
 2065         struct vnode *vp;
 2066         int mode;
 2067 {
 2068         int error;
 2069         struct mount *mp;
 2070         struct vattr vattr;
 2071 
 2072         if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
 2073                 return (error);
 2074         VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
 2075         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
 2076         VATTR_NULL(&vattr);
 2077         vattr.va_mode = mode & ALLPERMS;
 2078 #ifdef MAC
 2079         error = mac_check_vnode_setmode(td->td_ucred, vp, vattr.va_mode);
 2080         if (error == 0)
 2081 #endif
 2082                 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
 2083         VOP_UNLOCK(vp, 0, td);
 2084         vn_finished_write(mp);
 2085         return error;
 2086 }
 2087 
 2088 /*
 2089  * Change mode of a file given path name.
 2090  */
 2091 #ifndef _SYS_SYSPROTO_H_
 2092 struct chmod_args {
 2093         char    *path;
 2094         int     mode;
 2095 };
 2096 #endif
 2097 /* ARGSUSED */
 2098 int
 2099 chmod(td, uap)
 2100         struct thread *td;
 2101         register struct chmod_args /* {
 2102                 char *path;
 2103                 int mode;
 2104         } */ *uap;
 2105 {
 2106 
 2107         return (kern_chmod(td, uap->path, UIO_USERSPACE, uap->mode));
 2108 }
 2109 
 2110 int
 2111 kern_chmod(struct thread *td, char *path, enum uio_seg pathseg, int mode)
 2112 {
 2113         int error;
 2114         struct nameidata nd;
 2115 
 2116         NDINIT(&nd, LOOKUP, FOLLOW, pathseg, path, td);
 2117         if ((error = namei(&nd)) != 0)
 2118                 return (error);
 2119         NDFREE(&nd, NDF_ONLY_PNBUF);
 2120         error = setfmode(td, nd.ni_vp, mode);
 2121         vrele(nd.ni_vp);
 2122         return error;
 2123 }
 2124 
 2125 /*
 2126  * Change mode of a file given path name (don't follow links.)
 2127  */
 2128 #ifndef _SYS_SYSPROTO_H_
 2129 struct lchmod_args {
 2130         char    *path;
 2131         int     mode;
 2132 };
 2133 #endif
 2134 /* ARGSUSED */
 2135 int
 2136 lchmod(td, uap)
 2137         struct thread *td;
 2138         register struct lchmod_args /* {
 2139                 char *path;
 2140                 int mode;
 2141         } */ *uap;
 2142 {
 2143         int error;
 2144         struct nameidata nd;
 2145 
 2146         NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td);
 2147         if ((error = namei(&nd)) != 0)
 2148                 return (error);
 2149         NDFREE(&nd, NDF_ONLY_PNBUF);
 2150         error = setfmode(td, nd.ni_vp, uap->mode);
 2151         vrele(nd.ni_vp);
 2152         return error;
 2153 }
 2154 
 2155 /*
 2156  * Change mode of a file given a file descriptor.
 2157  */
 2158 #ifndef _SYS_SYSPROTO_H_
 2159 struct fchmod_args {
 2160         int     fd;
 2161         int     mode;
 2162 };
 2163 #endif
 2164 /* ARGSUSED */
 2165 int
 2166 fchmod(td, uap)
 2167         struct thread *td;
 2168         register struct fchmod_args /* {
 2169                 int fd;
 2170                 int mode;
 2171         } */ *uap;
 2172 {
 2173         struct file *fp;
 2174         struct vnode *vp;
 2175         int error;
 2176 
 2177         if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
 2178                 return (error);
 2179         vp = fp->f_data;
 2180         error = setfmode(td, fp->f_data, uap->mode);
 2181         fdrop(fp, td);
 2182         return (error);
 2183 }
 2184 
 2185 /*
 2186  * Common implementation for chown(), lchown(), and fchown()
 2187  */
 2188 static int
 2189 setfown(td, vp, uid, gid)
 2190         struct thread *td;
 2191         struct vnode *vp;
 2192         uid_t uid;
 2193         gid_t gid;
 2194 {
 2195         int error;
 2196         struct mount *mp;
 2197         struct vattr vattr;
 2198 
 2199         if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
 2200                 return (error);
 2201         VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
 2202         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
 2203         VATTR_NULL(&vattr);
 2204         vattr.va_uid = uid;
 2205         vattr.va_gid = gid;
 2206 #ifdef MAC
 2207         error = mac_check_vnode_setowner(td->td_ucred, vp, vattr.va_uid,
 2208             vattr.va_gid);
 2209         if (error == 0)
 2210 #endif
 2211                 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
 2212         VOP_UNLOCK(vp, 0, td);
 2213         vn_finished_write(mp);
 2214         return error;
 2215 }
 2216 
 2217 /*
 2218  * Set ownership given a path name.
 2219  */
 2220 #ifndef _SYS_SYSPROTO_H_
 2221 struct chown_args {
 2222         char    *path;
 2223         int     uid;
 2224         int     gid;
 2225 };
 2226 #endif
 2227 /* ARGSUSED */
 2228 int
 2229 chown(td, uap)
 2230         struct thread *td;
 2231         register struct chown_args /* {
 2232                 char *path;
 2233                 int uid;
 2234                 int gid;
 2235         } */ *uap;
 2236 {
 2237 
 2238         return (kern_chown(td, uap->path, UIO_USERSPACE, uap->uid, uap->gid));
 2239 }
 2240 
 2241 int
 2242 kern_chown(struct thread *td, char *path, enum uio_seg pathseg, int uid,
 2243     int gid)
 2244 {
 2245         int error;
 2246         struct nameidata nd;
 2247 
 2248         NDINIT(&nd, LOOKUP, FOLLOW, pathseg, path, td);
 2249         if ((error = namei(&nd)) != 0)
 2250                 return (error);
 2251         NDFREE(&nd, NDF_ONLY_PNBUF);
 2252         error = setfown(td, nd.ni_vp, uid, gid);
 2253         vrele(nd.ni_vp);
 2254         return (error);
 2255 }
 2256 
 2257 /*
 2258  * Set ownership given a path name, do not cross symlinks.
 2259  */
 2260 #ifndef _SYS_SYSPROTO_H_
 2261 struct lchown_args {
 2262         char    *path;
 2263         int     uid;
 2264         int     gid;
 2265 };
 2266 #endif
 2267 /* ARGSUSED */
 2268 int
 2269 lchown(td, uap)
 2270         struct thread *td;
 2271         register struct lchown_args /* {
 2272                 char *path;
 2273                 int uid;
 2274                 int gid;
 2275         } */ *uap;
 2276 {
 2277 
 2278         return (kern_lchown(td, uap->path, UIO_USERSPACE, uap->uid, uap->gid));
 2279 }
 2280 
 2281 int
 2282 kern_lchown(struct thread *td, char *path, enum uio_seg pathseg, int uid,
 2283     int gid)
 2284 {
 2285         int error;
 2286         struct nameidata nd;
 2287 
 2288         NDINIT(&nd, LOOKUP, NOFOLLOW, pathseg, path, td);
 2289         if ((error = namei(&nd)) != 0)
 2290                 return (error);
 2291         NDFREE(&nd, NDF_ONLY_PNBUF);
 2292         error = setfown(td, nd.ni_vp, uid, gid);
 2293         vrele(nd.ni_vp);
 2294         return (error);
 2295 }
 2296 
 2297 /*
 2298  * Set ownership given a file descriptor.
 2299  */
 2300 #ifndef _SYS_SYSPROTO_H_
 2301 struct fchown_args {
 2302         int     fd;
 2303         int     uid;
 2304         int     gid;
 2305 };
 2306 #endif
 2307 /* ARGSUSED */
 2308 int
 2309 fchown(td, uap)
 2310         struct thread *td;
 2311         register struct fchown_args /* {
 2312                 int fd;
 2313                 int uid;
 2314                 int gid;
 2315         } */ *uap;
 2316 {
 2317         struct file *fp;
 2318         struct vnode *vp;
 2319         int error;
 2320 
 2321         if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
 2322                 return (error);
 2323         vp = fp->f_data;
 2324         error = setfown(td, fp->f_data, uap->uid, uap->gid);
 2325         fdrop(fp, td);
 2326         return (error);
 2327 }
 2328 
 2329 /*
 2330  * Common implementation code for utimes(), lutimes(), and futimes().
 2331  */
 2332 static int
 2333 getutimes(usrtvp, tvpseg, tsp)
 2334         const struct timeval *usrtvp;
 2335         enum uio_seg tvpseg;
 2336         struct timespec *tsp;
 2337 {
 2338         struct timeval tv[2];
 2339         const struct timeval *tvp;
 2340         int error;
 2341 
 2342         if (usrtvp == NULL) {
 2343                 microtime(&tv[0]);
 2344                 TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]);
 2345                 tsp[1] = tsp[0];
 2346         } else {
 2347                 if (tvpseg == UIO_SYSSPACE) {
 2348                         tvp = usrtvp;
 2349                 } else {
 2350                         if ((error = copyin(usrtvp, tv, sizeof(tv))) != 0)
 2351                                 return (error);
 2352                         tvp = tv;
 2353                 }
 2354 
 2355                 TIMEVAL_TO_TIMESPEC(&tvp[0], &tsp[0]);
 2356                 TIMEVAL_TO_TIMESPEC(&tvp[1], &tsp[1]);
 2357         }
 2358         return 0;
 2359 }
 2360 
 2361 /*
 2362  * Common implementation code for utimes(), lutimes(), and futimes().
 2363  */
 2364 static int
 2365 setutimes(td, vp, ts, numtimes, nullflag)
 2366         struct thread *td;
 2367         struct vnode *vp;
 2368         const struct timespec *ts;
 2369         int numtimes;
 2370         int nullflag;
 2371 {
 2372         int error, setbirthtime;
 2373         struct mount *mp;
 2374         struct vattr vattr;
 2375 
 2376         if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
 2377                 return (error);
 2378         VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
 2379         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
 2380         setbirthtime = 0;
 2381         if (numtimes < 3 && VOP_GETATTR(vp, &vattr, td->td_ucred, td) == 0 &&
 2382             timespeccmp(&ts[1], &vattr.va_birthtime, < ))
 2383                 setbirthtime = 1;
 2384         VATTR_NULL(&vattr);
 2385         vattr.va_atime = ts[0];
 2386         vattr.va_mtime = ts[1];
 2387         if (setbirthtime)
 2388                 vattr.va_birthtime = ts[1];
 2389         if (numtimes > 2)
 2390                 vattr.va_birthtime = ts[2];
 2391         if (nullflag)
 2392                 vattr.va_vaflags |= VA_UTIMES_NULL;
 2393 #ifdef MAC
 2394         error = mac_check_vnode_setutimes(td->td_ucred, vp, vattr.va_atime,
 2395             vattr.va_mtime);
 2396 #endif
 2397         if (error == 0)
 2398                 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
 2399         VOP_UNLOCK(vp, 0, td);
 2400         vn_finished_write(mp);
 2401         return error;
 2402 }
 2403 
 2404 /*
 2405  * Set the access and modification times of a file.
 2406  */
 2407 #ifndef _SYS_SYSPROTO_H_
 2408 struct utimes_args {
 2409         char    *path;
 2410         struct  timeval *tptr;
 2411 };
 2412 #endif
 2413 /* ARGSUSED */
 2414 int
 2415 utimes(td, uap)
 2416         struct thread *td;
 2417         register struct utimes_args /* {
 2418                 char *path;
 2419                 struct timeval *tptr;
 2420         } */ *uap;
 2421 {
 2422 
 2423         return (kern_utimes(td, uap->path, UIO_USERSPACE, uap->tptr,
 2424             UIO_USERSPACE));
 2425 }
 2426 
 2427 int
 2428 kern_utimes(struct thread *td, char *path, enum uio_seg pathseg,
 2429     struct timeval *tptr, enum uio_seg tptrseg)
 2430 {
 2431         struct timespec ts[2];
 2432         int error;
 2433         struct nameidata nd;
 2434 
 2435         if ((error = getutimes(tptr, tptrseg, ts)) != 0)
 2436                 return (error);
 2437         NDINIT(&nd, LOOKUP, FOLLOW, pathseg, path, td);
 2438         if ((error = namei(&nd)) != 0)
 2439                 return (error);
 2440         NDFREE(&nd, NDF_ONLY_PNBUF);
 2441         error = setutimes(td, nd.ni_vp, ts, 2, tptr == NULL);
 2442         vrele(nd.ni_vp);
 2443         return (error);
 2444 }
 2445 
 2446 /*
 2447  * Set the access and modification times of a file.
 2448  */
 2449 #ifndef _SYS_SYSPROTO_H_
 2450 struct lutimes_args {
 2451         char    *path;
 2452         struct  timeval *tptr;
 2453 };
 2454 #endif
 2455 /* ARGSUSED */
 2456 int
 2457 lutimes(td, uap)
 2458         struct thread *td;
 2459         register struct lutimes_args /* {
 2460                 char *path;
 2461                 struct timeval *tptr;
 2462         } */ *uap;
 2463 {
 2464 
 2465         return (kern_lutimes(td, uap->path, UIO_USERSPACE, uap->tptr,
 2466             UIO_USERSPACE));
 2467 }
 2468 
 2469 int
 2470 kern_lutimes(struct thread *td, char *path, enum uio_seg pathseg,
 2471     struct timeval *tptr, enum uio_seg tptrseg)
 2472 {
 2473         struct timespec ts[2];
 2474         int error;
 2475         struct nameidata nd;
 2476 
 2477         if ((error = getutimes(tptr, tptrseg, ts)) != 0)
 2478                 return (error);
 2479         NDINIT(&nd, LOOKUP, NOFOLLOW, pathseg, path, td);
 2480         if ((error = namei(&nd)) != 0)
 2481                 return (error);
 2482         NDFREE(&nd, NDF_ONLY_PNBUF);
 2483         error = setutimes(td, nd.ni_vp, ts, 2, tptr == NULL);
 2484         vrele(nd.ni_vp);
 2485         return (error);
 2486 }
 2487 
 2488 /*
 2489  * Set the access and modification times of a file.
 2490  */
 2491 #ifndef _SYS_SYSPROTO_H_
 2492 struct futimes_args {
 2493         int     fd;
 2494         struct  timeval *tptr;
 2495 };
 2496 #endif
 2497 /* ARGSUSED */
 2498 int
 2499 futimes(td, uap)
 2500         struct thread *td;
 2501         register struct futimes_args /* {
 2502                 int  fd;
 2503                 struct timeval *tptr;
 2504         } */ *uap;
 2505 {
 2506 
 2507         return (kern_futimes(td, uap->fd, uap->tptr, UIO_USERSPACE));
 2508 }
 2509 
 2510 int
 2511 kern_futimes(struct thread *td, int fd, struct timeval *tptr,
 2512     enum uio_seg tptrseg)
 2513 {
 2514         struct timespec ts[2];
 2515         struct file *fp;
 2516         int error;
 2517 
 2518         if ((error = getutimes(tptr, tptrseg, ts)) != 0)
 2519                 return (error);
 2520         if ((error = getvnode(td->td_proc->p_fd, fd, &fp)) != 0)
 2521                 return (error);
 2522         error = setutimes(td, fp->f_data, ts, 2, tptr == NULL);
 2523         fdrop(fp, td);
 2524         return (error);
 2525 }
 2526 
 2527 /*
 2528  * Truncate a file given its path name.
 2529  */
 2530 #ifndef _SYS_SYSPROTO_H_
 2531 struct truncate_args {
 2532         char    *path;
 2533         int     pad;
 2534         off_t   length;
 2535 };
 2536 #endif
 2537 /* ARGSUSED */
 2538 int
 2539 truncate(td, uap)
 2540         struct thread *td;
 2541         register struct truncate_args /* {
 2542                 char *path;
 2543                 int pad;
 2544                 off_t length;
 2545         } */ *uap;
 2546 {
 2547 
 2548         return (kern_truncate(td, uap->path, UIO_USERSPACE, uap->length));
 2549 }
 2550 
 2551 int
 2552 kern_truncate(struct thread *td, char *path, enum uio_seg pathseg, off_t length)
 2553 {
 2554         struct mount *mp;
 2555         struct vnode *vp;
 2556         struct vattr vattr;
 2557         int error;
 2558         struct nameidata nd;
 2559 
 2560         if (length < 0)
 2561                 return(EINVAL);
 2562         NDINIT(&nd, LOOKUP, FOLLOW, pathseg, path, td);
 2563         if ((error = namei(&nd)) != 0)
 2564                 return (error);
 2565         vp = nd.ni_vp;
 2566         if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) {
 2567                 vrele(vp);
 2568                 return (error);
 2569         }
 2570         NDFREE(&nd, NDF_ONLY_PNBUF);
 2571         VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
 2572         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
 2573         if (vp->v_type == VDIR)
 2574                 error = EISDIR;
 2575 #ifdef MAC
 2576         else if ((error = mac_check_vnode_write(td->td_ucred, NOCRED, vp))) {
 2577         }
 2578 #endif
 2579         else if ((error = vn_writechk(vp)) == 0 &&
 2580             (error = VOP_ACCESS(vp, VWRITE, td->td_ucred, td)) == 0) {
 2581                 VATTR_NULL(&vattr);
 2582                 vattr.va_size = length;
 2583                 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
 2584         }
 2585         vput(vp);
 2586         vn_finished_write(mp);
 2587         return (error);
 2588 }
 2589 
 2590 /*
 2591  * Truncate a file given a file descriptor.
 2592  */
 2593 #ifndef _SYS_SYSPROTO_H_
 2594 struct ftruncate_args {
 2595         int     fd;
 2596         int     pad;
 2597         off_t   length;
 2598 };
 2599 #endif
 2600 /* ARGSUSED */
 2601 int
 2602 ftruncate(td, uap)
 2603         struct thread *td;
 2604         register struct ftruncate_args /* {
 2605                 int fd;
 2606                 int pad;
 2607                 off_t length;
 2608         } */ *uap;
 2609 {
 2610         struct mount *mp;
 2611         struct vattr vattr;
 2612         struct vnode *vp;
 2613         struct file *fp;
 2614         int error;
 2615 
 2616         if (uap->length < 0)
 2617                 return(EINVAL);
 2618         if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
 2619                 return (error);
 2620         if ((fp->f_flag & FWRITE) == 0) {
 2621                 fdrop(fp, td);
 2622                 return (EINVAL);
 2623         }
 2624         vp = fp->f_data;
 2625         if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) {
 2626                 fdrop(fp, td);
 2627                 return (error);
 2628         }
 2629         VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
 2630         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
 2631         if (vp->v_type == VDIR)
 2632                 error = EISDIR;
 2633 #ifdef MAC
 2634         else if ((error = mac_check_vnode_write(td->td_ucred, fp->f_cred,
 2635             vp))) {
 2636         }
 2637 #endif
 2638         else if ((error = vn_writechk(vp)) == 0) {
 2639                 VATTR_NULL(&vattr);
 2640                 vattr.va_size = uap->length;
 2641                 error = VOP_SETATTR(vp, &vattr, fp->f_cred, td);
 2642         }
 2643         VOP_UNLOCK(vp, 0, td);
 2644         vn_finished_write(mp);
 2645         fdrop(fp, td);
 2646         return (error);
 2647 }
 2648 
 2649 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
 2650 /*
 2651  * Truncate a file given its path name.
 2652  */
 2653 #ifndef _SYS_SYSPROTO_H_
 2654 struct otruncate_args {
 2655         char    *path;
 2656         long    length;
 2657 };
 2658 #endif
 2659 /* ARGSUSED */
 2660 int
 2661 otruncate(td, uap)
 2662         struct thread *td;
 2663         register struct otruncate_args /* {
 2664                 char *path;
 2665                 long length;
 2666         } */ *uap;
 2667 {
 2668         struct truncate_args /* {
 2669                 char *path;
 2670                 int pad;
 2671                 off_t length;
 2672         } */ nuap;
 2673 
 2674         nuap.path = uap->path;
 2675         nuap.length = uap->length;
 2676         return (truncate(td, &nuap));
 2677 }
 2678 
 2679 /*
 2680  * Truncate a file given a file descriptor.
 2681  */
 2682 #ifndef _SYS_SYSPROTO_H_
 2683 struct oftruncate_args {
 2684         int     fd;
 2685         long    length;
 2686 };
 2687 #endif
 2688 /* ARGSUSED */
 2689 int
 2690 oftruncate(td, uap)
 2691         struct thread *td;
 2692         register struct oftruncate_args /* {
 2693                 int fd;
 2694                 long length;
 2695         } */ *uap;
 2696 {
 2697         struct ftruncate_args /* {
 2698                 int fd;
 2699                 int pad;
 2700                 off_t length;
 2701         } */ nuap;
 2702 
 2703         nuap.fd = uap->fd;
 2704         nuap.length = uap->length;
 2705         return (ftruncate(td, &nuap));
 2706 }
 2707 #endif /* COMPAT_43 || COMPAT_SUNOS */
 2708 
 2709 /*
 2710  * Sync an open file.
 2711  */
 2712 #ifndef _SYS_SYSPROTO_H_
 2713 struct fsync_args {
 2714         int     fd;
 2715 };
 2716 #endif
 2717 /* ARGSUSED */
 2718 int
 2719 fsync(td, uap)
 2720         struct thread *td;
 2721         struct fsync_args /* {
 2722                 int fd;
 2723         } */ *uap;
 2724 {
 2725         struct vnode *vp;
 2726         struct mount *mp;
 2727         struct file *fp;
 2728         vm_object_t obj;
 2729         int error;
 2730 
 2731         GIANT_REQUIRED;
 2732 
 2733         if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
 2734                 return (error);
 2735         vp = fp->f_data;
 2736         if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) {
 2737                 fdrop(fp, td);
 2738                 return (error);
 2739         }
 2740         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
 2741         if (VOP_GETVOBJECT(vp, &obj) == 0) {
 2742                 VM_OBJECT_LOCK(obj);
 2743                 vm_object_page_clean(obj, 0, 0, 0);
 2744                 VM_OBJECT_UNLOCK(obj);
 2745         }
 2746         error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, td);
 2747         if (error == 0 && vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP)
 2748             && softdep_fsync_hook != NULL)
 2749                 error = (*softdep_fsync_hook)(vp);
 2750 
 2751         VOP_UNLOCK(vp, 0, td);
 2752         vn_finished_write(mp);
 2753         fdrop(fp, td);
 2754         return (error);
 2755 }
 2756 
 2757 /*
 2758  * Rename files.  Source and destination must either both be directories,
 2759  * or both not be directories.  If target is a directory, it must be empty.
 2760  */
 2761 #ifndef _SYS_SYSPROTO_H_
 2762 struct rename_args {
 2763         char    *from;
 2764         char    *to;
 2765 };
 2766 #endif
 2767 /* ARGSUSED */
 2768 int
 2769 rename(td, uap)
 2770         struct thread *td;
 2771         register struct rename_args /* {
 2772                 char *from;
 2773                 char *to;
 2774         } */ *uap;
 2775 {
 2776 
 2777         return (kern_rename(td, uap->from, uap->to, UIO_USERSPACE));
 2778 }
 2779 
 2780 int
 2781 kern_rename(struct thread *td, char *from, char *to, enum uio_seg pathseg)
 2782 {
 2783         struct mount *mp = NULL;
 2784         struct vnode *tvp, *fvp, *tdvp;
 2785         struct nameidata fromnd, tond;
 2786         int error;
 2787 
 2788         bwillwrite();
 2789 #ifdef MAC
 2790         NDINIT(&fromnd, DELETE, LOCKPARENT | LOCKLEAF | SAVESTART, pathseg,
 2791             from, td);
 2792 #else
 2793         NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, pathseg, from, td);
 2794 #endif
 2795         if ((error = namei(&fromnd)) != 0)
 2796                 return (error);
 2797 #ifdef MAC
 2798         error = mac_check_vnode_rename_from(td->td_ucred, fromnd.ni_dvp,
 2799             fromnd.ni_vp, &fromnd.ni_cnd);
 2800         VOP_UNLOCK(fromnd.ni_dvp, 0, td);
 2801         VOP_UNLOCK(fromnd.ni_vp, 0, td);
 2802 #endif
 2803         fvp = fromnd.ni_vp;
 2804         if (error == 0)
 2805                 error = vn_start_write(fvp, &mp, V_WAIT | PCATCH);
 2806         if (error != 0) {
 2807                 NDFREE(&fromnd, NDF_ONLY_PNBUF);
 2808                 vrele(fromnd.ni_dvp);
 2809                 vrele(fvp);
 2810                 goto out1;
 2811         }
 2812         NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART |
 2813             NOOBJ, pathseg, to, td);
 2814         if (fromnd.ni_vp->v_type == VDIR)
 2815                 tond.ni_cnd.cn_flags |= WILLBEDIR;
 2816         if ((error = namei(&tond)) != 0) {
 2817                 /* Translate error code for rename("dir1", "dir2/."). */
 2818                 if (error == EISDIR && fvp->v_type == VDIR)
 2819                         error = EINVAL;
 2820                 NDFREE(&fromnd, NDF_ONLY_PNBUF);
 2821                 vrele(fromnd.ni_dvp);
 2822                 vrele(fvp);
 2823                 goto out1;
 2824         }
 2825         tdvp = tond.ni_dvp;
 2826         tvp = tond.ni_vp;
 2827         if (tvp != NULL) {
 2828                 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
 2829                         error = ENOTDIR;
 2830                         goto out;
 2831                 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
 2832                         error = EISDIR;
 2833                         goto out;
 2834                 }
 2835         }
 2836         if (fvp == tdvp)
 2837                 error = EINVAL;
 2838         /*
 2839          * If the source is the same as the destination (that is, if they
 2840          * are links to the same vnode), then there is nothing to do.
 2841          */
 2842         if (fvp == tvp)
 2843                 error = -1;
 2844 #ifdef MAC
 2845         else
 2846                 error = mac_check_vnode_rename_to(td->td_ucred, tdvp,
 2847                     tond.ni_vp, fromnd.ni_dvp == tdvp, &tond.ni_cnd);
 2848 #endif
 2849 out:
 2850         if (!error) {
 2851                 VOP_LEASE(tdvp, td, td->td_ucred, LEASE_WRITE);
 2852                 if (fromnd.ni_dvp != tdvp) {
 2853                         VOP_LEASE(fromnd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
 2854                 }
 2855                 if (tvp) {
 2856                         VOP_LEASE(tvp, td, td->td_ucred, LEASE_WRITE);
 2857                 }
 2858                 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
 2859                                    tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
 2860                 NDFREE(&fromnd, NDF_ONLY_PNBUF);
 2861                 NDFREE(&tond, NDF_ONLY_PNBUF);
 2862         } else {
 2863                 NDFREE(&fromnd, NDF_ONLY_PNBUF);
 2864                 NDFREE(&tond, NDF_ONLY_PNBUF);
 2865                 if (tdvp == tvp)
 2866                         vrele(tdvp);
 2867                 else
 2868                         vput(tdvp);
 2869                 if (tvp)
 2870                         vput(tvp);
 2871                 vrele(fromnd.ni_dvp);
 2872                 vrele(fvp);
 2873         }
 2874         vrele(tond.ni_startdir);
 2875         ASSERT_VOP_UNLOCKED(fromnd.ni_dvp, "rename");
 2876         ASSERT_VOP_UNLOCKED(fromnd.ni_vp, "rename");
 2877         ASSERT_VOP_UNLOCKED(tond.ni_dvp, "rename");
 2878         ASSERT_VOP_UNLOCKED(tond.ni_vp, "rename");
 2879 out1:
 2880         vn_finished_write(mp);
 2881         if (fromnd.ni_startdir)
 2882                 vrele(fromnd.ni_startdir);
 2883         if (error == -1)
 2884                 return (0);
 2885         return (error);
 2886 }
 2887 
 2888 /*
 2889  * Make a directory file.
 2890  */
 2891 #ifndef _SYS_SYSPROTO_H_
 2892 struct mkdir_args {
 2893         char    *path;
 2894         int     mode;
 2895 };
 2896 #endif
 2897 /* ARGSUSED */
 2898 int
 2899 mkdir(td, uap)
 2900         struct thread *td;
 2901         register struct mkdir_args /* {
 2902                 char *path;
 2903                 int mode;
 2904         } */ *uap;
 2905 {
 2906 
 2907         return (kern_mkdir(td, uap->path, UIO_USERSPACE, uap->mode));
 2908 }
 2909 
 2910 int
 2911 kern_mkdir(struct thread *td, char *path, enum uio_seg segflg, int mode)
 2912 {
 2913         struct mount *mp;
 2914         struct vnode *vp;
 2915         struct vattr vattr;
 2916         int error;
 2917         struct nameidata nd;
 2918 
 2919 restart:
 2920         bwillwrite();
 2921         NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME, segflg, path, td);
 2922         nd.ni_cnd.cn_flags |= WILLBEDIR;
 2923         if ((error = namei(&nd)) != 0)
 2924                 return (error);
 2925         vp = nd.ni_vp;
 2926         if (vp != NULL) {
 2927                 NDFREE(&nd, NDF_ONLY_PNBUF);
 2928                 vrele(vp);
 2929                 /*
 2930                  * XXX namei called with LOCKPARENT but not LOCKLEAF has
 2931                  * the strange behaviour of leaving the vnode unlocked
 2932                  * if the target is the same vnode as the parent.
 2933                  */
 2934                 if (vp == nd.ni_dvp)
 2935                         vrele(nd.ni_dvp);
 2936                 else
 2937                         vput(nd.ni_dvp);
 2938                 return (EEXIST);
 2939         }
 2940         if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
 2941                 NDFREE(&nd, NDF_ONLY_PNBUF);
 2942                 vput(nd.ni_dvp);
 2943                 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
 2944                         return (error);
 2945                 goto restart;
 2946         }
 2947         VATTR_NULL(&vattr);
 2948         vattr.va_type = VDIR;
 2949         FILEDESC_LOCK(td->td_proc->p_fd);
 2950         vattr.va_mode = (mode & ACCESSPERMS) &~ td->td_proc->p_fd->fd_cmask;
 2951         FILEDESC_UNLOCK(td->td_proc->p_fd);
 2952 #ifdef MAC
 2953         error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
 2954             &vattr);
 2955         if (error)
 2956                 goto out;
 2957 #endif
 2958         VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
 2959         error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
 2960 #ifdef MAC
 2961 out:
 2962 #endif
 2963         NDFREE(&nd, NDF_ONLY_PNBUF);
 2964         vput(nd.ni_dvp);
 2965         if (!error)
 2966                 vput(nd.ni_vp);
 2967         vn_finished_write(mp);
 2968         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mkdir");
 2969         ASSERT_VOP_UNLOCKED(nd.ni_vp, "mkdir");
 2970         return (error);
 2971 }
 2972 
 2973 /*
 2974  * Remove a directory file.
 2975  */
 2976 #ifndef _SYS_SYSPROTO_H_
 2977 struct rmdir_args {
 2978         char    *path;
 2979 };
 2980 #endif
 2981 /* ARGSUSED */
 2982 int
 2983 rmdir(td, uap)
 2984         struct thread *td;
 2985         struct rmdir_args /* {
 2986                 char *path;
 2987         } */ *uap;
 2988 {
 2989 
 2990         return (kern_rmdir(td, uap->path, UIO_USERSPACE));
 2991 }
 2992 
 2993 int
 2994 kern_rmdir(struct thread *td, char *path, enum uio_seg pathseg)
 2995 {
 2996         struct mount *mp;
 2997         struct vnode *vp;
 2998         int error;
 2999         struct nameidata nd;
 3000 
 3001 restart:
 3002         bwillwrite();
 3003         NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, pathseg, path, td);
 3004         if ((error = namei(&nd)) != 0)
 3005                 return (error);
 3006         vp = nd.ni_vp;
 3007         if (vp->v_type != VDIR) {
 3008                 error = ENOTDIR;
 3009                 goto out;
 3010         }
 3011         /*
 3012          * No rmdir "." please.
 3013          */
 3014         if (nd.ni_dvp == vp) {
 3015                 error = EINVAL;
 3016                 goto out;
 3017         }
 3018         /*
 3019          * The root of a mounted filesystem cannot be deleted.
 3020          */
 3021         if (vp->v_vflag & VV_ROOT) {
 3022                 error = EBUSY;
 3023                 goto out;
 3024         }
 3025 #ifdef MAC
 3026         error = mac_check_vnode_delete(td->td_ucred, nd.ni_dvp, vp,
 3027             &nd.ni_cnd);
 3028         if (error)
 3029                 goto out;
 3030 #endif
 3031         if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
 3032                 NDFREE(&nd, NDF_ONLY_PNBUF);
 3033                 if (nd.ni_dvp == vp)
 3034                         vrele(nd.ni_dvp);
 3035                 else
 3036                         vput(nd.ni_dvp);
 3037                 vput(vp);
 3038                 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
 3039                         return (error);
 3040                 goto restart;
 3041         }
 3042         VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
 3043         VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
 3044         error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
 3045         vn_finished_write(mp);
 3046 out:
 3047         NDFREE(&nd, NDF_ONLY_PNBUF);
 3048         if (nd.ni_dvp == vp)
 3049                 vrele(nd.ni_dvp);
 3050         else
 3051                 vput(nd.ni_dvp);
 3052         vput(vp);
 3053         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "rmdir");
 3054         ASSERT_VOP_UNLOCKED(nd.ni_vp, "rmdir");
 3055         return (error);
 3056 }
 3057 
 3058 #ifdef COMPAT_43
 3059 /*
 3060  * Read a block of directory entries in a filesystem independent format.
 3061  */
 3062 #ifndef _SYS_SYSPROTO_H_
 3063 struct ogetdirentries_args {
 3064         int     fd;
 3065         char    *buf;
 3066         u_int   count;
 3067         long    *basep;
 3068 };
 3069 #endif
 3070 int
 3071 ogetdirentries(td, uap)
 3072         struct thread *td;
 3073         register struct ogetdirentries_args /* {
 3074                 int fd;
 3075                 char *buf;
 3076                 u_int count;
 3077                 long *basep;
 3078         } */ *uap;
 3079 {
 3080         struct vnode *vp;
 3081         struct file *fp;
 3082         struct uio auio, kuio;
 3083         struct iovec aiov, kiov;
 3084         struct dirent *dp, *edp;
 3085         caddr_t dirbuf;
 3086         int error, eofflag, readcnt;
 3087         long loff;
 3088 
 3089         /* XXX arbitrary sanity limit on `count'. */
 3090         if (uap->count > 64 * 1024)
 3091                 return (EINVAL);
 3092         if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
 3093                 return (error);
 3094         if ((fp->f_flag & FREAD) == 0) {
 3095                 fdrop(fp, td);
 3096                 return (EBADF);
 3097         }
 3098         vp = fp->f_data;
 3099 unionread:
 3100         if (vp->v_type != VDIR) {
 3101                 fdrop(fp, td);
 3102                 return (EINVAL);
 3103         }
 3104         aiov.iov_base = uap->buf;
 3105         aiov.iov_len = uap->count;
 3106         auio.uio_iov = &aiov;
 3107         auio.uio_iovcnt = 1;
 3108         auio.uio_rw = UIO_READ;
 3109         auio.uio_segflg = UIO_USERSPACE;
 3110         auio.uio_td = td;
 3111         auio.uio_resid = uap->count;
 3112         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
 3113         loff = auio.uio_offset = fp->f_offset;
 3114 #ifdef MAC
 3115         error = mac_check_vnode_readdir(td->td_ucred, vp);
 3116         if (error) {
 3117                 VOP_UNLOCK(vp, 0, td);
 3118                 fdrop(fp, td);
 3119                 return (error);
 3120         }
 3121 #endif
 3122 #       if (BYTE_ORDER != LITTLE_ENDIAN)
 3123                 if (vp->v_mount->mnt_maxsymlinklen <= 0) {
 3124                         error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
 3125                             NULL, NULL);
 3126                         fp->f_offset = auio.uio_offset;
 3127                 } else
 3128 #       endif
 3129         {
 3130                 kuio = auio;
 3131                 kuio.uio_iov = &kiov;
 3132                 kuio.uio_segflg = UIO_SYSSPACE;
 3133                 kiov.iov_len = uap->count;
 3134                 MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK);
 3135                 kiov.iov_base = dirbuf;
 3136                 error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag,
 3137                             NULL, NULL);
 3138                 fp->f_offset = kuio.uio_offset;
 3139                 if (error == 0) {
 3140                         readcnt = uap->count - kuio.uio_resid;
 3141                         edp = (struct dirent *)&dirbuf[readcnt];
 3142                         for (dp = (struct dirent *)dirbuf; dp < edp; ) {
 3143 #                               if (BYTE_ORDER == LITTLE_ENDIAN)
 3144                                         /*
 3145                                          * The expected low byte of
 3146                                          * dp->d_namlen is our dp->d_type.
 3147                                          * The high MBZ byte of dp->d_namlen
 3148                                          * is our dp->d_namlen.
 3149                                          */
 3150                                         dp->d_type = dp->d_namlen;
 3151                                         dp->d_namlen = 0;
 3152 #                               else
 3153                                         /*
 3154                                          * The dp->d_type is the high byte
 3155                                          * of the expected dp->d_namlen,
 3156                                          * so must be zero'ed.
 3157                                          */
 3158                                         dp->d_type = 0;
 3159 #                               endif
 3160                                 if (dp->d_reclen > 0) {
 3161                                         dp = (struct dirent *)
 3162                                             ((char *)dp + dp->d_reclen);
 3163                                 } else {
 3164                                         error = EIO;
 3165                                         break;
 3166                                 }
 3167                         }
 3168                         if (dp >= edp)
 3169                                 error = uiomove(dirbuf, readcnt, &auio);
 3170                 }
 3171                 FREE(dirbuf, M_TEMP);
 3172         }
 3173         VOP_UNLOCK(vp, 0, td);
 3174         if (error) {
 3175                 fdrop(fp, td);
 3176                 return (error);
 3177         }
 3178         if (uap->count == auio.uio_resid) {
 3179                 if (union_dircheckp) {
 3180                         error = union_dircheckp(td, &vp, fp);
 3181                         if (error == -1)
 3182                                 goto unionread;
 3183                         if (error) {
 3184                                 fdrop(fp, td);
 3185                                 return (error);
 3186                         }
 3187                 }
 3188                 /*
 3189                  * XXX We could delay dropping the lock above but
 3190                  * union_dircheckp complicates things.
 3191                  */
 3192                 vn_lock(vp, LK_EXCLUSIVE|LK_RETRY, td);
 3193                 if ((vp->v_vflag & VV_ROOT) &&
 3194                     (vp->v_mount->mnt_flag & MNT_UNION)) {
 3195                         struct vnode *tvp = vp;
 3196                         vp = vp->v_mount->mnt_vnodecovered;
 3197                         VREF(vp);
 3198                         fp->f_data = vp;
 3199                         fp->f_offset = 0;
 3200                         vput(tvp);
 3201                         goto unionread;
 3202                 }
 3203                 VOP_UNLOCK(vp, 0, td);
 3204         }
 3205         error = copyout(&loff, uap->basep, sizeof(long));
 3206         fdrop(fp, td);
 3207         td->td_retval[0] = uap->count - auio.uio_resid;
 3208         return (error);
 3209 }
 3210 #endif /* COMPAT_43 */
 3211 
 3212 /*
 3213  * Read a block of directory entries in a filesystem independent format.
 3214  */
 3215 #ifndef _SYS_SYSPROTO_H_
 3216 struct getdirentries_args {
 3217         int     fd;
 3218         char    *buf;
 3219         u_int   count;
 3220         long    *basep;
 3221 };
 3222 #endif
 3223 int
 3224 getdirentries(td, uap)
 3225         struct thread *td;
 3226         register struct getdirentries_args /* {
 3227                 int fd;
 3228                 char *buf;
 3229                 u_int count;
 3230                 long *basep;
 3231         } */ *uap;
 3232 {
 3233         struct vnode *vp;
 3234         struct file *fp;
 3235         struct uio auio;
 3236         struct iovec aiov;
 3237         long loff;
 3238         int error, eofflag;
 3239 
 3240         if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
 3241                 return (error);
 3242         if ((fp->f_flag & FREAD) == 0) {
 3243                 fdrop(fp, td);
 3244                 return (EBADF);
 3245         }
 3246         vp = fp->f_data;
 3247 unionread:
 3248         if (vp->v_type != VDIR) {
 3249                 fdrop(fp, td);
 3250                 return (EINVAL);
 3251         }
 3252         aiov.iov_base = uap->buf;
 3253         aiov.iov_len = uap->count;
 3254         auio.uio_iov = &aiov;
 3255         auio.uio_iovcnt = 1;
 3256         auio.uio_rw = UIO_READ;
 3257         auio.uio_segflg = UIO_USERSPACE;
 3258         auio.uio_td = td;
 3259         auio.uio_resid = uap->count;
 3260         /* vn_lock(vp, LK_SHARED | LK_RETRY, td); */
 3261         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
 3262         loff = auio.uio_offset = fp->f_offset;
 3263 #ifdef MAC
 3264         error = mac_check_vnode_readdir(td->td_ucred, vp);
 3265         if (error == 0)
 3266 #endif
 3267                 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL,
 3268                     NULL);
 3269         fp->f_offset = auio.uio_offset;
 3270         VOP_UNLOCK(vp, 0, td);
 3271         if (error) {
 3272                 fdrop(fp, td);
 3273                 return (error);
 3274         }
 3275         if (uap->count == auio.uio_resid) {
 3276                 if (union_dircheckp) {
 3277                         error = union_dircheckp(td, &vp, fp);
 3278                         if (error == -1)
 3279                                 goto unionread;
 3280                         if (error) {
 3281                                 fdrop(fp, td);
 3282                                 return (error);
 3283                         }
 3284                 }
 3285                 /*
 3286                  * XXX We could delay dropping the lock above but
 3287                  * union_dircheckp complicates things.
 3288                  */
 3289                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
 3290                 if ((vp->v_vflag & VV_ROOT) &&
 3291                     (vp->v_mount->mnt_flag & MNT_UNION)) {
 3292                         struct vnode *tvp = vp;
 3293                         vp = vp->v_mount->mnt_vnodecovered;
 3294                         VREF(vp);
 3295                         fp->f_data = vp;
 3296                         fp->f_offset = 0;
 3297                         vput(tvp);
 3298                         goto unionread;
 3299                 }
 3300                 VOP_UNLOCK(vp, 0, td);
 3301         }
 3302         if (uap->basep != NULL) {
 3303                 error = copyout(&loff, uap->basep, sizeof(long));
 3304         }
 3305         td->td_retval[0] = uap->count - auio.uio_resid;
 3306         fdrop(fp, td);
 3307         return (error);
 3308 }
 3309 #ifndef _SYS_SYSPROTO_H_
 3310 struct getdents_args {
 3311         int fd;
 3312         char *buf;
 3313         size_t count;
 3314 };
 3315 #endif
 3316 int
 3317 getdents(td, uap)
 3318         struct thread *td;
 3319         register struct getdents_args /* {
 3320                 int fd;
 3321                 char *buf;
 3322                 u_int count;
 3323         } */ *uap;
 3324 {
 3325         struct getdirentries_args ap;
 3326         ap.fd = uap->fd;
 3327         ap.buf = uap->buf;
 3328         ap.count = uap->count;
 3329         ap.basep = NULL;
 3330         return getdirentries(td, &ap);
 3331 }
 3332 
 3333 /*
 3334  * Set the mode mask for creation of filesystem nodes.
 3335  *
 3336  * MP SAFE
 3337  */
 3338 #ifndef _SYS_SYSPROTO_H_
 3339 struct umask_args {
 3340         int     newmask;
 3341 };
 3342 #endif
 3343 int
 3344 umask(td, uap)
 3345         struct thread *td;
 3346         struct umask_args /* {
 3347                 int newmask;
 3348         } */ *uap;
 3349 {
 3350         register struct filedesc *fdp;
 3351 
 3352         FILEDESC_LOCK(td->td_proc->p_fd);
 3353         fdp = td->td_proc->p_fd;
 3354         td->td_retval[0] = fdp->fd_cmask;
 3355         fdp->fd_cmask = uap->newmask & ALLPERMS;
 3356         FILEDESC_UNLOCK(td->td_proc->p_fd);
 3357         return (0);
 3358 }
 3359 
 3360 /*
 3361  * Void all references to file by ripping underlying filesystem
 3362  * away from vnode.
 3363  */
 3364 #ifndef _SYS_SYSPROTO_H_
 3365 struct revoke_args {
 3366         char    *path;
 3367 };
 3368 #endif
 3369 /* ARGSUSED */
 3370 int
 3371 revoke(td, uap)
 3372         struct thread *td;
 3373         register struct revoke_args /* {
 3374                 char *path;
 3375         } */ *uap;
 3376 {
 3377         struct mount *mp;
 3378         struct vnode *vp;
 3379         struct vattr vattr;
 3380         int error;
 3381         struct nameidata nd;
 3382 
 3383         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, td);
 3384         if ((error = namei(&nd)) != 0)
 3385                 return (error);
 3386         vp = nd.ni_vp;
 3387         NDFREE(&nd, NDF_ONLY_PNBUF);
 3388         if (vp->v_type != VCHR) {
 3389                 vput(vp);
 3390                 return (EINVAL);
 3391         }
 3392 #ifdef MAC
 3393         error = mac_check_vnode_revoke(td->td_ucred, vp);
 3394         if (error) {
 3395                 vput(vp);
 3396                 return (error);
 3397         }
 3398 #endif
 3399         error = VOP_GETATTR(vp, &vattr, td->td_ucred, td);
 3400         if (error) {
 3401                 vput(vp);
 3402                 return (error);
 3403         }
 3404         VOP_UNLOCK(vp, 0, td);
 3405         if (td->td_ucred->cr_uid != vattr.va_uid) {
 3406                 error = suser_cred(td->td_ucred, PRISON_ROOT);
 3407                 if (error)
 3408                         goto out;
 3409         }
 3410         if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
 3411                 goto out;
 3412         if (vcount(vp) > 1)
 3413                 VOP_REVOKE(vp, REVOKEALL);
 3414         vn_finished_write(mp);
 3415 out:
 3416         vrele(vp);
 3417         return (error);
 3418 }
 3419 
 3420 /*
 3421  * Convert a user file descriptor to a kernel file entry.
 3422  * The file entry is locked upon returning.
 3423  */
 3424 int
 3425 getvnode(fdp, fd, fpp)
 3426         struct filedesc *fdp;
 3427         int fd;
 3428         struct file **fpp;
 3429 {
 3430         int error;
 3431         struct file *fp;
 3432 
 3433         fp = NULL;
 3434         if (fdp == NULL)
 3435                 error = EBADF;
 3436         else {
 3437                 FILEDESC_LOCK(fdp);
 3438                 if ((u_int)fd >= fdp->fd_nfiles ||
 3439                     (fp = fdp->fd_ofiles[fd]) == NULL)
 3440                         error = EBADF;
 3441                 else if (fp->f_type != DTYPE_VNODE && fp->f_type != DTYPE_FIFO) {
 3442                         fp = NULL;
 3443                         error = EINVAL;
 3444                 } else {
 3445                         fhold(fp);
 3446                         error = 0;
 3447                 }
 3448                 FILEDESC_UNLOCK(fdp);
 3449         }
 3450         *fpp = fp;
 3451         return (error);
 3452 }
 3453 /*
 3454  * Get (NFS) file handle
 3455  */
 3456 #ifndef _SYS_SYSPROTO_H_
 3457 struct getfh_args {
 3458         char    *fname;
 3459         fhandle_t *fhp;
 3460 };
 3461 #endif
 3462 int
 3463 getfh(td, uap)
 3464         struct thread *td;
 3465         register struct getfh_args *uap;
 3466 {
 3467         struct nameidata nd;
 3468         fhandle_t fh;
 3469         register struct vnode *vp;
 3470         int error;
 3471 
 3472         /*
 3473          * Must be super user
 3474          */
 3475         error = suser(td);
 3476         if (error)
 3477                 return (error);
 3478         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, td);
 3479         error = namei(&nd);
 3480         if (error)
 3481                 return (error);
 3482         NDFREE(&nd, NDF_ONLY_PNBUF);
 3483         vp = nd.ni_vp;
 3484         bzero(&fh, sizeof(fh));
 3485         fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;
 3486         error = VFS_VPTOFH(vp, &fh.fh_fid);
 3487         vput(vp);
 3488         if (error)
 3489                 return (error);
 3490         error = copyout(&fh, uap->fhp, sizeof (fh));
 3491         return (error);
 3492 }
 3493 
 3494 /*
 3495  * syscall for the rpc.lockd to use to translate a NFS file handle into
 3496  * an open descriptor.
 3497  *
 3498  * warning: do not remove the suser() call or this becomes one giant
 3499  * security hole.
 3500  */
 3501 #ifndef _SYS_SYSPROTO_H_
 3502 struct fhopen_args {
 3503         const struct fhandle *u_fhp;
 3504         int flags;
 3505 };
 3506 #endif
 3507 int
 3508 fhopen(td, uap)
 3509         struct thread *td;
 3510         struct fhopen_args /* {
 3511                 const struct fhandle *u_fhp;
 3512                 int flags;
 3513         } */ *uap;
 3514 {
 3515         struct proc *p = td->td_proc;
 3516         struct mount *mp;
 3517         struct vnode *vp;
 3518         struct fhandle fhp;
 3519         struct vattr vat;
 3520         struct vattr *vap = &vat;
 3521         struct flock lf;
 3522         struct file *fp;
 3523         register struct filedesc *fdp = p->p_fd;
 3524         int fmode, mode, error, type;
 3525         struct file *nfp; 
 3526         int indx;
 3527 
 3528         /*
 3529          * Must be super user
 3530          */
 3531         error = suser(td);
 3532         if (error)
 3533                 return (error);
 3534 
 3535         fmode = FFLAGS(uap->flags);
 3536         /* why not allow a non-read/write open for our lockd? */
 3537         if (((fmode & (FREAD | FWRITE)) == 0) || (fmode & O_CREAT))
 3538                 return (EINVAL);
 3539         error = copyin(uap->u_fhp, &fhp, sizeof(fhp));
 3540         if (error)
 3541                 return(error);
 3542         /* find the mount point */
 3543         mp = vfs_getvfs(&fhp.fh_fsid);
 3544         if (mp == NULL)
 3545                 return (ESTALE);
 3546         /* now give me my vnode, it gets returned to me locked */
 3547         error = VFS_FHTOVP(mp, &fhp.fh_fid, &vp);
 3548         if (error)
 3549                 return (error);
 3550         /*
 3551          * from now on we have to make sure not
 3552          * to forget about the vnode
 3553          * any error that causes an abort must vput(vp) 
 3554          * just set error = err and 'goto bad;'.
 3555          */
 3556 
 3557         /* 
 3558          * from vn_open 
 3559          */
 3560         if (vp->v_type == VLNK) {
 3561                 error = EMLINK;
 3562                 goto bad;
 3563         }
 3564         if (vp->v_type == VSOCK) {
 3565                 error = EOPNOTSUPP;
 3566                 goto bad;
 3567         }
 3568         mode = 0;
 3569         if (fmode & (FWRITE | O_TRUNC)) {
 3570                 if (vp->v_type == VDIR) {
 3571                         error = EISDIR;
 3572                         goto bad;
 3573                 }
 3574                 error = vn_writechk(vp);
 3575                 if (error)
 3576                         goto bad;
 3577                 mode |= VWRITE;
 3578         }
 3579         if (fmode & FREAD)
 3580                 mode |= VREAD;
 3581         if (fmode & O_APPEND)
 3582                 mode |= VAPPEND;
 3583 #ifdef MAC
 3584         error = mac_check_vnode_open(td->td_ucred, vp, mode);
 3585         if (error)
 3586                 goto bad;
 3587 #endif
 3588         if (mode) {
 3589                 error = VOP_ACCESS(vp, mode, td->td_ucred, td);
 3590                 if (error)
 3591                         goto bad;
 3592         }
 3593         if (fmode & O_TRUNC) {
 3594                 VOP_UNLOCK(vp, 0, td);                          /* XXX */
 3595                 if ((error = vn_start_write(NULL, &mp, V_WAIT | PCATCH)) != 0) {
 3596                         vrele(vp);
 3597                         return (error);
 3598                 }
 3599                 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
 3600                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);       /* XXX */
 3601 #ifdef MAC
 3602                 /*
 3603                  * We don't yet have fp->f_cred, so use td->td_ucred, which
 3604                  * should be right.
 3605                  */
 3606                 error = mac_check_vnode_write(td->td_ucred, td->td_ucred, vp);
 3607                 if (error == 0) {
 3608 #endif
 3609                         VATTR_NULL(vap);
 3610                         vap->va_size = 0;
 3611                         error = VOP_SETATTR(vp, vap, td->td_ucred, td);
 3612 #ifdef MAC
 3613                 }
 3614 #endif
 3615                 vn_finished_write(mp);
 3616                 if (error)
 3617                         goto bad;
 3618         }
 3619         error = VOP_OPEN(vp, fmode, td->td_ucred, td);
 3620         if (error)
 3621                 goto bad;
 3622         /*
 3623          * Make sure that a VM object is created for VMIO support.
 3624          */
 3625         if (vn_canvmio(vp) == TRUE) {
 3626                 if ((error = vfs_object_create(vp, td, td->td_ucred)) != 0)
 3627                         goto bad;
 3628         }
 3629         if (fmode & FWRITE)
 3630                 vp->v_writecount++;
 3631 
 3632         /*
 3633          * end of vn_open code 
 3634          */
 3635 
 3636         if ((error = falloc(td, &nfp, &indx)) != 0) {
 3637                 if (fmode & FWRITE)
 3638                         vp->v_writecount--;
 3639                 goto bad;
 3640         }
 3641         fp = nfp;       
 3642 
 3643         /*
 3644          * Hold an extra reference to avoid having fp ripped out 
 3645          * from under us while we block in the lock op
 3646          */
 3647         fhold(fp);
 3648         nfp->f_data = vp;
 3649         nfp->f_flag = fmode & FMASK;
 3650         nfp->f_ops = &vnops;
 3651         nfp->f_type = DTYPE_VNODE;
 3652         if (fmode & (O_EXLOCK | O_SHLOCK)) {
 3653                 lf.l_whence = SEEK_SET;
 3654                 lf.l_start = 0;
 3655                 lf.l_len = 0;
 3656                 if (fmode & O_EXLOCK)
 3657                         lf.l_type = F_WRLCK;
 3658                 else
 3659                         lf.l_type = F_RDLCK;
 3660                 type = F_FLOCK;
 3661                 if ((fmode & FNONBLOCK) == 0)
 3662                         type |= F_WAIT;
 3663                 VOP_UNLOCK(vp, 0, td);
 3664                 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf,
 3665                             type)) != 0) {
 3666                         /*
 3667                          * The lock request failed.  Normally close the
 3668                          * descriptor but handle the case where someone might
 3669                          * have dup()d or close()d it when we weren't looking.
 3670                          */
 3671                         FILEDESC_LOCK(fdp);
 3672                         if (fdp->fd_ofiles[indx] == fp) {
 3673                                 fdp->fd_ofiles[indx] = NULL;
 3674                                 FILEDESC_UNLOCK(fdp);
 3675                                 fdrop(fp, td);
 3676                         } else
 3677                                 FILEDESC_UNLOCK(fdp);
 3678                         /*
 3679                          * release our private reference
 3680                          */
 3681                         fdrop(fp, td);
 3682                         return(error);
 3683                 }
 3684                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
 3685                 fp->f_flag |= FHASLOCK;
 3686         }
 3687         if ((vp->v_type == VREG) && (VOP_GETVOBJECT(vp, NULL) != 0))
 3688                 vfs_object_create(vp, td, td->td_ucred);
 3689 
 3690         VOP_UNLOCK(vp, 0, td);
 3691         fdrop(fp, td);
 3692         td->td_retval[0] = indx;
 3693         return (0);
 3694 
 3695 bad:
 3696         vput(vp);
 3697         return (error);
 3698 }
 3699 
 3700 /*
 3701  * Stat an (NFS) file handle.
 3702  */
 3703 #ifndef _SYS_SYSPROTO_H_
 3704 struct fhstat_args {
 3705         struct fhandle *u_fhp;
 3706         struct stat *sb;
 3707 };
 3708 #endif
 3709 int
 3710 fhstat(td, uap)
 3711         struct thread *td;
 3712         register struct fhstat_args /* {
 3713                 struct fhandle *u_fhp;
 3714                 struct stat *sb;
 3715         } */ *uap;
 3716 {
 3717         struct stat sb;
 3718         fhandle_t fh;
 3719         struct mount *mp;
 3720         struct vnode *vp;
 3721         int error;
 3722 
 3723         /*
 3724          * Must be super user
 3725          */
 3726         error = suser(td);
 3727         if (error)
 3728                 return (error);
 3729         
 3730         error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t));
 3731         if (error)
 3732                 return (error);
 3733 
 3734         if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
 3735                 return (ESTALE);
 3736         if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
 3737                 return (error);
 3738         error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td);
 3739         vput(vp);
 3740         if (error)
 3741                 return (error);
 3742         error = copyout(&sb, uap->sb, sizeof(sb));
 3743         return (error);
 3744 }
 3745 
 3746 /*
 3747  * Implement fstatfs() for (NFS) file handles.
 3748  */
 3749 #ifndef _SYS_SYSPROTO_H_
 3750 struct fhstatfs_args {
 3751         struct fhandle *u_fhp;
 3752         struct statfs *buf;
 3753 };
 3754 #endif
 3755 int
 3756 fhstatfs(td, uap)
 3757         struct thread *td;
 3758         struct fhstatfs_args /* {
 3759                 struct fhandle *u_fhp;
 3760                 struct statfs *buf;
 3761         } */ *uap;
 3762 {
 3763         struct statfs *sp;
 3764         struct mount *mp;
 3765         struct vnode *vp;
 3766         struct statfs sb;
 3767         fhandle_t fh;
 3768         int error;
 3769 
 3770         /*
 3771          * Must be super user
 3772          */
 3773         error = suser(td);
 3774         if (error)
 3775                 return (error);
 3776 
 3777         if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
 3778                 return (error);
 3779 
 3780         if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
 3781                 return (ESTALE);
 3782         if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
 3783                 return (error);
 3784         mp = vp->v_mount;
 3785         sp = &mp->mnt_stat;
 3786         vput(vp);
 3787 #ifdef MAC
 3788         error = mac_check_mount_stat(td->td_ucred, mp);
 3789         if (error)
 3790                 return (error);
 3791 #endif
 3792         if ((error = VFS_STATFS(mp, sp, td)) != 0)
 3793                 return (error);
 3794         sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
 3795         if (suser(td)) {
 3796                 bcopy(sp, &sb, sizeof(sb));
 3797                 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
 3798                 sp = &sb;
 3799         }
 3800         return (copyout(sp, uap->buf, sizeof(*sp)));
 3801 }
 3802 
 3803 /*
 3804  * Syscall to push extended attribute configuration information into the
 3805  * VFS.  Accepts a path, which it converts to a mountpoint, as well as
 3806  * a command (int cmd), and attribute name and misc data.  For now, the
 3807  * attribute name is left in userspace for consumption by the VFS_op.
 3808  * It will probably be changed to be copied into sysspace by the
 3809  * syscall in the future, once issues with various consumers of the
 3810  * attribute code have raised their hands.
 3811  *
 3812  * Currently this is used only by UFS Extended Attributes.
 3813  */
 3814 int
 3815 extattrctl(td, uap)
 3816         struct thread *td;
 3817         struct extattrctl_args /* {
 3818                 const char *path;
 3819                 int cmd;
 3820                 const char *filename;
 3821                 int attrnamespace;
 3822                 const char *attrname;
 3823         } */ *uap;
 3824 {
 3825         struct vnode *filename_vp;
 3826         struct nameidata nd;
 3827         struct mount *mp, *mp_writable;
 3828         char attrname[EXTATTR_MAXNAMELEN];
 3829         int error;
 3830 
 3831         /*
 3832          * uap->attrname is not always defined.  We check again later when we
 3833          * invoke the VFS call so as to pass in NULL there if needed.
 3834          */
 3835         if (uap->attrname != NULL) {
 3836                 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN,
 3837                     NULL);
 3838                 if (error)
 3839                         return (error);
 3840         }
 3841 
 3842         /*
 3843          * uap->filename is not always defined.  If it is, grab a vnode lock,
 3844          * which VFS_EXTATTRCTL() will later release.
 3845          */
 3846         filename_vp = NULL;
 3847         if (uap->filename != NULL) {
 3848                 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
 3849                     uap->filename, td);
 3850                 error = namei(&nd);
 3851                 if (error)
 3852                         return (error);
 3853                 filename_vp = nd.ni_vp;
 3854                 NDFREE(&nd, NDF_NO_VP_RELE | NDF_NO_VP_UNLOCK);
 3855         }
 3856 
 3857         /* uap->path is always defined. */
 3858         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
 3859         error = namei(&nd);
 3860         if (error) {
 3861                 if (filename_vp != NULL)
 3862                         vput(filename_vp);
 3863                 return (error);
 3864         }
 3865         mp = nd.ni_vp->v_mount;
 3866         error = vn_start_write(nd.ni_vp, &mp_writable, V_WAIT | PCATCH);
 3867         NDFREE(&nd, 0);
 3868         if (error) {
 3869                 if (filename_vp != NULL)
 3870                         vput(filename_vp);
 3871                 return (error);
 3872         }
 3873 
 3874         error = VFS_EXTATTRCTL(mp, uap->cmd, filename_vp, uap->attrnamespace,
 3875             uap->attrname != NULL ? attrname : NULL, td);
 3876 
 3877         vn_finished_write(mp_writable);
 3878         /*
 3879          * VFS_EXTATTRCTL will have unlocked, but not de-ref'd,
 3880          * filename_vp, so vrele it if it is defined.
 3881          */
 3882         if (filename_vp != NULL)
 3883                 vrele(filename_vp);
 3884         return (error);
 3885 }
 3886 
 3887 /*-
 3888  * Set a named extended attribute on a file or directory
 3889  * 
 3890  * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
 3891  *            kernelspace string pointer "attrname", userspace buffer
 3892  *            pointer "data", buffer length "nbytes", thread "td".
 3893  * Returns: 0 on success, an error number otherwise
 3894  * Locks: none
 3895  * References: vp must be a valid reference for the duration of the call
 3896  */
 3897 static int
 3898 extattr_set_vp(struct vnode *vp, int attrnamespace, const char *attrname,
 3899     void *data, size_t nbytes, struct thread *td)
 3900 {
 3901         struct mount *mp;
 3902         struct uio auio;
 3903         struct iovec aiov;
 3904         ssize_t cnt;
 3905         int error;
 3906 
 3907         error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
 3908         if (error)
 3909                 return (error);
 3910         VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
 3911         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
 3912 
 3913         aiov.iov_base = data;
 3914         aiov.iov_len = nbytes;
 3915         auio.uio_iov = &aiov;
 3916         auio.uio_iovcnt = 1;
 3917         auio.uio_offset = 0;
 3918         if (nbytes > INT_MAX) {
 3919                 error = EINVAL;
 3920                 goto done;
 3921         }
 3922         auio.uio_resid = nbytes;
 3923         auio.uio_rw = UIO_WRITE;
 3924         auio.uio_segflg = UIO_USERSPACE;
 3925         auio.uio_td = td;
 3926         cnt = nbytes;
 3927 
 3928 #ifdef MAC
 3929         error = mac_check_vnode_setextattr(td->td_ucred, vp, attrnamespace,
 3930             attrname, &auio);
 3931         if (error)
 3932                 goto done;
 3933 #endif
 3934 
 3935         error = VOP_SETEXTATTR(vp, attrnamespace, attrname, &auio,
 3936             td->td_ucred, td);
 3937         cnt -= auio.uio_resid;
 3938         td->td_retval[0] = cnt;
 3939 
 3940 done:
 3941         VOP_UNLOCK(vp, 0, td);
 3942         vn_finished_write(mp);
 3943         return (error);
 3944 }
 3945 
 3946 int
 3947 extattr_set_fd(td, uap)
 3948         struct thread *td;
 3949         struct extattr_set_fd_args /* {
 3950                 int fd;
 3951                 int attrnamespace;
 3952                 const char *attrname;
 3953                 void *data;
 3954                 size_t nbytes;
 3955         } */ *uap;
 3956 {
 3957         struct file *fp;
 3958         char attrname[EXTATTR_MAXNAMELEN];
 3959         int error;
 3960 
 3961         error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
 3962         if (error)
 3963                 return (error);
 3964 
 3965         error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
 3966         if (error)
 3967                 return (error);
 3968 
 3969         error = extattr_set_vp(fp->f_data, uap->attrnamespace,
 3970             attrname, uap->data, uap->nbytes, td);
 3971         fdrop(fp, td);
 3972 
 3973         return (error);
 3974 }
 3975 
 3976 int
 3977 extattr_set_file(td, uap)
 3978         struct thread *td;
 3979         struct extattr_set_file_args /* {
 3980                 const char *path;
 3981                 int attrnamespace;
 3982                 const char *attrname;
 3983                 void *data;
 3984                 size_t nbytes;
 3985         } */ *uap;
 3986 {
 3987         struct nameidata nd;
 3988         char attrname[EXTATTR_MAXNAMELEN];
 3989         int error;
 3990 
 3991         error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
 3992         if (error)
 3993                 return (error);
 3994 
 3995         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
 3996         error = namei(&nd);
 3997         if (error)
 3998                 return (error);
 3999         NDFREE(&nd, NDF_ONLY_PNBUF);
 4000 
 4001         error = extattr_set_vp(nd.ni_vp, uap->attrnamespace, attrname,
 4002             uap->data, uap->nbytes, td);
 4003 
 4004         vrele(nd.ni_vp);
 4005         return (error);
 4006 }
 4007 
 4008 int
 4009 extattr_set_link(td, uap)
 4010         struct thread *td;
 4011         struct extattr_set_link_args /* {
 4012                 const char *path;
 4013                 int attrnamespace;
 4014                 const char *attrname;
 4015                 void *data;
 4016                 size_t nbytes;
 4017         } */ *uap;
 4018 {
 4019         struct nameidata nd;
 4020         char attrname[EXTATTR_MAXNAMELEN];
 4021         int error;
 4022 
 4023         error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
 4024         if (error)
 4025                 return (error);
 4026 
 4027         NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td);
 4028         error = namei(&nd);
 4029         if (error)
 4030                 return (error);
 4031         NDFREE(&nd, NDF_ONLY_PNBUF);
 4032 
 4033         error = extattr_set_vp(nd.ni_vp, uap->attrnamespace, attrname,
 4034             uap->data, uap->nbytes, td);
 4035 
 4036         vrele(nd.ni_vp);
 4037         return (error);
 4038 }
 4039 
 4040 /*-
 4041  * Get a named extended attribute on a file or directory
 4042  * 
 4043  * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
 4044  *            kernelspace string pointer "attrname", userspace buffer
 4045  *            pointer "data", buffer length "nbytes", thread "td".
 4046  * Returns: 0 on success, an error number otherwise
 4047  * Locks: none
 4048  * References: vp must be a valid reference for the duration of the call
 4049  */
 4050 static int
 4051 extattr_get_vp(struct vnode *vp, int attrnamespace, const char *attrname,
 4052     void *data, size_t nbytes, struct thread *td)
 4053 {
 4054         struct uio auio, *auiop;
 4055         struct iovec aiov;
 4056         ssize_t cnt;
 4057         size_t size, *sizep;
 4058         int error;
 4059 
 4060         VOP_LEASE(vp, td, td->td_ucred, LEASE_READ);
 4061         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
 4062 
 4063         /*
 4064          * Slightly unusual semantics: if the user provides a NULL data
 4065          * pointer, they don't want to receive the data, just the
 4066          * maximum read length.
 4067          */
 4068         auiop = NULL;
 4069         sizep = NULL;
 4070         cnt = 0;
 4071         if (data != NULL) {
 4072                 aiov.iov_base = data;
 4073                 aiov.iov_len = nbytes;
 4074                 auio.uio_iov = &aiov;
 4075                 auio.uio_offset = 0;
 4076                 if (nbytes > INT_MAX) {
 4077                         error = EINVAL;
 4078                         goto done;
 4079                 }
 4080                 auio.uio_resid = nbytes;
 4081                 auio.uio_rw = UIO_READ;
 4082                 auio.uio_segflg = UIO_USERSPACE;
 4083                 auio.uio_td = td;
 4084                 auiop = &auio;
 4085                 cnt = nbytes;
 4086         } else
 4087                 sizep = &size;
 4088 
 4089 #ifdef MAC
 4090         error = mac_check_vnode_getextattr(td->td_ucred, vp, attrnamespace,
 4091             attrname, &auio);
 4092         if (error)
 4093                 goto done;
 4094 #endif
 4095 
 4096         error = VOP_GETEXTATTR(vp, attrnamespace, attrname, auiop, sizep,
 4097             td->td_ucred, td);
 4098 
 4099         if (auiop != NULL) {
 4100                 cnt -= auio.uio_resid;
 4101                 td->td_retval[0] = cnt;
 4102         } else
 4103                 td->td_retval[0] = size;
 4104 
 4105 done:
 4106         VOP_UNLOCK(vp, 0, td);
 4107         return (error);
 4108 }
 4109 
 4110 int
 4111 extattr_get_fd(td, uap)
 4112         struct thread *td;
 4113         struct extattr_get_fd_args /* {
 4114                 int fd;
 4115                 int attrnamespace;
 4116                 const char *attrname;
 4117                 void *data;
 4118                 size_t nbytes;
 4119         } */ *uap;
 4120 {
 4121         struct file *fp;
 4122         char attrname[EXTATTR_MAXNAMELEN];
 4123         int error;
 4124 
 4125         error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
 4126         if (error)
 4127                 return (error);
 4128 
 4129         error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
 4130         if (error)
 4131                 return (error);
 4132 
 4133         error = extattr_get_vp(fp->f_data, uap->attrnamespace,
 4134             attrname, uap->data, uap->nbytes, td);
 4135 
 4136         fdrop(fp, td);
 4137         return (error);
 4138 }
 4139 
 4140 int
 4141 extattr_get_file(td, uap)
 4142         struct thread *td;
 4143         struct extattr_get_file_args /* {
 4144                 const char *path;
 4145                 int attrnamespace;
 4146                 const char *attrname;
 4147                 void *data;
 4148                 size_t nbytes;
 4149         } */ *uap;
 4150 {
 4151         struct nameidata nd;
 4152         char attrname[EXTATTR_MAXNAMELEN];
 4153         int error;
 4154 
 4155         error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
 4156         if (error)
 4157                 return (error);
 4158 
 4159         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
 4160         error = namei(&nd);
 4161         if (error)
 4162                 return (error);
 4163         NDFREE(&nd, NDF_ONLY_PNBUF);
 4164 
 4165         error = extattr_get_vp(nd.ni_vp, uap->attrnamespace, attrname,
 4166             uap->data, uap->nbytes, td);
 4167 
 4168         vrele(nd.ni_vp);
 4169         return (error);
 4170 }
 4171 
 4172 int
 4173 extattr_get_link(td, uap)
 4174         struct thread *td;
 4175         struct extattr_get_link_args /* {
 4176                 const char *path;
 4177                 int attrnamespace;
 4178                 const char *attrname;
 4179                 void *data;
 4180                 size_t nbytes;
 4181         } */ *uap;
 4182 {
 4183         struct nameidata nd;
 4184         char attrname[EXTATTR_MAXNAMELEN];
 4185         int error;
 4186 
 4187         error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
 4188         if (error)
 4189                 return (error);
 4190 
 4191         NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td);
 4192         error = namei(&nd);
 4193         if (error)
 4194                 return (error);
 4195         NDFREE(&nd, NDF_ONLY_PNBUF);
 4196 
 4197         error = extattr_get_vp(nd.ni_vp, uap->attrnamespace, attrname,
 4198             uap->data, uap->nbytes, td);
 4199 
 4200         vrele(nd.ni_vp);
 4201         return (error);
 4202 }
 4203 
 4204 /*
 4205  * extattr_delete_vp(): Delete a named extended attribute on a file or
 4206  *                      directory
 4207  * 
 4208  * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
 4209  *            kernelspace string pointer "attrname", proc "p"
 4210  * Returns: 0 on success, an error number otherwise
 4211  * Locks: none
 4212  * References: vp must be a valid reference for the duration of the call
 4213  */
 4214 static int
 4215 extattr_delete_vp(struct vnode *vp, int attrnamespace, const char *attrname,
 4216     struct thread *td)
 4217 {
 4218         struct mount *mp;
 4219         int error;
 4220 
 4221         error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
 4222         if (error)
 4223                 return (error);
 4224         VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
 4225         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
 4226 
 4227 #ifdef MAC
 4228         error = mac_check_vnode_setextattr(td->td_ucred, vp, attrnamespace,
 4229             attrname, NULL);
 4230         if (error)
 4231                 goto done;
 4232 #endif
 4233 
 4234         error = VOP_SETEXTATTR(vp, attrnamespace, attrname, NULL, td->td_ucred,
 4235             td);
 4236 #ifdef MAC
 4237 done:
 4238 #endif
 4239         VOP_UNLOCK(vp, 0, td);
 4240         vn_finished_write(mp);
 4241         return (error);
 4242 }
 4243 
 4244 int
 4245 extattr_delete_fd(td, uap)
 4246         struct thread *td;
 4247         struct extattr_delete_fd_args /* {
 4248                 int fd;
 4249                 int attrnamespace;
 4250                 const char *attrname;
 4251         } */ *uap;
 4252 {
 4253         struct file *fp;
 4254         struct vnode *vp;
 4255         char attrname[EXTATTR_MAXNAMELEN];
 4256         int error;
 4257 
 4258         error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
 4259         if (error)
 4260                 return (error);
 4261 
 4262         error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
 4263         if (error)
 4264                 return (error);
 4265         vp = fp->f_data;
 4266 
 4267         error = extattr_delete_vp(vp, uap->attrnamespace, attrname, td);
 4268         fdrop(fp, td);
 4269         return (error);
 4270 }
 4271 
 4272 int
 4273 extattr_delete_file(td, uap)
 4274         struct thread *td;
 4275         struct extattr_delete_file_args /* {
 4276                 const char *path;
 4277                 int attrnamespace;
 4278                 const char *attrname;
 4279         } */ *uap;
 4280 {
 4281         struct nameidata nd;
 4282         char attrname[EXTATTR_MAXNAMELEN];
 4283         int error;
 4284 
 4285         error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
 4286         if (error)
 4287                 return(error);
 4288 
 4289         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
 4290         error = namei(&nd);
 4291         if (error)
 4292                 return(error);
 4293         NDFREE(&nd, NDF_ONLY_PNBUF);
 4294 
 4295         error = extattr_delete_vp(nd.ni_vp, uap->attrnamespace, attrname, td);
 4296         vrele(nd.ni_vp);
 4297         return(error);
 4298 }
 4299 
 4300 int
 4301 extattr_delete_link(td, uap)
 4302         struct thread *td;
 4303         struct extattr_delete_link_args /* {
 4304                 const char *path;
 4305                 int attrnamespace;
 4306                 const char *attrname;
 4307         } */ *uap;
 4308 {
 4309         struct nameidata nd;
 4310         char attrname[EXTATTR_MAXNAMELEN];
 4311         int error;
 4312 
 4313         error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
 4314         if (error)
 4315                 return(error);
 4316 
 4317         NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td);
 4318         error = namei(&nd);
 4319         if (error)
 4320                 return(error);
 4321         NDFREE(&nd, NDF_ONLY_PNBUF);
 4322 
 4323         error = extattr_delete_vp(nd.ni_vp, uap->attrnamespace, attrname, td);
 4324         vrele(nd.ni_vp);
 4325         return(error);
 4326 }

Cache object: 62b92fc2e8c30ebc2a42fb9a5dbf1c3e


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