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

Cache object: 9901ccde3d5dfa0f8aca54902a65b7a4


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