123405Smckusick /* 237741Smckusick * Copyright (c) 1989 The Regents of the University of California. 337741Smckusick * All rights reserved. 423405Smckusick * 544459Sbostic * %sccs.include.redist.c% 637741Smckusick * 7*52821Smckusick * @(#)vfs_syscalls.c 7.80 (Berkeley) 03/03/92 823405Smckusick */ 937Sbill 1017101Sbloom #include "param.h" 1117101Sbloom #include "systm.h" 1247540Skarels #include "namei.h" 1345914Smckusick #include "filedesc.h" 1417101Sbloom #include "kernel.h" 1517101Sbloom #include "file.h" 1617101Sbloom #include "stat.h" 1737741Smckusick #include "vnode.h" 1837741Smckusick #include "mount.h" 1917101Sbloom #include "proc.h" 2017101Sbloom #include "uio.h" 2137741Smckusick #include "malloc.h" 2237Sbill 2337741Smckusick /* 2437741Smckusick * Virtual File System System Calls 2537741Smckusick */ 2612756Ssam 279167Ssam /* 2849365Smckusick * Mount system call. 299167Ssam */ 3042441Smckusick /* ARGSUSED */ 3142441Smckusick mount(p, uap, retval) 3245914Smckusick struct proc *p; 3342441Smckusick register struct args { 3437741Smckusick int type; 3537741Smckusick char *dir; 3637741Smckusick int flags; 3737741Smckusick caddr_t data; 3842441Smckusick } *uap; 3942441Smckusick int *retval; 4042441Smckusick { 4139335Smckusick register struct vnode *vp; 4239335Smckusick register struct mount *mp; 4340111Smckusick int error, flag; 4447540Skarels struct nameidata nd; 456254Sroot 4637741Smckusick /* 4737741Smckusick * Must be super user 4837741Smckusick */ 4947540Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 5047540Skarels return (error); 5137741Smckusick /* 5237741Smckusick * Get vnode to be covered 5337741Smckusick */ 5452322Smckusick NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->dir, p); 5552322Smckusick if (error = namei(&nd)) 5647540Skarels return (error); 5752322Smckusick vp = nd.ni_vp; 5841400Smckusick if (uap->flags & MNT_UPDATE) { 5939335Smckusick if ((vp->v_flag & VROOT) == 0) { 6039335Smckusick vput(vp); 6147540Skarels return (EINVAL); 6239335Smckusick } 6339335Smckusick mp = vp->v_mount; 6439335Smckusick /* 6539335Smckusick * We allow going from read-only to read-write, 6639335Smckusick * but not from read-write to read-only. 6739335Smckusick */ 6841400Smckusick if ((mp->mnt_flag & MNT_RDONLY) == 0 && 6941400Smckusick (uap->flags & MNT_RDONLY) != 0) { 7039335Smckusick vput(vp); 7147540Skarels return (EOPNOTSUPP); /* Needs translation */ 7239335Smckusick } 7341400Smckusick flag = mp->mnt_flag; 7441400Smckusick mp->mnt_flag |= MNT_UPDATE; 7539335Smckusick VOP_UNLOCK(vp); 7639335Smckusick goto update; 7739335Smckusick } 7839665Smckusick vinvalbuf(vp, 1); 7939805Smckusick if (vp->v_usecount != 1) { 8037741Smckusick vput(vp); 8147540Skarels return (EBUSY); 8237741Smckusick } 8337741Smckusick if (vp->v_type != VDIR) { 8437741Smckusick vput(vp); 8547540Skarels return (ENOTDIR); 8637741Smckusick } 8739741Smckusick if ((unsigned long)uap->type > MOUNT_MAXTYPE || 8837741Smckusick vfssw[uap->type] == (struct vfsops *)0) { 8937741Smckusick vput(vp); 9047540Skarels return (ENODEV); 9137741Smckusick } 9237741Smckusick 9337741Smckusick /* 9439335Smckusick * Allocate and initialize the file system. 9537741Smckusick */ 9637741Smckusick mp = (struct mount *)malloc((u_long)sizeof(struct mount), 9737741Smckusick M_MOUNT, M_WAITOK); 9841400Smckusick mp->mnt_op = vfssw[uap->type]; 9941400Smckusick mp->mnt_flag = 0; 10041400Smckusick mp->mnt_mounth = NULLVP; 10139335Smckusick if (error = vfs_lock(mp)) { 10239335Smckusick free((caddr_t)mp, M_MOUNT); 10339335Smckusick vput(vp); 10447540Skarels return (error); 10539335Smckusick } 10639335Smckusick if (vp->v_mountedhere != (struct mount *)0) { 10739335Smckusick vfs_unlock(mp); 10839335Smckusick free((caddr_t)mp, M_MOUNT); 10939335Smckusick vput(vp); 11047540Skarels return (EBUSY); 11139335Smckusick } 11239335Smckusick vp->v_mountedhere = mp; 11341400Smckusick mp->mnt_vnodecovered = vp; 11439335Smckusick update: 11539335Smckusick /* 11639335Smckusick * Set the mount level flags. 11739335Smckusick */ 11841400Smckusick if (uap->flags & MNT_RDONLY) 11941400Smckusick mp->mnt_flag |= MNT_RDONLY; 12039335Smckusick else 12141400Smckusick mp->mnt_flag &= ~MNT_RDONLY; 12241400Smckusick if (uap->flags & MNT_NOSUID) 12341400Smckusick mp->mnt_flag |= MNT_NOSUID; 12439335Smckusick else 12541400Smckusick mp->mnt_flag &= ~MNT_NOSUID; 12641400Smckusick if (uap->flags & MNT_NOEXEC) 12741400Smckusick mp->mnt_flag |= MNT_NOEXEC; 12839335Smckusick else 12941400Smckusick mp->mnt_flag &= ~MNT_NOEXEC; 13041400Smckusick if (uap->flags & MNT_NODEV) 13141400Smckusick mp->mnt_flag |= MNT_NODEV; 13239335Smckusick else 13341400Smckusick mp->mnt_flag &= ~MNT_NODEV; 13441400Smckusick if (uap->flags & MNT_SYNCHRONOUS) 13541400Smckusick mp->mnt_flag |= MNT_SYNCHRONOUS; 13639335Smckusick else 13741400Smckusick mp->mnt_flag &= ~MNT_SYNCHRONOUS; 13839335Smckusick /* 13939335Smckusick * Mount the filesystem. 14039335Smckusick */ 14152322Smckusick error = VFS_MOUNT(mp, uap->dir, uap->data, &nd, p); 14241400Smckusick if (mp->mnt_flag & MNT_UPDATE) { 14341400Smckusick mp->mnt_flag &= ~MNT_UPDATE; 14439335Smckusick vrele(vp); 14540111Smckusick if (error) 14641400Smckusick mp->mnt_flag = flag; 14747540Skarels return (error); 14839335Smckusick } 14940110Smckusick /* 15040110Smckusick * Put the new filesystem on the mount list after root. 15140110Smckusick */ 15241400Smckusick mp->mnt_next = rootfs->mnt_next; 15341400Smckusick mp->mnt_prev = rootfs; 15441400Smckusick rootfs->mnt_next = mp; 15541400Smckusick mp->mnt_next->mnt_prev = mp; 15637741Smckusick cache_purge(vp); 15737741Smckusick if (!error) { 15839335Smckusick VOP_UNLOCK(vp); 15937741Smckusick vfs_unlock(mp); 16048026Smckusick error = VFS_START(mp, 0, p); 16137741Smckusick } else { 16237741Smckusick vfs_remove(mp); 16337741Smckusick free((caddr_t)mp, M_MOUNT); 16439335Smckusick vput(vp); 16537741Smckusick } 16647540Skarels return (error); 1676254Sroot } 1686254Sroot 1699167Ssam /* 17037741Smckusick * Unmount system call. 17137741Smckusick * 17237741Smckusick * Note: unmount takes a path to the vnode mounted on as argument, 17337741Smckusick * not special file (as before). 1749167Ssam */ 17542441Smckusick /* ARGSUSED */ 17642441Smckusick unmount(p, uap, retval) 17745914Smckusick struct proc *p; 17842441Smckusick register struct args { 17937741Smckusick char *pathp; 18037741Smckusick int flags; 18142441Smckusick } *uap; 18242441Smckusick int *retval; 18342441Smckusick { 18437741Smckusick register struct vnode *vp; 18539356Smckusick struct mount *mp; 18637741Smckusick int error; 18747540Skarels struct nameidata nd; 1886254Sroot 18937741Smckusick /* 19037741Smckusick * Must be super user 19137741Smckusick */ 19247540Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 19347540Skarels return (error); 19437741Smckusick 19552322Smckusick NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->pathp, p); 19652322Smckusick if (error = namei(&nd)) 19747540Skarels return (error); 19852322Smckusick vp = nd.ni_vp; 19937741Smckusick /* 20037741Smckusick * Must be the root of the filesystem 20137741Smckusick */ 20237741Smckusick if ((vp->v_flag & VROOT) == 0) { 20337741Smckusick vput(vp); 20447540Skarels return (EINVAL); 20537741Smckusick } 20637741Smckusick mp = vp->v_mount; 20737741Smckusick vput(vp); 20848026Smckusick return (dounmount(mp, uap->flags, p)); 20939356Smckusick } 21039356Smckusick 21139356Smckusick /* 21239356Smckusick * Do an unmount. 21339356Smckusick */ 21448026Smckusick dounmount(mp, flags, p) 21539356Smckusick register struct mount *mp; 21639356Smckusick int flags; 21748026Smckusick struct proc *p; 21839356Smckusick { 21939356Smckusick struct vnode *coveredvp; 22039356Smckusick int error; 22139356Smckusick 22241400Smckusick coveredvp = mp->mnt_vnodecovered; 22341298Smckusick if (vfs_busy(mp)) 22441298Smckusick return (EBUSY); 22541400Smckusick mp->mnt_flag |= MNT_UNMOUNT; 22637741Smckusick if (error = vfs_lock(mp)) 22739356Smckusick return (error); 22837741Smckusick 22945738Smckusick vnode_pager_umount(mp); /* release cached vnodes */ 23037741Smckusick cache_purgevfs(mp); /* remove cache entries for this file sys */ 23141676Smckusick if ((error = VFS_SYNC(mp, MNT_WAIT)) == 0 || (flags & MNT_FORCE)) 23248026Smckusick error = VFS_UNMOUNT(mp, flags, p); 23341400Smckusick mp->mnt_flag &= ~MNT_UNMOUNT; 23441298Smckusick vfs_unbusy(mp); 23537741Smckusick if (error) { 23637741Smckusick vfs_unlock(mp); 23737741Smckusick } else { 23837741Smckusick vrele(coveredvp); 23937741Smckusick vfs_remove(mp); 24052287Smckusick if (mp->mnt_mounth != NULL) 24152287Smckusick panic("unmount: dangling vnode"); 24237741Smckusick free((caddr_t)mp, M_MOUNT); 24337741Smckusick } 24439356Smckusick return (error); 2456254Sroot } 2466254Sroot 2479167Ssam /* 24837741Smckusick * Sync system call. 24937741Smckusick * Sync each mounted filesystem. 2509167Ssam */ 25139491Smckusick /* ARGSUSED */ 25242441Smckusick sync(p, uap, retval) 25345914Smckusick struct proc *p; 25447540Skarels void *uap; 25542441Smckusick int *retval; 2566254Sroot { 25737741Smckusick register struct mount *mp; 25841298Smckusick struct mount *omp; 25937741Smckusick 26037741Smckusick mp = rootfs; 26137741Smckusick do { 26240343Smckusick /* 26340343Smckusick * The lock check below is to avoid races with mount 26440343Smckusick * and unmount. 26540343Smckusick */ 26641400Smckusick if ((mp->mnt_flag & (MNT_MLOCK|MNT_RDONLY|MNT_MPBUSY)) == 0 && 26741298Smckusick !vfs_busy(mp)) { 26837741Smckusick VFS_SYNC(mp, MNT_NOWAIT); 26941298Smckusick omp = mp; 27041400Smckusick mp = mp->mnt_next; 27141298Smckusick vfs_unbusy(omp); 27241298Smckusick } else 27341400Smckusick mp = mp->mnt_next; 27437741Smckusick } while (mp != rootfs); 27547688Skarels return (0); 27637741Smckusick } 27737741Smckusick 27837741Smckusick /* 27949365Smckusick * Operate on filesystem quotas. 28041298Smckusick */ 28142441Smckusick /* ARGSUSED */ 28242441Smckusick quotactl(p, uap, retval) 28345914Smckusick struct proc *p; 28442441Smckusick register struct args { 28541298Smckusick char *path; 28641298Smckusick int cmd; 28741298Smckusick int uid; 28841298Smckusick caddr_t arg; 28942441Smckusick } *uap; 29042441Smckusick int *retval; 29142441Smckusick { 29241298Smckusick register struct mount *mp; 29341298Smckusick int error; 29447540Skarels struct nameidata nd; 29541298Smckusick 29652322Smckusick NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 29752322Smckusick if (error = namei(&nd)) 29847540Skarels return (error); 29952322Smckusick mp = nd.ni_vp->v_mount; 30052322Smckusick vrele(nd.ni_vp); 30148026Smckusick return (VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg, p)); 30241298Smckusick } 30341298Smckusick 30441298Smckusick /* 30549365Smckusick * Get filesystem statistics. 30637741Smckusick */ 30742441Smckusick /* ARGSUSED */ 30842441Smckusick statfs(p, uap, retval) 30945914Smckusick struct proc *p; 31042441Smckusick register struct args { 31137741Smckusick char *path; 31237741Smckusick struct statfs *buf; 31342441Smckusick } *uap; 31442441Smckusick int *retval; 31542441Smckusick { 31639464Smckusick register struct mount *mp; 31740343Smckusick register struct statfs *sp; 31837741Smckusick int error; 31947540Skarels struct nameidata nd; 32037741Smckusick 32152322Smckusick NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 32252322Smckusick if (error = namei(&nd)) 32347540Skarels return (error); 32452322Smckusick mp = nd.ni_vp->v_mount; 32541400Smckusick sp = &mp->mnt_stat; 32652322Smckusick vrele(nd.ni_vp); 32748026Smckusick if (error = VFS_STATFS(mp, sp, p)) 32847540Skarels return (error); 32941400Smckusick sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 33047540Skarels return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp))); 33137741Smckusick } 33237741Smckusick 33342441Smckusick /* 33449365Smckusick * Get filesystem statistics. 33542441Smckusick */ 33642441Smckusick /* ARGSUSED */ 33742441Smckusick fstatfs(p, uap, retval) 33845914Smckusick struct proc *p; 33942441Smckusick register struct args { 34037741Smckusick int fd; 34137741Smckusick struct statfs *buf; 34242441Smckusick } *uap; 34342441Smckusick int *retval; 34442441Smckusick { 34537741Smckusick struct file *fp; 34639464Smckusick struct mount *mp; 34740343Smckusick register struct statfs *sp; 34837741Smckusick int error; 34937741Smckusick 35045914Smckusick if (error = getvnode(p->p_fd, uap->fd, &fp)) 35147540Skarels return (error); 35239464Smckusick mp = ((struct vnode *)fp->f_data)->v_mount; 35341400Smckusick sp = &mp->mnt_stat; 35448026Smckusick if (error = VFS_STATFS(mp, sp, p)) 35547540Skarels return (error); 35641400Smckusick sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 35747540Skarels return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp))); 35837741Smckusick } 35937741Smckusick 36037741Smckusick /* 36149365Smckusick * Get statistics on all filesystems. 36238270Smckusick */ 36342441Smckusick getfsstat(p, uap, retval) 36445914Smckusick struct proc *p; 36542441Smckusick register struct args { 36638270Smckusick struct statfs *buf; 36738270Smckusick long bufsize; 36840343Smckusick int flags; 36942441Smckusick } *uap; 37042441Smckusick int *retval; 37142441Smckusick { 37238270Smckusick register struct mount *mp; 37340343Smckusick register struct statfs *sp; 37439606Smckusick caddr_t sfsp; 37538270Smckusick long count, maxcount, error; 37638270Smckusick 37738270Smckusick maxcount = uap->bufsize / sizeof(struct statfs); 37839606Smckusick sfsp = (caddr_t)uap->buf; 37938270Smckusick mp = rootfs; 38038270Smckusick count = 0; 38138270Smckusick do { 38241400Smckusick if (sfsp && count < maxcount && 38341400Smckusick ((mp->mnt_flag & MNT_MLOCK) == 0)) { 38441400Smckusick sp = &mp->mnt_stat; 38540343Smckusick /* 38640343Smckusick * If MNT_NOWAIT is specified, do not refresh the 38740343Smckusick * fsstat cache. MNT_WAIT overrides MNT_NOWAIT. 38840343Smckusick */ 38940343Smckusick if (((uap->flags & MNT_NOWAIT) == 0 || 39040343Smckusick (uap->flags & MNT_WAIT)) && 39148026Smckusick (error = VFS_STATFS(mp, sp, p))) { 39241400Smckusick mp = mp->mnt_prev; 39339607Smckusick continue; 39439607Smckusick } 39541400Smckusick sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 39640343Smckusick if (error = copyout((caddr_t)sp, sfsp, sizeof(*sp))) 39747540Skarels return (error); 39840343Smckusick sfsp += sizeof(*sp); 39938270Smckusick } 40039606Smckusick count++; 40141400Smckusick mp = mp->mnt_prev; 40238270Smckusick } while (mp != rootfs); 40338270Smckusick if (sfsp && count > maxcount) 40442441Smckusick *retval = maxcount; 40538270Smckusick else 40642441Smckusick *retval = count; 40747540Skarels return (0); 40838270Smckusick } 40938270Smckusick 41038270Smckusick /* 41138259Smckusick * Change current working directory to a given file descriptor. 41238259Smckusick */ 41342441Smckusick /* ARGSUSED */ 41442441Smckusick fchdir(p, uap, retval) 41545914Smckusick struct proc *p; 41642441Smckusick struct args { 41742441Smckusick int fd; 41842441Smckusick } *uap; 41942441Smckusick int *retval; 42038259Smckusick { 42145914Smckusick register struct filedesc *fdp = p->p_fd; 42238259Smckusick register struct vnode *vp; 42338259Smckusick struct file *fp; 42438259Smckusick int error; 42538259Smckusick 42645914Smckusick if (error = getvnode(fdp, uap->fd, &fp)) 42747540Skarels return (error); 42838259Smckusick vp = (struct vnode *)fp->f_data; 42938259Smckusick VOP_LOCK(vp); 43038259Smckusick if (vp->v_type != VDIR) 43138259Smckusick error = ENOTDIR; 43238259Smckusick else 43348026Smckusick error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); 43438259Smckusick VOP_UNLOCK(vp); 43539860Smckusick if (error) 43647540Skarels return (error); 43739860Smckusick VREF(vp); 43845914Smckusick vrele(fdp->fd_cdir); 43945914Smckusick fdp->fd_cdir = vp; 44047540Skarels return (0); 44138259Smckusick } 44238259Smckusick 44338259Smckusick /* 44437741Smckusick * Change current working directory (``.''). 44537741Smckusick */ 44642441Smckusick /* ARGSUSED */ 44742441Smckusick chdir(p, uap, retval) 44845914Smckusick struct proc *p; 44942441Smckusick struct args { 45042441Smckusick char *fname; 45142441Smckusick } *uap; 45242441Smckusick int *retval; 45337741Smckusick { 45445914Smckusick register struct filedesc *fdp = p->p_fd; 45537741Smckusick int error; 45647540Skarels struct nameidata nd; 4576254Sroot 45852322Smckusick NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 45952781Sralph if (error = chdirec(&nd, p)) 46047540Skarels return (error); 46145914Smckusick vrele(fdp->fd_cdir); 46252322Smckusick fdp->fd_cdir = nd.ni_vp; 46347540Skarels return (0); 46437741Smckusick } 4656254Sroot 46637741Smckusick /* 46737741Smckusick * Change notion of root (``/'') directory. 46837741Smckusick */ 46942441Smckusick /* ARGSUSED */ 47042441Smckusick chroot(p, uap, retval) 47145914Smckusick struct proc *p; 47242441Smckusick struct args { 47342441Smckusick char *fname; 47442441Smckusick } *uap; 47542441Smckusick int *retval; 47637741Smckusick { 47745914Smckusick register struct filedesc *fdp = p->p_fd; 47837741Smckusick int error; 47947540Skarels struct nameidata nd; 48037741Smckusick 48147540Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 48247540Skarels return (error); 48352322Smckusick NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 48452781Sralph if (error = chdirec(&nd, p)) 48547540Skarels return (error); 48645914Smckusick if (fdp->fd_rdir != NULL) 48745914Smckusick vrele(fdp->fd_rdir); 48852322Smckusick fdp->fd_rdir = nd.ni_vp; 48947540Skarels return (0); 4906254Sroot } 4916254Sroot 49237Sbill /* 49337741Smckusick * Common routine for chroot and chdir. 49437741Smckusick */ 49547540Skarels chdirec(ndp, p) 49652322Smckusick register struct nameidata *ndp; 49747540Skarels struct proc *p; 49837741Smckusick { 49937741Smckusick struct vnode *vp; 50037741Smckusick int error; 50137741Smckusick 50252322Smckusick if (error = namei(ndp)) 50337741Smckusick return (error); 50437741Smckusick vp = ndp->ni_vp; 50537741Smckusick if (vp->v_type != VDIR) 50637741Smckusick error = ENOTDIR; 50737741Smckusick else 50848026Smckusick error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); 50937741Smckusick VOP_UNLOCK(vp); 51037741Smckusick if (error) 51137741Smckusick vrele(vp); 51237741Smckusick return (error); 51337741Smckusick } 51437741Smckusick 51537741Smckusick /* 5166254Sroot * Open system call. 51742441Smckusick * Check permissions, allocate an open file structure, 51842441Smckusick * and call the device open routine if any. 5196254Sroot */ 52042441Smckusick open(p, uap, retval) 52145914Smckusick struct proc *p; 52242441Smckusick register struct args { 5236254Sroot char *fname; 5247701Ssam int mode; 52512756Ssam int crtmode; 52642441Smckusick } *uap; 52742441Smckusick int *retval; 5286254Sroot { 52945914Smckusick register struct filedesc *fdp = p->p_fd; 53042441Smckusick register struct file *fp; 53150111Smckusick register struct vnode *vp; 53237741Smckusick int fmode, cmode; 53337741Smckusick struct file *nfp; 53449945Smckusick int type, indx, error; 53549945Smckusick struct flock lf; 53647540Skarels struct nameidata nd; 53737741Smckusick extern struct fileops vnops; 5386254Sroot 53945914Smckusick if (error = falloc(p, &nfp, &indx)) 54047540Skarels return (error); 54137741Smckusick fp = nfp; 54246553Skarels fmode = FFLAGS(uap->mode); 54345914Smckusick cmode = ((uap->crtmode &~ fdp->fd_cmask) & 07777) &~ S_ISVTX; 54452322Smckusick NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->fname, p); 54545202Smckusick p->p_dupfd = -indx - 1; /* XXX check for fdopen */ 54652322Smckusick if (error = vn_open(&nd, fmode, cmode)) { 54749980Smckusick ffree(fp); 54843405Smckusick if (error == ENODEV && /* XXX from fdopen */ 54945202Smckusick p->p_dupfd >= 0 && 55045914Smckusick (error = dupfdopen(fdp, indx, p->p_dupfd, fmode)) == 0) { 55142441Smckusick *retval = indx; 55247540Skarels return (0); 55342441Smckusick } 55440884Smckusick if (error == ERESTART) 55540884Smckusick error = EINTR; 55647688Skarels fdp->fd_ofiles[indx] = NULL; 55747540Skarels return (error); 55812756Ssam } 55952322Smckusick vp = nd.ni_vp; 56049949Smckusick fp->f_flag = fmode & FMASK; 56149945Smckusick if (fmode & (O_EXLOCK | O_SHLOCK)) { 56249945Smckusick lf.l_whence = SEEK_SET; 56349945Smckusick lf.l_start = 0; 56449945Smckusick lf.l_len = 0; 56549945Smckusick if (fmode & O_EXLOCK) 56649945Smckusick lf.l_type = F_WRLCK; 56749945Smckusick else 56849945Smckusick lf.l_type = F_RDLCK; 56949945Smckusick type = F_FLOCK; 57049945Smckusick if ((fmode & FNONBLOCK) == 0) 57149945Smckusick type |= F_WAIT; 57250111Smckusick if (error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) { 57350111Smckusick VOP_UNLOCK(vp); 57450111Smckusick (void) vn_close(vp, fp->f_flag, fp->f_cred, p); 57549980Smckusick ffree(fp); 57649945Smckusick fdp->fd_ofiles[indx] = NULL; 57749945Smckusick return (error); 57849945Smckusick } 57949949Smckusick fp->f_flag |= FHASLOCK; 58049945Smckusick } 58150111Smckusick VOP_UNLOCK(vp); 58237741Smckusick fp->f_type = DTYPE_VNODE; 58337741Smckusick fp->f_ops = &vnops; 58450111Smckusick fp->f_data = (caddr_t)vp; 58542441Smckusick *retval = indx; 58647540Skarels return (0); 5876254Sroot } 5886254Sroot 58942955Smckusick #ifdef COMPAT_43 5906254Sroot /* 59142441Smckusick * Creat system call. 5926254Sroot */ 59342955Smckusick ocreat(p, uap, retval) 59442441Smckusick struct proc *p; 59542441Smckusick register struct args { 59642441Smckusick char *fname; 59742441Smckusick int fmode; 59842441Smckusick } *uap; 59942441Smckusick int *retval; 6006254Sroot { 60142441Smckusick struct args { 6026254Sroot char *fname; 60342441Smckusick int mode; 60442441Smckusick int crtmode; 60542441Smckusick } openuap; 60642441Smckusick 60742441Smckusick openuap.fname = uap->fname; 60842441Smckusick openuap.crtmode = uap->fmode; 60942441Smckusick openuap.mode = O_WRONLY | O_CREAT | O_TRUNC; 61047540Skarels return (open(p, &openuap, retval)); 61142441Smckusick } 61242955Smckusick #endif /* COMPAT_43 */ 61342441Smckusick 61442441Smckusick /* 61549365Smckusick * Mknod system call. 61642441Smckusick */ 61742441Smckusick /* ARGSUSED */ 61842441Smckusick mknod(p, uap, retval) 61945914Smckusick struct proc *p; 62042441Smckusick register struct args { 62142441Smckusick char *fname; 6226254Sroot int fmode; 6236254Sroot int dev; 62442441Smckusick } *uap; 62542441Smckusick int *retval; 62642441Smckusick { 62737741Smckusick register struct vnode *vp; 62837741Smckusick struct vattr vattr; 62937741Smckusick int error; 63047540Skarels struct nameidata nd; 6316254Sroot 63247540Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 63347540Skarels return (error); 63452322Smckusick NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->fname, p); 63552322Smckusick if (error = namei(&nd)) 63647540Skarels return (error); 63752322Smckusick vp = nd.ni_vp; 63837741Smckusick if (vp != NULL) { 63937741Smckusick error = EEXIST; 64012756Ssam goto out; 6416254Sroot } 64241362Smckusick VATTR_NULL(&vattr); 64340635Smckusick switch (uap->fmode & S_IFMT) { 64412756Ssam 64540635Smckusick case S_IFMT: /* used by badsect to flag bad sectors */ 64637741Smckusick vattr.va_type = VBAD; 64737741Smckusick break; 64840635Smckusick case S_IFCHR: 64937741Smckusick vattr.va_type = VCHR; 65037741Smckusick break; 65140635Smckusick case S_IFBLK: 65237741Smckusick vattr.va_type = VBLK; 65337741Smckusick break; 65437741Smckusick default: 65537741Smckusick error = EINVAL; 65637741Smckusick goto out; 6576254Sroot } 65845914Smckusick vattr.va_mode = (uap->fmode & 07777) &~ p->p_fd->fd_cmask; 65937741Smckusick vattr.va_rdev = uap->dev; 6606254Sroot out: 66142465Smckusick if (!error) { 66252322Smckusick LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 66352322Smckusick error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 66442465Smckusick } else { 66552322Smckusick VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 66652322Smckusick if (nd.ni_dvp == vp) 66752322Smckusick vrele(nd.ni_dvp); 66843344Smckusick else 66952322Smckusick vput(nd.ni_dvp); 67042465Smckusick if (vp) 67142465Smckusick vrele(vp); 67242465Smckusick } 67347540Skarels return (error); 6746254Sroot } 6756254Sroot 6766254Sroot /* 67749365Smckusick * Mkfifo system call. 67840285Smckusick */ 67942441Smckusick /* ARGSUSED */ 68042441Smckusick mkfifo(p, uap, retval) 68145914Smckusick struct proc *p; 68242441Smckusick register struct args { 68340285Smckusick char *fname; 68440285Smckusick int fmode; 68542441Smckusick } *uap; 68642441Smckusick int *retval; 68742441Smckusick { 68840285Smckusick struct vattr vattr; 68940285Smckusick int error; 69047540Skarels struct nameidata nd; 69140285Smckusick 69240285Smckusick #ifndef FIFO 69347540Skarels return (EOPNOTSUPP); 69440285Smckusick #else 69552322Smckusick NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->fname, p); 69652322Smckusick if (error = namei(&nd)) 69747540Skarels return (error); 69852322Smckusick if (nd.ni_vp != NULL) { 69952322Smckusick VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 70052322Smckusick if (nd.ni_dvp == nd.ni_vp) 70152322Smckusick vrele(nd.ni_dvp); 70243344Smckusick else 70352322Smckusick vput(nd.ni_dvp); 70452322Smckusick vrele(nd.ni_vp); 70547540Skarels return (EEXIST); 70640285Smckusick } 70745785Sbostic VATTR_NULL(&vattr); 70845785Sbostic vattr.va_type = VFIFO; 70945914Smckusick vattr.va_mode = (uap->fmode & 07777) &~ p->p_fd->fd_cmask; 71052322Smckusick LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 71152322Smckusick return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr)); 71240285Smckusick #endif /* FIFO */ 71340285Smckusick } 71440285Smckusick 71540285Smckusick /* 71649365Smckusick * Link system call. 7176254Sroot */ 71842441Smckusick /* ARGSUSED */ 71942441Smckusick link(p, uap, retval) 72045914Smckusick struct proc *p; 72142441Smckusick register struct args { 7226254Sroot char *target; 7236254Sroot char *linkname; 72442441Smckusick } *uap; 72542441Smckusick int *retval; 72642441Smckusick { 72737741Smckusick register struct vnode *vp, *xp; 72837741Smckusick int error; 72947540Skarels struct nameidata nd; 7306254Sroot 73152322Smckusick NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->target, p); 73252322Smckusick if (error = namei(&nd)) 73347540Skarels return (error); 73452322Smckusick vp = nd.ni_vp; 73537741Smckusick if (vp->v_type == VDIR && 73647540Skarels (error = suser(p->p_ucred, &p->p_acflag))) 73737741Smckusick goto out1; 73852322Smckusick nd.ni_cnd.cn_nameiop = CREATE; 73952322Smckusick nd.ni_cnd.cn_flags = LOCKPARENT; 74052322Smckusick nd.ni_dirp = (caddr_t)uap->linkname; 74152322Smckusick if (error = namei(&nd)) 74237741Smckusick goto out1; 74352322Smckusick xp = nd.ni_vp; 7446254Sroot if (xp != NULL) { 74537741Smckusick error = EEXIST; 7466254Sroot goto out; 7476254Sroot } 74852322Smckusick xp = nd.ni_dvp; 74937741Smckusick if (vp->v_mount != xp->v_mount) 75037741Smckusick error = EXDEV; 7516254Sroot out: 75242465Smckusick if (!error) { 75352192Smckusick LEASE_CHECK(xp, p, p->p_ucred, LEASE_WRITE); 75452192Smckusick LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 755*52821Smckusick error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd); 75642465Smckusick } else { 75752322Smckusick VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 75852322Smckusick if (nd.ni_dvp == nd.ni_vp) 75952322Smckusick vrele(nd.ni_dvp); 76043344Smckusick else 76152322Smckusick vput(nd.ni_dvp); 76252322Smckusick if (nd.ni_vp) 76352322Smckusick vrele(nd.ni_vp); 76442465Smckusick } 76537741Smckusick out1: 76637741Smckusick vrele(vp); 76747540Skarels return (error); 7686254Sroot } 7696254Sroot 7706254Sroot /* 77149365Smckusick * Make a symbolic link. 7726254Sroot */ 77342441Smckusick /* ARGSUSED */ 77442441Smckusick symlink(p, uap, retval) 77545914Smckusick struct proc *p; 77642441Smckusick register struct args { 7776254Sroot char *target; 7786254Sroot char *linkname; 77942441Smckusick } *uap; 78042441Smckusick int *retval; 78142441Smckusick { 78237741Smckusick struct vattr vattr; 78337741Smckusick char *target; 78437741Smckusick int error; 78547540Skarels struct nameidata nd; 7866254Sroot 78737741Smckusick MALLOC(target, char *, MAXPATHLEN, M_NAMEI, M_WAITOK); 78837741Smckusick if (error = copyinstr(uap->target, target, MAXPATHLEN, (u_int *)0)) 78942465Smckusick goto out; 79052322Smckusick NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->linkname, p); 79152322Smckusick if (error = namei(&nd)) 79242465Smckusick goto out; 79352322Smckusick if (nd.ni_vp) { 79452322Smckusick VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 79552322Smckusick if (nd.ni_dvp == nd.ni_vp) 79652322Smckusick vrele(nd.ni_dvp); 79743344Smckusick else 79852322Smckusick vput(nd.ni_dvp); 79952322Smckusick vrele(nd.ni_vp); 80037741Smckusick error = EEXIST; 80137741Smckusick goto out; 8026254Sroot } 80341362Smckusick VATTR_NULL(&vattr); 80445914Smckusick vattr.va_mode = 0777 &~ p->p_fd->fd_cmask; 80552322Smckusick LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 80652322Smckusick error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, target); 80737741Smckusick out: 80837741Smckusick FREE(target, M_NAMEI); 80947540Skarels return (error); 8106254Sroot } 8116254Sroot 8126254Sroot /* 81349365Smckusick * Delete a name from the filesystem. 8146254Sroot */ 81542441Smckusick /* ARGSUSED */ 81642441Smckusick unlink(p, uap, retval) 81745914Smckusick struct proc *p; 81842441Smckusick struct args { 81952322Smckusick char *name; 82042441Smckusick } *uap; 82142441Smckusick int *retval; 8226254Sroot { 82337741Smckusick register struct vnode *vp; 82437741Smckusick int error; 82547540Skarels struct nameidata nd; 8266254Sroot 82752322Smckusick NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, uap->name, p); 82852322Smckusick if (error = namei(&nd)) 82947540Skarels return (error); 83052322Smckusick vp = nd.ni_vp; 83137741Smckusick if (vp->v_type == VDIR && 83247540Skarels (error = suser(p->p_ucred, &p->p_acflag))) 8336254Sroot goto out; 8346254Sroot /* 83549365Smckusick * The root of a mounted filesystem cannot be deleted. 8366254Sroot */ 83737741Smckusick if (vp->v_flag & VROOT) { 83837741Smckusick error = EBUSY; 8396254Sroot goto out; 8406254Sroot } 84145738Smckusick (void) vnode_pager_uncache(vp); 8426254Sroot out: 84342465Smckusick if (!error) { 84452322Smckusick LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 84552192Smckusick LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 84652322Smckusick error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 84742465Smckusick } else { 84852322Smckusick VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 84952322Smckusick if (nd.ni_dvp == vp) 85052322Smckusick vrele(nd.ni_dvp); 85143344Smckusick else 85252322Smckusick vput(nd.ni_dvp); 85342465Smckusick vput(vp); 85442465Smckusick } 85547540Skarels return (error); 8566254Sroot } 8576254Sroot 8586254Sroot /* 85949365Smckusick * Seek system call. 8606254Sroot */ 86142441Smckusick lseek(p, uap, retval) 86245914Smckusick struct proc *p; 86342441Smckusick register struct args { 86437741Smckusick int fdes; 8656254Sroot off_t off; 8666254Sroot int sbase; 86742441Smckusick } *uap; 86842441Smckusick off_t *retval; 86942441Smckusick { 87047540Skarels struct ucred *cred = p->p_ucred; 87145914Smckusick register struct filedesc *fdp = p->p_fd; 87242441Smckusick register struct file *fp; 87337741Smckusick struct vattr vattr; 87437741Smckusick int error; 8756254Sroot 87647540Skarels if ((unsigned)uap->fdes >= fdp->fd_nfiles || 87747688Skarels (fp = fdp->fd_ofiles[uap->fdes]) == NULL) 87847540Skarels return (EBADF); 87937741Smckusick if (fp->f_type != DTYPE_VNODE) 88047540Skarels return (ESPIPE); 88113878Ssam switch (uap->sbase) { 88213878Ssam 88313878Ssam case L_INCR: 88413878Ssam fp->f_offset += uap->off; 88513878Ssam break; 88613878Ssam 88713878Ssam case L_XTND: 88837741Smckusick if (error = VOP_GETATTR((struct vnode *)fp->f_data, 88948026Smckusick &vattr, cred, p)) 89047540Skarels return (error); 89137741Smckusick fp->f_offset = uap->off + vattr.va_size; 89213878Ssam break; 89313878Ssam 89413878Ssam case L_SET: 89513878Ssam fp->f_offset = uap->off; 89613878Ssam break; 89713878Ssam 89813878Ssam default: 89947540Skarels return (EINVAL); 90013878Ssam } 90142441Smckusick *retval = fp->f_offset; 90247540Skarels return (0); 9036254Sroot } 9046254Sroot 9056254Sroot /* 90649365Smckusick * Check access permissions. 9076254Sroot */ 90842441Smckusick /* ARGSUSED */ 90942441Smckusick saccess(p, uap, retval) 91045914Smckusick struct proc *p; 91142441Smckusick register struct args { 9126254Sroot char *fname; 9136254Sroot int fmode; 91442441Smckusick } *uap; 91542441Smckusick int *retval; 91642441Smckusick { 91747540Skarels register struct ucred *cred = p->p_ucred; 91837741Smckusick register struct vnode *vp; 91937741Smckusick int error, mode, svuid, svgid; 92047540Skarels struct nameidata nd; 9216254Sroot 92242441Smckusick svuid = cred->cr_uid; 92342441Smckusick svgid = cred->cr_groups[0]; 92447540Skarels cred->cr_uid = p->p_cred->p_ruid; 92547540Skarels cred->cr_groups[0] = p->p_cred->p_rgid; 92652322Smckusick NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 92752322Smckusick if (error = namei(&nd)) 92837741Smckusick goto out1; 92952322Smckusick vp = nd.ni_vp; 93037741Smckusick /* 93137741Smckusick * fmode == 0 means only check for exist 93237741Smckusick */ 93337741Smckusick if (uap->fmode) { 93437741Smckusick mode = 0; 93537741Smckusick if (uap->fmode & R_OK) 93637741Smckusick mode |= VREAD; 93737741Smckusick if (uap->fmode & W_OK) 93837741Smckusick mode |= VWRITE; 93937741Smckusick if (uap->fmode & X_OK) 94037741Smckusick mode |= VEXEC; 94139543Smckusick if ((mode & VWRITE) == 0 || (error = vn_writechk(vp)) == 0) 94248026Smckusick error = VOP_ACCESS(vp, mode, cred, p); 9436254Sroot } 94437741Smckusick vput(vp); 94537741Smckusick out1: 94642441Smckusick cred->cr_uid = svuid; 94742441Smckusick cred->cr_groups[0] = svgid; 94847540Skarels return (error); 9496254Sroot } 9506254Sroot 9516254Sroot /* 95249365Smckusick * Stat system call. 95349365Smckusick * This version follows links. 95437Sbill */ 95542441Smckusick /* ARGSUSED */ 95642441Smckusick stat(p, uap, retval) 95745914Smckusick struct proc *p; 95842441Smckusick register struct args { 95942441Smckusick char *fname; 96042441Smckusick struct stat *ub; 96142441Smckusick } *uap; 96242441Smckusick int *retval; 96337Sbill { 96442441Smckusick struct stat sb; 96542441Smckusick int error; 96647540Skarels struct nameidata nd; 96737Sbill 96852322Smckusick NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 96952322Smckusick if (error = namei(&nd)) 97047540Skarels return (error); 97152322Smckusick error = vn_stat(nd.ni_vp, &sb, p); 97252322Smckusick vput(nd.ni_vp); 97342441Smckusick if (error) 97447540Skarels return (error); 97542441Smckusick error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb)); 97647540Skarels return (error); 97737Sbill } 97837Sbill 97937Sbill /* 98049365Smckusick * Lstat system call. 98149365Smckusick * This version does not follow links. 9825992Swnj */ 98342441Smckusick /* ARGSUSED */ 98442441Smckusick lstat(p, uap, retval) 98545914Smckusick struct proc *p; 98642441Smckusick register struct args { 9875992Swnj char *fname; 98812756Ssam struct stat *ub; 98942441Smckusick } *uap; 99042441Smckusick int *retval; 99142441Smckusick { 99212756Ssam struct stat sb; 99337741Smckusick int error; 99447540Skarels struct nameidata nd; 9955992Swnj 99652322Smckusick NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 99752322Smckusick if (error = namei(&nd)) 99847540Skarels return (error); 99952322Smckusick error = vn_stat(nd.ni_vp, &sb, p); 100052322Smckusick vput(nd.ni_vp); 100137741Smckusick if (error) 100247540Skarels return (error); 100337741Smckusick error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb)); 100447540Skarels return (error); 10055992Swnj } 10065992Swnj 10075992Swnj /* 100849365Smckusick * Return target name of a symbolic link. 100937Sbill */ 101042441Smckusick /* ARGSUSED */ 101142441Smckusick readlink(p, uap, retval) 101245914Smckusick struct proc *p; 101342441Smckusick register struct args { 10145992Swnj char *name; 10155992Swnj char *buf; 10165992Swnj int count; 101742441Smckusick } *uap; 101842441Smckusick int *retval; 101942441Smckusick { 102037741Smckusick register struct vnode *vp; 102137741Smckusick struct iovec aiov; 102237741Smckusick struct uio auio; 102337741Smckusick int error; 102447540Skarels struct nameidata nd; 10255992Swnj 102652322Smckusick NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->name, p); 102752322Smckusick if (error = namei(&nd)) 102847540Skarels return (error); 102952322Smckusick vp = nd.ni_vp; 103037741Smckusick if (vp->v_type != VLNK) { 103137741Smckusick error = EINVAL; 10325992Swnj goto out; 10335992Swnj } 103437741Smckusick aiov.iov_base = uap->buf; 103537741Smckusick aiov.iov_len = uap->count; 103637741Smckusick auio.uio_iov = &aiov; 103737741Smckusick auio.uio_iovcnt = 1; 103837741Smckusick auio.uio_offset = 0; 103937741Smckusick auio.uio_rw = UIO_READ; 104037741Smckusick auio.uio_segflg = UIO_USERSPACE; 104148026Smckusick auio.uio_procp = p; 104237741Smckusick auio.uio_resid = uap->count; 104347540Skarels error = VOP_READLINK(vp, &auio, p->p_ucred); 10445992Swnj out: 104537741Smckusick vput(vp); 104642441Smckusick *retval = uap->count - auio.uio_resid; 104747540Skarels return (error); 10485992Swnj } 10495992Swnj 10509167Ssam /* 105138259Smckusick * Change flags of a file given path name. 105238259Smckusick */ 105342441Smckusick /* ARGSUSED */ 105442441Smckusick chflags(p, uap, retval) 105545914Smckusick struct proc *p; 105642441Smckusick register struct args { 105738259Smckusick char *fname; 105838259Smckusick int flags; 105942441Smckusick } *uap; 106042441Smckusick int *retval; 106142441Smckusick { 106238259Smckusick register struct vnode *vp; 106338259Smckusick struct vattr vattr; 106438259Smckusick int error; 106547540Skarels struct nameidata nd; 106638259Smckusick 106752322Smckusick NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 106852322Smckusick if (error = namei(&nd)) 106947540Skarels return (error); 107052322Smckusick vp = nd.ni_vp; 107141400Smckusick if (vp->v_mount->mnt_flag & MNT_RDONLY) { 107238259Smckusick error = EROFS; 107338259Smckusick goto out; 107438259Smckusick } 107545785Sbostic VATTR_NULL(&vattr); 107645785Sbostic vattr.va_flags = uap->flags; 107752192Smckusick LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 107848026Smckusick error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 107938259Smckusick out: 108038259Smckusick vput(vp); 108147540Skarels return (error); 108238259Smckusick } 108338259Smckusick 108438259Smckusick /* 108538259Smckusick * Change flags of a file given a file descriptor. 108638259Smckusick */ 108742441Smckusick /* ARGSUSED */ 108842441Smckusick fchflags(p, uap, retval) 108945914Smckusick struct proc *p; 109042441Smckusick register struct args { 109138259Smckusick int fd; 109238259Smckusick int flags; 109342441Smckusick } *uap; 109442441Smckusick int *retval; 109542441Smckusick { 109638259Smckusick struct vattr vattr; 109738259Smckusick struct vnode *vp; 109838259Smckusick struct file *fp; 109938259Smckusick int error; 110038259Smckusick 110145914Smckusick if (error = getvnode(p->p_fd, uap->fd, &fp)) 110247540Skarels return (error); 110338259Smckusick vp = (struct vnode *)fp->f_data; 110438259Smckusick VOP_LOCK(vp); 110541400Smckusick if (vp->v_mount->mnt_flag & MNT_RDONLY) { 110638259Smckusick error = EROFS; 110738259Smckusick goto out; 110838259Smckusick } 110945785Sbostic VATTR_NULL(&vattr); 111045785Sbostic vattr.va_flags = uap->flags; 111152192Smckusick LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 111248026Smckusick error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 111338259Smckusick out: 111438259Smckusick VOP_UNLOCK(vp); 111547540Skarels return (error); 111638259Smckusick } 111738259Smckusick 111838259Smckusick /* 11199167Ssam * Change mode of a file given path name. 11209167Ssam */ 112142441Smckusick /* ARGSUSED */ 112242441Smckusick chmod(p, uap, retval) 112345914Smckusick struct proc *p; 112442441Smckusick register struct args { 11256254Sroot char *fname; 11266254Sroot int fmode; 112742441Smckusick } *uap; 112842441Smckusick int *retval; 112942441Smckusick { 113037741Smckusick register struct vnode *vp; 113137741Smckusick struct vattr vattr; 113237741Smckusick int error; 113347540Skarels struct nameidata nd; 11345992Swnj 113552322Smckusick NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 113652322Smckusick if (error = namei(&nd)) 113747540Skarels return (error); 113852322Smckusick vp = nd.ni_vp; 113941400Smckusick if (vp->v_mount->mnt_flag & MNT_RDONLY) { 114037741Smckusick error = EROFS; 114137741Smckusick goto out; 114237741Smckusick } 114345785Sbostic VATTR_NULL(&vattr); 114445785Sbostic vattr.va_mode = uap->fmode & 07777; 114552192Smckusick LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 114648026Smckusick error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 114737741Smckusick out: 114837741Smckusick vput(vp); 114947540Skarels return (error); 11507701Ssam } 11517439Sroot 11529167Ssam /* 11539167Ssam * Change mode of a file given a file descriptor. 11549167Ssam */ 115542441Smckusick /* ARGSUSED */ 115642441Smckusick fchmod(p, uap, retval) 115745914Smckusick struct proc *p; 115842441Smckusick register struct args { 11597701Ssam int fd; 11607701Ssam int fmode; 116142441Smckusick } *uap; 116242441Smckusick int *retval; 116342441Smckusick { 116437741Smckusick struct vattr vattr; 116537741Smckusick struct vnode *vp; 116637741Smckusick struct file *fp; 116737741Smckusick int error; 11687701Ssam 116945914Smckusick if (error = getvnode(p->p_fd, uap->fd, &fp)) 117047540Skarels return (error); 117137741Smckusick vp = (struct vnode *)fp->f_data; 117237741Smckusick VOP_LOCK(vp); 117341400Smckusick if (vp->v_mount->mnt_flag & MNT_RDONLY) { 117437741Smckusick error = EROFS; 117537741Smckusick goto out; 11767439Sroot } 117745785Sbostic VATTR_NULL(&vattr); 117845785Sbostic vattr.va_mode = uap->fmode & 07777; 117952192Smckusick LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 118048026Smckusick error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 118137741Smckusick out: 118237741Smckusick VOP_UNLOCK(vp); 118347540Skarels return (error); 11845992Swnj } 11855992Swnj 11869167Ssam /* 11879167Ssam * Set ownership given a path name. 11889167Ssam */ 118942441Smckusick /* ARGSUSED */ 119042441Smckusick chown(p, uap, retval) 119145914Smckusick struct proc *p; 119242441Smckusick register struct args { 11936254Sroot char *fname; 11946254Sroot int uid; 11956254Sroot int gid; 119642441Smckusick } *uap; 119742441Smckusick int *retval; 119842441Smckusick { 119937741Smckusick register struct vnode *vp; 120037741Smckusick struct vattr vattr; 120137741Smckusick int error; 120247540Skarels struct nameidata nd; 120337Sbill 120452322Smckusick NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 120552322Smckusick if (error = namei(&nd)) 120647540Skarels return (error); 120752322Smckusick vp = nd.ni_vp; 120841400Smckusick if (vp->v_mount->mnt_flag & MNT_RDONLY) { 120937741Smckusick error = EROFS; 121037741Smckusick goto out; 121137741Smckusick } 121245785Sbostic VATTR_NULL(&vattr); 121345785Sbostic vattr.va_uid = uap->uid; 121445785Sbostic vattr.va_gid = uap->gid; 121552192Smckusick LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 121648026Smckusick error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 121737741Smckusick out: 121837741Smckusick vput(vp); 121947540Skarels return (error); 12207701Ssam } 12217439Sroot 12229167Ssam /* 12239167Ssam * Set ownership given a file descriptor. 12249167Ssam */ 122542441Smckusick /* ARGSUSED */ 122642441Smckusick fchown(p, uap, retval) 122745914Smckusick struct proc *p; 122842441Smckusick register struct args { 12297701Ssam int fd; 12307701Ssam int uid; 12317701Ssam int gid; 123242441Smckusick } *uap; 123342441Smckusick int *retval; 123442441Smckusick { 123537741Smckusick struct vattr vattr; 123637741Smckusick struct vnode *vp; 123737741Smckusick struct file *fp; 123837741Smckusick int error; 12397701Ssam 124045914Smckusick if (error = getvnode(p->p_fd, uap->fd, &fp)) 124147540Skarels return (error); 124237741Smckusick vp = (struct vnode *)fp->f_data; 124337741Smckusick VOP_LOCK(vp); 124441400Smckusick if (vp->v_mount->mnt_flag & MNT_RDONLY) { 124537741Smckusick error = EROFS; 124637741Smckusick goto out; 124737741Smckusick } 124845785Sbostic VATTR_NULL(&vattr); 124945785Sbostic vattr.va_uid = uap->uid; 125045785Sbostic vattr.va_gid = uap->gid; 125152192Smckusick LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 125248026Smckusick error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 125337741Smckusick out: 125437741Smckusick VOP_UNLOCK(vp); 125547540Skarels return (error); 12567701Ssam } 12577701Ssam 125842441Smckusick /* 125942441Smckusick * Set the access and modification times of a file. 126042441Smckusick */ 126142441Smckusick /* ARGSUSED */ 126242441Smckusick utimes(p, uap, retval) 126345914Smckusick struct proc *p; 126442441Smckusick register struct args { 126511811Ssam char *fname; 126611811Ssam struct timeval *tptr; 126742441Smckusick } *uap; 126842441Smckusick int *retval; 126942441Smckusick { 127037741Smckusick register struct vnode *vp; 127111811Ssam struct timeval tv[2]; 127237741Smckusick struct vattr vattr; 127337741Smckusick int error; 127447540Skarels struct nameidata nd; 127511811Ssam 127637741Smckusick if (error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv))) 127747540Skarels return (error); 127852322Smckusick NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 127952322Smckusick if (error = namei(&nd)) 128047540Skarels return (error); 128152322Smckusick vp = nd.ni_vp; 128241400Smckusick if (vp->v_mount->mnt_flag & MNT_RDONLY) { 128337741Smckusick error = EROFS; 128437741Smckusick goto out; 128521015Smckusick } 128645785Sbostic VATTR_NULL(&vattr); 128745785Sbostic vattr.va_atime = tv[0]; 128845785Sbostic vattr.va_mtime = tv[1]; 128952192Smckusick LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 129048026Smckusick error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 129137741Smckusick out: 129237741Smckusick vput(vp); 129347540Skarels return (error); 129411811Ssam } 129511811Ssam 12969167Ssam /* 12979167Ssam * Truncate a file given its path name. 12989167Ssam */ 129942441Smckusick /* ARGSUSED */ 130042441Smckusick truncate(p, uap, retval) 130145914Smckusick struct proc *p; 130242441Smckusick register struct args { 13037701Ssam char *fname; 130426473Skarels off_t length; 130542441Smckusick } *uap; 130642441Smckusick int *retval; 130742441Smckusick { 130837741Smckusick register struct vnode *vp; 130937741Smckusick struct vattr vattr; 131037741Smckusick int error; 131147540Skarels struct nameidata nd; 13127701Ssam 131352322Smckusick NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 131452322Smckusick if (error = namei(&nd)) 131547540Skarels return (error); 131652322Smckusick vp = nd.ni_vp; 131737741Smckusick if (vp->v_type == VDIR) { 131837741Smckusick error = EISDIR; 131937741Smckusick goto out; 13207701Ssam } 132138399Smckusick if ((error = vn_writechk(vp)) || 132248026Smckusick (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p))) 132337741Smckusick goto out; 132445785Sbostic VATTR_NULL(&vattr); 132545785Sbostic vattr.va_size = uap->length; 132652192Smckusick LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 132748026Smckusick error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 132837741Smckusick out: 132937741Smckusick vput(vp); 133047540Skarels return (error); 13317701Ssam } 13327701Ssam 13339167Ssam /* 13349167Ssam * Truncate a file given a file descriptor. 13359167Ssam */ 133642441Smckusick /* ARGSUSED */ 133742441Smckusick ftruncate(p, uap, retval) 133845914Smckusick struct proc *p; 133942441Smckusick register struct args { 13407701Ssam int fd; 134126473Skarels off_t length; 134242441Smckusick } *uap; 134342441Smckusick int *retval; 134442441Smckusick { 134537741Smckusick struct vattr vattr; 134637741Smckusick struct vnode *vp; 13477701Ssam struct file *fp; 134837741Smckusick int error; 13497701Ssam 135045914Smckusick if (error = getvnode(p->p_fd, uap->fd, &fp)) 135147540Skarels return (error); 135237741Smckusick if ((fp->f_flag & FWRITE) == 0) 135347540Skarels return (EINVAL); 135437741Smckusick vp = (struct vnode *)fp->f_data; 135537741Smckusick VOP_LOCK(vp); 135637741Smckusick if (vp->v_type == VDIR) { 135737741Smckusick error = EISDIR; 135837741Smckusick goto out; 13597701Ssam } 136038399Smckusick if (error = vn_writechk(vp)) 136137741Smckusick goto out; 136245785Sbostic VATTR_NULL(&vattr); 136345785Sbostic vattr.va_size = uap->length; 136452192Smckusick LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 136548026Smckusick error = VOP_SETATTR(vp, &vattr, fp->f_cred, p); 136637741Smckusick out: 136737741Smckusick VOP_UNLOCK(vp); 136847540Skarels return (error); 13697701Ssam } 13707701Ssam 13719167Ssam /* 13729167Ssam * Synch an open file. 13739167Ssam */ 137442441Smckusick /* ARGSUSED */ 137542441Smckusick fsync(p, uap, retval) 137645914Smckusick struct proc *p; 137742441Smckusick struct args { 137842441Smckusick int fd; 137942441Smckusick } *uap; 138042441Smckusick int *retval; 13819167Ssam { 138239592Smckusick register struct vnode *vp; 13839167Ssam struct file *fp; 138437741Smckusick int error; 13859167Ssam 138645914Smckusick if (error = getvnode(p->p_fd, uap->fd, &fp)) 138747540Skarels return (error); 138839592Smckusick vp = (struct vnode *)fp->f_data; 138939592Smckusick VOP_LOCK(vp); 139048026Smckusick error = VOP_FSYNC(vp, fp->f_flag, fp->f_cred, MNT_WAIT, p); 139139592Smckusick VOP_UNLOCK(vp); 139247540Skarels return (error); 13939167Ssam } 13949167Ssam 13959167Ssam /* 13969167Ssam * Rename system call. 13979167Ssam * 13989167Ssam * Source and destination must either both be directories, or both 13999167Ssam * not be directories. If target is a directory, it must be empty. 14009167Ssam */ 140142441Smckusick /* ARGSUSED */ 140242441Smckusick rename(p, uap, retval) 140345914Smckusick struct proc *p; 140442441Smckusick register struct args { 14057701Ssam char *from; 14067701Ssam char *to; 140742441Smckusick } *uap; 140842441Smckusick int *retval; 140942441Smckusick { 141037741Smckusick register struct vnode *tvp, *fvp, *tdvp; 141149735Smckusick struct nameidata fromnd, tond; 141237741Smckusick int error; 14137701Ssam 141452322Smckusick NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE, 141552322Smckusick uap->from, p); 141652322Smckusick if (error = namei(&fromnd)) 141747540Skarels return (error); 141849735Smckusick fvp = fromnd.ni_vp; 141952322Smckusick NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART, 142052322Smckusick UIO_USERSPACE, uap->to, p); 142152322Smckusick if (error = namei(&tond)) { 142252230Sheideman VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 142349735Smckusick vrele(fromnd.ni_dvp); 142442465Smckusick vrele(fvp); 142542465Smckusick goto out1; 142642465Smckusick } 142737741Smckusick tdvp = tond.ni_dvp; 142837741Smckusick tvp = tond.ni_vp; 142937741Smckusick if (tvp != NULL) { 143037741Smckusick if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 143139242Sbostic error = ENOTDIR; 143237741Smckusick goto out; 143337741Smckusick } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 143439242Sbostic error = EISDIR; 143537741Smckusick goto out; 14369167Ssam } 143745240Smckusick if (fvp->v_mount != tvp->v_mount) { 143845240Smckusick error = EXDEV; 143945240Smckusick goto out; 144045240Smckusick } 14419167Ssam } 144237741Smckusick if (fvp->v_mount != tdvp->v_mount) { 144337741Smckusick error = EXDEV; 14449167Ssam goto out; 144510051Ssam } 144639286Smckusick if (fvp == tdvp) 144737741Smckusick error = EINVAL; 144839286Smckusick /* 144949735Smckusick * If source is the same as the destination (that is the 145049735Smckusick * same inode number with the same name in the same directory), 145139286Smckusick * then there is nothing to do. 145239286Smckusick */ 145349735Smckusick if (fvp == tvp && fromnd.ni_dvp == tdvp && 145452322Smckusick fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen && 145552322Smckusick !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr, 145652322Smckusick fromnd.ni_cnd.cn_namelen)) 145739286Smckusick error = -1; 145837741Smckusick out: 145942465Smckusick if (!error) { 146052192Smckusick LEASE_CHECK(tdvp, p, p->p_ucred, LEASE_WRITE); 146152192Smckusick if (fromnd.ni_dvp != tdvp) 146252192Smckusick LEASE_CHECK(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 146352192Smckusick if (tvp) 146452192Smckusick LEASE_CHECK(tvp, p, p->p_ucred, LEASE_WRITE); 146552230Sheideman error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd, 146652230Sheideman tond.ni_dvp, tond.ni_vp, &tond.ni_cnd); 146742465Smckusick } else { 146852230Sheideman VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd); 146943344Smckusick if (tdvp == tvp) 147043344Smckusick vrele(tdvp); 147143344Smckusick else 147243344Smckusick vput(tdvp); 147342465Smckusick if (tvp) 147442465Smckusick vput(tvp); 147552230Sheideman VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 147649735Smckusick vrele(fromnd.ni_dvp); 147742465Smckusick vrele(fvp); 14789167Ssam } 147949735Smckusick vrele(tond.ni_startdir); 148052322Smckusick FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI); 148137741Smckusick out1: 148249735Smckusick vrele(fromnd.ni_startdir); 148352322Smckusick FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI); 148439286Smckusick if (error == -1) 148547540Skarels return (0); 148647540Skarels return (error); 14877701Ssam } 14887701Ssam 14897535Sroot /* 149049365Smckusick * Mkdir system call. 149112756Ssam */ 149242441Smckusick /* ARGSUSED */ 149342441Smckusick mkdir(p, uap, retval) 149445914Smckusick struct proc *p; 149542441Smckusick register struct args { 149612756Ssam char *name; 149712756Ssam int dmode; 149842441Smckusick } *uap; 149942441Smckusick int *retval; 150042441Smckusick { 150137741Smckusick register struct vnode *vp; 150237741Smckusick struct vattr vattr; 150337741Smckusick int error; 150447540Skarels struct nameidata nd; 150512756Ssam 150652322Smckusick NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->name, p); 150752322Smckusick if (error = namei(&nd)) 150847540Skarels return (error); 150952322Smckusick vp = nd.ni_vp; 151037741Smckusick if (vp != NULL) { 151152322Smckusick VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 151252322Smckusick if (nd.ni_dvp == vp) 151352322Smckusick vrele(nd.ni_dvp); 151443344Smckusick else 151552322Smckusick vput(nd.ni_dvp); 151642465Smckusick vrele(vp); 151747540Skarels return (EEXIST); 151812756Ssam } 151941362Smckusick VATTR_NULL(&vattr); 152037741Smckusick vattr.va_type = VDIR; 152145914Smckusick vattr.va_mode = (uap->dmode & 0777) &~ p->p_fd->fd_cmask; 152252322Smckusick LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 152352322Smckusick error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 152438145Smckusick if (!error) 152552322Smckusick vput(nd.ni_vp); 152647540Skarels return (error); 152712756Ssam } 152812756Ssam 152912756Ssam /* 153012756Ssam * Rmdir system call. 153112756Ssam */ 153242441Smckusick /* ARGSUSED */ 153342441Smckusick rmdir(p, uap, retval) 153445914Smckusick struct proc *p; 153542441Smckusick struct args { 153642441Smckusick char *name; 153742441Smckusick } *uap; 153842441Smckusick int *retval; 153912756Ssam { 154037741Smckusick register struct vnode *vp; 154137741Smckusick int error; 154247540Skarels struct nameidata nd; 154312756Ssam 154452322Smckusick NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, uap->name, p); 154552322Smckusick if (error = namei(&nd)) 154647540Skarels return (error); 154752322Smckusick vp = nd.ni_vp; 154837741Smckusick if (vp->v_type != VDIR) { 154937741Smckusick error = ENOTDIR; 155012756Ssam goto out; 155112756Ssam } 155212756Ssam /* 155337741Smckusick * No rmdir "." please. 155412756Ssam */ 155552322Smckusick if (nd.ni_dvp == vp) { 155637741Smckusick error = EINVAL; 155712756Ssam goto out; 155812756Ssam } 155912756Ssam /* 156049365Smckusick * The root of a mounted filesystem cannot be deleted. 156112756Ssam */ 156237741Smckusick if (vp->v_flag & VROOT) 156337741Smckusick error = EBUSY; 156412756Ssam out: 156542465Smckusick if (!error) { 156652322Smckusick LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 156752192Smckusick LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 156852322Smckusick error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 156942465Smckusick } else { 157052322Smckusick VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 157152322Smckusick if (nd.ni_dvp == vp) 157252322Smckusick vrele(nd.ni_dvp); 157343344Smckusick else 157452322Smckusick vput(nd.ni_dvp); 157542465Smckusick vput(vp); 157642465Smckusick } 157747540Skarels return (error); 157812756Ssam } 157912756Ssam 158037741Smckusick /* 158149365Smckusick * Read a block of directory entries in a file system independent format. 158237741Smckusick */ 158342441Smckusick getdirentries(p, uap, retval) 158445914Smckusick struct proc *p; 158542441Smckusick register struct args { 158637741Smckusick int fd; 158737741Smckusick char *buf; 158837741Smckusick unsigned count; 158937741Smckusick long *basep; 159042441Smckusick } *uap; 159142441Smckusick int *retval; 159242441Smckusick { 159339592Smckusick register struct vnode *vp; 159416540Ssam struct file *fp; 159537741Smckusick struct uio auio; 159637741Smckusick struct iovec aiov; 159738129Smckusick off_t off; 159840321Smckusick int error, eofflag; 159912756Ssam 160045914Smckusick if (error = getvnode(p->p_fd, uap->fd, &fp)) 160147540Skarels return (error); 160237741Smckusick if ((fp->f_flag & FREAD) == 0) 160347540Skarels return (EBADF); 160439592Smckusick vp = (struct vnode *)fp->f_data; 160539592Smckusick if (vp->v_type != VDIR) 160647540Skarels return (EINVAL); 160737741Smckusick aiov.iov_base = uap->buf; 160837741Smckusick aiov.iov_len = uap->count; 160937741Smckusick auio.uio_iov = &aiov; 161037741Smckusick auio.uio_iovcnt = 1; 161137741Smckusick auio.uio_rw = UIO_READ; 161237741Smckusick auio.uio_segflg = UIO_USERSPACE; 161348026Smckusick auio.uio_procp = p; 161437741Smckusick auio.uio_resid = uap->count; 161539592Smckusick VOP_LOCK(vp); 161639592Smckusick auio.uio_offset = off = fp->f_offset; 161740321Smckusick error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag); 161839592Smckusick fp->f_offset = auio.uio_offset; 161939592Smckusick VOP_UNLOCK(vp); 162039592Smckusick if (error) 162147540Skarels return (error); 162239592Smckusick error = copyout((caddr_t)&off, (caddr_t)uap->basep, sizeof(long)); 162342441Smckusick *retval = uap->count - auio.uio_resid; 162447540Skarels return (error); 162512756Ssam } 162612756Ssam 162712756Ssam /* 162849365Smckusick * Set the mode mask for creation of filesystem nodes. 162912756Ssam */ 163042441Smckusick mode_t 163142441Smckusick umask(p, uap, retval) 163245914Smckusick struct proc *p; 163342441Smckusick struct args { 163442441Smckusick int mask; 163542441Smckusick } *uap; 163642441Smckusick int *retval; 163712756Ssam { 163845914Smckusick register struct filedesc *fdp = p->p_fd; 163912756Ssam 164045914Smckusick *retval = fdp->fd_cmask; 164145914Smckusick fdp->fd_cmask = uap->mask & 07777; 164247540Skarels return (0); 164312756Ssam } 164437741Smckusick 164539566Smarc /* 164639566Smarc * Void all references to file by ripping underlying filesystem 164739566Smarc * away from vnode. 164839566Smarc */ 164942441Smckusick /* ARGSUSED */ 165042441Smckusick revoke(p, uap, retval) 165145914Smckusick struct proc *p; 165242441Smckusick register struct args { 165339566Smarc char *fname; 165442441Smckusick } *uap; 165542441Smckusick int *retval; 165642441Smckusick { 165739566Smarc register struct vnode *vp; 165839566Smarc struct vattr vattr; 165939566Smarc int error; 166047540Skarels struct nameidata nd; 166139566Smarc 166252322Smckusick NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->fname, p); 166352322Smckusick if (error = namei(&nd)) 166447540Skarels return (error); 166552322Smckusick vp = nd.ni_vp; 166639566Smarc if (vp->v_type != VCHR && vp->v_type != VBLK) { 166739566Smarc error = EINVAL; 166839566Smarc goto out; 166939566Smarc } 167048026Smckusick if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) 167139566Smarc goto out; 167247540Skarels if (p->p_ucred->cr_uid != vattr.va_uid && 167347540Skarels (error = suser(p->p_ucred, &p->p_acflag))) 167439566Smarc goto out; 167539805Smckusick if (vp->v_usecount > 1 || (vp->v_flag & VALIASED)) 167639632Smckusick vgoneall(vp); 167739566Smarc out: 167839566Smarc vrele(vp); 167947540Skarels return (error); 168039566Smarc } 168139566Smarc 168249365Smckusick /* 168349365Smckusick * Convert a user file descriptor to a kernel file entry. 168449365Smckusick */ 168545914Smckusick getvnode(fdp, fdes, fpp) 168645914Smckusick struct filedesc *fdp; 168737741Smckusick struct file **fpp; 168837741Smckusick int fdes; 168937741Smckusick { 169037741Smckusick struct file *fp; 169137741Smckusick 169247540Skarels if ((unsigned)fdes >= fdp->fd_nfiles || 169347688Skarels (fp = fdp->fd_ofiles[fdes]) == NULL) 169437741Smckusick return (EBADF); 169537741Smckusick if (fp->f_type != DTYPE_VNODE) 169637741Smckusick return (EINVAL); 169737741Smckusick *fpp = fp; 169837741Smckusick return (0); 169937741Smckusick } 1700