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


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

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

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

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

Cache object: db16979e798ce8d72e4585aaf69fda7d


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