root/kern/vfs_syscalls.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sys_mount
  2. checkdirs
  3. sys_unmount
  4. dounmount
  5. sys_sync
  6. sys_quotactl
  7. copyout_statfs
  8. sys_statfs
  9. sys_fstatfs
  10. sys_getfsstat
  11. sys_fchdir
  12. sys_chdir
  13. sys_chroot
  14. change_dir
  15. sys_open
  16. sys_getfh
  17. sys_fhopen
  18. sys_fhstat
  19. sys_fhstatfs
  20. sys_mknod
  21. sys_mkfifo
  22. sys_link
  23. sys_symlink
  24. sys_unlink
  25. sys_lseek
  26. sys_access
  27. sys_stat
  28. sys_lstat
  29. sys_pathconf
  30. sys_readlink
  31. sys_chflags
  32. sys_fchflags
  33. sys_chmod
  34. sys_fchmod
  35. sys_chown
  36. sys_lchown
  37. sys_fchown
  38. sys_utimes
  39. sys_futimes
  40. sys_truncate
  41. sys_ftruncate
  42. sys_fsync
  43. sys_rename
  44. sys_mkdir
  45. sys_rmdir
  46. sys_getdirentries
  47. sys_umask
  48. sys_revoke
  49. getvnode
  50. sys_pread
  51. sys_preadv
  52. sys_pwrite
  53. sys_pwritev

    1 /*      $OpenBSD: vfs_syscalls.c,v 1.141 2007/08/06 16:58:26 millert Exp $      */
    2 /*      $NetBSD: vfs_syscalls.c,v 1.71 1996/04/23 10:29:02 mycroft Exp $        */
    3 
    4 /*
    5  * Copyright (c) 1989, 1993
    6  *      The Regents of the University of California.  All rights reserved.
    7  * (c) UNIX System Laboratories, Inc.
    8  * All or some portions of this file are derived from material licensed
    9  * to the University of California by American Telephone and Telegraph
   10  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
   11  * the permission of UNIX System Laboratories, Inc.
   12  *
   13  * Redistribution and use in source and binary forms, with or without
   14  * modification, are permitted provided that the following conditions
   15  * are met:
   16  * 1. Redistributions of source code must retain the above copyright
   17  *    notice, this list of conditions and the following disclaimer.
   18  * 2. Redistributions in binary form must reproduce the above copyright
   19  *    notice, this list of conditions and the following disclaimer in the
   20  *    documentation and/or other materials provided with the distribution.
   21  * 3. Neither the name of the University nor the names of its contributors
   22  *    may be used to endorse or promote products derived from this software
   23  *    without specific prior written permission.
   24  *
   25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   35  * SUCH DAMAGE.
   36  *
   37  *      @(#)vfs_syscalls.c      8.28 (Berkeley) 12/10/94
   38  */
   39 
   40 #include <sys/param.h>
   41 #include <sys/systm.h>
   42 #include <sys/namei.h>
   43 #include <sys/filedesc.h>
   44 #include <sys/kernel.h>
   45 #include <sys/file.h>
   46 #include <sys/stat.h>
   47 #include <sys/vnode.h>
   48 #include <sys/mount.h>
   49 #include <sys/proc.h>
   50 #include <sys/uio.h>
   51 #include <sys/malloc.h>
   52 #include <sys/pool.h>
   53 #include <sys/dirent.h>
   54 #include <sys/dkio.h>
   55 #include <sys/disklabel.h>
   56 
   57 #include <sys/syscallargs.h>
   58 
   59 #include <uvm/uvm_extern.h>
   60 #include <sys/sysctl.h>
   61 
   62 extern int suid_clear;
   63 int     usermount = 0;          /* sysctl: by default, users may not mount */
   64 
   65 static int change_dir(struct nameidata *, struct proc *);
   66 
   67 void checkdirs(struct vnode *);
   68 
   69 int copyout_statfs(struct statfs *, void *, struct proc *);
   70 
   71 /*
   72  * Virtual File System System Calls
   73  */
   74 
   75 /*
   76  * Mount a file system.
   77  */
   78 /* ARGSUSED */
   79 int
   80 sys_mount(struct proc *p, void *v, register_t *retval)
   81 {
   82         struct sys_mount_args /* {
   83                 syscallarg(const char *) type;
   84                 syscallarg(const char *) path;
   85                 syscallarg(int) flags;
   86                 syscallarg(void *) data;
   87         } */ *uap = v;
   88         struct vnode *vp;
   89         struct mount *mp;
   90         int error, flag = 0;
   91 #ifdef COMPAT_43
   92         u_long fstypenum = 0;
   93 #endif
   94         char fstypename[MFSNAMELEN];
   95         char fspath[MNAMELEN];
   96         struct vattr va;
   97         struct nameidata nd;
   98         struct vfsconf *vfsp;
   99 
  100         if (usermount == 0 && (error = suser(p, 0)))
  101                 return (error);
  102 
  103         /*
  104          * Mount points must fit in MNAMELEN, not MAXPATHLEN.
  105          */
  106         error = copyinstr(SCARG(uap, path), fspath, MNAMELEN, NULL);
  107         if (error)
  108                 return(error);
  109 
  110         /*
  111          * Get vnode to be covered
  112          */
  113         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, fspath, p);
  114         if ((error = namei(&nd)) != 0)
  115                 return (error);
  116         vp = nd.ni_vp;
  117         if (SCARG(uap, flags) & MNT_UPDATE) {
  118                 if ((vp->v_flag & VROOT) == 0) {
  119                         vput(vp);
  120                         return (EINVAL);
  121                 }
  122                 mp = vp->v_mount;
  123                 flag = mp->mnt_flag;
  124                 /*
  125                  * We only allow the filesystem to be reloaded if it
  126                  * is currently mounted read-only.
  127                  */
  128                 if ((SCARG(uap, flags) & MNT_RELOAD) &&
  129                     ((mp->mnt_flag & MNT_RDONLY) == 0)) {
  130                         vput(vp);
  131                         return (EOPNOTSUPP);    /* Needs translation */
  132                 }
  133 
  134                 /*
  135                  * Only root, or the user that did the original mount is
  136                  * permitted to update it.
  137                  */
  138                 if (mp->mnt_stat.f_owner != p->p_ucred->cr_uid &&
  139                     (error = suser(p, 0))) {
  140                         vput(vp);
  141                         return (error);
  142                 }
  143                 /*
  144                  * Do not allow NFS export by non-root users. Silently
  145                  * enforce MNT_NOSUID and MNT_NODEV for non-root users, and
  146                  * inherit MNT_NOEXEC from the mount point.
  147                  */
  148                 if (p->p_ucred->cr_uid != 0) {
  149                         if (SCARG(uap, flags) & MNT_EXPORTED) {
  150                                 vput(vp);
  151                                 return (EPERM);
  152                         }
  153                         SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV;
  154                         if (flag & MNT_NOEXEC)
  155                                 SCARG(uap, flags) |= MNT_NOEXEC;
  156                 }
  157                 if ((error = vfs_busy(mp, VB_READ|VB_NOWAIT)) != 0) {
  158                         vput(vp);
  159                         return (error);
  160                 }
  161                 VOP_UNLOCK(vp, 0, p);
  162                 mp->mnt_flag |= SCARG(uap, flags) & (MNT_RELOAD | MNT_UPDATE);
  163                 goto update;
  164         }
  165         /*
  166          * If the user is not root, ensure that they own the directory
  167          * onto which we are attempting to mount.
  168          */
  169         if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) ||
  170             (va.va_uid != p->p_ucred->cr_uid &&
  171             (error = suser(p, 0)))) {
  172                 vput(vp);
  173                 return (error);
  174         }
  175         /*
  176          * Do not allow NFS export by non-root users. Silently
  177          * enforce MNT_NOSUID and MNT_NODEV for non-root users, and inherit
  178          * MNT_NOEXEC from the mount point.
  179          */
  180         if (p->p_ucred->cr_uid != 0) {
  181                 if (SCARG(uap, flags) & MNT_EXPORTED) {
  182                         vput(vp);
  183                         return (EPERM);
  184                 }
  185                 SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV;
  186                 if (vp->v_mount->mnt_flag & MNT_NOEXEC)
  187                         SCARG(uap, flags) |= MNT_NOEXEC;
  188         }
  189         if ((error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0)) != 0) {
  190                 vput(vp);
  191                 return (error);
  192         }
  193         if (vp->v_type != VDIR) {
  194                 vput(vp);
  195                 return (ENOTDIR);
  196         }
  197         error = copyinstr(SCARG(uap, type), fstypename, MFSNAMELEN, NULL);
  198         if (error) {
  199 #ifdef COMPAT_43
  200                 /*
  201                  * Historically filesystem types were identified by number.
  202                  * If we get an integer for the filesystem type instead of a
  203                  * string, we check to see if it matches one of the historic
  204                  * filesystem types.
  205                  */
  206                 fstypenum = (u_long)SCARG(uap, type);
  207 
  208                 for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
  209                         if (vfsp->vfc_typenum == fstypenum)
  210                                 break;
  211                 if (vfsp == NULL) {
  212                         vput(vp);
  213                         return (ENODEV);
  214                 }
  215                 strncpy(fstypename, vfsp->vfc_name, MFSNAMELEN);
  216 
  217 #else
  218                 vput(vp);
  219                 return (error);
  220 #endif
  221         }
  222         for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) {
  223                 if (!strcmp(vfsp->vfc_name, fstypename))
  224                         break;
  225         }
  226 
  227         if (vfsp == NULL) {
  228                 vput(vp);
  229                 return (EOPNOTSUPP);
  230         }
  231 
  232         if (vp->v_mountedhere != NULL) {
  233                 vput(vp);
  234                 return (EBUSY);
  235         }
  236 
  237         /*
  238          * Allocate and initialize the file system.
  239          */
  240         mp = (struct mount *)malloc((u_long)sizeof(struct mount),
  241                 M_MOUNT, M_WAITOK);
  242         bzero((char *)mp, (u_long)sizeof(struct mount));
  243         (void) vfs_busy(mp, VB_READ|VB_NOWAIT);
  244         mp->mnt_op = vfsp->vfc_vfsops;
  245         mp->mnt_vfc = vfsp;
  246         mp->mnt_flag |= (vfsp->vfc_flags & MNT_VISFLAGMASK);
  247         strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN);
  248         mp->mnt_vnodecovered = vp;
  249         mp->mnt_stat.f_owner = p->p_ucred->cr_uid;
  250 update:
  251         /*
  252          * Set the mount level flags.
  253          */
  254         if (SCARG(uap, flags) & MNT_RDONLY)
  255                 mp->mnt_flag |= MNT_RDONLY;
  256         else if (mp->mnt_flag & MNT_RDONLY)
  257                 mp->mnt_flag |= MNT_WANTRDWR;
  258         mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV |
  259             MNT_SYNCHRONOUS | MNT_ASYNC | MNT_SOFTDEP | MNT_NOATIME |
  260             MNT_FORCE);
  261         mp->mnt_flag |= SCARG(uap, flags) & (MNT_NOSUID | MNT_NOEXEC |
  262             MNT_NODEV | MNT_SYNCHRONOUS | MNT_ASYNC | MNT_SOFTDEP |
  263             MNT_NOATIME | MNT_FORCE);
  264         /*
  265          * Mount the filesystem.
  266          */
  267         error = VFS_MOUNT(mp, SCARG(uap, path), SCARG(uap, data), &nd, p);
  268         if (!error) {
  269                 mp->mnt_stat.f_ctime = time_second;
  270         }
  271         if (mp->mnt_flag & MNT_UPDATE) {
  272                 vrele(vp);
  273                 if (mp->mnt_flag & MNT_WANTRDWR)
  274                         mp->mnt_flag &= ~MNT_RDONLY;
  275                 mp->mnt_flag &=~
  276                     (MNT_UPDATE | MNT_RELOAD | MNT_FORCE | MNT_WANTRDWR);
  277                 if (error)
  278                         mp->mnt_flag = flag;
  279 
  280                 if ((mp->mnt_flag & MNT_RDONLY) == 0) {
  281                         if (mp->mnt_syncer == NULL)
  282                                 error = vfs_allocate_syncvnode(mp);
  283                 } else {
  284                         if (mp->mnt_syncer != NULL)
  285                                 vgone(mp->mnt_syncer);
  286                         mp->mnt_syncer = NULL;
  287                 }
  288 
  289                 vfs_unbusy(mp);
  290                 return (error);
  291         }
  292 
  293         vp->v_mountedhere = mp;
  294 
  295         /*
  296          * Put the new filesystem on the mount list after root.
  297          */
  298         cache_purge(vp);
  299         if (!error) {
  300                 vfsp->vfc_refcount++;
  301                 CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
  302                 checkdirs(vp);
  303                 VOP_UNLOCK(vp, 0, p);
  304                 if ((mp->mnt_flag & MNT_RDONLY) == 0)
  305                         error = vfs_allocate_syncvnode(mp);
  306                 vfs_unbusy(mp);
  307                 (void) VFS_STATFS(mp, &mp->mnt_stat, p);
  308                 if ((error = VFS_START(mp, 0, p)) != 0)
  309                         vrele(vp);
  310         } else {
  311                 mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0;
  312                 vfs_unbusy(mp);
  313                 free(mp, M_MOUNT);
  314                 vput(vp);
  315         }
  316         return (error);
  317 }
  318 
  319 /*
  320  * Scan all active processes to see if any of them have a current
  321  * or root directory onto which the new filesystem has just been
  322  * mounted. If so, replace them with the new mount point.
  323  */
  324 void
  325 checkdirs(struct vnode *olddp)
  326 {
  327         struct filedesc *fdp;
  328         struct vnode *newdp;
  329         struct proc *p;
  330 
  331         if (olddp->v_usecount == 1)
  332                 return;
  333         if (VFS_ROOT(olddp->v_mountedhere, &newdp))
  334                 panic("mount: lost mount");
  335         for (p = LIST_FIRST(&allproc); p != 0; p = LIST_NEXT(p, p_list)) {
  336                 fdp = p->p_fd;
  337                 if (fdp->fd_cdir == olddp) {
  338                         vrele(fdp->fd_cdir);
  339                         VREF(newdp);
  340                         fdp->fd_cdir = newdp;
  341                 }
  342                 if (fdp->fd_rdir == olddp) {
  343                         vrele(fdp->fd_rdir);
  344                         VREF(newdp);
  345                         fdp->fd_rdir = newdp;
  346                 }
  347         }
  348         if (rootvnode == olddp) {
  349                 vrele(rootvnode);
  350                 VREF(newdp);
  351                 rootvnode = newdp;
  352         }
  353         vput(newdp);
  354 }
  355 
  356 /*
  357  * Unmount a file system.
  358  *
  359  * Note: unmount takes a path to the vnode mounted on as argument,
  360  * not special file (as before).
  361  */
  362 /* ARGSUSED */
  363 int
  364 sys_unmount(struct proc *p, void *v, register_t *retval)
  365 {
  366         struct sys_unmount_args /* {
  367                 syscallarg(const char *) path;
  368                 syscallarg(int) flags;
  369         } */ *uap = v;
  370         struct vnode *vp;
  371         struct mount *mp;
  372         int error;
  373         struct nameidata nd;
  374 
  375         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
  376             SCARG(uap, path), p);
  377         if ((error = namei(&nd)) != 0)
  378                 return (error);
  379         vp = nd.ni_vp;
  380         mp = vp->v_mount;
  381 
  382         /*
  383          * Only root, or the user that did the original mount is
  384          * permitted to unmount this filesystem.
  385          */
  386         if ((mp->mnt_stat.f_owner != p->p_ucred->cr_uid) &&
  387             (error = suser(p, 0))) {
  388                 vput(vp);
  389                 return (error);
  390         }
  391 
  392         /*
  393          * Don't allow unmounting the root file system.
  394          */
  395         if (mp->mnt_flag & MNT_ROOTFS) {
  396                 vput(vp);
  397                 return (EINVAL);
  398         }
  399 
  400         /*
  401          * Must be the root of the filesystem
  402          */
  403         if ((vp->v_flag & VROOT) == 0) {
  404                 vput(vp);
  405                 return (EINVAL);
  406         }
  407         vput(vp);
  408 
  409         if (vfs_busy(mp, VB_WRITE|VB_WAIT))
  410                 return (EBUSY);
  411 
  412         return (dounmount(mp, SCARG(uap, flags), p, vp));
  413 }
  414 
  415 /*
  416  * Do the actual file system unmount.
  417  */
  418 int
  419 dounmount(struct mount *mp, int flags, struct proc *p, struct vnode *olddp)
  420 {
  421         struct vnode *coveredvp;
  422         int error;
  423         int hadsyncer = 0;
  424 
  425         mp->mnt_flag &=~ MNT_ASYNC;
  426         cache_purgevfs(mp);     /* remove cache entries for this file sys */
  427         if (mp->mnt_syncer != NULL) {
  428                 hadsyncer = 1;
  429                 vgone(mp->mnt_syncer);
  430                 mp->mnt_syncer = NULL;
  431         }
  432         if (((mp->mnt_flag & MNT_RDONLY) ||
  433             (error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0) ||
  434             (flags & MNT_FORCE))
  435                 error = VFS_UNMOUNT(mp, flags, p);
  436 
  437         if (error && error != EIO && !(flags & MNT_DOOMED)) {
  438                 if ((mp->mnt_flag & MNT_RDONLY) == 0 && hadsyncer)
  439                         (void) vfs_allocate_syncvnode(mp);
  440                 vfs_unbusy(mp);
  441                 return (error);
  442         }
  443 
  444         CIRCLEQ_REMOVE(&mountlist, mp, mnt_list);
  445         if ((coveredvp = mp->mnt_vnodecovered) != NULLVP) {
  446                 coveredvp->v_mountedhere = NULL;
  447                 vrele(coveredvp);
  448         }
  449 
  450         mp->mnt_vfc->vfc_refcount--;
  451 
  452         if (!LIST_EMPTY(&mp->mnt_vnodelist))
  453                 panic("unmount: dangling vnode");
  454 
  455         vfs_unbusy(mp);
  456         free(mp, M_MOUNT);
  457 
  458         return (0);
  459 }
  460 
  461 /*
  462  * Sync each mounted filesystem.
  463  */
  464 #ifdef DEBUG
  465 int syncprt = 0;
  466 struct ctldebug debug0 = { "syncprt", &syncprt };
  467 #endif
  468 
  469 /* ARGSUSED */
  470 int
  471 sys_sync(struct proc *p, void *v, register_t *retval)
  472 {
  473         struct mount *mp, *nmp;
  474         int asyncflag;
  475 
  476         for (mp = CIRCLEQ_LAST(&mountlist); mp != CIRCLEQ_END(&mountlist);
  477             mp = nmp) {
  478                 if (vfs_busy(mp, VB_READ|VB_NOWAIT)) {
  479                         nmp = CIRCLEQ_PREV(mp, mnt_list);
  480                         continue;
  481                 }
  482                 if ((mp->mnt_flag & MNT_RDONLY) == 0) {
  483                         asyncflag = mp->mnt_flag & MNT_ASYNC;
  484                         mp->mnt_flag &= ~MNT_ASYNC;
  485                         uvm_vnp_sync(mp);
  486                         VFS_SYNC(mp, MNT_NOWAIT, p->p_ucred, p);
  487                         if (asyncflag)
  488                                 mp->mnt_flag |= MNT_ASYNC;
  489                 }
  490                 nmp = CIRCLEQ_PREV(mp, mnt_list);
  491                 vfs_unbusy(mp);
  492         }
  493 
  494 #ifdef DEBUG
  495         if (syncprt)
  496                 vfs_bufstats();
  497 #endif /* DEBUG */
  498         return (0);
  499 }
  500 
  501 /*
  502  * Change filesystem quotas.
  503  */
  504 /* ARGSUSED */
  505 int
  506 sys_quotactl(struct proc *p, void *v, register_t *retval)
  507 {
  508         struct sys_quotactl_args /* {
  509                 syscallarg(const char *) path;
  510                 syscallarg(int) cmd;
  511                 syscallarg(int) uid;
  512                 syscallarg(char *) arg;
  513         } */ *uap = v;
  514         struct mount *mp;
  515         int error;
  516         struct nameidata nd;
  517 
  518         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
  519         if ((error = namei(&nd)) != 0)
  520                 return (error);
  521         mp = nd.ni_vp->v_mount;
  522         vrele(nd.ni_vp);
  523         return (VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid),
  524             SCARG(uap, arg), p));
  525 }
  526 
  527 int
  528 copyout_statfs(struct statfs *sp, void *uaddr, struct proc *p)
  529 {
  530         size_t co_sz1 = offsetof(struct statfs, f_fsid);
  531         size_t co_off2 = co_sz1 + sizeof(fsid_t);
  532         size_t co_sz2 = sizeof(struct statfs) - co_off2;
  533         char *s, *d;
  534         int error;
  535 
  536         /* Don't let non-root see filesystem id (for NFS security) */
  537         if (suser(p, 0)) {
  538                 fsid_t fsid;
  539 
  540                 s = (char *)sp;
  541                 d = (char *)uaddr;
  542 
  543                 memset(&fsid, 0, sizeof(fsid));
  544 
  545                 if ((error = copyout(s, d, co_sz1)) != 0)
  546                         return (error);
  547                 if ((error = copyout(&fsid, d + co_sz1, sizeof(fsid))) != 0)
  548                         return (error);
  549                 return (copyout(s + co_off2, d + co_off2, co_sz2));
  550         }
  551 
  552         return (copyout(sp, uaddr, sizeof(*sp)));
  553 }
  554 
  555 /*
  556  * Get filesystem statistics.
  557  */
  558 /* ARGSUSED */
  559 int
  560 sys_statfs(struct proc *p, void *v, register_t *retval)
  561 {
  562         struct sys_statfs_args /* {
  563                 syscallarg(const char *) path;
  564                 syscallarg(struct statfs *) buf;
  565         } */ *uap = v;
  566         struct mount *mp;
  567         struct statfs *sp;
  568         int error;
  569         struct nameidata nd;
  570 
  571         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
  572         if ((error = namei(&nd)) != 0)
  573                 return (error);
  574         mp = nd.ni_vp->v_mount;
  575         sp = &mp->mnt_stat;
  576         vrele(nd.ni_vp);
  577         if ((error = VFS_STATFS(mp, sp, p)) != 0)
  578                 return (error);
  579         sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
  580 #if notyet
  581         if (mp->mnt_flag & MNT_SOFTDEP)
  582                 sp->f_eflags = STATFS_SOFTUPD;
  583 #endif
  584         return (copyout_statfs(sp, SCARG(uap, buf), p));
  585 }
  586 
  587 /*
  588  * Get filesystem statistics.
  589  */
  590 /* ARGSUSED */
  591 int
  592 sys_fstatfs(struct proc *p, void *v, register_t *retval)
  593 {
  594         struct sys_fstatfs_args /* {
  595                 syscallarg(int) fd;
  596                 syscallarg(struct statfs *) buf;
  597         } */ *uap = v;
  598         struct file *fp;
  599         struct mount *mp;
  600         struct statfs *sp;
  601         int error;
  602 
  603         if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
  604                 return (error);
  605         mp = ((struct vnode *)fp->f_data)->v_mount;
  606         if (!mp) {
  607                 FRELE(fp);
  608                 return (ENOENT);
  609         }
  610         sp = &mp->mnt_stat;
  611         error = VFS_STATFS(mp, sp, p);
  612         FRELE(fp);
  613         if (error)
  614                 return (error);
  615         sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
  616 #if notyet
  617         if (mp->mnt_flag & MNT_SOFTDEP)
  618                 sp->f_eflags = STATFS_SOFTUPD;
  619 #endif
  620         return (copyout_statfs(sp, SCARG(uap, buf), p));
  621 }
  622 
  623 /*
  624  * Get statistics on all filesystems.
  625  */
  626 int
  627 sys_getfsstat(struct proc *p, void *v, register_t *retval)
  628 {
  629         struct sys_getfsstat_args /* {
  630                 syscallarg(struct statfs *) buf;
  631                 syscallarg(size_t) bufsize;
  632                 syscallarg(int) flags;
  633         } */ *uap = v;
  634         struct mount *mp, *nmp;
  635         struct statfs *sp;
  636         struct statfs *sfsp;
  637         size_t count, maxcount;
  638         int error, flags = SCARG(uap, flags);
  639 
  640         maxcount = SCARG(uap, bufsize) / sizeof(struct statfs);
  641         sfsp = SCARG(uap, buf);
  642         count = 0;
  643 
  644         for (mp = CIRCLEQ_FIRST(&mountlist); mp != CIRCLEQ_END(&mountlist);
  645             mp = nmp) {
  646                 if (vfs_busy(mp, VB_READ|VB_NOWAIT)) {
  647                         nmp = CIRCLEQ_NEXT(mp, mnt_list);
  648                         continue;
  649                 }
  650                 if (sfsp && count < maxcount) {
  651                         sp = &mp->mnt_stat;
  652 
  653                         /* Refresh stats unless MNT_NOWAIT is specified */
  654                         if (flags != MNT_NOWAIT &&
  655                             flags != MNT_LAZY &&
  656                             (flags == MNT_WAIT ||
  657                             flags == 0) &&
  658                             (error = VFS_STATFS(mp, sp, p))) {
  659                                 nmp = CIRCLEQ_NEXT(mp, mnt_list);
  660                                 vfs_unbusy(mp);
  661                                 continue;
  662                         }
  663 
  664                         sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
  665 #if notyet
  666                         if (mp->mnt_flag & MNT_SOFTDEP)
  667                                 sp->f_eflags = STATFS_SOFTUPD;
  668 #endif
  669                         error = (copyout_statfs(sp, sfsp, p));
  670                         if (error) {
  671                                 vfs_unbusy(mp);
  672                                 return (error);
  673                         }
  674                         sfsp++;
  675                 }
  676                 count++;
  677                 nmp = CIRCLEQ_NEXT(mp, mnt_list);
  678                 vfs_unbusy(mp);
  679         }
  680 
  681         if (sfsp && count > maxcount)
  682                 *retval = maxcount;
  683         else
  684                 *retval = count;
  685 
  686         return (0);
  687 }
  688 
  689 /*
  690  * Change current working directory to a given file descriptor.
  691  */
  692 /* ARGSUSED */
  693 int
  694 sys_fchdir(struct proc *p, void *v, register_t *retval)
  695 {
  696         struct sys_fchdir_args /* {
  697                 syscallarg(int) fd;
  698         } */ *uap = v;
  699         struct filedesc *fdp = p->p_fd;
  700         struct vnode *vp, *tdp;
  701         struct mount *mp;
  702         struct file *fp;
  703         int error;
  704 
  705         if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0)
  706                 return (error);
  707         vp = (struct vnode *)fp->f_data;
  708         VREF(vp);
  709         FRELE(fp);
  710         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
  711         if (vp->v_type != VDIR)
  712                 error = ENOTDIR;
  713         else
  714                 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
  715 
  716         while (!error && (mp = vp->v_mountedhere) != NULL) {
  717                 if (vfs_busy(mp, VB_READ|VB_WAIT))
  718                         continue;
  719                 error = VFS_ROOT(mp, &tdp);
  720                 vfs_unbusy(mp);
  721                 if (error)
  722                         break;
  723                 vput(vp);
  724                 vp = tdp;
  725         }
  726         if (error) {
  727                 vput(vp);
  728                 return (error);
  729         }
  730         VOP_UNLOCK(vp, 0, p);
  731         vrele(fdp->fd_cdir);
  732         fdp->fd_cdir = vp;
  733         return (0);
  734 }
  735 
  736 /*
  737  * Change current working directory (``.'').
  738  */
  739 /* ARGSUSED */
  740 int
  741 sys_chdir(struct proc *p, void *v, register_t *retval)
  742 {
  743         struct sys_chdir_args /* {
  744                 syscallarg(const char *) path;
  745         } */ *uap = v;
  746         struct filedesc *fdp = p->p_fd;
  747         int error;
  748         struct nameidata nd;
  749 
  750         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
  751             SCARG(uap, path), p);
  752         if ((error = change_dir(&nd, p)) != 0)
  753                 return (error);
  754         vrele(fdp->fd_cdir);
  755         fdp->fd_cdir = nd.ni_vp;
  756         return (0);
  757 }
  758 
  759 /*
  760  * Change notion of root (``/'') directory.
  761  */
  762 /* ARGSUSED */
  763 int
  764 sys_chroot(struct proc *p, void *v, register_t *retval)
  765 {
  766         struct sys_chroot_args /* {
  767                 syscallarg(const char *) path;
  768         } */ *uap = v;
  769         struct filedesc *fdp = p->p_fd;
  770         int error;
  771         struct nameidata nd;
  772 
  773         if ((error = suser(p, 0)) != 0)
  774                 return (error);
  775         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
  776             SCARG(uap, path), p);
  777         if ((error = change_dir(&nd, p)) != 0)
  778                 return (error);
  779         if (fdp->fd_rdir != NULL) {
  780                 /*
  781                  * A chroot() done inside a changed root environment does
  782                  * an automatic chdir to avoid the out-of-tree experience.
  783                  */
  784                 vrele(fdp->fd_rdir);
  785                 vrele(fdp->fd_cdir);
  786                 VREF(nd.ni_vp);
  787                 fdp->fd_cdir = nd.ni_vp;
  788         }
  789         fdp->fd_rdir = nd.ni_vp;
  790         return (0);
  791 }
  792 
  793 /*
  794  * Common routine for chroot and chdir.
  795  */
  796 static int
  797 change_dir(struct nameidata *ndp, struct proc *p)
  798 {
  799         struct vnode *vp;
  800         int error;
  801 
  802         if ((error = namei(ndp)) != 0)
  803                 return (error);
  804         vp = ndp->ni_vp;
  805         if (vp->v_type != VDIR)
  806                 error = ENOTDIR;
  807         else
  808                 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
  809         if (error)
  810                 vput(vp);
  811         else
  812                 VOP_UNLOCK(vp, 0, p);
  813         return (error);
  814 }
  815 
  816 /*
  817  * Check permissions, allocate an open file structure,
  818  * and call the device open routine if any.
  819  */
  820 int
  821 sys_open(struct proc *p, void *v, register_t *retval)
  822 {
  823         struct sys_open_args /* {
  824                 syscallarg(const char *) path;
  825                 syscallarg(int) flags;
  826                 syscallarg(mode_t) mode;
  827         } */ *uap = v;
  828         struct filedesc *fdp = p->p_fd;
  829         struct file *fp;
  830         struct vnode *vp;
  831         struct vattr vattr;
  832         int flags, cmode;
  833         int type, indx, error, localtrunc = 0;
  834         struct flock lf;
  835         struct nameidata nd;
  836 
  837         fdplock(fdp);
  838 
  839         if ((error = falloc(p, &fp, &indx)) != 0)
  840                 goto out;
  841 
  842         flags = FFLAGS(SCARG(uap, flags));
  843         cmode = ((SCARG(uap, mode) &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
  844         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
  845         p->p_dupfd = -1;                        /* XXX check for fdopen */
  846         if ((flags & O_TRUNC) && (flags & (O_EXLOCK | O_SHLOCK))) {
  847                 localtrunc = 1;
  848                 flags &= ~O_TRUNC;      /* Must do truncate ourselves */
  849         }
  850         if ((error = vn_open(&nd, flags, cmode)) != 0) {
  851                 if ((error == ENODEV || error == ENXIO) &&
  852                     p->p_dupfd >= 0 &&                  /* XXX from fdopen */
  853                     (error =
  854                         dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) {
  855                         closef(fp, p);
  856                         *retval = indx;
  857                         goto out;
  858                 }
  859                 if (error == ERESTART)
  860                         error = EINTR;
  861                 fdremove(fdp, indx);
  862                 closef(fp, p);
  863                 goto out;
  864         }
  865         p->p_dupfd = 0;
  866         vp = nd.ni_vp;
  867         fp->f_flag = flags & FMASK;
  868         fp->f_type = DTYPE_VNODE;
  869         fp->f_ops = &vnops;
  870         fp->f_data = vp;
  871         if (flags & (O_EXLOCK | O_SHLOCK)) {
  872                 lf.l_whence = SEEK_SET;
  873                 lf.l_start = 0;
  874                 lf.l_len = 0;
  875                 if (flags & O_EXLOCK)
  876                         lf.l_type = F_WRLCK;
  877                 else
  878                         lf.l_type = F_RDLCK;
  879                 type = F_FLOCK;
  880                 if ((flags & FNONBLOCK) == 0)
  881                         type |= F_WAIT;
  882                 VOP_UNLOCK(vp, 0, p);
  883                 error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type);
  884                 if (error) {
  885                         /* closef will vn_close the file for us. */
  886                         fdremove(fdp, indx);
  887                         closef(fp, p);
  888                         goto out;
  889                 }
  890                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
  891                 fp->f_flag |= FHASLOCK;
  892         }
  893         if (localtrunc) {
  894                 if ((fp->f_flag & FWRITE) == 0)
  895                         error = EACCES;
  896                 else if (vp->v_mount->mnt_flag & MNT_RDONLY)
  897                         error = EROFS;
  898                 else if (vp->v_type == VDIR)
  899                         error = EISDIR;
  900                 else if ((error = vn_writechk(vp)) == 0) {
  901                         VATTR_NULL(&vattr);
  902                         vattr.va_size = 0;
  903                         error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
  904                 }
  905                 if (error) {
  906                         VOP_UNLOCK(vp, 0, p);
  907                         /* closef will close the file for us. */
  908                         fdremove(fdp, indx);
  909                         closef(fp, p);
  910                         goto out;
  911                 }
  912         }
  913         VOP_UNLOCK(vp, 0, p);
  914         *retval = indx;
  915         FILE_SET_MATURE(fp);
  916 out:
  917         fdpunlock(fdp);
  918         return (error);
  919 }
  920 
  921 /*
  922  * Get file handle system call
  923  */
  924 int
  925 sys_getfh(struct proc *p, void *v, register_t *retval)
  926 {
  927         struct sys_getfh_args /* {
  928                 syscallarg(const char *) fname;
  929                 syscallarg(fhandle_t *) fhp;
  930         } */ *uap = v;
  931         struct vnode *vp;
  932         fhandle_t fh;
  933         int error;
  934         struct nameidata nd;
  935 
  936         /*
  937          * Must be super user
  938          */
  939         error = suser(p, 0);
  940         if (error)
  941                 return (error);
  942         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
  943             SCARG(uap, fname), p);
  944         error = namei(&nd);
  945         if (error)
  946                 return (error);
  947         vp = nd.ni_vp;
  948         bzero(&fh, sizeof(fh));
  949         fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;
  950         error = VFS_VPTOFH(vp, &fh.fh_fid);
  951         vput(vp);
  952         if (error)
  953                 return (error);
  954         error = copyout(&fh, SCARG(uap, fhp), sizeof(fh));
  955         return (error);
  956 }
  957 
  958 /*
  959  * Open a file given a file handle.
  960  *
  961  * Check permissions, allocate an open file structure,
  962  * and call the device open routine if any.
  963  */
  964 int
  965 sys_fhopen(struct proc *p, void *v, register_t *retval)
  966 {
  967         struct sys_fhopen_args /* {
  968                 syscallarg(const fhandle_t *) fhp;
  969                 syscallarg(int) flags;
  970         } */ *uap = v;
  971         struct filedesc *fdp = p->p_fd;
  972         struct file *fp;
  973         struct vnode *vp = NULL;
  974         struct mount *mp;
  975         struct ucred *cred = p->p_ucred;
  976         int flags;
  977         int type, indx, error=0;
  978         struct flock lf;
  979         struct vattr va;
  980         fhandle_t fh;
  981 
  982         /*
  983          * Must be super user
  984          */
  985         if ((error = suser(p, 0)))
  986                 return (error);
  987 
  988         flags = FFLAGS(SCARG(uap, flags));
  989         if ((flags & (FREAD | FWRITE)) == 0)
  990                 return (EINVAL);
  991         if ((flags & O_CREAT))
  992                 return (EINVAL);
  993 
  994         fdplock(fdp);
  995         if ((error = falloc(p, &fp, &indx)) != 0) {
  996                 fp = NULL;
  997                 goto bad;
  998         }
  999 
 1000         if ((error = copyin(SCARG(uap, fhp), &fh, sizeof(fhandle_t))) != 0)
 1001                 goto bad;
 1002 
 1003         if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) {
 1004                 error = ESTALE;
 1005                 goto bad;
 1006         }
 1007 
 1008         if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)) != 0) {
 1009                 vp = NULL;      /* most likely unnecessary sanity for bad: */
 1010                 goto bad;
 1011         }
 1012 
 1013         /* Now do an effective vn_open */
 1014 
 1015         if (vp->v_type == VSOCK) {
 1016                 error = EOPNOTSUPP;
 1017                 goto bad;
 1018         }
 1019         if (flags & FREAD) {
 1020                 if ((error = VOP_ACCESS(vp, VREAD, cred, p)) != 0)
 1021                         goto bad;
 1022         }
 1023         if (flags & (FWRITE | O_TRUNC)) {
 1024                 if (vp->v_type == VDIR) {
 1025                         error = EISDIR;
 1026                         goto bad;
 1027                 }
 1028                 if ((error = vn_writechk(vp)) != 0 ||
 1029                     (error = VOP_ACCESS(vp, VWRITE, cred, p)) != 0)
 1030                         goto bad;
 1031         }
 1032         if (flags & O_TRUNC) {
 1033                 VATTR_NULL(&va);
 1034                 va.va_size = 0;
 1035                 if ((error = VOP_SETATTR(vp, &va, cred, p)) != 0)
 1036                         goto bad;
 1037         }
 1038         if ((error = VOP_OPEN(vp, flags, cred, p)) != 0)
 1039                 goto bad;
 1040         if (flags & FWRITE)
 1041                 vp->v_writecount++;
 1042 
 1043         /* done with modified vn_open, now finish what sys_open does. */
 1044 
 1045         fp->f_flag = flags & FMASK;
 1046         fp->f_type = DTYPE_VNODE;
 1047         fp->f_ops = &vnops;
 1048         fp->f_data = vp;
 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                 VOP_UNLOCK(vp, 0, p);
 1061                 error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type);
 1062                 if (error)
 1063                         goto bad;
 1064                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
 1065                 fp->f_flag |= FHASLOCK;
 1066         }
 1067         VOP_UNLOCK(vp, 0, p);
 1068         *retval = indx;
 1069         FILE_SET_MATURE(fp);
 1070 
 1071         fdpunlock(fdp);
 1072         return (0);
 1073 
 1074 bad:
 1075         if (fp) {
 1076                 fdremove(fdp, indx);
 1077                 closef(fp, p);
 1078                 if (vp != NULL)
 1079                         vput(vp);
 1080         }
 1081         fdpunlock(fdp);
 1082         return (error);
 1083 }
 1084 
 1085 /* ARGSUSED */
 1086 int
 1087 sys_fhstat(struct proc *p, void *v, register_t *retval)
 1088 {
 1089         struct sys_fhstat_args /* {
 1090                 syscallarg(const fhandle_t *) fhp;
 1091                 syscallarg(struct stat *) sb;
 1092         } */ *uap = v;
 1093         struct stat sb;
 1094         int error;
 1095         fhandle_t fh;
 1096         struct mount *mp;
 1097         struct vnode *vp;
 1098 
 1099         /*
 1100          * Must be super user
 1101          */
 1102         if ((error = suser(p, 0)))
 1103                 return (error);
 1104 
 1105         if ((error = copyin(SCARG(uap, fhp), &fh, sizeof(fhandle_t))) != 0)
 1106                 return (error);
 1107 
 1108         if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
 1109                 return (ESTALE);
 1110         if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
 1111                 return (error);
 1112         error = vn_stat(vp, &sb, p);
 1113         vput(vp);
 1114         if (error)
 1115                 return (error);
 1116         error = copyout(&sb, SCARG(uap, sb), sizeof(sb));
 1117         return (error);
 1118 }
 1119 
 1120 /* ARGSUSED */
 1121 int
 1122 sys_fhstatfs(struct proc *p, void *v, register_t *retval)
 1123 {
 1124         struct sys_fhstatfs_args /*
 1125                 syscallarg(const fhandle_t *) fhp;
 1126                 syscallarg(struct statfs *) buf;
 1127         } */ *uap = v;
 1128         struct statfs *sp;
 1129         fhandle_t fh;
 1130         struct mount *mp;
 1131         struct vnode *vp;
 1132         int error;
 1133 
 1134         /*
 1135          * Must be super user
 1136          */
 1137         if ((error = suser(p, 0)))
 1138                 return (error);
 1139 
 1140         if ((error = copyin(SCARG(uap, fhp), &fh, sizeof(fhandle_t))) != 0)
 1141                 return (error);
 1142 
 1143         if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
 1144                 return (ESTALE);
 1145         if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
 1146                 return (error);
 1147         mp = vp->v_mount;
 1148         sp = &mp->mnt_stat;
 1149         vput(vp);
 1150         if ((error = VFS_STATFS(mp, sp, p)) != 0)
 1151                 return (error);
 1152         sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
 1153         return (copyout(sp, SCARG(uap, buf), sizeof(sp)));
 1154 }
 1155 
 1156 /*
 1157  * Create a special file.
 1158  */
 1159 /* ARGSUSED */
 1160 int
 1161 sys_mknod(struct proc *p, void *v, register_t *retval)
 1162 {
 1163         struct sys_mknod_args /* {
 1164                 syscallarg(const char *) path;
 1165                 syscallarg(mode_t) mode;
 1166                 syscallarg(int) dev;
 1167         } */ *uap = v;
 1168         struct vnode *vp;
 1169         struct vattr vattr;
 1170         int error;
 1171         struct nameidata nd;
 1172 
 1173         if ((error = suser(p, 0)) != 0)
 1174                 return (error);
 1175         if (p->p_fd->fd_rdir)
 1176                 return (EINVAL);
 1177         NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
 1178         if ((error = namei(&nd)) != 0)
 1179                 return (error);
 1180         vp = nd.ni_vp;
 1181         if (vp != NULL)
 1182                 error = EEXIST;
 1183         else {
 1184                 VATTR_NULL(&vattr);
 1185                 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
 1186                 vattr.va_rdev = SCARG(uap, dev);
 1187 
 1188                 switch (SCARG(uap, mode) & S_IFMT) {
 1189                 case S_IFMT:    /* used by badsect to flag bad sectors */
 1190                         vattr.va_type = VBAD;
 1191                         break;
 1192                 case S_IFCHR:
 1193                         vattr.va_type = VCHR;
 1194                         break;
 1195                 case S_IFBLK:
 1196                         vattr.va_type = VBLK;
 1197                         break;
 1198                 default:
 1199                         error = EINVAL;
 1200                         break;
 1201                 }
 1202         }
 1203         if (!error) {
 1204                 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
 1205         } else {
 1206                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
 1207                 if (nd.ni_dvp == vp)
 1208                         vrele(nd.ni_dvp);
 1209                 else
 1210                         vput(nd.ni_dvp);
 1211                 if (vp)
 1212                         vrele(vp);
 1213         }
 1214         return (error);
 1215 }
 1216 
 1217 /*
 1218  * Create a named pipe.
 1219  */
 1220 /* ARGSUSED */
 1221 int
 1222 sys_mkfifo(struct proc *p, void *v, register_t *retval)
 1223 {
 1224 #ifndef FIFO
 1225         return (EOPNOTSUPP);
 1226 #else
 1227         struct sys_mkfifo_args /* {
 1228                 syscallarg(const char *) path;
 1229                 syscallarg(mode_t) mode;
 1230         } */ *uap = v;
 1231         struct vattr vattr;
 1232         int error;
 1233         struct nameidata nd;
 1234 
 1235         NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
 1236         if ((error = namei(&nd)) != 0)
 1237                 return (error);
 1238         if (nd.ni_vp != NULL) {
 1239                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
 1240                 if (nd.ni_dvp == nd.ni_vp)
 1241                         vrele(nd.ni_dvp);
 1242                 else
 1243                         vput(nd.ni_dvp);
 1244                 vrele(nd.ni_vp);
 1245                 return (EEXIST);
 1246         }
 1247         VATTR_NULL(&vattr);
 1248         vattr.va_type = VFIFO;
 1249         vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
 1250         return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr));
 1251 #endif /* FIFO */
 1252 }
 1253 
 1254 /*
 1255  * Make a hard file link.
 1256  */
 1257 /* ARGSUSED */
 1258 int
 1259 sys_link(struct proc *p, void *v, register_t *retval)
 1260 {
 1261         struct sys_link_args /* {
 1262                 syscallarg(const char *) path;
 1263                 syscallarg(const char *) link;
 1264         } */ *uap = v;
 1265         struct vnode *vp;
 1266         struct nameidata nd;
 1267         int error;
 1268         int flags;
 1269 
 1270         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
 1271         if ((error = namei(&nd)) != 0)
 1272                 return (error);
 1273         vp = nd.ni_vp;
 1274 
 1275         flags = LOCKPARENT;
 1276         if (vp->v_type == VDIR) {
 1277                 flags |= STRIPSLASHES;
 1278         }
 1279 
 1280         NDINIT(&nd, CREATE, flags, UIO_USERSPACE, SCARG(uap, link), p);
 1281         if ((error = namei(&nd)) != 0)
 1282                 goto out;
 1283         if (nd.ni_vp) {
 1284                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
 1285                 if (nd.ni_dvp == nd.ni_vp)
 1286                         vrele(nd.ni_dvp);
 1287                 else
 1288                         vput(nd.ni_dvp);
 1289                 vrele(nd.ni_vp);
 1290                 error = EEXIST;
 1291                 goto out;
 1292         }
 1293         error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
 1294 out:
 1295         vrele(vp);
 1296         return (error);
 1297 }
 1298 
 1299 /*
 1300  * Make a symbolic link.
 1301  */
 1302 /* ARGSUSED */
 1303 int
 1304 sys_symlink(struct proc *p, void *v, register_t *retval)
 1305 {
 1306         struct sys_symlink_args /* {
 1307                 syscallarg(const char *) path;
 1308                 syscallarg(const char *) link;
 1309         } */ *uap = v;
 1310         struct vattr vattr;
 1311         char *path;
 1312         int error;
 1313         struct nameidata nd;
 1314 
 1315         path = pool_get(&namei_pool, PR_WAITOK);
 1316         error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL);
 1317         if (error)
 1318                 goto out;
 1319         NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p);
 1320         if ((error = namei(&nd)) != 0)
 1321                 goto out;
 1322         if (nd.ni_vp) {
 1323                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
 1324                 if (nd.ni_dvp == nd.ni_vp)
 1325                         vrele(nd.ni_dvp);
 1326                 else
 1327                         vput(nd.ni_dvp);
 1328                 vrele(nd.ni_vp);
 1329                 error = EEXIST;
 1330                 goto out;
 1331         }
 1332         VATTR_NULL(&vattr);
 1333         vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask;
 1334         error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path);
 1335 out:
 1336         pool_put(&namei_pool, path);
 1337         return (error);
 1338 }
 1339 
 1340 /*
 1341  * Delete a name from the filesystem.
 1342  */
 1343 /* ARGSUSED */
 1344 int
 1345 sys_unlink(struct proc *p, void *v, register_t *retval)
 1346 {
 1347         struct sys_unlink_args /* {
 1348                 syscallarg(const char *) path;
 1349         } */ *uap = v;
 1350         struct vnode *vp;
 1351         int error;
 1352         struct nameidata nd;
 1353 
 1354         NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
 1355             SCARG(uap, path), p);
 1356         if ((error = namei(&nd)) != 0)
 1357                 return (error);
 1358         vp = nd.ni_vp;
 1359 
 1360         /*
 1361          * The root of a mounted filesystem cannot be deleted.
 1362          */
 1363         if (vp->v_flag & VROOT) {
 1364                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
 1365                 if (nd.ni_dvp == vp)
 1366                         vrele(nd.ni_dvp);
 1367                 else
 1368                         vput(nd.ni_dvp);
 1369                 vput(vp);
 1370                 error = EBUSY;
 1371                 goto out;
 1372         }
 1373 
 1374         (void)uvm_vnp_uncache(vp);
 1375 
 1376         error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
 1377 out:
 1378         return (error);
 1379 }
 1380 
 1381 /*
 1382  * Reposition read/write file offset.
 1383  */
 1384 int
 1385 sys_lseek(struct proc *p, void *v, register_t *retval)
 1386 {
 1387         struct sys_lseek_args /* {
 1388                 syscallarg(int) fd;
 1389                 syscallarg(int) pad;
 1390                 syscallarg(off_t) offset;
 1391                 syscallarg(int) whence;
 1392         } */ *uap = v;
 1393         struct ucred *cred = p->p_ucred;
 1394         struct filedesc *fdp = p->p_fd;
 1395         struct file *fp;
 1396         struct vattr vattr;
 1397         struct vnode *vp;
 1398         off_t offarg, newoff;
 1399         int error, special;
 1400 
 1401         if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL)
 1402                 return (EBADF);
 1403         if (fp->f_type != DTYPE_VNODE)
 1404                 return (ESPIPE);
 1405         vp = (struct vnode *)fp->f_data;
 1406         if (vp->v_type == VFIFO)
 1407                 return (ESPIPE);
 1408         if (vp->v_type == VCHR)
 1409                 special = 1;
 1410         else
 1411                 special = 0;
 1412         offarg = SCARG(uap, offset);
 1413 
 1414         switch (SCARG(uap, whence)) {
 1415         case SEEK_CUR:
 1416                 newoff = fp->f_offset + offarg;;
 1417                 break;
 1418         case SEEK_END:
 1419                 error = VOP_GETATTR((struct vnode *)fp->f_data, &vattr,
 1420                                     cred, p);
 1421                 if (error)
 1422                         return (error);
 1423                 newoff = offarg + (off_t)vattr.va_size;
 1424                 break;
 1425         case SEEK_SET:
 1426                 newoff = offarg;
 1427                 break;
 1428         default:
 1429                 return (EINVAL);
 1430         }
 1431         if (!special) {
 1432                 if (newoff < 0)
 1433                         return (EINVAL);
 1434         } else {
 1435                 /*
 1436                  * Make sure the user don't seek beyond the end of the
 1437                  * partition.
 1438                  */
 1439                 struct partinfo dpart;
 1440                 error = vn_ioctl(fp, DIOCGPART, (void *)&dpart, p);
 1441                 if (!error) {
 1442                         if (newoff >= DL_GETPSIZE(dpart.part) *
 1443                             dpart.disklab->d_secsize)
 1444                                         return (EINVAL);
 1445                 }
 1446         }
 1447         *(off_t *)retval = fp->f_offset = newoff;
 1448         fp->f_seek++;
 1449         return (0);
 1450 }
 1451 
 1452 /*
 1453  * Check access permissions.
 1454  */
 1455 int
 1456 sys_access(struct proc *p, void *v, register_t *retval)
 1457 {
 1458         struct sys_access_args /* {
 1459                 syscallarg(const char *) path;
 1460                 syscallarg(int) flags;
 1461         } */ *uap = v;
 1462         struct ucred *cred = p->p_ucred;
 1463         struct vnode *vp;
 1464         int error, flags, t_gid, t_uid;
 1465         struct nameidata nd;
 1466 
 1467         if (SCARG(uap, flags) & ~(R_OK | W_OK | X_OK))
 1468                 return (EINVAL);
 1469         t_uid = cred->cr_uid;
 1470         t_gid = cred->cr_gid;
 1471         cred->cr_uid = p->p_cred->p_ruid;
 1472         cred->cr_gid = p->p_cred->p_rgid;
 1473         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
 1474             SCARG(uap, path), p);
 1475         if ((error = namei(&nd)) != 0)
 1476                 goto out1;
 1477         vp = nd.ni_vp;
 1478 
 1479         /* Flags == 0 means only check for existence. */
 1480         if (SCARG(uap, flags)) {
 1481                 flags = 0;
 1482                 if (SCARG(uap, flags) & R_OK)
 1483                         flags |= VREAD;
 1484                 if (SCARG(uap, flags) & W_OK)
 1485                         flags |= VWRITE;
 1486                 if (SCARG(uap, flags) & X_OK)
 1487                         flags |= VEXEC;
 1488                 if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
 1489                         error = VOP_ACCESS(vp, flags, cred, p);
 1490         }
 1491         vput(vp);
 1492 out1:
 1493         cred->cr_uid = t_uid;
 1494         cred->cr_gid = t_gid;
 1495         return (error);
 1496 }
 1497 
 1498 /*
 1499  * Get file status; this version follows links.
 1500  */
 1501 /* ARGSUSED */
 1502 int
 1503 sys_stat(struct proc *p, void *v, register_t *retval)
 1504 {
 1505         struct sys_stat_args /* {
 1506                 syscallarg(const char *) path;
 1507                 syscallarg(struct stat *) ub;
 1508         } */ *uap = v;
 1509         struct stat sb;
 1510         int error;
 1511         struct nameidata nd;
 1512 
 1513         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
 1514             SCARG(uap, path), p);
 1515         if ((error = namei(&nd)) != 0)
 1516                 return (error);
 1517         error = vn_stat(nd.ni_vp, &sb, p);
 1518         vput(nd.ni_vp);
 1519         if (error)
 1520                 return (error);
 1521         /* Don't let non-root see generation numbers (for NFS security) */
 1522         if (suser(p, 0))
 1523                 sb.st_gen = 0;
 1524         error = copyout(&sb, SCARG(uap, ub), sizeof(sb));
 1525         return (error);
 1526 }
 1527 
 1528 /*
 1529  * Get file status; this version does not follow links.
 1530  */
 1531 /* ARGSUSED */
 1532 int
 1533 sys_lstat(struct proc *p, void *v, register_t *retval)
 1534 {
 1535         struct sys_lstat_args /* {
 1536                 syscallarg(const char *) path;
 1537                 syscallarg(struct stat *) ub;
 1538         } */ *uap = v;
 1539         struct stat sb;
 1540         int error;
 1541         struct nameidata nd;
 1542 
 1543         NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
 1544             SCARG(uap, path), p);
 1545         if ((error = namei(&nd)) != 0)
 1546                 return (error);
 1547         error = vn_stat(nd.ni_vp, &sb, p);
 1548         vput(nd.ni_vp);
 1549         if (error)
 1550                 return (error);
 1551         /* Don't let non-root see generation numbers (for NFS security) */
 1552         if (suser(p, 0))
 1553                 sb.st_gen = 0;
 1554         error = copyout(&sb, SCARG(uap, ub), sizeof(sb));
 1555         return (error);
 1556 }
 1557 
 1558 /*
 1559  * Get configurable pathname variables.
 1560  */
 1561 /* ARGSUSED */
 1562 int
 1563 sys_pathconf(struct proc *p, void *v, register_t *retval)
 1564 {
 1565         struct sys_pathconf_args /* {
 1566                 syscallarg(const char *) path;
 1567                 syscallarg(int) name;
 1568         } */ *uap = v;
 1569         int error;
 1570         struct nameidata nd;
 1571 
 1572         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
 1573             SCARG(uap, path), p);
 1574         if ((error = namei(&nd)) != 0)
 1575                 return (error);
 1576         error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), retval);
 1577         vput(nd.ni_vp);
 1578         return (error);
 1579 }
 1580 
 1581 /*
 1582  * Return target name of a symbolic link.
 1583  */
 1584 /* ARGSUSED */
 1585 int
 1586 sys_readlink(struct proc *p, void *v, register_t *retval)
 1587 {
 1588         struct sys_readlink_args /* {
 1589                 syscallarg(const char *) path;
 1590                 syscallarg(char *) buf;
 1591                 syscallarg(size_t) count;
 1592         } */ *uap = v;
 1593         struct vnode *vp;
 1594         struct iovec aiov;
 1595         struct uio auio;
 1596         int error;
 1597         struct nameidata nd;
 1598 
 1599         NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
 1600             SCARG(uap, path), p);
 1601         if ((error = namei(&nd)) != 0)
 1602                 return (error);
 1603         vp = nd.ni_vp;
 1604         if (vp->v_type != VLNK)
 1605                 error = EINVAL;
 1606         else {
 1607                 aiov.iov_base = SCARG(uap, buf);
 1608                 aiov.iov_len = SCARG(uap, count);
 1609                 auio.uio_iov = &aiov;
 1610                 auio.uio_iovcnt = 1;
 1611                 auio.uio_offset = 0;
 1612                 auio.uio_rw = UIO_READ;
 1613                 auio.uio_segflg = UIO_USERSPACE;
 1614                 auio.uio_procp = p;
 1615                 auio.uio_resid = SCARG(uap, count);
 1616                 error = VOP_READLINK(vp, &auio, p->p_ucred);
 1617         }
 1618         vput(vp);
 1619         *retval = SCARG(uap, count) - auio.uio_resid;
 1620         return (error);
 1621 }
 1622 
 1623 /*
 1624  * Change flags of a file given a path name.
 1625  */
 1626 /* ARGSUSED */
 1627 int
 1628 sys_chflags(struct proc *p, void *v, register_t *retval)
 1629 {
 1630         struct sys_chflags_args /* {
 1631                 syscallarg(const char *) path;
 1632                 syscallarg(u_int) flags;
 1633         } */ *uap = v;
 1634         struct vnode *vp;
 1635         struct vattr vattr;
 1636         int error;
 1637         struct nameidata nd;
 1638 
 1639         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
 1640         if ((error = namei(&nd)) != 0)
 1641                 return (error);
 1642         vp = nd.ni_vp;
 1643         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
 1644         if (vp->v_mount->mnt_flag & MNT_RDONLY)
 1645                 error = EROFS;
 1646         else if (SCARG(uap, flags) == VNOVAL)
 1647                 error = EINVAL;
 1648         else {
 1649                 if (suser(p, 0)) {
 1650                         if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0)
 1651                                 goto out;
 1652                         if (vattr.va_type == VCHR || vattr.va_type == VBLK) {
 1653                                 error = EINVAL;
 1654                                 goto out;
 1655                         }
 1656                 }
 1657                 VATTR_NULL(&vattr);
 1658                 vattr.va_flags = SCARG(uap, flags);
 1659                 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
 1660         }
 1661 out:
 1662         vput(vp);
 1663         return (error);
 1664 }
 1665 
 1666 /*
 1667  * Change flags of a file given a file descriptor.
 1668  */
 1669 /* ARGSUSED */
 1670 int
 1671 sys_fchflags(struct proc *p, void *v, register_t *retval)
 1672 {
 1673         struct sys_fchflags_args /* {
 1674                 syscallarg(int) fd;
 1675                 syscallarg(u_int) flags;
 1676         } */ *uap = v;
 1677         struct vattr vattr;
 1678         struct vnode *vp;
 1679         struct file *fp;
 1680         int error;
 1681 
 1682         if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
 1683                 return (error);
 1684         vp = (struct vnode *)fp->f_data;
 1685         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
 1686         if (vp->v_mount && vp->v_mount->mnt_flag & MNT_RDONLY)
 1687                 error = EROFS;
 1688         else if (SCARG(uap, flags) == VNOVAL)
 1689                 error = EINVAL;
 1690         else {
 1691                 if (suser(p, 0)) {
 1692                         if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p))
 1693                             != 0)
 1694                                 goto out;
 1695                         if (vattr.va_type == VCHR || vattr.va_type == VBLK) {
 1696                                 error = EINVAL;
 1697                                 goto out;
 1698                         }
 1699                 }
 1700                 VATTR_NULL(&vattr);
 1701                 vattr.va_flags = SCARG(uap, flags);
 1702                 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
 1703         }
 1704 out:
 1705         VOP_UNLOCK(vp, 0, p);
 1706         FRELE(fp);
 1707         return (error);
 1708 }
 1709 
 1710 /*
 1711  * Change mode of a file given path name.
 1712  */
 1713 /* ARGSUSED */
 1714 int
 1715 sys_chmod(struct proc *p, void *v, register_t *retval)
 1716 {
 1717         struct sys_chmod_args /* {
 1718                 syscallarg(const char *) path;
 1719                 syscallarg(mode_t) mode;
 1720         } */ *uap = v;
 1721         struct vnode *vp;
 1722         struct vattr vattr;
 1723         int error;
 1724         struct nameidata nd;
 1725 
 1726         if (SCARG(uap, mode) & ~(S_IFMT | ALLPERMS))
 1727                 return (EINVAL);
 1728 
 1729         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
 1730         if ((error = namei(&nd)) != 0)
 1731                 return (error);
 1732         vp = nd.ni_vp;
 1733         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
 1734         if (vp->v_mount->mnt_flag & MNT_RDONLY)
 1735                 error = EROFS;
 1736         else {
 1737                 VATTR_NULL(&vattr);
 1738                 vattr.va_mode = SCARG(uap, mode) & ALLPERMS;
 1739                 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
 1740         }
 1741         vput(vp);
 1742         return (error);
 1743 }
 1744 
 1745 /*
 1746  * Change mode of a file given a file descriptor.
 1747  */
 1748 /* ARGSUSED */
 1749 int
 1750 sys_fchmod(struct proc *p, void *v, register_t *retval)
 1751 {
 1752         struct sys_fchmod_args /* {
 1753                 syscallarg(int) fd;
 1754                 syscallarg(mode_t) mode;
 1755         } */ *uap = v;
 1756         struct vattr vattr;
 1757         struct vnode *vp;
 1758         struct file *fp;
 1759         int error;
 1760 
 1761         if (SCARG(uap, mode) & ~(S_IFMT | ALLPERMS))
 1762                 return (EINVAL);
 1763 
 1764         if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
 1765                 return (error);
 1766         vp = (struct vnode *)fp->f_data;
 1767         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
 1768         if (vp->v_mount && vp->v_mount->mnt_flag & MNT_RDONLY)
 1769                 error = EROFS;
 1770         else {
 1771                 VATTR_NULL(&vattr);
 1772                 vattr.va_mode = SCARG(uap, mode) & ALLPERMS;
 1773                 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
 1774         }
 1775         VOP_UNLOCK(vp, 0, p);
 1776         FRELE(fp);
 1777         return (error);
 1778 }
 1779 
 1780 /*
 1781  * Set ownership given a path name.
 1782  */
 1783 /* ARGSUSED */
 1784 int
 1785 sys_chown(struct proc *p, void *v, register_t *retval)
 1786 {
 1787         struct sys_chown_args /* {
 1788                 syscallarg(const char *) path;
 1789                 syscallarg(uid_t) uid;
 1790                 syscallarg(gid_t) gid;
 1791         } */ *uap = v;
 1792         struct vnode *vp;
 1793         struct vattr vattr;
 1794         int error;
 1795         struct nameidata nd;
 1796         mode_t mode;
 1797 
 1798         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
 1799         if ((error = namei(&nd)) != 0)
 1800                 return (error);
 1801         vp = nd.ni_vp;
 1802         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
 1803         if (vp->v_mount->mnt_flag & MNT_RDONLY)
 1804                 error = EROFS;
 1805         else {
 1806                 if ((SCARG(uap, uid) != -1 || SCARG(uap, gid) != -1) &&
 1807                     (suser(p, 0) || suid_clear)) {
 1808                         error = VOP_GETATTR(vp, &vattr, p->p_ucred, p);
 1809                         if (error)
 1810                                 goto out;
 1811                         mode = vattr.va_mode & ~(VSUID | VSGID);
 1812                         if (mode == vattr.va_mode)
 1813                                 mode = VNOVAL;
 1814                 }
 1815                 else
 1816                         mode = VNOVAL;
 1817                 VATTR_NULL(&vattr);
 1818                 vattr.va_uid = SCARG(uap, uid);
 1819                 vattr.va_gid = SCARG(uap, gid);
 1820                 vattr.va_mode = mode;
 1821                 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
 1822         }
 1823 out:
 1824         vput(vp);
 1825         return (error);
 1826 }
 1827 
 1828 /*
 1829  * Set ownership given a path name, without following links.
 1830  */
 1831 /* ARGSUSED */
 1832 int
 1833 sys_lchown(struct proc *p, void *v, register_t *retval)
 1834 {
 1835         struct sys_lchown_args /* {
 1836                 syscallarg(const char *) path;
 1837                 syscallarg(uid_t) uid;
 1838                 syscallarg(gid_t) gid;
 1839         } */ *uap = v;
 1840         struct vnode *vp;
 1841         struct vattr vattr;
 1842         int error;
 1843         struct nameidata nd;
 1844         mode_t mode;
 1845 
 1846         NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
 1847         if ((error = namei(&nd)) != 0)
 1848                 return (error);
 1849         vp = nd.ni_vp;
 1850         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
 1851         if (vp->v_mount->mnt_flag & MNT_RDONLY)
 1852                 error = EROFS;
 1853         else {
 1854                 if ((SCARG(uap, uid) != -1 || SCARG(uap, gid) != -1) &&
 1855                     (suser(p, 0) || suid_clear)) {
 1856                         error = VOP_GETATTR(vp, &vattr, p->p_ucred, p);
 1857                         if (error)
 1858                                 goto out;
 1859                         mode = vattr.va_mode & ~(VSUID | VSGID);
 1860                         if (mode == vattr.va_mode)
 1861                                 mode = VNOVAL;
 1862                 }
 1863                 else
 1864                         mode = VNOVAL;
 1865                 VATTR_NULL(&vattr);
 1866                 vattr.va_uid = SCARG(uap, uid);
 1867                 vattr.va_gid = SCARG(uap, gid);
 1868                 vattr.va_mode = mode;
 1869                 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
 1870         }
 1871 out:
 1872         vput(vp);
 1873         return (error);
 1874 }
 1875 
 1876 /*
 1877  * Set ownership given a file descriptor.
 1878  */
 1879 /* ARGSUSED */
 1880 int
 1881 sys_fchown(struct proc *p, void *v, register_t *retval)
 1882 {
 1883         struct sys_fchown_args /* {
 1884                 syscallarg(int) fd;
 1885                 syscallarg(uid_t) uid;
 1886                 syscallarg(gid_t) gid;
 1887         } */ *uap = v;
 1888         struct vnode *vp;
 1889         struct vattr vattr;
 1890         int error;
 1891         struct file *fp;
 1892         mode_t mode;
 1893 
 1894         if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
 1895                 return (error);
 1896         vp = (struct vnode *)fp->f_data;
 1897         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
 1898         if (vp->v_mount->mnt_flag & MNT_RDONLY)
 1899                 error = EROFS;
 1900         else {
 1901                 if ((SCARG(uap, uid) != -1 || SCARG(uap, gid) != -1) &&
 1902                     (suser(p, 0) || suid_clear)) {
 1903                         error = VOP_GETATTR(vp, &vattr, p->p_ucred, p);
 1904                         if (error)
 1905                                 goto out;
 1906                         mode = vattr.va_mode & ~(VSUID | VSGID);
 1907                         if (mode == vattr.va_mode)
 1908                                 mode = VNOVAL;
 1909                 } else
 1910                         mode = VNOVAL;
 1911                 VATTR_NULL(&vattr);
 1912                 vattr.va_uid = SCARG(uap, uid);
 1913                 vattr.va_gid = SCARG(uap, gid);
 1914                 vattr.va_mode = mode;
 1915                 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
 1916         }
 1917 out:
 1918         VOP_UNLOCK(vp, 0, p);
 1919         FRELE(fp);
 1920         return (error);
 1921 }
 1922 
 1923 /*
 1924  * Set the access and modification times given a path name.
 1925  */
 1926 /* ARGSUSED */
 1927 int
 1928 sys_utimes(struct proc *p, void *v, register_t *retval)
 1929 {
 1930         struct sys_utimes_args /* {
 1931                 syscallarg(const char *) path;
 1932                 syscallarg(const struct timeval *) tptr;
 1933         } */ *uap = v;
 1934         struct vnode *vp;
 1935         struct timeval tv[2];
 1936         struct vattr vattr;
 1937         int error;
 1938         struct nameidata nd;
 1939 
 1940         VATTR_NULL(&vattr);
 1941         if (SCARG(uap, tptr) == NULL) {
 1942                 microtime(&tv[0]);
 1943                 tv[1] = tv[0];
 1944                 vattr.va_vaflags |= VA_UTIMES_NULL;
 1945         } else {
 1946                 error = copyin(SCARG(uap, tptr), tv,
 1947                     sizeof(tv));
 1948                 if (error)
 1949                         return (error);
 1950                 /* XXX workaround timeval matching the VFS constant VNOVAL */
 1951                 if (tv[0].tv_sec == VNOVAL)
 1952                         tv[0].tv_sec = VNOVAL - 1;
 1953                 if (tv[1].tv_sec == VNOVAL)
 1954                         tv[1].tv_sec = VNOVAL - 1;
 1955         }
 1956         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
 1957         if ((error = namei(&nd)) != 0)
 1958                 return (error);
 1959         vp = nd.ni_vp;
 1960         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
 1961         if (vp->v_mount->mnt_flag & MNT_RDONLY)
 1962                 error = EROFS;
 1963         else {
 1964                 vattr.va_atime.tv_sec = tv[0].tv_sec;
 1965                 vattr.va_atime.tv_nsec = tv[0].tv_usec * 1000;
 1966                 vattr.va_mtime.tv_sec = tv[1].tv_sec;
 1967                 vattr.va_mtime.tv_nsec = tv[1].tv_usec * 1000;
 1968                 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
 1969         }
 1970         vput(vp);
 1971         return (error);
 1972 }
 1973 
 1974 /*
 1975  * Set the access and modification times given a file descriptor.
 1976  */
 1977 /* ARGSUSED */
 1978 int
 1979 sys_futimes(struct proc *p, void *v, register_t *retval)
 1980 {
 1981         struct sys_futimes_args /* {
 1982                 syscallarg(int) fd;
 1983                 syscallarg(const struct timeval *) tptr;
 1984         } */ *uap = v;
 1985         struct vnode *vp;
 1986         struct timeval tv[2];
 1987         struct vattr vattr;
 1988         int error;
 1989         struct file *fp;
 1990 
 1991         VATTR_NULL(&vattr);
 1992         if (SCARG(uap, tptr) == NULL) {
 1993                 microtime(&tv[0]);
 1994                 tv[1] = tv[0];
 1995                 vattr.va_vaflags |= VA_UTIMES_NULL;
 1996         } else {
 1997                 error = copyin(SCARG(uap, tptr), tv,
 1998                     sizeof(tv));
 1999                 if (error)
 2000                         return (error);
 2001                 /* XXX workaround timeval matching the VFS constant VNOVAL */
 2002                 if (tv[0].tv_sec == VNOVAL)
 2003                         tv[0].tv_sec = VNOVAL - 1;
 2004                 if (tv[1].tv_sec == VNOVAL)
 2005                         tv[1].tv_sec = VNOVAL - 1;
 2006         }
 2007         if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
 2008                 return (error);
 2009         vp = (struct vnode *)fp->f_data;
 2010         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
 2011         if (vp->v_mount && vp->v_mount->mnt_flag & MNT_RDONLY)
 2012                 error = EROFS;
 2013         else {
 2014                 vattr.va_atime.tv_sec = tv[0].tv_sec;
 2015                 vattr.va_atime.tv_nsec = tv[0].tv_usec * 1000;
 2016                 vattr.va_mtime.tv_sec = tv[1].tv_sec;
 2017                 vattr.va_mtime.tv_nsec = tv[1].tv_usec * 1000;
 2018                 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
 2019         }
 2020         VOP_UNLOCK(vp, 0, p);
 2021         FRELE(fp);
 2022         return (error);
 2023 }
 2024 
 2025 /*
 2026  * Truncate a file given its path name.
 2027  */
 2028 /* ARGSUSED */
 2029 int
 2030 sys_truncate(struct proc *p, void *v, register_t *retval)
 2031 {
 2032         struct sys_truncate_args /* {
 2033                 syscallarg(const char *) path;
 2034                 syscallarg(int) pad;
 2035                 syscallarg(off_t) length;
 2036         } */ *uap = v;
 2037         struct vnode *vp;
 2038         struct vattr vattr;
 2039         int error;
 2040         struct nameidata nd;
 2041 
 2042         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
 2043         if ((error = namei(&nd)) != 0)
 2044                 return (error);
 2045         vp = nd.ni_vp;
 2046         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
 2047         if (vp->v_type == VDIR)
 2048                 error = EISDIR;
 2049         else if ((error = vn_writechk(vp)) == 0 &&
 2050             (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) {
 2051                 VATTR_NULL(&vattr);
 2052                 vattr.va_size = SCARG(uap, length);
 2053                 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
 2054         }
 2055         vput(vp);
 2056         return (error);
 2057 }
 2058 
 2059 /*
 2060  * Truncate a file given a file descriptor.
 2061  */
 2062 /* ARGSUSED */
 2063 int
 2064 sys_ftruncate(struct proc *p, void *v, register_t *retval)
 2065 {
 2066         struct sys_ftruncate_args /* {
 2067                 syscallarg(int) fd;
 2068                 syscallarg(int) pad;
 2069                 syscallarg(off_t) length;
 2070         } */ *uap = v;
 2071         struct vattr vattr;
 2072         struct vnode *vp;
 2073         struct file *fp;
 2074         off_t len;
 2075         int error;
 2076 
 2077         if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
 2078                 return (error);
 2079         len = SCARG(uap, length);
 2080         if ((fp->f_flag & FWRITE) == 0 || len < 0) {
 2081                 error = EINVAL;
 2082                 goto bad;
 2083         }
 2084         vp = (struct vnode *)fp->f_data;
 2085         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
 2086         if (vp->v_type == VDIR)
 2087                 error = EISDIR;
 2088         else if ((error = vn_writechk(vp)) == 0) {
 2089                 VATTR_NULL(&vattr);
 2090                 vattr.va_size = len;
 2091                 error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
 2092         }
 2093         VOP_UNLOCK(vp, 0, p);
 2094 bad:
 2095         FRELE(fp);
 2096         return (error);
 2097 }
 2098 
 2099 /*
 2100  * Sync an open file.
 2101  */
 2102 /* ARGSUSED */
 2103 int
 2104 sys_fsync(struct proc *p, void *v, register_t *retval)
 2105 {
 2106         struct sys_fsync_args /* {
 2107                 syscallarg(int) fd;
 2108         } */ *uap = v;
 2109         struct vnode *vp;
 2110         struct file *fp;
 2111         int error;
 2112 
 2113         if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
 2114                 return (error);
 2115         vp = (struct vnode *)fp->f_data;
 2116         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
 2117         error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p);
 2118 #ifdef FFS_SOFTUPDATES
 2119         if (error == 0 && vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP))
 2120                 error = softdep_fsync(vp);
 2121 #endif
 2122 
 2123         VOP_UNLOCK(vp, 0, p);
 2124         FRELE(fp);
 2125         return (error);
 2126 }
 2127 
 2128 /*
 2129  * Rename files.  Source and destination must either both be directories,
 2130  * or both not be directories.  If target is a directory, it must be empty.
 2131  */
 2132 /* ARGSUSED */
 2133 int
 2134 sys_rename(struct proc *p, void *v, register_t *retval)
 2135 {
 2136         struct sys_rename_args /* {
 2137                 syscallarg(const char *) from;
 2138                 syscallarg(const char *) to;
 2139         } */ *uap = v;
 2140         struct vnode *tvp, *fvp, *tdvp;
 2141         struct nameidata fromnd, tond;
 2142         int error;
 2143         int flags;
 2144 
 2145         NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
 2146             SCARG(uap, from), p);
 2147         if ((error = namei(&fromnd)) != 0)
 2148                 return (error);
 2149         fvp = fromnd.ni_vp;
 2150 
 2151         flags = LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART;
 2152         /*
 2153          * rename("foo/", "bar/");  is  OK
 2154          */
 2155         if (fvp->v_type == VDIR)
 2156                 flags |= STRIPSLASHES;
 2157 
 2158         NDINIT(&tond, RENAME, flags,
 2159             UIO_USERSPACE, SCARG(uap, to), p);
 2160         if ((error = namei(&tond)) != 0) {
 2161                 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
 2162                 vrele(fromnd.ni_dvp);
 2163                 vrele(fvp);
 2164                 goto out1;
 2165         }
 2166         tdvp = tond.ni_dvp;
 2167         tvp = tond.ni_vp;
 2168         if (tvp != NULL) {
 2169                 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
 2170                         error = ENOTDIR;
 2171                         goto out;
 2172                 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
 2173                         error = EISDIR;
 2174                         goto out;
 2175                 }
 2176         }
 2177         if (fvp == tdvp)
 2178                 error = EINVAL;
 2179         /*
 2180          * If source is the same as the destination (that is the
 2181          * same inode number)
 2182          */
 2183         if (fvp == tvp)
 2184                 error = -1;
 2185 out:
 2186         if (!error) {
 2187                 if (tvp) {
 2188                         (void)uvm_vnp_uncache(tvp);
 2189                 }
 2190                 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
 2191                                    tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
 2192         } else {
 2193                 VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
 2194                 if (tdvp == tvp)
 2195                         vrele(tdvp);
 2196                 else
 2197                         vput(tdvp);
 2198                 if (tvp)
 2199                         vput(tvp);
 2200                 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
 2201                 vrele(fromnd.ni_dvp);
 2202                 vrele(fvp);
 2203         }
 2204         vrele(tond.ni_startdir);
 2205         pool_put(&namei_pool, tond.ni_cnd.cn_pnbuf);
 2206 out1:
 2207         if (fromnd.ni_startdir)
 2208                 vrele(fromnd.ni_startdir);
 2209         pool_put(&namei_pool, fromnd.ni_cnd.cn_pnbuf);
 2210         if (error == -1)
 2211                 return (0);
 2212         return (error);
 2213 }
 2214 
 2215 /*
 2216  * Make a directory file.
 2217  */
 2218 /* ARGSUSED */
 2219 int
 2220 sys_mkdir(struct proc *p, void *v, register_t *retval)
 2221 {
 2222         struct sys_mkdir_args /* {
 2223                 syscallarg(const char *) path;
 2224                 syscallarg(mode_t) mode;
 2225         } */ *uap = v;
 2226         struct vnode *vp;
 2227         struct vattr vattr;
 2228         int error;
 2229         struct nameidata nd;
 2230 
 2231         NDINIT(&nd, CREATE, LOCKPARENT | STRIPSLASHES,
 2232             UIO_USERSPACE, SCARG(uap, path), p);
 2233         if ((error = namei(&nd)) != 0)
 2234                 return (error);
 2235         vp = nd.ni_vp;
 2236         if (vp != NULL) {
 2237                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
 2238                 if (nd.ni_dvp == vp)
 2239                         vrele(nd.ni_dvp);
 2240                 else
 2241                         vput(nd.ni_dvp);
 2242                 vrele(vp);
 2243                 return (EEXIST);
 2244         }
 2245         VATTR_NULL(&vattr);
 2246         vattr.va_type = VDIR;
 2247         vattr.va_mode = (SCARG(uap, mode) & ACCESSPERMS) &~ p->p_fd->fd_cmask;
 2248         error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
 2249         if (!error)
 2250                 vput(nd.ni_vp);
 2251         return (error);
 2252 }
 2253 
 2254 /*
 2255  * Remove a directory file.
 2256  */
 2257 /* ARGSUSED */
 2258 int
 2259 sys_rmdir(struct proc *p, void *v, register_t *retval)
 2260 {
 2261         struct sys_rmdir_args /* {
 2262                 syscallarg(const char *) path;
 2263         } */ *uap = v;
 2264         struct vnode *vp;
 2265         int error;
 2266         struct nameidata nd;
 2267 
 2268         NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
 2269             SCARG(uap, path), p);
 2270         if ((error = namei(&nd)) != 0)
 2271                 return (error);
 2272         vp = nd.ni_vp;
 2273         if (vp->v_type != VDIR) {
 2274                 error = ENOTDIR;
 2275                 goto out;
 2276         }
 2277         /*
 2278          * No rmdir "." please.
 2279          */
 2280         if (nd.ni_dvp == vp) {
 2281                 error = EBUSY;
 2282                 goto out;
 2283         }
 2284         /*
 2285          * The root of a mounted filesystem cannot be deleted.
 2286          */
 2287         if (vp->v_flag & VROOT)
 2288                 error = EBUSY;
 2289 out:
 2290         if (!error) {
 2291                 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
 2292         } else {
 2293                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
 2294                 if (nd.ni_dvp == vp)
 2295                         vrele(nd.ni_dvp);
 2296                 else
 2297                         vput(nd.ni_dvp);
 2298                 vput(vp);
 2299         }
 2300         return (error);
 2301 }
 2302 
 2303 /*
 2304  * Read a block of directory entries in a file system independent format.
 2305  */
 2306 int
 2307 sys_getdirentries(struct proc *p, void *v, register_t *retval)
 2308 {
 2309         struct sys_getdirentries_args /* {
 2310                 syscallarg(int) fd;
 2311                 syscallarg(char *) buf;
 2312                 syscallarg(int) count;
 2313                 syscallarg(long *) basep;
 2314         } */ *uap = v;
 2315         struct vnode *vp;
 2316         struct file *fp;
 2317         struct uio auio;
 2318         struct iovec aiov;
 2319         long loff;
 2320         int error, eofflag;
 2321 
 2322         if (SCARG(uap, count) < 0)
 2323                 return EINVAL;
 2324         if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
 2325                 return (error);
 2326         if ((fp->f_flag & FREAD) == 0) {
 2327                 error = EBADF;
 2328                 goto bad;
 2329         }
 2330         vp = (struct vnode *)fp->f_data;
 2331         if (vp->v_type != VDIR) {
 2332                 error = EINVAL;
 2333                 goto bad;
 2334         }
 2335         aiov.iov_base = SCARG(uap, buf);
 2336         aiov.iov_len = SCARG(uap, count);
 2337         auio.uio_iov = &aiov;
 2338         auio.uio_iovcnt = 1;
 2339         auio.uio_rw = UIO_READ;
 2340         auio.uio_segflg = UIO_USERSPACE;
 2341         auio.uio_procp = p;
 2342         auio.uio_resid = SCARG(uap, count);
 2343         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
 2344         loff = auio.uio_offset = fp->f_offset;
 2345         error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, 0, 0);
 2346         fp->f_offset = auio.uio_offset;
 2347         VOP_UNLOCK(vp, 0, p);
 2348         if (error)
 2349                 goto bad;
 2350         error = copyout(&loff, SCARG(uap, basep),
 2351             sizeof(long));
 2352         *retval = SCARG(uap, count) - auio.uio_resid;
 2353 bad:
 2354         FRELE(fp);
 2355         return (error);
 2356 }
 2357 
 2358 /*
 2359  * Set the mode mask for creation of filesystem nodes.
 2360  */
 2361 int
 2362 sys_umask(struct proc *p, void *v, register_t *retval)
 2363 {
 2364         struct sys_umask_args /* {
 2365                 syscallarg(mode_t) newmask;
 2366         } */ *uap = v;
 2367         struct filedesc *fdp;
 2368 
 2369         fdp = p->p_fd;
 2370         *retval = fdp->fd_cmask;
 2371         fdp->fd_cmask = SCARG(uap, newmask) & ACCESSPERMS;
 2372         return (0);
 2373 }
 2374 
 2375 /*
 2376  * Void all references to file by ripping underlying filesystem
 2377  * away from vnode.
 2378  */
 2379 /* ARGSUSED */
 2380 int
 2381 sys_revoke(struct proc *p, void *v, register_t *retval)
 2382 {
 2383         struct sys_revoke_args /* {
 2384                 syscallarg(const char *) path;
 2385         } */ *uap = v;
 2386         struct vnode *vp;
 2387         struct vattr vattr;
 2388         int error;
 2389         struct nameidata nd;
 2390 
 2391         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
 2392         if ((error = namei(&nd)) != 0)
 2393                 return (error);
 2394         vp = nd.ni_vp;
 2395         if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0)
 2396                 goto out;
 2397         if (p->p_ucred->cr_uid != vattr.va_uid &&
 2398             (error = suser(p, 0)))
 2399                 goto out;
 2400         if (vp->v_usecount > 1 || (vp->v_flag & (VALIASED)))
 2401                 VOP_REVOKE(vp, REVOKEALL);
 2402 out:
 2403         vrele(vp);
 2404         return (error);
 2405 }
 2406 
 2407 /*
 2408  * Convert a user file descriptor to a kernel file entry.
 2409  *
 2410  * On return *fpp is FREF:ed.
 2411  */
 2412 int
 2413 getvnode(struct filedesc *fdp, int fd, struct file **fpp)
 2414 {
 2415         struct file *fp;
 2416         struct vnode *vp;
 2417 
 2418         if ((fp = fd_getfile(fdp, fd)) == NULL)
 2419                 return (EBADF);
 2420 
 2421         if (fp->f_type != DTYPE_VNODE)
 2422                 return (EINVAL);
 2423 
 2424         vp = (struct vnode *)fp->f_data;
 2425         if (vp->v_type == VBAD)
 2426                 return (EBADF);
 2427 
 2428         FREF(fp);
 2429         *fpp = fp;
 2430 
 2431         return (0);
 2432 }
 2433 
 2434 /*
 2435  * Positional read system call.
 2436  */
 2437 int
 2438 sys_pread(struct proc *p, void *v, register_t *retval)
 2439 {
 2440         struct sys_pread_args /* {
 2441                 syscallarg(int) fd;
 2442                 syscallarg(void *) buf;
 2443                 syscallarg(size_t) nbyte;
 2444                 syscallarg(int) pad;
 2445                 syscallarg(off_t) offset;
 2446         } */ *uap = v;
 2447         struct filedesc *fdp = p->p_fd;
 2448         struct file *fp;
 2449         struct vnode *vp;
 2450         off_t offset;
 2451         int fd = SCARG(uap, fd);
 2452 
 2453         if ((fp = fd_getfile(fdp, fd)) == NULL)
 2454                 return (EBADF);
 2455         if ((fp->f_flag & FREAD) == 0)
 2456                 return (EBADF);
 2457 
 2458         vp = (struct vnode *)fp->f_data;
 2459         if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
 2460                 return (ESPIPE);
 2461         }
 2462 
 2463         offset = SCARG(uap, offset);
 2464 
 2465         FREF(fp);
 2466 
 2467         /* dofileread() will FRELE the descriptor for us */
 2468         return (dofileread(p, fd, fp, SCARG(uap, buf), SCARG(uap, nbyte),
 2469             &offset, retval));
 2470 }
 2471 
 2472 /*
 2473  * Positional scatter read system call.
 2474  */
 2475 int
 2476 sys_preadv(struct proc *p, void *v, register_t *retval)
 2477 {
 2478         struct sys_preadv_args /* {
 2479                 syscallarg(int) fd;
 2480                 syscallarg(const struct iovec *) iovp;
 2481                 syscallarg(int) iovcnt;
 2482                 syscallarg(int) pad;
 2483                 syscallarg(off_t) offset;
 2484         } */ *uap = v;
 2485         struct filedesc *fdp = p->p_fd;
 2486         struct file *fp;
 2487         struct vnode *vp;
 2488         off_t offset;
 2489         int fd = SCARG(uap, fd);
 2490 
 2491         if ((fp = fd_getfile(fdp, fd)) == NULL)
 2492                 return (EBADF);
 2493         if ((fp->f_flag & FREAD) == 0)
 2494                 return (EBADF);
 2495 
 2496         vp = (struct vnode *)fp->f_data;
 2497         if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
 2498                 return (ESPIPE);
 2499         }
 2500 
 2501         FREF(fp);
 2502 
 2503         offset = SCARG(uap, offset);
 2504 
 2505         /* dofilereadv() will FRELE the descriptor for us */
 2506         return (dofilereadv(p, fd, fp, SCARG(uap, iovp), SCARG(uap, iovcnt),
 2507             &offset, retval));
 2508 }
 2509 
 2510 /*
 2511  * Positional write system call.
 2512  */
 2513 int
 2514 sys_pwrite(struct proc *p, void *v, register_t *retval)
 2515 {
 2516         struct sys_pwrite_args /* {
 2517                 syscallarg(int) fd;
 2518                 syscallarg(const void *) buf;
 2519                 syscallarg(size_t) nbyte;
 2520                 syscallarg(int) pad;
 2521                 syscallarg(off_t) offset;
 2522         } */ *uap = v;
 2523         struct filedesc *fdp = p->p_fd;
 2524         struct file *fp;
 2525         struct vnode *vp;
 2526         off_t offset;
 2527         int fd = SCARG(uap, fd);
 2528 
 2529         if ((fp = fd_getfile(fdp, fd)) == NULL)
 2530                 return (EBADF);
 2531         if ((fp->f_flag & FWRITE) == 0)
 2532                 return (EBADF);
 2533 
 2534         vp = (struct vnode *)fp->f_data;
 2535         if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
 2536                 return (ESPIPE);
 2537         }
 2538 
 2539         FREF(fp);
 2540 
 2541         offset = SCARG(uap, offset);
 2542 
 2543         /* dofilewrite() will FRELE the descriptor for us */
 2544         return (dofilewrite(p, fd, fp, SCARG(uap, buf), SCARG(uap, nbyte),
 2545             &offset, retval));
 2546 }
 2547 
 2548 /*
 2549  * Positional gather write system call.
 2550  */
 2551 int
 2552 sys_pwritev(struct proc *p, void *v, register_t *retval)
 2553 {
 2554         struct sys_pwritev_args /* {
 2555                 syscallarg(int) fd;
 2556                 syscallarg(const struct iovec *) iovp;
 2557                 syscallarg(int) iovcnt;
 2558                 syscallarg(int) pad;
 2559                 syscallarg(off_t) offset;
 2560         } */ *uap = v;
 2561         struct filedesc *fdp = p->p_fd;
 2562         struct file *fp;
 2563         struct vnode *vp;
 2564         off_t offset;
 2565         int fd = SCARG(uap, fd);
 2566 
 2567         if ((fp = fd_getfile(fdp, fd)) == NULL)
 2568                 return (EBADF);
 2569         if ((fp->f_flag & FWRITE) == 0)
 2570                 return (EBADF);
 2571 
 2572         vp = (struct vnode *)fp->f_data;
 2573         if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
 2574                 return (ESPIPE);
 2575         }
 2576 
 2577         FREF(fp);
 2578 
 2579         offset = SCARG(uap, offset);
 2580 
 2581         /* dofilewritev() will FRELE the descriptor for us */
 2582         return (dofilewritev(p, fd, fp, SCARG(uap, iovp), SCARG(uap, iovcnt),
 2583             &offset, retval));
 2584 }

/* [<][>][^][v][top][bottom][index][help] */