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

Cache object: f196a7e64b13334d4a2333ca1307f3b2


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