123405Smckusick /* 237741Smckusick * Copyright (c) 1989 The Regents of the University of California. 337741Smckusick * All rights reserved. 423405Smckusick * 544459Sbostic * %sccs.include.redist.c% 637741Smckusick * 7*45202Smckusick * @(#)vfs_syscalls.c 7.58 (Berkeley) 09/05/90 823405Smckusick */ 937Sbill 1017101Sbloom #include "param.h" 1117101Sbloom #include "systm.h" 1244407Skarels #include "user.h" 1317101Sbloom #include "kernel.h" 1417101Sbloom #include "file.h" 1517101Sbloom #include "stat.h" 1637741Smckusick #include "vnode.h" 1737741Smckusick #include "mount.h" 1817101Sbloom #include "proc.h" 1917101Sbloom #include "uio.h" 2037741Smckusick #include "malloc.h" 2137Sbill 2243450Smckusick #define RETURN(val) {if (u.u_spare[0] != 0) panic("lock count"); return (val);} 2339797Smckusick 2437741Smckusick /* 2537741Smckusick * Virtual File System System Calls 2637741Smckusick */ 2712756Ssam 289167Ssam /* 2937741Smckusick * mount system call 309167Ssam */ 3142441Smckusick /* ARGSUSED */ 3242441Smckusick mount(p, uap, retval) 3342441Smckusick register struct proc *p; 3442441Smckusick register struct args { 3537741Smckusick int type; 3637741Smckusick char *dir; 3737741Smckusick int flags; 3837741Smckusick caddr_t data; 3942441Smckusick } *uap; 4042441Smckusick int *retval; 4142441Smckusick { 4242441Smckusick register struct nameidata *ndp = &u.u_nd; 4339335Smckusick register struct vnode *vp; 4439335Smckusick register struct mount *mp; 4540111Smckusick int error, flag; 466254Sroot 4737741Smckusick /* 4837741Smckusick * Must be super user 4937741Smckusick */ 5042441Smckusick if (error = suser(ndp->ni_cred, &u.u_acflag)) 5137741Smckusick RETURN (error); 5237741Smckusick /* 5337741Smckusick * Get vnode to be covered 5437741Smckusick */ 5537741Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 5637741Smckusick ndp->ni_segflg = UIO_USERSPACE; 5737741Smckusick ndp->ni_dirp = uap->dir; 5837741Smckusick if (error = namei(ndp)) 5937741Smckusick RETURN (error); 6037741Smckusick vp = ndp->ni_vp; 6141400Smckusick if (uap->flags & MNT_UPDATE) { 6239335Smckusick if ((vp->v_flag & VROOT) == 0) { 6339335Smckusick vput(vp); 6439335Smckusick RETURN (EINVAL); 6539335Smckusick } 6639335Smckusick mp = vp->v_mount; 6739335Smckusick /* 6839335Smckusick * We allow going from read-only to read-write, 6939335Smckusick * but not from read-write to read-only. 7039335Smckusick */ 7141400Smckusick if ((mp->mnt_flag & MNT_RDONLY) == 0 && 7241400Smckusick (uap->flags & MNT_RDONLY) != 0) { 7339335Smckusick vput(vp); 7439335Smckusick RETURN (EOPNOTSUPP); /* Needs translation */ 7539335Smckusick } 7641400Smckusick flag = mp->mnt_flag; 7741400Smckusick mp->mnt_flag |= MNT_UPDATE; 7839335Smckusick VOP_UNLOCK(vp); 7939335Smckusick goto update; 8039335Smckusick } 8139665Smckusick vinvalbuf(vp, 1); 8239805Smckusick if (vp->v_usecount != 1) { 8337741Smckusick vput(vp); 8437741Smckusick RETURN (EBUSY); 8537741Smckusick } 8637741Smckusick if (vp->v_type != VDIR) { 8737741Smckusick vput(vp); 8837741Smckusick RETURN (ENOTDIR); 8937741Smckusick } 9039741Smckusick if ((unsigned long)uap->type > MOUNT_MAXTYPE || 9137741Smckusick vfssw[uap->type] == (struct vfsops *)0) { 9237741Smckusick vput(vp); 9337741Smckusick RETURN (ENODEV); 9437741Smckusick } 9537741Smckusick 9637741Smckusick /* 9739335Smckusick * Allocate and initialize the file system. 9837741Smckusick */ 9937741Smckusick mp = (struct mount *)malloc((u_long)sizeof(struct mount), 10037741Smckusick M_MOUNT, M_WAITOK); 10141400Smckusick mp->mnt_op = vfssw[uap->type]; 10241400Smckusick mp->mnt_flag = 0; 10341400Smckusick mp->mnt_exroot = 0; 10441400Smckusick mp->mnt_mounth = NULLVP; 10539335Smckusick if (error = vfs_lock(mp)) { 10639335Smckusick free((caddr_t)mp, M_MOUNT); 10739335Smckusick vput(vp); 10839335Smckusick RETURN (error); 10939335Smckusick } 11039335Smckusick if (vp->v_mountedhere != (struct mount *)0) { 11139335Smckusick vfs_unlock(mp); 11239335Smckusick free((caddr_t)mp, M_MOUNT); 11339335Smckusick vput(vp); 11439335Smckusick RETURN (EBUSY); 11539335Smckusick } 11639335Smckusick vp->v_mountedhere = mp; 11741400Smckusick mp->mnt_vnodecovered = vp; 11839335Smckusick update: 11939335Smckusick /* 12039335Smckusick * Set the mount level flags. 12139335Smckusick */ 12241400Smckusick if (uap->flags & MNT_RDONLY) 12341400Smckusick mp->mnt_flag |= MNT_RDONLY; 12439335Smckusick else 12541400Smckusick mp->mnt_flag &= ~MNT_RDONLY; 12641400Smckusick if (uap->flags & MNT_NOSUID) 12741400Smckusick mp->mnt_flag |= MNT_NOSUID; 12839335Smckusick else 12941400Smckusick mp->mnt_flag &= ~MNT_NOSUID; 13041400Smckusick if (uap->flags & MNT_NOEXEC) 13141400Smckusick mp->mnt_flag |= MNT_NOEXEC; 13239335Smckusick else 13341400Smckusick mp->mnt_flag &= ~MNT_NOEXEC; 13441400Smckusick if (uap->flags & MNT_NODEV) 13541400Smckusick mp->mnt_flag |= MNT_NODEV; 13639335Smckusick else 13741400Smckusick mp->mnt_flag &= ~MNT_NODEV; 13841400Smckusick if (uap->flags & MNT_SYNCHRONOUS) 13941400Smckusick mp->mnt_flag |= MNT_SYNCHRONOUS; 14039335Smckusick else 14141400Smckusick mp->mnt_flag &= ~MNT_SYNCHRONOUS; 14239335Smckusick /* 14339335Smckusick * Mount the filesystem. 14439335Smckusick */ 14539335Smckusick error = VFS_MOUNT(mp, uap->dir, uap->data, ndp); 14641400Smckusick if (mp->mnt_flag & MNT_UPDATE) { 14741400Smckusick mp->mnt_flag &= ~MNT_UPDATE; 14839335Smckusick vrele(vp); 14940111Smckusick if (error) 15041400Smckusick mp->mnt_flag = flag; 15139335Smckusick RETURN (error); 15239335Smckusick } 15340110Smckusick /* 15440110Smckusick * Put the new filesystem on the mount list after root. 15540110Smckusick */ 15641400Smckusick mp->mnt_next = rootfs->mnt_next; 15741400Smckusick mp->mnt_prev = rootfs; 15841400Smckusick rootfs->mnt_next = mp; 15941400Smckusick mp->mnt_next->mnt_prev = mp; 16037741Smckusick cache_purge(vp); 16137741Smckusick if (!error) { 16239335Smckusick VOP_UNLOCK(vp); 16337741Smckusick vfs_unlock(mp); 16439044Smckusick error = VFS_START(mp, 0); 16537741Smckusick } else { 16637741Smckusick vfs_remove(mp); 16737741Smckusick free((caddr_t)mp, M_MOUNT); 16839335Smckusick vput(vp); 16937741Smckusick } 17037741Smckusick RETURN (error); 1716254Sroot } 1726254Sroot 1739167Ssam /* 17437741Smckusick * Unmount system call. 17537741Smckusick * 17637741Smckusick * Note: unmount takes a path to the vnode mounted on as argument, 17737741Smckusick * not special file (as before). 1789167Ssam */ 17942441Smckusick /* ARGSUSED */ 18042441Smckusick unmount(p, uap, retval) 18142441Smckusick register struct proc *p; 18242441Smckusick register struct args { 18337741Smckusick char *pathp; 18437741Smckusick int flags; 18542441Smckusick } *uap; 18642441Smckusick int *retval; 18742441Smckusick { 18837741Smckusick register struct vnode *vp; 18942441Smckusick register struct nameidata *ndp = &u.u_nd; 19039356Smckusick struct mount *mp; 19137741Smckusick int error; 1926254Sroot 19337741Smckusick /* 19437741Smckusick * Must be super user 19537741Smckusick */ 19642441Smckusick if (error = suser(ndp->ni_cred, &u.u_acflag)) 19737741Smckusick RETURN (error); 19837741Smckusick 19937741Smckusick ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW; 20037741Smckusick ndp->ni_segflg = UIO_USERSPACE; 20137741Smckusick ndp->ni_dirp = uap->pathp; 20237741Smckusick if (error = namei(ndp)) 20337741Smckusick RETURN (error); 20437741Smckusick vp = ndp->ni_vp; 20537741Smckusick /* 20637741Smckusick * Must be the root of the filesystem 20737741Smckusick */ 20837741Smckusick if ((vp->v_flag & VROOT) == 0) { 20937741Smckusick vput(vp); 21037741Smckusick RETURN (EINVAL); 21137741Smckusick } 21237741Smckusick mp = vp->v_mount; 21337741Smckusick vput(vp); 21439356Smckusick RETURN (dounmount(mp, uap->flags)); 21539356Smckusick } 21639356Smckusick 21739356Smckusick /* 21839356Smckusick * Do an unmount. 21939356Smckusick */ 22039356Smckusick dounmount(mp, flags) 22139356Smckusick register struct mount *mp; 22239356Smckusick int flags; 22339356Smckusick { 22439356Smckusick struct vnode *coveredvp; 22539356Smckusick int error; 22639356Smckusick 22741400Smckusick coveredvp = mp->mnt_vnodecovered; 22841298Smckusick if (vfs_busy(mp)) 22941298Smckusick return (EBUSY); 23041400Smckusick mp->mnt_flag |= MNT_UNMOUNT; 23137741Smckusick if (error = vfs_lock(mp)) 23239356Smckusick return (error); 23337741Smckusick 23437741Smckusick xumount(mp); /* remove unused sticky files from text table */ 23537741Smckusick cache_purgevfs(mp); /* remove cache entries for this file sys */ 23641676Smckusick if ((error = VFS_SYNC(mp, MNT_WAIT)) == 0 || (flags & MNT_FORCE)) 23741676Smckusick error = VFS_UNMOUNT(mp, flags); 23841400Smckusick mp->mnt_flag &= ~MNT_UNMOUNT; 23941298Smckusick vfs_unbusy(mp); 24037741Smckusick if (error) { 24137741Smckusick vfs_unlock(mp); 24237741Smckusick } else { 24337741Smckusick vrele(coveredvp); 24437741Smckusick vfs_remove(mp); 24537741Smckusick free((caddr_t)mp, M_MOUNT); 24637741Smckusick } 24739356Smckusick return (error); 2486254Sroot } 2496254Sroot 2509167Ssam /* 25137741Smckusick * Sync system call. 25237741Smckusick * Sync each mounted filesystem. 2539167Ssam */ 25439491Smckusick /* ARGSUSED */ 25542441Smckusick sync(p, uap, retval) 25642441Smckusick register struct proc *p; 25742441Smckusick struct args *uap; 25842441Smckusick int *retval; 2596254Sroot { 26037741Smckusick register struct mount *mp; 26141298Smckusick struct mount *omp; 26237741Smckusick 26337741Smckusick mp = rootfs; 26437741Smckusick do { 26540343Smckusick /* 26640343Smckusick * The lock check below is to avoid races with mount 26740343Smckusick * and unmount. 26840343Smckusick */ 26941400Smckusick if ((mp->mnt_flag & (MNT_MLOCK|MNT_RDONLY|MNT_MPBUSY)) == 0 && 27041298Smckusick !vfs_busy(mp)) { 27137741Smckusick VFS_SYNC(mp, MNT_NOWAIT); 27241298Smckusick omp = mp; 27341400Smckusick mp = mp->mnt_next; 27441298Smckusick vfs_unbusy(omp); 27541298Smckusick } else 27641400Smckusick mp = mp->mnt_next; 27737741Smckusick } while (mp != rootfs); 27837741Smckusick } 27937741Smckusick 28037741Smckusick /* 28141298Smckusick * operate on filesystem quotas 28241298Smckusick */ 28342441Smckusick /* ARGSUSED */ 28442441Smckusick quotactl(p, uap, retval) 28542441Smckusick register struct proc *p; 28642441Smckusick register struct args { 28741298Smckusick char *path; 28841298Smckusick int cmd; 28941298Smckusick int uid; 29041298Smckusick caddr_t arg; 29142441Smckusick } *uap; 29242441Smckusick int *retval; 29342441Smckusick { 29441298Smckusick register struct mount *mp; 29542441Smckusick register struct nameidata *ndp = &u.u_nd; 29641298Smckusick int error; 29741298Smckusick 29841298Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW; 29941298Smckusick ndp->ni_segflg = UIO_USERSPACE; 30041298Smckusick ndp->ni_dirp = uap->path; 30141298Smckusick if (error = namei(ndp)) 30241298Smckusick RETURN (error); 30341298Smckusick mp = ndp->ni_vp->v_mount; 30441298Smckusick vrele(ndp->ni_vp); 30541298Smckusick RETURN (VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg)); 30641298Smckusick } 30741298Smckusick 30841298Smckusick /* 30937741Smckusick * get filesystem statistics 31037741Smckusick */ 31142441Smckusick /* ARGSUSED */ 31242441Smckusick statfs(p, uap, retval) 31342441Smckusick register struct proc *p; 31442441Smckusick register struct args { 31537741Smckusick char *path; 31637741Smckusick struct statfs *buf; 31742441Smckusick } *uap; 31842441Smckusick int *retval; 31942441Smckusick { 32039464Smckusick register struct mount *mp; 32142441Smckusick register struct nameidata *ndp = &u.u_nd; 32240343Smckusick register struct statfs *sp; 32337741Smckusick int error; 32437741Smckusick 32539544Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW; 32637741Smckusick ndp->ni_segflg = UIO_USERSPACE; 32737741Smckusick ndp->ni_dirp = uap->path; 32837741Smckusick if (error = namei(ndp)) 32937741Smckusick RETURN (error); 33039544Smckusick mp = ndp->ni_vp->v_mount; 33141400Smckusick sp = &mp->mnt_stat; 33239544Smckusick vrele(ndp->ni_vp); 33340343Smckusick if (error = VFS_STATFS(mp, sp)) 33439544Smckusick RETURN (error); 33541400Smckusick sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 33640343Smckusick RETURN (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp))); 33737741Smckusick } 33837741Smckusick 33942441Smckusick /* 34042441Smckusick * get filesystem statistics 34142441Smckusick */ 34242441Smckusick /* ARGSUSED */ 34342441Smckusick fstatfs(p, uap, retval) 34442441Smckusick register struct proc *p; 34542441Smckusick register struct args { 34637741Smckusick int fd; 34737741Smckusick struct statfs *buf; 34842441Smckusick } *uap; 34942441Smckusick int *retval; 35042441Smckusick { 35137741Smckusick struct file *fp; 35239464Smckusick struct mount *mp; 35340343Smckusick register struct statfs *sp; 35437741Smckusick int error; 35537741Smckusick 35642441Smckusick if (error = getvnode(u.u_ofile, uap->fd, &fp)) 35737741Smckusick RETURN (error); 35839464Smckusick mp = ((struct vnode *)fp->f_data)->v_mount; 35941400Smckusick sp = &mp->mnt_stat; 36040343Smckusick if (error = VFS_STATFS(mp, sp)) 36137741Smckusick RETURN (error); 36241400Smckusick sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 36340343Smckusick RETURN (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp))); 36437741Smckusick } 36537741Smckusick 36637741Smckusick /* 36738270Smckusick * get statistics on all filesystems 36838270Smckusick */ 36942441Smckusick getfsstat(p, uap, retval) 37042441Smckusick register struct proc *p; 37142441Smckusick register struct args { 37238270Smckusick struct statfs *buf; 37338270Smckusick long bufsize; 37440343Smckusick int flags; 37542441Smckusick } *uap; 37642441Smckusick int *retval; 37742441Smckusick { 37838270Smckusick register struct mount *mp; 37940343Smckusick register struct statfs *sp; 38039606Smckusick caddr_t sfsp; 38138270Smckusick long count, maxcount, error; 38238270Smckusick 38338270Smckusick maxcount = uap->bufsize / sizeof(struct statfs); 38439606Smckusick sfsp = (caddr_t)uap->buf; 38538270Smckusick mp = rootfs; 38638270Smckusick count = 0; 38738270Smckusick do { 38841400Smckusick if (sfsp && count < maxcount && 38941400Smckusick ((mp->mnt_flag & MNT_MLOCK) == 0)) { 39041400Smckusick sp = &mp->mnt_stat; 39140343Smckusick /* 39240343Smckusick * If MNT_NOWAIT is specified, do not refresh the 39340343Smckusick * fsstat cache. MNT_WAIT overrides MNT_NOWAIT. 39440343Smckusick */ 39540343Smckusick if (((uap->flags & MNT_NOWAIT) == 0 || 39640343Smckusick (uap->flags & MNT_WAIT)) && 39740343Smckusick (error = VFS_STATFS(mp, sp))) { 39841400Smckusick mp = mp->mnt_prev; 39939607Smckusick continue; 40039607Smckusick } 40141400Smckusick sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 40240343Smckusick if (error = copyout((caddr_t)sp, sfsp, sizeof(*sp))) 40339606Smckusick RETURN (error); 40440343Smckusick sfsp += sizeof(*sp); 40538270Smckusick } 40639606Smckusick count++; 40741400Smckusick mp = mp->mnt_prev; 40838270Smckusick } while (mp != rootfs); 40938270Smckusick if (sfsp && count > maxcount) 41042441Smckusick *retval = maxcount; 41138270Smckusick else 41242441Smckusick *retval = count; 41338270Smckusick RETURN (0); 41438270Smckusick } 41538270Smckusick 41638270Smckusick /* 41738259Smckusick * Change current working directory to a given file descriptor. 41838259Smckusick */ 41942441Smckusick /* ARGSUSED */ 42042441Smckusick fchdir(p, uap, retval) 42142441Smckusick register struct proc *p; 42242441Smckusick struct args { 42342441Smckusick int fd; 42442441Smckusick } *uap; 42542441Smckusick int *retval; 42638259Smckusick { 42742441Smckusick register struct nameidata *ndp = &u.u_nd; 42838259Smckusick register struct vnode *vp; 42938259Smckusick struct file *fp; 43038259Smckusick int error; 43138259Smckusick 43242441Smckusick if (error = getvnode(u.u_ofile, uap->fd, &fp)) 43338259Smckusick RETURN (error); 43438259Smckusick vp = (struct vnode *)fp->f_data; 43538259Smckusick VOP_LOCK(vp); 43638259Smckusick if (vp->v_type != VDIR) 43738259Smckusick error = ENOTDIR; 43838259Smckusick else 43942441Smckusick error = VOP_ACCESS(vp, VEXEC, ndp->ni_cred); 44038259Smckusick VOP_UNLOCK(vp); 44139860Smckusick if (error) 44239860Smckusick RETURN (error); 44339860Smckusick VREF(vp); 44442441Smckusick vrele(ndp->ni_cdir); 44542441Smckusick ndp->ni_cdir = vp; 44639860Smckusick RETURN (0); 44738259Smckusick } 44838259Smckusick 44938259Smckusick /* 45037741Smckusick * Change current working directory (``.''). 45137741Smckusick */ 45242441Smckusick /* ARGSUSED */ 45342441Smckusick chdir(p, uap, retval) 45442441Smckusick register struct proc *p; 45542441Smckusick struct args { 45642441Smckusick char *fname; 45742441Smckusick } *uap; 45842441Smckusick int *retval; 45937741Smckusick { 46042441Smckusick register struct nameidata *ndp = &u.u_nd; 46137741Smckusick int error; 4626254Sroot 46337741Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 46416694Smckusick ndp->ni_segflg = UIO_USERSPACE; 46516694Smckusick ndp->ni_dirp = uap->fname; 46637741Smckusick if (error = chdirec(ndp)) 46737741Smckusick RETURN (error); 46842441Smckusick vrele(ndp->ni_cdir); 46942441Smckusick ndp->ni_cdir = ndp->ni_vp; 47037741Smckusick RETURN (0); 47137741Smckusick } 4726254Sroot 47337741Smckusick /* 47437741Smckusick * Change notion of root (``/'') directory. 47537741Smckusick */ 47642441Smckusick /* ARGSUSED */ 47742441Smckusick chroot(p, uap, retval) 47842441Smckusick register struct proc *p; 47942441Smckusick struct args { 48042441Smckusick char *fname; 48142441Smckusick } *uap; 48242441Smckusick int *retval; 48337741Smckusick { 48442441Smckusick register struct nameidata *ndp = &u.u_nd; 48537741Smckusick int error; 48637741Smckusick 48742441Smckusick if (error = suser(ndp->ni_cred, &u.u_acflag)) 48837741Smckusick RETURN (error); 48937741Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 49037741Smckusick ndp->ni_segflg = UIO_USERSPACE; 49137741Smckusick ndp->ni_dirp = uap->fname; 49237741Smckusick if (error = chdirec(ndp)) 49337741Smckusick RETURN (error); 49442441Smckusick if (ndp->ni_rdir != NULL) 49542441Smckusick vrele(ndp->ni_rdir); 49642441Smckusick ndp->ni_rdir = ndp->ni_vp; 49737741Smckusick RETURN (0); 4986254Sroot } 4996254Sroot 50037Sbill /* 50137741Smckusick * Common routine for chroot and chdir. 50237741Smckusick */ 50337741Smckusick chdirec(ndp) 50437741Smckusick register struct nameidata *ndp; 50537741Smckusick { 50637741Smckusick struct vnode *vp; 50737741Smckusick int error; 50837741Smckusick 50937741Smckusick if (error = namei(ndp)) 51037741Smckusick return (error); 51137741Smckusick vp = ndp->ni_vp; 51237741Smckusick if (vp->v_type != VDIR) 51337741Smckusick error = ENOTDIR; 51437741Smckusick else 51538399Smckusick error = VOP_ACCESS(vp, VEXEC, ndp->ni_cred); 51637741Smckusick VOP_UNLOCK(vp); 51737741Smckusick if (error) 51837741Smckusick vrele(vp); 51937741Smckusick return (error); 52037741Smckusick } 52137741Smckusick 52237741Smckusick /* 5236254Sroot * Open system call. 52442441Smckusick * Check permissions, allocate an open file structure, 52542441Smckusick * and call the device open routine if any. 5266254Sroot */ 52742441Smckusick open(p, uap, retval) 52842441Smckusick register struct proc *p; 52942441Smckusick register struct args { 5306254Sroot char *fname; 5317701Ssam int mode; 53212756Ssam int crtmode; 53342441Smckusick } *uap; 53442441Smckusick int *retval; 5356254Sroot { 53642441Smckusick struct nameidata *ndp = &u.u_nd; 53742441Smckusick register struct file *fp; 53837741Smckusick int fmode, cmode; 53937741Smckusick struct file *nfp; 54037741Smckusick int indx, error; 54137741Smckusick extern struct fileops vnops; 5426254Sroot 54337741Smckusick if (error = falloc(&nfp, &indx)) 54442441Smckusick RETURN (error); 54537741Smckusick fp = nfp; 54642441Smckusick fmode = uap->mode - FOPEN; 54742441Smckusick cmode = ((uap->crtmode &~ u.u_cmask) & 07777) &~ S_ISVTX; 54842441Smckusick ndp->ni_segflg = UIO_USERSPACE; 54942441Smckusick ndp->ni_dirp = uap->fname; 550*45202Smckusick p->p_dupfd = -indx - 1; /* XXX check for fdopen */ 55142441Smckusick if (error = vn_open(ndp, fmode, cmode)) { 55237741Smckusick crfree(fp->f_cred); 55337741Smckusick fp->f_count--; 55443405Smckusick if (error == ENODEV && /* XXX from fdopen */ 555*45202Smckusick p->p_dupfd >= 0 && 55643450Smckusick (error = dupfdopen(indx, p->p_dupfd, fmode)) == 0) { 55742441Smckusick *retval = indx; 55842441Smckusick RETURN (0); 55942441Smckusick } 56040884Smckusick if (error == ERESTART) 56140884Smckusick error = EINTR; 56242441Smckusick u.u_ofile[indx] = NULL; 56342441Smckusick RETURN (error); 56412756Ssam } 56537741Smckusick fp->f_flag = fmode & FMASK; 56637741Smckusick fp->f_type = DTYPE_VNODE; 56737741Smckusick fp->f_ops = &vnops; 56837741Smckusick fp->f_data = (caddr_t)ndp->ni_vp; 56942441Smckusick *retval = indx; 57042441Smckusick RETURN (0); 5716254Sroot } 5726254Sroot 57342955Smckusick #ifdef COMPAT_43 5746254Sroot /* 57542441Smckusick * Creat system call. 5766254Sroot */ 57742955Smckusick ocreat(p, uap, retval) 57842441Smckusick struct proc *p; 57942441Smckusick register struct args { 58042441Smckusick char *fname; 58142441Smckusick int fmode; 58242441Smckusick } *uap; 58342441Smckusick int *retval; 5846254Sroot { 58542441Smckusick struct args { 5866254Sroot char *fname; 58742441Smckusick int mode; 58842441Smckusick int crtmode; 58942441Smckusick } openuap; 59042441Smckusick 59142441Smckusick openuap.fname = uap->fname; 59242441Smckusick openuap.crtmode = uap->fmode; 59342441Smckusick openuap.mode = O_WRONLY | O_CREAT | O_TRUNC; 59442441Smckusick RETURN (open(p, &openuap, retval)); 59542441Smckusick } 59642955Smckusick #endif /* COMPAT_43 */ 59742441Smckusick 59842441Smckusick /* 59942441Smckusick * Mknod system call 60042441Smckusick */ 60142441Smckusick /* ARGSUSED */ 60242441Smckusick mknod(p, uap, retval) 60342441Smckusick register struct proc *p; 60442441Smckusick register struct args { 60542441Smckusick char *fname; 6066254Sroot int fmode; 6076254Sroot int dev; 60842441Smckusick } *uap; 60942441Smckusick int *retval; 61042441Smckusick { 61142441Smckusick register struct nameidata *ndp = &u.u_nd; 61237741Smckusick register struct vnode *vp; 61337741Smckusick struct vattr vattr; 61437741Smckusick int error; 6156254Sroot 61642441Smckusick if (error = suser(ndp->ni_cred, &u.u_acflag)) 61737741Smckusick RETURN (error); 61837741Smckusick ndp->ni_nameiop = CREATE | LOCKPARENT; 61916694Smckusick ndp->ni_segflg = UIO_USERSPACE; 62016694Smckusick ndp->ni_dirp = uap->fname; 62137741Smckusick if (error = namei(ndp)) 62237741Smckusick RETURN (error); 62337741Smckusick vp = ndp->ni_vp; 62437741Smckusick if (vp != NULL) { 62537741Smckusick error = EEXIST; 62612756Ssam goto out; 6276254Sroot } 62841362Smckusick VATTR_NULL(&vattr); 62940635Smckusick switch (uap->fmode & S_IFMT) { 63012756Ssam 63140635Smckusick case S_IFMT: /* used by badsect to flag bad sectors */ 63237741Smckusick vattr.va_type = VBAD; 63337741Smckusick break; 63440635Smckusick case S_IFCHR: 63537741Smckusick vattr.va_type = VCHR; 63637741Smckusick break; 63740635Smckusick case S_IFBLK: 63837741Smckusick vattr.va_type = VBLK; 63937741Smckusick break; 64037741Smckusick default: 64137741Smckusick error = EINVAL; 64237741Smckusick goto out; 6436254Sroot } 64442441Smckusick vattr.va_mode = (uap->fmode & 07777) &~ u.u_cmask; 64537741Smckusick vattr.va_rdev = uap->dev; 6466254Sroot out: 64742465Smckusick if (!error) { 64842465Smckusick error = VOP_MKNOD(ndp, &vattr, ndp->ni_cred); 64942465Smckusick } else { 65037741Smckusick VOP_ABORTOP(ndp); 65143344Smckusick if (ndp->ni_dvp == vp) 65243344Smckusick vrele(ndp->ni_dvp); 65343344Smckusick else 65443344Smckusick vput(ndp->ni_dvp); 65542465Smckusick if (vp) 65642465Smckusick vrele(vp); 65742465Smckusick } 65837741Smckusick RETURN (error); 6596254Sroot } 6606254Sroot 6616254Sroot /* 66240285Smckusick * Mkfifo system call 66340285Smckusick */ 66442441Smckusick /* ARGSUSED */ 66542441Smckusick mkfifo(p, uap, retval) 66642441Smckusick register struct proc *p; 66742441Smckusick register struct args { 66840285Smckusick char *fname; 66940285Smckusick int fmode; 67042441Smckusick } *uap; 67142441Smckusick int *retval; 67242441Smckusick { 67342441Smckusick register struct nameidata *ndp = &u.u_nd; 67440285Smckusick struct vattr vattr; 67540285Smckusick int error; 67640285Smckusick 67740285Smckusick #ifndef FIFO 67840285Smckusick RETURN (EOPNOTSUPP); 67940285Smckusick #else 68040285Smckusick ndp->ni_nameiop = CREATE | LOCKPARENT; 68140285Smckusick ndp->ni_segflg = UIO_USERSPACE; 68240285Smckusick ndp->ni_dirp = uap->fname; 68340285Smckusick if (error = namei(ndp)) 68440285Smckusick RETURN (error); 68540285Smckusick if (ndp->ni_vp != NULL) { 68640285Smckusick VOP_ABORTOP(ndp); 68743344Smckusick if (ndp->ni_dvp == ndp->ni_vp) 68843344Smckusick vrele(ndp->ni_dvp); 68943344Smckusick else 69043344Smckusick vput(ndp->ni_dvp); 69142465Smckusick vrele(ndp->ni_vp); 69240285Smckusick RETURN (EEXIST); 69340285Smckusick } else { 69441362Smckusick VATTR_NULL(&vattr); 69540285Smckusick vattr.va_type = VFIFO; 69642441Smckusick vattr.va_mode = (uap->fmode & 07777) &~ u.u_cmask; 69740285Smckusick } 69840285Smckusick RETURN (VOP_MKNOD(ndp, &vattr, ndp->ni_cred)); 69940285Smckusick #endif /* FIFO */ 70040285Smckusick } 70140285Smckusick 70240285Smckusick /* 7036254Sroot * link system call 7046254Sroot */ 70542441Smckusick /* ARGSUSED */ 70642441Smckusick link(p, uap, retval) 70742441Smckusick register struct proc *p; 70842441Smckusick register struct args { 7096254Sroot char *target; 7106254Sroot char *linkname; 71142441Smckusick } *uap; 71242441Smckusick int *retval; 71342441Smckusick { 71442441Smckusick register struct nameidata *ndp = &u.u_nd; 71537741Smckusick register struct vnode *vp, *xp; 71637741Smckusick int error; 7176254Sroot 71816694Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW; 71916694Smckusick ndp->ni_segflg = UIO_USERSPACE; 72016694Smckusick ndp->ni_dirp = uap->target; 72137741Smckusick if (error = namei(ndp)) 72237741Smckusick RETURN (error); 72337741Smckusick vp = ndp->ni_vp; 72437741Smckusick if (vp->v_type == VDIR && 72542441Smckusick (error = suser(ndp->ni_cred, &u.u_acflag))) 72637741Smckusick goto out1; 72737741Smckusick ndp->ni_nameiop = CREATE | LOCKPARENT; 72816694Smckusick ndp->ni_dirp = (caddr_t)uap->linkname; 72937741Smckusick if (error = namei(ndp)) 73037741Smckusick goto out1; 73137741Smckusick xp = ndp->ni_vp; 7326254Sroot if (xp != NULL) { 73337741Smckusick error = EEXIST; 7346254Sroot goto out; 7356254Sroot } 73637741Smckusick xp = ndp->ni_dvp; 73737741Smckusick if (vp->v_mount != xp->v_mount) 73837741Smckusick error = EXDEV; 7396254Sroot out: 74042465Smckusick if (!error) { 74142465Smckusick error = VOP_LINK(vp, ndp); 74242465Smckusick } else { 74337741Smckusick VOP_ABORTOP(ndp); 74443344Smckusick if (ndp->ni_dvp == ndp->ni_vp) 74543344Smckusick vrele(ndp->ni_dvp); 74643344Smckusick else 74743344Smckusick vput(ndp->ni_dvp); 74842465Smckusick if (ndp->ni_vp) 74942465Smckusick vrele(ndp->ni_vp); 75042465Smckusick } 75137741Smckusick out1: 75237741Smckusick vrele(vp); 75337741Smckusick RETURN (error); 7546254Sroot } 7556254Sroot 7566254Sroot /* 7576254Sroot * symlink -- make a symbolic link 7586254Sroot */ 75942441Smckusick /* ARGSUSED */ 76042441Smckusick symlink(p, uap, retval) 76142441Smckusick register struct proc *p; 76242441Smckusick register struct args { 7636254Sroot char *target; 7646254Sroot char *linkname; 76542441Smckusick } *uap; 76642441Smckusick int *retval; 76742441Smckusick { 76842441Smckusick register struct nameidata *ndp = &u.u_nd; 76937741Smckusick struct vattr vattr; 77037741Smckusick char *target; 77137741Smckusick int error; 7726254Sroot 77316694Smckusick ndp->ni_segflg = UIO_USERSPACE; 77416694Smckusick ndp->ni_dirp = uap->linkname; 77537741Smckusick MALLOC(target, char *, MAXPATHLEN, M_NAMEI, M_WAITOK); 77637741Smckusick if (error = copyinstr(uap->target, target, MAXPATHLEN, (u_int *)0)) 77742465Smckusick goto out; 77837741Smckusick ndp->ni_nameiop = CREATE | LOCKPARENT; 77937741Smckusick if (error = namei(ndp)) 78042465Smckusick goto out; 78142465Smckusick if (ndp->ni_vp) { 78242465Smckusick VOP_ABORTOP(ndp); 78343344Smckusick if (ndp->ni_dvp == ndp->ni_vp) 78443344Smckusick vrele(ndp->ni_dvp); 78543344Smckusick else 78643344Smckusick vput(ndp->ni_dvp); 78742465Smckusick vrele(ndp->ni_vp); 78837741Smckusick error = EEXIST; 78937741Smckusick goto out; 7906254Sroot } 79141362Smckusick VATTR_NULL(&vattr); 79242441Smckusick vattr.va_mode = 0777 &~ u.u_cmask; 79342465Smckusick error = VOP_SYMLINK(ndp, &vattr, target); 79437741Smckusick out: 79537741Smckusick FREE(target, M_NAMEI); 79637741Smckusick RETURN (error); 7976254Sroot } 7986254Sroot 7996254Sroot /* 8006254Sroot * Unlink system call. 8016254Sroot * Hard to avoid races here, especially 8026254Sroot * in unlinking directories. 8036254Sroot */ 80442441Smckusick /* ARGSUSED */ 80542441Smckusick unlink(p, uap, retval) 80642441Smckusick register struct proc *p; 80742441Smckusick struct args { 80842441Smckusick char *fname; 80942441Smckusick } *uap; 81042441Smckusick int *retval; 8116254Sroot { 81242441Smckusick register struct nameidata *ndp = &u.u_nd; 81337741Smckusick register struct vnode *vp; 81437741Smckusick int error; 8156254Sroot 81637741Smckusick ndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF; 81716694Smckusick ndp->ni_segflg = UIO_USERSPACE; 81816694Smckusick ndp->ni_dirp = uap->fname; 81937741Smckusick if (error = namei(ndp)) 82037741Smckusick RETURN (error); 82137741Smckusick vp = ndp->ni_vp; 82237741Smckusick if (vp->v_type == VDIR && 82342441Smckusick (error = suser(ndp->ni_cred, &u.u_acflag))) 8246254Sroot goto out; 8256254Sroot /* 8266254Sroot * Don't unlink a mounted file. 8276254Sroot */ 82837741Smckusick if (vp->v_flag & VROOT) { 82937741Smckusick error = EBUSY; 8306254Sroot goto out; 8316254Sroot } 83237741Smckusick if (vp->v_flag & VTEXT) 83337741Smckusick xrele(vp); /* try once to free text */ 8346254Sroot out: 83542465Smckusick if (!error) { 83642465Smckusick error = VOP_REMOVE(ndp); 83742465Smckusick } else { 83837741Smckusick VOP_ABORTOP(ndp); 83943344Smckusick if (ndp->ni_dvp == vp) 84043344Smckusick vrele(ndp->ni_dvp); 84143344Smckusick else 84243344Smckusick vput(ndp->ni_dvp); 84342465Smckusick vput(vp); 84442465Smckusick } 84537741Smckusick RETURN (error); 8466254Sroot } 8476254Sroot 8486254Sroot /* 8496254Sroot * Seek system call 8506254Sroot */ 85142441Smckusick lseek(p, uap, retval) 85242441Smckusick register struct proc *p; 85342441Smckusick register struct args { 85437741Smckusick int fdes; 8556254Sroot off_t off; 8566254Sroot int sbase; 85742441Smckusick } *uap; 85842441Smckusick off_t *retval; 85942441Smckusick { 86042441Smckusick struct ucred *cred = u.u_nd.ni_cred; 86142441Smckusick register struct file *fp; 86237741Smckusick struct vattr vattr; 86337741Smckusick int error; 8646254Sroot 86537741Smckusick if ((unsigned)uap->fdes >= NOFILE || 86642441Smckusick (fp = u.u_ofile[uap->fdes]) == NULL) 86737741Smckusick RETURN (EBADF); 86837741Smckusick if (fp->f_type != DTYPE_VNODE) 86937741Smckusick RETURN (ESPIPE); 87013878Ssam switch (uap->sbase) { 87113878Ssam 87213878Ssam case L_INCR: 87313878Ssam fp->f_offset += uap->off; 87413878Ssam break; 87513878Ssam 87613878Ssam case L_XTND: 87737741Smckusick if (error = VOP_GETATTR((struct vnode *)fp->f_data, 87842441Smckusick &vattr, cred)) 87937741Smckusick RETURN (error); 88037741Smckusick fp->f_offset = uap->off + vattr.va_size; 88113878Ssam break; 88213878Ssam 88313878Ssam case L_SET: 88413878Ssam fp->f_offset = uap->off; 88513878Ssam break; 88613878Ssam 88713878Ssam default: 88837741Smckusick RETURN (EINVAL); 88913878Ssam } 89042441Smckusick *retval = fp->f_offset; 89137741Smckusick RETURN (0); 8926254Sroot } 8936254Sroot 8946254Sroot /* 8956254Sroot * Access system call 8966254Sroot */ 89742441Smckusick /* ARGSUSED */ 89842441Smckusick saccess(p, uap, retval) 89942441Smckusick register struct proc *p; 90042441Smckusick register struct args { 9016254Sroot char *fname; 9026254Sroot int fmode; 90342441Smckusick } *uap; 90442441Smckusick int *retval; 90542441Smckusick { 90642441Smckusick register struct nameidata *ndp = &u.u_nd; 90742441Smckusick register struct ucred *cred = ndp->ni_cred; 90837741Smckusick register struct vnode *vp; 90937741Smckusick int error, mode, svuid, svgid; 9106254Sroot 91142441Smckusick svuid = cred->cr_uid; 91242441Smckusick svgid = cred->cr_groups[0]; 91342441Smckusick cred->cr_uid = p->p_ruid; 91442441Smckusick cred->cr_groups[0] = p->p_rgid; 91537741Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 91616694Smckusick ndp->ni_segflg = UIO_USERSPACE; 91716694Smckusick ndp->ni_dirp = uap->fname; 91837741Smckusick if (error = namei(ndp)) 91937741Smckusick goto out1; 92037741Smckusick vp = ndp->ni_vp; 92137741Smckusick /* 92237741Smckusick * fmode == 0 means only check for exist 92337741Smckusick */ 92437741Smckusick if (uap->fmode) { 92537741Smckusick mode = 0; 92637741Smckusick if (uap->fmode & R_OK) 92737741Smckusick mode |= VREAD; 92837741Smckusick if (uap->fmode & W_OK) 92937741Smckusick mode |= VWRITE; 93037741Smckusick if (uap->fmode & X_OK) 93137741Smckusick mode |= VEXEC; 93239543Smckusick if ((mode & VWRITE) == 0 || (error = vn_writechk(vp)) == 0) 93338399Smckusick error = VOP_ACCESS(vp, mode, ndp->ni_cred); 9346254Sroot } 93537741Smckusick vput(vp); 93637741Smckusick out1: 93742441Smckusick cred->cr_uid = svuid; 93842441Smckusick cred->cr_groups[0] = svgid; 93937741Smckusick RETURN (error); 9406254Sroot } 9416254Sroot 9426254Sroot /* 9436574Smckusic * Stat system call. This version follows links. 94437Sbill */ 94542441Smckusick /* ARGSUSED */ 94642441Smckusick stat(p, uap, retval) 94742441Smckusick register struct proc *p; 94842441Smckusick register struct args { 94942441Smckusick char *fname; 95042441Smckusick struct stat *ub; 95142441Smckusick } *uap; 95242441Smckusick int *retval; 95337Sbill { 95442441Smckusick register struct nameidata *ndp = &u.u_nd; 95542441Smckusick struct stat sb; 95642441Smckusick int error; 95737Sbill 95842441Smckusick ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW; 95942441Smckusick ndp->ni_segflg = UIO_USERSPACE; 96042441Smckusick ndp->ni_dirp = uap->fname; 96142441Smckusick if (error = namei(ndp)) 96242441Smckusick RETURN (error); 96342441Smckusick error = vn_stat(ndp->ni_vp, &sb); 96442441Smckusick vput(ndp->ni_vp); 96542441Smckusick if (error) 96642441Smckusick RETURN (error); 96742441Smckusick error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb)); 96842441Smckusick RETURN (error); 96937Sbill } 97037Sbill 97137Sbill /* 9726574Smckusic * Lstat system call. This version does not follow links. 9735992Swnj */ 97442441Smckusick /* ARGSUSED */ 97542441Smckusick lstat(p, uap, retval) 97642441Smckusick register struct proc *p; 97742441Smckusick register struct args { 9785992Swnj char *fname; 97912756Ssam struct stat *ub; 98042441Smckusick } *uap; 98142441Smckusick int *retval; 98242441Smckusick { 98342441Smckusick register struct nameidata *ndp = &u.u_nd; 98412756Ssam struct stat sb; 98537741Smckusick int error; 9865992Swnj 98742441Smckusick ndp->ni_nameiop = LOOKUP | LOCKLEAF | NOFOLLOW; 98816694Smckusick ndp->ni_segflg = UIO_USERSPACE; 98916694Smckusick ndp->ni_dirp = uap->fname; 99037741Smckusick if (error = namei(ndp)) 99137741Smckusick RETURN (error); 99237741Smckusick error = vn_stat(ndp->ni_vp, &sb); 99337741Smckusick vput(ndp->ni_vp); 99437741Smckusick if (error) 99537741Smckusick RETURN (error); 99637741Smckusick error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb)); 99737741Smckusick RETURN (error); 9985992Swnj } 9995992Swnj 10005992Swnj /* 10015992Swnj * Return target name of a symbolic link 100237Sbill */ 100342441Smckusick /* ARGSUSED */ 100442441Smckusick readlink(p, uap, retval) 100542441Smckusick register struct proc *p; 100642441Smckusick register struct args { 10075992Swnj char *name; 10085992Swnj char *buf; 10095992Swnj int count; 101042441Smckusick } *uap; 101142441Smckusick int *retval; 101242441Smckusick { 101342441Smckusick register struct nameidata *ndp = &u.u_nd; 101437741Smckusick register struct vnode *vp; 101537741Smckusick struct iovec aiov; 101637741Smckusick struct uio auio; 101737741Smckusick int error; 10185992Swnj 101937741Smckusick ndp->ni_nameiop = LOOKUP | LOCKLEAF; 102016694Smckusick ndp->ni_segflg = UIO_USERSPACE; 102116694Smckusick ndp->ni_dirp = uap->name; 102237741Smckusick if (error = namei(ndp)) 102337741Smckusick RETURN (error); 102437741Smckusick vp = ndp->ni_vp; 102537741Smckusick if (vp->v_type != VLNK) { 102637741Smckusick error = EINVAL; 10275992Swnj goto out; 10285992Swnj } 102937741Smckusick aiov.iov_base = uap->buf; 103037741Smckusick aiov.iov_len = uap->count; 103137741Smckusick auio.uio_iov = &aiov; 103237741Smckusick auio.uio_iovcnt = 1; 103337741Smckusick auio.uio_offset = 0; 103437741Smckusick auio.uio_rw = UIO_READ; 103537741Smckusick auio.uio_segflg = UIO_USERSPACE; 103637741Smckusick auio.uio_resid = uap->count; 103737741Smckusick error = VOP_READLINK(vp, &auio, ndp->ni_cred); 10385992Swnj out: 103937741Smckusick vput(vp); 104042441Smckusick *retval = uap->count - auio.uio_resid; 104137741Smckusick RETURN (error); 10425992Swnj } 10435992Swnj 10449167Ssam /* 104538259Smckusick * Change flags of a file given path name. 104638259Smckusick */ 104742441Smckusick /* ARGSUSED */ 104842441Smckusick chflags(p, uap, retval) 104942441Smckusick register struct proc *p; 105042441Smckusick register struct args { 105138259Smckusick char *fname; 105238259Smckusick int flags; 105342441Smckusick } *uap; 105442441Smckusick int *retval; 105542441Smckusick { 105642441Smckusick register struct nameidata *ndp = &u.u_nd; 105738259Smckusick register struct vnode *vp; 105838259Smckusick struct vattr vattr; 105938259Smckusick int error; 106038259Smckusick 106138259Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 106238259Smckusick ndp->ni_segflg = UIO_USERSPACE; 106338259Smckusick ndp->ni_dirp = uap->fname; 106441362Smckusick VATTR_NULL(&vattr); 106538259Smckusick vattr.va_flags = uap->flags; 106638259Smckusick if (error = namei(ndp)) 106738259Smckusick RETURN (error); 106838259Smckusick vp = ndp->ni_vp; 106941400Smckusick if (vp->v_mount->mnt_flag & MNT_RDONLY) { 107038259Smckusick error = EROFS; 107138259Smckusick goto out; 107238259Smckusick } 107338259Smckusick error = VOP_SETATTR(vp, &vattr, ndp->ni_cred); 107438259Smckusick out: 107538259Smckusick vput(vp); 107638259Smckusick RETURN (error); 107738259Smckusick } 107838259Smckusick 107938259Smckusick /* 108038259Smckusick * Change flags of a file given a file descriptor. 108138259Smckusick */ 108242441Smckusick /* ARGSUSED */ 108342441Smckusick fchflags(p, uap, retval) 108442441Smckusick register struct proc *p; 108542441Smckusick register struct args { 108638259Smckusick int fd; 108738259Smckusick int flags; 108842441Smckusick } *uap; 108942441Smckusick int *retval; 109042441Smckusick { 109138259Smckusick struct vattr vattr; 109238259Smckusick struct vnode *vp; 109338259Smckusick struct file *fp; 109438259Smckusick int error; 109538259Smckusick 109642441Smckusick if (error = getvnode(u.u_ofile, uap->fd, &fp)) 109738259Smckusick RETURN (error); 109841362Smckusick VATTR_NULL(&vattr); 109938259Smckusick vattr.va_flags = uap->flags; 110038259Smckusick vp = (struct vnode *)fp->f_data; 110138259Smckusick VOP_LOCK(vp); 110241400Smckusick if (vp->v_mount->mnt_flag & MNT_RDONLY) { 110338259Smckusick error = EROFS; 110438259Smckusick goto out; 110538259Smckusick } 110638259Smckusick error = VOP_SETATTR(vp, &vattr, fp->f_cred); 110738259Smckusick out: 110838259Smckusick VOP_UNLOCK(vp); 110938259Smckusick RETURN (error); 111038259Smckusick } 111138259Smckusick 111238259Smckusick /* 11139167Ssam * Change mode of a file given path name. 11149167Ssam */ 111542441Smckusick /* ARGSUSED */ 111642441Smckusick chmod(p, uap, retval) 111742441Smckusick register struct proc *p; 111842441Smckusick register struct args { 11196254Sroot char *fname; 11206254Sroot int fmode; 112142441Smckusick } *uap; 112242441Smckusick int *retval; 112342441Smckusick { 112442441Smckusick register struct nameidata *ndp = &u.u_nd; 112537741Smckusick register struct vnode *vp; 112637741Smckusick struct vattr vattr; 112737741Smckusick int error; 11285992Swnj 112937741Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 113037741Smckusick ndp->ni_segflg = UIO_USERSPACE; 113137741Smckusick ndp->ni_dirp = uap->fname; 113241362Smckusick VATTR_NULL(&vattr); 113337741Smckusick vattr.va_mode = uap->fmode & 07777; 113437741Smckusick if (error = namei(ndp)) 113537741Smckusick RETURN (error); 113637741Smckusick vp = ndp->ni_vp; 113741400Smckusick if (vp->v_mount->mnt_flag & MNT_RDONLY) { 113837741Smckusick error = EROFS; 113937741Smckusick goto out; 114037741Smckusick } 114137741Smckusick error = VOP_SETATTR(vp, &vattr, ndp->ni_cred); 114237741Smckusick out: 114337741Smckusick vput(vp); 114437741Smckusick RETURN (error); 11457701Ssam } 11467439Sroot 11479167Ssam /* 11489167Ssam * Change mode of a file given a file descriptor. 11499167Ssam */ 115042441Smckusick /* ARGSUSED */ 115142441Smckusick fchmod(p, uap, retval) 115242441Smckusick register struct proc *p; 115342441Smckusick register struct args { 11547701Ssam int fd; 11557701Ssam int fmode; 115642441Smckusick } *uap; 115742441Smckusick int *retval; 115842441Smckusick { 115937741Smckusick struct vattr vattr; 116037741Smckusick struct vnode *vp; 116137741Smckusick struct file *fp; 116237741Smckusick int error; 11637701Ssam 116442441Smckusick if (error = getvnode(u.u_ofile, uap->fd, &fp)) 116537741Smckusick RETURN (error); 116641362Smckusick VATTR_NULL(&vattr); 116737741Smckusick vattr.va_mode = uap->fmode & 07777; 116837741Smckusick vp = (struct vnode *)fp->f_data; 116937741Smckusick VOP_LOCK(vp); 117041400Smckusick if (vp->v_mount->mnt_flag & MNT_RDONLY) { 117137741Smckusick error = EROFS; 117237741Smckusick goto out; 11737439Sroot } 117437741Smckusick error = VOP_SETATTR(vp, &vattr, fp->f_cred); 117537741Smckusick out: 117637741Smckusick VOP_UNLOCK(vp); 117737741Smckusick RETURN (error); 11785992Swnj } 11795992Swnj 11809167Ssam /* 11819167Ssam * Set ownership given a path name. 11829167Ssam */ 118342441Smckusick /* ARGSUSED */ 118442441Smckusick chown(p, uap, retval) 118542441Smckusick register struct proc *p; 118642441Smckusick register struct args { 11876254Sroot char *fname; 11886254Sroot int uid; 11896254Sroot int gid; 119042441Smckusick } *uap; 119142441Smckusick int *retval; 119242441Smckusick { 119342441Smckusick register struct nameidata *ndp = &u.u_nd; 119437741Smckusick register struct vnode *vp; 119537741Smckusick struct vattr vattr; 119637741Smckusick int error; 119737Sbill 119837741Smckusick ndp->ni_nameiop = LOOKUP | NOFOLLOW | LOCKLEAF; 119936614Sbostic ndp->ni_segflg = UIO_USERSPACE; 120036614Sbostic ndp->ni_dirp = uap->fname; 120141362Smckusick VATTR_NULL(&vattr); 120237741Smckusick vattr.va_uid = uap->uid; 120337741Smckusick vattr.va_gid = uap->gid; 120437741Smckusick if (error = namei(ndp)) 120537741Smckusick RETURN (error); 120637741Smckusick vp = ndp->ni_vp; 120741400Smckusick if (vp->v_mount->mnt_flag & MNT_RDONLY) { 120837741Smckusick error = EROFS; 120937741Smckusick goto out; 121037741Smckusick } 121137741Smckusick error = VOP_SETATTR(vp, &vattr, ndp->ni_cred); 121237741Smckusick out: 121337741Smckusick vput(vp); 121437741Smckusick RETURN (error); 12157701Ssam } 12167439Sroot 12179167Ssam /* 12189167Ssam * Set ownership given a file descriptor. 12199167Ssam */ 122042441Smckusick /* ARGSUSED */ 122142441Smckusick fchown(p, uap, retval) 122242441Smckusick register struct proc *p; 122342441Smckusick register struct args { 12247701Ssam int fd; 12257701Ssam int uid; 12267701Ssam int gid; 122742441Smckusick } *uap; 122842441Smckusick int *retval; 122942441Smckusick { 123037741Smckusick struct vattr vattr; 123137741Smckusick struct vnode *vp; 123237741Smckusick struct file *fp; 123337741Smckusick int error; 12347701Ssam 123542441Smckusick if (error = getvnode(u.u_ofile, uap->fd, &fp)) 123637741Smckusick RETURN (error); 123741362Smckusick VATTR_NULL(&vattr); 123837741Smckusick vattr.va_uid = uap->uid; 123937741Smckusick vattr.va_gid = uap->gid; 124037741Smckusick vp = (struct vnode *)fp->f_data; 124137741Smckusick VOP_LOCK(vp); 124241400Smckusick if (vp->v_mount->mnt_flag & MNT_RDONLY) { 124337741Smckusick error = EROFS; 124437741Smckusick goto out; 124537741Smckusick } 124637741Smckusick error = VOP_SETATTR(vp, &vattr, fp->f_cred); 124737741Smckusick out: 124837741Smckusick VOP_UNLOCK(vp); 124937741Smckusick RETURN (error); 12507701Ssam } 12517701Ssam 125242441Smckusick /* 125342441Smckusick * Set the access and modification times of a file. 125442441Smckusick */ 125542441Smckusick /* ARGSUSED */ 125642441Smckusick utimes(p, uap, retval) 125742441Smckusick register struct proc *p; 125842441Smckusick register struct args { 125911811Ssam char *fname; 126011811Ssam struct timeval *tptr; 126142441Smckusick } *uap; 126242441Smckusick int *retval; 126342441Smckusick { 126442441Smckusick register struct nameidata *ndp = &u.u_nd; 126537741Smckusick register struct vnode *vp; 126611811Ssam struct timeval tv[2]; 126737741Smckusick struct vattr vattr; 126837741Smckusick int error; 126911811Ssam 127037741Smckusick if (error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv))) 127137741Smckusick RETURN (error); 127237741Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 127337741Smckusick ndp->ni_segflg = UIO_USERSPACE; 127437741Smckusick ndp->ni_dirp = uap->fname; 127541362Smckusick VATTR_NULL(&vattr); 127637741Smckusick vattr.va_atime = tv[0]; 127737741Smckusick vattr.va_mtime = tv[1]; 127837741Smckusick if (error = namei(ndp)) 127937741Smckusick RETURN (error); 128037741Smckusick vp = ndp->ni_vp; 128141400Smckusick if (vp->v_mount->mnt_flag & MNT_RDONLY) { 128237741Smckusick error = EROFS; 128337741Smckusick goto out; 128421015Smckusick } 128537741Smckusick error = VOP_SETATTR(vp, &vattr, ndp->ni_cred); 128637741Smckusick out: 128737741Smckusick vput(vp); 128837741Smckusick RETURN (error); 128911811Ssam } 129011811Ssam 12919167Ssam /* 12929167Ssam * Truncate a file given its path name. 12939167Ssam */ 129442441Smckusick /* ARGSUSED */ 129542441Smckusick truncate(p, uap, retval) 129642441Smckusick register struct proc *p; 129742441Smckusick register struct args { 12987701Ssam char *fname; 129926473Skarels off_t length; 130042441Smckusick } *uap; 130142441Smckusick int *retval; 130242441Smckusick { 130342441Smckusick register struct nameidata *ndp = &u.u_nd; 130437741Smckusick register struct vnode *vp; 130537741Smckusick struct vattr vattr; 130637741Smckusick int error; 13077701Ssam 130837741Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 130916694Smckusick ndp->ni_segflg = UIO_USERSPACE; 131016694Smckusick ndp->ni_dirp = uap->fname; 131141362Smckusick VATTR_NULL(&vattr); 131237741Smckusick vattr.va_size = uap->length; 131337741Smckusick if (error = namei(ndp)) 131437741Smckusick RETURN (error); 131537741Smckusick vp = ndp->ni_vp; 131637741Smckusick if (vp->v_type == VDIR) { 131737741Smckusick error = EISDIR; 131837741Smckusick goto out; 13197701Ssam } 132038399Smckusick if ((error = vn_writechk(vp)) || 132138399Smckusick (error = VOP_ACCESS(vp, VWRITE, ndp->ni_cred))) 132237741Smckusick goto out; 132337741Smckusick error = VOP_SETATTR(vp, &vattr, ndp->ni_cred); 132437741Smckusick out: 132537741Smckusick vput(vp); 132637741Smckusick RETURN (error); 13277701Ssam } 13287701Ssam 13299167Ssam /* 13309167Ssam * Truncate a file given a file descriptor. 13319167Ssam */ 133242441Smckusick /* ARGSUSED */ 133342441Smckusick ftruncate(p, uap, retval) 133442441Smckusick register struct proc *p; 133542441Smckusick register struct args { 13367701Ssam int fd; 133726473Skarels off_t length; 133842441Smckusick } *uap; 133942441Smckusick int *retval; 134042441Smckusick { 134137741Smckusick struct vattr vattr; 134237741Smckusick struct vnode *vp; 13437701Ssam struct file *fp; 134437741Smckusick int error; 13457701Ssam 134642441Smckusick if (error = getvnode(u.u_ofile, uap->fd, &fp)) 134737741Smckusick RETURN (error); 134837741Smckusick if ((fp->f_flag & FWRITE) == 0) 134937741Smckusick RETURN (EINVAL); 135041362Smckusick VATTR_NULL(&vattr); 135137741Smckusick vattr.va_size = uap->length; 135237741Smckusick vp = (struct vnode *)fp->f_data; 135337741Smckusick VOP_LOCK(vp); 135437741Smckusick if (vp->v_type == VDIR) { 135537741Smckusick error = EISDIR; 135637741Smckusick goto out; 13577701Ssam } 135838399Smckusick if (error = vn_writechk(vp)) 135937741Smckusick goto out; 136037741Smckusick error = VOP_SETATTR(vp, &vattr, fp->f_cred); 136137741Smckusick out: 136237741Smckusick VOP_UNLOCK(vp); 136337741Smckusick RETURN (error); 13647701Ssam } 13657701Ssam 13669167Ssam /* 13679167Ssam * Synch an open file. 13689167Ssam */ 136942441Smckusick /* ARGSUSED */ 137042441Smckusick fsync(p, uap, retval) 137142441Smckusick register struct proc *p; 137242441Smckusick struct args { 137342441Smckusick int fd; 137442441Smckusick } *uap; 137542441Smckusick int *retval; 13769167Ssam { 137739592Smckusick register struct vnode *vp; 13789167Ssam struct file *fp; 137937741Smckusick int error; 13809167Ssam 138142441Smckusick if (error = getvnode(u.u_ofile, uap->fd, &fp)) 138237741Smckusick RETURN (error); 138339592Smckusick vp = (struct vnode *)fp->f_data; 138439592Smckusick VOP_LOCK(vp); 138539592Smckusick error = VOP_FSYNC(vp, fp->f_flag, fp->f_cred, MNT_WAIT); 138639592Smckusick VOP_UNLOCK(vp); 138737741Smckusick RETURN (error); 13889167Ssam } 13899167Ssam 13909167Ssam /* 13919167Ssam * Rename system call. 13929167Ssam * 13939167Ssam * Source and destination must either both be directories, or both 13949167Ssam * not be directories. If target is a directory, it must be empty. 13959167Ssam */ 139642441Smckusick /* ARGSUSED */ 139742441Smckusick rename(p, uap, retval) 139842441Smckusick register struct proc *p; 139942441Smckusick register struct args { 14007701Ssam char *from; 14017701Ssam char *to; 140242441Smckusick } *uap; 140342441Smckusick int *retval; 140442441Smckusick { 140537741Smckusick register struct vnode *tvp, *fvp, *tdvp; 140642441Smckusick register struct nameidata *ndp = &u.u_nd; 140737741Smckusick struct nameidata tond; 140837741Smckusick int error; 14097701Ssam 141037741Smckusick ndp->ni_nameiop = DELETE | WANTPARENT; 141116694Smckusick ndp->ni_segflg = UIO_USERSPACE; 141216694Smckusick ndp->ni_dirp = uap->from; 141337741Smckusick if (error = namei(ndp)) 141437741Smckusick RETURN (error); 141537741Smckusick fvp = ndp->ni_vp; 141638266Smckusick nddup(ndp, &tond); 141737741Smckusick tond.ni_nameiop = RENAME | LOCKPARENT | LOCKLEAF | NOCACHE; 141837741Smckusick tond.ni_segflg = UIO_USERSPACE; 141937741Smckusick tond.ni_dirp = uap->to; 142042465Smckusick if (error = namei(&tond)) { 142142465Smckusick VOP_ABORTOP(ndp); 142242465Smckusick vrele(ndp->ni_dvp); 142342465Smckusick vrele(fvp); 142442465Smckusick goto out1; 142542465Smckusick } 142637741Smckusick tdvp = tond.ni_dvp; 142737741Smckusick tvp = tond.ni_vp; 142837741Smckusick if (tvp != NULL) { 142937741Smckusick if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 143039242Sbostic error = ENOTDIR; 143137741Smckusick goto out; 143237741Smckusick } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 143339242Sbostic error = EISDIR; 143437741Smckusick goto out; 14359167Ssam } 14369167Ssam } 143737741Smckusick if (fvp->v_mount != tdvp->v_mount) { 143837741Smckusick error = EXDEV; 14399167Ssam goto out; 144010051Ssam } 144139286Smckusick if (fvp == tdvp) 144237741Smckusick error = EINVAL; 144339286Smckusick /* 144439286Smckusick * If source is the same as the destination, 144539286Smckusick * then there is nothing to do. 144639286Smckusick */ 144739286Smckusick if (fvp == tvp) 144839286Smckusick error = -1; 144937741Smckusick out: 145042465Smckusick if (!error) { 145142465Smckusick error = VOP_RENAME(ndp, &tond); 145242465Smckusick } else { 145337741Smckusick VOP_ABORTOP(&tond); 145443344Smckusick if (tdvp == tvp) 145543344Smckusick vrele(tdvp); 145643344Smckusick else 145743344Smckusick vput(tdvp); 145842465Smckusick if (tvp) 145942465Smckusick vput(tvp); 146037741Smckusick VOP_ABORTOP(ndp); 146142465Smckusick vrele(ndp->ni_dvp); 146242465Smckusick vrele(fvp); 14639167Ssam } 146437741Smckusick out1: 146538266Smckusick ndrele(&tond); 146639286Smckusick if (error == -1) 146739286Smckusick RETURN (0); 146837741Smckusick RETURN (error); 14697701Ssam } 14707701Ssam 14717535Sroot /* 147212756Ssam * Mkdir system call 147312756Ssam */ 147442441Smckusick /* ARGSUSED */ 147542441Smckusick mkdir(p, uap, retval) 147642441Smckusick register struct proc *p; 147742441Smckusick register struct args { 147812756Ssam char *name; 147912756Ssam int dmode; 148042441Smckusick } *uap; 148142441Smckusick int *retval; 148242441Smckusick { 148342441Smckusick register struct nameidata *ndp = &u.u_nd; 148437741Smckusick register struct vnode *vp; 148537741Smckusick struct vattr vattr; 148637741Smckusick int error; 148712756Ssam 148837741Smckusick ndp->ni_nameiop = CREATE | LOCKPARENT; 148916694Smckusick ndp->ni_segflg = UIO_USERSPACE; 149016694Smckusick ndp->ni_dirp = uap->name; 149137741Smckusick if (error = namei(ndp)) 149237741Smckusick RETURN (error); 149337741Smckusick vp = ndp->ni_vp; 149437741Smckusick if (vp != NULL) { 149537741Smckusick VOP_ABORTOP(ndp); 149643344Smckusick if (ndp->ni_dvp == vp) 149743344Smckusick vrele(ndp->ni_dvp); 149843344Smckusick else 149943344Smckusick vput(ndp->ni_dvp); 150042465Smckusick vrele(vp); 150137741Smckusick RETURN (EEXIST); 150212756Ssam } 150341362Smckusick VATTR_NULL(&vattr); 150437741Smckusick vattr.va_type = VDIR; 150542441Smckusick vattr.va_mode = (uap->dmode & 0777) &~ u.u_cmask; 150637741Smckusick error = VOP_MKDIR(ndp, &vattr); 150738145Smckusick if (!error) 150838145Smckusick vput(ndp->ni_vp); 150937741Smckusick RETURN (error); 151012756Ssam } 151112756Ssam 151212756Ssam /* 151312756Ssam * Rmdir system call. 151412756Ssam */ 151542441Smckusick /* ARGSUSED */ 151642441Smckusick rmdir(p, uap, retval) 151742441Smckusick register struct proc *p; 151842441Smckusick struct args { 151942441Smckusick char *name; 152042441Smckusick } *uap; 152142441Smckusick int *retval; 152212756Ssam { 152342441Smckusick register struct nameidata *ndp = &u.u_nd; 152437741Smckusick register struct vnode *vp; 152537741Smckusick int error; 152612756Ssam 152737741Smckusick ndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF; 152816694Smckusick ndp->ni_segflg = UIO_USERSPACE; 152916694Smckusick ndp->ni_dirp = uap->name; 153037741Smckusick if (error = namei(ndp)) 153137741Smckusick RETURN (error); 153237741Smckusick vp = ndp->ni_vp; 153337741Smckusick if (vp->v_type != VDIR) { 153437741Smckusick error = ENOTDIR; 153512756Ssam goto out; 153612756Ssam } 153712756Ssam /* 153837741Smckusick * No rmdir "." please. 153912756Ssam */ 154037741Smckusick if (ndp->ni_dvp == vp) { 154137741Smckusick error = EINVAL; 154212756Ssam goto out; 154312756Ssam } 154412756Ssam /* 154537741Smckusick * Don't unlink a mounted file. 154612756Ssam */ 154737741Smckusick if (vp->v_flag & VROOT) 154837741Smckusick error = EBUSY; 154912756Ssam out: 155042465Smckusick if (!error) { 155142465Smckusick error = VOP_RMDIR(ndp); 155242465Smckusick } else { 155337741Smckusick VOP_ABORTOP(ndp); 155443344Smckusick if (ndp->ni_dvp == vp) 155543344Smckusick vrele(ndp->ni_dvp); 155643344Smckusick else 155743344Smckusick vput(ndp->ni_dvp); 155842465Smckusick vput(vp); 155942465Smckusick } 156037741Smckusick RETURN (error); 156112756Ssam } 156212756Ssam 156337741Smckusick /* 156437741Smckusick * Read a block of directory entries in a file system independent format 156537741Smckusick */ 156642441Smckusick getdirentries(p, uap, retval) 156742441Smckusick register struct proc *p; 156842441Smckusick register struct args { 156937741Smckusick int fd; 157037741Smckusick char *buf; 157137741Smckusick unsigned count; 157237741Smckusick long *basep; 157342441Smckusick } *uap; 157442441Smckusick int *retval; 157542441Smckusick { 157639592Smckusick register struct vnode *vp; 157716540Ssam struct file *fp; 157837741Smckusick struct uio auio; 157937741Smckusick struct iovec aiov; 158038129Smckusick off_t off; 158140321Smckusick int error, eofflag; 158212756Ssam 158342441Smckusick if (error = getvnode(u.u_ofile, uap->fd, &fp)) 158437741Smckusick RETURN (error); 158537741Smckusick if ((fp->f_flag & FREAD) == 0) 158637741Smckusick RETURN (EBADF); 158739592Smckusick vp = (struct vnode *)fp->f_data; 158839592Smckusick if (vp->v_type != VDIR) 158939592Smckusick RETURN (EINVAL); 159037741Smckusick aiov.iov_base = uap->buf; 159137741Smckusick aiov.iov_len = uap->count; 159237741Smckusick auio.uio_iov = &aiov; 159337741Smckusick auio.uio_iovcnt = 1; 159437741Smckusick auio.uio_rw = UIO_READ; 159537741Smckusick auio.uio_segflg = UIO_USERSPACE; 159637741Smckusick auio.uio_resid = uap->count; 159739592Smckusick VOP_LOCK(vp); 159839592Smckusick auio.uio_offset = off = fp->f_offset; 159940321Smckusick error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag); 160039592Smckusick fp->f_offset = auio.uio_offset; 160139592Smckusick VOP_UNLOCK(vp); 160239592Smckusick if (error) 160337741Smckusick RETURN (error); 160439592Smckusick error = copyout((caddr_t)&off, (caddr_t)uap->basep, sizeof(long)); 160542441Smckusick *retval = uap->count - auio.uio_resid; 160637741Smckusick RETURN (error); 160712756Ssam } 160812756Ssam 160912756Ssam /* 161012756Ssam * mode mask for creation of files 161112756Ssam */ 161242441Smckusick mode_t 161342441Smckusick umask(p, uap, retval) 161442441Smckusick register struct proc *p; 161542441Smckusick struct args { 161642441Smckusick int mask; 161742441Smckusick } *uap; 161842441Smckusick int *retval; 161912756Ssam { 162012756Ssam 162142441Smckusick *retval = u.u_cmask; 162242441Smckusick u.u_cmask = uap->mask & 07777; 162337741Smckusick RETURN (0); 162412756Ssam } 162537741Smckusick 162639566Smarc /* 162739566Smarc * Void all references to file by ripping underlying filesystem 162839566Smarc * away from vnode. 162939566Smarc */ 163042441Smckusick /* ARGSUSED */ 163142441Smckusick revoke(p, uap, retval) 163242441Smckusick register struct proc *p; 163342441Smckusick register struct args { 163439566Smarc char *fname; 163542441Smckusick } *uap; 163642441Smckusick int *retval; 163742441Smckusick { 163842441Smckusick register struct nameidata *ndp = &u.u_nd; 163939566Smarc register struct vnode *vp; 164039566Smarc struct vattr vattr; 164139566Smarc int error; 164239566Smarc 164339566Smarc ndp->ni_nameiop = LOOKUP | FOLLOW; 164439566Smarc ndp->ni_segflg = UIO_USERSPACE; 164539566Smarc ndp->ni_dirp = uap->fname; 164639566Smarc if (error = namei(ndp)) 164739566Smarc RETURN (error); 164839566Smarc vp = ndp->ni_vp; 164939566Smarc if (vp->v_type != VCHR && vp->v_type != VBLK) { 165039566Smarc error = EINVAL; 165139566Smarc goto out; 165239566Smarc } 165342441Smckusick if (error = VOP_GETATTR(vp, &vattr, ndp->ni_cred)) 165439566Smarc goto out; 165542955Smckusick if (ndp->ni_cred->cr_uid != vattr.va_uid && 165642441Smckusick (error = suser(ndp->ni_cred, &u.u_acflag))) 165739566Smarc goto out; 165839805Smckusick if (vp->v_usecount > 1 || (vp->v_flag & VALIASED)) 165939632Smckusick vgoneall(vp); 166039566Smarc out: 166139566Smarc vrele(vp); 166239566Smarc RETURN (error); 166339566Smarc } 166439566Smarc 166538408Smckusick getvnode(ofile, fdes, fpp) 166638408Smckusick struct file *ofile[]; 166737741Smckusick struct file **fpp; 166837741Smckusick int fdes; 166937741Smckusick { 167037741Smckusick struct file *fp; 167137741Smckusick 167238408Smckusick if ((unsigned)fdes >= NOFILE || (fp = ofile[fdes]) == NULL) 167337741Smckusick return (EBADF); 167437741Smckusick if (fp->f_type != DTYPE_VNODE) 167537741Smckusick return (EINVAL); 167637741Smckusick *fpp = fp; 167737741Smckusick return (0); 167837741Smckusick } 1679