123405Smckusick /* 237741Smckusick * Copyright (c) 1989 The Regents of the University of California. 337741Smckusick * All rights reserved. 423405Smckusick * 537741Smckusick * Redistribution and use in source and binary forms are permitted 637741Smckusick * provided that the above copyright notice and this paragraph are 737741Smckusick * duplicated in all such forms and that any documentation, 837741Smckusick * advertising materials, and other materials related to such 937741Smckusick * distribution and use acknowledge that the software was developed 1037741Smckusick * by the University of California, Berkeley. The name of the 1137741Smckusick * University may not be used to endorse or promote products derived 1237741Smckusick * from this software without specific prior written permission. 1337741Smckusick * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1437741Smckusick * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1537741Smckusick * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1637741Smckusick * 17*38266Smckusick * @(#)vfs_syscalls.c 7.11 (Berkeley) 06/08/89 1823405Smckusick */ 1937Sbill 2017101Sbloom #include "param.h" 2117101Sbloom #include "systm.h" 2237741Smckusick #include "syscontext.h" 2317101Sbloom #include "kernel.h" 2417101Sbloom #include "file.h" 2517101Sbloom #include "stat.h" 2637741Smckusick #include "vnode.h" 2737741Smckusick #include "../ufs/inode.h" 2837741Smckusick #include "mount.h" 2917101Sbloom #include "proc.h" 3017101Sbloom #include "uio.h" 3137741Smckusick #include "malloc.h" 3237Sbill 3337741Smckusick /* 3437741Smckusick * Virtual File System System Calls 3537741Smckusick */ 3612756Ssam 379167Ssam /* 3837741Smckusick * mount system call 399167Ssam */ 4037741Smckusick mount() 416254Sroot { 4237741Smckusick register struct a { 4337741Smckusick int type; 4437741Smckusick char *dir; 4537741Smckusick int flags; 4637741Smckusick caddr_t data; 4737741Smckusick } *uap = (struct a *)u.u_ap; 4837741Smckusick register struct nameidata *ndp = &u.u_nd; 4937741Smckusick struct vnode *vp; 5037741Smckusick struct mount *mp; 5137741Smckusick int error; 526254Sroot 5337741Smckusick /* 5437741Smckusick * Must be super user 5537741Smckusick */ 5637741Smckusick if (error = suser(u.u_cred, &u.u_acflag)) 5737741Smckusick RETURN (error); 5837741Smckusick /* 5937741Smckusick * Get vnode to be covered 6037741Smckusick */ 6137741Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 6237741Smckusick ndp->ni_segflg = UIO_USERSPACE; 6337741Smckusick ndp->ni_dirp = uap->dir; 6437741Smckusick if (error = namei(ndp)) 6537741Smckusick RETURN (error); 6637741Smckusick vp = ndp->ni_vp; 6737741Smckusick if (vp->v_count != 1) { 6837741Smckusick vput(vp); 6937741Smckusick RETURN (EBUSY); 7037741Smckusick } 7137741Smckusick if (vp->v_type != VDIR) { 7237741Smckusick vput(vp); 7337741Smckusick RETURN (ENOTDIR); 7437741Smckusick } 7537741Smckusick if (uap->type > MOUNT_MAXTYPE || 7637741Smckusick vfssw[uap->type] == (struct vfsops *)0) { 7737741Smckusick vput(vp); 7837741Smckusick RETURN (ENODEV); 7937741Smckusick } 8037741Smckusick 8137741Smckusick /* 8237741Smckusick * Mount the filesystem. 8337741Smckusick */ 8437741Smckusick mp = (struct mount *)malloc((u_long)sizeof(struct mount), 8537741Smckusick M_MOUNT, M_WAITOK); 8637741Smckusick mp->m_op = vfssw[uap->type]; 8737741Smckusick mp->m_flag = 0; 8837741Smckusick mp->m_exroot = 0; 8937741Smckusick error = vfs_add(vp, mp, uap->flags); 9037741Smckusick if (!error) 9137741Smckusick error = VFS_MOUNT(mp, uap->dir, uap->data, ndp); 9237741Smckusick cache_purge(vp); 9337741Smckusick VOP_UNLOCK(vp); 9437741Smckusick if (!error) { 9537741Smckusick vfs_unlock(mp); 9637741Smckusick } else { 9737741Smckusick vfs_remove(mp); 9837741Smckusick free((caddr_t)mp, M_MOUNT); 9937741Smckusick vrele(vp); 10037741Smckusick } 10137741Smckusick RETURN (error); 1026254Sroot } 1036254Sroot 1049167Ssam /* 10537741Smckusick * Unmount system call. 10637741Smckusick * 10737741Smckusick * Note: unmount takes a path to the vnode mounted on as argument, 10837741Smckusick * not special file (as before). 1099167Ssam */ 11037741Smckusick unmount() 1116254Sroot { 11237741Smckusick struct a { 11337741Smckusick char *pathp; 11437741Smckusick int flags; 11537741Smckusick } *uap = (struct a *)u.u_ap; 11637741Smckusick register struct vnode *vp; 11737741Smckusick register struct mount *mp; 11837741Smckusick register struct nameidata *ndp = &u.u_nd; 11937741Smckusick struct vnode *coveredvp; 12037741Smckusick int error; 1216254Sroot 12237741Smckusick /* 12337741Smckusick * Must be super user 12437741Smckusick */ 12537741Smckusick if (error = suser(u.u_cred, &u.u_acflag)) 12637741Smckusick RETURN (error); 12737741Smckusick 12837741Smckusick ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW; 12937741Smckusick ndp->ni_segflg = UIO_USERSPACE; 13037741Smckusick ndp->ni_dirp = uap->pathp; 13137741Smckusick if (error = namei(ndp)) 13237741Smckusick RETURN (error); 13337741Smckusick vp = ndp->ni_vp; 13437741Smckusick /* 13537741Smckusick * Must be the root of the filesystem 13637741Smckusick */ 13737741Smckusick if ((vp->v_flag & VROOT) == 0) { 13837741Smckusick vput(vp); 13937741Smckusick RETURN (EINVAL); 14037741Smckusick } 14137741Smckusick mp = vp->v_mount; 14237741Smckusick vput(vp); 14337741Smckusick /* 14437741Smckusick * Do the unmount. 14537741Smckusick */ 14637741Smckusick coveredvp = mp->m_vnodecovered; 14737741Smckusick if (error = vfs_lock(mp)) 14837741Smckusick RETURN (error); 14937741Smckusick 15037741Smckusick xumount(mp); /* remove unused sticky files from text table */ 15137741Smckusick cache_purgevfs(mp); /* remove cache entries for this file sys */ 15237741Smckusick VFS_SYNC(mp, MNT_WAIT); 15337741Smckusick 15437741Smckusick error = VFS_UNMOUNT(mp, uap->flags); 15537741Smckusick if (error) { 15637741Smckusick vfs_unlock(mp); 15737741Smckusick } else { 15837741Smckusick vrele(coveredvp); 15937741Smckusick vfs_remove(mp); 16037741Smckusick free((caddr_t)mp, M_MOUNT); 16137741Smckusick } 16237741Smckusick RETURN (error); 1636254Sroot } 1646254Sroot 1659167Ssam /* 16637741Smckusick * Sync system call. 16737741Smckusick * Sync each mounted filesystem. 1689167Ssam */ 16937741Smckusick sync() 1706254Sroot { 17137741Smckusick register struct mount *mp; 17237741Smckusick 17337741Smckusick mp = rootfs; 17437741Smckusick do { 17537741Smckusick if ((mp->m_flag & M_RDONLY) == 0) 17637741Smckusick VFS_SYNC(mp, MNT_NOWAIT); 17737741Smckusick mp = mp->m_next; 17837741Smckusick } while (mp != rootfs); 17937741Smckusick } 18037741Smckusick 18137741Smckusick /* 18237741Smckusick * get filesystem statistics 18337741Smckusick */ 18437741Smckusick statfs() 18537741Smckusick { 1866254Sroot struct a { 18737741Smckusick char *path; 18837741Smckusick struct statfs *buf; 18937741Smckusick } *uap = (struct a *)u.u_ap; 19037741Smckusick register struct vnode *vp; 19137741Smckusick register struct nameidata *ndp = &u.u_nd; 19237741Smckusick struct statfs sb; 19337741Smckusick int error; 19437741Smckusick 19537741Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 19637741Smckusick ndp->ni_segflg = UIO_USERSPACE; 19737741Smckusick ndp->ni_dirp = uap->path; 19837741Smckusick if (error = namei(ndp)) 19937741Smckusick RETURN (error); 20037741Smckusick vp = ndp->ni_vp; 20137741Smckusick if (error = VFS_STATFS(vp->v_mount, &sb)) 20237741Smckusick goto out; 20337741Smckusick error = copyout((caddr_t)&sb, (caddr_t)uap->buf, sizeof(sb)); 20437741Smckusick out: 20537741Smckusick vput(vp); 20637741Smckusick RETURN (error); 20737741Smckusick } 20837741Smckusick 20937741Smckusick fstatfs() 21037741Smckusick { 21137741Smckusick struct a { 21237741Smckusick int fd; 21337741Smckusick struct statfs *buf; 21437741Smckusick } *uap = (struct a *)u.u_ap; 21537741Smckusick struct file *fp; 21637741Smckusick struct statfs sb; 21737741Smckusick int error; 21837741Smckusick 21937741Smckusick if (error = getvnode(uap->fd, &fp)) 22037741Smckusick RETURN (error); 22137741Smckusick if (error = VFS_STATFS(((struct vnode *)fp->f_data)->v_mount, &sb)) 22237741Smckusick RETURN (error); 22337741Smckusick RETURN (copyout((caddr_t)&sb, (caddr_t)uap->buf, sizeof(sb))); 22437741Smckusick } 22537741Smckusick 22637741Smckusick /* 22738259Smckusick * Change current working directory to a given file descriptor. 22838259Smckusick */ 22938259Smckusick fchdir() 23038259Smckusick { 23138259Smckusick struct a { 23238259Smckusick int fd; 23338259Smckusick } *uap = (struct a *)u.u_ap; 23438259Smckusick register struct vnode *vp; 23538259Smckusick struct file *fp; 23638259Smckusick int error; 23738259Smckusick 23838259Smckusick if (error = getvnode(uap->fd, &fp)) 23938259Smckusick RETURN (error); 24038259Smckusick vp = (struct vnode *)fp->f_data; 24138259Smckusick VOP_LOCK(vp); 24238259Smckusick if (vp->v_type != VDIR) 24338259Smckusick error = ENOTDIR; 24438259Smckusick else 24538259Smckusick error = vn_access(vp, VEXEC, u.u_cred); 24638259Smckusick VOP_UNLOCK(vp); 24738259Smckusick vrele(u.u_cdir); 24838259Smckusick u.u_cdir = vp; 24938259Smckusick RETURN (error); 25038259Smckusick } 25138259Smckusick 25238259Smckusick /* 25337741Smckusick * Change current working directory (``.''). 25437741Smckusick */ 25537741Smckusick chdir() 25637741Smckusick { 25737741Smckusick struct a { 2586254Sroot char *fname; 25916694Smckusick } *uap = (struct a *)u.u_ap; 26016694Smckusick register struct nameidata *ndp = &u.u_nd; 26137741Smckusick int error; 2626254Sroot 26337741Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 26416694Smckusick ndp->ni_segflg = UIO_USERSPACE; 26516694Smckusick ndp->ni_dirp = uap->fname; 26637741Smckusick if (error = chdirec(ndp)) 26737741Smckusick RETURN (error); 26837741Smckusick vrele(u.u_cdir); 26937741Smckusick u.u_cdir = ndp->ni_vp; 27037741Smckusick RETURN (0); 27137741Smckusick } 2726254Sroot 27337741Smckusick /* 27437741Smckusick * Change notion of root (``/'') directory. 27537741Smckusick */ 27637741Smckusick chroot() 27737741Smckusick { 27837741Smckusick struct a { 27937741Smckusick char *fname; 28037741Smckusick } *uap = (struct a *)u.u_ap; 28137741Smckusick register struct nameidata *ndp = &u.u_nd; 28237741Smckusick int error; 28337741Smckusick 28437741Smckusick if (error = suser(u.u_cred, &u.u_acflag)) 28537741Smckusick RETURN (error); 28637741Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 28737741Smckusick ndp->ni_segflg = UIO_USERSPACE; 28837741Smckusick ndp->ni_dirp = uap->fname; 28937741Smckusick if (error = chdirec(ndp)) 29037741Smckusick RETURN (error); 29137741Smckusick vrele(u.u_rdir); 29237741Smckusick u.u_rdir = ndp->ni_vp; 29337741Smckusick RETURN (0); 2946254Sroot } 2956254Sroot 29637Sbill /* 29737741Smckusick * Common routine for chroot and chdir. 29837741Smckusick */ 29937741Smckusick chdirec(ndp) 30037741Smckusick register struct nameidata *ndp; 30137741Smckusick { 30237741Smckusick struct vnode *vp; 30337741Smckusick int error; 30437741Smckusick 30537741Smckusick if (error = namei(ndp)) 30637741Smckusick return (error); 30737741Smckusick vp = ndp->ni_vp; 30837741Smckusick if (vp->v_type != VDIR) 30937741Smckusick error = ENOTDIR; 31037741Smckusick else 31137741Smckusick error = vn_access(vp, VEXEC, ndp->ni_cred); 31237741Smckusick VOP_UNLOCK(vp); 31337741Smckusick if (error) 31437741Smckusick vrele(vp); 31537741Smckusick return (error); 31637741Smckusick } 31737741Smckusick 31837741Smckusick /* 3196254Sroot * Open system call. 3206254Sroot */ 3216254Sroot open() 3226254Sroot { 32312756Ssam struct a { 3246254Sroot char *fname; 3257701Ssam int mode; 32612756Ssam int crtmode; 32712756Ssam } *uap = (struct a *) u.u_ap; 32837741Smckusick struct nameidata *ndp = &u.u_nd; 3296254Sroot 33037741Smckusick ndp->ni_segflg = UIO_USERSPACE; 33137741Smckusick ndp->ni_dirp = uap->fname; 33237741Smckusick RETURN (copen(uap->mode-FOPEN, uap->crtmode &~ u.u_cmask, ndp, 33337741Smckusick &u.u_r.r_val1)); 3346254Sroot } 3356254Sroot 3366254Sroot /* 3376254Sroot * Creat system call. 3386254Sroot */ 33912756Ssam creat() 3406254Sroot { 34112756Ssam struct a { 3426254Sroot char *fname; 3436254Sroot int fmode; 34412756Ssam } *uap = (struct a *)u.u_ap; 34537741Smckusick struct nameidata *ndp = &u.u_nd; 3466254Sroot 34737741Smckusick ndp->ni_segflg = UIO_USERSPACE; 34837741Smckusick ndp->ni_dirp = uap->fname; 34937741Smckusick RETURN (copen(FWRITE|FCREAT|FTRUNC, uap->fmode &~ u.u_cmask, ndp, 35037741Smckusick &u.u_r.r_val1)); 3516254Sroot } 3526254Sroot 3536254Sroot /* 3546254Sroot * Common code for open and creat. 35512756Ssam * Check permissions, allocate an open file structure, 35612756Ssam * and call the device open routine if any. 3576254Sroot */ 35837741Smckusick copen(fmode, cmode, ndp, resultfd) 35937741Smckusick int fmode, cmode; 36037741Smckusick struct nameidata *ndp; 36137741Smckusick int *resultfd; 36212756Ssam { 3636254Sroot register struct file *fp; 36437741Smckusick struct file *nfp; 36537741Smckusick int indx, error; 36637741Smckusick extern struct fileops vnops; 3676254Sroot 36837741Smckusick if (error = falloc(&nfp, &indx)) 36937741Smckusick return (error); 37037741Smckusick fp = nfp; 37137741Smckusick u.u_r.r_val1 = indx; /* XXX for fdopen() */ 37237741Smckusick if (error = vn_open(ndp, fmode, (cmode & 07777) &~ ISVTX)) { 37324543Smckusick u.u_ofile[indx] = NULL; 37437741Smckusick crfree(fp->f_cred); 37537741Smckusick fp->f_count--; 37637741Smckusick return (error); 37712756Ssam } 37837741Smckusick fp->f_flag = fmode & FMASK; 37937741Smckusick fp->f_type = DTYPE_VNODE; 38037741Smckusick fp->f_ops = &vnops; 38137741Smckusick fp->f_data = (caddr_t)ndp->ni_vp; 38237741Smckusick if (resultfd) 38337741Smckusick *resultfd = indx; 38437741Smckusick return (0); 3856254Sroot } 3866254Sroot 3876254Sroot /* 3886254Sroot * Mknod system call 3896254Sroot */ 3906254Sroot mknod() 3916254Sroot { 3926254Sroot register struct a { 3936254Sroot char *fname; 3946254Sroot int fmode; 3956254Sroot int dev; 39616694Smckusick } *uap = (struct a *)u.u_ap; 39716694Smckusick register struct nameidata *ndp = &u.u_nd; 39837741Smckusick register struct vnode *vp; 39937741Smckusick struct vattr vattr; 40037741Smckusick int error; 4016254Sroot 40237741Smckusick if (error = suser(u.u_cred, &u.u_acflag)) 40337741Smckusick RETURN (error); 40437741Smckusick ndp->ni_nameiop = CREATE | LOCKPARENT; 40516694Smckusick ndp->ni_segflg = UIO_USERSPACE; 40616694Smckusick ndp->ni_dirp = uap->fname; 40737741Smckusick if (error = namei(ndp)) 40837741Smckusick RETURN (error); 40937741Smckusick vp = ndp->ni_vp; 41037741Smckusick if (vp != NULL) { 41137741Smckusick error = EEXIST; 41212756Ssam goto out; 4136254Sroot } 41437741Smckusick vattr_null(&vattr); 41537741Smckusick switch (uap->fmode & IFMT) { 41612756Ssam 41715093Smckusick case IFMT: /* used by badsect to flag bad sectors */ 41837741Smckusick vattr.va_type = VBAD; 41937741Smckusick break; 42012756Ssam case IFCHR: 42137741Smckusick vattr.va_type = VCHR; 42237741Smckusick break; 42312756Ssam case IFBLK: 42437741Smckusick vattr.va_type = VBLK; 42537741Smckusick break; 42637741Smckusick default: 42737741Smckusick error = EINVAL; 42837741Smckusick goto out; 4296254Sroot } 43037741Smckusick vattr.va_mode = (uap->fmode & 07777) &~ u.u_cmask; 43137741Smckusick vattr.va_rdev = uap->dev; 4326254Sroot out: 43337741Smckusick if (error) 43437741Smckusick VOP_ABORTOP(ndp); 43537741Smckusick else 43637741Smckusick error = VOP_MKNOD(ndp, &vattr, ndp->ni_cred); 43737741Smckusick RETURN (error); 4386254Sroot } 4396254Sroot 4406254Sroot /* 4416254Sroot * link system call 4426254Sroot */ 4436254Sroot link() 4446254Sroot { 4456254Sroot register struct a { 4466254Sroot char *target; 4476254Sroot char *linkname; 44816694Smckusick } *uap = (struct a *)u.u_ap; 44916694Smckusick register struct nameidata *ndp = &u.u_nd; 45037741Smckusick register struct vnode *vp, *xp; 45137741Smckusick int error; 4526254Sroot 45316694Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW; 45416694Smckusick ndp->ni_segflg = UIO_USERSPACE; 45516694Smckusick ndp->ni_dirp = uap->target; 45637741Smckusick if (error = namei(ndp)) 45737741Smckusick RETURN (error); 45837741Smckusick vp = ndp->ni_vp; 45937741Smckusick if (vp->v_type == VDIR && 46037741Smckusick (error = suser(u.u_cred, &u.u_acflag))) 46137741Smckusick goto out1; 46237741Smckusick ndp->ni_nameiop = CREATE | LOCKPARENT; 46316694Smckusick ndp->ni_dirp = (caddr_t)uap->linkname; 46437741Smckusick if (error = namei(ndp)) 46537741Smckusick goto out1; 46637741Smckusick xp = ndp->ni_vp; 4676254Sroot if (xp != NULL) { 46837741Smckusick error = EEXIST; 4696254Sroot goto out; 4706254Sroot } 47137741Smckusick xp = ndp->ni_dvp; 47237741Smckusick if (vp->v_mount != xp->v_mount) 47337741Smckusick error = EXDEV; 4746254Sroot out: 47537741Smckusick if (error) 47637741Smckusick VOP_ABORTOP(ndp); 47737741Smckusick else 47837741Smckusick error = VOP_LINK(vp, ndp); 47937741Smckusick out1: 48037741Smckusick vrele(vp); 48137741Smckusick RETURN (error); 4826254Sroot } 4836254Sroot 4846254Sroot /* 4856254Sroot * symlink -- make a symbolic link 4866254Sroot */ 4876254Sroot symlink() 4886254Sroot { 48937741Smckusick struct a { 4906254Sroot char *target; 4916254Sroot char *linkname; 49216694Smckusick } *uap = (struct a *)u.u_ap; 49316694Smckusick register struct nameidata *ndp = &u.u_nd; 49437741Smckusick register struct vnode *vp; 49537741Smckusick struct vattr vattr; 49637741Smckusick char *target; 49737741Smckusick int error; 4986254Sroot 49916694Smckusick ndp->ni_segflg = UIO_USERSPACE; 50016694Smckusick ndp->ni_dirp = uap->linkname; 50137741Smckusick MALLOC(target, char *, MAXPATHLEN, M_NAMEI, M_WAITOK); 50237741Smckusick if (error = copyinstr(uap->target, target, MAXPATHLEN, (u_int *)0)) 50337741Smckusick goto out1; 50437741Smckusick ndp->ni_nameiop = CREATE | LOCKPARENT; 50537741Smckusick if (error = namei(ndp)) 50637741Smckusick goto out1; 50737741Smckusick vp = ndp->ni_vp; 50837741Smckusick if (vp) { 50937741Smckusick error = EEXIST; 51037741Smckusick goto out; 5116254Sroot } 51237741Smckusick vp = ndp->ni_dvp; 51337741Smckusick vattr_null(&vattr); 51437741Smckusick vattr.va_mode = 0777 &~ u.u_cmask; 51537741Smckusick out: 51637741Smckusick if (error) 51737741Smckusick VOP_ABORTOP(ndp); 51837741Smckusick else 51937741Smckusick error = VOP_SYMLINK(ndp, &vattr, target); 52037741Smckusick out1: 52137741Smckusick FREE(target, M_NAMEI); 52237741Smckusick RETURN (error); 5236254Sroot } 5246254Sroot 5256254Sroot /* 5266254Sroot * Unlink system call. 5276254Sroot * Hard to avoid races here, especially 5286254Sroot * in unlinking directories. 5296254Sroot */ 5306254Sroot unlink() 5316254Sroot { 5326254Sroot struct a { 5336254Sroot char *fname; 53416694Smckusick } *uap = (struct a *)u.u_ap; 53516694Smckusick register struct nameidata *ndp = &u.u_nd; 53637741Smckusick register struct vnode *vp; 53737741Smckusick int error; 5386254Sroot 53937741Smckusick ndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF; 54016694Smckusick ndp->ni_segflg = UIO_USERSPACE; 54116694Smckusick ndp->ni_dirp = uap->fname; 54237741Smckusick if (error = namei(ndp)) 54337741Smckusick RETURN (error); 54437741Smckusick vp = ndp->ni_vp; 54537741Smckusick if (vp->v_type == VDIR && 54637741Smckusick (error = suser(u.u_cred, &u.u_acflag))) 5476254Sroot goto out; 5486254Sroot /* 5496254Sroot * Don't unlink a mounted file. 5506254Sroot */ 55137741Smckusick if (vp->v_flag & VROOT) { 55237741Smckusick error = EBUSY; 5536254Sroot goto out; 5546254Sroot } 55537741Smckusick if (vp->v_flag & VTEXT) 55637741Smckusick xrele(vp); /* try once to free text */ 5576254Sroot out: 55837741Smckusick if (error) 55937741Smckusick VOP_ABORTOP(ndp); 5607142Smckusick else 56137741Smckusick error = VOP_REMOVE(ndp); 56237741Smckusick RETURN (error); 5636254Sroot } 5646254Sroot 5656254Sroot /* 5666254Sroot * Seek system call 5676254Sroot */ 5688040Sroot lseek() 5696254Sroot { 5706254Sroot register struct file *fp; 5716254Sroot register struct a { 57237741Smckusick int fdes; 5736254Sroot off_t off; 5746254Sroot int sbase; 57516694Smckusick } *uap = (struct a *)u.u_ap; 57637741Smckusick struct vattr vattr; 57737741Smckusick int error; 5786254Sroot 57937741Smckusick if ((unsigned)uap->fdes >= NOFILE || 58037741Smckusick (fp = u.u_ofile[uap->fdes]) == NULL) 58137741Smckusick RETURN (EBADF); 58237741Smckusick if (fp->f_type != DTYPE_VNODE) 58337741Smckusick RETURN (ESPIPE); 58413878Ssam switch (uap->sbase) { 58513878Ssam 58613878Ssam case L_INCR: 58713878Ssam fp->f_offset += uap->off; 58813878Ssam break; 58913878Ssam 59013878Ssam case L_XTND: 59137741Smckusick if (error = VOP_GETATTR((struct vnode *)fp->f_data, 59237741Smckusick &vattr, u.u_cred)) 59337741Smckusick RETURN (error); 59437741Smckusick fp->f_offset = uap->off + vattr.va_size; 59513878Ssam break; 59613878Ssam 59713878Ssam case L_SET: 59813878Ssam fp->f_offset = uap->off; 59913878Ssam break; 60013878Ssam 60113878Ssam default: 60237741Smckusick RETURN (EINVAL); 60313878Ssam } 60413878Ssam u.u_r.r_off = fp->f_offset; 60537741Smckusick RETURN (0); 6066254Sroot } 6076254Sroot 6086254Sroot /* 6096254Sroot * Access system call 6106254Sroot */ 6116254Sroot saccess() 6126254Sroot { 6136254Sroot register struct a { 6146254Sroot char *fname; 6156254Sroot int fmode; 61616694Smckusick } *uap = (struct a *)u.u_ap; 61716694Smckusick register struct nameidata *ndp = &u.u_nd; 61837741Smckusick register struct vnode *vp; 61937741Smckusick int error, mode, svuid, svgid; 6206254Sroot 6216254Sroot svuid = u.u_uid; 6226254Sroot svgid = u.u_gid; 6236254Sroot u.u_uid = u.u_ruid; 6246254Sroot u.u_gid = u.u_rgid; 62537741Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 62616694Smckusick ndp->ni_segflg = UIO_USERSPACE; 62716694Smckusick ndp->ni_dirp = uap->fname; 62837741Smckusick if (error = namei(ndp)) 62937741Smckusick goto out1; 63037741Smckusick vp = ndp->ni_vp; 63137741Smckusick /* 63237741Smckusick * fmode == 0 means only check for exist 63337741Smckusick */ 63437741Smckusick if (uap->fmode) { 63537741Smckusick mode = 0; 63637741Smckusick if (uap->fmode & R_OK) 63737741Smckusick mode |= VREAD; 63837741Smckusick if (uap->fmode & W_OK) 63937741Smckusick mode |= VWRITE; 64037741Smckusick if (uap->fmode & X_OK) 64137741Smckusick mode |= VEXEC; 64237741Smckusick error = vn_access(vp, mode, u.u_cred); 6436254Sroot } 64437741Smckusick vput(vp); 64537741Smckusick out1: 6466254Sroot u.u_uid = svuid; 6476254Sroot u.u_gid = svgid; 64837741Smckusick RETURN (error); 6496254Sroot } 6506254Sroot 6516254Sroot /* 6526574Smckusic * Stat system call. This version follows links. 65337Sbill */ 65437Sbill stat() 65537Sbill { 65637Sbill 65716694Smckusick stat1(FOLLOW); 65837Sbill } 65937Sbill 66037Sbill /* 6616574Smckusic * Lstat system call. This version does not follow links. 6625992Swnj */ 6635992Swnj lstat() 6645992Swnj { 66512756Ssam 66616694Smckusick stat1(NOFOLLOW); 66712756Ssam } 66812756Ssam 66912756Ssam stat1(follow) 67012756Ssam int follow; 67112756Ssam { 6725992Swnj register struct a { 6735992Swnj char *fname; 67412756Ssam struct stat *ub; 67516694Smckusick } *uap = (struct a *)u.u_ap; 67637741Smckusick register struct nameidata *ndp = &u.u_nd; 67712756Ssam struct stat sb; 67837741Smckusick int error; 6795992Swnj 68037741Smckusick ndp->ni_nameiop = LOOKUP | LOCKLEAF | follow; 68116694Smckusick ndp->ni_segflg = UIO_USERSPACE; 68216694Smckusick ndp->ni_dirp = uap->fname; 68337741Smckusick if (error = namei(ndp)) 68437741Smckusick RETURN (error); 68537741Smckusick error = vn_stat(ndp->ni_vp, &sb); 68637741Smckusick vput(ndp->ni_vp); 68737741Smckusick if (error) 68837741Smckusick RETURN (error); 68937741Smckusick error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb)); 69037741Smckusick RETURN (error); 6915992Swnj } 6925992Swnj 6935992Swnj /* 6945992Swnj * Return target name of a symbolic link 69537Sbill */ 6965992Swnj readlink() 6975992Swnj { 6985992Swnj register struct a { 6995992Swnj char *name; 7005992Swnj char *buf; 7015992Swnj int count; 7027826Sroot } *uap = (struct a *)u.u_ap; 70316694Smckusick register struct nameidata *ndp = &u.u_nd; 70437741Smckusick register struct vnode *vp; 70537741Smckusick struct iovec aiov; 70637741Smckusick struct uio auio; 70737741Smckusick int error; 7085992Swnj 70937741Smckusick ndp->ni_nameiop = LOOKUP | LOCKLEAF; 71016694Smckusick ndp->ni_segflg = UIO_USERSPACE; 71116694Smckusick ndp->ni_dirp = uap->name; 71237741Smckusick if (error = namei(ndp)) 71337741Smckusick RETURN (error); 71437741Smckusick vp = ndp->ni_vp; 71537741Smckusick if (vp->v_type != VLNK) { 71637741Smckusick error = EINVAL; 7175992Swnj goto out; 7185992Swnj } 71937741Smckusick aiov.iov_base = uap->buf; 72037741Smckusick aiov.iov_len = uap->count; 72137741Smckusick auio.uio_iov = &aiov; 72237741Smckusick auio.uio_iovcnt = 1; 72337741Smckusick auio.uio_offset = 0; 72437741Smckusick auio.uio_rw = UIO_READ; 72537741Smckusick auio.uio_segflg = UIO_USERSPACE; 72637741Smckusick auio.uio_resid = uap->count; 72737741Smckusick error = VOP_READLINK(vp, &auio, ndp->ni_cred); 7285992Swnj out: 72937741Smckusick vput(vp); 73037741Smckusick u.u_r.r_val1 = uap->count - auio.uio_resid; 73137741Smckusick RETURN (error); 7325992Swnj } 7335992Swnj 7349167Ssam /* 73538259Smckusick * Change flags of a file given path name. 73638259Smckusick */ 73738259Smckusick chflags() 73838259Smckusick { 73938259Smckusick struct a { 74038259Smckusick char *fname; 74138259Smckusick int flags; 74238259Smckusick } *uap = (struct a *)u.u_ap; 74338259Smckusick register struct nameidata *ndp = &u.u_nd; 74438259Smckusick register struct vnode *vp; 74538259Smckusick struct vattr vattr; 74638259Smckusick int error; 74738259Smckusick 74838259Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 74938259Smckusick ndp->ni_segflg = UIO_USERSPACE; 75038259Smckusick ndp->ni_dirp = uap->fname; 75138259Smckusick vattr_null(&vattr); 75238259Smckusick vattr.va_flags = uap->flags; 75338259Smckusick if (error = namei(ndp)) 75438259Smckusick RETURN (error); 75538259Smckusick vp = ndp->ni_vp; 75638259Smckusick if (vp->v_mount->m_flag & M_RDONLY) { 75738259Smckusick error = EROFS; 75838259Smckusick goto out; 75938259Smckusick } 76038259Smckusick error = VOP_SETATTR(vp, &vattr, ndp->ni_cred); 76138259Smckusick out: 76238259Smckusick vput(vp); 76338259Smckusick RETURN (error); 76438259Smckusick } 76538259Smckusick 76638259Smckusick /* 76738259Smckusick * Change flags of a file given a file descriptor. 76838259Smckusick */ 76938259Smckusick fchflags() 77038259Smckusick { 77138259Smckusick struct a { 77238259Smckusick int fd; 77338259Smckusick int flags; 77438259Smckusick } *uap = (struct a *)u.u_ap; 77538259Smckusick struct vattr vattr; 77638259Smckusick struct vnode *vp; 77738259Smckusick struct file *fp; 77838259Smckusick int error; 77938259Smckusick 78038259Smckusick if (error = getvnode(uap->fd, &fp)) 78138259Smckusick RETURN (error); 78238259Smckusick vattr_null(&vattr); 78338259Smckusick vattr.va_flags = uap->flags; 78438259Smckusick vp = (struct vnode *)fp->f_data; 78538259Smckusick VOP_LOCK(vp); 78638259Smckusick if (vp->v_mount->m_flag & M_RDONLY) { 78738259Smckusick error = EROFS; 78838259Smckusick goto out; 78938259Smckusick } 79038259Smckusick error = VOP_SETATTR(vp, &vattr, fp->f_cred); 79138259Smckusick out: 79238259Smckusick VOP_UNLOCK(vp); 79338259Smckusick RETURN (error); 79438259Smckusick } 79538259Smckusick 79638259Smckusick /* 7979167Ssam * Change mode of a file given path name. 7989167Ssam */ 7996254Sroot chmod() 8005992Swnj { 8017701Ssam struct a { 8026254Sroot char *fname; 8036254Sroot int fmode; 80416694Smckusick } *uap = (struct a *)u.u_ap; 80537741Smckusick register struct nameidata *ndp = &u.u_nd; 80637741Smckusick register struct vnode *vp; 80737741Smckusick struct vattr vattr; 80837741Smckusick int error; 8095992Swnj 81037741Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 81137741Smckusick ndp->ni_segflg = UIO_USERSPACE; 81237741Smckusick ndp->ni_dirp = uap->fname; 81337741Smckusick vattr_null(&vattr); 81437741Smckusick vattr.va_mode = uap->fmode & 07777; 81537741Smckusick if (error = namei(ndp)) 81637741Smckusick RETURN (error); 81737741Smckusick vp = ndp->ni_vp; 81837741Smckusick if (vp->v_mount->m_flag & M_RDONLY) { 81937741Smckusick error = EROFS; 82037741Smckusick goto out; 82137741Smckusick } 82237741Smckusick error = VOP_SETATTR(vp, &vattr, ndp->ni_cred); 82337741Smckusick out: 82437741Smckusick vput(vp); 82537741Smckusick RETURN (error); 8267701Ssam } 8277439Sroot 8289167Ssam /* 8299167Ssam * Change mode of a file given a file descriptor. 8309167Ssam */ 8317701Ssam fchmod() 8327701Ssam { 8337701Ssam struct a { 8347701Ssam int fd; 8357701Ssam int fmode; 83616694Smckusick } *uap = (struct a *)u.u_ap; 83737741Smckusick struct vattr vattr; 83837741Smckusick struct vnode *vp; 83937741Smckusick struct file *fp; 84037741Smckusick int error; 8417701Ssam 84237741Smckusick if (error = getvnode(uap->fd, &fp)) 84337741Smckusick RETURN (error); 84437741Smckusick vattr_null(&vattr); 84537741Smckusick vattr.va_mode = uap->fmode & 07777; 84637741Smckusick vp = (struct vnode *)fp->f_data; 84737741Smckusick VOP_LOCK(vp); 84837741Smckusick if (vp->v_mount->m_flag & M_RDONLY) { 84937741Smckusick error = EROFS; 85037741Smckusick goto out; 8517439Sroot } 85237741Smckusick error = VOP_SETATTR(vp, &vattr, fp->f_cred); 85337741Smckusick out: 85437741Smckusick VOP_UNLOCK(vp); 85537741Smckusick RETURN (error); 8565992Swnj } 8575992Swnj 8589167Ssam /* 8599167Ssam * Set ownership given a path name. 8609167Ssam */ 8616254Sroot chown() 86237Sbill { 8637701Ssam struct a { 8646254Sroot char *fname; 8656254Sroot int uid; 8666254Sroot int gid; 86716694Smckusick } *uap = (struct a *)u.u_ap; 86836614Sbostic register struct nameidata *ndp = &u.u_nd; 86937741Smckusick register struct vnode *vp; 87037741Smckusick struct vattr vattr; 87137741Smckusick int error; 87237Sbill 87337741Smckusick ndp->ni_nameiop = LOOKUP | NOFOLLOW | LOCKLEAF; 87436614Sbostic ndp->ni_segflg = UIO_USERSPACE; 87536614Sbostic ndp->ni_dirp = uap->fname; 87637741Smckusick vattr_null(&vattr); 87737741Smckusick vattr.va_uid = uap->uid; 87837741Smckusick vattr.va_gid = uap->gid; 87937741Smckusick if (error = namei(ndp)) 88037741Smckusick RETURN (error); 88137741Smckusick vp = ndp->ni_vp; 88237741Smckusick if (vp->v_mount->m_flag & M_RDONLY) { 88337741Smckusick error = EROFS; 88437741Smckusick goto out; 88537741Smckusick } 88637741Smckusick error = VOP_SETATTR(vp, &vattr, ndp->ni_cred); 88737741Smckusick out: 88837741Smckusick vput(vp); 88937741Smckusick RETURN (error); 8907701Ssam } 8917439Sroot 8929167Ssam /* 8939167Ssam * Set ownership given a file descriptor. 8949167Ssam */ 8957701Ssam fchown() 8967701Ssam { 8977701Ssam struct a { 8987701Ssam int fd; 8997701Ssam int uid; 9007701Ssam int gid; 90116694Smckusick } *uap = (struct a *)u.u_ap; 90237741Smckusick struct vattr vattr; 90337741Smckusick struct vnode *vp; 90437741Smckusick struct file *fp; 90537741Smckusick int error; 9067701Ssam 90737741Smckusick if (error = getvnode(uap->fd, &fp)) 90837741Smckusick RETURN (error); 90937741Smckusick vattr_null(&vattr); 91037741Smckusick vattr.va_uid = uap->uid; 91137741Smckusick vattr.va_gid = uap->gid; 91237741Smckusick vp = (struct vnode *)fp->f_data; 91337741Smckusick VOP_LOCK(vp); 91437741Smckusick if (vp->v_mount->m_flag & M_RDONLY) { 91537741Smckusick error = EROFS; 91637741Smckusick goto out; 91737741Smckusick } 91837741Smckusick error = VOP_SETATTR(vp, &vattr, fp->f_cred); 91937741Smckusick out: 92037741Smckusick VOP_UNLOCK(vp); 92137741Smckusick RETURN (error); 9227701Ssam } 9237701Ssam 92411811Ssam utimes() 92511811Ssam { 92611811Ssam register struct a { 92711811Ssam char *fname; 92811811Ssam struct timeval *tptr; 92911811Ssam } *uap = (struct a *)u.u_ap; 93037741Smckusick register struct nameidata *ndp = &u.u_nd; 93137741Smckusick register struct vnode *vp; 93211811Ssam struct timeval tv[2]; 93337741Smckusick struct vattr vattr; 93437741Smckusick int error; 93511811Ssam 93637741Smckusick if (error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv))) 93737741Smckusick RETURN (error); 93837741Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 93937741Smckusick ndp->ni_segflg = UIO_USERSPACE; 94037741Smckusick ndp->ni_dirp = uap->fname; 94137741Smckusick vattr_null(&vattr); 94237741Smckusick vattr.va_atime = tv[0]; 94337741Smckusick vattr.va_mtime = tv[1]; 94437741Smckusick if (error = namei(ndp)) 94537741Smckusick RETURN (error); 94637741Smckusick vp = ndp->ni_vp; 94737741Smckusick if (vp->v_mount->m_flag & M_RDONLY) { 94837741Smckusick error = EROFS; 94937741Smckusick goto out; 95021015Smckusick } 95137741Smckusick error = VOP_SETATTR(vp, &vattr, ndp->ni_cred); 95237741Smckusick out: 95337741Smckusick vput(vp); 95437741Smckusick RETURN (error); 95511811Ssam } 95611811Ssam 9579167Ssam /* 9589167Ssam * Truncate a file given its path name. 9599167Ssam */ 9607701Ssam truncate() 9617701Ssam { 9627701Ssam struct a { 9637701Ssam char *fname; 96426473Skarels off_t length; 9657826Sroot } *uap = (struct a *)u.u_ap; 96616694Smckusick register struct nameidata *ndp = &u.u_nd; 96737741Smckusick register struct vnode *vp; 96837741Smckusick struct vattr vattr; 96937741Smckusick int error; 9707701Ssam 97137741Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 97216694Smckusick ndp->ni_segflg = UIO_USERSPACE; 97316694Smckusick ndp->ni_dirp = uap->fname; 97437741Smckusick vattr_null(&vattr); 97537741Smckusick vattr.va_size = uap->length; 97637741Smckusick if (error = namei(ndp)) 97737741Smckusick RETURN (error); 97837741Smckusick vp = ndp->ni_vp; 97937741Smckusick if (vp->v_type == VDIR) { 98037741Smckusick error = EISDIR; 98137741Smckusick goto out; 9827701Ssam } 98337741Smckusick if (error = vn_access(vp, VWRITE, ndp->ni_cred)) 98437741Smckusick goto out; 98537741Smckusick error = VOP_SETATTR(vp, &vattr, ndp->ni_cred); 98637741Smckusick out: 98737741Smckusick vput(vp); 98837741Smckusick RETURN (error); 9897701Ssam } 9907701Ssam 9919167Ssam /* 9929167Ssam * Truncate a file given a file descriptor. 9939167Ssam */ 9947701Ssam ftruncate() 9957701Ssam { 9967701Ssam struct a { 9977701Ssam int fd; 99826473Skarels off_t length; 9997826Sroot } *uap = (struct a *)u.u_ap; 100037741Smckusick struct vattr vattr; 100137741Smckusick struct vnode *vp; 10027701Ssam struct file *fp; 100337741Smckusick int error; 10047701Ssam 100537741Smckusick if (error = getvnode(uap->fd, &fp)) 100637741Smckusick RETURN (error); 100737741Smckusick if ((fp->f_flag & FWRITE) == 0) 100837741Smckusick RETURN (EINVAL); 100937741Smckusick vattr_null(&vattr); 101037741Smckusick vattr.va_size = uap->length; 101137741Smckusick vp = (struct vnode *)fp->f_data; 101237741Smckusick VOP_LOCK(vp); 101337741Smckusick if (vp->v_type == VDIR) { 101437741Smckusick error = EISDIR; 101537741Smckusick goto out; 10167701Ssam } 101737741Smckusick if (error = vn_access(vp, VWRITE, fp->f_cred)) 101837741Smckusick goto out; 101937741Smckusick error = VOP_SETATTR(vp, &vattr, fp->f_cred); 102037741Smckusick out: 102137741Smckusick VOP_UNLOCK(vp); 102237741Smckusick RETURN (error); 10237701Ssam } 10247701Ssam 10259167Ssam /* 10269167Ssam * Synch an open file. 10279167Ssam */ 10289167Ssam fsync() 10299167Ssam { 10309167Ssam struct a { 10319167Ssam int fd; 10329167Ssam } *uap = (struct a *)u.u_ap; 10339167Ssam struct file *fp; 103437741Smckusick int error; 10359167Ssam 103637741Smckusick if (error = getvnode(uap->fd, &fp)) 103737741Smckusick RETURN (error); 103837741Smckusick error = VOP_FSYNC((struct vnode *)fp->f_data, fp->f_flag, fp->f_cred); 103937741Smckusick RETURN (error); 10409167Ssam } 10419167Ssam 10429167Ssam /* 10439167Ssam * Rename system call. 10449167Ssam * 10459167Ssam * Source and destination must either both be directories, or both 10469167Ssam * not be directories. If target is a directory, it must be empty. 10479167Ssam */ 10487701Ssam rename() 10497701Ssam { 10507701Ssam struct a { 10517701Ssam char *from; 10527701Ssam char *to; 105316694Smckusick } *uap = (struct a *)u.u_ap; 105437741Smckusick register struct vnode *tvp, *fvp, *tdvp; 105516694Smckusick register struct nameidata *ndp = &u.u_nd; 105637741Smckusick struct nameidata tond; 105737741Smckusick int error; 10587701Ssam 105937741Smckusick ndp->ni_nameiop = DELETE | WANTPARENT; 106016694Smckusick ndp->ni_segflg = UIO_USERSPACE; 106116694Smckusick ndp->ni_dirp = uap->from; 106237741Smckusick if (error = namei(ndp)) 106337741Smckusick RETURN (error); 106437741Smckusick fvp = ndp->ni_vp; 1065*38266Smckusick nddup(ndp, &tond); 106637741Smckusick tond.ni_nameiop = RENAME | LOCKPARENT | LOCKLEAF | NOCACHE; 106737741Smckusick tond.ni_segflg = UIO_USERSPACE; 106837741Smckusick tond.ni_dirp = uap->to; 106937741Smckusick error = namei(&tond); 107037741Smckusick tdvp = tond.ni_dvp; 107137741Smckusick tvp = tond.ni_vp; 107237741Smckusick if (tvp != NULL) { 107337741Smckusick if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 107437741Smckusick error = EISDIR; 107537741Smckusick goto out; 107637741Smckusick } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 107737741Smckusick error = ENOTDIR; 107837741Smckusick goto out; 10799167Ssam } 10809167Ssam } 108137741Smckusick if (error) { 108237741Smckusick VOP_ABORTOP(ndp); 108337741Smckusick goto out1; 108437741Smckusick } 108537741Smckusick if (fvp->v_mount != tdvp->v_mount) { 108637741Smckusick error = EXDEV; 10879167Ssam goto out; 108810051Ssam } 108937741Smckusick if (fvp == tdvp || fvp == tvp) 109037741Smckusick error = EINVAL; 109137741Smckusick out: 109237741Smckusick if (error) { 109337741Smckusick VOP_ABORTOP(&tond); 109437741Smckusick VOP_ABORTOP(ndp); 10959167Ssam } else { 109637741Smckusick error = VOP_RENAME(ndp, &tond); 10979167Ssam } 109837741Smckusick out1: 1099*38266Smckusick ndrele(&tond); 110037741Smckusick RETURN (error); 11017701Ssam } 11027701Ssam 11037535Sroot /* 110412756Ssam * Mkdir system call 110512756Ssam */ 110612756Ssam mkdir() 110712756Ssam { 110812756Ssam struct a { 110912756Ssam char *name; 111012756Ssam int dmode; 111116694Smckusick } *uap = (struct a *)u.u_ap; 111216694Smckusick register struct nameidata *ndp = &u.u_nd; 111337741Smckusick register struct vnode *vp; 111437741Smckusick struct vattr vattr; 111537741Smckusick int error; 111612756Ssam 111737741Smckusick ndp->ni_nameiop = CREATE | LOCKPARENT; 111816694Smckusick ndp->ni_segflg = UIO_USERSPACE; 111916694Smckusick ndp->ni_dirp = uap->name; 112037741Smckusick if (error = namei(ndp)) 112137741Smckusick RETURN (error); 112237741Smckusick vp = ndp->ni_vp; 112337741Smckusick if (vp != NULL) { 112437741Smckusick VOP_ABORTOP(ndp); 112537741Smckusick RETURN (EEXIST); 112612756Ssam } 112737741Smckusick vattr_null(&vattr); 112837741Smckusick vattr.va_type = VDIR; 112937741Smckusick vattr.va_mode = (uap->dmode & 0777) &~ u.u_cmask; 113037741Smckusick error = VOP_MKDIR(ndp, &vattr); 113138145Smckusick if (!error) 113238145Smckusick vput(ndp->ni_vp); 113337741Smckusick RETURN (error); 113412756Ssam } 113512756Ssam 113612756Ssam /* 113712756Ssam * Rmdir system call. 113812756Ssam */ 113912756Ssam rmdir() 114012756Ssam { 114112756Ssam struct a { 114212756Ssam char *name; 114316694Smckusick } *uap = (struct a *)u.u_ap; 114416694Smckusick register struct nameidata *ndp = &u.u_nd; 114537741Smckusick register struct vnode *vp; 114637741Smckusick int error; 114712756Ssam 114837741Smckusick ndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF; 114916694Smckusick ndp->ni_segflg = UIO_USERSPACE; 115016694Smckusick ndp->ni_dirp = uap->name; 115137741Smckusick if (error = namei(ndp)) 115237741Smckusick RETURN (error); 115337741Smckusick vp = ndp->ni_vp; 115437741Smckusick if (vp->v_type != VDIR) { 115537741Smckusick error = ENOTDIR; 115612756Ssam goto out; 115712756Ssam } 115812756Ssam /* 115937741Smckusick * No rmdir "." please. 116012756Ssam */ 116137741Smckusick if (ndp->ni_dvp == vp) { 116237741Smckusick error = EINVAL; 116312756Ssam goto out; 116412756Ssam } 116512756Ssam /* 116637741Smckusick * Don't unlink a mounted file. 116712756Ssam */ 116837741Smckusick if (vp->v_flag & VROOT) 116937741Smckusick error = EBUSY; 117012756Ssam out: 117137741Smckusick if (error) 117237741Smckusick VOP_ABORTOP(ndp); 117337741Smckusick else 117437741Smckusick error = VOP_RMDIR(ndp); 117537741Smckusick RETURN (error); 117612756Ssam } 117712756Ssam 117837741Smckusick /* 117937741Smckusick * Read a block of directory entries in a file system independent format 118037741Smckusick */ 118137741Smckusick getdirentries() 118212756Ssam { 118337741Smckusick register struct a { 118437741Smckusick int fd; 118537741Smckusick char *buf; 118637741Smckusick unsigned count; 118737741Smckusick long *basep; 118837741Smckusick } *uap = (struct a *)u.u_ap; 118916540Ssam struct file *fp; 119037741Smckusick struct uio auio; 119137741Smckusick struct iovec aiov; 119238129Smckusick off_t off; 119337741Smckusick int error; 119412756Ssam 119537741Smckusick if (error = getvnode(uap->fd, &fp)) 119637741Smckusick RETURN (error); 119737741Smckusick if ((fp->f_flag & FREAD) == 0) 119837741Smckusick RETURN (EBADF); 119937741Smckusick aiov.iov_base = uap->buf; 120037741Smckusick aiov.iov_len = uap->count; 120137741Smckusick auio.uio_iov = &aiov; 120237741Smckusick auio.uio_iovcnt = 1; 120337741Smckusick auio.uio_rw = UIO_READ; 120437741Smckusick auio.uio_segflg = UIO_USERSPACE; 120537741Smckusick auio.uio_resid = uap->count; 120638129Smckusick off = fp->f_offset; 120737741Smckusick if (error = VOP_READDIR((struct vnode *)fp->f_data, &auio, 120837741Smckusick &(fp->f_offset), fp->f_cred)) 120937741Smckusick RETURN (error); 121038129Smckusick error = copyout((caddr_t)&off, (caddr_t)uap->basep, 121137741Smckusick sizeof(long)); 121237741Smckusick u.u_r.r_val1 = uap->count - auio.uio_resid; 121337741Smckusick RETURN (error); 121412756Ssam } 121512756Ssam 121612756Ssam /* 121712756Ssam * mode mask for creation of files 121812756Ssam */ 121912756Ssam umask() 122012756Ssam { 122112756Ssam register struct a { 122212756Ssam int mask; 122316694Smckusick } *uap = (struct a *)u.u_ap; 122412756Ssam 122512756Ssam u.u_r.r_val1 = u.u_cmask; 122612756Ssam u.u_cmask = uap->mask & 07777; 122737741Smckusick RETURN (0); 122812756Ssam } 122937741Smckusick 123037741Smckusick getvnode(fdes, fpp) 123137741Smckusick struct file **fpp; 123237741Smckusick int fdes; 123337741Smckusick { 123437741Smckusick struct file *fp; 123537741Smckusick 123637741Smckusick if ((unsigned)fdes >= NOFILE || (fp = u.u_ofile[fdes]) == NULL) 123737741Smckusick return (EBADF); 123837741Smckusick if (fp->f_type != DTYPE_VNODE) 123937741Smckusick return (EINVAL); 124037741Smckusick *fpp = fp; 124137741Smckusick return (0); 124237741Smckusick } 1243