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