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

Cache object: c5facef569cb3ca5ed97ce67fd60c46f


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