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

Cache object: 24633fbcdd2cf6aedba652a62f44d9c1


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