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