The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/vfs_syscalls.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 550b945115add839ae7077d7aab9f8a0


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