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*38129Smckusick * @(#)vfs_syscalls.c 7.8 (Berkeley) 05/25/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 /* 22737741Smckusick * Change current working directory (``.''). 22837741Smckusick */ 22937741Smckusick chdir() 23037741Smckusick { 23137741Smckusick struct a { 2326254Sroot char *fname; 23316694Smckusick } *uap = (struct a *)u.u_ap; 23416694Smckusick register struct nameidata *ndp = &u.u_nd; 23537741Smckusick int error; 2366254Sroot 23737741Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 23816694Smckusick ndp->ni_segflg = UIO_USERSPACE; 23916694Smckusick ndp->ni_dirp = uap->fname; 24037741Smckusick if (error = chdirec(ndp)) 24137741Smckusick RETURN (error); 24237741Smckusick vrele(u.u_cdir); 24337741Smckusick u.u_cdir = ndp->ni_vp; 24437741Smckusick RETURN (0); 24537741Smckusick } 2466254Sroot 24737741Smckusick /* 24837741Smckusick * Change notion of root (``/'') directory. 24937741Smckusick */ 25037741Smckusick chroot() 25137741Smckusick { 25237741Smckusick struct a { 25337741Smckusick char *fname; 25437741Smckusick } *uap = (struct a *)u.u_ap; 25537741Smckusick register struct nameidata *ndp = &u.u_nd; 25637741Smckusick int error; 25737741Smckusick 25837741Smckusick if (error = suser(u.u_cred, &u.u_acflag)) 25937741Smckusick RETURN (error); 26037741Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 26137741Smckusick ndp->ni_segflg = UIO_USERSPACE; 26237741Smckusick ndp->ni_dirp = uap->fname; 26337741Smckusick if (error = chdirec(ndp)) 26437741Smckusick RETURN (error); 26537741Smckusick vrele(u.u_rdir); 26637741Smckusick u.u_rdir = ndp->ni_vp; 26737741Smckusick RETURN (0); 2686254Sroot } 2696254Sroot 27037Sbill /* 27137741Smckusick * Common routine for chroot and chdir. 27237741Smckusick */ 27337741Smckusick chdirec(ndp) 27437741Smckusick register struct nameidata *ndp; 27537741Smckusick { 27637741Smckusick struct vnode *vp; 27737741Smckusick int error; 27837741Smckusick 27937741Smckusick if (error = namei(ndp)) 28037741Smckusick return (error); 28137741Smckusick vp = ndp->ni_vp; 28237741Smckusick if (vp->v_type != VDIR) 28337741Smckusick error = ENOTDIR; 28437741Smckusick else 28537741Smckusick error = vn_access(vp, VEXEC, ndp->ni_cred); 28637741Smckusick VOP_UNLOCK(vp); 28737741Smckusick if (error) 28837741Smckusick vrele(vp); 28937741Smckusick return (error); 29037741Smckusick } 29137741Smckusick 29237741Smckusick /* 2936254Sroot * Open system call. 2946254Sroot */ 2956254Sroot open() 2966254Sroot { 29712756Ssam struct a { 2986254Sroot char *fname; 2997701Ssam int mode; 30012756Ssam int crtmode; 30112756Ssam } *uap = (struct a *) u.u_ap; 30237741Smckusick struct nameidata *ndp = &u.u_nd; 3036254Sroot 30437741Smckusick ndp->ni_segflg = UIO_USERSPACE; 30537741Smckusick ndp->ni_dirp = uap->fname; 30637741Smckusick RETURN (copen(uap->mode-FOPEN, uap->crtmode &~ u.u_cmask, ndp, 30737741Smckusick &u.u_r.r_val1)); 3086254Sroot } 3096254Sroot 3106254Sroot /* 3116254Sroot * Creat system call. 3126254Sroot */ 31312756Ssam creat() 3146254Sroot { 31512756Ssam struct a { 3166254Sroot char *fname; 3176254Sroot int fmode; 31812756Ssam } *uap = (struct a *)u.u_ap; 31937741Smckusick struct nameidata *ndp = &u.u_nd; 3206254Sroot 32137741Smckusick ndp->ni_segflg = UIO_USERSPACE; 32237741Smckusick ndp->ni_dirp = uap->fname; 32337741Smckusick RETURN (copen(FWRITE|FCREAT|FTRUNC, uap->fmode &~ u.u_cmask, ndp, 32437741Smckusick &u.u_r.r_val1)); 3256254Sroot } 3266254Sroot 3276254Sroot /* 3286254Sroot * Common code for open and creat. 32912756Ssam * Check permissions, allocate an open file structure, 33012756Ssam * and call the device open routine if any. 3316254Sroot */ 33237741Smckusick copen(fmode, cmode, ndp, resultfd) 33337741Smckusick int fmode, cmode; 33437741Smckusick struct nameidata *ndp; 33537741Smckusick int *resultfd; 33612756Ssam { 3376254Sroot register struct file *fp; 33837741Smckusick struct file *nfp; 33937741Smckusick int indx, error; 34037741Smckusick extern struct fileops vnops; 3416254Sroot 34237741Smckusick if (error = falloc(&nfp, &indx)) 34337741Smckusick return (error); 34437741Smckusick fp = nfp; 34537741Smckusick u.u_r.r_val1 = indx; /* XXX for fdopen() */ 34637741Smckusick if (error = vn_open(ndp, fmode, (cmode & 07777) &~ ISVTX)) { 34724543Smckusick u.u_ofile[indx] = NULL; 34837741Smckusick crfree(fp->f_cred); 34937741Smckusick fp->f_count--; 35037741Smckusick return (error); 35112756Ssam } 35237741Smckusick fp->f_flag = fmode & FMASK; 35337741Smckusick fp->f_type = DTYPE_VNODE; 35437741Smckusick fp->f_ops = &vnops; 35537741Smckusick fp->f_data = (caddr_t)ndp->ni_vp; 35637741Smckusick if (resultfd) 35737741Smckusick *resultfd = indx; 35837741Smckusick return (0); 3596254Sroot } 3606254Sroot 3616254Sroot /* 3626254Sroot * Mknod system call 3636254Sroot */ 3646254Sroot mknod() 3656254Sroot { 3666254Sroot register struct a { 3676254Sroot char *fname; 3686254Sroot int fmode; 3696254Sroot int dev; 37016694Smckusick } *uap = (struct a *)u.u_ap; 37116694Smckusick register struct nameidata *ndp = &u.u_nd; 37237741Smckusick register struct vnode *vp; 37337741Smckusick struct vattr vattr; 37437741Smckusick int error; 3756254Sroot 37637741Smckusick if (error = suser(u.u_cred, &u.u_acflag)) 37737741Smckusick RETURN (error); 37837741Smckusick ndp->ni_nameiop = CREATE | LOCKPARENT; 37916694Smckusick ndp->ni_segflg = UIO_USERSPACE; 38016694Smckusick ndp->ni_dirp = uap->fname; 38137741Smckusick if (error = namei(ndp)) 38237741Smckusick RETURN (error); 38337741Smckusick vp = ndp->ni_vp; 38437741Smckusick if (vp != NULL) { 38537741Smckusick error = EEXIST; 38612756Ssam goto out; 3876254Sroot } 38837741Smckusick vattr_null(&vattr); 38937741Smckusick switch (uap->fmode & IFMT) { 39012756Ssam 39115093Smckusick case IFMT: /* used by badsect to flag bad sectors */ 39237741Smckusick vattr.va_type = VBAD; 39337741Smckusick break; 39412756Ssam case IFCHR: 39537741Smckusick vattr.va_type = VCHR; 39637741Smckusick break; 39712756Ssam case IFBLK: 39837741Smckusick vattr.va_type = VBLK; 39937741Smckusick break; 40037741Smckusick default: 40137741Smckusick error = EINVAL; 40237741Smckusick goto out; 4036254Sroot } 40437741Smckusick vattr.va_mode = (uap->fmode & 07777) &~ u.u_cmask; 40537741Smckusick vattr.va_rdev = uap->dev; 4066254Sroot out: 40737741Smckusick if (error) 40837741Smckusick VOP_ABORTOP(ndp); 40937741Smckusick else 41037741Smckusick error = VOP_MKNOD(ndp, &vattr, ndp->ni_cred); 41137741Smckusick RETURN (error); 4126254Sroot } 4136254Sroot 4146254Sroot /* 4156254Sroot * link system call 4166254Sroot */ 4176254Sroot link() 4186254Sroot { 4196254Sroot register struct a { 4206254Sroot char *target; 4216254Sroot char *linkname; 42216694Smckusick } *uap = (struct a *)u.u_ap; 42316694Smckusick register struct nameidata *ndp = &u.u_nd; 42437741Smckusick register struct vnode *vp, *xp; 42537741Smckusick int error; 4266254Sroot 42716694Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW; 42816694Smckusick ndp->ni_segflg = UIO_USERSPACE; 42916694Smckusick ndp->ni_dirp = uap->target; 43037741Smckusick if (error = namei(ndp)) 43137741Smckusick RETURN (error); 43237741Smckusick vp = ndp->ni_vp; 43337741Smckusick if (vp->v_type == VDIR && 43437741Smckusick (error = suser(u.u_cred, &u.u_acflag))) 43537741Smckusick goto out1; 43637741Smckusick ndp->ni_nameiop = CREATE | LOCKPARENT; 43716694Smckusick ndp->ni_dirp = (caddr_t)uap->linkname; 43837741Smckusick if (error = namei(ndp)) 43937741Smckusick goto out1; 44037741Smckusick xp = ndp->ni_vp; 4416254Sroot if (xp != NULL) { 44237741Smckusick error = EEXIST; 4436254Sroot goto out; 4446254Sroot } 44537741Smckusick xp = ndp->ni_dvp; 44637741Smckusick if (vp->v_mount != xp->v_mount) 44737741Smckusick error = EXDEV; 4486254Sroot out: 44937741Smckusick if (error) 45037741Smckusick VOP_ABORTOP(ndp); 45137741Smckusick else 45237741Smckusick error = VOP_LINK(vp, ndp); 45337741Smckusick out1: 45437741Smckusick vrele(vp); 45537741Smckusick RETURN (error); 4566254Sroot } 4576254Sroot 4586254Sroot /* 4596254Sroot * symlink -- make a symbolic link 4606254Sroot */ 4616254Sroot symlink() 4626254Sroot { 46337741Smckusick struct a { 4646254Sroot char *target; 4656254Sroot char *linkname; 46616694Smckusick } *uap = (struct a *)u.u_ap; 46716694Smckusick register struct nameidata *ndp = &u.u_nd; 46837741Smckusick register struct vnode *vp; 46937741Smckusick struct vattr vattr; 47037741Smckusick char *target; 47137741Smckusick int error; 4726254Sroot 47316694Smckusick ndp->ni_segflg = UIO_USERSPACE; 47416694Smckusick ndp->ni_dirp = uap->linkname; 47537741Smckusick MALLOC(target, char *, MAXPATHLEN, M_NAMEI, M_WAITOK); 47637741Smckusick if (error = copyinstr(uap->target, target, MAXPATHLEN, (u_int *)0)) 47737741Smckusick goto out1; 47837741Smckusick ndp->ni_nameiop = CREATE | LOCKPARENT; 47937741Smckusick if (error = namei(ndp)) 48037741Smckusick goto out1; 48137741Smckusick vp = ndp->ni_vp; 48237741Smckusick if (vp) { 48337741Smckusick error = EEXIST; 48437741Smckusick goto out; 4856254Sroot } 48637741Smckusick vp = ndp->ni_dvp; 48737741Smckusick vattr_null(&vattr); 48837741Smckusick vattr.va_mode = 0777 &~ u.u_cmask; 48937741Smckusick out: 49037741Smckusick if (error) 49137741Smckusick VOP_ABORTOP(ndp); 49237741Smckusick else 49337741Smckusick error = VOP_SYMLINK(ndp, &vattr, target); 49437741Smckusick out1: 49537741Smckusick FREE(target, M_NAMEI); 49637741Smckusick RETURN (error); 4976254Sroot } 4986254Sroot 4996254Sroot /* 5006254Sroot * Unlink system call. 5016254Sroot * Hard to avoid races here, especially 5026254Sroot * in unlinking directories. 5036254Sroot */ 5046254Sroot unlink() 5056254Sroot { 5066254Sroot struct a { 5076254Sroot char *fname; 50816694Smckusick } *uap = (struct a *)u.u_ap; 50916694Smckusick register struct nameidata *ndp = &u.u_nd; 51037741Smckusick register struct vnode *vp; 51137741Smckusick int error; 5126254Sroot 51337741Smckusick ndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF; 51416694Smckusick ndp->ni_segflg = UIO_USERSPACE; 51516694Smckusick ndp->ni_dirp = uap->fname; 51637741Smckusick if (error = namei(ndp)) 51737741Smckusick RETURN (error); 51837741Smckusick vp = ndp->ni_vp; 51937741Smckusick if (vp->v_type == VDIR && 52037741Smckusick (error = suser(u.u_cred, &u.u_acflag))) 5216254Sroot goto out; 5226254Sroot /* 5236254Sroot * Don't unlink a mounted file. 5246254Sroot */ 52537741Smckusick if (vp->v_flag & VROOT) { 52637741Smckusick error = EBUSY; 5276254Sroot goto out; 5286254Sroot } 52937741Smckusick if (vp->v_flag & VTEXT) 53037741Smckusick xrele(vp); /* try once to free text */ 5316254Sroot out: 53237741Smckusick if (error) 53337741Smckusick VOP_ABORTOP(ndp); 5347142Smckusick else 53537741Smckusick error = VOP_REMOVE(ndp); 53637741Smckusick RETURN (error); 5376254Sroot } 5386254Sroot 5396254Sroot /* 5406254Sroot * Seek system call 5416254Sroot */ 5428040Sroot lseek() 5436254Sroot { 5446254Sroot register struct file *fp; 5456254Sroot register struct a { 54637741Smckusick int fdes; 5476254Sroot off_t off; 5486254Sroot int sbase; 54916694Smckusick } *uap = (struct a *)u.u_ap; 55037741Smckusick struct vattr vattr; 55137741Smckusick int error; 5526254Sroot 55337741Smckusick if ((unsigned)uap->fdes >= NOFILE || 55437741Smckusick (fp = u.u_ofile[uap->fdes]) == NULL) 55537741Smckusick RETURN (EBADF); 55637741Smckusick if (fp->f_type != DTYPE_VNODE) 55737741Smckusick RETURN (ESPIPE); 55813878Ssam switch (uap->sbase) { 55913878Ssam 56013878Ssam case L_INCR: 56113878Ssam fp->f_offset += uap->off; 56213878Ssam break; 56313878Ssam 56413878Ssam case L_XTND: 56537741Smckusick if (error = VOP_GETATTR((struct vnode *)fp->f_data, 56637741Smckusick &vattr, u.u_cred)) 56737741Smckusick RETURN (error); 56837741Smckusick fp->f_offset = uap->off + vattr.va_size; 56913878Ssam break; 57013878Ssam 57113878Ssam case L_SET: 57213878Ssam fp->f_offset = uap->off; 57313878Ssam break; 57413878Ssam 57513878Ssam default: 57637741Smckusick RETURN (EINVAL); 57713878Ssam } 57813878Ssam u.u_r.r_off = fp->f_offset; 57937741Smckusick RETURN (0); 5806254Sroot } 5816254Sroot 5826254Sroot /* 5836254Sroot * Access system call 5846254Sroot */ 5856254Sroot saccess() 5866254Sroot { 5876254Sroot register struct a { 5886254Sroot char *fname; 5896254Sroot int fmode; 59016694Smckusick } *uap = (struct a *)u.u_ap; 59116694Smckusick register struct nameidata *ndp = &u.u_nd; 59237741Smckusick register struct vnode *vp; 59337741Smckusick int error, mode, svuid, svgid; 5946254Sroot 5956254Sroot svuid = u.u_uid; 5966254Sroot svgid = u.u_gid; 5976254Sroot u.u_uid = u.u_ruid; 5986254Sroot u.u_gid = u.u_rgid; 59937741Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 60016694Smckusick ndp->ni_segflg = UIO_USERSPACE; 60116694Smckusick ndp->ni_dirp = uap->fname; 60237741Smckusick if (error = namei(ndp)) 60337741Smckusick goto out1; 60437741Smckusick vp = ndp->ni_vp; 60537741Smckusick /* 60637741Smckusick * fmode == 0 means only check for exist 60737741Smckusick */ 60837741Smckusick if (uap->fmode) { 60937741Smckusick mode = 0; 61037741Smckusick if (uap->fmode & R_OK) 61137741Smckusick mode |= VREAD; 61237741Smckusick if (uap->fmode & W_OK) 61337741Smckusick mode |= VWRITE; 61437741Smckusick if (uap->fmode & X_OK) 61537741Smckusick mode |= VEXEC; 61637741Smckusick error = vn_access(vp, mode, u.u_cred); 6176254Sroot } 61837741Smckusick vput(vp); 61937741Smckusick out1: 6206254Sroot u.u_uid = svuid; 6216254Sroot u.u_gid = svgid; 62237741Smckusick RETURN (error); 6236254Sroot } 6246254Sroot 6256254Sroot /* 6266574Smckusic * Stat system call. This version follows links. 62737Sbill */ 62837Sbill stat() 62937Sbill { 63037Sbill 63116694Smckusick stat1(FOLLOW); 63237Sbill } 63337Sbill 63437Sbill /* 6356574Smckusic * Lstat system call. This version does not follow links. 6365992Swnj */ 6375992Swnj lstat() 6385992Swnj { 63912756Ssam 64016694Smckusick stat1(NOFOLLOW); 64112756Ssam } 64212756Ssam 64312756Ssam stat1(follow) 64412756Ssam int follow; 64512756Ssam { 6465992Swnj register struct a { 6475992Swnj char *fname; 64812756Ssam struct stat *ub; 64916694Smckusick } *uap = (struct a *)u.u_ap; 65037741Smckusick register struct nameidata *ndp = &u.u_nd; 65112756Ssam struct stat sb; 65237741Smckusick int error; 6535992Swnj 65437741Smckusick ndp->ni_nameiop = LOOKUP | LOCKLEAF | follow; 65516694Smckusick ndp->ni_segflg = UIO_USERSPACE; 65616694Smckusick ndp->ni_dirp = uap->fname; 65737741Smckusick if (error = namei(ndp)) 65837741Smckusick RETURN (error); 65937741Smckusick error = vn_stat(ndp->ni_vp, &sb); 66037741Smckusick vput(ndp->ni_vp); 66137741Smckusick if (error) 66237741Smckusick RETURN (error); 66337741Smckusick error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb)); 66437741Smckusick RETURN (error); 6655992Swnj } 6665992Swnj 6675992Swnj /* 6685992Swnj * Return target name of a symbolic link 66937Sbill */ 6705992Swnj readlink() 6715992Swnj { 6725992Swnj register struct a { 6735992Swnj char *name; 6745992Swnj char *buf; 6755992Swnj int count; 6767826Sroot } *uap = (struct a *)u.u_ap; 67716694Smckusick register struct nameidata *ndp = &u.u_nd; 67837741Smckusick register struct vnode *vp; 67937741Smckusick struct iovec aiov; 68037741Smckusick struct uio auio; 68137741Smckusick int error; 6825992Swnj 68337741Smckusick ndp->ni_nameiop = LOOKUP | LOCKLEAF; 68416694Smckusick ndp->ni_segflg = UIO_USERSPACE; 68516694Smckusick ndp->ni_dirp = uap->name; 68637741Smckusick if (error = namei(ndp)) 68737741Smckusick RETURN (error); 68837741Smckusick vp = ndp->ni_vp; 68937741Smckusick if (vp->v_type != VLNK) { 69037741Smckusick error = EINVAL; 6915992Swnj goto out; 6925992Swnj } 69337741Smckusick aiov.iov_base = uap->buf; 69437741Smckusick aiov.iov_len = uap->count; 69537741Smckusick auio.uio_iov = &aiov; 69637741Smckusick auio.uio_iovcnt = 1; 69737741Smckusick auio.uio_offset = 0; 69837741Smckusick auio.uio_rw = UIO_READ; 69937741Smckusick auio.uio_segflg = UIO_USERSPACE; 70037741Smckusick auio.uio_resid = uap->count; 70137741Smckusick error = VOP_READLINK(vp, &auio, ndp->ni_cred); 7025992Swnj out: 70337741Smckusick vput(vp); 70437741Smckusick u.u_r.r_val1 = uap->count - auio.uio_resid; 70537741Smckusick RETURN (error); 7065992Swnj } 7075992Swnj 7089167Ssam /* 7099167Ssam * Change mode of a file given path name. 7109167Ssam */ 7116254Sroot chmod() 7125992Swnj { 7137701Ssam struct a { 7146254Sroot char *fname; 7156254Sroot int fmode; 71616694Smckusick } *uap = (struct a *)u.u_ap; 71737741Smckusick register struct nameidata *ndp = &u.u_nd; 71837741Smckusick register struct vnode *vp; 71937741Smckusick struct vattr vattr; 72037741Smckusick int error; 7215992Swnj 72237741Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 72337741Smckusick ndp->ni_segflg = UIO_USERSPACE; 72437741Smckusick ndp->ni_dirp = uap->fname; 72537741Smckusick vattr_null(&vattr); 72637741Smckusick vattr.va_mode = uap->fmode & 07777; 72737741Smckusick if (error = namei(ndp)) 72837741Smckusick RETURN (error); 72937741Smckusick vp = ndp->ni_vp; 73037741Smckusick if (vp->v_mount->m_flag & M_RDONLY) { 73137741Smckusick error = EROFS; 73237741Smckusick goto out; 73337741Smckusick } 73437741Smckusick error = VOP_SETATTR(vp, &vattr, ndp->ni_cred); 73537741Smckusick out: 73637741Smckusick vput(vp); 73737741Smckusick RETURN (error); 7387701Ssam } 7397439Sroot 7409167Ssam /* 7419167Ssam * Change mode of a file given a file descriptor. 7429167Ssam */ 7437701Ssam fchmod() 7447701Ssam { 7457701Ssam struct a { 7467701Ssam int fd; 7477701Ssam int fmode; 74816694Smckusick } *uap = (struct a *)u.u_ap; 74937741Smckusick struct vattr vattr; 75037741Smckusick struct vnode *vp; 75137741Smckusick struct file *fp; 75237741Smckusick int error; 7537701Ssam 75437741Smckusick if (error = getvnode(uap->fd, &fp)) 75537741Smckusick RETURN (error); 75637741Smckusick vattr_null(&vattr); 75737741Smckusick vattr.va_mode = uap->fmode & 07777; 75837741Smckusick vp = (struct vnode *)fp->f_data; 75937741Smckusick VOP_LOCK(vp); 76037741Smckusick if (vp->v_mount->m_flag & M_RDONLY) { 76137741Smckusick error = EROFS; 76237741Smckusick goto out; 7637439Sroot } 76437741Smckusick error = VOP_SETATTR(vp, &vattr, fp->f_cred); 76537741Smckusick out: 76637741Smckusick VOP_UNLOCK(vp); 76737741Smckusick RETURN (error); 7685992Swnj } 7695992Swnj 7709167Ssam /* 7719167Ssam * Set ownership given a path name. 7729167Ssam */ 7736254Sroot chown() 77437Sbill { 7757701Ssam struct a { 7766254Sroot char *fname; 7776254Sroot int uid; 7786254Sroot int gid; 77916694Smckusick } *uap = (struct a *)u.u_ap; 78036614Sbostic register struct nameidata *ndp = &u.u_nd; 78137741Smckusick register struct vnode *vp; 78237741Smckusick struct vattr vattr; 78337741Smckusick int error; 78437Sbill 78537741Smckusick ndp->ni_nameiop = LOOKUP | NOFOLLOW | LOCKLEAF; 78636614Sbostic ndp->ni_segflg = UIO_USERSPACE; 78736614Sbostic ndp->ni_dirp = uap->fname; 78837741Smckusick vattr_null(&vattr); 78937741Smckusick vattr.va_uid = uap->uid; 79037741Smckusick vattr.va_gid = uap->gid; 79137741Smckusick if (error = namei(ndp)) 79237741Smckusick RETURN (error); 79337741Smckusick vp = ndp->ni_vp; 79437741Smckusick if (vp->v_mount->m_flag & M_RDONLY) { 79537741Smckusick error = EROFS; 79637741Smckusick goto out; 79737741Smckusick } 79837741Smckusick error = VOP_SETATTR(vp, &vattr, ndp->ni_cred); 79937741Smckusick out: 80037741Smckusick vput(vp); 80137741Smckusick RETURN (error); 8027701Ssam } 8037439Sroot 8049167Ssam /* 8059167Ssam * Set ownership given a file descriptor. 8069167Ssam */ 8077701Ssam fchown() 8087701Ssam { 8097701Ssam struct a { 8107701Ssam int fd; 8117701Ssam int uid; 8127701Ssam int gid; 81316694Smckusick } *uap = (struct a *)u.u_ap; 81437741Smckusick struct vattr vattr; 81537741Smckusick struct vnode *vp; 81637741Smckusick struct file *fp; 81737741Smckusick int error; 8187701Ssam 81937741Smckusick if (error = getvnode(uap->fd, &fp)) 82037741Smckusick RETURN (error); 82137741Smckusick vattr_null(&vattr); 82237741Smckusick vattr.va_uid = uap->uid; 82337741Smckusick vattr.va_gid = uap->gid; 82437741Smckusick vp = (struct vnode *)fp->f_data; 82537741Smckusick VOP_LOCK(vp); 82637741Smckusick if (vp->v_mount->m_flag & M_RDONLY) { 82737741Smckusick error = EROFS; 82837741Smckusick goto out; 82937741Smckusick } 83037741Smckusick error = VOP_SETATTR(vp, &vattr, fp->f_cred); 83137741Smckusick out: 83237741Smckusick VOP_UNLOCK(vp); 83337741Smckusick RETURN (error); 8347701Ssam } 8357701Ssam 83611811Ssam utimes() 83711811Ssam { 83811811Ssam register struct a { 83911811Ssam char *fname; 84011811Ssam struct timeval *tptr; 84111811Ssam } *uap = (struct a *)u.u_ap; 84237741Smckusick register struct nameidata *ndp = &u.u_nd; 84337741Smckusick register struct vnode *vp; 84411811Ssam struct timeval tv[2]; 84537741Smckusick struct vattr vattr; 84637741Smckusick int error; 84711811Ssam 84837741Smckusick if (error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv))) 84937741Smckusick RETURN (error); 85037741Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 85137741Smckusick ndp->ni_segflg = UIO_USERSPACE; 85237741Smckusick ndp->ni_dirp = uap->fname; 85337741Smckusick vattr_null(&vattr); 85437741Smckusick vattr.va_atime = tv[0]; 85537741Smckusick vattr.va_mtime = tv[1]; 85637741Smckusick if (error = namei(ndp)) 85737741Smckusick RETURN (error); 85837741Smckusick vp = ndp->ni_vp; 85937741Smckusick if (vp->v_mount->m_flag & M_RDONLY) { 86037741Smckusick error = EROFS; 86137741Smckusick goto out; 86221015Smckusick } 86337741Smckusick error = VOP_SETATTR(vp, &vattr, ndp->ni_cred); 86437741Smckusick out: 86537741Smckusick vput(vp); 86637741Smckusick RETURN (error); 86711811Ssam } 86811811Ssam 8699167Ssam /* 8709167Ssam * Truncate a file given its path name. 8719167Ssam */ 8727701Ssam truncate() 8737701Ssam { 8747701Ssam struct a { 8757701Ssam char *fname; 87626473Skarels off_t length; 8777826Sroot } *uap = (struct a *)u.u_ap; 87816694Smckusick register struct nameidata *ndp = &u.u_nd; 87937741Smckusick register struct vnode *vp; 88037741Smckusick struct vattr vattr; 88137741Smckusick int error; 8827701Ssam 88337741Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 88416694Smckusick ndp->ni_segflg = UIO_USERSPACE; 88516694Smckusick ndp->ni_dirp = uap->fname; 88637741Smckusick vattr_null(&vattr); 88737741Smckusick vattr.va_size = uap->length; 88837741Smckusick if (error = namei(ndp)) 88937741Smckusick RETURN (error); 89037741Smckusick vp = ndp->ni_vp; 89137741Smckusick if (vp->v_type == VDIR) { 89237741Smckusick error = EISDIR; 89337741Smckusick goto out; 8947701Ssam } 89537741Smckusick if (error = vn_access(vp, VWRITE, ndp->ni_cred)) 89637741Smckusick goto out; 89737741Smckusick error = VOP_SETATTR(vp, &vattr, ndp->ni_cred); 89837741Smckusick out: 89937741Smckusick vput(vp); 90037741Smckusick RETURN (error); 9017701Ssam } 9027701Ssam 9039167Ssam /* 9049167Ssam * Truncate a file given a file descriptor. 9059167Ssam */ 9067701Ssam ftruncate() 9077701Ssam { 9087701Ssam struct a { 9097701Ssam int fd; 91026473Skarels off_t length; 9117826Sroot } *uap = (struct a *)u.u_ap; 91237741Smckusick struct vattr vattr; 91337741Smckusick struct vnode *vp; 9147701Ssam struct file *fp; 91537741Smckusick int error; 9167701Ssam 91737741Smckusick if (error = getvnode(uap->fd, &fp)) 91837741Smckusick RETURN (error); 91937741Smckusick if ((fp->f_flag & FWRITE) == 0) 92037741Smckusick RETURN (EINVAL); 92137741Smckusick vattr_null(&vattr); 92237741Smckusick vattr.va_size = uap->length; 92337741Smckusick vp = (struct vnode *)fp->f_data; 92437741Smckusick VOP_LOCK(vp); 92537741Smckusick if (vp->v_type == VDIR) { 92637741Smckusick error = EISDIR; 92737741Smckusick goto out; 9287701Ssam } 92937741Smckusick if (error = vn_access(vp, VWRITE, fp->f_cred)) 93037741Smckusick goto out; 93137741Smckusick error = VOP_SETATTR(vp, &vattr, fp->f_cred); 93237741Smckusick out: 93337741Smckusick VOP_UNLOCK(vp); 93437741Smckusick RETURN (error); 9357701Ssam } 9367701Ssam 9379167Ssam /* 9389167Ssam * Synch an open file. 9399167Ssam */ 9409167Ssam fsync() 9419167Ssam { 9429167Ssam struct a { 9439167Ssam int fd; 9449167Ssam } *uap = (struct a *)u.u_ap; 9459167Ssam struct file *fp; 94637741Smckusick int error; 9479167Ssam 94837741Smckusick if (error = getvnode(uap->fd, &fp)) 94937741Smckusick RETURN (error); 95037741Smckusick error = VOP_FSYNC((struct vnode *)fp->f_data, fp->f_flag, fp->f_cred); 95137741Smckusick RETURN (error); 9529167Ssam } 9539167Ssam 9549167Ssam /* 9559167Ssam * Rename system call. 9569167Ssam * 9579167Ssam * Source and destination must either both be directories, or both 9589167Ssam * not be directories. If target is a directory, it must be empty. 9599167Ssam */ 9607701Ssam rename() 9617701Ssam { 9627701Ssam struct a { 9637701Ssam char *from; 9647701Ssam char *to; 96516694Smckusick } *uap = (struct a *)u.u_ap; 96637741Smckusick register struct vnode *tvp, *fvp, *tdvp; 96716694Smckusick register struct nameidata *ndp = &u.u_nd; 96837741Smckusick struct nameidata tond; 96937741Smckusick int error; 9707701Ssam 97137741Smckusick ndp->ni_nameiop = DELETE | WANTPARENT; 97216694Smckusick ndp->ni_segflg = UIO_USERSPACE; 97316694Smckusick ndp->ni_dirp = uap->from; 97437741Smckusick if (error = namei(ndp)) 97537741Smckusick RETURN (error); 97637741Smckusick fvp = ndp->ni_vp; 97737741Smckusick bzero((caddr_t)&tond, sizeof(tond)); 97837741Smckusick tond.ni_nameiop = RENAME | LOCKPARENT | LOCKLEAF | NOCACHE; 97937741Smckusick tond.ni_segflg = UIO_USERSPACE; 98037741Smckusick tond.ni_dirp = uap->to; 98137741Smckusick tond.ni_cdir = ndp->ni_cdir; 98237741Smckusick tond.ni_cdir->v_count++; 98337741Smckusick tond.ni_rdir = ndp->ni_rdir; 98437741Smckusick if (tond.ni_rdir) 98537741Smckusick tond.ni_rdir->v_count++; 98637741Smckusick tond.ni_cred = ndp->ni_cred; 98737741Smckusick crhold(tond.ni_cred); 98837741Smckusick error = namei(&tond); 98937741Smckusick tdvp = tond.ni_dvp; 99037741Smckusick tvp = tond.ni_vp; 99137741Smckusick if (tvp != NULL) { 99237741Smckusick if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 99337741Smckusick error = EISDIR; 99437741Smckusick goto out; 99537741Smckusick } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 99637741Smckusick error = ENOTDIR; 99737741Smckusick goto out; 9989167Ssam } 9999167Ssam } 100037741Smckusick if (error) { 100137741Smckusick VOP_ABORTOP(ndp); 100237741Smckusick goto out1; 100337741Smckusick } 100437741Smckusick if (fvp->v_mount != tdvp->v_mount) { 100537741Smckusick error = EXDEV; 10069167Ssam goto out; 100710051Ssam } 100837741Smckusick if (fvp == tdvp || fvp == tvp) 100937741Smckusick error = EINVAL; 101037741Smckusick out: 101137741Smckusick if (error) { 101237741Smckusick VOP_ABORTOP(&tond); 101337741Smckusick VOP_ABORTOP(ndp); 10149167Ssam } else { 101537741Smckusick error = VOP_RENAME(ndp, &tond); 10169167Ssam } 101737741Smckusick out1: 101837741Smckusick vrele(tond.ni_cdir); 101937741Smckusick if (tond.ni_rdir) 102037741Smckusick vrele(tond.ni_rdir); 102137741Smckusick crfree(tond.ni_cred); 102237741Smckusick RETURN (error); 10237701Ssam } 10247701Ssam 10257535Sroot /* 102612756Ssam * Mkdir system call 102712756Ssam */ 102812756Ssam mkdir() 102912756Ssam { 103012756Ssam struct a { 103112756Ssam char *name; 103212756Ssam int dmode; 103316694Smckusick } *uap = (struct a *)u.u_ap; 103416694Smckusick register struct nameidata *ndp = &u.u_nd; 103537741Smckusick register struct vnode *vp; 103637741Smckusick struct vattr vattr; 103737741Smckusick int error; 103812756Ssam 103937741Smckusick ndp->ni_nameiop = CREATE | LOCKPARENT; 104016694Smckusick ndp->ni_segflg = UIO_USERSPACE; 104116694Smckusick ndp->ni_dirp = uap->name; 104237741Smckusick if (error = namei(ndp)) 104337741Smckusick RETURN (error); 104437741Smckusick vp = ndp->ni_vp; 104537741Smckusick if (vp != NULL) { 104637741Smckusick VOP_ABORTOP(ndp); 104737741Smckusick RETURN (EEXIST); 104812756Ssam } 104937741Smckusick vattr_null(&vattr); 105037741Smckusick vattr.va_type = VDIR; 105137741Smckusick vattr.va_mode = (uap->dmode & 0777) &~ u.u_cmask; 105237741Smckusick error = VOP_MKDIR(ndp, &vattr); 105337741Smckusick RETURN (error); 105412756Ssam } 105512756Ssam 105612756Ssam /* 105712756Ssam * Rmdir system call. 105812756Ssam */ 105912756Ssam rmdir() 106012756Ssam { 106112756Ssam struct a { 106212756Ssam char *name; 106316694Smckusick } *uap = (struct a *)u.u_ap; 106416694Smckusick register struct nameidata *ndp = &u.u_nd; 106537741Smckusick register struct vnode *vp; 106637741Smckusick int error; 106712756Ssam 106837741Smckusick ndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF; 106916694Smckusick ndp->ni_segflg = UIO_USERSPACE; 107016694Smckusick ndp->ni_dirp = uap->name; 107137741Smckusick if (error = namei(ndp)) 107237741Smckusick RETURN (error); 107337741Smckusick vp = ndp->ni_vp; 107437741Smckusick if (vp->v_type != VDIR) { 107537741Smckusick error = ENOTDIR; 107612756Ssam goto out; 107712756Ssam } 107812756Ssam /* 107937741Smckusick * No rmdir "." please. 108012756Ssam */ 108137741Smckusick if (ndp->ni_dvp == vp) { 108237741Smckusick error = EINVAL; 108312756Ssam goto out; 108412756Ssam } 108512756Ssam /* 108637741Smckusick * Don't unlink a mounted file. 108712756Ssam */ 108837741Smckusick if (vp->v_flag & VROOT) 108937741Smckusick error = EBUSY; 109012756Ssam out: 109137741Smckusick if (error) 109237741Smckusick VOP_ABORTOP(ndp); 109337741Smckusick else 109437741Smckusick error = VOP_RMDIR(ndp); 109537741Smckusick RETURN (error); 109612756Ssam } 109712756Ssam 109837741Smckusick /* 109937741Smckusick * Read a block of directory entries in a file system independent format 110037741Smckusick */ 110137741Smckusick getdirentries() 110212756Ssam { 110337741Smckusick register struct a { 110437741Smckusick int fd; 110537741Smckusick char *buf; 110637741Smckusick unsigned count; 110737741Smckusick long *basep; 110837741Smckusick } *uap = (struct a *)u.u_ap; 110916540Ssam struct file *fp; 111037741Smckusick struct uio auio; 111137741Smckusick struct iovec aiov; 1112*38129Smckusick off_t off; 111337741Smckusick int error; 111412756Ssam 111537741Smckusick if (error = getvnode(uap->fd, &fp)) 111637741Smckusick RETURN (error); 111737741Smckusick if ((fp->f_flag & FREAD) == 0) 111837741Smckusick RETURN (EBADF); 111937741Smckusick aiov.iov_base = uap->buf; 112037741Smckusick aiov.iov_len = uap->count; 112137741Smckusick auio.uio_iov = &aiov; 112237741Smckusick auio.uio_iovcnt = 1; 112337741Smckusick auio.uio_rw = UIO_READ; 112437741Smckusick auio.uio_segflg = UIO_USERSPACE; 112537741Smckusick auio.uio_resid = uap->count; 1126*38129Smckusick off = fp->f_offset; 112737741Smckusick if (error = VOP_READDIR((struct vnode *)fp->f_data, &auio, 112837741Smckusick &(fp->f_offset), fp->f_cred)) 112937741Smckusick RETURN (error); 1130*38129Smckusick error = copyout((caddr_t)&off, (caddr_t)uap->basep, 113137741Smckusick sizeof(long)); 113237741Smckusick u.u_r.r_val1 = uap->count - auio.uio_resid; 113337741Smckusick RETURN (error); 113412756Ssam } 113512756Ssam 113612756Ssam /* 113712756Ssam * mode mask for creation of files 113812756Ssam */ 113912756Ssam umask() 114012756Ssam { 114112756Ssam register struct a { 114212756Ssam int mask; 114316694Smckusick } *uap = (struct a *)u.u_ap; 114412756Ssam 114512756Ssam u.u_r.r_val1 = u.u_cmask; 114612756Ssam u.u_cmask = uap->mask & 07777; 114737741Smckusick RETURN (0); 114812756Ssam } 114937741Smckusick 115037741Smckusick getvnode(fdes, fpp) 115137741Smckusick struct file **fpp; 115237741Smckusick int fdes; 115337741Smckusick { 115437741Smckusick struct file *fp; 115537741Smckusick 115637741Smckusick if ((unsigned)fdes >= NOFILE || (fp = u.u_ofile[fdes]) == NULL) 115737741Smckusick return (EBADF); 115837741Smckusick if (fp->f_type != DTYPE_VNODE) 115937741Smckusick return (EINVAL); 116037741Smckusick *fpp = fp; 116137741Smckusick return (0); 116237741Smckusick } 1163