123405Smckusick /* 2*37741Smckusick * Copyright (c) 1989 The Regents of the University of California. 3*37741Smckusick * All rights reserved. 423405Smckusick * 5*37741Smckusick * Redistribution and use in source and binary forms are permitted 6*37741Smckusick * provided that the above copyright notice and this paragraph are 7*37741Smckusick * duplicated in all such forms and that any documentation, 8*37741Smckusick * advertising materials, and other materials related to such 9*37741Smckusick * distribution and use acknowledge that the software was developed 10*37741Smckusick * by the University of California, Berkeley. The name of the 11*37741Smckusick * University may not be used to endorse or promote products derived 12*37741Smckusick * from this software without specific prior written permission. 13*37741Smckusick * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14*37741Smckusick * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15*37741Smckusick * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16*37741Smckusick * 17*37741Smckusick * @(#)vfs_syscalls.c 7.7 (Berkeley) 05/09/89 1823405Smckusick */ 1937Sbill 2017101Sbloom #include "param.h" 2117101Sbloom #include "systm.h" 22*37741Smckusick #include "syscontext.h" 2317101Sbloom #include "kernel.h" 2417101Sbloom #include "file.h" 2517101Sbloom #include "stat.h" 26*37741Smckusick #include "vnode.h" 27*37741Smckusick #include "../ufs/inode.h" 28*37741Smckusick #include "mount.h" 2917101Sbloom #include "proc.h" 3017101Sbloom #include "uio.h" 31*37741Smckusick #include "malloc.h" 3237Sbill 33*37741Smckusick /* 34*37741Smckusick * Virtual File System System Calls 35*37741Smckusick */ 3612756Ssam 379167Ssam /* 38*37741Smckusick * mount system call 399167Ssam */ 40*37741Smckusick mount() 416254Sroot { 42*37741Smckusick register struct a { 43*37741Smckusick int type; 44*37741Smckusick char *dir; 45*37741Smckusick int flags; 46*37741Smckusick caddr_t data; 47*37741Smckusick } *uap = (struct a *)u.u_ap; 48*37741Smckusick register struct nameidata *ndp = &u.u_nd; 49*37741Smckusick struct vnode *vp; 50*37741Smckusick struct mount *mp; 51*37741Smckusick int error; 526254Sroot 53*37741Smckusick /* 54*37741Smckusick * Must be super user 55*37741Smckusick */ 56*37741Smckusick if (error = suser(u.u_cred, &u.u_acflag)) 57*37741Smckusick RETURN (error); 58*37741Smckusick /* 59*37741Smckusick * Get vnode to be covered 60*37741Smckusick */ 61*37741Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 62*37741Smckusick ndp->ni_segflg = UIO_USERSPACE; 63*37741Smckusick ndp->ni_dirp = uap->dir; 64*37741Smckusick if (error = namei(ndp)) 65*37741Smckusick RETURN (error); 66*37741Smckusick vp = ndp->ni_vp; 67*37741Smckusick if (vp->v_count != 1) { 68*37741Smckusick vput(vp); 69*37741Smckusick RETURN (EBUSY); 70*37741Smckusick } 71*37741Smckusick if (vp->v_type != VDIR) { 72*37741Smckusick vput(vp); 73*37741Smckusick RETURN (ENOTDIR); 74*37741Smckusick } 75*37741Smckusick if (uap->type > MOUNT_MAXTYPE || 76*37741Smckusick vfssw[uap->type] == (struct vfsops *)0) { 77*37741Smckusick vput(vp); 78*37741Smckusick RETURN (ENODEV); 79*37741Smckusick } 80*37741Smckusick 81*37741Smckusick /* 82*37741Smckusick * Mount the filesystem. 83*37741Smckusick */ 84*37741Smckusick mp = (struct mount *)malloc((u_long)sizeof(struct mount), 85*37741Smckusick M_MOUNT, M_WAITOK); 86*37741Smckusick mp->m_op = vfssw[uap->type]; 87*37741Smckusick mp->m_flag = 0; 88*37741Smckusick mp->m_exroot = 0; 89*37741Smckusick error = vfs_add(vp, mp, uap->flags); 90*37741Smckusick if (!error) 91*37741Smckusick error = VFS_MOUNT(mp, uap->dir, uap->data, ndp); 92*37741Smckusick cache_purge(vp); 93*37741Smckusick VOP_UNLOCK(vp); 94*37741Smckusick if (!error) { 95*37741Smckusick vfs_unlock(mp); 96*37741Smckusick } else { 97*37741Smckusick vfs_remove(mp); 98*37741Smckusick free((caddr_t)mp, M_MOUNT); 99*37741Smckusick vrele(vp); 100*37741Smckusick } 101*37741Smckusick RETURN (error); 1026254Sroot } 1036254Sroot 1049167Ssam /* 105*37741Smckusick * Unmount system call. 106*37741Smckusick * 107*37741Smckusick * Note: unmount takes a path to the vnode mounted on as argument, 108*37741Smckusick * not special file (as before). 1099167Ssam */ 110*37741Smckusick unmount() 1116254Sroot { 112*37741Smckusick struct a { 113*37741Smckusick char *pathp; 114*37741Smckusick int flags; 115*37741Smckusick } *uap = (struct a *)u.u_ap; 116*37741Smckusick register struct vnode *vp; 117*37741Smckusick register struct mount *mp; 118*37741Smckusick register struct nameidata *ndp = &u.u_nd; 119*37741Smckusick struct vnode *coveredvp; 120*37741Smckusick int error; 1216254Sroot 122*37741Smckusick /* 123*37741Smckusick * Must be super user 124*37741Smckusick */ 125*37741Smckusick if (error = suser(u.u_cred, &u.u_acflag)) 126*37741Smckusick RETURN (error); 127*37741Smckusick 128*37741Smckusick ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW; 129*37741Smckusick ndp->ni_segflg = UIO_USERSPACE; 130*37741Smckusick ndp->ni_dirp = uap->pathp; 131*37741Smckusick if (error = namei(ndp)) 132*37741Smckusick RETURN (error); 133*37741Smckusick vp = ndp->ni_vp; 134*37741Smckusick /* 135*37741Smckusick * Must be the root of the filesystem 136*37741Smckusick */ 137*37741Smckusick if ((vp->v_flag & VROOT) == 0) { 138*37741Smckusick vput(vp); 139*37741Smckusick RETURN (EINVAL); 140*37741Smckusick } 141*37741Smckusick mp = vp->v_mount; 142*37741Smckusick vput(vp); 143*37741Smckusick /* 144*37741Smckusick * Do the unmount. 145*37741Smckusick */ 146*37741Smckusick coveredvp = mp->m_vnodecovered; 147*37741Smckusick if (error = vfs_lock(mp)) 148*37741Smckusick RETURN (error); 149*37741Smckusick 150*37741Smckusick xumount(mp); /* remove unused sticky files from text table */ 151*37741Smckusick cache_purgevfs(mp); /* remove cache entries for this file sys */ 152*37741Smckusick VFS_SYNC(mp, MNT_WAIT); 153*37741Smckusick 154*37741Smckusick error = VFS_UNMOUNT(mp, uap->flags); 155*37741Smckusick if (error) { 156*37741Smckusick vfs_unlock(mp); 157*37741Smckusick } else { 158*37741Smckusick vrele(coveredvp); 159*37741Smckusick vfs_remove(mp); 160*37741Smckusick free((caddr_t)mp, M_MOUNT); 161*37741Smckusick } 162*37741Smckusick RETURN (error); 1636254Sroot } 1646254Sroot 1659167Ssam /* 166*37741Smckusick * Sync system call. 167*37741Smckusick * Sync each mounted filesystem. 1689167Ssam */ 169*37741Smckusick sync() 1706254Sroot { 171*37741Smckusick register struct mount *mp; 172*37741Smckusick 173*37741Smckusick mp = rootfs; 174*37741Smckusick do { 175*37741Smckusick if ((mp->m_flag & M_RDONLY) == 0) 176*37741Smckusick VFS_SYNC(mp, MNT_NOWAIT); 177*37741Smckusick mp = mp->m_next; 178*37741Smckusick } while (mp != rootfs); 179*37741Smckusick } 180*37741Smckusick 181*37741Smckusick /* 182*37741Smckusick * get filesystem statistics 183*37741Smckusick */ 184*37741Smckusick statfs() 185*37741Smckusick { 1866254Sroot struct a { 187*37741Smckusick char *path; 188*37741Smckusick struct statfs *buf; 189*37741Smckusick } *uap = (struct a *)u.u_ap; 190*37741Smckusick register struct vnode *vp; 191*37741Smckusick register struct nameidata *ndp = &u.u_nd; 192*37741Smckusick struct statfs sb; 193*37741Smckusick int error; 194*37741Smckusick 195*37741Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 196*37741Smckusick ndp->ni_segflg = UIO_USERSPACE; 197*37741Smckusick ndp->ni_dirp = uap->path; 198*37741Smckusick if (error = namei(ndp)) 199*37741Smckusick RETURN (error); 200*37741Smckusick vp = ndp->ni_vp; 201*37741Smckusick if (error = VFS_STATFS(vp->v_mount, &sb)) 202*37741Smckusick goto out; 203*37741Smckusick error = copyout((caddr_t)&sb, (caddr_t)uap->buf, sizeof(sb)); 204*37741Smckusick out: 205*37741Smckusick vput(vp); 206*37741Smckusick RETURN (error); 207*37741Smckusick } 208*37741Smckusick 209*37741Smckusick fstatfs() 210*37741Smckusick { 211*37741Smckusick struct a { 212*37741Smckusick int fd; 213*37741Smckusick struct statfs *buf; 214*37741Smckusick } *uap = (struct a *)u.u_ap; 215*37741Smckusick struct file *fp; 216*37741Smckusick struct statfs sb; 217*37741Smckusick int error; 218*37741Smckusick 219*37741Smckusick if (error = getvnode(uap->fd, &fp)) 220*37741Smckusick RETURN (error); 221*37741Smckusick if (error = VFS_STATFS(((struct vnode *)fp->f_data)->v_mount, &sb)) 222*37741Smckusick RETURN (error); 223*37741Smckusick RETURN (copyout((caddr_t)&sb, (caddr_t)uap->buf, sizeof(sb))); 224*37741Smckusick } 225*37741Smckusick 226*37741Smckusick /* 227*37741Smckusick * Change current working directory (``.''). 228*37741Smckusick */ 229*37741Smckusick chdir() 230*37741Smckusick { 231*37741Smckusick struct a { 2326254Sroot char *fname; 23316694Smckusick } *uap = (struct a *)u.u_ap; 23416694Smckusick register struct nameidata *ndp = &u.u_nd; 235*37741Smckusick int error; 2366254Sroot 237*37741Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 23816694Smckusick ndp->ni_segflg = UIO_USERSPACE; 23916694Smckusick ndp->ni_dirp = uap->fname; 240*37741Smckusick if (error = chdirec(ndp)) 241*37741Smckusick RETURN (error); 242*37741Smckusick vrele(u.u_cdir); 243*37741Smckusick u.u_cdir = ndp->ni_vp; 244*37741Smckusick RETURN (0); 245*37741Smckusick } 2466254Sroot 247*37741Smckusick /* 248*37741Smckusick * Change notion of root (``/'') directory. 249*37741Smckusick */ 250*37741Smckusick chroot() 251*37741Smckusick { 252*37741Smckusick struct a { 253*37741Smckusick char *fname; 254*37741Smckusick } *uap = (struct a *)u.u_ap; 255*37741Smckusick register struct nameidata *ndp = &u.u_nd; 256*37741Smckusick int error; 257*37741Smckusick 258*37741Smckusick if (error = suser(u.u_cred, &u.u_acflag)) 259*37741Smckusick RETURN (error); 260*37741Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 261*37741Smckusick ndp->ni_segflg = UIO_USERSPACE; 262*37741Smckusick ndp->ni_dirp = uap->fname; 263*37741Smckusick if (error = chdirec(ndp)) 264*37741Smckusick RETURN (error); 265*37741Smckusick vrele(u.u_rdir); 266*37741Smckusick u.u_rdir = ndp->ni_vp; 267*37741Smckusick RETURN (0); 2686254Sroot } 2696254Sroot 27037Sbill /* 271*37741Smckusick * Common routine for chroot and chdir. 272*37741Smckusick */ 273*37741Smckusick chdirec(ndp) 274*37741Smckusick register struct nameidata *ndp; 275*37741Smckusick { 276*37741Smckusick struct vnode *vp; 277*37741Smckusick int error; 278*37741Smckusick 279*37741Smckusick if (error = namei(ndp)) 280*37741Smckusick return (error); 281*37741Smckusick vp = ndp->ni_vp; 282*37741Smckusick if (vp->v_type != VDIR) 283*37741Smckusick error = ENOTDIR; 284*37741Smckusick else 285*37741Smckusick error = vn_access(vp, VEXEC, ndp->ni_cred); 286*37741Smckusick VOP_UNLOCK(vp); 287*37741Smckusick if (error) 288*37741Smckusick vrele(vp); 289*37741Smckusick return (error); 290*37741Smckusick } 291*37741Smckusick 292*37741Smckusick /* 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; 302*37741Smckusick struct nameidata *ndp = &u.u_nd; 3036254Sroot 304*37741Smckusick ndp->ni_segflg = UIO_USERSPACE; 305*37741Smckusick ndp->ni_dirp = uap->fname; 306*37741Smckusick RETURN (copen(uap->mode-FOPEN, uap->crtmode &~ u.u_cmask, ndp, 307*37741Smckusick &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; 319*37741Smckusick struct nameidata *ndp = &u.u_nd; 3206254Sroot 321*37741Smckusick ndp->ni_segflg = UIO_USERSPACE; 322*37741Smckusick ndp->ni_dirp = uap->fname; 323*37741Smckusick RETURN (copen(FWRITE|FCREAT|FTRUNC, uap->fmode &~ u.u_cmask, ndp, 324*37741Smckusick &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 */ 332*37741Smckusick copen(fmode, cmode, ndp, resultfd) 333*37741Smckusick int fmode, cmode; 334*37741Smckusick struct nameidata *ndp; 335*37741Smckusick int *resultfd; 33612756Ssam { 3376254Sroot register struct file *fp; 338*37741Smckusick struct file *nfp; 339*37741Smckusick int indx, error; 340*37741Smckusick extern struct fileops vnops; 3416254Sroot 342*37741Smckusick if (error = falloc(&nfp, &indx)) 343*37741Smckusick return (error); 344*37741Smckusick fp = nfp; 345*37741Smckusick u.u_r.r_val1 = indx; /* XXX for fdopen() */ 346*37741Smckusick if (error = vn_open(ndp, fmode, (cmode & 07777) &~ ISVTX)) { 34724543Smckusick u.u_ofile[indx] = NULL; 348*37741Smckusick crfree(fp->f_cred); 349*37741Smckusick fp->f_count--; 350*37741Smckusick return (error); 35112756Ssam } 352*37741Smckusick fp->f_flag = fmode & FMASK; 353*37741Smckusick fp->f_type = DTYPE_VNODE; 354*37741Smckusick fp->f_ops = &vnops; 355*37741Smckusick fp->f_data = (caddr_t)ndp->ni_vp; 356*37741Smckusick if (resultfd) 357*37741Smckusick *resultfd = indx; 358*37741Smckusick 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; 372*37741Smckusick register struct vnode *vp; 373*37741Smckusick struct vattr vattr; 374*37741Smckusick int error; 3756254Sroot 376*37741Smckusick if (error = suser(u.u_cred, &u.u_acflag)) 377*37741Smckusick RETURN (error); 378*37741Smckusick ndp->ni_nameiop = CREATE | LOCKPARENT; 37916694Smckusick ndp->ni_segflg = UIO_USERSPACE; 38016694Smckusick ndp->ni_dirp = uap->fname; 381*37741Smckusick if (error = namei(ndp)) 382*37741Smckusick RETURN (error); 383*37741Smckusick vp = ndp->ni_vp; 384*37741Smckusick if (vp != NULL) { 385*37741Smckusick error = EEXIST; 38612756Ssam goto out; 3876254Sroot } 388*37741Smckusick vattr_null(&vattr); 389*37741Smckusick switch (uap->fmode & IFMT) { 39012756Ssam 39115093Smckusick case IFMT: /* used by badsect to flag bad sectors */ 392*37741Smckusick vattr.va_type = VBAD; 393*37741Smckusick break; 39412756Ssam case IFCHR: 395*37741Smckusick vattr.va_type = VCHR; 396*37741Smckusick break; 39712756Ssam case IFBLK: 398*37741Smckusick vattr.va_type = VBLK; 399*37741Smckusick break; 400*37741Smckusick default: 401*37741Smckusick error = EINVAL; 402*37741Smckusick goto out; 4036254Sroot } 404*37741Smckusick vattr.va_mode = (uap->fmode & 07777) &~ u.u_cmask; 405*37741Smckusick vattr.va_rdev = uap->dev; 4066254Sroot out: 407*37741Smckusick if (error) 408*37741Smckusick VOP_ABORTOP(ndp); 409*37741Smckusick else 410*37741Smckusick error = VOP_MKNOD(ndp, &vattr, ndp->ni_cred); 411*37741Smckusick 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; 424*37741Smckusick register struct vnode *vp, *xp; 425*37741Smckusick int error; 4266254Sroot 42716694Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW; 42816694Smckusick ndp->ni_segflg = UIO_USERSPACE; 42916694Smckusick ndp->ni_dirp = uap->target; 430*37741Smckusick if (error = namei(ndp)) 431*37741Smckusick RETURN (error); 432*37741Smckusick vp = ndp->ni_vp; 433*37741Smckusick if (vp->v_type == VDIR && 434*37741Smckusick (error = suser(u.u_cred, &u.u_acflag))) 435*37741Smckusick goto out1; 436*37741Smckusick ndp->ni_nameiop = CREATE | LOCKPARENT; 43716694Smckusick ndp->ni_dirp = (caddr_t)uap->linkname; 438*37741Smckusick if (error = namei(ndp)) 439*37741Smckusick goto out1; 440*37741Smckusick xp = ndp->ni_vp; 4416254Sroot if (xp != NULL) { 442*37741Smckusick error = EEXIST; 4436254Sroot goto out; 4446254Sroot } 445*37741Smckusick xp = ndp->ni_dvp; 446*37741Smckusick if (vp->v_mount != xp->v_mount) 447*37741Smckusick error = EXDEV; 4486254Sroot out: 449*37741Smckusick if (error) 450*37741Smckusick VOP_ABORTOP(ndp); 451*37741Smckusick else 452*37741Smckusick error = VOP_LINK(vp, ndp); 453*37741Smckusick out1: 454*37741Smckusick vrele(vp); 455*37741Smckusick RETURN (error); 4566254Sroot } 4576254Sroot 4586254Sroot /* 4596254Sroot * symlink -- make a symbolic link 4606254Sroot */ 4616254Sroot symlink() 4626254Sroot { 463*37741Smckusick struct a { 4646254Sroot char *target; 4656254Sroot char *linkname; 46616694Smckusick } *uap = (struct a *)u.u_ap; 46716694Smckusick register struct nameidata *ndp = &u.u_nd; 468*37741Smckusick register struct vnode *vp; 469*37741Smckusick struct vattr vattr; 470*37741Smckusick char *target; 471*37741Smckusick int error; 4726254Sroot 47316694Smckusick ndp->ni_segflg = UIO_USERSPACE; 47416694Smckusick ndp->ni_dirp = uap->linkname; 475*37741Smckusick MALLOC(target, char *, MAXPATHLEN, M_NAMEI, M_WAITOK); 476*37741Smckusick if (error = copyinstr(uap->target, target, MAXPATHLEN, (u_int *)0)) 477*37741Smckusick goto out1; 478*37741Smckusick ndp->ni_nameiop = CREATE | LOCKPARENT; 479*37741Smckusick if (error = namei(ndp)) 480*37741Smckusick goto out1; 481*37741Smckusick vp = ndp->ni_vp; 482*37741Smckusick if (vp) { 483*37741Smckusick error = EEXIST; 484*37741Smckusick goto out; 4856254Sroot } 486*37741Smckusick vp = ndp->ni_dvp; 487*37741Smckusick vattr_null(&vattr); 488*37741Smckusick vattr.va_mode = 0777 &~ u.u_cmask; 489*37741Smckusick out: 490*37741Smckusick if (error) 491*37741Smckusick VOP_ABORTOP(ndp); 492*37741Smckusick else 493*37741Smckusick error = VOP_SYMLINK(ndp, &vattr, target); 494*37741Smckusick out1: 495*37741Smckusick FREE(target, M_NAMEI); 496*37741Smckusick 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; 510*37741Smckusick register struct vnode *vp; 511*37741Smckusick int error; 5126254Sroot 513*37741Smckusick ndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF; 51416694Smckusick ndp->ni_segflg = UIO_USERSPACE; 51516694Smckusick ndp->ni_dirp = uap->fname; 516*37741Smckusick if (error = namei(ndp)) 517*37741Smckusick RETURN (error); 518*37741Smckusick vp = ndp->ni_vp; 519*37741Smckusick if (vp->v_type == VDIR && 520*37741Smckusick (error = suser(u.u_cred, &u.u_acflag))) 5216254Sroot goto out; 5226254Sroot /* 5236254Sroot * Don't unlink a mounted file. 5246254Sroot */ 525*37741Smckusick if (vp->v_flag & VROOT) { 526*37741Smckusick error = EBUSY; 5276254Sroot goto out; 5286254Sroot } 529*37741Smckusick if (vp->v_flag & VTEXT) 530*37741Smckusick xrele(vp); /* try once to free text */ 5316254Sroot out: 532*37741Smckusick if (error) 533*37741Smckusick VOP_ABORTOP(ndp); 5347142Smckusick else 535*37741Smckusick error = VOP_REMOVE(ndp); 536*37741Smckusick RETURN (error); 5376254Sroot } 5386254Sroot 5396254Sroot /* 5406254Sroot * Seek system call 5416254Sroot */ 5428040Sroot lseek() 5436254Sroot { 5446254Sroot register struct file *fp; 5456254Sroot register struct a { 546*37741Smckusick int fdes; 5476254Sroot off_t off; 5486254Sroot int sbase; 54916694Smckusick } *uap = (struct a *)u.u_ap; 550*37741Smckusick struct vattr vattr; 551*37741Smckusick int error; 5526254Sroot 553*37741Smckusick if ((unsigned)uap->fdes >= NOFILE || 554*37741Smckusick (fp = u.u_ofile[uap->fdes]) == NULL) 555*37741Smckusick RETURN (EBADF); 556*37741Smckusick if (fp->f_type != DTYPE_VNODE) 557*37741Smckusick RETURN (ESPIPE); 55813878Ssam switch (uap->sbase) { 55913878Ssam 56013878Ssam case L_INCR: 56113878Ssam fp->f_offset += uap->off; 56213878Ssam break; 56313878Ssam 56413878Ssam case L_XTND: 565*37741Smckusick if (error = VOP_GETATTR((struct vnode *)fp->f_data, 566*37741Smckusick &vattr, u.u_cred)) 567*37741Smckusick RETURN (error); 568*37741Smckusick 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: 576*37741Smckusick RETURN (EINVAL); 57713878Ssam } 57813878Ssam u.u_r.r_off = fp->f_offset; 579*37741Smckusick 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; 592*37741Smckusick register struct vnode *vp; 593*37741Smckusick 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; 599*37741Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 60016694Smckusick ndp->ni_segflg = UIO_USERSPACE; 60116694Smckusick ndp->ni_dirp = uap->fname; 602*37741Smckusick if (error = namei(ndp)) 603*37741Smckusick goto out1; 604*37741Smckusick vp = ndp->ni_vp; 605*37741Smckusick /* 606*37741Smckusick * fmode == 0 means only check for exist 607*37741Smckusick */ 608*37741Smckusick if (uap->fmode) { 609*37741Smckusick mode = 0; 610*37741Smckusick if (uap->fmode & R_OK) 611*37741Smckusick mode |= VREAD; 612*37741Smckusick if (uap->fmode & W_OK) 613*37741Smckusick mode |= VWRITE; 614*37741Smckusick if (uap->fmode & X_OK) 615*37741Smckusick mode |= VEXEC; 616*37741Smckusick error = vn_access(vp, mode, u.u_cred); 6176254Sroot } 618*37741Smckusick vput(vp); 619*37741Smckusick out1: 6206254Sroot u.u_uid = svuid; 6216254Sroot u.u_gid = svgid; 622*37741Smckusick 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; 650*37741Smckusick register struct nameidata *ndp = &u.u_nd; 65112756Ssam struct stat sb; 652*37741Smckusick int error; 6535992Swnj 654*37741Smckusick ndp->ni_nameiop = LOOKUP | LOCKLEAF | follow; 65516694Smckusick ndp->ni_segflg = UIO_USERSPACE; 65616694Smckusick ndp->ni_dirp = uap->fname; 657*37741Smckusick if (error = namei(ndp)) 658*37741Smckusick RETURN (error); 659*37741Smckusick error = vn_stat(ndp->ni_vp, &sb); 660*37741Smckusick vput(ndp->ni_vp); 661*37741Smckusick if (error) 662*37741Smckusick RETURN (error); 663*37741Smckusick error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb)); 664*37741Smckusick 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; 678*37741Smckusick register struct vnode *vp; 679*37741Smckusick struct iovec aiov; 680*37741Smckusick struct uio auio; 681*37741Smckusick int error; 6825992Swnj 683*37741Smckusick ndp->ni_nameiop = LOOKUP | LOCKLEAF; 68416694Smckusick ndp->ni_segflg = UIO_USERSPACE; 68516694Smckusick ndp->ni_dirp = uap->name; 686*37741Smckusick if (error = namei(ndp)) 687*37741Smckusick RETURN (error); 688*37741Smckusick vp = ndp->ni_vp; 689*37741Smckusick if (vp->v_type != VLNK) { 690*37741Smckusick error = EINVAL; 6915992Swnj goto out; 6925992Swnj } 693*37741Smckusick aiov.iov_base = uap->buf; 694*37741Smckusick aiov.iov_len = uap->count; 695*37741Smckusick auio.uio_iov = &aiov; 696*37741Smckusick auio.uio_iovcnt = 1; 697*37741Smckusick auio.uio_offset = 0; 698*37741Smckusick auio.uio_rw = UIO_READ; 699*37741Smckusick auio.uio_segflg = UIO_USERSPACE; 700*37741Smckusick auio.uio_resid = uap->count; 701*37741Smckusick error = VOP_READLINK(vp, &auio, ndp->ni_cred); 7025992Swnj out: 703*37741Smckusick vput(vp); 704*37741Smckusick u.u_r.r_val1 = uap->count - auio.uio_resid; 705*37741Smckusick 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; 717*37741Smckusick register struct nameidata *ndp = &u.u_nd; 718*37741Smckusick register struct vnode *vp; 719*37741Smckusick struct vattr vattr; 720*37741Smckusick int error; 7215992Swnj 722*37741Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 723*37741Smckusick ndp->ni_segflg = UIO_USERSPACE; 724*37741Smckusick ndp->ni_dirp = uap->fname; 725*37741Smckusick vattr_null(&vattr); 726*37741Smckusick vattr.va_mode = uap->fmode & 07777; 727*37741Smckusick if (error = namei(ndp)) 728*37741Smckusick RETURN (error); 729*37741Smckusick vp = ndp->ni_vp; 730*37741Smckusick if (vp->v_mount->m_flag & M_RDONLY) { 731*37741Smckusick error = EROFS; 732*37741Smckusick goto out; 733*37741Smckusick } 734*37741Smckusick error = VOP_SETATTR(vp, &vattr, ndp->ni_cred); 735*37741Smckusick out: 736*37741Smckusick vput(vp); 737*37741Smckusick 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; 749*37741Smckusick struct vattr vattr; 750*37741Smckusick struct vnode *vp; 751*37741Smckusick struct file *fp; 752*37741Smckusick int error; 7537701Ssam 754*37741Smckusick if (error = getvnode(uap->fd, &fp)) 755*37741Smckusick RETURN (error); 756*37741Smckusick vattr_null(&vattr); 757*37741Smckusick vattr.va_mode = uap->fmode & 07777; 758*37741Smckusick vp = (struct vnode *)fp->f_data; 759*37741Smckusick VOP_LOCK(vp); 760*37741Smckusick if (vp->v_mount->m_flag & M_RDONLY) { 761*37741Smckusick error = EROFS; 762*37741Smckusick goto out; 7637439Sroot } 764*37741Smckusick error = VOP_SETATTR(vp, &vattr, fp->f_cred); 765*37741Smckusick out: 766*37741Smckusick VOP_UNLOCK(vp); 767*37741Smckusick 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; 781*37741Smckusick register struct vnode *vp; 782*37741Smckusick struct vattr vattr; 783*37741Smckusick int error; 78437Sbill 785*37741Smckusick ndp->ni_nameiop = LOOKUP | NOFOLLOW | LOCKLEAF; 78636614Sbostic ndp->ni_segflg = UIO_USERSPACE; 78736614Sbostic ndp->ni_dirp = uap->fname; 788*37741Smckusick vattr_null(&vattr); 789*37741Smckusick vattr.va_uid = uap->uid; 790*37741Smckusick vattr.va_gid = uap->gid; 791*37741Smckusick if (error = namei(ndp)) 792*37741Smckusick RETURN (error); 793*37741Smckusick vp = ndp->ni_vp; 794*37741Smckusick if (vp->v_mount->m_flag & M_RDONLY) { 795*37741Smckusick error = EROFS; 796*37741Smckusick goto out; 797*37741Smckusick } 798*37741Smckusick error = VOP_SETATTR(vp, &vattr, ndp->ni_cred); 799*37741Smckusick out: 800*37741Smckusick vput(vp); 801*37741Smckusick 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; 814*37741Smckusick struct vattr vattr; 815*37741Smckusick struct vnode *vp; 816*37741Smckusick struct file *fp; 817*37741Smckusick int error; 8187701Ssam 819*37741Smckusick if (error = getvnode(uap->fd, &fp)) 820*37741Smckusick RETURN (error); 821*37741Smckusick vattr_null(&vattr); 822*37741Smckusick vattr.va_uid = uap->uid; 823*37741Smckusick vattr.va_gid = uap->gid; 824*37741Smckusick vp = (struct vnode *)fp->f_data; 825*37741Smckusick VOP_LOCK(vp); 826*37741Smckusick if (vp->v_mount->m_flag & M_RDONLY) { 827*37741Smckusick error = EROFS; 828*37741Smckusick goto out; 829*37741Smckusick } 830*37741Smckusick error = VOP_SETATTR(vp, &vattr, fp->f_cred); 831*37741Smckusick out: 832*37741Smckusick VOP_UNLOCK(vp); 833*37741Smckusick 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; 842*37741Smckusick register struct nameidata *ndp = &u.u_nd; 843*37741Smckusick register struct vnode *vp; 84411811Ssam struct timeval tv[2]; 845*37741Smckusick struct vattr vattr; 846*37741Smckusick int error; 84711811Ssam 848*37741Smckusick if (error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv))) 849*37741Smckusick RETURN (error); 850*37741Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 851*37741Smckusick ndp->ni_segflg = UIO_USERSPACE; 852*37741Smckusick ndp->ni_dirp = uap->fname; 853*37741Smckusick vattr_null(&vattr); 854*37741Smckusick vattr.va_atime = tv[0]; 855*37741Smckusick vattr.va_mtime = tv[1]; 856*37741Smckusick if (error = namei(ndp)) 857*37741Smckusick RETURN (error); 858*37741Smckusick vp = ndp->ni_vp; 859*37741Smckusick if (vp->v_mount->m_flag & M_RDONLY) { 860*37741Smckusick error = EROFS; 861*37741Smckusick goto out; 86221015Smckusick } 863*37741Smckusick error = VOP_SETATTR(vp, &vattr, ndp->ni_cred); 864*37741Smckusick out: 865*37741Smckusick vput(vp); 866*37741Smckusick 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; 879*37741Smckusick register struct vnode *vp; 880*37741Smckusick struct vattr vattr; 881*37741Smckusick int error; 8827701Ssam 883*37741Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 88416694Smckusick ndp->ni_segflg = UIO_USERSPACE; 88516694Smckusick ndp->ni_dirp = uap->fname; 886*37741Smckusick vattr_null(&vattr); 887*37741Smckusick vattr.va_size = uap->length; 888*37741Smckusick if (error = namei(ndp)) 889*37741Smckusick RETURN (error); 890*37741Smckusick vp = ndp->ni_vp; 891*37741Smckusick if (vp->v_type == VDIR) { 892*37741Smckusick error = EISDIR; 893*37741Smckusick goto out; 8947701Ssam } 895*37741Smckusick if (error = vn_access(vp, VWRITE, ndp->ni_cred)) 896*37741Smckusick goto out; 897*37741Smckusick error = VOP_SETATTR(vp, &vattr, ndp->ni_cred); 898*37741Smckusick out: 899*37741Smckusick vput(vp); 900*37741Smckusick 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; 912*37741Smckusick struct vattr vattr; 913*37741Smckusick struct vnode *vp; 9147701Ssam struct file *fp; 915*37741Smckusick int error; 9167701Ssam 917*37741Smckusick if (error = getvnode(uap->fd, &fp)) 918*37741Smckusick RETURN (error); 919*37741Smckusick if ((fp->f_flag & FWRITE) == 0) 920*37741Smckusick RETURN (EINVAL); 921*37741Smckusick vattr_null(&vattr); 922*37741Smckusick vattr.va_size = uap->length; 923*37741Smckusick vp = (struct vnode *)fp->f_data; 924*37741Smckusick VOP_LOCK(vp); 925*37741Smckusick if (vp->v_type == VDIR) { 926*37741Smckusick error = EISDIR; 927*37741Smckusick goto out; 9287701Ssam } 929*37741Smckusick if (error = vn_access(vp, VWRITE, fp->f_cred)) 930*37741Smckusick goto out; 931*37741Smckusick error = VOP_SETATTR(vp, &vattr, fp->f_cred); 932*37741Smckusick out: 933*37741Smckusick VOP_UNLOCK(vp); 934*37741Smckusick 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; 946*37741Smckusick int error; 9479167Ssam 948*37741Smckusick if (error = getvnode(uap->fd, &fp)) 949*37741Smckusick RETURN (error); 950*37741Smckusick error = VOP_FSYNC((struct vnode *)fp->f_data, fp->f_flag, fp->f_cred); 951*37741Smckusick 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; 966*37741Smckusick register struct vnode *tvp, *fvp, *tdvp; 96716694Smckusick register struct nameidata *ndp = &u.u_nd; 968*37741Smckusick struct nameidata tond; 969*37741Smckusick int error; 9707701Ssam 971*37741Smckusick ndp->ni_nameiop = DELETE | WANTPARENT; 97216694Smckusick ndp->ni_segflg = UIO_USERSPACE; 97316694Smckusick ndp->ni_dirp = uap->from; 974*37741Smckusick if (error = namei(ndp)) 975*37741Smckusick RETURN (error); 976*37741Smckusick fvp = ndp->ni_vp; 977*37741Smckusick bzero((caddr_t)&tond, sizeof(tond)); 978*37741Smckusick tond.ni_nameiop = RENAME | LOCKPARENT | LOCKLEAF | NOCACHE; 979*37741Smckusick tond.ni_segflg = UIO_USERSPACE; 980*37741Smckusick tond.ni_dirp = uap->to; 981*37741Smckusick tond.ni_cdir = ndp->ni_cdir; 982*37741Smckusick tond.ni_cdir->v_count++; 983*37741Smckusick tond.ni_rdir = ndp->ni_rdir; 984*37741Smckusick if (tond.ni_rdir) 985*37741Smckusick tond.ni_rdir->v_count++; 986*37741Smckusick tond.ni_cred = ndp->ni_cred; 987*37741Smckusick crhold(tond.ni_cred); 988*37741Smckusick error = namei(&tond); 989*37741Smckusick tdvp = tond.ni_dvp; 990*37741Smckusick tvp = tond.ni_vp; 991*37741Smckusick if (tvp != NULL) { 992*37741Smckusick if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 993*37741Smckusick error = EISDIR; 994*37741Smckusick goto out; 995*37741Smckusick } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 996*37741Smckusick error = ENOTDIR; 997*37741Smckusick goto out; 9989167Ssam } 9999167Ssam } 1000*37741Smckusick if (error) { 1001*37741Smckusick VOP_ABORTOP(ndp); 1002*37741Smckusick goto out1; 1003*37741Smckusick } 1004*37741Smckusick if (fvp->v_mount != tdvp->v_mount) { 1005*37741Smckusick error = EXDEV; 10069167Ssam goto out; 100710051Ssam } 1008*37741Smckusick if (fvp == tdvp || fvp == tvp) 1009*37741Smckusick error = EINVAL; 1010*37741Smckusick out: 1011*37741Smckusick if (error) { 1012*37741Smckusick VOP_ABORTOP(&tond); 1013*37741Smckusick VOP_ABORTOP(ndp); 10149167Ssam } else { 1015*37741Smckusick error = VOP_RENAME(ndp, &tond); 10169167Ssam } 1017*37741Smckusick out1: 1018*37741Smckusick vrele(tond.ni_cdir); 1019*37741Smckusick if (tond.ni_rdir) 1020*37741Smckusick vrele(tond.ni_rdir); 1021*37741Smckusick crfree(tond.ni_cred); 1022*37741Smckusick 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; 1035*37741Smckusick register struct vnode *vp; 1036*37741Smckusick struct vattr vattr; 1037*37741Smckusick int error; 103812756Ssam 1039*37741Smckusick ndp->ni_nameiop = CREATE | LOCKPARENT; 104016694Smckusick ndp->ni_segflg = UIO_USERSPACE; 104116694Smckusick ndp->ni_dirp = uap->name; 1042*37741Smckusick if (error = namei(ndp)) 1043*37741Smckusick RETURN (error); 1044*37741Smckusick vp = ndp->ni_vp; 1045*37741Smckusick if (vp != NULL) { 1046*37741Smckusick VOP_ABORTOP(ndp); 1047*37741Smckusick RETURN (EEXIST); 104812756Ssam } 1049*37741Smckusick vattr_null(&vattr); 1050*37741Smckusick vattr.va_type = VDIR; 1051*37741Smckusick vattr.va_mode = (uap->dmode & 0777) &~ u.u_cmask; 1052*37741Smckusick error = VOP_MKDIR(ndp, &vattr); 1053*37741Smckusick 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; 1065*37741Smckusick register struct vnode *vp; 1066*37741Smckusick int error; 106712756Ssam 1068*37741Smckusick ndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF; 106916694Smckusick ndp->ni_segflg = UIO_USERSPACE; 107016694Smckusick ndp->ni_dirp = uap->name; 1071*37741Smckusick if (error = namei(ndp)) 1072*37741Smckusick RETURN (error); 1073*37741Smckusick vp = ndp->ni_vp; 1074*37741Smckusick if (vp->v_type != VDIR) { 1075*37741Smckusick error = ENOTDIR; 107612756Ssam goto out; 107712756Ssam } 107812756Ssam /* 1079*37741Smckusick * No rmdir "." please. 108012756Ssam */ 1081*37741Smckusick if (ndp->ni_dvp == vp) { 1082*37741Smckusick error = EINVAL; 108312756Ssam goto out; 108412756Ssam } 108512756Ssam /* 1086*37741Smckusick * Don't unlink a mounted file. 108712756Ssam */ 1088*37741Smckusick if (vp->v_flag & VROOT) 1089*37741Smckusick error = EBUSY; 109012756Ssam out: 1091*37741Smckusick if (error) 1092*37741Smckusick VOP_ABORTOP(ndp); 1093*37741Smckusick else 1094*37741Smckusick error = VOP_RMDIR(ndp); 1095*37741Smckusick RETURN (error); 109612756Ssam } 109712756Ssam 1098*37741Smckusick /* 1099*37741Smckusick * Read a block of directory entries in a file system independent format 1100*37741Smckusick */ 1101*37741Smckusick getdirentries() 110212756Ssam { 1103*37741Smckusick register struct a { 1104*37741Smckusick int fd; 1105*37741Smckusick char *buf; 1106*37741Smckusick unsigned count; 1107*37741Smckusick long *basep; 1108*37741Smckusick } *uap = (struct a *)u.u_ap; 110916540Ssam struct file *fp; 1110*37741Smckusick struct uio auio; 1111*37741Smckusick struct iovec aiov; 1112*37741Smckusick int error; 111312756Ssam 1114*37741Smckusick if (error = getvnode(uap->fd, &fp)) 1115*37741Smckusick RETURN (error); 1116*37741Smckusick if ((fp->f_flag & FREAD) == 0) 1117*37741Smckusick RETURN (EBADF); 1118*37741Smckusick aiov.iov_base = uap->buf; 1119*37741Smckusick aiov.iov_len = uap->count; 1120*37741Smckusick auio.uio_iov = &aiov; 1121*37741Smckusick auio.uio_iovcnt = 1; 1122*37741Smckusick auio.uio_rw = UIO_READ; 1123*37741Smckusick auio.uio_segflg = UIO_USERSPACE; 1124*37741Smckusick auio.uio_resid = uap->count; 1125*37741Smckusick if (error = VOP_READDIR((struct vnode *)fp->f_data, &auio, 1126*37741Smckusick &(fp->f_offset), fp->f_cred)) 1127*37741Smckusick RETURN (error); 1128*37741Smckusick error = copyout((caddr_t)&fp->f_offset, (caddr_t)uap->basep, 1129*37741Smckusick sizeof(long)); 1130*37741Smckusick u.u_r.r_val1 = uap->count - auio.uio_resid; 1131*37741Smckusick RETURN (error); 113212756Ssam } 113312756Ssam 113412756Ssam /* 113512756Ssam * mode mask for creation of files 113612756Ssam */ 113712756Ssam umask() 113812756Ssam { 113912756Ssam register struct a { 114012756Ssam int mask; 114116694Smckusick } *uap = (struct a *)u.u_ap; 114212756Ssam 114312756Ssam u.u_r.r_val1 = u.u_cmask; 114412756Ssam u.u_cmask = uap->mask & 07777; 1145*37741Smckusick RETURN (0); 114612756Ssam } 1147*37741Smckusick 1148*37741Smckusick getvnode(fdes, fpp) 1149*37741Smckusick struct file **fpp; 1150*37741Smckusick int fdes; 1151*37741Smckusick { 1152*37741Smckusick struct file *fp; 1153*37741Smckusick 1154*37741Smckusick if ((unsigned)fdes >= NOFILE || (fp = u.u_ofile[fdes]) == NULL) 1155*37741Smckusick return (EBADF); 1156*37741Smckusick if (fp->f_type != DTYPE_VNODE) 1157*37741Smckusick return (EINVAL); 1158*37741Smckusick *fpp = fp; 1159*37741Smckusick return (0); 1160*37741Smckusick } 1161