|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1989 The Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms, with or without ! 6: * modification, are permitted provided that the following conditions ! 7: * are met: ! 8: * 1. Redistributions of source code must retain the above copyright ! 9: * notice, this list of conditions and the following disclaimer. ! 10: * 2. Redistributions in binary form must reproduce the above copyright ! 11: * notice, this list of conditions and the following disclaimer in the ! 12: * documentation and/or other materials provided with the distribution. ! 13: * 3. All advertising materials mentioning features or use of this software ! 14: * must display the following acknowledgement: ! 15: * This product includes software developed by the University of ! 16: * California, Berkeley and its contributors. ! 17: * 4. Neither the name of the University nor the names of its contributors ! 18: * may be used to endorse or promote products derived from this software ! 19: * without specific prior written permission. ! 20: * ! 21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 31: * SUCH DAMAGE. ! 32: * ! 33: * @(#)vfs_syscalls.c 7.74 (Berkeley) 6/21/91 ! 34: */ ! 35: ! 36: #include "param.h" ! 37: #include "systm.h" ! 38: #include "namei.h" ! 39: #include "filedesc.h" ! 40: #include "kernel.h" ! 41: #include "file.h" ! 42: #include "stat.h" ! 43: #include "vnode.h" ! 44: #include "mount.h" ! 45: #include "proc.h" ! 46: #include "uio.h" ! 47: #include "malloc.h" ! 48: ! 49: /* ! 50: * Virtual File System System Calls ! 51: */ ! 52: ! 53: /* ! 54: * Mount system call. ! 55: */ ! 56: /* ARGSUSED */ ! 57: mount(p, uap, retval) ! 58: struct proc *p; ! 59: register struct args { ! 60: int type; ! 61: char *dir; ! 62: int flags; ! 63: caddr_t data; ! 64: } *uap; ! 65: int *retval; ! 66: { ! 67: register struct nameidata *ndp; ! 68: register struct vnode *vp; ! 69: register struct mount *mp; ! 70: int error, flag; ! 71: struct nameidata nd; ! 72: ! 73: /* ! 74: * Must be super user ! 75: */ ! 76: if (error = suser(p->p_ucred, &p->p_acflag)) ! 77: return (error); ! 78: /* ! 79: * Get vnode to be covered ! 80: */ ! 81: ndp = &nd; ! 82: ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; ! 83: ndp->ni_segflg = UIO_USERSPACE; ! 84: ndp->ni_dirp = uap->dir; ! 85: if (error = namei(ndp, p)) ! 86: return (error); ! 87: vp = ndp->ni_vp; ! 88: if (uap->flags & MNT_UPDATE) { ! 89: if ((vp->v_flag & VROOT) == 0) { ! 90: vput(vp); ! 91: return (EINVAL); ! 92: } ! 93: mp = vp->v_mount; ! 94: /* ! 95: * We allow going from read-only to read-write, ! 96: * but not from read-write to read-only. ! 97: */ ! 98: if ((mp->mnt_flag & MNT_RDONLY) == 0 && ! 99: (uap->flags & MNT_RDONLY) != 0) { ! 100: vput(vp); ! 101: return (EOPNOTSUPP); /* Needs translation */ ! 102: } ! 103: flag = mp->mnt_flag; ! 104: mp->mnt_flag |= MNT_UPDATE; ! 105: VOP_UNLOCK(vp); ! 106: goto update; ! 107: } ! 108: vinvalbuf(vp, 1); ! 109: if (vp->v_usecount != 1) { ! 110: vput(vp); ! 111: return (EBUSY); ! 112: } ! 113: if (vp->v_type != VDIR) { ! 114: vput(vp); ! 115: return (ENOTDIR); ! 116: } ! 117: if ((unsigned long)uap->type > MOUNT_MAXTYPE || ! 118: vfssw[uap->type] == (struct vfsops *)0) { ! 119: vput(vp); ! 120: return (ENODEV); ! 121: } ! 122: ! 123: /* ! 124: * Allocate and initialize the file system. ! 125: */ ! 126: mp = (struct mount *)malloc((u_long)sizeof(struct mount), ! 127: M_MOUNT, M_WAITOK); ! 128: mp->mnt_op = vfssw[uap->type]; ! 129: mp->mnt_flag = 0; ! 130: mp->mnt_exroot = 0; ! 131: mp->mnt_mounth = NULLVP; ! 132: if (error = vfs_lock(mp)) { ! 133: free((caddr_t)mp, M_MOUNT); ! 134: vput(vp); ! 135: return (error); ! 136: } ! 137: if (vp->v_mountedhere != (struct mount *)0) { ! 138: vfs_unlock(mp); ! 139: free((caddr_t)mp, M_MOUNT); ! 140: vput(vp); ! 141: return (EBUSY); ! 142: } ! 143: vp->v_mountedhere = mp; ! 144: mp->mnt_vnodecovered = vp; ! 145: update: ! 146: /* ! 147: * Set the mount level flags. ! 148: */ ! 149: if (uap->flags & MNT_RDONLY) ! 150: mp->mnt_flag |= MNT_RDONLY; ! 151: else ! 152: mp->mnt_flag &= ~MNT_RDONLY; ! 153: if (uap->flags & MNT_NOSUID) ! 154: mp->mnt_flag |= MNT_NOSUID; ! 155: else ! 156: mp->mnt_flag &= ~MNT_NOSUID; ! 157: if (uap->flags & MNT_NOEXEC) ! 158: mp->mnt_flag |= MNT_NOEXEC; ! 159: else ! 160: mp->mnt_flag &= ~MNT_NOEXEC; ! 161: if (uap->flags & MNT_NODEV) ! 162: mp->mnt_flag |= MNT_NODEV; ! 163: else ! 164: mp->mnt_flag &= ~MNT_NODEV; ! 165: if (uap->flags & MNT_SYNCHRONOUS) ! 166: mp->mnt_flag |= MNT_SYNCHRONOUS; ! 167: else ! 168: mp->mnt_flag &= ~MNT_SYNCHRONOUS; ! 169: /* ! 170: * Mount the filesystem. ! 171: */ ! 172: error = VFS_MOUNT(mp, uap->dir, uap->data, ndp, p); ! 173: if (mp->mnt_flag & MNT_UPDATE) { ! 174: mp->mnt_flag &= ~MNT_UPDATE; ! 175: vrele(vp); ! 176: if (error) ! 177: mp->mnt_flag = flag; ! 178: return (error); ! 179: } ! 180: /* ! 181: * Put the new filesystem on the mount list after root. ! 182: */ ! 183: mp->mnt_next = rootfs->mnt_next; ! 184: mp->mnt_prev = rootfs; ! 185: rootfs->mnt_next = mp; ! 186: mp->mnt_next->mnt_prev = mp; ! 187: cache_purge(vp); ! 188: if (!error) { ! 189: VOP_UNLOCK(vp); ! 190: vfs_unlock(mp); ! 191: error = VFS_START(mp, 0, p); ! 192: } else { ! 193: vfs_remove(mp); ! 194: free((caddr_t)mp, M_MOUNT); ! 195: vput(vp); ! 196: } ! 197: return (error); ! 198: } ! 199: ! 200: /* ! 201: * Unmount system call. ! 202: * ! 203: * Note: unmount takes a path to the vnode mounted on as argument, ! 204: * not special file (as before). ! 205: */ ! 206: /* ARGSUSED */ ! 207: unmount(p, uap, retval) ! 208: struct proc *p; ! 209: register struct args { ! 210: char *pathp; ! 211: int flags; ! 212: } *uap; ! 213: int *retval; ! 214: { ! 215: register struct vnode *vp; ! 216: register struct nameidata *ndp; ! 217: struct mount *mp; ! 218: int error; ! 219: struct nameidata nd; ! 220: ! 221: /* ! 222: * Must be super user ! 223: */ ! 224: if (error = suser(p->p_ucred, &p->p_acflag)) ! 225: return (error); ! 226: ! 227: ndp = &nd; ! 228: ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW; ! 229: ndp->ni_segflg = UIO_USERSPACE; ! 230: ndp->ni_dirp = uap->pathp; ! 231: if (error = namei(ndp, p)) ! 232: return (error); ! 233: vp = ndp->ni_vp; ! 234: /* ! 235: * Must be the root of the filesystem ! 236: */ ! 237: if ((vp->v_flag & VROOT) == 0) { ! 238: vput(vp); ! 239: return (EINVAL); ! 240: } ! 241: mp = vp->v_mount; ! 242: vput(vp); ! 243: return (dounmount(mp, uap->flags, p)); ! 244: } ! 245: ! 246: /* ! 247: * Do an unmount. ! 248: */ ! 249: dounmount(mp, flags, p) ! 250: register struct mount *mp; ! 251: int flags; ! 252: struct proc *p; ! 253: { ! 254: struct vnode *coveredvp; ! 255: int error; ! 256: ! 257: coveredvp = mp->mnt_vnodecovered; ! 258: if (vfs_busy(mp)) ! 259: return (EBUSY); ! 260: mp->mnt_flag |= MNT_UNMOUNT; ! 261: if (error = vfs_lock(mp)) ! 262: return (error); ! 263: ! 264: vnode_pager_umount(mp); /* release cached vnodes */ ! 265: cache_purgevfs(mp); /* remove cache entries for this file sys */ ! 266: if ((error = VFS_SYNC(mp, MNT_WAIT)) == 0 || (flags & MNT_FORCE)) ! 267: error = VFS_UNMOUNT(mp, flags, p); ! 268: mp->mnt_flag &= ~MNT_UNMOUNT; ! 269: vfs_unbusy(mp); ! 270: if (error) { ! 271: vfs_unlock(mp); ! 272: } else { ! 273: vrele(coveredvp); ! 274: vfs_remove(mp); ! 275: free((caddr_t)mp, M_MOUNT); ! 276: } ! 277: return (error); ! 278: } ! 279: ! 280: /* ! 281: * Sync system call. ! 282: * Sync each mounted filesystem. ! 283: */ ! 284: /* ARGSUSED */ ! 285: sync(p, uap, retval) ! 286: struct proc *p; ! 287: void *uap; ! 288: int *retval; ! 289: { ! 290: register struct mount *mp; ! 291: struct mount *omp; ! 292: ! 293: mp = rootfs; ! 294: do { ! 295: /* ! 296: * The lock check below is to avoid races with mount ! 297: * and unmount. ! 298: */ ! 299: if ((mp->mnt_flag & (MNT_MLOCK|MNT_RDONLY|MNT_MPBUSY)) == 0 && ! 300: !vfs_busy(mp)) { ! 301: VFS_SYNC(mp, MNT_NOWAIT); ! 302: omp = mp; ! 303: mp = mp->mnt_next; ! 304: vfs_unbusy(omp); ! 305: } else ! 306: mp = mp->mnt_next; ! 307: } while (mp != rootfs); ! 308: return (0); ! 309: } ! 310: ! 311: /* ! 312: * Operate on filesystem quotas. ! 313: */ ! 314: /* ARGSUSED */ ! 315: quotactl(p, uap, retval) ! 316: struct proc *p; ! 317: register struct args { ! 318: char *path; ! 319: int cmd; ! 320: int uid; ! 321: caddr_t arg; ! 322: } *uap; ! 323: int *retval; ! 324: { ! 325: register struct mount *mp; ! 326: register struct nameidata *ndp; ! 327: int error; ! 328: struct nameidata nd; ! 329: ! 330: ndp = &nd; ! 331: ndp->ni_nameiop = LOOKUP | FOLLOW; ! 332: ndp->ni_segflg = UIO_USERSPACE; ! 333: ndp->ni_dirp = uap->path; ! 334: if (error = namei(ndp, p)) ! 335: return (error); ! 336: mp = ndp->ni_vp->v_mount; ! 337: vrele(ndp->ni_vp); ! 338: return (VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg, p)); ! 339: } ! 340: ! 341: /* ! 342: * Get filesystem statistics. ! 343: */ ! 344: /* ARGSUSED */ ! 345: statfs(p, uap, retval) ! 346: struct proc *p; ! 347: register struct args { ! 348: char *path; ! 349: struct statfs *buf; ! 350: } *uap; ! 351: int *retval; ! 352: { ! 353: register struct mount *mp; ! 354: register struct nameidata *ndp; ! 355: register struct statfs *sp; ! 356: int error; ! 357: struct nameidata nd; ! 358: ! 359: ndp = &nd; ! 360: ndp->ni_nameiop = LOOKUP | FOLLOW; ! 361: ndp->ni_segflg = UIO_USERSPACE; ! 362: ndp->ni_dirp = uap->path; ! 363: if (error = namei(ndp, p)) ! 364: return (error); ! 365: mp = ndp->ni_vp->v_mount; ! 366: sp = &mp->mnt_stat; ! 367: vrele(ndp->ni_vp); ! 368: if (error = VFS_STATFS(mp, sp, p)) ! 369: return (error); ! 370: sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; ! 371: return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp))); ! 372: } ! 373: ! 374: /* ! 375: * Get filesystem statistics. ! 376: */ ! 377: /* ARGSUSED */ ! 378: fstatfs(p, uap, retval) ! 379: struct proc *p; ! 380: register struct args { ! 381: int fd; ! 382: struct statfs *buf; ! 383: } *uap; ! 384: int *retval; ! 385: { ! 386: struct file *fp; ! 387: struct mount *mp; ! 388: register struct statfs *sp; ! 389: int error; ! 390: ! 391: if (error = getvnode(p->p_fd, uap->fd, &fp)) ! 392: return (error); ! 393: mp = ((struct vnode *)fp->f_data)->v_mount; ! 394: sp = &mp->mnt_stat; ! 395: if (error = VFS_STATFS(mp, sp, p)) ! 396: return (error); ! 397: sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; ! 398: return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp))); ! 399: } ! 400: ! 401: /* ! 402: * Get statistics on all filesystems. ! 403: */ ! 404: getfsstat(p, uap, retval) ! 405: struct proc *p; ! 406: register struct args { ! 407: struct statfs *buf; ! 408: long bufsize; ! 409: int flags; ! 410: } *uap; ! 411: int *retval; ! 412: { ! 413: register struct mount *mp; ! 414: register struct statfs *sp; ! 415: caddr_t sfsp; ! 416: long count, maxcount, error; ! 417: ! 418: maxcount = uap->bufsize / sizeof(struct statfs); ! 419: sfsp = (caddr_t)uap->buf; ! 420: mp = rootfs; ! 421: count = 0; ! 422: do { ! 423: if (sfsp && count < maxcount && ! 424: ((mp->mnt_flag & MNT_MLOCK) == 0)) { ! 425: sp = &mp->mnt_stat; ! 426: /* ! 427: * If MNT_NOWAIT is specified, do not refresh the ! 428: * fsstat cache. MNT_WAIT overrides MNT_NOWAIT. ! 429: */ ! 430: if (((uap->flags & MNT_NOWAIT) == 0 || ! 431: (uap->flags & MNT_WAIT)) && ! 432: (error = VFS_STATFS(mp, sp, p))) { ! 433: mp = mp->mnt_prev; ! 434: continue; ! 435: } ! 436: sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; ! 437: if (error = copyout((caddr_t)sp, sfsp, sizeof(*sp))) ! 438: return (error); ! 439: sfsp += sizeof(*sp); ! 440: } ! 441: count++; ! 442: mp = mp->mnt_prev; ! 443: } while (mp != rootfs); ! 444: if (sfsp && count > maxcount) ! 445: *retval = maxcount; ! 446: else ! 447: *retval = count; ! 448: return (0); ! 449: } ! 450: ! 451: /* ! 452: * Change current working directory to a given file descriptor. ! 453: */ ! 454: /* ARGSUSED */ ! 455: fchdir(p, uap, retval) ! 456: struct proc *p; ! 457: struct args { ! 458: int fd; ! 459: } *uap; ! 460: int *retval; ! 461: { ! 462: register struct filedesc *fdp = p->p_fd; ! 463: register struct vnode *vp; ! 464: struct file *fp; ! 465: int error; ! 466: ! 467: if (error = getvnode(fdp, uap->fd, &fp)) ! 468: return (error); ! 469: vp = (struct vnode *)fp->f_data; ! 470: VOP_LOCK(vp); ! 471: if (vp->v_type != VDIR) ! 472: error = ENOTDIR; ! 473: else ! 474: error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); ! 475: VOP_UNLOCK(vp); ! 476: if (error) ! 477: return (error); ! 478: VREF(vp); ! 479: vrele(fdp->fd_cdir); ! 480: fdp->fd_cdir = vp; ! 481: return (0); ! 482: } ! 483: ! 484: /* ! 485: * Change current working directory (``.''). ! 486: */ ! 487: /* ARGSUSED */ ! 488: chdir(p, uap, retval) ! 489: struct proc *p; ! 490: struct args { ! 491: char *fname; ! 492: } *uap; ! 493: int *retval; ! 494: { ! 495: register struct nameidata *ndp; ! 496: register struct filedesc *fdp = p->p_fd; ! 497: int error; ! 498: struct nameidata nd; ! 499: ! 500: ndp = &nd; ! 501: ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; ! 502: ndp->ni_segflg = UIO_USERSPACE; ! 503: ndp->ni_dirp = uap->fname; ! 504: if (error = chdirec(ndp, p)) ! 505: return (error); ! 506: vrele(fdp->fd_cdir); ! 507: fdp->fd_cdir = ndp->ni_vp; ! 508: return (0); ! 509: } ! 510: ! 511: /* ! 512: * Change notion of root (``/'') directory. ! 513: */ ! 514: /* ARGSUSED */ ! 515: chroot(p, uap, retval) ! 516: struct proc *p; ! 517: struct args { ! 518: char *fname; ! 519: } *uap; ! 520: int *retval; ! 521: { ! 522: register struct nameidata *ndp; ! 523: register struct filedesc *fdp = p->p_fd; ! 524: int error; ! 525: struct nameidata nd; ! 526: ! 527: if (error = suser(p->p_ucred, &p->p_acflag)) ! 528: return (error); ! 529: ndp = &nd; ! 530: ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; ! 531: ndp->ni_segflg = UIO_USERSPACE; ! 532: ndp->ni_dirp = uap->fname; ! 533: if (error = chdirec(ndp, p)) ! 534: return (error); ! 535: if (fdp->fd_rdir != NULL) ! 536: vrele(fdp->fd_rdir); ! 537: fdp->fd_rdir = ndp->ni_vp; ! 538: return (0); ! 539: } ! 540: ! 541: /* ! 542: * Common routine for chroot and chdir. ! 543: */ ! 544: chdirec(ndp, p) ! 545: struct nameidata *ndp; ! 546: struct proc *p; ! 547: { ! 548: struct vnode *vp; ! 549: int error; ! 550: ! 551: if (error = namei(ndp, p)) ! 552: return (error); ! 553: vp = ndp->ni_vp; ! 554: if (vp->v_type != VDIR) ! 555: error = ENOTDIR; ! 556: else ! 557: error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); ! 558: VOP_UNLOCK(vp); ! 559: if (error) ! 560: vrele(vp); ! 561: return (error); ! 562: } ! 563: ! 564: /* ! 565: * Open system call. ! 566: * Check permissions, allocate an open file structure, ! 567: * and call the device open routine if any. ! 568: */ ! 569: open(p, uap, retval) ! 570: struct proc *p; ! 571: register struct args { ! 572: char *fname; ! 573: int mode; ! 574: int crtmode; ! 575: } *uap; ! 576: int *retval; ! 577: { ! 578: struct nameidata *ndp; ! 579: register struct filedesc *fdp = p->p_fd; ! 580: register struct file *fp; ! 581: register struct vnode *vp; ! 582: int fmode, cmode; ! 583: struct file *nfp; ! 584: int type, indx, error; ! 585: struct flock lf; ! 586: struct nameidata nd; ! 587: extern struct fileops vnops; ! 588: ! 589: if (error = falloc(p, &nfp, &indx)) ! 590: return (error); ! 591: fp = nfp; ! 592: fmode = FFLAGS(uap->mode); ! 593: cmode = ((uap->crtmode &~ fdp->fd_cmask) & 07777) &~ S_ISVTX; ! 594: ndp = &nd; ! 595: ndp->ni_segflg = UIO_USERSPACE; ! 596: ndp->ni_dirp = uap->fname; ! 597: p->p_dupfd = -indx - 1; /* XXX check for fdopen */ ! 598: if (error = vn_open(ndp, p, fmode, cmode)) { ! 599: ffree(fp); ! 600: if (error == ENODEV && /* XXX from fdopen */ ! 601: p->p_dupfd >= 0 && ! 602: (error = dupfdopen(fdp, indx, p->p_dupfd, fmode)) == 0) { ! 603: *retval = indx; ! 604: return (0); ! 605: } ! 606: if (error == ERESTART) ! 607: error = EINTR; ! 608: fdp->fd_ofiles[indx] = NULL; ! 609: return (error); ! 610: } ! 611: vp = ndp->ni_vp; ! 612: fp->f_flag = fmode & FMASK; ! 613: if (fmode & (O_EXLOCK | O_SHLOCK)) { ! 614: lf.l_whence = SEEK_SET; ! 615: lf.l_start = 0; ! 616: lf.l_len = 0; ! 617: if (fmode & O_EXLOCK) ! 618: lf.l_type = F_WRLCK; ! 619: else ! 620: lf.l_type = F_RDLCK; ! 621: type = F_FLOCK; ! 622: if ((fmode & FNONBLOCK) == 0) ! 623: type |= F_WAIT; ! 624: if (error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) { ! 625: VOP_UNLOCK(vp); ! 626: (void) vn_close(vp, fp->f_flag, fp->f_cred, p); ! 627: ffree(fp); ! 628: fdp->fd_ofiles[indx] = NULL; ! 629: return (error); ! 630: } ! 631: fp->f_flag |= FHASLOCK; ! 632: } ! 633: VOP_UNLOCK(vp); ! 634: fp->f_type = DTYPE_VNODE; ! 635: fp->f_ops = &vnops; ! 636: fp->f_data = (caddr_t)vp; ! 637: *retval = indx; ! 638: return (0); ! 639: } ! 640: ! 641: #ifdef COMPAT_43 ! 642: /* ! 643: * Creat system call. ! 644: */ ! 645: ocreat(p, uap, retval) ! 646: struct proc *p; ! 647: register struct args { ! 648: char *fname; ! 649: int fmode; ! 650: } *uap; ! 651: int *retval; ! 652: { ! 653: struct args { ! 654: char *fname; ! 655: int mode; ! 656: int crtmode; ! 657: } openuap; ! 658: ! 659: openuap.fname = uap->fname; ! 660: openuap.crtmode = uap->fmode; ! 661: openuap.mode = O_WRONLY | O_CREAT | O_TRUNC; ! 662: return (open(p, &openuap, retval)); ! 663: } ! 664: #endif /* COMPAT_43 */ ! 665: ! 666: /* ! 667: * Mknod system call. ! 668: */ ! 669: /* ARGSUSED */ ! 670: mknod(p, uap, retval) ! 671: struct proc *p; ! 672: register struct args { ! 673: char *fname; ! 674: int fmode; ! 675: int dev; ! 676: } *uap; ! 677: int *retval; ! 678: { ! 679: register struct nameidata *ndp; ! 680: register struct vnode *vp; ! 681: struct vattr vattr; ! 682: int error; ! 683: struct nameidata nd; ! 684: ! 685: if (error = suser(p->p_ucred, &p->p_acflag)) ! 686: return (error); ! 687: ndp = &nd; ! 688: ndp->ni_nameiop = CREATE | LOCKPARENT; ! 689: ndp->ni_segflg = UIO_USERSPACE; ! 690: ndp->ni_dirp = uap->fname; ! 691: if (error = namei(ndp, p)) ! 692: return (error); ! 693: vp = ndp->ni_vp; ! 694: if (vp != NULL) { ! 695: error = EEXIST; ! 696: goto out; ! 697: } ! 698: VATTR_NULL(&vattr); ! 699: switch (uap->fmode & S_IFMT) { ! 700: ! 701: case S_IFMT: /* used by badsect to flag bad sectors */ ! 702: vattr.va_type = VBAD; ! 703: break; ! 704: case S_IFCHR: ! 705: vattr.va_type = VCHR; ! 706: break; ! 707: case S_IFBLK: ! 708: vattr.va_type = VBLK; ! 709: break; ! 710: default: ! 711: error = EINVAL; ! 712: goto out; ! 713: } ! 714: vattr.va_mode = (uap->fmode & 07777) &~ p->p_fd->fd_cmask; ! 715: vattr.va_rdev = uap->dev; ! 716: out: ! 717: if (!error) { ! 718: error = VOP_MKNOD(ndp, &vattr, p->p_ucred, p); ! 719: } else { ! 720: VOP_ABORTOP(ndp); ! 721: if (ndp->ni_dvp == vp) ! 722: vrele(ndp->ni_dvp); ! 723: else ! 724: vput(ndp->ni_dvp); ! 725: if (vp) ! 726: vrele(vp); ! 727: } ! 728: return (error); ! 729: } ! 730: ! 731: /* ! 732: * Mkfifo system call. ! 733: */ ! 734: /* ARGSUSED */ ! 735: mkfifo(p, uap, retval) ! 736: struct proc *p; ! 737: register struct args { ! 738: char *fname; ! 739: int fmode; ! 740: } *uap; ! 741: int *retval; ! 742: { ! 743: register struct nameidata *ndp; ! 744: struct vattr vattr; ! 745: int error; ! 746: struct nameidata nd; ! 747: ! 748: #ifndef FIFO ! 749: return (EOPNOTSUPP); ! 750: #else ! 751: ndp = &nd; ! 752: ndp->ni_nameiop = CREATE | LOCKPARENT; ! 753: ndp->ni_segflg = UIO_USERSPACE; ! 754: ndp->ni_dirp = uap->fname; ! 755: if (error = namei(ndp, p)) ! 756: return (error); ! 757: if (ndp->ni_vp != NULL) { ! 758: VOP_ABORTOP(ndp); ! 759: if (ndp->ni_dvp == ndp->ni_vp) ! 760: vrele(ndp->ni_dvp); ! 761: else ! 762: vput(ndp->ni_dvp); ! 763: vrele(ndp->ni_vp); ! 764: return (EEXIST); ! 765: } ! 766: VATTR_NULL(&vattr); ! 767: vattr.va_type = VFIFO; ! 768: vattr.va_mode = (uap->fmode & 07777) &~ p->p_fd->fd_cmask; ! 769: return (VOP_MKNOD(ndp, &vattr, p->p_ucred, p)); ! 770: #endif /* FIFO */ ! 771: } ! 772: ! 773: /* ! 774: * Link system call. ! 775: */ ! 776: /* ARGSUSED */ ! 777: link(p, uap, retval) ! 778: struct proc *p; ! 779: register struct args { ! 780: char *target; ! 781: char *linkname; ! 782: } *uap; ! 783: int *retval; ! 784: { ! 785: register struct nameidata *ndp; ! 786: register struct vnode *vp, *xp; ! 787: int error; ! 788: struct nameidata nd; ! 789: ! 790: ndp = &nd; ! 791: ndp->ni_nameiop = LOOKUP | FOLLOW; ! 792: ndp->ni_segflg = UIO_USERSPACE; ! 793: ndp->ni_dirp = uap->target; ! 794: if (error = namei(ndp, p)) ! 795: return (error); ! 796: vp = ndp->ni_vp; ! 797: if (vp->v_type == VDIR && ! 798: (error = suser(p->p_ucred, &p->p_acflag))) ! 799: goto out1; ! 800: ndp->ni_nameiop = CREATE | LOCKPARENT; ! 801: ndp->ni_dirp = (caddr_t)uap->linkname; ! 802: if (error = namei(ndp, p)) ! 803: goto out1; ! 804: xp = ndp->ni_vp; ! 805: if (xp != NULL) { ! 806: error = EEXIST; ! 807: goto out; ! 808: } ! 809: xp = ndp->ni_dvp; ! 810: if (vp->v_mount != xp->v_mount) ! 811: error = EXDEV; ! 812: out: ! 813: if (!error) { ! 814: error = VOP_LINK(vp, ndp, p); ! 815: } else { ! 816: VOP_ABORTOP(ndp); ! 817: if (ndp->ni_dvp == ndp->ni_vp) ! 818: vrele(ndp->ni_dvp); ! 819: else ! 820: vput(ndp->ni_dvp); ! 821: if (ndp->ni_vp) ! 822: vrele(ndp->ni_vp); ! 823: } ! 824: out1: ! 825: vrele(vp); ! 826: return (error); ! 827: } ! 828: ! 829: /* ! 830: * Make a symbolic link. ! 831: */ ! 832: /* ARGSUSED */ ! 833: symlink(p, uap, retval) ! 834: struct proc *p; ! 835: register struct args { ! 836: char *target; ! 837: char *linkname; ! 838: } *uap; ! 839: int *retval; ! 840: { ! 841: register struct nameidata *ndp; ! 842: struct vattr vattr; ! 843: char *target; ! 844: int error; ! 845: struct nameidata nd; ! 846: ! 847: ndp = &nd; ! 848: ndp->ni_segflg = UIO_USERSPACE; ! 849: ndp->ni_dirp = uap->linkname; ! 850: MALLOC(target, char *, MAXPATHLEN, M_NAMEI, M_WAITOK); ! 851: if (error = copyinstr(uap->target, target, MAXPATHLEN, (u_int *)0)) ! 852: goto out; ! 853: ndp->ni_nameiop = CREATE | LOCKPARENT; ! 854: if (error = namei(ndp, p)) ! 855: goto out; ! 856: if (ndp->ni_vp) { ! 857: VOP_ABORTOP(ndp); ! 858: if (ndp->ni_dvp == ndp->ni_vp) ! 859: vrele(ndp->ni_dvp); ! 860: else ! 861: vput(ndp->ni_dvp); ! 862: vrele(ndp->ni_vp); ! 863: error = EEXIST; ! 864: goto out; ! 865: } ! 866: VATTR_NULL(&vattr); ! 867: vattr.va_mode = 0777 &~ p->p_fd->fd_cmask; ! 868: error = VOP_SYMLINK(ndp, &vattr, target, p); ! 869: out: ! 870: FREE(target, M_NAMEI); ! 871: return (error); ! 872: } ! 873: ! 874: /* ! 875: * Delete a name from the filesystem. ! 876: */ ! 877: /* ARGSUSED */ ! 878: unlink(p, uap, retval) ! 879: struct proc *p; ! 880: struct args { ! 881: char *fname; ! 882: } *uap; ! 883: int *retval; ! 884: { ! 885: register struct nameidata *ndp; ! 886: register struct vnode *vp; ! 887: int error; ! 888: struct nameidata nd; ! 889: ! 890: ndp = &nd; ! 891: ndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF; ! 892: ndp->ni_segflg = UIO_USERSPACE; ! 893: ndp->ni_dirp = uap->fname; ! 894: if (error = namei(ndp, p)) ! 895: return (error); ! 896: vp = ndp->ni_vp; ! 897: if (vp->v_type == VDIR && ! 898: (error = suser(p->p_ucred, &p->p_acflag))) ! 899: goto out; ! 900: /* ! 901: * The root of a mounted filesystem cannot be deleted. ! 902: */ ! 903: if (vp->v_flag & VROOT) { ! 904: error = EBUSY; ! 905: goto out; ! 906: } ! 907: (void) vnode_pager_uncache(vp); ! 908: out: ! 909: if (!error) { ! 910: error = VOP_REMOVE(ndp, p); ! 911: } else { ! 912: VOP_ABORTOP(ndp); ! 913: if (ndp->ni_dvp == vp) ! 914: vrele(ndp->ni_dvp); ! 915: else ! 916: vput(ndp->ni_dvp); ! 917: vput(vp); ! 918: } ! 919: return (error); ! 920: } ! 921: ! 922: /* ! 923: * Seek system call. ! 924: */ ! 925: lseek(p, uap, retval) ! 926: struct proc *p; ! 927: register struct args { ! 928: int fdes; ! 929: off_t off; ! 930: int sbase; ! 931: } *uap; ! 932: off_t *retval; ! 933: { ! 934: struct ucred *cred = p->p_ucred; ! 935: register struct filedesc *fdp = p->p_fd; ! 936: register struct file *fp; ! 937: struct vattr vattr; ! 938: int error; ! 939: ! 940: if ((unsigned)uap->fdes >= fdp->fd_nfiles || ! 941: (fp = fdp->fd_ofiles[uap->fdes]) == NULL) ! 942: return (EBADF); ! 943: if (fp->f_type != DTYPE_VNODE) ! 944: return (ESPIPE); ! 945: switch (uap->sbase) { ! 946: ! 947: case L_INCR: ! 948: fp->f_offset += uap->off; ! 949: break; ! 950: ! 951: case L_XTND: ! 952: if (error = VOP_GETATTR((struct vnode *)fp->f_data, ! 953: &vattr, cred, p)) ! 954: return (error); ! 955: fp->f_offset = uap->off + vattr.va_size; ! 956: break; ! 957: ! 958: case L_SET: ! 959: fp->f_offset = uap->off; ! 960: break; ! 961: ! 962: default: ! 963: return (EINVAL); ! 964: } ! 965: *retval = fp->f_offset; ! 966: return (0); ! 967: } ! 968: ! 969: /* ! 970: * Check access permissions. ! 971: */ ! 972: /* ARGSUSED */ ! 973: saccess(p, uap, retval) ! 974: struct proc *p; ! 975: register struct args { ! 976: char *fname; ! 977: int fmode; ! 978: } *uap; ! 979: int *retval; ! 980: { ! 981: register struct nameidata *ndp; ! 982: register struct ucred *cred = p->p_ucred; ! 983: register struct vnode *vp; ! 984: int error, mode, svuid, svgid; ! 985: struct nameidata nd; ! 986: ! 987: ndp = &nd; ! 988: svuid = cred->cr_uid; ! 989: svgid = cred->cr_groups[0]; ! 990: cred->cr_uid = p->p_cred->p_ruid; ! 991: cred->cr_groups[0] = p->p_cred->p_rgid; ! 992: ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; ! 993: ndp->ni_segflg = UIO_USERSPACE; ! 994: ndp->ni_dirp = uap->fname; ! 995: if (error = namei(ndp, p)) ! 996: goto out1; ! 997: vp = ndp->ni_vp; ! 998: /* ! 999: * fmode == 0 means only check for exist ! 1000: */ ! 1001: if (uap->fmode) { ! 1002: mode = 0; ! 1003: if (uap->fmode & R_OK) ! 1004: mode |= VREAD; ! 1005: if (uap->fmode & W_OK) ! 1006: mode |= VWRITE; ! 1007: if (uap->fmode & X_OK) ! 1008: mode |= VEXEC; ! 1009: if ((mode & VWRITE) == 0 || (error = vn_writechk(vp)) == 0) ! 1010: error = VOP_ACCESS(vp, mode, cred, p); ! 1011: } ! 1012: vput(vp); ! 1013: out1: ! 1014: cred->cr_uid = svuid; ! 1015: cred->cr_groups[0] = svgid; ! 1016: return (error); ! 1017: } ! 1018: ! 1019: /* ! 1020: * Stat system call. ! 1021: * This version follows links. ! 1022: */ ! 1023: /* ARGSUSED */ ! 1024: stat(p, uap, retval) ! 1025: struct proc *p; ! 1026: register struct args { ! 1027: char *fname; ! 1028: struct stat *ub; ! 1029: } *uap; ! 1030: int *retval; ! 1031: { ! 1032: register struct nameidata *ndp; ! 1033: struct stat sb; ! 1034: int error; ! 1035: struct nameidata nd; ! 1036: ! 1037: ndp = &nd; ! 1038: ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW; ! 1039: ndp->ni_segflg = UIO_USERSPACE; ! 1040: ndp->ni_dirp = uap->fname; ! 1041: if (error = namei(ndp, p)) ! 1042: return (error); ! 1043: error = vn_stat(ndp->ni_vp, &sb, p); ! 1044: vput(ndp->ni_vp); ! 1045: if (error) ! 1046: return (error); ! 1047: error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb)); ! 1048: return (error); ! 1049: } ! 1050: ! 1051: /* ! 1052: * Lstat system call. ! 1053: * This version does not follow links. ! 1054: */ ! 1055: /* ARGSUSED */ ! 1056: lstat(p, uap, retval) ! 1057: struct proc *p; ! 1058: register struct args { ! 1059: char *fname; ! 1060: struct stat *ub; ! 1061: } *uap; ! 1062: int *retval; ! 1063: { ! 1064: register struct nameidata *ndp; ! 1065: struct stat sb; ! 1066: int error; ! 1067: struct nameidata nd; ! 1068: ! 1069: ndp = &nd; ! 1070: ndp->ni_nameiop = LOOKUP | LOCKLEAF | NOFOLLOW; ! 1071: ndp->ni_segflg = UIO_USERSPACE; ! 1072: ndp->ni_dirp = uap->fname; ! 1073: if (error = namei(ndp, p)) ! 1074: return (error); ! 1075: error = vn_stat(ndp->ni_vp, &sb, p); ! 1076: vput(ndp->ni_vp); ! 1077: if (error) ! 1078: return (error); ! 1079: error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb)); ! 1080: return (error); ! 1081: } ! 1082: ! 1083: /* ! 1084: * Return target name of a symbolic link. ! 1085: */ ! 1086: /* ARGSUSED */ ! 1087: readlink(p, uap, retval) ! 1088: struct proc *p; ! 1089: register struct args { ! 1090: char *name; ! 1091: char *buf; ! 1092: int count; ! 1093: } *uap; ! 1094: int *retval; ! 1095: { ! 1096: register struct nameidata *ndp; ! 1097: register struct vnode *vp; ! 1098: struct iovec aiov; ! 1099: struct uio auio; ! 1100: int error; ! 1101: struct nameidata nd; ! 1102: ! 1103: ndp = &nd; ! 1104: ndp->ni_nameiop = LOOKUP | LOCKLEAF; ! 1105: ndp->ni_segflg = UIO_USERSPACE; ! 1106: ndp->ni_dirp = uap->name; ! 1107: if (error = namei(ndp, p)) ! 1108: return (error); ! 1109: vp = ndp->ni_vp; ! 1110: if (vp->v_type != VLNK) { ! 1111: error = EINVAL; ! 1112: goto out; ! 1113: } ! 1114: aiov.iov_base = uap->buf; ! 1115: aiov.iov_len = uap->count; ! 1116: auio.uio_iov = &aiov; ! 1117: auio.uio_iovcnt = 1; ! 1118: auio.uio_offset = 0; ! 1119: auio.uio_rw = UIO_READ; ! 1120: auio.uio_segflg = UIO_USERSPACE; ! 1121: auio.uio_procp = p; ! 1122: auio.uio_resid = uap->count; ! 1123: error = VOP_READLINK(vp, &auio, p->p_ucred); ! 1124: out: ! 1125: vput(vp); ! 1126: *retval = uap->count - auio.uio_resid; ! 1127: return (error); ! 1128: } ! 1129: ! 1130: /* ! 1131: * Change flags of a file given path name. ! 1132: */ ! 1133: /* ARGSUSED */ ! 1134: chflags(p, uap, retval) ! 1135: struct proc *p; ! 1136: register struct args { ! 1137: char *fname; ! 1138: int flags; ! 1139: } *uap; ! 1140: int *retval; ! 1141: { ! 1142: register struct nameidata *ndp; ! 1143: register struct vnode *vp; ! 1144: struct vattr vattr; ! 1145: int error; ! 1146: struct nameidata nd; ! 1147: ! 1148: ndp = &nd; ! 1149: ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; ! 1150: ndp->ni_segflg = UIO_USERSPACE; ! 1151: ndp->ni_dirp = uap->fname; ! 1152: if (error = namei(ndp, p)) ! 1153: return (error); ! 1154: vp = ndp->ni_vp; ! 1155: if (vp->v_mount->mnt_flag & MNT_RDONLY) { ! 1156: error = EROFS; ! 1157: goto out; ! 1158: } ! 1159: VATTR_NULL(&vattr); ! 1160: vattr.va_flags = uap->flags; ! 1161: error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); ! 1162: out: ! 1163: vput(vp); ! 1164: return (error); ! 1165: } ! 1166: ! 1167: /* ! 1168: * Change flags of a file given a file descriptor. ! 1169: */ ! 1170: /* ARGSUSED */ ! 1171: fchflags(p, uap, retval) ! 1172: struct proc *p; ! 1173: register struct args { ! 1174: int fd; ! 1175: int flags; ! 1176: } *uap; ! 1177: int *retval; ! 1178: { ! 1179: struct vattr vattr; ! 1180: struct vnode *vp; ! 1181: struct file *fp; ! 1182: int error; ! 1183: ! 1184: if (error = getvnode(p->p_fd, uap->fd, &fp)) ! 1185: return (error); ! 1186: vp = (struct vnode *)fp->f_data; ! 1187: VOP_LOCK(vp); ! 1188: if (vp->v_mount->mnt_flag & MNT_RDONLY) { ! 1189: error = EROFS; ! 1190: goto out; ! 1191: } ! 1192: VATTR_NULL(&vattr); ! 1193: vattr.va_flags = uap->flags; ! 1194: error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); ! 1195: out: ! 1196: VOP_UNLOCK(vp); ! 1197: return (error); ! 1198: } ! 1199: ! 1200: /* ! 1201: * Change mode of a file given path name. ! 1202: */ ! 1203: /* ARGSUSED */ ! 1204: chmod(p, uap, retval) ! 1205: struct proc *p; ! 1206: register struct args { ! 1207: char *fname; ! 1208: int fmode; ! 1209: } *uap; ! 1210: int *retval; ! 1211: { ! 1212: register struct nameidata *ndp; ! 1213: register struct vnode *vp; ! 1214: struct vattr vattr; ! 1215: int error; ! 1216: struct nameidata nd; ! 1217: ! 1218: ndp = &nd; ! 1219: ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; ! 1220: ndp->ni_segflg = UIO_USERSPACE; ! 1221: ndp->ni_dirp = uap->fname; ! 1222: if (error = namei(ndp, p)) ! 1223: return (error); ! 1224: vp = ndp->ni_vp; ! 1225: if (vp->v_mount->mnt_flag & MNT_RDONLY) { ! 1226: error = EROFS; ! 1227: goto out; ! 1228: } ! 1229: VATTR_NULL(&vattr); ! 1230: vattr.va_mode = uap->fmode & 07777; ! 1231: error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); ! 1232: out: ! 1233: vput(vp); ! 1234: return (error); ! 1235: } ! 1236: ! 1237: /* ! 1238: * Change mode of a file given a file descriptor. ! 1239: */ ! 1240: /* ARGSUSED */ ! 1241: fchmod(p, uap, retval) ! 1242: struct proc *p; ! 1243: register struct args { ! 1244: int fd; ! 1245: int fmode; ! 1246: } *uap; ! 1247: int *retval; ! 1248: { ! 1249: struct vattr vattr; ! 1250: struct vnode *vp; ! 1251: struct file *fp; ! 1252: int error; ! 1253: ! 1254: if (error = getvnode(p->p_fd, uap->fd, &fp)) ! 1255: return (error); ! 1256: vp = (struct vnode *)fp->f_data; ! 1257: VOP_LOCK(vp); ! 1258: if (vp->v_mount->mnt_flag & MNT_RDONLY) { ! 1259: error = EROFS; ! 1260: goto out; ! 1261: } ! 1262: VATTR_NULL(&vattr); ! 1263: vattr.va_mode = uap->fmode & 07777; ! 1264: error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); ! 1265: out: ! 1266: VOP_UNLOCK(vp); ! 1267: return (error); ! 1268: } ! 1269: ! 1270: /* ! 1271: * Set ownership given a path name. ! 1272: */ ! 1273: /* ARGSUSED */ ! 1274: chown(p, uap, retval) ! 1275: struct proc *p; ! 1276: register struct args { ! 1277: char *fname; ! 1278: int uid; ! 1279: int gid; ! 1280: } *uap; ! 1281: int *retval; ! 1282: { ! 1283: register struct nameidata *ndp; ! 1284: register struct vnode *vp; ! 1285: struct vattr vattr; ! 1286: int error; ! 1287: struct nameidata nd; ! 1288: ! 1289: ndp = &nd; ! 1290: ndp->ni_nameiop = LOOKUP | NOFOLLOW | LOCKLEAF; ! 1291: ndp->ni_segflg = UIO_USERSPACE; ! 1292: ndp->ni_dirp = uap->fname; ! 1293: if (error = namei(ndp, p)) ! 1294: return (error); ! 1295: vp = ndp->ni_vp; ! 1296: if (vp->v_mount->mnt_flag & MNT_RDONLY) { ! 1297: error = EROFS; ! 1298: goto out; ! 1299: } ! 1300: VATTR_NULL(&vattr); ! 1301: vattr.va_uid = uap->uid; ! 1302: vattr.va_gid = uap->gid; ! 1303: error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); ! 1304: out: ! 1305: vput(vp); ! 1306: return (error); ! 1307: } ! 1308: ! 1309: /* ! 1310: * Set ownership given a file descriptor. ! 1311: */ ! 1312: /* ARGSUSED */ ! 1313: fchown(p, uap, retval) ! 1314: struct proc *p; ! 1315: register struct args { ! 1316: int fd; ! 1317: int uid; ! 1318: int gid; ! 1319: } *uap; ! 1320: int *retval; ! 1321: { ! 1322: struct vattr vattr; ! 1323: struct vnode *vp; ! 1324: struct file *fp; ! 1325: int error; ! 1326: ! 1327: if (error = getvnode(p->p_fd, uap->fd, &fp)) ! 1328: return (error); ! 1329: vp = (struct vnode *)fp->f_data; ! 1330: VOP_LOCK(vp); ! 1331: if (vp->v_mount->mnt_flag & MNT_RDONLY) { ! 1332: error = EROFS; ! 1333: goto out; ! 1334: } ! 1335: VATTR_NULL(&vattr); ! 1336: vattr.va_uid = uap->uid; ! 1337: vattr.va_gid = uap->gid; ! 1338: error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); ! 1339: out: ! 1340: VOP_UNLOCK(vp); ! 1341: return (error); ! 1342: } ! 1343: ! 1344: /* ! 1345: * Set the access and modification times of a file. ! 1346: */ ! 1347: /* ARGSUSED */ ! 1348: utimes(p, uap, retval) ! 1349: struct proc *p; ! 1350: register struct args { ! 1351: char *fname; ! 1352: struct timeval *tptr; ! 1353: } *uap; ! 1354: int *retval; ! 1355: { ! 1356: register struct nameidata *ndp; ! 1357: register struct vnode *vp; ! 1358: struct timeval tv[2]; ! 1359: struct vattr vattr; ! 1360: int error; ! 1361: struct nameidata nd; ! 1362: ! 1363: if (error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv))) ! 1364: return (error); ! 1365: ndp = &nd; ! 1366: ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; ! 1367: ndp->ni_segflg = UIO_USERSPACE; ! 1368: ndp->ni_dirp = uap->fname; ! 1369: if (error = namei(ndp, p)) ! 1370: return (error); ! 1371: vp = ndp->ni_vp; ! 1372: if (vp->v_mount->mnt_flag & MNT_RDONLY) { ! 1373: error = EROFS; ! 1374: goto out; ! 1375: } ! 1376: VATTR_NULL(&vattr); ! 1377: vattr.va_atime = tv[0]; ! 1378: vattr.va_mtime = tv[1]; ! 1379: error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); ! 1380: out: ! 1381: vput(vp); ! 1382: return (error); ! 1383: } ! 1384: ! 1385: /* ! 1386: * Truncate a file given its path name. ! 1387: */ ! 1388: /* ARGSUSED */ ! 1389: truncate(p, uap, retval) ! 1390: struct proc *p; ! 1391: register struct args { ! 1392: char *fname; ! 1393: off_t length; ! 1394: } *uap; ! 1395: int *retval; ! 1396: { ! 1397: register struct nameidata *ndp; ! 1398: register struct vnode *vp; ! 1399: struct vattr vattr; ! 1400: int error; ! 1401: struct nameidata nd; ! 1402: ! 1403: ndp = &nd; ! 1404: ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; ! 1405: ndp->ni_segflg = UIO_USERSPACE; ! 1406: ndp->ni_dirp = uap->fname; ! 1407: if (error = namei(ndp, p)) ! 1408: return (error); ! 1409: vp = ndp->ni_vp; ! 1410: if (vp->v_type == VDIR) { ! 1411: error = EISDIR; ! 1412: goto out; ! 1413: } ! 1414: if ((error = vn_writechk(vp)) || ! 1415: (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p))) ! 1416: goto out; ! 1417: VATTR_NULL(&vattr); ! 1418: vattr.va_size = uap->length; ! 1419: error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); ! 1420: out: ! 1421: vput(vp); ! 1422: return (error); ! 1423: } ! 1424: ! 1425: /* ! 1426: * Truncate a file given a file descriptor. ! 1427: */ ! 1428: /* ARGSUSED */ ! 1429: ftruncate(p, uap, retval) ! 1430: struct proc *p; ! 1431: register struct args { ! 1432: int fd; ! 1433: off_t length; ! 1434: } *uap; ! 1435: int *retval; ! 1436: { ! 1437: struct vattr vattr; ! 1438: struct vnode *vp; ! 1439: struct file *fp; ! 1440: int error; ! 1441: ! 1442: if (error = getvnode(p->p_fd, uap->fd, &fp)) ! 1443: return (error); ! 1444: if ((fp->f_flag & FWRITE) == 0) ! 1445: return (EINVAL); ! 1446: vp = (struct vnode *)fp->f_data; ! 1447: VOP_LOCK(vp); ! 1448: if (vp->v_type == VDIR) { ! 1449: error = EISDIR; ! 1450: goto out; ! 1451: } ! 1452: if (error = vn_writechk(vp)) ! 1453: goto out; ! 1454: VATTR_NULL(&vattr); ! 1455: vattr.va_size = uap->length; ! 1456: error = VOP_SETATTR(vp, &vattr, fp->f_cred, p); ! 1457: out: ! 1458: VOP_UNLOCK(vp); ! 1459: return (error); ! 1460: } ! 1461: ! 1462: /* ! 1463: * Synch an open file. ! 1464: */ ! 1465: /* ARGSUSED */ ! 1466: fsync(p, uap, retval) ! 1467: struct proc *p; ! 1468: struct args { ! 1469: int fd; ! 1470: } *uap; ! 1471: int *retval; ! 1472: { ! 1473: register struct vnode *vp; ! 1474: struct file *fp; ! 1475: int error; ! 1476: ! 1477: if (error = getvnode(p->p_fd, uap->fd, &fp)) ! 1478: return (error); ! 1479: vp = (struct vnode *)fp->f_data; ! 1480: VOP_LOCK(vp); ! 1481: error = VOP_FSYNC(vp, fp->f_flag, fp->f_cred, MNT_WAIT, p); ! 1482: VOP_UNLOCK(vp); ! 1483: return (error); ! 1484: } ! 1485: ! 1486: /* ! 1487: * Rename system call. ! 1488: * ! 1489: * Source and destination must either both be directories, or both ! 1490: * not be directories. If target is a directory, it must be empty. ! 1491: */ ! 1492: /* ARGSUSED */ ! 1493: rename(p, uap, retval) ! 1494: struct proc *p; ! 1495: register struct args { ! 1496: char *from; ! 1497: char *to; ! 1498: } *uap; ! 1499: int *retval; ! 1500: { ! 1501: register struct vnode *tvp, *fvp, *tdvp; ! 1502: struct nameidata fromnd, tond; ! 1503: int error; ! 1504: ! 1505: fromnd.ni_nameiop = DELETE | WANTPARENT | SAVESTART; ! 1506: fromnd.ni_segflg = UIO_USERSPACE; ! 1507: fromnd.ni_dirp = uap->from; ! 1508: if (error = namei(&fromnd, p)) ! 1509: return (error); ! 1510: fvp = fromnd.ni_vp; ! 1511: tond.ni_nameiop = RENAME | LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART; ! 1512: tond.ni_segflg = UIO_USERSPACE; ! 1513: tond.ni_dirp = uap->to; ! 1514: if (error = namei(&tond, p)) { ! 1515: VOP_ABORTOP(&fromnd); ! 1516: vrele(fromnd.ni_dvp); ! 1517: vrele(fvp); ! 1518: goto out1; ! 1519: } ! 1520: tdvp = tond.ni_dvp; ! 1521: tvp = tond.ni_vp; ! 1522: if (tvp != NULL) { ! 1523: if (fvp->v_type == VDIR && tvp->v_type != VDIR) { ! 1524: error = ENOTDIR; ! 1525: goto out; ! 1526: } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { ! 1527: error = EISDIR; ! 1528: goto out; ! 1529: } ! 1530: if (fvp->v_mount != tvp->v_mount) { ! 1531: error = EXDEV; ! 1532: goto out; ! 1533: } ! 1534: } ! 1535: if (fvp->v_mount != tdvp->v_mount) { ! 1536: error = EXDEV; ! 1537: goto out; ! 1538: } ! 1539: if (fvp == tdvp) ! 1540: error = EINVAL; ! 1541: /* ! 1542: * If source is the same as the destination (that is the ! 1543: * same inode number with the same name in the same directory), ! 1544: * then there is nothing to do. ! 1545: */ ! 1546: if (fvp == tvp && fromnd.ni_dvp == tdvp && ! 1547: fromnd.ni_namelen == tond.ni_namelen && ! 1548: !bcmp(fromnd.ni_ptr, tond.ni_ptr, fromnd.ni_namelen)) ! 1549: error = -1; ! 1550: out: ! 1551: if (!error) { ! 1552: error = VOP_RENAME(&fromnd, &tond, p); ! 1553: } else { ! 1554: VOP_ABORTOP(&tond); ! 1555: if (tdvp == tvp) ! 1556: vrele(tdvp); ! 1557: else ! 1558: vput(tdvp); ! 1559: if (tvp) ! 1560: vput(tvp); ! 1561: VOP_ABORTOP(&fromnd); ! 1562: vrele(fromnd.ni_dvp); ! 1563: vrele(fvp); ! 1564: } ! 1565: vrele(tond.ni_startdir); ! 1566: FREE(tond.ni_pnbuf, M_NAMEI); ! 1567: out1: ! 1568: vrele(fromnd.ni_startdir); ! 1569: FREE(fromnd.ni_pnbuf, M_NAMEI); ! 1570: if (error == -1) ! 1571: return (0); ! 1572: return (error); ! 1573: } ! 1574: ! 1575: /* ! 1576: * Mkdir system call. ! 1577: */ ! 1578: /* ARGSUSED */ ! 1579: mkdir(p, uap, retval) ! 1580: struct proc *p; ! 1581: register struct args { ! 1582: char *name; ! 1583: int dmode; ! 1584: } *uap; ! 1585: int *retval; ! 1586: { ! 1587: register struct nameidata *ndp; ! 1588: register struct vnode *vp; ! 1589: struct vattr vattr; ! 1590: int error; ! 1591: struct nameidata nd; ! 1592: ! 1593: ndp = &nd; ! 1594: ndp->ni_nameiop = CREATE | LOCKPARENT; ! 1595: ndp->ni_segflg = UIO_USERSPACE; ! 1596: ndp->ni_dirp = uap->name; ! 1597: if (error = namei(ndp, p)) ! 1598: return (error); ! 1599: vp = ndp->ni_vp; ! 1600: if (vp != NULL) { ! 1601: VOP_ABORTOP(ndp); ! 1602: if (ndp->ni_dvp == vp) ! 1603: vrele(ndp->ni_dvp); ! 1604: else ! 1605: vput(ndp->ni_dvp); ! 1606: vrele(vp); ! 1607: return (EEXIST); ! 1608: } ! 1609: VATTR_NULL(&vattr); ! 1610: vattr.va_type = VDIR; ! 1611: vattr.va_mode = (uap->dmode & 0777) &~ p->p_fd->fd_cmask; ! 1612: error = VOP_MKDIR(ndp, &vattr, p); ! 1613: if (!error) ! 1614: vput(ndp->ni_vp); ! 1615: return (error); ! 1616: } ! 1617: ! 1618: /* ! 1619: * Rmdir system call. ! 1620: */ ! 1621: /* ARGSUSED */ ! 1622: rmdir(p, uap, retval) ! 1623: struct proc *p; ! 1624: struct args { ! 1625: char *name; ! 1626: } *uap; ! 1627: int *retval; ! 1628: { ! 1629: register struct nameidata *ndp; ! 1630: register struct vnode *vp; ! 1631: int error; ! 1632: struct nameidata nd; ! 1633: ! 1634: ndp = &nd; ! 1635: ndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF; ! 1636: ndp->ni_segflg = UIO_USERSPACE; ! 1637: ndp->ni_dirp = uap->name; ! 1638: if (error = namei(ndp, p)) ! 1639: return (error); ! 1640: vp = ndp->ni_vp; ! 1641: if (vp->v_type != VDIR) { ! 1642: error = ENOTDIR; ! 1643: goto out; ! 1644: } ! 1645: /* ! 1646: * No rmdir "." please. ! 1647: */ ! 1648: if (ndp->ni_dvp == vp) { ! 1649: error = EINVAL; ! 1650: goto out; ! 1651: } ! 1652: /* ! 1653: * The root of a mounted filesystem cannot be deleted. ! 1654: */ ! 1655: if (vp->v_flag & VROOT) ! 1656: error = EBUSY; ! 1657: out: ! 1658: if (!error) { ! 1659: error = VOP_RMDIR(ndp, p); ! 1660: } else { ! 1661: VOP_ABORTOP(ndp); ! 1662: if (ndp->ni_dvp == vp) ! 1663: vrele(ndp->ni_dvp); ! 1664: else ! 1665: vput(ndp->ni_dvp); ! 1666: vput(vp); ! 1667: } ! 1668: return (error); ! 1669: } ! 1670: ! 1671: /* ! 1672: * Read a block of directory entries in a file system independent format. ! 1673: */ ! 1674: getdirentries(p, uap, retval) ! 1675: struct proc *p; ! 1676: register struct args { ! 1677: int fd; ! 1678: char *buf; ! 1679: unsigned count; ! 1680: long *basep; ! 1681: } *uap; ! 1682: int *retval; ! 1683: { ! 1684: register struct vnode *vp; ! 1685: struct file *fp; ! 1686: struct uio auio; ! 1687: struct iovec aiov; ! 1688: off_t off; ! 1689: int error, eofflag; ! 1690: ! 1691: if (error = getvnode(p->p_fd, uap->fd, &fp)) ! 1692: return (error); ! 1693: if ((fp->f_flag & FREAD) == 0) ! 1694: return (EBADF); ! 1695: vp = (struct vnode *)fp->f_data; ! 1696: if (vp->v_type != VDIR) ! 1697: return (EINVAL); ! 1698: aiov.iov_base = uap->buf; ! 1699: aiov.iov_len = uap->count; ! 1700: auio.uio_iov = &aiov; ! 1701: auio.uio_iovcnt = 1; ! 1702: auio.uio_rw = UIO_READ; ! 1703: auio.uio_segflg = UIO_USERSPACE; ! 1704: auio.uio_procp = p; ! 1705: auio.uio_resid = uap->count; ! 1706: VOP_LOCK(vp); ! 1707: auio.uio_offset = off = fp->f_offset; ! 1708: error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag); ! 1709: fp->f_offset = auio.uio_offset; ! 1710: VOP_UNLOCK(vp); ! 1711: if (error) ! 1712: return (error); ! 1713: error = copyout((caddr_t)&off, (caddr_t)uap->basep, sizeof(long)); ! 1714: *retval = uap->count - auio.uio_resid; ! 1715: return (error); ! 1716: } ! 1717: ! 1718: /* ! 1719: * Set the mode mask for creation of filesystem nodes. ! 1720: */ ! 1721: mode_t ! 1722: umask(p, uap, retval) ! 1723: struct proc *p; ! 1724: struct args { ! 1725: int mask; ! 1726: } *uap; ! 1727: int *retval; ! 1728: { ! 1729: register struct filedesc *fdp = p->p_fd; ! 1730: ! 1731: *retval = fdp->fd_cmask; ! 1732: fdp->fd_cmask = uap->mask & 07777; ! 1733: return (0); ! 1734: } ! 1735: ! 1736: /* ! 1737: * Void all references to file by ripping underlying filesystem ! 1738: * away from vnode. ! 1739: */ ! 1740: /* ARGSUSED */ ! 1741: revoke(p, uap, retval) ! 1742: struct proc *p; ! 1743: register struct args { ! 1744: char *fname; ! 1745: } *uap; ! 1746: int *retval; ! 1747: { ! 1748: register struct nameidata *ndp; ! 1749: register struct vnode *vp; ! 1750: struct vattr vattr; ! 1751: int error; ! 1752: struct nameidata nd; ! 1753: ! 1754: ndp = &nd; ! 1755: ndp->ni_nameiop = LOOKUP | FOLLOW; ! 1756: ndp->ni_segflg = UIO_USERSPACE; ! 1757: ndp->ni_dirp = uap->fname; ! 1758: if (error = namei(ndp, p)) ! 1759: return (error); ! 1760: vp = ndp->ni_vp; ! 1761: if (vp->v_type != VCHR && vp->v_type != VBLK) { ! 1762: error = EINVAL; ! 1763: goto out; ! 1764: } ! 1765: if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) ! 1766: goto out; ! 1767: if (p->p_ucred->cr_uid != vattr.va_uid && ! 1768: (error = suser(p->p_ucred, &p->p_acflag))) ! 1769: goto out; ! 1770: if (vp->v_usecount > 1 || (vp->v_flag & VALIASED)) ! 1771: vgoneall(vp); ! 1772: out: ! 1773: vrele(vp); ! 1774: return (error); ! 1775: } ! 1776: ! 1777: /* ! 1778: * Convert a user file descriptor to a kernel file entry. ! 1779: */ ! 1780: getvnode(fdp, fdes, fpp) ! 1781: struct filedesc *fdp; ! 1782: struct file **fpp; ! 1783: int fdes; ! 1784: { ! 1785: struct file *fp; ! 1786: ! 1787: if ((unsigned)fdes >= fdp->fd_nfiles || ! 1788: (fp = fdp->fd_ofiles[fdes]) == NULL) ! 1789: return (EBADF); ! 1790: if (fp->f_type != DTYPE_VNODE) ! 1791: return (EINVAL); ! 1792: *fpp = fp; ! 1793: return (0); ! 1794: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.