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

Cache object: 29ba587abac2dbe9e0d9013cafd7214a


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