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


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

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

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

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

Cache object: 9a8a15d8a45e30c0d5c4cd81178eef0b


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