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