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

Cache object: 5a37398d5474e953e0a7793ec2ae3c0a


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