268 /* 269 * Mount the filesystem. 270 */ 271 error = VFS_MOUNT(mp, SCARG(uap, path), SCARG(uap, data), &nd, p); 272 if (mp->mnt_flag & MNT_UPDATE) { 273 vrele(vp); 274 if (mp->mnt_kern_flag & MNTK_WANTRDWR) 275 mp->mnt_flag &= ~MNT_RDONLY; 276 mp->mnt_flag &=~ (MNT_UPDATE | MNT_RELOAD | MNT_FORCE); 277 mp->mnt_kern_flag &=~ (MNTK_WANTRDWR); 278 if (error) 279 mp->mnt_flag = flag; 280 mp->mnt_kern_flag = flag2; 281 vfs_unbusy(mp, p); 282 return (error); 283 } 284 /* 285 * Put the new filesystem on the mount list after root. 286 */ 287 cache_purge(vp); 288 if (!error) { 289 simple_lock(&mountlist_slock); 290 CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list); 291 simple_unlock(&mountlist_slock); 292 checkdirs(vp); 293 VOP_UNLOCK(vp, 0, p); 294 vfs_unbusy(mp, p); 295 if (error = VFS_START(mp, 0, p)) 296 vrele(vp); 297 } else { 298 mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0; 299 mp->mnt_vfc->vfc_refcount--; 300 vfs_unbusy(mp, p); 301 free((caddr_t)mp, M_MOUNT); 302 vput(vp); 303 } 304 return (error); 305} 306 307/* 308 * Scan all active processes to see if any of them have a current 309 * or root directory onto which the new filesystem has just been 310 * mounted. If so, replace them with the new mount point. 311 */ 312static void 313checkdirs(olddp) 314 struct vnode *olddp; 315{ 316 struct filedesc *fdp; 317 struct vnode *newdp; 318 struct proc *p; 319 320 if (olddp->v_usecount == 1) 321 return; 322 if (VFS_ROOT(olddp->v_mountedhere, &newdp)) 323 panic("mount: lost mount"); 324 for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) { 325 fdp = p->p_fd; 326 if (fdp->fd_cdir == olddp) { 327 vrele(fdp->fd_cdir); 328 VREF(newdp); 329 fdp->fd_cdir = newdp; 330 } 331 if (fdp->fd_rdir == olddp) { 332 vrele(fdp->fd_rdir); 333 VREF(newdp); 334 fdp->fd_rdir = newdp; 335 } 336 } 337 if (rootvnode == olddp) { 338 vrele(rootvnode); 339 VREF(newdp); 340 rootvnode = newdp; 341 } 342 vput(newdp); 343} 344 345/* 346 * Unmount a file system. 347 * 348 * Note: unmount takes a path to the vnode mounted on as argument, 349 * not special file (as before). 350 */ 351#ifndef _SYS_SYSPROTO_H_ 352struct unmount_args { 353 char *path; 354 int flags; 355}; 356#endif 357/* ARGSUSED */ 358int 359unmount(p, uap) 360 struct proc *p; 361 register struct unmount_args /* { 362 syscallarg(char *) path; 363 syscallarg(int) flags; 364 } */ *uap; 365{ 366 register struct vnode *vp; 367 struct mount *mp; 368 int error; 369 struct nameidata nd; 370 371 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 372 SCARG(uap, path), p); 373 if (error = namei(&nd)) 374 return (error); 375 vp = nd.ni_vp; 376 mp = vp->v_mount; 377 378 /* 379 * Only root, or the user that did the original mount is 380 * permitted to unmount this filesystem. 381 */ 382 if ((mp->mnt_stat.f_owner != p->p_ucred->cr_uid) && 383 (error = suser(p->p_ucred, &p->p_acflag))) { 384 vput(vp); 385 return (error); 386 } 387 388 /* 389 * Don't allow unmounting the root file system. 390 */ 391 if (mp->mnt_flag & MNT_ROOTFS) { 392 vput(vp); 393 return (EINVAL); 394 } 395 396 /* 397 * Must be the root of the filesystem 398 */ 399 if ((vp->v_flag & VROOT) == 0) { 400 vput(vp); 401 return (EINVAL); 402 } 403 vput(vp); 404 return (dounmount(mp, SCARG(uap, flags), p)); 405} 406 407/* 408 * Do the actual file system unmount. 409 */ 410int 411dounmount(mp, flags, p) 412 register struct mount *mp; 413 int flags; 414 struct proc *p; 415{ 416 struct vnode *coveredvp; 417 int error; 418 419 simple_lock(&mountlist_slock); 420 mp->mnt_kern_flag |= MNTK_UNMOUNT; 421 lockmgr(&mp->mnt_lock, LK_DRAIN | LK_INTERLOCK, &mountlist_slock, p); 422 423 if (mp->mnt_flag & MNT_EXPUBLIC) 424 vfs_setpublicfs(NULL, NULL, NULL); 425 426 mp->mnt_flag &=~ MNT_ASYNC; 427 vfs_msync(mp, MNT_NOWAIT); 428 vnode_pager_umount(mp); /* release cached vnodes */ 429 cache_purgevfs(mp); /* remove cache entries for this file sys */ 430 if (((mp->mnt_flag & MNT_RDONLY) || 431 (error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0) || 432 (flags & MNT_FORCE)) 433 error = VFS_UNMOUNT(mp, flags, p); 434 simple_lock(&mountlist_slock); 435 if (error) { 436 mp->mnt_kern_flag &= ~MNTK_UNMOUNT; 437 lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK | LK_REENABLE, 438 &mountlist_slock, p); 439 return (error); 440 } 441 CIRCLEQ_REMOVE(&mountlist, mp, mnt_list); 442 if ((coveredvp = mp->mnt_vnodecovered) != NULLVP) { 443 coveredvp->v_mountedhere = (struct mount *)0; 444 vrele(coveredvp); 445 } 446 mp->mnt_vfc->vfc_refcount--; 447 if (mp->mnt_vnodelist.lh_first != NULL) 448 panic("unmount: dangling vnode"); 449 lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK, &mountlist_slock, p); 450 if (mp->mnt_kern_flag & MNTK_MWAIT) 451 wakeup((caddr_t)mp); 452 free((caddr_t)mp, M_MOUNT); 453 return (0); 454} 455 456/* 457 * Sync each mounted filesystem. 458 */ 459#ifndef _SYS_SYSPROTO_H_ 460struct sync_args { 461 int dummy; 462}; 463#endif 464 465#ifdef DEBUG 466int syncprt = 0; 467SYSCTL_INT(_debug, 0, syncprt, CTLFLAG_RW, &syncprt, 0, ""); 468#endif 469 470/* ARGSUSED */ 471int 472sync(p, uap) 473 struct proc *p; 474 struct sync_args *uap; 475{ 476 register struct mount *mp, *nmp; 477 int asyncflag; 478 479 simple_lock(&mountlist_slock); 480 for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) { 481 if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) { 482 nmp = mp->mnt_list.cqe_next; 483 continue; 484 } 485 if ((mp->mnt_flag & MNT_RDONLY) == 0) { 486 asyncflag = mp->mnt_flag & MNT_ASYNC; 487 mp->mnt_flag &= ~MNT_ASYNC; 488 vfs_msync(mp, MNT_NOWAIT); 489 VFS_SYNC(mp, MNT_NOWAIT, p != NULL ? p->p_ucred : NOCRED, p); 490 if (asyncflag) 491 mp->mnt_flag |= MNT_ASYNC; 492 } 493 simple_lock(&mountlist_slock); 494 nmp = mp->mnt_list.cqe_next; 495 vfs_unbusy(mp, p); 496 } 497 simple_unlock(&mountlist_slock); 498#if 0 499/* 500 * XXX don't call vfs_bufstats() yet because that routine 501 * was not imported in the Lite2 merge. 502 */ 503#ifdef DIAGNOSTIC 504 if (syncprt) 505 vfs_bufstats(); 506#endif /* DIAGNOSTIC */ 507#endif 508 return (0); 509} 510 511/* 512 * Change filesystem quotas. 513 */ 514#ifndef _SYS_SYSPROTO_H_ 515struct quotactl_args { 516 char *path; 517 int cmd; 518 int uid; 519 caddr_t arg; 520}; 521#endif 522/* ARGSUSED */ 523int 524quotactl(p, uap) 525 struct proc *p; 526 register struct quotactl_args /* { 527 syscallarg(char *) path; 528 syscallarg(int) cmd; 529 syscallarg(int) uid; 530 syscallarg(caddr_t) arg; 531 } */ *uap; 532{ 533 register struct mount *mp; 534 int error; 535 struct nameidata nd; 536 537 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 538 if (error = namei(&nd)) 539 return (error); 540 mp = nd.ni_vp->v_mount; 541 vrele(nd.ni_vp); 542 return (VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid), 543 SCARG(uap, arg), p)); 544} 545 546/* 547 * Get filesystem statistics. 548 */ 549#ifndef _SYS_SYSPROTO_H_ 550struct statfs_args { 551 char *path; 552 struct statfs *buf; 553}; 554#endif 555/* ARGSUSED */ 556int 557statfs(p, uap) 558 struct proc *p; 559 register struct statfs_args /* { 560 syscallarg(char *) path; 561 syscallarg(struct statfs *) buf; 562 } */ *uap; 563{ 564 register struct mount *mp; 565 register struct statfs *sp; 566 int error; 567 struct nameidata nd; 568 struct statfs sb; 569 570 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 571 if (error = namei(&nd)) 572 return (error); 573 mp = nd.ni_vp->v_mount; 574 sp = &mp->mnt_stat; 575 vrele(nd.ni_vp); 576 error = VFS_STATFS(mp, sp, p); 577 if (error) 578 return (error); 579 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 580 if (p->p_ucred->cr_uid != 0) { 581 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); 582 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; 583 sp = &sb; 584 } 585 return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp))); 586} 587 588/* 589 * Get filesystem statistics. 590 */ 591#ifndef _SYS_SYSPROTO_H_ 592struct fstatfs_args { 593 int fd; 594 struct statfs *buf; 595}; 596#endif 597/* ARGSUSED */ 598int 599fstatfs(p, uap) 600 struct proc *p; 601 register struct fstatfs_args /* { 602 syscallarg(int) fd; 603 syscallarg(struct statfs *) buf; 604 } */ *uap; 605{ 606 struct file *fp; 607 struct mount *mp; 608 register struct statfs *sp; 609 int error; 610 struct statfs sb; 611 612 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 613 return (error); 614 mp = ((struct vnode *)fp->f_data)->v_mount; 615 sp = &mp->mnt_stat; 616 error = VFS_STATFS(mp, sp, p); 617 if (error) 618 return (error); 619 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 620 if (p->p_ucred->cr_uid != 0) { 621 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); 622 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; 623 sp = &sb; 624 } 625 return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp))); 626} 627 628/* 629 * Get statistics on all filesystems. 630 */ 631#ifndef _SYS_SYSPROTO_H_ 632struct getfsstat_args { 633 struct statfs *buf; 634 long bufsize; 635 int flags; 636}; 637#endif 638int 639getfsstat(p, uap) 640 struct proc *p; 641 register struct getfsstat_args /* { 642 syscallarg(struct statfs *) buf; 643 syscallarg(long) bufsize; 644 syscallarg(int) flags; 645 } */ *uap; 646{ 647 register struct mount *mp, *nmp; 648 register struct statfs *sp; 649 caddr_t sfsp; 650 long count, maxcount, error; 651 652 maxcount = SCARG(uap, bufsize) / sizeof(struct statfs); 653 sfsp = (caddr_t)SCARG(uap, buf); 654 count = 0; 655 simple_lock(&mountlist_slock); 656 for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) { 657 if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) { 658 nmp = mp->mnt_list.cqe_next; 659 continue; 660 } 661 if (sfsp && count < maxcount) { 662 sp = &mp->mnt_stat; 663 /* 664 * If MNT_NOWAIT is specified, do not refresh the 665 * fsstat cache. MNT_WAIT overrides MNT_NOWAIT. 666 */ 667 if (((SCARG(uap, flags) & MNT_NOWAIT) == 0 || 668 (SCARG(uap, flags) & MNT_WAIT)) && 669 (error = VFS_STATFS(mp, sp, p))) { 670 simple_lock(&mountlist_slock); 671 nmp = mp->mnt_list.cqe_next; 672 vfs_unbusy(mp, p); 673 continue; 674 } 675 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 676 error = copyout((caddr_t)sp, sfsp, sizeof(*sp)); 677 if (error) { 678 vfs_unbusy(mp, p); 679 return (error); 680 } 681 sfsp += sizeof(*sp); 682 } 683 count++; 684 simple_lock(&mountlist_slock); 685 nmp = mp->mnt_list.cqe_next; 686 vfs_unbusy(mp, p); 687 } 688 simple_unlock(&mountlist_slock); 689 if (sfsp && count > maxcount) 690 p->p_retval[0] = maxcount; 691 else 692 p->p_retval[0] = count; 693 return (0); 694} 695 696/* 697 * Change current working directory to a given file descriptor. 698 */ 699#ifndef _SYS_SYSPROTO_H_ 700struct fchdir_args { 701 int fd; 702}; 703#endif 704/* ARGSUSED */ 705int 706fchdir(p, uap) 707 struct proc *p; 708 struct fchdir_args /* { 709 syscallarg(int) fd; 710 } */ *uap; 711{ 712 register struct filedesc *fdp = p->p_fd; 713 struct vnode *vp, *tdp; 714 struct mount *mp; 715 struct file *fp; 716 int error; 717 718 if (error = getvnode(fdp, SCARG(uap, fd), &fp)) 719 return (error); 720 vp = (struct vnode *)fp->f_data; 721 VREF(vp); 722 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 723 if (vp->v_type != VDIR) 724 error = ENOTDIR; 725 else 726 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); 727 while (!error && (mp = vp->v_mountedhere) != NULL) { 728 if (vfs_busy(mp, 0, 0, p)) 729 continue; 730 error = VFS_ROOT(mp, &tdp); 731 vfs_unbusy(mp, p); 732 if (error) 733 break; 734 vput(vp); 735 vp = tdp; 736 } 737 if (error) { 738 vput(vp); 739 return (error); 740 } 741 VOP_UNLOCK(vp, 0, p); 742 vrele(fdp->fd_cdir); 743 fdp->fd_cdir = vp; 744 return (0); 745} 746 747/* 748 * Change current working directory (``.''). 749 */ 750#ifndef _SYS_SYSPROTO_H_ 751struct chdir_args { 752 char *path; 753}; 754#endif 755/* ARGSUSED */ 756int 757chdir(p, uap) 758 struct proc *p; 759 struct chdir_args /* { 760 syscallarg(char *) path; 761 } */ *uap; 762{ 763 register struct filedesc *fdp = p->p_fd; 764 int error; 765 struct nameidata nd; 766 767 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 768 SCARG(uap, path), p); 769 if (error = change_dir(&nd, p)) 770 return (error); 771 vrele(fdp->fd_cdir); 772 fdp->fd_cdir = nd.ni_vp; 773 return (0); 774} 775 776/* 777 * Change notion of root (``/'') directory. 778 */ 779#ifndef _SYS_SYSPROTO_H_ 780struct chroot_args { 781 char *path; 782}; 783#endif 784/* ARGSUSED */ 785int 786chroot(p, uap) 787 struct proc *p; 788 struct chroot_args /* { 789 syscallarg(char *) path; 790 } */ *uap; 791{ 792 register struct filedesc *fdp = p->p_fd; 793 int error; 794 struct nameidata nd; 795 796 error = suser(p->p_ucred, &p->p_acflag); 797 if (error) 798 return (error); 799 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 800 SCARG(uap, path), p); 801 if (error = change_dir(&nd, p)) 802 return (error); 803 if (fdp->fd_rdir != NULL) 804 vrele(fdp->fd_rdir); 805 fdp->fd_rdir = nd.ni_vp; 806 return (0); 807} 808 809/* 810 * Common routine for chroot and chdir. 811 */ 812static int 813change_dir(ndp, p) 814 register struct nameidata *ndp; 815 struct proc *p; 816{ 817 struct vnode *vp; 818 int error; 819 820 error = namei(ndp); 821 if (error) 822 return (error); 823 vp = ndp->ni_vp; 824 if (vp->v_type != VDIR) 825 error = ENOTDIR; 826 else 827 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); 828 if (error) 829 vput(vp); 830 else 831 VOP_UNLOCK(vp, 0, p); 832 return (error); 833} 834 835/* 836 * Check permissions, allocate an open file structure, 837 * and call the device open routine if any. 838 */ 839#ifndef _SYS_SYSPROTO_H_ 840struct open_args { 841 char *path; 842 int flags; 843 int mode; 844}; 845#endif 846int 847open(p, uap) 848 struct proc *p; 849 register struct open_args /* { 850 syscallarg(char *) path; 851 syscallarg(int) flags; 852 syscallarg(int) mode; 853 } */ *uap; 854{ 855 register struct filedesc *fdp = p->p_fd; 856 register struct file *fp; 857 register struct vnode *vp; 858 int cmode, flags, oflags; 859 struct file *nfp; 860 int type, indx, error; 861 struct flock lf; 862 struct nameidata nd; 863 864 oflags = SCARG(uap, flags); 865 if ((oflags & O_ACCMODE) == O_ACCMODE) 866 return (EINVAL); 867 flags = FFLAGS(oflags); 868 error = falloc(p, &nfp, &indx); 869 if (error) 870 return (error); 871 fp = nfp; 872 cmode = ((SCARG(uap, mode) &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT; 873 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 874 p->p_dupfd = -indx - 1; /* XXX check for fdopen */ 875 error = vn_open(&nd, flags, cmode); 876 if (error) { 877 ffree(fp); 878 if ((error == ENODEV || error == ENXIO) && 879 p->p_dupfd >= 0 && /* XXX from fdopen */ 880 (error = 881 dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) { 882 p->p_retval[0] = indx; 883 return (0); 884 } 885 if (error == ERESTART) 886 error = EINTR; 887 fdp->fd_ofiles[indx] = NULL; 888 return (error); 889 } 890 p->p_dupfd = 0; 891 vp = nd.ni_vp; 892 893 fp->f_flag = flags & FMASK; 894 fp->f_type = (vp->v_type == VFIFO ? DTYPE_FIFO : DTYPE_VNODE); 895 fp->f_ops = &vnops; 896 fp->f_data = (caddr_t)vp; 897 if (flags & (O_EXLOCK | O_SHLOCK)) { 898 lf.l_whence = SEEK_SET; 899 lf.l_start = 0; 900 lf.l_len = 0; 901 if (flags & O_EXLOCK) 902 lf.l_type = F_WRLCK; 903 else 904 lf.l_type = F_RDLCK; 905 type = F_FLOCK; 906 if ((flags & FNONBLOCK) == 0) 907 type |= F_WAIT; 908 VOP_UNLOCK(vp, 0, p); 909 if (error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) { 910 (void) vn_close(vp, fp->f_flag, fp->f_cred, p); 911 ffree(fp); 912 fdp->fd_ofiles[indx] = NULL; 913 return (error); 914 } 915 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 916 fp->f_flag |= FHASLOCK; 917 } 918 VOP_UNLOCK(vp, 0, p); 919 p->p_retval[0] = indx; 920 return (0); 921} 922 923#ifdef COMPAT_43 924/* 925 * Create a file. 926 */ 927#ifndef _SYS_SYSPROTO_H_ 928struct ocreat_args { 929 char *path; 930 int mode; 931}; 932#endif 933int 934ocreat(p, uap) 935 struct proc *p; 936 register struct ocreat_args /* { 937 syscallarg(char *) path; 938 syscallarg(int) mode; 939 } */ *uap; 940{ 941 struct open_args /* { 942 syscallarg(char *) path; 943 syscallarg(int) flags; 944 syscallarg(int) mode; 945 } */ nuap; 946 947 SCARG(&nuap, path) = SCARG(uap, path); 948 SCARG(&nuap, mode) = SCARG(uap, mode); 949 SCARG(&nuap, flags) = O_WRONLY | O_CREAT | O_TRUNC; 950 return (open(p, &nuap)); 951} 952#endif /* COMPAT_43 */ 953 954/* 955 * Create a special file. 956 */ 957#ifndef _SYS_SYSPROTO_H_ 958struct mknod_args { 959 char *path; 960 int mode; 961 int dev; 962}; 963#endif 964/* ARGSUSED */ 965int 966mknod(p, uap) 967 struct proc *p; 968 register struct mknod_args /* { 969 syscallarg(char *) path; 970 syscallarg(int) mode; 971 syscallarg(int) dev; 972 } */ *uap; 973{ 974 register struct vnode *vp; 975 struct vattr vattr; 976 int error; 977 int whiteout; 978 struct nameidata nd; 979 980 error = suser(p->p_ucred, &p->p_acflag); 981 if (error) 982 return (error); 983 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); 984 if (error = namei(&nd)) 985 return (error); 986 vp = nd.ni_vp; 987 if (vp != NULL) 988 error = EEXIST; 989 else { 990 VATTR_NULL(&vattr); 991 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask; 992 vattr.va_rdev = SCARG(uap, dev); 993 whiteout = 0; 994 995 switch (SCARG(uap, mode) & S_IFMT) { 996 case S_IFMT: /* used by badsect to flag bad sectors */ 997 vattr.va_type = VBAD; 998 break; 999 case S_IFCHR: 1000 vattr.va_type = VCHR; 1001 break; 1002 case S_IFBLK: 1003 vattr.va_type = VBLK; 1004 break; 1005 case S_IFWHT: 1006 whiteout = 1; 1007 break; 1008 default: 1009 error = EINVAL; 1010 break; 1011 } 1012 } 1013 if (!error) { 1014 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1015 if (whiteout) { 1016 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE); 1017 if (error) 1018 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1019 vput(nd.ni_dvp); 1020 } else { 1021 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, 1022 &nd.ni_cnd, &vattr); 1023 } 1024 } else { 1025 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1026 if (nd.ni_dvp == vp) 1027 vrele(nd.ni_dvp); 1028 else 1029 vput(nd.ni_dvp); 1030 if (vp) 1031 vrele(vp); 1032 } 1033 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mknod"); 1034 ASSERT_VOP_UNLOCKED(nd.ni_vp, "mknod"); 1035 return (error); 1036} 1037 1038/* 1039 * Create a named pipe. 1040 */ 1041#ifndef _SYS_SYSPROTO_H_ 1042struct mkfifo_args { 1043 char *path; 1044 int mode; 1045}; 1046#endif 1047/* ARGSUSED */ 1048int 1049mkfifo(p, uap) 1050 struct proc *p; 1051 register struct mkfifo_args /* { 1052 syscallarg(char *) path; 1053 syscallarg(int) mode; 1054 } */ *uap; 1055{ 1056 struct vattr vattr; 1057 int error; 1058 struct nameidata nd; 1059 1060 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); 1061 if (error = namei(&nd)) 1062 return (error); 1063 if (nd.ni_vp != NULL) { 1064 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1065 if (nd.ni_dvp == nd.ni_vp) 1066 vrele(nd.ni_dvp); 1067 else 1068 vput(nd.ni_dvp); 1069 vrele(nd.ni_vp); 1070 return (EEXIST); 1071 } 1072 VATTR_NULL(&vattr); 1073 vattr.va_type = VFIFO; 1074 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask; 1075 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1076 return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr)); 1077} 1078 1079/* 1080 * Make a hard file link. 1081 */ 1082#ifndef _SYS_SYSPROTO_H_ 1083struct link_args { 1084 char *path; 1085 char *link; 1086}; 1087#endif 1088/* ARGSUSED */ 1089int 1090link(p, uap) 1091 struct proc *p; 1092 register struct link_args /* { 1093 syscallarg(char *) path; 1094 syscallarg(char *) link; 1095 } */ *uap; 1096{ 1097 register struct vnode *vp; 1098 struct nameidata nd; 1099 int error; 1100 1101 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1102 if (error = namei(&nd)) 1103 return (error); 1104 vp = nd.ni_vp; 1105 if (vp->v_type == VDIR) 1106 error = EPERM; /* POSIX */ 1107 else { 1108 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p); 1109 error = namei(&nd); 1110 if (!error) { 1111 if (nd.ni_vp != NULL) { 1112 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1113 if (nd.ni_dvp == nd.ni_vp) 1114 vrele(nd.ni_dvp); 1115 else 1116 vput(nd.ni_dvp); 1117 if (nd.ni_vp) 1118 vrele(nd.ni_vp); 1119 error = EEXIST; 1120 } else { 1121 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, 1122 LEASE_WRITE); 1123 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1124 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd); 1125 } 1126 } 1127 } 1128 vrele(vp); 1129 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "link"); 1130 ASSERT_VOP_UNLOCKED(nd.ni_vp, "link"); 1131 return (error); 1132} 1133 1134/* 1135 * Make a symbolic link. 1136 */ 1137#ifndef _SYS_SYSPROTO_H_ 1138struct symlink_args { 1139 char *path; 1140 char *link; 1141}; 1142#endif 1143/* ARGSUSED */ 1144int 1145symlink(p, uap) 1146 struct proc *p; 1147 register struct symlink_args /* { 1148 syscallarg(char *) path; 1149 syscallarg(char *) link; 1150 } */ *uap; 1151{ 1152 struct vattr vattr; 1153 char *path; 1154 int error; 1155 struct nameidata nd; 1156 1157 path = zalloc(namei_zone); 1158 if (error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL)) 1159 goto out; 1160 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p); 1161 if (error = namei(&nd)) 1162 goto out; 1163 if (nd.ni_vp) { 1164 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1165 if (nd.ni_dvp == nd.ni_vp) 1166 vrele(nd.ni_dvp); 1167 else 1168 vput(nd.ni_dvp); 1169 vrele(nd.ni_vp); 1170 error = EEXIST; 1171 goto out; 1172 } 1173 VATTR_NULL(&vattr); 1174 vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask; 1175 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1176 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path); 1177 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "symlink"); 1178 ASSERT_VOP_UNLOCKED(nd.ni_vp, "symlink"); 1179out: 1180 zfree(namei_zone, path); 1181 return (error); 1182} 1183 1184/* 1185 * Delete a whiteout from the filesystem. 1186 */ 1187/* ARGSUSED */ 1188int 1189undelete(p, uap) 1190 struct proc *p; 1191 register struct undelete_args /* { 1192 syscallarg(char *) path; 1193 } */ *uap; 1194{ 1195 int error; 1196 struct nameidata nd; 1197 1198 NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE, 1199 SCARG(uap, path), p); 1200 error = namei(&nd); 1201 if (error) 1202 return (error); 1203 1204 if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) { 1205 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1206 if (nd.ni_dvp == nd.ni_vp) 1207 vrele(nd.ni_dvp); 1208 else 1209 vput(nd.ni_dvp); 1210 if (nd.ni_vp) 1211 vrele(nd.ni_vp); 1212 return (EEXIST); 1213 } 1214 1215 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1216 if (error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE)) 1217 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1218 vput(nd.ni_dvp); 1219 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "undelete"); 1220 ASSERT_VOP_UNLOCKED(nd.ni_vp, "undelete"); 1221 return (error); 1222} 1223 1224/* 1225 * Delete a name from the filesystem. 1226 */ 1227#ifndef _SYS_SYSPROTO_H_ 1228struct unlink_args { 1229 char *path; 1230}; 1231#endif 1232/* ARGSUSED */ 1233int 1234unlink(p, uap) 1235 struct proc *p; 1236 struct unlink_args /* { 1237 syscallarg(char *) path; 1238 } */ *uap; 1239{ 1240 register struct vnode *vp; 1241 int error; 1242 struct nameidata nd; 1243 1244 NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); 1245 if (error = namei(&nd)) 1246 return (error); 1247 vp = nd.ni_vp; 1248 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1249 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1250 1251 if (vp->v_type == VDIR) 1252 error = EPERM; /* POSIX */ 1253 else { 1254 /* 1255 * The root of a mounted filesystem cannot be deleted. 1256 * 1257 * XXX: can this only be a VDIR case? 1258 */ 1259 if (vp->v_flag & VROOT) 1260 error = EBUSY; 1261 else 1262 (void) vnode_pager_uncache(vp, p); 1263 } 1264 1265 if (!error) { 1266 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1267 error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 1268 } else { 1269 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1270 if (nd.ni_dvp == vp) 1271 vrele(nd.ni_dvp); 1272 else 1273 vput(nd.ni_dvp); 1274 if (vp != NULLVP) 1275 vput(vp); 1276 } 1277 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "unlink"); 1278 ASSERT_VOP_UNLOCKED(nd.ni_vp, "unlink"); 1279 return (error); 1280} 1281 1282/* 1283 * Reposition read/write file offset. 1284 */ 1285#ifndef _SYS_SYSPROTO_H_ 1286struct lseek_args { 1287 int fd; 1288 int pad; 1289 off_t offset; 1290 int whence; 1291}; 1292#endif 1293int 1294lseek(p, uap) 1295 struct proc *p; 1296 register struct lseek_args /* { 1297 syscallarg(int) fd; 1298 syscallarg(int) pad; 1299 syscallarg(off_t) offset; 1300 syscallarg(int) whence; 1301 } */ *uap; 1302{ 1303 struct ucred *cred = p->p_ucred; 1304 register struct filedesc *fdp = p->p_fd; 1305 register struct file *fp; 1306 struct vattr vattr; 1307 int error; 1308 1309 if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles || 1310 (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL) 1311 return (EBADF); 1312 if (fp->f_type != DTYPE_VNODE) 1313 return (ESPIPE); 1314 switch (SCARG(uap, whence)) { 1315 case L_INCR: 1316 fp->f_offset += SCARG(uap, offset); 1317 break; 1318 case L_XTND: 1319 error=VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p); 1320 if (error) 1321 return (error); 1322 fp->f_offset = SCARG(uap, offset) + vattr.va_size; 1323 break; 1324 case L_SET: 1325 fp->f_offset = SCARG(uap, offset); 1326 break; 1327 default: 1328 return (EINVAL); 1329 } 1330 *(off_t *)(p->p_retval) = fp->f_offset; 1331 return (0); 1332} 1333 1334#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1335/* 1336 * Reposition read/write file offset. 1337 */ 1338#ifndef _SYS_SYSPROTO_H_ 1339struct olseek_args { 1340 int fd; 1341 long offset; 1342 int whence; 1343}; 1344#endif 1345int 1346olseek(p, uap) 1347 struct proc *p; 1348 register struct olseek_args /* { 1349 syscallarg(int) fd; 1350 syscallarg(long) offset; 1351 syscallarg(int) whence; 1352 } */ *uap; 1353{ 1354 struct lseek_args /* { 1355 syscallarg(int) fd; 1356 syscallarg(int) pad; 1357 syscallarg(off_t) offset; 1358 syscallarg(int) whence; 1359 } */ nuap; 1360 int error; 1361 1362 SCARG(&nuap, fd) = SCARG(uap, fd); 1363 SCARG(&nuap, offset) = SCARG(uap, offset); 1364 SCARG(&nuap, whence) = SCARG(uap, whence); 1365 error = lseek(p, &nuap); 1366 return (error); 1367} 1368#endif /* COMPAT_43 */ 1369 1370/* 1371 * Check access permissions. 1372 */ 1373#ifndef _SYS_SYSPROTO_H_ 1374struct access_args { 1375 char *path; 1376 int flags; 1377}; 1378#endif 1379int 1380access(p, uap) 1381 struct proc *p; 1382 register struct access_args /* { 1383 syscallarg(char *) path; 1384 syscallarg(int) flags; 1385 } */ *uap; 1386{ 1387 register struct ucred *cred = p->p_ucred; 1388 register struct vnode *vp; 1389 int error, flags, t_gid, t_uid; 1390 struct nameidata nd; 1391 1392 t_uid = cred->cr_uid; 1393 t_gid = cred->cr_groups[0]; 1394 cred->cr_uid = p->p_cred->p_ruid; 1395 cred->cr_groups[0] = p->p_cred->p_rgid; 1396 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 1397 SCARG(uap, path), p); 1398 if (error = namei(&nd)) 1399 goto out1; 1400 vp = nd.ni_vp; 1401 1402 /* Flags == 0 means only check for existence. */ 1403 if (SCARG(uap, flags)) { 1404 flags = 0; 1405 if (SCARG(uap, flags) & R_OK) 1406 flags |= VREAD; 1407 if (SCARG(uap, flags) & W_OK) 1408 flags |= VWRITE; 1409 if (SCARG(uap, flags) & X_OK) 1410 flags |= VEXEC; 1411 if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0) 1412 error = VOP_ACCESS(vp, flags, cred, p); 1413 } 1414 vput(vp); 1415out1: 1416 cred->cr_uid = t_uid; 1417 cred->cr_groups[0] = t_gid; 1418 return (error); 1419} 1420 1421#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1422/* 1423 * Get file status; this version follows links. 1424 */ 1425#ifndef _SYS_SYSPROTO_H_ 1426struct ostat_args { 1427 char *path; 1428 struct ostat *ub; 1429}; 1430#endif 1431/* ARGSUSED */ 1432int 1433ostat(p, uap) 1434 struct proc *p; 1435 register struct ostat_args /* { 1436 syscallarg(char *) path; 1437 syscallarg(struct ostat *) ub; 1438 } */ *uap; 1439{ 1440 struct stat sb; 1441 struct ostat osb; 1442 int error; 1443 struct nameidata nd; 1444 1445 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 1446 SCARG(uap, path), p); 1447 if (error = namei(&nd)) 1448 return (error); 1449 error = vn_stat(nd.ni_vp, &sb, p); 1450 vput(nd.ni_vp); 1451 if (error) 1452 return (error); 1453 cvtstat(&sb, &osb); 1454 error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb)); 1455 return (error); 1456} 1457 1458/* 1459 * Get file status; this version does not follow links. 1460 */ 1461#ifndef _SYS_SYSPROTO_H_ 1462struct olstat_args { 1463 char *path; 1464 struct ostat *ub; 1465}; 1466#endif 1467/* ARGSUSED */ 1468int 1469olstat(p, uap) 1470 struct proc *p; 1471 register struct olstat_args /* { 1472 syscallarg(char *) path; 1473 syscallarg(struct ostat *) ub; 1474 } */ *uap; 1475{ 1476 struct vnode *vp; 1477 struct stat sb; 1478 struct ostat osb; 1479 int error; 1480 struct nameidata nd; 1481 1482 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, 1483 SCARG(uap, path), p); 1484 if (error = namei(&nd)) 1485 return (error); 1486 vp = nd.ni_vp; 1487 error = vn_stat(vp, &sb, p); 1488 if (vp->v_type == VLNK) 1489 sb.st_mode |= S_IFLNK | ACCESSPERMS; /* 0777 */ 1490 vput(vp); 1491 if (error) 1492 return (error); 1493 cvtstat(&sb, &osb); 1494 error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb)); 1495 return (error); 1496} 1497 1498/* 1499 * Convert from an old to a new stat structure. 1500 */ 1501void 1502cvtstat(st, ost) 1503 struct stat *st; 1504 struct ostat *ost; 1505{ 1506 1507 ost->st_dev = st->st_dev; 1508 ost->st_ino = st->st_ino; 1509 ost->st_mode = st->st_mode; 1510 ost->st_nlink = st->st_nlink; 1511 ost->st_uid = st->st_uid; 1512 ost->st_gid = st->st_gid; 1513 ost->st_rdev = st->st_rdev; 1514 if (st->st_size < (quad_t)1 << 32) 1515 ost->st_size = st->st_size; 1516 else 1517 ost->st_size = -2; 1518 ost->st_atime = st->st_atime; 1519 ost->st_mtime = st->st_mtime; 1520 ost->st_ctime = st->st_ctime; 1521 ost->st_blksize = st->st_blksize; 1522 ost->st_blocks = st->st_blocks; 1523 ost->st_flags = st->st_flags; 1524 ost->st_gen = st->st_gen; 1525} 1526#endif /* COMPAT_43 || COMPAT_SUNOS */ 1527 1528/* 1529 * Get file status; this version follows links. 1530 */ 1531#ifndef _SYS_SYSPROTO_H_ 1532struct stat_args { 1533 char *path; 1534 struct stat *ub; 1535}; 1536#endif 1537/* ARGSUSED */ 1538int 1539stat(p, uap) 1540 struct proc *p; 1541 register struct stat_args /* { 1542 syscallarg(char *) path; 1543 syscallarg(struct stat *) ub; 1544 } */ *uap; 1545{ 1546 struct stat sb; 1547 int error; 1548 struct nameidata nd; 1549 1550 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 1551 SCARG(uap, path), p); 1552 if (error = namei(&nd)) 1553 return (error); 1554 error = vn_stat(nd.ni_vp, &sb, p); 1555 vput(nd.ni_vp); 1556 if (error) 1557 return (error); 1558 error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb)); 1559 return (error); 1560} 1561 1562/* 1563 * Get file status; this version does not follow links. 1564 */ 1565#ifndef _SYS_SYSPROTO_H_ 1566struct lstat_args { 1567 char *path; 1568 struct stat *ub; 1569}; 1570#endif 1571/* ARGSUSED */ 1572int 1573lstat(p, uap) 1574 struct proc *p; 1575 register struct lstat_args /* { 1576 syscallarg(char *) path; 1577 syscallarg(struct stat *) ub; 1578 } */ *uap; 1579{ 1580 int error; 1581 struct vnode *vp; 1582 struct stat sb; 1583 struct nameidata nd; 1584 1585 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, 1586 SCARG(uap, path), p); 1587 if (error = namei(&nd)) 1588 return (error); 1589 vp = nd.ni_vp; 1590 error = vn_stat(vp, &sb, p); 1591 if (vp->v_type == VLNK) 1592 sb.st_mode |= S_IFLNK | ACCESSPERMS; /* 0777 */ 1593 vput(vp); 1594 if (error) 1595 return (error); 1596 error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb)); 1597 return (error); 1598} 1599 1600/* 1601 * Get configurable pathname variables. 1602 */ 1603#ifndef _SYS_SYSPROTO_H_ 1604struct pathconf_args { 1605 char *path; 1606 int name; 1607}; 1608#endif 1609/* ARGSUSED */ 1610int 1611pathconf(p, uap) 1612 struct proc *p; 1613 register struct pathconf_args /* { 1614 syscallarg(char *) path; 1615 syscallarg(int) name; 1616 } */ *uap; 1617{ 1618 int error; 1619 struct nameidata nd; 1620 1621 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 1622 SCARG(uap, path), p); 1623 if (error = namei(&nd)) 1624 return (error); 1625 error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), p->p_retval); 1626 vput(nd.ni_vp); 1627 return (error); 1628} 1629 1630/* 1631 * Return target name of a symbolic link. 1632 */ 1633#ifndef _SYS_SYSPROTO_H_ 1634struct readlink_args { 1635 char *path; 1636 char *buf; 1637 int count; 1638}; 1639#endif 1640/* ARGSUSED */ 1641int 1642readlink(p, uap) 1643 struct proc *p; 1644 register struct readlink_args /* { 1645 syscallarg(char *) path; 1646 syscallarg(char *) buf; 1647 syscallarg(int) count; 1648 } */ *uap; 1649{ 1650 register struct vnode *vp; 1651 struct iovec aiov; 1652 struct uio auio; 1653 int error; 1654 struct nameidata nd; 1655 1656 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, 1657 SCARG(uap, path), p); 1658 if (error = namei(&nd)) 1659 return (error); 1660 vp = nd.ni_vp; 1661 if (vp->v_type != VLNK) 1662 error = EINVAL; 1663 else { 1664 aiov.iov_base = SCARG(uap, buf); 1665 aiov.iov_len = SCARG(uap, count); 1666 auio.uio_iov = &aiov; 1667 auio.uio_iovcnt = 1; 1668 auio.uio_offset = 0; 1669 auio.uio_rw = UIO_READ; 1670 auio.uio_segflg = UIO_USERSPACE; 1671 auio.uio_procp = p; 1672 auio.uio_resid = SCARG(uap, count); 1673 error = VOP_READLINK(vp, &auio, p->p_ucred); 1674 } 1675 vput(vp); 1676 p->p_retval[0] = SCARG(uap, count) - auio.uio_resid; 1677 return (error); 1678} 1679 1680/* 1681 * Change flags of a file given a path name. 1682 */ 1683#ifndef _SYS_SYSPROTO_H_ 1684struct chflags_args { 1685 char *path; 1686 int flags; 1687}; 1688#endif 1689/* ARGSUSED */ 1690int 1691chflags(p, uap) 1692 struct proc *p; 1693 register struct chflags_args /* { 1694 syscallarg(char *) path; 1695 syscallarg(int) flags; 1696 } */ *uap; 1697{ 1698 register struct vnode *vp; 1699 struct vattr vattr; 1700 int error; 1701 struct nameidata nd; 1702 1703 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1704 if (error = namei(&nd)) 1705 return (error); 1706 vp = nd.ni_vp; 1707 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1708 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1709 VATTR_NULL(&vattr); 1710 vattr.va_flags = SCARG(uap, flags); 1711 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1712 vput(vp); 1713 return (error); 1714} 1715 1716/* 1717 * Change flags of a file given a file descriptor. 1718 */ 1719#ifndef _SYS_SYSPROTO_H_ 1720struct fchflags_args { 1721 int fd; 1722 int flags; 1723}; 1724#endif 1725/* ARGSUSED */ 1726int 1727fchflags(p, uap) 1728 struct proc *p; 1729 register struct fchflags_args /* { 1730 syscallarg(int) fd; 1731 syscallarg(int) flags; 1732 } */ *uap; 1733{ 1734 struct vattr vattr; 1735 struct vnode *vp; 1736 struct file *fp; 1737 int error; 1738 1739 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 1740 return (error); 1741 vp = (struct vnode *)fp->f_data; 1742 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1743 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1744 VATTR_NULL(&vattr); 1745 vattr.va_flags = SCARG(uap, flags); 1746 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1747 VOP_UNLOCK(vp, 0, p); 1748 return (error); 1749} 1750 1751/* 1752 * Change mode of a file given path name. 1753 */ 1754#ifndef _SYS_SYSPROTO_H_ 1755struct chmod_args { 1756 char *path; 1757 int mode; 1758}; 1759#endif 1760/* ARGSUSED */ 1761int 1762chmod(p, uap) 1763 struct proc *p; 1764 register struct chmod_args /* { 1765 syscallarg(char *) path; 1766 syscallarg(int) mode; 1767 } */ *uap; 1768{ 1769 register struct vnode *vp; 1770 struct vattr vattr; 1771 int error; 1772 struct nameidata nd; 1773 1774 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1775 if (error = namei(&nd)) 1776 return (error); 1777 vp = nd.ni_vp; 1778 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1779 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1780 VATTR_NULL(&vattr); 1781 vattr.va_mode = SCARG(uap, mode) & ALLPERMS; 1782 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1783 vput(vp); 1784 return (error); 1785} 1786 1787/* 1788 * Change mode of a file given a file descriptor. 1789 */ 1790#ifndef _SYS_SYSPROTO_H_ 1791struct fchmod_args { 1792 int fd; 1793 int mode; 1794}; 1795#endif 1796/* ARGSUSED */ 1797int 1798fchmod(p, uap) 1799 struct proc *p; 1800 register struct fchmod_args /* { 1801 syscallarg(int) fd; 1802 syscallarg(int) mode; 1803 } */ *uap; 1804{ 1805 struct vattr vattr; 1806 struct vnode *vp; 1807 struct file *fp; 1808 int error; 1809 1810 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 1811 return (error); 1812 vp = (struct vnode *)fp->f_data; 1813 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1814 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1815 VATTR_NULL(&vattr); 1816 vattr.va_mode = SCARG(uap, mode) & ALLPERMS; 1817 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1818 VOP_UNLOCK(vp, 0, p); 1819 return (error); 1820} 1821 1822/* 1823 * Set ownership given a path name. 1824 */ 1825#ifndef _SYS_SYSPROTO_H_ 1826struct chown_args { 1827 char *path; 1828 int uid; 1829 int gid; 1830}; 1831#endif 1832/* ARGSUSED */ 1833int 1834chown(p, uap) 1835 struct proc *p; 1836 register struct chown_args /* { 1837 syscallarg(char *) path; 1838 syscallarg(int) uid; 1839 syscallarg(int) gid; 1840 } */ *uap; 1841{ 1842 register struct vnode *vp; 1843 struct vattr vattr; 1844 int error; 1845 struct nameidata nd; 1846 1847 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1848 if (error = namei(&nd)) 1849 return (error); 1850 vp = nd.ni_vp; 1851 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1852 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1853 VATTR_NULL(&vattr); 1854 vattr.va_uid = SCARG(uap, uid); 1855 vattr.va_gid = SCARG(uap, gid); 1856 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1857 vput(vp); 1858 return (error); 1859} 1860 1861/* 1862 * Set ownership given a path name, do not cross symlinks. 1863 */ 1864#ifndef _SYS_SYSPROTO_H_ 1865struct lchown_args { 1866 char *path; 1867 int uid; 1868 int gid; 1869}; 1870#endif 1871/* ARGSUSED */ 1872int 1873lchown(p, uap) 1874 struct proc *p; 1875 register struct lchown_args /* { 1876 syscallarg(char *) path; 1877 syscallarg(int) uid; 1878 syscallarg(int) gid; 1879 } */ *uap; 1880{ 1881 register struct vnode *vp; 1882 struct vattr vattr; 1883 int error; 1884 struct nameidata nd; 1885 1886 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1887 if (error = namei(&nd)) 1888 return (error); 1889 vp = nd.ni_vp; 1890 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1891 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1892 VATTR_NULL(&vattr); 1893 vattr.va_uid = SCARG(uap, uid); 1894 vattr.va_gid = SCARG(uap, gid); 1895 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1896 vput(vp); 1897 return (error); 1898} 1899 1900/* 1901 * Set ownership given a file descriptor. 1902 */ 1903#ifndef _SYS_SYSPROTO_H_ 1904struct fchown_args { 1905 int fd; 1906 int uid; 1907 int gid; 1908}; 1909#endif 1910/* ARGSUSED */ 1911int 1912fchown(p, uap) 1913 struct proc *p; 1914 register struct fchown_args /* { 1915 syscallarg(int) fd; 1916 syscallarg(int) uid; 1917 syscallarg(int) gid; 1918 } */ *uap; 1919{ 1920 struct vattr vattr; 1921 struct vnode *vp; 1922 struct file *fp; 1923 int error; 1924 1925 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 1926 return (error); 1927 vp = (struct vnode *)fp->f_data; 1928 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1929 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1930 VATTR_NULL(&vattr); 1931 vattr.va_uid = SCARG(uap, uid); 1932 vattr.va_gid = SCARG(uap, gid); 1933 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1934 VOP_UNLOCK(vp, 0, p); 1935 return (error); 1936} 1937 1938/* 1939 * Set the access and modification times of a file. 1940 */ 1941#ifndef _SYS_SYSPROTO_H_ 1942struct utimes_args { 1943 char *path; 1944 struct timeval *tptr; 1945}; 1946#endif 1947/* ARGSUSED */ 1948int 1949utimes(p, uap) 1950 struct proc *p; 1951 register struct utimes_args /* { 1952 syscallarg(char *) path; 1953 syscallarg(struct timeval *) tptr; 1954 } */ *uap; 1955{ 1956 register struct vnode *vp; 1957 struct timeval tv[2]; 1958 struct vattr vattr; 1959 int error; 1960 struct nameidata nd; 1961 1962 VATTR_NULL(&vattr); 1963 if (SCARG(uap, tptr) == NULL) { 1964 microtime(&tv[0]); 1965 tv[1] = tv[0]; 1966 vattr.va_vaflags |= VA_UTIMES_NULL; 1967 } else if (error = copyin((caddr_t)SCARG(uap, tptr), (caddr_t)tv, 1968 sizeof (tv))) 1969 return (error); 1970 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1971 if (error = namei(&nd)) 1972 return (error); 1973 vp = nd.ni_vp; 1974 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1975 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1976 vattr.va_atime.tv_sec = tv[0].tv_sec; 1977 vattr.va_atime.tv_nsec = tv[0].tv_usec * 1000; 1978 vattr.va_mtime.tv_sec = tv[1].tv_sec; 1979 vattr.va_mtime.tv_nsec = tv[1].tv_usec * 1000; 1980 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1981 vput(vp); 1982 return (error); 1983} 1984 1985/* 1986 * Truncate a file given its path name. 1987 */ 1988#ifndef _SYS_SYSPROTO_H_ 1989struct truncate_args { 1990 char *path; 1991 int pad; 1992 off_t length; 1993}; 1994#endif 1995/* ARGSUSED */ 1996int 1997truncate(p, uap) 1998 struct proc *p; 1999 register struct truncate_args /* { 2000 syscallarg(char *) path; 2001 syscallarg(int) pad; 2002 syscallarg(off_t) length; 2003 } */ *uap; 2004{ 2005 register struct vnode *vp; 2006 struct vattr vattr; 2007 int error; 2008 struct nameidata nd; 2009 2010 if (uap->length < 0) 2011 return(EINVAL); 2012 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 2013 if (error = namei(&nd)) 2014 return (error); 2015 vp = nd.ni_vp; 2016 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 2017 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2018 if (vp->v_type == VDIR) 2019 error = EISDIR; 2020 else if ((error = vn_writechk(vp)) == 0 && 2021 (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) { 2022 VATTR_NULL(&vattr); 2023 vattr.va_size = SCARG(uap, length); 2024 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 2025 } 2026 vput(vp); 2027 return (error); 2028} 2029 2030/* 2031 * Truncate a file given a file descriptor. 2032 */ 2033#ifndef _SYS_SYSPROTO_H_ 2034struct ftruncate_args { 2035 int fd; 2036 int pad; 2037 off_t length; 2038}; 2039#endif 2040/* ARGSUSED */ 2041int 2042ftruncate(p, uap) 2043 struct proc *p; 2044 register struct ftruncate_args /* { 2045 syscallarg(int) fd; 2046 syscallarg(int) pad; 2047 syscallarg(off_t) length; 2048 } */ *uap; 2049{ 2050 struct vattr vattr; 2051 struct vnode *vp; 2052 struct file *fp; 2053 int error; 2054 2055 if (uap->length < 0) 2056 return(EINVAL); 2057 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 2058 return (error); 2059 if ((fp->f_flag & FWRITE) == 0) 2060 return (EINVAL); 2061 vp = (struct vnode *)fp->f_data; 2062 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 2063 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2064 if (vp->v_type == VDIR) 2065 error = EISDIR; 2066 else if ((error = vn_writechk(vp)) == 0) { 2067 VATTR_NULL(&vattr); 2068 vattr.va_size = SCARG(uap, length); 2069 error = VOP_SETATTR(vp, &vattr, fp->f_cred, p); 2070 } 2071 VOP_UNLOCK(vp, 0, p); 2072 return (error); 2073} 2074 2075#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 2076/* 2077 * Truncate a file given its path name. 2078 */ 2079#ifndef _SYS_SYSPROTO_H_ 2080struct otruncate_args { 2081 char *path; 2082 long length; 2083}; 2084#endif 2085/* ARGSUSED */ 2086int 2087otruncate(p, uap) 2088 struct proc *p; 2089 register struct otruncate_args /* { 2090 syscallarg(char *) path; 2091 syscallarg(long) length; 2092 } */ *uap; 2093{ 2094 struct truncate_args /* { 2095 syscallarg(char *) path; 2096 syscallarg(int) pad; 2097 syscallarg(off_t) length; 2098 } */ nuap; 2099 2100 SCARG(&nuap, path) = SCARG(uap, path); 2101 SCARG(&nuap, length) = SCARG(uap, length); 2102 return (truncate(p, &nuap)); 2103} 2104 2105/* 2106 * Truncate a file given a file descriptor. 2107 */ 2108#ifndef _SYS_SYSPROTO_H_ 2109struct oftruncate_args { 2110 int fd; 2111 long length; 2112}; 2113#endif 2114/* ARGSUSED */ 2115int 2116oftruncate(p, uap) 2117 struct proc *p; 2118 register struct oftruncate_args /* { 2119 syscallarg(int) fd; 2120 syscallarg(long) length; 2121 } */ *uap; 2122{ 2123 struct ftruncate_args /* { 2124 syscallarg(int) fd; 2125 syscallarg(int) pad; 2126 syscallarg(off_t) length; 2127 } */ nuap; 2128 2129 SCARG(&nuap, fd) = SCARG(uap, fd); 2130 SCARG(&nuap, length) = SCARG(uap, length); 2131 return (ftruncate(p, &nuap)); 2132} 2133#endif /* COMPAT_43 || COMPAT_SUNOS */ 2134 2135/* 2136 * Sync an open file. 2137 */ 2138#ifndef _SYS_SYSPROTO_H_ 2139struct fsync_args { 2140 int fd; 2141}; 2142#endif 2143/* ARGSUSED */ 2144int 2145fsync(p, uap) 2146 struct proc *p; 2147 struct fsync_args /* { 2148 syscallarg(int) fd; 2149 } */ *uap; 2150{ 2151 register struct vnode *vp; 2152 struct file *fp; 2153 int error; 2154 2155 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 2156 return (error); 2157 vp = (struct vnode *)fp->f_data; 2158 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2159 if (vp->v_object) { 2160 vm_object_page_clean(vp->v_object, 0, 0 ,0, FALSE); 2161 } 2162 error = VOP_FSYNC(vp, fp->f_cred, 2163 (vp->v_mount && (vp->v_mount->mnt_flag & MNT_ASYNC)) ? 2164 MNT_NOWAIT : MNT_WAIT, p); 2165 VOP_UNLOCK(vp, 0, p); 2166 return (error); 2167} 2168 2169/* 2170 * Rename files. Source and destination must either both be directories, 2171 * or both not be directories. If target is a directory, it must be empty. 2172 */ 2173#ifndef _SYS_SYSPROTO_H_ 2174struct rename_args { 2175 char *from; 2176 char *to; 2177}; 2178#endif 2179/* ARGSUSED */ 2180int 2181rename(p, uap) 2182 struct proc *p; 2183 register struct rename_args /* { 2184 syscallarg(char *) from; 2185 syscallarg(char *) to; 2186 } */ *uap; 2187{ 2188 register struct vnode *tvp, *fvp, *tdvp; 2189 struct nameidata fromnd, tond; 2190 int error; 2191 2192 NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE, 2193 SCARG(uap, from), p); 2194 if (error = namei(&fromnd)) 2195 return (error); 2196 fvp = fromnd.ni_vp; 2197 NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART, 2198 UIO_USERSPACE, SCARG(uap, to), p); 2199 if (fromnd.ni_vp->v_type == VDIR) 2200 tond.ni_cnd.cn_flags |= WILLBEDIR; 2201 if (error = namei(&tond)) { 2202 /* Translate error code for rename("dir1", "dir2/."). */ 2203 if (error == EISDIR && fvp->v_type == VDIR) 2204 error = EINVAL; 2205 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 2206 vrele(fromnd.ni_dvp); 2207 vrele(fvp); 2208 goto out1; 2209 } 2210 tdvp = tond.ni_dvp; 2211 tvp = tond.ni_vp; 2212 if (tvp != NULL) { 2213 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 2214 error = ENOTDIR; 2215 goto out; 2216 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 2217 error = EISDIR; 2218 goto out; 2219 } 2220 } 2221 if (fvp == tdvp) 2222 error = EINVAL; 2223 /* 2224 * If source is the same as the destination (that is the 2225 * same inode number with the same name in the same directory), 2226 * then there is nothing to do. 2227 */ 2228 if (fvp == tvp && fromnd.ni_dvp == tdvp && 2229 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen && 2230 !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr, 2231 fromnd.ni_cnd.cn_namelen)) 2232 error = -1; 2233out: 2234 if (!error) { 2235 VOP_LEASE(tdvp, p, p->p_ucred, LEASE_WRITE); 2236 if (fromnd.ni_dvp != tdvp) 2237 VOP_LEASE(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 2238 if (tvp) { 2239 VOP_LEASE(tvp, p, p->p_ucred, LEASE_WRITE); 2240 (void) vnode_pager_uncache(tvp, p); 2241 } 2242 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd, 2243 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd); 2244 } else { 2245 VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd); 2246 if (tdvp == tvp) 2247 vrele(tdvp); 2248 else 2249 vput(tdvp); 2250 if (tvp) 2251 vput(tvp); 2252 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 2253 vrele(fromnd.ni_dvp); 2254 vrele(fvp); 2255 } 2256 vrele(tond.ni_startdir); 2257 ASSERT_VOP_UNLOCKED(fromnd.ni_dvp, "rename"); 2258 ASSERT_VOP_UNLOCKED(fromnd.ni_vp, "rename"); 2259 ASSERT_VOP_UNLOCKED(tond.ni_dvp, "rename"); 2260 ASSERT_VOP_UNLOCKED(tond.ni_vp, "rename"); 2261 zfree(namei_zone, tond.ni_cnd.cn_pnbuf); 2262out1: 2263 if (fromnd.ni_startdir) 2264 vrele(fromnd.ni_startdir); 2265 zfree(namei_zone, fromnd.ni_cnd.cn_pnbuf); 2266 if (error == -1) 2267 return (0); 2268 return (error); 2269} 2270 2271/* 2272 * Make a directory file. 2273 */ 2274#ifndef _SYS_SYSPROTO_H_ 2275struct mkdir_args { 2276 char *path; 2277 int mode; 2278}; 2279#endif 2280/* ARGSUSED */ 2281int 2282mkdir(p, uap) 2283 struct proc *p; 2284 register struct mkdir_args /* { 2285 syscallarg(char *) path; 2286 syscallarg(int) mode; 2287 } */ *uap; 2288{ 2289 register struct vnode *vp; 2290 struct vattr vattr; 2291 int error; 2292 struct nameidata nd; 2293 2294 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); 2295 nd.ni_cnd.cn_flags |= WILLBEDIR; 2296 if (error = namei(&nd)) 2297 return (error); 2298 vp = nd.ni_vp; 2299 if (vp != NULL) { 2300 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 2301 if (nd.ni_dvp == vp) 2302 vrele(nd.ni_dvp); 2303 else 2304 vput(nd.ni_dvp); 2305 vrele(vp); 2306 return (EEXIST); 2307 } 2308 VATTR_NULL(&vattr); 2309 vattr.va_type = VDIR; 2310 vattr.va_mode = (SCARG(uap, mode) & ACCESSPERMS) &~ p->p_fd->fd_cmask; 2311 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 2312 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 2313 if (!error) 2314 vput(nd.ni_vp); 2315 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mkdir"); 2316 ASSERT_VOP_UNLOCKED(nd.ni_vp, "mkdir"); 2317 return (error); 2318} 2319 2320/* 2321 * Remove a directory file. 2322 */ 2323#ifndef _SYS_SYSPROTO_H_ 2324struct rmdir_args { 2325 char *path; 2326}; 2327#endif 2328/* ARGSUSED */ 2329int 2330rmdir(p, uap) 2331 struct proc *p; 2332 struct rmdir_args /* { 2333 syscallarg(char *) path; 2334 } */ *uap; 2335{ 2336 register struct vnode *vp; 2337 int error; 2338 struct nameidata nd; 2339 2340 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, 2341 SCARG(uap, path), p); 2342 if (error = namei(&nd)) 2343 return (error); 2344 vp = nd.ni_vp; 2345 if (vp->v_type != VDIR) { 2346 error = ENOTDIR; 2347 goto out; 2348 } 2349 /* 2350 * No rmdir "." please. 2351 */ 2352 if (nd.ni_dvp == vp) { 2353 error = EINVAL; 2354 goto out; 2355 } 2356 /* 2357 * The root of a mounted filesystem cannot be deleted. 2358 */ 2359 if (vp->v_flag & VROOT) 2360 error = EBUSY; 2361out: 2362 if (!error) { 2363 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 2364 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 2365 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 2366 } else { 2367 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 2368 if (nd.ni_dvp == vp) 2369 vrele(nd.ni_dvp); 2370 else 2371 vput(nd.ni_dvp); 2372 vput(vp); 2373 } 2374 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "rmdir"); 2375 ASSERT_VOP_UNLOCKED(nd.ni_vp, "rmdir"); 2376 return (error); 2377} 2378 2379#ifdef COMPAT_43 2380/* 2381 * Read a block of directory entries in a file system independent format. 2382 */ 2383#ifndef _SYS_SYSPROTO_H_ 2384struct ogetdirentries_args { 2385 int fd; 2386 char *buf; 2387 u_int count; 2388 long *basep; 2389}; 2390#endif 2391int 2392ogetdirentries(p, uap) 2393 struct proc *p; 2394 register struct ogetdirentries_args /* { 2395 syscallarg(int) fd; 2396 syscallarg(char *) buf; 2397 syscallarg(u_int) count; 2398 syscallarg(long *) basep; 2399 } */ *uap; 2400{ 2401 register struct vnode *vp; 2402 struct file *fp; 2403 struct uio auio, kuio; 2404 struct iovec aiov, kiov; 2405 struct dirent *dp, *edp; 2406 caddr_t dirbuf; 2407 int error, eofflag, readcnt; 2408 long loff; 2409 2410 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 2411 return (error); 2412 if ((fp->f_flag & FREAD) == 0) 2413 return (EBADF); 2414 vp = (struct vnode *)fp->f_data; 2415unionread: 2416 if (vp->v_type != VDIR) 2417 return (EINVAL); 2418 aiov.iov_base = SCARG(uap, buf); 2419 aiov.iov_len = SCARG(uap, count); 2420 auio.uio_iov = &aiov; 2421 auio.uio_iovcnt = 1; 2422 auio.uio_rw = UIO_READ; 2423 auio.uio_segflg = UIO_USERSPACE; 2424 auio.uio_procp = p; 2425 auio.uio_resid = SCARG(uap, count); 2426 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2427 loff = auio.uio_offset = fp->f_offset; 2428# if (BYTE_ORDER != LITTLE_ENDIAN) 2429 if (vp->v_mount->mnt_maxsymlinklen <= 0) { 2430 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, 2431 NULL, NULL); 2432 fp->f_offset = auio.uio_offset; 2433 } else 2434# endif 2435 { 2436 kuio = auio; 2437 kuio.uio_iov = &kiov; 2438 kuio.uio_segflg = UIO_SYSSPACE; 2439 kiov.iov_len = SCARG(uap, count); 2440 MALLOC(dirbuf, caddr_t, SCARG(uap, count), M_TEMP, M_WAITOK); 2441 kiov.iov_base = dirbuf; 2442 error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag, 2443 NULL, NULL); 2444 fp->f_offset = kuio.uio_offset; 2445 if (error == 0) { 2446 readcnt = SCARG(uap, count) - kuio.uio_resid; 2447 edp = (struct dirent *)&dirbuf[readcnt]; 2448 for (dp = (struct dirent *)dirbuf; dp < edp; ) { 2449# if (BYTE_ORDER == LITTLE_ENDIAN) 2450 /* 2451 * The expected low byte of 2452 * dp->d_namlen is our dp->d_type. 2453 * The high MBZ byte of dp->d_namlen 2454 * is our dp->d_namlen. 2455 */ 2456 dp->d_type = dp->d_namlen; 2457 dp->d_namlen = 0; 2458# else 2459 /* 2460 * The dp->d_type is the high byte 2461 * of the expected dp->d_namlen, 2462 * so must be zero'ed. 2463 */ 2464 dp->d_type = 0; 2465# endif 2466 if (dp->d_reclen > 0) { 2467 dp = (struct dirent *) 2468 ((char *)dp + dp->d_reclen); 2469 } else { 2470 error = EIO; 2471 break; 2472 } 2473 } 2474 if (dp >= edp) 2475 error = uiomove(dirbuf, readcnt, &auio); 2476 } 2477 FREE(dirbuf, M_TEMP); 2478 } 2479 VOP_UNLOCK(vp, 0, p); 2480 if (error) 2481 return (error); 2482 2483#ifdef UNION 2484{ 2485 if ((SCARG(uap, count) == auio.uio_resid) && 2486 (vp->v_op == union_vnodeop_p)) { 2487 struct vnode *lvp; 2488 2489 lvp = union_dircache(vp, p); 2490 if (lvp != NULLVP) { 2491 struct vattr va; 2492 2493 /* 2494 * If the directory is opaque, 2495 * then don't show lower entries 2496 */ 2497 error = VOP_GETATTR(vp, &va, fp->f_cred, p); 2498 if (va.va_flags & OPAQUE) { 2499 vput(lvp); 2500 lvp = NULL; 2501 } 2502 } 2503 2504 if (lvp != NULLVP) { 2505 error = VOP_OPEN(lvp, FREAD, fp->f_cred, p); 2506 if (error) { 2507 vput(lvp); 2508 return (error); 2509 } 2510 VOP_UNLOCK(lvp, 0, p); 2511 fp->f_data = (caddr_t) lvp; 2512 fp->f_offset = 0; 2513 error = vn_close(vp, FREAD, fp->f_cred, p); 2514 if (error) 2515 return (error); 2516 vp = lvp; 2517 goto unionread; 2518 } 2519 } 2520} 2521#endif /* UNION */ 2522 2523 if ((SCARG(uap, count) == auio.uio_resid) && 2524 (vp->v_flag & VROOT) && 2525 (vp->v_mount->mnt_flag & MNT_UNION)) { 2526 struct vnode *tvp = vp; 2527 vp = vp->v_mount->mnt_vnodecovered; 2528 VREF(vp); 2529 fp->f_data = (caddr_t) vp; 2530 fp->f_offset = 0; 2531 vrele(tvp); 2532 goto unionread; 2533 } 2534 error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep), 2535 sizeof(long)); 2536 p->p_retval[0] = SCARG(uap, count) - auio.uio_resid; 2537 return (error); 2538} 2539#endif /* COMPAT_43 */ 2540 2541/* 2542 * Read a block of directory entries in a file system independent format. 2543 */ 2544#ifndef _SYS_SYSPROTO_H_ 2545struct getdirentries_args { 2546 int fd; 2547 char *buf; 2548 u_int count; 2549 long *basep; 2550}; 2551#endif 2552int 2553getdirentries(p, uap) 2554 struct proc *p; 2555 register struct getdirentries_args /* { 2556 syscallarg(int) fd; 2557 syscallarg(char *) buf; 2558 syscallarg(u_int) count; 2559 syscallarg(long *) basep; 2560 } */ *uap; 2561{ 2562 register struct vnode *vp; 2563 struct file *fp; 2564 struct uio auio; 2565 struct iovec aiov; 2566 long loff; 2567 int error, eofflag; 2568 2569 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 2570 return (error); 2571 if ((fp->f_flag & FREAD) == 0) 2572 return (EBADF); 2573 vp = (struct vnode *)fp->f_data; 2574unionread: 2575 if (vp->v_type != VDIR) 2576 return (EINVAL); 2577 aiov.iov_base = SCARG(uap, buf); 2578 aiov.iov_len = SCARG(uap, count); 2579 auio.uio_iov = &aiov; 2580 auio.uio_iovcnt = 1; 2581 auio.uio_rw = UIO_READ; 2582 auio.uio_segflg = UIO_USERSPACE; 2583 auio.uio_procp = p; 2584 auio.uio_resid = SCARG(uap, count); 2585 /* vn_lock(vp, LK_SHARED | LK_RETRY, p); */ 2586 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2587 loff = auio.uio_offset = fp->f_offset; 2588 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL, NULL); 2589 fp->f_offset = auio.uio_offset; 2590 VOP_UNLOCK(vp, 0, p); 2591 if (error) 2592 return (error); 2593 2594#ifdef UNION 2595{ 2596 if ((SCARG(uap, count) == auio.uio_resid) && 2597 (vp->v_op == union_vnodeop_p)) { 2598 struct vnode *lvp; 2599 2600 lvp = union_dircache(vp, p); 2601 if (lvp != NULLVP) { 2602 struct vattr va; 2603 2604 /* 2605 * If the directory is opaque, 2606 * then don't show lower entries 2607 */ 2608 error = VOP_GETATTR(vp, &va, fp->f_cred, p); 2609 if (va.va_flags & OPAQUE) { 2610 vput(lvp); 2611 lvp = NULL; 2612 } 2613 } 2614 2615 if (lvp != NULLVP) { 2616 error = VOP_OPEN(lvp, FREAD, fp->f_cred, p); 2617 if (error) { 2618 vput(lvp); 2619 return (error); 2620 } 2621 VOP_UNLOCK(lvp, 0, p); 2622 fp->f_data = (caddr_t) lvp; 2623 fp->f_offset = 0; 2624 error = vn_close(vp, FREAD, fp->f_cred, p); 2625 if (error) 2626 return (error); 2627 vp = lvp; 2628 goto unionread; 2629 } 2630 } 2631} 2632#endif /* UNION */ 2633 2634 if ((SCARG(uap, count) == auio.uio_resid) && 2635 (vp->v_flag & VROOT) && 2636 (vp->v_mount->mnt_flag & MNT_UNION)) { 2637 struct vnode *tvp = vp; 2638 vp = vp->v_mount->mnt_vnodecovered; 2639 VREF(vp); 2640 fp->f_data = (caddr_t) vp; 2641 fp->f_offset = 0; 2642 vrele(tvp); 2643 goto unionread; 2644 } 2645 error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep), 2646 sizeof(long)); 2647 p->p_retval[0] = SCARG(uap, count) - auio.uio_resid; 2648 return (error); 2649} 2650 2651/* 2652 * Set the mode mask for creation of filesystem nodes. 2653 */ 2654#ifndef _SYS_SYSPROTO_H_ 2655struct umask_args { 2656 int newmask; 2657}; 2658#endif 2659int 2660umask(p, uap) 2661 struct proc *p; 2662 struct umask_args /* { 2663 syscallarg(int) newmask; 2664 } */ *uap; 2665{ 2666 register struct filedesc *fdp; 2667 2668 fdp = p->p_fd; 2669 p->p_retval[0] = fdp->fd_cmask; 2670 fdp->fd_cmask = SCARG(uap, newmask) & ALLPERMS; 2671 return (0); 2672} 2673 2674/* 2675 * Void all references to file by ripping underlying filesystem 2676 * away from vnode. 2677 */ 2678#ifndef _SYS_SYSPROTO_H_ 2679struct revoke_args { 2680 char *path; 2681}; 2682#endif 2683/* ARGSUSED */ 2684int 2685revoke(p, uap) 2686 struct proc *p; 2687 register struct revoke_args /* { 2688 syscallarg(char *) path; 2689 } */ *uap; 2690{ 2691 register struct vnode *vp; 2692 struct vattr vattr; 2693 int error; 2694 struct nameidata nd; 2695 2696 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 2697 if (error = namei(&nd)) 2698 return (error); 2699 vp = nd.ni_vp; 2700 if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) 2701 goto out; 2702 if (p->p_ucred->cr_uid != vattr.va_uid && 2703 (error = suser(p->p_ucred, &p->p_acflag))) 2704 goto out; 2705 if (vp->v_usecount > 1 || (vp->v_flag & VALIASED)) 2706 VOP_REVOKE(vp, REVOKEALL); 2707out: 2708 vrele(vp); 2709 return (error); 2710} 2711 2712/* 2713 * Convert a user file descriptor to a kernel file entry. 2714 */ 2715int 2716getvnode(fdp, fd, fpp) 2717 struct filedesc *fdp; 2718 int fd; 2719 struct file **fpp; 2720{ 2721 struct file *fp; 2722 2723 if ((u_int)fd >= fdp->fd_nfiles || 2724 (fp = fdp->fd_ofiles[fd]) == NULL) 2725 return (EBADF); 2726 if (fp->f_type != DTYPE_VNODE && fp->f_type != DTYPE_FIFO) 2727 return (EINVAL); 2728 *fpp = fp; 2729 return (0); 2730} 2731#ifndef _SYS_SYSPROTO_H_ 2732struct __getcwd_args { 2733 u_char *buf; 2734 u_int buflen; 2735}; 2736#endif 2737#define STATNODE(mode, name, var) \ 2738 SYSCTL_INT(_vfs_cache, OID_AUTO, name, mode, var, 0, ""); 2739 2740static int disablecwd; 2741SYSCTL_INT(_debug, OID_AUTO, disablecwd, CTLFLAG_RW, &disablecwd, 0, ""); 2742 2743static u_long numcwdcalls; STATNODE(CTLFLAG_RD, numcwdcalls, &numcwdcalls); 2744static u_long numcwdfail1; STATNODE(CTLFLAG_RD, numcwdfail1, &numcwdfail1); 2745static u_long numcwdfail2; STATNODE(CTLFLAG_RD, numcwdfail2, &numcwdfail2); 2746static u_long numcwdfail3; STATNODE(CTLFLAG_RD, numcwdfail3, &numcwdfail3); 2747static u_long numcwdfail4; STATNODE(CTLFLAG_RD, numcwdfail4, &numcwdfail4); 2748static u_long numcwdfound; STATNODE(CTLFLAG_RD, numcwdfound, &numcwdfound); 2749int 2750__getcwd(p, uap) 2751 struct proc *p; 2752 struct __getcwd_args *uap; 2753{ 2754 struct filedesc *fdp; 2755 struct vnode *vp; 2756 struct namecache *ncp; 2757 char *buf, *bp; 2758 int i, j, error; 2759 2760 if (disablecwd) 2761 return (ENODEV); 2762 fdp = p->p_fd; 2763 j = 0; 2764 error = 0; 2765 if (uap->buflen < 2) 2766 return (EINVAL); 2767 if (uap->buflen > MAXPATHLEN) 2768 uap->buflen = MAXPATHLEN; 2769 buf = bp = malloc(uap->buflen, M_TEMP, M_WAITOK); 2770 bp += uap->buflen - 1; 2771 *bp = '\0'; 2772 numcwdcalls++; 2773 for (vp = fdp->fd_cdir; vp != fdp->fd_rdir && vp != rootvnode;) { 2774 if (vp->v_flag & VROOT) { 2775 vp = vp->v_mount->mnt_vnodecovered; 2776 continue; 2777 } 2778 if (vp->v_dd->v_id != vp->v_ddid) { 2779 numcwdfail1++; 2780 free(buf, M_TEMP); 2781 return (ENOTDIR); 2782 } 2783 ncp = TAILQ_FIRST(&vp->v_cache_dst); 2784 if (!ncp) { 2785 numcwdfail2++; 2786 free(buf, M_TEMP); 2787 return (ENOENT); 2788 } 2789 if (ncp->nc_dvp != vp->v_dd) { 2790 numcwdfail3++; 2791 free(buf, M_TEMP); 2792 return (EBADF); 2793 } 2794 for (i=ncp->nc_nlen - 1; i >= 0; i--) { 2795 if (bp == buf) { 2796 numcwdfail4++; 2797 free(buf, M_TEMP); 2798 return (ENOMEM); 2799 } 2800 *--bp = ncp->nc_name[i]; 2801 } 2802 if (bp == buf) { 2803 numcwdfail4++; 2804 free(buf, M_TEMP); 2805 return (ENOMEM); 2806 } 2807 *--bp = '/'; 2808 j++; 2809 vp = vp->v_dd; 2810 } 2811 if (!j) { 2812 if (bp == buf) { 2813 numcwdfail4++; 2814 free(buf, M_TEMP); 2815 return (ENOMEM); 2816 } 2817 *--bp = '/'; 2818 } 2819 numcwdfound++; 2820 error = copyout(bp, uap->buf, strlen(bp) + 1); 2821 free(buf, M_TEMP); 2822 return (error); 2823}
| 268 /* 269 * Mount the filesystem. 270 */ 271 error = VFS_MOUNT(mp, SCARG(uap, path), SCARG(uap, data), &nd, p); 272 if (mp->mnt_flag & MNT_UPDATE) { 273 vrele(vp); 274 if (mp->mnt_kern_flag & MNTK_WANTRDWR) 275 mp->mnt_flag &= ~MNT_RDONLY; 276 mp->mnt_flag &=~ (MNT_UPDATE | MNT_RELOAD | MNT_FORCE); 277 mp->mnt_kern_flag &=~ (MNTK_WANTRDWR); 278 if (error) 279 mp->mnt_flag = flag; 280 mp->mnt_kern_flag = flag2; 281 vfs_unbusy(mp, p); 282 return (error); 283 } 284 /* 285 * Put the new filesystem on the mount list after root. 286 */ 287 cache_purge(vp); 288 if (!error) { 289 simple_lock(&mountlist_slock); 290 CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list); 291 simple_unlock(&mountlist_slock); 292 checkdirs(vp); 293 VOP_UNLOCK(vp, 0, p); 294 vfs_unbusy(mp, p); 295 if (error = VFS_START(mp, 0, p)) 296 vrele(vp); 297 } else { 298 mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0; 299 mp->mnt_vfc->vfc_refcount--; 300 vfs_unbusy(mp, p); 301 free((caddr_t)mp, M_MOUNT); 302 vput(vp); 303 } 304 return (error); 305} 306 307/* 308 * Scan all active processes to see if any of them have a current 309 * or root directory onto which the new filesystem has just been 310 * mounted. If so, replace them with the new mount point. 311 */ 312static void 313checkdirs(olddp) 314 struct vnode *olddp; 315{ 316 struct filedesc *fdp; 317 struct vnode *newdp; 318 struct proc *p; 319 320 if (olddp->v_usecount == 1) 321 return; 322 if (VFS_ROOT(olddp->v_mountedhere, &newdp)) 323 panic("mount: lost mount"); 324 for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) { 325 fdp = p->p_fd; 326 if (fdp->fd_cdir == olddp) { 327 vrele(fdp->fd_cdir); 328 VREF(newdp); 329 fdp->fd_cdir = newdp; 330 } 331 if (fdp->fd_rdir == olddp) { 332 vrele(fdp->fd_rdir); 333 VREF(newdp); 334 fdp->fd_rdir = newdp; 335 } 336 } 337 if (rootvnode == olddp) { 338 vrele(rootvnode); 339 VREF(newdp); 340 rootvnode = newdp; 341 } 342 vput(newdp); 343} 344 345/* 346 * Unmount a file system. 347 * 348 * Note: unmount takes a path to the vnode mounted on as argument, 349 * not special file (as before). 350 */ 351#ifndef _SYS_SYSPROTO_H_ 352struct unmount_args { 353 char *path; 354 int flags; 355}; 356#endif 357/* ARGSUSED */ 358int 359unmount(p, uap) 360 struct proc *p; 361 register struct unmount_args /* { 362 syscallarg(char *) path; 363 syscallarg(int) flags; 364 } */ *uap; 365{ 366 register struct vnode *vp; 367 struct mount *mp; 368 int error; 369 struct nameidata nd; 370 371 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 372 SCARG(uap, path), p); 373 if (error = namei(&nd)) 374 return (error); 375 vp = nd.ni_vp; 376 mp = vp->v_mount; 377 378 /* 379 * Only root, or the user that did the original mount is 380 * permitted to unmount this filesystem. 381 */ 382 if ((mp->mnt_stat.f_owner != p->p_ucred->cr_uid) && 383 (error = suser(p->p_ucred, &p->p_acflag))) { 384 vput(vp); 385 return (error); 386 } 387 388 /* 389 * Don't allow unmounting the root file system. 390 */ 391 if (mp->mnt_flag & MNT_ROOTFS) { 392 vput(vp); 393 return (EINVAL); 394 } 395 396 /* 397 * Must be the root of the filesystem 398 */ 399 if ((vp->v_flag & VROOT) == 0) { 400 vput(vp); 401 return (EINVAL); 402 } 403 vput(vp); 404 return (dounmount(mp, SCARG(uap, flags), p)); 405} 406 407/* 408 * Do the actual file system unmount. 409 */ 410int 411dounmount(mp, flags, p) 412 register struct mount *mp; 413 int flags; 414 struct proc *p; 415{ 416 struct vnode *coveredvp; 417 int error; 418 419 simple_lock(&mountlist_slock); 420 mp->mnt_kern_flag |= MNTK_UNMOUNT; 421 lockmgr(&mp->mnt_lock, LK_DRAIN | LK_INTERLOCK, &mountlist_slock, p); 422 423 if (mp->mnt_flag & MNT_EXPUBLIC) 424 vfs_setpublicfs(NULL, NULL, NULL); 425 426 mp->mnt_flag &=~ MNT_ASYNC; 427 vfs_msync(mp, MNT_NOWAIT); 428 vnode_pager_umount(mp); /* release cached vnodes */ 429 cache_purgevfs(mp); /* remove cache entries for this file sys */ 430 if (((mp->mnt_flag & MNT_RDONLY) || 431 (error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0) || 432 (flags & MNT_FORCE)) 433 error = VFS_UNMOUNT(mp, flags, p); 434 simple_lock(&mountlist_slock); 435 if (error) { 436 mp->mnt_kern_flag &= ~MNTK_UNMOUNT; 437 lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK | LK_REENABLE, 438 &mountlist_slock, p); 439 return (error); 440 } 441 CIRCLEQ_REMOVE(&mountlist, mp, mnt_list); 442 if ((coveredvp = mp->mnt_vnodecovered) != NULLVP) { 443 coveredvp->v_mountedhere = (struct mount *)0; 444 vrele(coveredvp); 445 } 446 mp->mnt_vfc->vfc_refcount--; 447 if (mp->mnt_vnodelist.lh_first != NULL) 448 panic("unmount: dangling vnode"); 449 lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK, &mountlist_slock, p); 450 if (mp->mnt_kern_flag & MNTK_MWAIT) 451 wakeup((caddr_t)mp); 452 free((caddr_t)mp, M_MOUNT); 453 return (0); 454} 455 456/* 457 * Sync each mounted filesystem. 458 */ 459#ifndef _SYS_SYSPROTO_H_ 460struct sync_args { 461 int dummy; 462}; 463#endif 464 465#ifdef DEBUG 466int syncprt = 0; 467SYSCTL_INT(_debug, 0, syncprt, CTLFLAG_RW, &syncprt, 0, ""); 468#endif 469 470/* ARGSUSED */ 471int 472sync(p, uap) 473 struct proc *p; 474 struct sync_args *uap; 475{ 476 register struct mount *mp, *nmp; 477 int asyncflag; 478 479 simple_lock(&mountlist_slock); 480 for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) { 481 if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) { 482 nmp = mp->mnt_list.cqe_next; 483 continue; 484 } 485 if ((mp->mnt_flag & MNT_RDONLY) == 0) { 486 asyncflag = mp->mnt_flag & MNT_ASYNC; 487 mp->mnt_flag &= ~MNT_ASYNC; 488 vfs_msync(mp, MNT_NOWAIT); 489 VFS_SYNC(mp, MNT_NOWAIT, p != NULL ? p->p_ucred : NOCRED, p); 490 if (asyncflag) 491 mp->mnt_flag |= MNT_ASYNC; 492 } 493 simple_lock(&mountlist_slock); 494 nmp = mp->mnt_list.cqe_next; 495 vfs_unbusy(mp, p); 496 } 497 simple_unlock(&mountlist_slock); 498#if 0 499/* 500 * XXX don't call vfs_bufstats() yet because that routine 501 * was not imported in the Lite2 merge. 502 */ 503#ifdef DIAGNOSTIC 504 if (syncprt) 505 vfs_bufstats(); 506#endif /* DIAGNOSTIC */ 507#endif 508 return (0); 509} 510 511/* 512 * Change filesystem quotas. 513 */ 514#ifndef _SYS_SYSPROTO_H_ 515struct quotactl_args { 516 char *path; 517 int cmd; 518 int uid; 519 caddr_t arg; 520}; 521#endif 522/* ARGSUSED */ 523int 524quotactl(p, uap) 525 struct proc *p; 526 register struct quotactl_args /* { 527 syscallarg(char *) path; 528 syscallarg(int) cmd; 529 syscallarg(int) uid; 530 syscallarg(caddr_t) arg; 531 } */ *uap; 532{ 533 register struct mount *mp; 534 int error; 535 struct nameidata nd; 536 537 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 538 if (error = namei(&nd)) 539 return (error); 540 mp = nd.ni_vp->v_mount; 541 vrele(nd.ni_vp); 542 return (VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid), 543 SCARG(uap, arg), p)); 544} 545 546/* 547 * Get filesystem statistics. 548 */ 549#ifndef _SYS_SYSPROTO_H_ 550struct statfs_args { 551 char *path; 552 struct statfs *buf; 553}; 554#endif 555/* ARGSUSED */ 556int 557statfs(p, uap) 558 struct proc *p; 559 register struct statfs_args /* { 560 syscallarg(char *) path; 561 syscallarg(struct statfs *) buf; 562 } */ *uap; 563{ 564 register struct mount *mp; 565 register struct statfs *sp; 566 int error; 567 struct nameidata nd; 568 struct statfs sb; 569 570 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 571 if (error = namei(&nd)) 572 return (error); 573 mp = nd.ni_vp->v_mount; 574 sp = &mp->mnt_stat; 575 vrele(nd.ni_vp); 576 error = VFS_STATFS(mp, sp, p); 577 if (error) 578 return (error); 579 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 580 if (p->p_ucred->cr_uid != 0) { 581 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); 582 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; 583 sp = &sb; 584 } 585 return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp))); 586} 587 588/* 589 * Get filesystem statistics. 590 */ 591#ifndef _SYS_SYSPROTO_H_ 592struct fstatfs_args { 593 int fd; 594 struct statfs *buf; 595}; 596#endif 597/* ARGSUSED */ 598int 599fstatfs(p, uap) 600 struct proc *p; 601 register struct fstatfs_args /* { 602 syscallarg(int) fd; 603 syscallarg(struct statfs *) buf; 604 } */ *uap; 605{ 606 struct file *fp; 607 struct mount *mp; 608 register struct statfs *sp; 609 int error; 610 struct statfs sb; 611 612 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 613 return (error); 614 mp = ((struct vnode *)fp->f_data)->v_mount; 615 sp = &mp->mnt_stat; 616 error = VFS_STATFS(mp, sp, p); 617 if (error) 618 return (error); 619 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 620 if (p->p_ucred->cr_uid != 0) { 621 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); 622 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; 623 sp = &sb; 624 } 625 return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp))); 626} 627 628/* 629 * Get statistics on all filesystems. 630 */ 631#ifndef _SYS_SYSPROTO_H_ 632struct getfsstat_args { 633 struct statfs *buf; 634 long bufsize; 635 int flags; 636}; 637#endif 638int 639getfsstat(p, uap) 640 struct proc *p; 641 register struct getfsstat_args /* { 642 syscallarg(struct statfs *) buf; 643 syscallarg(long) bufsize; 644 syscallarg(int) flags; 645 } */ *uap; 646{ 647 register struct mount *mp, *nmp; 648 register struct statfs *sp; 649 caddr_t sfsp; 650 long count, maxcount, error; 651 652 maxcount = SCARG(uap, bufsize) / sizeof(struct statfs); 653 sfsp = (caddr_t)SCARG(uap, buf); 654 count = 0; 655 simple_lock(&mountlist_slock); 656 for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) { 657 if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) { 658 nmp = mp->mnt_list.cqe_next; 659 continue; 660 } 661 if (sfsp && count < maxcount) { 662 sp = &mp->mnt_stat; 663 /* 664 * If MNT_NOWAIT is specified, do not refresh the 665 * fsstat cache. MNT_WAIT overrides MNT_NOWAIT. 666 */ 667 if (((SCARG(uap, flags) & MNT_NOWAIT) == 0 || 668 (SCARG(uap, flags) & MNT_WAIT)) && 669 (error = VFS_STATFS(mp, sp, p))) { 670 simple_lock(&mountlist_slock); 671 nmp = mp->mnt_list.cqe_next; 672 vfs_unbusy(mp, p); 673 continue; 674 } 675 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 676 error = copyout((caddr_t)sp, sfsp, sizeof(*sp)); 677 if (error) { 678 vfs_unbusy(mp, p); 679 return (error); 680 } 681 sfsp += sizeof(*sp); 682 } 683 count++; 684 simple_lock(&mountlist_slock); 685 nmp = mp->mnt_list.cqe_next; 686 vfs_unbusy(mp, p); 687 } 688 simple_unlock(&mountlist_slock); 689 if (sfsp && count > maxcount) 690 p->p_retval[0] = maxcount; 691 else 692 p->p_retval[0] = count; 693 return (0); 694} 695 696/* 697 * Change current working directory to a given file descriptor. 698 */ 699#ifndef _SYS_SYSPROTO_H_ 700struct fchdir_args { 701 int fd; 702}; 703#endif 704/* ARGSUSED */ 705int 706fchdir(p, uap) 707 struct proc *p; 708 struct fchdir_args /* { 709 syscallarg(int) fd; 710 } */ *uap; 711{ 712 register struct filedesc *fdp = p->p_fd; 713 struct vnode *vp, *tdp; 714 struct mount *mp; 715 struct file *fp; 716 int error; 717 718 if (error = getvnode(fdp, SCARG(uap, fd), &fp)) 719 return (error); 720 vp = (struct vnode *)fp->f_data; 721 VREF(vp); 722 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 723 if (vp->v_type != VDIR) 724 error = ENOTDIR; 725 else 726 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); 727 while (!error && (mp = vp->v_mountedhere) != NULL) { 728 if (vfs_busy(mp, 0, 0, p)) 729 continue; 730 error = VFS_ROOT(mp, &tdp); 731 vfs_unbusy(mp, p); 732 if (error) 733 break; 734 vput(vp); 735 vp = tdp; 736 } 737 if (error) { 738 vput(vp); 739 return (error); 740 } 741 VOP_UNLOCK(vp, 0, p); 742 vrele(fdp->fd_cdir); 743 fdp->fd_cdir = vp; 744 return (0); 745} 746 747/* 748 * Change current working directory (``.''). 749 */ 750#ifndef _SYS_SYSPROTO_H_ 751struct chdir_args { 752 char *path; 753}; 754#endif 755/* ARGSUSED */ 756int 757chdir(p, uap) 758 struct proc *p; 759 struct chdir_args /* { 760 syscallarg(char *) path; 761 } */ *uap; 762{ 763 register struct filedesc *fdp = p->p_fd; 764 int error; 765 struct nameidata nd; 766 767 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 768 SCARG(uap, path), p); 769 if (error = change_dir(&nd, p)) 770 return (error); 771 vrele(fdp->fd_cdir); 772 fdp->fd_cdir = nd.ni_vp; 773 return (0); 774} 775 776/* 777 * Change notion of root (``/'') directory. 778 */ 779#ifndef _SYS_SYSPROTO_H_ 780struct chroot_args { 781 char *path; 782}; 783#endif 784/* ARGSUSED */ 785int 786chroot(p, uap) 787 struct proc *p; 788 struct chroot_args /* { 789 syscallarg(char *) path; 790 } */ *uap; 791{ 792 register struct filedesc *fdp = p->p_fd; 793 int error; 794 struct nameidata nd; 795 796 error = suser(p->p_ucred, &p->p_acflag); 797 if (error) 798 return (error); 799 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 800 SCARG(uap, path), p); 801 if (error = change_dir(&nd, p)) 802 return (error); 803 if (fdp->fd_rdir != NULL) 804 vrele(fdp->fd_rdir); 805 fdp->fd_rdir = nd.ni_vp; 806 return (0); 807} 808 809/* 810 * Common routine for chroot and chdir. 811 */ 812static int 813change_dir(ndp, p) 814 register struct nameidata *ndp; 815 struct proc *p; 816{ 817 struct vnode *vp; 818 int error; 819 820 error = namei(ndp); 821 if (error) 822 return (error); 823 vp = ndp->ni_vp; 824 if (vp->v_type != VDIR) 825 error = ENOTDIR; 826 else 827 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); 828 if (error) 829 vput(vp); 830 else 831 VOP_UNLOCK(vp, 0, p); 832 return (error); 833} 834 835/* 836 * Check permissions, allocate an open file structure, 837 * and call the device open routine if any. 838 */ 839#ifndef _SYS_SYSPROTO_H_ 840struct open_args { 841 char *path; 842 int flags; 843 int mode; 844}; 845#endif 846int 847open(p, uap) 848 struct proc *p; 849 register struct open_args /* { 850 syscallarg(char *) path; 851 syscallarg(int) flags; 852 syscallarg(int) mode; 853 } */ *uap; 854{ 855 register struct filedesc *fdp = p->p_fd; 856 register struct file *fp; 857 register struct vnode *vp; 858 int cmode, flags, oflags; 859 struct file *nfp; 860 int type, indx, error; 861 struct flock lf; 862 struct nameidata nd; 863 864 oflags = SCARG(uap, flags); 865 if ((oflags & O_ACCMODE) == O_ACCMODE) 866 return (EINVAL); 867 flags = FFLAGS(oflags); 868 error = falloc(p, &nfp, &indx); 869 if (error) 870 return (error); 871 fp = nfp; 872 cmode = ((SCARG(uap, mode) &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT; 873 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 874 p->p_dupfd = -indx - 1; /* XXX check for fdopen */ 875 error = vn_open(&nd, flags, cmode); 876 if (error) { 877 ffree(fp); 878 if ((error == ENODEV || error == ENXIO) && 879 p->p_dupfd >= 0 && /* XXX from fdopen */ 880 (error = 881 dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) { 882 p->p_retval[0] = indx; 883 return (0); 884 } 885 if (error == ERESTART) 886 error = EINTR; 887 fdp->fd_ofiles[indx] = NULL; 888 return (error); 889 } 890 p->p_dupfd = 0; 891 vp = nd.ni_vp; 892 893 fp->f_flag = flags & FMASK; 894 fp->f_type = (vp->v_type == VFIFO ? DTYPE_FIFO : DTYPE_VNODE); 895 fp->f_ops = &vnops; 896 fp->f_data = (caddr_t)vp; 897 if (flags & (O_EXLOCK | O_SHLOCK)) { 898 lf.l_whence = SEEK_SET; 899 lf.l_start = 0; 900 lf.l_len = 0; 901 if (flags & O_EXLOCK) 902 lf.l_type = F_WRLCK; 903 else 904 lf.l_type = F_RDLCK; 905 type = F_FLOCK; 906 if ((flags & FNONBLOCK) == 0) 907 type |= F_WAIT; 908 VOP_UNLOCK(vp, 0, p); 909 if (error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) { 910 (void) vn_close(vp, fp->f_flag, fp->f_cred, p); 911 ffree(fp); 912 fdp->fd_ofiles[indx] = NULL; 913 return (error); 914 } 915 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 916 fp->f_flag |= FHASLOCK; 917 } 918 VOP_UNLOCK(vp, 0, p); 919 p->p_retval[0] = indx; 920 return (0); 921} 922 923#ifdef COMPAT_43 924/* 925 * Create a file. 926 */ 927#ifndef _SYS_SYSPROTO_H_ 928struct ocreat_args { 929 char *path; 930 int mode; 931}; 932#endif 933int 934ocreat(p, uap) 935 struct proc *p; 936 register struct ocreat_args /* { 937 syscallarg(char *) path; 938 syscallarg(int) mode; 939 } */ *uap; 940{ 941 struct open_args /* { 942 syscallarg(char *) path; 943 syscallarg(int) flags; 944 syscallarg(int) mode; 945 } */ nuap; 946 947 SCARG(&nuap, path) = SCARG(uap, path); 948 SCARG(&nuap, mode) = SCARG(uap, mode); 949 SCARG(&nuap, flags) = O_WRONLY | O_CREAT | O_TRUNC; 950 return (open(p, &nuap)); 951} 952#endif /* COMPAT_43 */ 953 954/* 955 * Create a special file. 956 */ 957#ifndef _SYS_SYSPROTO_H_ 958struct mknod_args { 959 char *path; 960 int mode; 961 int dev; 962}; 963#endif 964/* ARGSUSED */ 965int 966mknod(p, uap) 967 struct proc *p; 968 register struct mknod_args /* { 969 syscallarg(char *) path; 970 syscallarg(int) mode; 971 syscallarg(int) dev; 972 } */ *uap; 973{ 974 register struct vnode *vp; 975 struct vattr vattr; 976 int error; 977 int whiteout; 978 struct nameidata nd; 979 980 error = suser(p->p_ucred, &p->p_acflag); 981 if (error) 982 return (error); 983 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); 984 if (error = namei(&nd)) 985 return (error); 986 vp = nd.ni_vp; 987 if (vp != NULL) 988 error = EEXIST; 989 else { 990 VATTR_NULL(&vattr); 991 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask; 992 vattr.va_rdev = SCARG(uap, dev); 993 whiteout = 0; 994 995 switch (SCARG(uap, mode) & S_IFMT) { 996 case S_IFMT: /* used by badsect to flag bad sectors */ 997 vattr.va_type = VBAD; 998 break; 999 case S_IFCHR: 1000 vattr.va_type = VCHR; 1001 break; 1002 case S_IFBLK: 1003 vattr.va_type = VBLK; 1004 break; 1005 case S_IFWHT: 1006 whiteout = 1; 1007 break; 1008 default: 1009 error = EINVAL; 1010 break; 1011 } 1012 } 1013 if (!error) { 1014 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1015 if (whiteout) { 1016 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE); 1017 if (error) 1018 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1019 vput(nd.ni_dvp); 1020 } else { 1021 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, 1022 &nd.ni_cnd, &vattr); 1023 } 1024 } else { 1025 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1026 if (nd.ni_dvp == vp) 1027 vrele(nd.ni_dvp); 1028 else 1029 vput(nd.ni_dvp); 1030 if (vp) 1031 vrele(vp); 1032 } 1033 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mknod"); 1034 ASSERT_VOP_UNLOCKED(nd.ni_vp, "mknod"); 1035 return (error); 1036} 1037 1038/* 1039 * Create a named pipe. 1040 */ 1041#ifndef _SYS_SYSPROTO_H_ 1042struct mkfifo_args { 1043 char *path; 1044 int mode; 1045}; 1046#endif 1047/* ARGSUSED */ 1048int 1049mkfifo(p, uap) 1050 struct proc *p; 1051 register struct mkfifo_args /* { 1052 syscallarg(char *) path; 1053 syscallarg(int) mode; 1054 } */ *uap; 1055{ 1056 struct vattr vattr; 1057 int error; 1058 struct nameidata nd; 1059 1060 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); 1061 if (error = namei(&nd)) 1062 return (error); 1063 if (nd.ni_vp != NULL) { 1064 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1065 if (nd.ni_dvp == nd.ni_vp) 1066 vrele(nd.ni_dvp); 1067 else 1068 vput(nd.ni_dvp); 1069 vrele(nd.ni_vp); 1070 return (EEXIST); 1071 } 1072 VATTR_NULL(&vattr); 1073 vattr.va_type = VFIFO; 1074 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask; 1075 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1076 return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr)); 1077} 1078 1079/* 1080 * Make a hard file link. 1081 */ 1082#ifndef _SYS_SYSPROTO_H_ 1083struct link_args { 1084 char *path; 1085 char *link; 1086}; 1087#endif 1088/* ARGSUSED */ 1089int 1090link(p, uap) 1091 struct proc *p; 1092 register struct link_args /* { 1093 syscallarg(char *) path; 1094 syscallarg(char *) link; 1095 } */ *uap; 1096{ 1097 register struct vnode *vp; 1098 struct nameidata nd; 1099 int error; 1100 1101 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1102 if (error = namei(&nd)) 1103 return (error); 1104 vp = nd.ni_vp; 1105 if (vp->v_type == VDIR) 1106 error = EPERM; /* POSIX */ 1107 else { 1108 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p); 1109 error = namei(&nd); 1110 if (!error) { 1111 if (nd.ni_vp != NULL) { 1112 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1113 if (nd.ni_dvp == nd.ni_vp) 1114 vrele(nd.ni_dvp); 1115 else 1116 vput(nd.ni_dvp); 1117 if (nd.ni_vp) 1118 vrele(nd.ni_vp); 1119 error = EEXIST; 1120 } else { 1121 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, 1122 LEASE_WRITE); 1123 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1124 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd); 1125 } 1126 } 1127 } 1128 vrele(vp); 1129 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "link"); 1130 ASSERT_VOP_UNLOCKED(nd.ni_vp, "link"); 1131 return (error); 1132} 1133 1134/* 1135 * Make a symbolic link. 1136 */ 1137#ifndef _SYS_SYSPROTO_H_ 1138struct symlink_args { 1139 char *path; 1140 char *link; 1141}; 1142#endif 1143/* ARGSUSED */ 1144int 1145symlink(p, uap) 1146 struct proc *p; 1147 register struct symlink_args /* { 1148 syscallarg(char *) path; 1149 syscallarg(char *) link; 1150 } */ *uap; 1151{ 1152 struct vattr vattr; 1153 char *path; 1154 int error; 1155 struct nameidata nd; 1156 1157 path = zalloc(namei_zone); 1158 if (error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL)) 1159 goto out; 1160 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p); 1161 if (error = namei(&nd)) 1162 goto out; 1163 if (nd.ni_vp) { 1164 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1165 if (nd.ni_dvp == nd.ni_vp) 1166 vrele(nd.ni_dvp); 1167 else 1168 vput(nd.ni_dvp); 1169 vrele(nd.ni_vp); 1170 error = EEXIST; 1171 goto out; 1172 } 1173 VATTR_NULL(&vattr); 1174 vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask; 1175 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1176 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path); 1177 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "symlink"); 1178 ASSERT_VOP_UNLOCKED(nd.ni_vp, "symlink"); 1179out: 1180 zfree(namei_zone, path); 1181 return (error); 1182} 1183 1184/* 1185 * Delete a whiteout from the filesystem. 1186 */ 1187/* ARGSUSED */ 1188int 1189undelete(p, uap) 1190 struct proc *p; 1191 register struct undelete_args /* { 1192 syscallarg(char *) path; 1193 } */ *uap; 1194{ 1195 int error; 1196 struct nameidata nd; 1197 1198 NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE, 1199 SCARG(uap, path), p); 1200 error = namei(&nd); 1201 if (error) 1202 return (error); 1203 1204 if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) { 1205 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1206 if (nd.ni_dvp == nd.ni_vp) 1207 vrele(nd.ni_dvp); 1208 else 1209 vput(nd.ni_dvp); 1210 if (nd.ni_vp) 1211 vrele(nd.ni_vp); 1212 return (EEXIST); 1213 } 1214 1215 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1216 if (error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE)) 1217 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1218 vput(nd.ni_dvp); 1219 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "undelete"); 1220 ASSERT_VOP_UNLOCKED(nd.ni_vp, "undelete"); 1221 return (error); 1222} 1223 1224/* 1225 * Delete a name from the filesystem. 1226 */ 1227#ifndef _SYS_SYSPROTO_H_ 1228struct unlink_args { 1229 char *path; 1230}; 1231#endif 1232/* ARGSUSED */ 1233int 1234unlink(p, uap) 1235 struct proc *p; 1236 struct unlink_args /* { 1237 syscallarg(char *) path; 1238 } */ *uap; 1239{ 1240 register struct vnode *vp; 1241 int error; 1242 struct nameidata nd; 1243 1244 NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); 1245 if (error = namei(&nd)) 1246 return (error); 1247 vp = nd.ni_vp; 1248 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1249 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1250 1251 if (vp->v_type == VDIR) 1252 error = EPERM; /* POSIX */ 1253 else { 1254 /* 1255 * The root of a mounted filesystem cannot be deleted. 1256 * 1257 * XXX: can this only be a VDIR case? 1258 */ 1259 if (vp->v_flag & VROOT) 1260 error = EBUSY; 1261 else 1262 (void) vnode_pager_uncache(vp, p); 1263 } 1264 1265 if (!error) { 1266 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1267 error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 1268 } else { 1269 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1270 if (nd.ni_dvp == vp) 1271 vrele(nd.ni_dvp); 1272 else 1273 vput(nd.ni_dvp); 1274 if (vp != NULLVP) 1275 vput(vp); 1276 } 1277 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "unlink"); 1278 ASSERT_VOP_UNLOCKED(nd.ni_vp, "unlink"); 1279 return (error); 1280} 1281 1282/* 1283 * Reposition read/write file offset. 1284 */ 1285#ifndef _SYS_SYSPROTO_H_ 1286struct lseek_args { 1287 int fd; 1288 int pad; 1289 off_t offset; 1290 int whence; 1291}; 1292#endif 1293int 1294lseek(p, uap) 1295 struct proc *p; 1296 register struct lseek_args /* { 1297 syscallarg(int) fd; 1298 syscallarg(int) pad; 1299 syscallarg(off_t) offset; 1300 syscallarg(int) whence; 1301 } */ *uap; 1302{ 1303 struct ucred *cred = p->p_ucred; 1304 register struct filedesc *fdp = p->p_fd; 1305 register struct file *fp; 1306 struct vattr vattr; 1307 int error; 1308 1309 if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles || 1310 (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL) 1311 return (EBADF); 1312 if (fp->f_type != DTYPE_VNODE) 1313 return (ESPIPE); 1314 switch (SCARG(uap, whence)) { 1315 case L_INCR: 1316 fp->f_offset += SCARG(uap, offset); 1317 break; 1318 case L_XTND: 1319 error=VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p); 1320 if (error) 1321 return (error); 1322 fp->f_offset = SCARG(uap, offset) + vattr.va_size; 1323 break; 1324 case L_SET: 1325 fp->f_offset = SCARG(uap, offset); 1326 break; 1327 default: 1328 return (EINVAL); 1329 } 1330 *(off_t *)(p->p_retval) = fp->f_offset; 1331 return (0); 1332} 1333 1334#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1335/* 1336 * Reposition read/write file offset. 1337 */ 1338#ifndef _SYS_SYSPROTO_H_ 1339struct olseek_args { 1340 int fd; 1341 long offset; 1342 int whence; 1343}; 1344#endif 1345int 1346olseek(p, uap) 1347 struct proc *p; 1348 register struct olseek_args /* { 1349 syscallarg(int) fd; 1350 syscallarg(long) offset; 1351 syscallarg(int) whence; 1352 } */ *uap; 1353{ 1354 struct lseek_args /* { 1355 syscallarg(int) fd; 1356 syscallarg(int) pad; 1357 syscallarg(off_t) offset; 1358 syscallarg(int) whence; 1359 } */ nuap; 1360 int error; 1361 1362 SCARG(&nuap, fd) = SCARG(uap, fd); 1363 SCARG(&nuap, offset) = SCARG(uap, offset); 1364 SCARG(&nuap, whence) = SCARG(uap, whence); 1365 error = lseek(p, &nuap); 1366 return (error); 1367} 1368#endif /* COMPAT_43 */ 1369 1370/* 1371 * Check access permissions. 1372 */ 1373#ifndef _SYS_SYSPROTO_H_ 1374struct access_args { 1375 char *path; 1376 int flags; 1377}; 1378#endif 1379int 1380access(p, uap) 1381 struct proc *p; 1382 register struct access_args /* { 1383 syscallarg(char *) path; 1384 syscallarg(int) flags; 1385 } */ *uap; 1386{ 1387 register struct ucred *cred = p->p_ucred; 1388 register struct vnode *vp; 1389 int error, flags, t_gid, t_uid; 1390 struct nameidata nd; 1391 1392 t_uid = cred->cr_uid; 1393 t_gid = cred->cr_groups[0]; 1394 cred->cr_uid = p->p_cred->p_ruid; 1395 cred->cr_groups[0] = p->p_cred->p_rgid; 1396 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 1397 SCARG(uap, path), p); 1398 if (error = namei(&nd)) 1399 goto out1; 1400 vp = nd.ni_vp; 1401 1402 /* Flags == 0 means only check for existence. */ 1403 if (SCARG(uap, flags)) { 1404 flags = 0; 1405 if (SCARG(uap, flags) & R_OK) 1406 flags |= VREAD; 1407 if (SCARG(uap, flags) & W_OK) 1408 flags |= VWRITE; 1409 if (SCARG(uap, flags) & X_OK) 1410 flags |= VEXEC; 1411 if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0) 1412 error = VOP_ACCESS(vp, flags, cred, p); 1413 } 1414 vput(vp); 1415out1: 1416 cred->cr_uid = t_uid; 1417 cred->cr_groups[0] = t_gid; 1418 return (error); 1419} 1420 1421#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1422/* 1423 * Get file status; this version follows links. 1424 */ 1425#ifndef _SYS_SYSPROTO_H_ 1426struct ostat_args { 1427 char *path; 1428 struct ostat *ub; 1429}; 1430#endif 1431/* ARGSUSED */ 1432int 1433ostat(p, uap) 1434 struct proc *p; 1435 register struct ostat_args /* { 1436 syscallarg(char *) path; 1437 syscallarg(struct ostat *) ub; 1438 } */ *uap; 1439{ 1440 struct stat sb; 1441 struct ostat osb; 1442 int error; 1443 struct nameidata nd; 1444 1445 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 1446 SCARG(uap, path), p); 1447 if (error = namei(&nd)) 1448 return (error); 1449 error = vn_stat(nd.ni_vp, &sb, p); 1450 vput(nd.ni_vp); 1451 if (error) 1452 return (error); 1453 cvtstat(&sb, &osb); 1454 error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb)); 1455 return (error); 1456} 1457 1458/* 1459 * Get file status; this version does not follow links. 1460 */ 1461#ifndef _SYS_SYSPROTO_H_ 1462struct olstat_args { 1463 char *path; 1464 struct ostat *ub; 1465}; 1466#endif 1467/* ARGSUSED */ 1468int 1469olstat(p, uap) 1470 struct proc *p; 1471 register struct olstat_args /* { 1472 syscallarg(char *) path; 1473 syscallarg(struct ostat *) ub; 1474 } */ *uap; 1475{ 1476 struct vnode *vp; 1477 struct stat sb; 1478 struct ostat osb; 1479 int error; 1480 struct nameidata nd; 1481 1482 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, 1483 SCARG(uap, path), p); 1484 if (error = namei(&nd)) 1485 return (error); 1486 vp = nd.ni_vp; 1487 error = vn_stat(vp, &sb, p); 1488 if (vp->v_type == VLNK) 1489 sb.st_mode |= S_IFLNK | ACCESSPERMS; /* 0777 */ 1490 vput(vp); 1491 if (error) 1492 return (error); 1493 cvtstat(&sb, &osb); 1494 error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb)); 1495 return (error); 1496} 1497 1498/* 1499 * Convert from an old to a new stat structure. 1500 */ 1501void 1502cvtstat(st, ost) 1503 struct stat *st; 1504 struct ostat *ost; 1505{ 1506 1507 ost->st_dev = st->st_dev; 1508 ost->st_ino = st->st_ino; 1509 ost->st_mode = st->st_mode; 1510 ost->st_nlink = st->st_nlink; 1511 ost->st_uid = st->st_uid; 1512 ost->st_gid = st->st_gid; 1513 ost->st_rdev = st->st_rdev; 1514 if (st->st_size < (quad_t)1 << 32) 1515 ost->st_size = st->st_size; 1516 else 1517 ost->st_size = -2; 1518 ost->st_atime = st->st_atime; 1519 ost->st_mtime = st->st_mtime; 1520 ost->st_ctime = st->st_ctime; 1521 ost->st_blksize = st->st_blksize; 1522 ost->st_blocks = st->st_blocks; 1523 ost->st_flags = st->st_flags; 1524 ost->st_gen = st->st_gen; 1525} 1526#endif /* COMPAT_43 || COMPAT_SUNOS */ 1527 1528/* 1529 * Get file status; this version follows links. 1530 */ 1531#ifndef _SYS_SYSPROTO_H_ 1532struct stat_args { 1533 char *path; 1534 struct stat *ub; 1535}; 1536#endif 1537/* ARGSUSED */ 1538int 1539stat(p, uap) 1540 struct proc *p; 1541 register struct stat_args /* { 1542 syscallarg(char *) path; 1543 syscallarg(struct stat *) ub; 1544 } */ *uap; 1545{ 1546 struct stat sb; 1547 int error; 1548 struct nameidata nd; 1549 1550 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 1551 SCARG(uap, path), p); 1552 if (error = namei(&nd)) 1553 return (error); 1554 error = vn_stat(nd.ni_vp, &sb, p); 1555 vput(nd.ni_vp); 1556 if (error) 1557 return (error); 1558 error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb)); 1559 return (error); 1560} 1561 1562/* 1563 * Get file status; this version does not follow links. 1564 */ 1565#ifndef _SYS_SYSPROTO_H_ 1566struct lstat_args { 1567 char *path; 1568 struct stat *ub; 1569}; 1570#endif 1571/* ARGSUSED */ 1572int 1573lstat(p, uap) 1574 struct proc *p; 1575 register struct lstat_args /* { 1576 syscallarg(char *) path; 1577 syscallarg(struct stat *) ub; 1578 } */ *uap; 1579{ 1580 int error; 1581 struct vnode *vp; 1582 struct stat sb; 1583 struct nameidata nd; 1584 1585 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, 1586 SCARG(uap, path), p); 1587 if (error = namei(&nd)) 1588 return (error); 1589 vp = nd.ni_vp; 1590 error = vn_stat(vp, &sb, p); 1591 if (vp->v_type == VLNK) 1592 sb.st_mode |= S_IFLNK | ACCESSPERMS; /* 0777 */ 1593 vput(vp); 1594 if (error) 1595 return (error); 1596 error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb)); 1597 return (error); 1598} 1599 1600/* 1601 * Get configurable pathname variables. 1602 */ 1603#ifndef _SYS_SYSPROTO_H_ 1604struct pathconf_args { 1605 char *path; 1606 int name; 1607}; 1608#endif 1609/* ARGSUSED */ 1610int 1611pathconf(p, uap) 1612 struct proc *p; 1613 register struct pathconf_args /* { 1614 syscallarg(char *) path; 1615 syscallarg(int) name; 1616 } */ *uap; 1617{ 1618 int error; 1619 struct nameidata nd; 1620 1621 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 1622 SCARG(uap, path), p); 1623 if (error = namei(&nd)) 1624 return (error); 1625 error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), p->p_retval); 1626 vput(nd.ni_vp); 1627 return (error); 1628} 1629 1630/* 1631 * Return target name of a symbolic link. 1632 */ 1633#ifndef _SYS_SYSPROTO_H_ 1634struct readlink_args { 1635 char *path; 1636 char *buf; 1637 int count; 1638}; 1639#endif 1640/* ARGSUSED */ 1641int 1642readlink(p, uap) 1643 struct proc *p; 1644 register struct readlink_args /* { 1645 syscallarg(char *) path; 1646 syscallarg(char *) buf; 1647 syscallarg(int) count; 1648 } */ *uap; 1649{ 1650 register struct vnode *vp; 1651 struct iovec aiov; 1652 struct uio auio; 1653 int error; 1654 struct nameidata nd; 1655 1656 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, 1657 SCARG(uap, path), p); 1658 if (error = namei(&nd)) 1659 return (error); 1660 vp = nd.ni_vp; 1661 if (vp->v_type != VLNK) 1662 error = EINVAL; 1663 else { 1664 aiov.iov_base = SCARG(uap, buf); 1665 aiov.iov_len = SCARG(uap, count); 1666 auio.uio_iov = &aiov; 1667 auio.uio_iovcnt = 1; 1668 auio.uio_offset = 0; 1669 auio.uio_rw = UIO_READ; 1670 auio.uio_segflg = UIO_USERSPACE; 1671 auio.uio_procp = p; 1672 auio.uio_resid = SCARG(uap, count); 1673 error = VOP_READLINK(vp, &auio, p->p_ucred); 1674 } 1675 vput(vp); 1676 p->p_retval[0] = SCARG(uap, count) - auio.uio_resid; 1677 return (error); 1678} 1679 1680/* 1681 * Change flags of a file given a path name. 1682 */ 1683#ifndef _SYS_SYSPROTO_H_ 1684struct chflags_args { 1685 char *path; 1686 int flags; 1687}; 1688#endif 1689/* ARGSUSED */ 1690int 1691chflags(p, uap) 1692 struct proc *p; 1693 register struct chflags_args /* { 1694 syscallarg(char *) path; 1695 syscallarg(int) flags; 1696 } */ *uap; 1697{ 1698 register struct vnode *vp; 1699 struct vattr vattr; 1700 int error; 1701 struct nameidata nd; 1702 1703 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1704 if (error = namei(&nd)) 1705 return (error); 1706 vp = nd.ni_vp; 1707 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1708 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1709 VATTR_NULL(&vattr); 1710 vattr.va_flags = SCARG(uap, flags); 1711 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1712 vput(vp); 1713 return (error); 1714} 1715 1716/* 1717 * Change flags of a file given a file descriptor. 1718 */ 1719#ifndef _SYS_SYSPROTO_H_ 1720struct fchflags_args { 1721 int fd; 1722 int flags; 1723}; 1724#endif 1725/* ARGSUSED */ 1726int 1727fchflags(p, uap) 1728 struct proc *p; 1729 register struct fchflags_args /* { 1730 syscallarg(int) fd; 1731 syscallarg(int) flags; 1732 } */ *uap; 1733{ 1734 struct vattr vattr; 1735 struct vnode *vp; 1736 struct file *fp; 1737 int error; 1738 1739 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 1740 return (error); 1741 vp = (struct vnode *)fp->f_data; 1742 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1743 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1744 VATTR_NULL(&vattr); 1745 vattr.va_flags = SCARG(uap, flags); 1746 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1747 VOP_UNLOCK(vp, 0, p); 1748 return (error); 1749} 1750 1751/* 1752 * Change mode of a file given path name. 1753 */ 1754#ifndef _SYS_SYSPROTO_H_ 1755struct chmod_args { 1756 char *path; 1757 int mode; 1758}; 1759#endif 1760/* ARGSUSED */ 1761int 1762chmod(p, uap) 1763 struct proc *p; 1764 register struct chmod_args /* { 1765 syscallarg(char *) path; 1766 syscallarg(int) mode; 1767 } */ *uap; 1768{ 1769 register struct vnode *vp; 1770 struct vattr vattr; 1771 int error; 1772 struct nameidata nd; 1773 1774 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1775 if (error = namei(&nd)) 1776 return (error); 1777 vp = nd.ni_vp; 1778 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1779 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1780 VATTR_NULL(&vattr); 1781 vattr.va_mode = SCARG(uap, mode) & ALLPERMS; 1782 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1783 vput(vp); 1784 return (error); 1785} 1786 1787/* 1788 * Change mode of a file given a file descriptor. 1789 */ 1790#ifndef _SYS_SYSPROTO_H_ 1791struct fchmod_args { 1792 int fd; 1793 int mode; 1794}; 1795#endif 1796/* ARGSUSED */ 1797int 1798fchmod(p, uap) 1799 struct proc *p; 1800 register struct fchmod_args /* { 1801 syscallarg(int) fd; 1802 syscallarg(int) mode; 1803 } */ *uap; 1804{ 1805 struct vattr vattr; 1806 struct vnode *vp; 1807 struct file *fp; 1808 int error; 1809 1810 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 1811 return (error); 1812 vp = (struct vnode *)fp->f_data; 1813 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1814 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1815 VATTR_NULL(&vattr); 1816 vattr.va_mode = SCARG(uap, mode) & ALLPERMS; 1817 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1818 VOP_UNLOCK(vp, 0, p); 1819 return (error); 1820} 1821 1822/* 1823 * Set ownership given a path name. 1824 */ 1825#ifndef _SYS_SYSPROTO_H_ 1826struct chown_args { 1827 char *path; 1828 int uid; 1829 int gid; 1830}; 1831#endif 1832/* ARGSUSED */ 1833int 1834chown(p, uap) 1835 struct proc *p; 1836 register struct chown_args /* { 1837 syscallarg(char *) path; 1838 syscallarg(int) uid; 1839 syscallarg(int) gid; 1840 } */ *uap; 1841{ 1842 register struct vnode *vp; 1843 struct vattr vattr; 1844 int error; 1845 struct nameidata nd; 1846 1847 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1848 if (error = namei(&nd)) 1849 return (error); 1850 vp = nd.ni_vp; 1851 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1852 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1853 VATTR_NULL(&vattr); 1854 vattr.va_uid = SCARG(uap, uid); 1855 vattr.va_gid = SCARG(uap, gid); 1856 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1857 vput(vp); 1858 return (error); 1859} 1860 1861/* 1862 * Set ownership given a path name, do not cross symlinks. 1863 */ 1864#ifndef _SYS_SYSPROTO_H_ 1865struct lchown_args { 1866 char *path; 1867 int uid; 1868 int gid; 1869}; 1870#endif 1871/* ARGSUSED */ 1872int 1873lchown(p, uap) 1874 struct proc *p; 1875 register struct lchown_args /* { 1876 syscallarg(char *) path; 1877 syscallarg(int) uid; 1878 syscallarg(int) gid; 1879 } */ *uap; 1880{ 1881 register struct vnode *vp; 1882 struct vattr vattr; 1883 int error; 1884 struct nameidata nd; 1885 1886 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1887 if (error = namei(&nd)) 1888 return (error); 1889 vp = nd.ni_vp; 1890 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1891 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1892 VATTR_NULL(&vattr); 1893 vattr.va_uid = SCARG(uap, uid); 1894 vattr.va_gid = SCARG(uap, gid); 1895 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1896 vput(vp); 1897 return (error); 1898} 1899 1900/* 1901 * Set ownership given a file descriptor. 1902 */ 1903#ifndef _SYS_SYSPROTO_H_ 1904struct fchown_args { 1905 int fd; 1906 int uid; 1907 int gid; 1908}; 1909#endif 1910/* ARGSUSED */ 1911int 1912fchown(p, uap) 1913 struct proc *p; 1914 register struct fchown_args /* { 1915 syscallarg(int) fd; 1916 syscallarg(int) uid; 1917 syscallarg(int) gid; 1918 } */ *uap; 1919{ 1920 struct vattr vattr; 1921 struct vnode *vp; 1922 struct file *fp; 1923 int error; 1924 1925 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 1926 return (error); 1927 vp = (struct vnode *)fp->f_data; 1928 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1929 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1930 VATTR_NULL(&vattr); 1931 vattr.va_uid = SCARG(uap, uid); 1932 vattr.va_gid = SCARG(uap, gid); 1933 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1934 VOP_UNLOCK(vp, 0, p); 1935 return (error); 1936} 1937 1938/* 1939 * Set the access and modification times of a file. 1940 */ 1941#ifndef _SYS_SYSPROTO_H_ 1942struct utimes_args { 1943 char *path; 1944 struct timeval *tptr; 1945}; 1946#endif 1947/* ARGSUSED */ 1948int 1949utimes(p, uap) 1950 struct proc *p; 1951 register struct utimes_args /* { 1952 syscallarg(char *) path; 1953 syscallarg(struct timeval *) tptr; 1954 } */ *uap; 1955{ 1956 register struct vnode *vp; 1957 struct timeval tv[2]; 1958 struct vattr vattr; 1959 int error; 1960 struct nameidata nd; 1961 1962 VATTR_NULL(&vattr); 1963 if (SCARG(uap, tptr) == NULL) { 1964 microtime(&tv[0]); 1965 tv[1] = tv[0]; 1966 vattr.va_vaflags |= VA_UTIMES_NULL; 1967 } else if (error = copyin((caddr_t)SCARG(uap, tptr), (caddr_t)tv, 1968 sizeof (tv))) 1969 return (error); 1970 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1971 if (error = namei(&nd)) 1972 return (error); 1973 vp = nd.ni_vp; 1974 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1975 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1976 vattr.va_atime.tv_sec = tv[0].tv_sec; 1977 vattr.va_atime.tv_nsec = tv[0].tv_usec * 1000; 1978 vattr.va_mtime.tv_sec = tv[1].tv_sec; 1979 vattr.va_mtime.tv_nsec = tv[1].tv_usec * 1000; 1980 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1981 vput(vp); 1982 return (error); 1983} 1984 1985/* 1986 * Truncate a file given its path name. 1987 */ 1988#ifndef _SYS_SYSPROTO_H_ 1989struct truncate_args { 1990 char *path; 1991 int pad; 1992 off_t length; 1993}; 1994#endif 1995/* ARGSUSED */ 1996int 1997truncate(p, uap) 1998 struct proc *p; 1999 register struct truncate_args /* { 2000 syscallarg(char *) path; 2001 syscallarg(int) pad; 2002 syscallarg(off_t) length; 2003 } */ *uap; 2004{ 2005 register struct vnode *vp; 2006 struct vattr vattr; 2007 int error; 2008 struct nameidata nd; 2009 2010 if (uap->length < 0) 2011 return(EINVAL); 2012 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 2013 if (error = namei(&nd)) 2014 return (error); 2015 vp = nd.ni_vp; 2016 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 2017 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2018 if (vp->v_type == VDIR) 2019 error = EISDIR; 2020 else if ((error = vn_writechk(vp)) == 0 && 2021 (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) { 2022 VATTR_NULL(&vattr); 2023 vattr.va_size = SCARG(uap, length); 2024 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 2025 } 2026 vput(vp); 2027 return (error); 2028} 2029 2030/* 2031 * Truncate a file given a file descriptor. 2032 */ 2033#ifndef _SYS_SYSPROTO_H_ 2034struct ftruncate_args { 2035 int fd; 2036 int pad; 2037 off_t length; 2038}; 2039#endif 2040/* ARGSUSED */ 2041int 2042ftruncate(p, uap) 2043 struct proc *p; 2044 register struct ftruncate_args /* { 2045 syscallarg(int) fd; 2046 syscallarg(int) pad; 2047 syscallarg(off_t) length; 2048 } */ *uap; 2049{ 2050 struct vattr vattr; 2051 struct vnode *vp; 2052 struct file *fp; 2053 int error; 2054 2055 if (uap->length < 0) 2056 return(EINVAL); 2057 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 2058 return (error); 2059 if ((fp->f_flag & FWRITE) == 0) 2060 return (EINVAL); 2061 vp = (struct vnode *)fp->f_data; 2062 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 2063 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2064 if (vp->v_type == VDIR) 2065 error = EISDIR; 2066 else if ((error = vn_writechk(vp)) == 0) { 2067 VATTR_NULL(&vattr); 2068 vattr.va_size = SCARG(uap, length); 2069 error = VOP_SETATTR(vp, &vattr, fp->f_cred, p); 2070 } 2071 VOP_UNLOCK(vp, 0, p); 2072 return (error); 2073} 2074 2075#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 2076/* 2077 * Truncate a file given its path name. 2078 */ 2079#ifndef _SYS_SYSPROTO_H_ 2080struct otruncate_args { 2081 char *path; 2082 long length; 2083}; 2084#endif 2085/* ARGSUSED */ 2086int 2087otruncate(p, uap) 2088 struct proc *p; 2089 register struct otruncate_args /* { 2090 syscallarg(char *) path; 2091 syscallarg(long) length; 2092 } */ *uap; 2093{ 2094 struct truncate_args /* { 2095 syscallarg(char *) path; 2096 syscallarg(int) pad; 2097 syscallarg(off_t) length; 2098 } */ nuap; 2099 2100 SCARG(&nuap, path) = SCARG(uap, path); 2101 SCARG(&nuap, length) = SCARG(uap, length); 2102 return (truncate(p, &nuap)); 2103} 2104 2105/* 2106 * Truncate a file given a file descriptor. 2107 */ 2108#ifndef _SYS_SYSPROTO_H_ 2109struct oftruncate_args { 2110 int fd; 2111 long length; 2112}; 2113#endif 2114/* ARGSUSED */ 2115int 2116oftruncate(p, uap) 2117 struct proc *p; 2118 register struct oftruncate_args /* { 2119 syscallarg(int) fd; 2120 syscallarg(long) length; 2121 } */ *uap; 2122{ 2123 struct ftruncate_args /* { 2124 syscallarg(int) fd; 2125 syscallarg(int) pad; 2126 syscallarg(off_t) length; 2127 } */ nuap; 2128 2129 SCARG(&nuap, fd) = SCARG(uap, fd); 2130 SCARG(&nuap, length) = SCARG(uap, length); 2131 return (ftruncate(p, &nuap)); 2132} 2133#endif /* COMPAT_43 || COMPAT_SUNOS */ 2134 2135/* 2136 * Sync an open file. 2137 */ 2138#ifndef _SYS_SYSPROTO_H_ 2139struct fsync_args { 2140 int fd; 2141}; 2142#endif 2143/* ARGSUSED */ 2144int 2145fsync(p, uap) 2146 struct proc *p; 2147 struct fsync_args /* { 2148 syscallarg(int) fd; 2149 } */ *uap; 2150{ 2151 register struct vnode *vp; 2152 struct file *fp; 2153 int error; 2154 2155 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 2156 return (error); 2157 vp = (struct vnode *)fp->f_data; 2158 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2159 if (vp->v_object) { 2160 vm_object_page_clean(vp->v_object, 0, 0 ,0, FALSE); 2161 } 2162 error = VOP_FSYNC(vp, fp->f_cred, 2163 (vp->v_mount && (vp->v_mount->mnt_flag & MNT_ASYNC)) ? 2164 MNT_NOWAIT : MNT_WAIT, p); 2165 VOP_UNLOCK(vp, 0, p); 2166 return (error); 2167} 2168 2169/* 2170 * Rename files. Source and destination must either both be directories, 2171 * or both not be directories. If target is a directory, it must be empty. 2172 */ 2173#ifndef _SYS_SYSPROTO_H_ 2174struct rename_args { 2175 char *from; 2176 char *to; 2177}; 2178#endif 2179/* ARGSUSED */ 2180int 2181rename(p, uap) 2182 struct proc *p; 2183 register struct rename_args /* { 2184 syscallarg(char *) from; 2185 syscallarg(char *) to; 2186 } */ *uap; 2187{ 2188 register struct vnode *tvp, *fvp, *tdvp; 2189 struct nameidata fromnd, tond; 2190 int error; 2191 2192 NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE, 2193 SCARG(uap, from), p); 2194 if (error = namei(&fromnd)) 2195 return (error); 2196 fvp = fromnd.ni_vp; 2197 NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART, 2198 UIO_USERSPACE, SCARG(uap, to), p); 2199 if (fromnd.ni_vp->v_type == VDIR) 2200 tond.ni_cnd.cn_flags |= WILLBEDIR; 2201 if (error = namei(&tond)) { 2202 /* Translate error code for rename("dir1", "dir2/."). */ 2203 if (error == EISDIR && fvp->v_type == VDIR) 2204 error = EINVAL; 2205 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 2206 vrele(fromnd.ni_dvp); 2207 vrele(fvp); 2208 goto out1; 2209 } 2210 tdvp = tond.ni_dvp; 2211 tvp = tond.ni_vp; 2212 if (tvp != NULL) { 2213 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 2214 error = ENOTDIR; 2215 goto out; 2216 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 2217 error = EISDIR; 2218 goto out; 2219 } 2220 } 2221 if (fvp == tdvp) 2222 error = EINVAL; 2223 /* 2224 * If source is the same as the destination (that is the 2225 * same inode number with the same name in the same directory), 2226 * then there is nothing to do. 2227 */ 2228 if (fvp == tvp && fromnd.ni_dvp == tdvp && 2229 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen && 2230 !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr, 2231 fromnd.ni_cnd.cn_namelen)) 2232 error = -1; 2233out: 2234 if (!error) { 2235 VOP_LEASE(tdvp, p, p->p_ucred, LEASE_WRITE); 2236 if (fromnd.ni_dvp != tdvp) 2237 VOP_LEASE(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 2238 if (tvp) { 2239 VOP_LEASE(tvp, p, p->p_ucred, LEASE_WRITE); 2240 (void) vnode_pager_uncache(tvp, p); 2241 } 2242 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd, 2243 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd); 2244 } else { 2245 VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd); 2246 if (tdvp == tvp) 2247 vrele(tdvp); 2248 else 2249 vput(tdvp); 2250 if (tvp) 2251 vput(tvp); 2252 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 2253 vrele(fromnd.ni_dvp); 2254 vrele(fvp); 2255 } 2256 vrele(tond.ni_startdir); 2257 ASSERT_VOP_UNLOCKED(fromnd.ni_dvp, "rename"); 2258 ASSERT_VOP_UNLOCKED(fromnd.ni_vp, "rename"); 2259 ASSERT_VOP_UNLOCKED(tond.ni_dvp, "rename"); 2260 ASSERT_VOP_UNLOCKED(tond.ni_vp, "rename"); 2261 zfree(namei_zone, tond.ni_cnd.cn_pnbuf); 2262out1: 2263 if (fromnd.ni_startdir) 2264 vrele(fromnd.ni_startdir); 2265 zfree(namei_zone, fromnd.ni_cnd.cn_pnbuf); 2266 if (error == -1) 2267 return (0); 2268 return (error); 2269} 2270 2271/* 2272 * Make a directory file. 2273 */ 2274#ifndef _SYS_SYSPROTO_H_ 2275struct mkdir_args { 2276 char *path; 2277 int mode; 2278}; 2279#endif 2280/* ARGSUSED */ 2281int 2282mkdir(p, uap) 2283 struct proc *p; 2284 register struct mkdir_args /* { 2285 syscallarg(char *) path; 2286 syscallarg(int) mode; 2287 } */ *uap; 2288{ 2289 register struct vnode *vp; 2290 struct vattr vattr; 2291 int error; 2292 struct nameidata nd; 2293 2294 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); 2295 nd.ni_cnd.cn_flags |= WILLBEDIR; 2296 if (error = namei(&nd)) 2297 return (error); 2298 vp = nd.ni_vp; 2299 if (vp != NULL) { 2300 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 2301 if (nd.ni_dvp == vp) 2302 vrele(nd.ni_dvp); 2303 else 2304 vput(nd.ni_dvp); 2305 vrele(vp); 2306 return (EEXIST); 2307 } 2308 VATTR_NULL(&vattr); 2309 vattr.va_type = VDIR; 2310 vattr.va_mode = (SCARG(uap, mode) & ACCESSPERMS) &~ p->p_fd->fd_cmask; 2311 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 2312 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 2313 if (!error) 2314 vput(nd.ni_vp); 2315 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mkdir"); 2316 ASSERT_VOP_UNLOCKED(nd.ni_vp, "mkdir"); 2317 return (error); 2318} 2319 2320/* 2321 * Remove a directory file. 2322 */ 2323#ifndef _SYS_SYSPROTO_H_ 2324struct rmdir_args { 2325 char *path; 2326}; 2327#endif 2328/* ARGSUSED */ 2329int 2330rmdir(p, uap) 2331 struct proc *p; 2332 struct rmdir_args /* { 2333 syscallarg(char *) path; 2334 } */ *uap; 2335{ 2336 register struct vnode *vp; 2337 int error; 2338 struct nameidata nd; 2339 2340 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, 2341 SCARG(uap, path), p); 2342 if (error = namei(&nd)) 2343 return (error); 2344 vp = nd.ni_vp; 2345 if (vp->v_type != VDIR) { 2346 error = ENOTDIR; 2347 goto out; 2348 } 2349 /* 2350 * No rmdir "." please. 2351 */ 2352 if (nd.ni_dvp == vp) { 2353 error = EINVAL; 2354 goto out; 2355 } 2356 /* 2357 * The root of a mounted filesystem cannot be deleted. 2358 */ 2359 if (vp->v_flag & VROOT) 2360 error = EBUSY; 2361out: 2362 if (!error) { 2363 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 2364 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 2365 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 2366 } else { 2367 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 2368 if (nd.ni_dvp == vp) 2369 vrele(nd.ni_dvp); 2370 else 2371 vput(nd.ni_dvp); 2372 vput(vp); 2373 } 2374 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "rmdir"); 2375 ASSERT_VOP_UNLOCKED(nd.ni_vp, "rmdir"); 2376 return (error); 2377} 2378 2379#ifdef COMPAT_43 2380/* 2381 * Read a block of directory entries in a file system independent format. 2382 */ 2383#ifndef _SYS_SYSPROTO_H_ 2384struct ogetdirentries_args { 2385 int fd; 2386 char *buf; 2387 u_int count; 2388 long *basep; 2389}; 2390#endif 2391int 2392ogetdirentries(p, uap) 2393 struct proc *p; 2394 register struct ogetdirentries_args /* { 2395 syscallarg(int) fd; 2396 syscallarg(char *) buf; 2397 syscallarg(u_int) count; 2398 syscallarg(long *) basep; 2399 } */ *uap; 2400{ 2401 register struct vnode *vp; 2402 struct file *fp; 2403 struct uio auio, kuio; 2404 struct iovec aiov, kiov; 2405 struct dirent *dp, *edp; 2406 caddr_t dirbuf; 2407 int error, eofflag, readcnt; 2408 long loff; 2409 2410 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 2411 return (error); 2412 if ((fp->f_flag & FREAD) == 0) 2413 return (EBADF); 2414 vp = (struct vnode *)fp->f_data; 2415unionread: 2416 if (vp->v_type != VDIR) 2417 return (EINVAL); 2418 aiov.iov_base = SCARG(uap, buf); 2419 aiov.iov_len = SCARG(uap, count); 2420 auio.uio_iov = &aiov; 2421 auio.uio_iovcnt = 1; 2422 auio.uio_rw = UIO_READ; 2423 auio.uio_segflg = UIO_USERSPACE; 2424 auio.uio_procp = p; 2425 auio.uio_resid = SCARG(uap, count); 2426 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2427 loff = auio.uio_offset = fp->f_offset; 2428# if (BYTE_ORDER != LITTLE_ENDIAN) 2429 if (vp->v_mount->mnt_maxsymlinklen <= 0) { 2430 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, 2431 NULL, NULL); 2432 fp->f_offset = auio.uio_offset; 2433 } else 2434# endif 2435 { 2436 kuio = auio; 2437 kuio.uio_iov = &kiov; 2438 kuio.uio_segflg = UIO_SYSSPACE; 2439 kiov.iov_len = SCARG(uap, count); 2440 MALLOC(dirbuf, caddr_t, SCARG(uap, count), M_TEMP, M_WAITOK); 2441 kiov.iov_base = dirbuf; 2442 error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag, 2443 NULL, NULL); 2444 fp->f_offset = kuio.uio_offset; 2445 if (error == 0) { 2446 readcnt = SCARG(uap, count) - kuio.uio_resid; 2447 edp = (struct dirent *)&dirbuf[readcnt]; 2448 for (dp = (struct dirent *)dirbuf; dp < edp; ) { 2449# if (BYTE_ORDER == LITTLE_ENDIAN) 2450 /* 2451 * The expected low byte of 2452 * dp->d_namlen is our dp->d_type. 2453 * The high MBZ byte of dp->d_namlen 2454 * is our dp->d_namlen. 2455 */ 2456 dp->d_type = dp->d_namlen; 2457 dp->d_namlen = 0; 2458# else 2459 /* 2460 * The dp->d_type is the high byte 2461 * of the expected dp->d_namlen, 2462 * so must be zero'ed. 2463 */ 2464 dp->d_type = 0; 2465# endif 2466 if (dp->d_reclen > 0) { 2467 dp = (struct dirent *) 2468 ((char *)dp + dp->d_reclen); 2469 } else { 2470 error = EIO; 2471 break; 2472 } 2473 } 2474 if (dp >= edp) 2475 error = uiomove(dirbuf, readcnt, &auio); 2476 } 2477 FREE(dirbuf, M_TEMP); 2478 } 2479 VOP_UNLOCK(vp, 0, p); 2480 if (error) 2481 return (error); 2482 2483#ifdef UNION 2484{ 2485 if ((SCARG(uap, count) == auio.uio_resid) && 2486 (vp->v_op == union_vnodeop_p)) { 2487 struct vnode *lvp; 2488 2489 lvp = union_dircache(vp, p); 2490 if (lvp != NULLVP) { 2491 struct vattr va; 2492 2493 /* 2494 * If the directory is opaque, 2495 * then don't show lower entries 2496 */ 2497 error = VOP_GETATTR(vp, &va, fp->f_cred, p); 2498 if (va.va_flags & OPAQUE) { 2499 vput(lvp); 2500 lvp = NULL; 2501 } 2502 } 2503 2504 if (lvp != NULLVP) { 2505 error = VOP_OPEN(lvp, FREAD, fp->f_cred, p); 2506 if (error) { 2507 vput(lvp); 2508 return (error); 2509 } 2510 VOP_UNLOCK(lvp, 0, p); 2511 fp->f_data = (caddr_t) lvp; 2512 fp->f_offset = 0; 2513 error = vn_close(vp, FREAD, fp->f_cred, p); 2514 if (error) 2515 return (error); 2516 vp = lvp; 2517 goto unionread; 2518 } 2519 } 2520} 2521#endif /* UNION */ 2522 2523 if ((SCARG(uap, count) == auio.uio_resid) && 2524 (vp->v_flag & VROOT) && 2525 (vp->v_mount->mnt_flag & MNT_UNION)) { 2526 struct vnode *tvp = vp; 2527 vp = vp->v_mount->mnt_vnodecovered; 2528 VREF(vp); 2529 fp->f_data = (caddr_t) vp; 2530 fp->f_offset = 0; 2531 vrele(tvp); 2532 goto unionread; 2533 } 2534 error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep), 2535 sizeof(long)); 2536 p->p_retval[0] = SCARG(uap, count) - auio.uio_resid; 2537 return (error); 2538} 2539#endif /* COMPAT_43 */ 2540 2541/* 2542 * Read a block of directory entries in a file system independent format. 2543 */ 2544#ifndef _SYS_SYSPROTO_H_ 2545struct getdirentries_args { 2546 int fd; 2547 char *buf; 2548 u_int count; 2549 long *basep; 2550}; 2551#endif 2552int 2553getdirentries(p, uap) 2554 struct proc *p; 2555 register struct getdirentries_args /* { 2556 syscallarg(int) fd; 2557 syscallarg(char *) buf; 2558 syscallarg(u_int) count; 2559 syscallarg(long *) basep; 2560 } */ *uap; 2561{ 2562 register struct vnode *vp; 2563 struct file *fp; 2564 struct uio auio; 2565 struct iovec aiov; 2566 long loff; 2567 int error, eofflag; 2568 2569 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 2570 return (error); 2571 if ((fp->f_flag & FREAD) == 0) 2572 return (EBADF); 2573 vp = (struct vnode *)fp->f_data; 2574unionread: 2575 if (vp->v_type != VDIR) 2576 return (EINVAL); 2577 aiov.iov_base = SCARG(uap, buf); 2578 aiov.iov_len = SCARG(uap, count); 2579 auio.uio_iov = &aiov; 2580 auio.uio_iovcnt = 1; 2581 auio.uio_rw = UIO_READ; 2582 auio.uio_segflg = UIO_USERSPACE; 2583 auio.uio_procp = p; 2584 auio.uio_resid = SCARG(uap, count); 2585 /* vn_lock(vp, LK_SHARED | LK_RETRY, p); */ 2586 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2587 loff = auio.uio_offset = fp->f_offset; 2588 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL, NULL); 2589 fp->f_offset = auio.uio_offset; 2590 VOP_UNLOCK(vp, 0, p); 2591 if (error) 2592 return (error); 2593 2594#ifdef UNION 2595{ 2596 if ((SCARG(uap, count) == auio.uio_resid) && 2597 (vp->v_op == union_vnodeop_p)) { 2598 struct vnode *lvp; 2599 2600 lvp = union_dircache(vp, p); 2601 if (lvp != NULLVP) { 2602 struct vattr va; 2603 2604 /* 2605 * If the directory is opaque, 2606 * then don't show lower entries 2607 */ 2608 error = VOP_GETATTR(vp, &va, fp->f_cred, p); 2609 if (va.va_flags & OPAQUE) { 2610 vput(lvp); 2611 lvp = NULL; 2612 } 2613 } 2614 2615 if (lvp != NULLVP) { 2616 error = VOP_OPEN(lvp, FREAD, fp->f_cred, p); 2617 if (error) { 2618 vput(lvp); 2619 return (error); 2620 } 2621 VOP_UNLOCK(lvp, 0, p); 2622 fp->f_data = (caddr_t) lvp; 2623 fp->f_offset = 0; 2624 error = vn_close(vp, FREAD, fp->f_cred, p); 2625 if (error) 2626 return (error); 2627 vp = lvp; 2628 goto unionread; 2629 } 2630 } 2631} 2632#endif /* UNION */ 2633 2634 if ((SCARG(uap, count) == auio.uio_resid) && 2635 (vp->v_flag & VROOT) && 2636 (vp->v_mount->mnt_flag & MNT_UNION)) { 2637 struct vnode *tvp = vp; 2638 vp = vp->v_mount->mnt_vnodecovered; 2639 VREF(vp); 2640 fp->f_data = (caddr_t) vp; 2641 fp->f_offset = 0; 2642 vrele(tvp); 2643 goto unionread; 2644 } 2645 error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep), 2646 sizeof(long)); 2647 p->p_retval[0] = SCARG(uap, count) - auio.uio_resid; 2648 return (error); 2649} 2650 2651/* 2652 * Set the mode mask for creation of filesystem nodes. 2653 */ 2654#ifndef _SYS_SYSPROTO_H_ 2655struct umask_args { 2656 int newmask; 2657}; 2658#endif 2659int 2660umask(p, uap) 2661 struct proc *p; 2662 struct umask_args /* { 2663 syscallarg(int) newmask; 2664 } */ *uap; 2665{ 2666 register struct filedesc *fdp; 2667 2668 fdp = p->p_fd; 2669 p->p_retval[0] = fdp->fd_cmask; 2670 fdp->fd_cmask = SCARG(uap, newmask) & ALLPERMS; 2671 return (0); 2672} 2673 2674/* 2675 * Void all references to file by ripping underlying filesystem 2676 * away from vnode. 2677 */ 2678#ifndef _SYS_SYSPROTO_H_ 2679struct revoke_args { 2680 char *path; 2681}; 2682#endif 2683/* ARGSUSED */ 2684int 2685revoke(p, uap) 2686 struct proc *p; 2687 register struct revoke_args /* { 2688 syscallarg(char *) path; 2689 } */ *uap; 2690{ 2691 register struct vnode *vp; 2692 struct vattr vattr; 2693 int error; 2694 struct nameidata nd; 2695 2696 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 2697 if (error = namei(&nd)) 2698 return (error); 2699 vp = nd.ni_vp; 2700 if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) 2701 goto out; 2702 if (p->p_ucred->cr_uid != vattr.va_uid && 2703 (error = suser(p->p_ucred, &p->p_acflag))) 2704 goto out; 2705 if (vp->v_usecount > 1 || (vp->v_flag & VALIASED)) 2706 VOP_REVOKE(vp, REVOKEALL); 2707out: 2708 vrele(vp); 2709 return (error); 2710} 2711 2712/* 2713 * Convert a user file descriptor to a kernel file entry. 2714 */ 2715int 2716getvnode(fdp, fd, fpp) 2717 struct filedesc *fdp; 2718 int fd; 2719 struct file **fpp; 2720{ 2721 struct file *fp; 2722 2723 if ((u_int)fd >= fdp->fd_nfiles || 2724 (fp = fdp->fd_ofiles[fd]) == NULL) 2725 return (EBADF); 2726 if (fp->f_type != DTYPE_VNODE && fp->f_type != DTYPE_FIFO) 2727 return (EINVAL); 2728 *fpp = fp; 2729 return (0); 2730} 2731#ifndef _SYS_SYSPROTO_H_ 2732struct __getcwd_args { 2733 u_char *buf; 2734 u_int buflen; 2735}; 2736#endif 2737#define STATNODE(mode, name, var) \ 2738 SYSCTL_INT(_vfs_cache, OID_AUTO, name, mode, var, 0, ""); 2739 2740static int disablecwd; 2741SYSCTL_INT(_debug, OID_AUTO, disablecwd, CTLFLAG_RW, &disablecwd, 0, ""); 2742 2743static u_long numcwdcalls; STATNODE(CTLFLAG_RD, numcwdcalls, &numcwdcalls); 2744static u_long numcwdfail1; STATNODE(CTLFLAG_RD, numcwdfail1, &numcwdfail1); 2745static u_long numcwdfail2; STATNODE(CTLFLAG_RD, numcwdfail2, &numcwdfail2); 2746static u_long numcwdfail3; STATNODE(CTLFLAG_RD, numcwdfail3, &numcwdfail3); 2747static u_long numcwdfail4; STATNODE(CTLFLAG_RD, numcwdfail4, &numcwdfail4); 2748static u_long numcwdfound; STATNODE(CTLFLAG_RD, numcwdfound, &numcwdfound); 2749int 2750__getcwd(p, uap) 2751 struct proc *p; 2752 struct __getcwd_args *uap; 2753{ 2754 struct filedesc *fdp; 2755 struct vnode *vp; 2756 struct namecache *ncp; 2757 char *buf, *bp; 2758 int i, j, error; 2759 2760 if (disablecwd) 2761 return (ENODEV); 2762 fdp = p->p_fd; 2763 j = 0; 2764 error = 0; 2765 if (uap->buflen < 2) 2766 return (EINVAL); 2767 if (uap->buflen > MAXPATHLEN) 2768 uap->buflen = MAXPATHLEN; 2769 buf = bp = malloc(uap->buflen, M_TEMP, M_WAITOK); 2770 bp += uap->buflen - 1; 2771 *bp = '\0'; 2772 numcwdcalls++; 2773 for (vp = fdp->fd_cdir; vp != fdp->fd_rdir && vp != rootvnode;) { 2774 if (vp->v_flag & VROOT) { 2775 vp = vp->v_mount->mnt_vnodecovered; 2776 continue; 2777 } 2778 if (vp->v_dd->v_id != vp->v_ddid) { 2779 numcwdfail1++; 2780 free(buf, M_TEMP); 2781 return (ENOTDIR); 2782 } 2783 ncp = TAILQ_FIRST(&vp->v_cache_dst); 2784 if (!ncp) { 2785 numcwdfail2++; 2786 free(buf, M_TEMP); 2787 return (ENOENT); 2788 } 2789 if (ncp->nc_dvp != vp->v_dd) { 2790 numcwdfail3++; 2791 free(buf, M_TEMP); 2792 return (EBADF); 2793 } 2794 for (i=ncp->nc_nlen - 1; i >= 0; i--) { 2795 if (bp == buf) { 2796 numcwdfail4++; 2797 free(buf, M_TEMP); 2798 return (ENOMEM); 2799 } 2800 *--bp = ncp->nc_name[i]; 2801 } 2802 if (bp == buf) { 2803 numcwdfail4++; 2804 free(buf, M_TEMP); 2805 return (ENOMEM); 2806 } 2807 *--bp = '/'; 2808 j++; 2809 vp = vp->v_dd; 2810 } 2811 if (!j) { 2812 if (bp == buf) { 2813 numcwdfail4++; 2814 free(buf, M_TEMP); 2815 return (ENOMEM); 2816 } 2817 *--bp = '/'; 2818 } 2819 numcwdfound++; 2820 error = copyout(bp, uap->buf, strlen(bp) + 1); 2821 free(buf, M_TEMP); 2822 return (error); 2823}
|