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

Cache object: 63eb2edeb340b273e08682038e841bb4


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