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

Cache object: 2b856237dda4413dea7992489b51ea8e


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