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