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