285 if (mp->mnt_vnodelist.lh_first != NULL) 286 panic("unmount: dangling vnode"); 287 free((caddr_t)mp, M_MOUNT); 288 } 289 return (error); 290} 291 292/* 293 * Sync each mounted filesystem. 294 */ 295#ifdef DIAGNOSTIC 296int syncprt = 0; 297struct ctldebug debug0 = { "syncprt", &syncprt }; 298#endif 299 300struct sync_args { 301 int dummy; 302}; 303/* ARGSUSED */ 304int 305sync(p, uap, retval) 306 struct proc *p; 307 struct sync_args *uap; 308 int *retval; 309{ 310 register struct mount *mp, *nmp; 311 int asyncflag; 312 313 for (mp = mountlist.tqh_first; mp != NULL; mp = nmp) { 314 nmp = mp->mnt_list.tqe_next; 315 /* 316 * The lock check below is to avoid races with mount 317 * and unmount. 318 */ 319 if ((mp->mnt_flag & (MNT_MLOCK|MNT_RDONLY|MNT_MPBUSY)) == 0 && 320 !vfs_busy(mp)) { 321 asyncflag = mp->mnt_flag & MNT_ASYNC; 322 mp->mnt_flag &= ~MNT_ASYNC; 323 VFS_SYNC(mp, MNT_NOWAIT, p->p_ucred, p); 324 if (asyncflag) 325 mp->mnt_flag |= MNT_ASYNC; 326 vfs_unbusy(mp); 327 } 328 } 329#ifdef DIAGNOSTIC 330 if (syncprt) 331 vfs_bufstats(); 332#endif /* DIAGNOSTIC */ 333 return (0); 334} 335 336/* 337 * Change filesystem quotas. 338 */ 339struct quotactl_args { 340 char *path; 341 int cmd; 342 int uid; 343 caddr_t arg; 344}; 345/* ARGSUSED */ 346int 347quotactl(p, uap, retval) 348 struct proc *p; 349 register struct quotactl_args *uap; 350 int *retval; 351{ 352 register struct mount *mp; 353 int error; 354 struct nameidata nd; 355 356 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 357 if (error = namei(&nd)) 358 return (error); 359 mp = nd.ni_vp->v_mount; 360 vrele(nd.ni_vp); 361 return (VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg, p)); 362} 363 364/* 365 * Get filesystem statistics. 366 */ 367struct statfs_args { 368 char *path; 369 struct statfs *buf; 370}; 371/* ARGSUSED */ 372int 373statfs(p, uap, retval) 374 struct proc *p; 375 register struct statfs_args *uap; 376 int *retval; 377{ 378 register struct mount *mp; 379 register struct statfs *sp; 380 int error; 381 struct nameidata nd; 382 383 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 384 if (error = namei(&nd)) 385 return (error); 386 mp = nd.ni_vp->v_mount; 387 sp = &mp->mnt_stat; 388 vrele(nd.ni_vp); 389 if (error = VFS_STATFS(mp, sp, p)) 390 return (error); 391 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 392 return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp))); 393} 394 395/* 396 * Get filesystem statistics. 397 */ 398struct fstatfs_args { 399 int fd; 400 struct statfs *buf; 401}; 402/* ARGSUSED */ 403int 404fstatfs(p, uap, retval) 405 struct proc *p; 406 register struct fstatfs_args *uap; 407 int *retval; 408{ 409 struct file *fp; 410 struct mount *mp; 411 register struct statfs *sp; 412 int error; 413 414 if (error = getvnode(p->p_fd, uap->fd, &fp)) 415 return (error); 416 mp = ((struct vnode *)fp->f_data)->v_mount; 417 sp = &mp->mnt_stat; 418 if (error = VFS_STATFS(mp, sp, p)) 419 return (error); 420 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 421 return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp))); 422} 423 424/* 425 * Get statistics on all filesystems. 426 */ 427struct getfsstat_args { 428 struct statfs *buf; 429 long bufsize; 430 int flags; 431}; 432int 433getfsstat(p, uap, retval) 434 struct proc *p; 435 register struct getfsstat_args *uap; 436 int *retval; 437{ 438 register struct mount *mp, *nmp; 439 register struct statfs *sp; 440 caddr_t sfsp; 441 long count, maxcount, error; 442 443 maxcount = uap->bufsize / sizeof(struct statfs); 444 sfsp = (caddr_t)uap->buf; 445 for (count = 0, mp = mountlist.tqh_first; mp != NULL; mp = nmp) { 446 nmp = mp->mnt_list.tqe_next; 447 if (sfsp && count < maxcount && 448 ((mp->mnt_flag & MNT_MLOCK) == 0)) { 449 sp = &mp->mnt_stat; 450 /* 451 * If MNT_NOWAIT is specified, do not refresh the 452 * fsstat cache. MNT_WAIT overrides MNT_NOWAIT. 453 */ 454 if (((uap->flags & MNT_NOWAIT) == 0 || 455 (uap->flags & MNT_WAIT)) && 456 (error = VFS_STATFS(mp, sp, p))) 457 continue; 458 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 459 if (error = copyout((caddr_t)sp, sfsp, sizeof(*sp))) 460 return (error); 461 sfsp += sizeof(*sp); 462 } 463 count++; 464 } 465 if (sfsp && count > maxcount) 466 *retval = maxcount; 467 else 468 *retval = count; 469 return (0); 470} 471 472/* 473 * Change current working directory to a given file descriptor. 474 */ 475struct fchdir_args { 476 int fd; 477}; 478/* ARGSUSED */ 479int 480fchdir(p, uap, retval) 481 struct proc *p; 482 struct fchdir_args *uap; 483 int *retval; 484{ 485 register struct filedesc *fdp = p->p_fd; 486 register struct vnode *vp; 487 struct file *fp; 488 int error; 489 490 if (error = getvnode(fdp, uap->fd, &fp)) 491 return (error); 492 vp = (struct vnode *)fp->f_data; 493 VOP_LOCK(vp); 494 if (vp->v_type != VDIR) 495 error = ENOTDIR; 496 else 497 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); 498 VOP_UNLOCK(vp); 499 if (error) 500 return (error); 501 VREF(vp); 502 vrele(fdp->fd_cdir); 503 fdp->fd_cdir = vp; 504 return (0); 505} 506 507/* 508 * Change current working directory (``.''). 509 */ 510struct chdir_args { 511 char *path; 512}; 513/* ARGSUSED */ 514int 515chdir(p, uap, retval) 516 struct proc *p; 517 struct chdir_args *uap; 518 int *retval; 519{ 520 register struct filedesc *fdp = p->p_fd; 521 int error; 522 struct nameidata nd; 523 524 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); 525 if (error = change_dir(&nd, p)) 526 return (error); 527 vrele(fdp->fd_cdir); 528 fdp->fd_cdir = nd.ni_vp; 529 return (0); 530} 531 532/* 533 * Change notion of root (``/'') directory. 534 */ 535struct chroot_args { 536 char *path; 537}; 538/* ARGSUSED */ 539int 540chroot(p, uap, retval) 541 struct proc *p; 542 struct chroot_args *uap; 543 int *retval; 544{ 545 register struct filedesc *fdp = p->p_fd; 546 int error; 547 struct nameidata nd; 548 549 if (error = suser(p->p_ucred, &p->p_acflag)) 550 return (error); 551 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); 552 if (error = change_dir(&nd, p)) 553 return (error); 554 if (fdp->fd_rdir != NULL) 555 vrele(fdp->fd_rdir); 556 fdp->fd_rdir = nd.ni_vp; 557 return (0); 558} 559 560/* 561 * Common routine for chroot and chdir. 562 */ 563static int 564change_dir(ndp, p) 565 register struct nameidata *ndp; 566 struct proc *p; 567{ 568 struct vnode *vp; 569 int error; 570 571 if (error = namei(ndp)) 572 return (error); 573 vp = ndp->ni_vp; 574 if (vp->v_type != VDIR) 575 error = ENOTDIR; 576 else 577 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); 578 VOP_UNLOCK(vp); 579 if (error) 580 vrele(vp); 581 return (error); 582} 583 584/* 585 * Check permissions, allocate an open file structure, 586 * and call the device open routine if any. 587 */ 588struct open_args { 589 char *path; 590 int flags; 591 int mode; 592}; 593int 594open(p, uap, retval) 595 struct proc *p; 596 register struct open_args *uap; 597 int *retval; 598{ 599 register struct filedesc *fdp = p->p_fd; 600 register struct file *fp; 601 register struct vnode *vp; 602 int flags, cmode; 603 struct file *nfp; 604 int type, indx, error; 605 struct flock lf; 606 struct nameidata nd; 607 extern struct fileops vnops; 608 609 if (error = falloc(p, &nfp, &indx)) 610 return (error); 611 fp = nfp; 612 flags = FFLAGS(uap->flags); 613 cmode = ((uap->mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT; 614 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 615 p->p_dupfd = -indx - 1; /* XXX check for fdopen */ 616 if (error = vn_open(&nd, flags, cmode)) { 617 ffree(fp); 618 if ((error == ENODEV || error == ENXIO) && 619 p->p_dupfd >= 0 && /* XXX from fdopen */ 620 (error = 621 dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) { 622 *retval = indx; 623 return (0); 624 } 625 if (error == ERESTART) 626 error = EINTR; 627 fdp->fd_ofiles[indx] = NULL; 628 return (error); 629 } 630 p->p_dupfd = 0; 631 vp = nd.ni_vp; 632 fp->f_flag = flags & FMASK; 633 fp->f_type = DTYPE_VNODE; 634 fp->f_ops = &vnops; 635 fp->f_data = (caddr_t)vp; 636 if (flags & (O_EXLOCK | O_SHLOCK)) { 637 lf.l_whence = SEEK_SET; 638 lf.l_start = 0; 639 lf.l_len = 0; 640 if (flags & O_EXLOCK) 641 lf.l_type = F_WRLCK; 642 else 643 lf.l_type = F_RDLCK; 644 type = F_FLOCK; 645 if ((flags & FNONBLOCK) == 0) 646 type |= F_WAIT; 647 VOP_UNLOCK(vp); 648 if (error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) { 649 (void) vn_close(vp, fp->f_flag, fp->f_cred, p); 650 ffree(fp); 651 fdp->fd_ofiles[indx] = NULL; 652 return (error); 653 } 654 VOP_LOCK(vp); 655 fp->f_flag |= FHASLOCK; 656 } 657 VOP_UNLOCK(vp); 658 *retval = indx; 659 return (0); 660} 661 662#ifdef COMPAT_43 663/* 664 * Create a file. 665 */ 666struct ocreat_args { 667 char *path; 668 int mode; 669}; 670int 671ocreat(p, uap, retval) 672 struct proc *p; 673 register struct ocreat_args *uap; 674 int *retval; 675{ 676 struct open_args openuap; 677 678 openuap.path = uap->path; 679 openuap.mode = uap->mode; 680 openuap.flags = O_WRONLY | O_CREAT | O_TRUNC; 681 return (open(p, &openuap, retval)); 682} 683#endif /* COMPAT_43 */ 684 685/* 686 * Create a special file. 687 */ 688struct mknod_args { 689 char *path; 690 int mode; 691 int dev; 692}; 693/* ARGSUSED */ 694int 695mknod(p, uap, retval) 696 struct proc *p; 697 register struct mknod_args *uap; 698 int *retval; 699{ 700 register struct vnode *vp; 701 struct vattr vattr; 702 int error; 703 struct nameidata nd; 704 705 if (error = suser(p->p_ucred, &p->p_acflag)) 706 return (error); 707 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p); 708 if (error = namei(&nd)) 709 return (error); 710 vp = nd.ni_vp; 711 if (vp != NULL) 712 error = EEXIST; 713 else { 714 VATTR_NULL(&vattr); 715 vattr.va_mode = (uap->mode & ALLPERMS) &~ p->p_fd->fd_cmask; 716 vattr.va_rdev = uap->dev; 717 718 switch (uap->mode & S_IFMT) { 719 case S_IFMT: /* used by badsect to flag bad sectors */ 720 vattr.va_type = VBAD; 721 break; 722 case S_IFCHR: 723 vattr.va_type = VCHR; 724 break; 725 case S_IFBLK: 726 vattr.va_type = VBLK; 727 break; 728 default: 729 error = EINVAL; 730 break; 731 } 732 } 733 if (!error) { 734 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 735 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 736 } else { 737 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 738 if (nd.ni_dvp == vp) 739 vrele(nd.ni_dvp); 740 else 741 vput(nd.ni_dvp); 742 if (vp) 743 vrele(vp); 744 } 745 return (error); 746} 747 748/* 749 * Create named pipe. 750 */ 751struct mkfifo_args { 752 char *path; 753 int mode; 754}; 755/* ARGSUSED */ 756int 757mkfifo(p, uap, retval) 758 struct proc *p; 759 register struct mkfifo_args *uap; 760 int *retval; 761{ 762 struct vattr vattr; 763 int error; 764 struct nameidata nd; 765 766#ifndef FIFO 767 return (EOPNOTSUPP); 768#else 769 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p); 770 if (error = namei(&nd)) 771 return (error); 772 if (nd.ni_vp != NULL) { 773 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 774 if (nd.ni_dvp == nd.ni_vp) 775 vrele(nd.ni_dvp); 776 else 777 vput(nd.ni_dvp); 778 vrele(nd.ni_vp); 779 return (EEXIST); 780 } 781 VATTR_NULL(&vattr); 782 vattr.va_type = VFIFO; 783 vattr.va_mode = (uap->mode & ALLPERMS) &~ p->p_fd->fd_cmask; 784 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 785 return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr)); 786#endif /* FIFO */ 787} 788 789/* 790 * Make a hard file link. 791 */ 792struct link_args { 793 char *path; 794 char *link; 795}; 796/* ARGSUSED */ 797int 798link(p, uap, retval) 799 struct proc *p; 800 register struct link_args *uap; 801 int *retval; 802{ 803 register struct vnode *vp; 804 struct nameidata nd; 805 int error; 806 807 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 808 if (error = namei(&nd)) 809 return (error); 810 vp = nd.ni_vp; 811 if (vp->v_type != VDIR || 812 (error = suser(p->p_ucred, &p->p_acflag)) == 0) { 813 nd.ni_cnd.cn_nameiop = CREATE; 814 nd.ni_cnd.cn_flags = LOCKPARENT; 815 nd.ni_dirp = uap->link; 816 if ((error = namei(&nd)) == 0) { 817 if (nd.ni_vp != NULL) 818 error = EEXIST; 819 if (!error) { 820 LEASE_CHECK(nd.ni_dvp, 821 p, p->p_ucred, LEASE_WRITE); 822 LEASE_CHECK(vp, 823 p, p->p_ucred, LEASE_WRITE); 824 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd); 825 } else { 826 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 827 if (nd.ni_dvp == nd.ni_vp) 828 vrele(nd.ni_dvp); 829 else 830 vput(nd.ni_dvp); 831 if (nd.ni_vp) 832 vrele(nd.ni_vp); 833 } 834 } 835 } 836 vrele(vp); 837 return (error); 838} 839 840/* 841 * Make a symbolic link. 842 */ 843struct symlink_args { 844 char *path; 845 char *link; 846}; 847/* ARGSUSED */ 848int 849symlink(p, uap, retval) 850 struct proc *p; 851 register struct symlink_args *uap; 852 int *retval; 853{ 854 struct vattr vattr; 855 char *path; 856 int error; 857 struct nameidata nd; 858 859 MALLOC(path, char *, MAXPATHLEN, M_NAMEI, M_WAITOK); 860 if (error = copyinstr(uap->path, path, MAXPATHLEN, NULL)) 861 goto out; 862 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->link, p); 863 if (error = namei(&nd)) 864 goto out; 865 if (nd.ni_vp) { 866 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 867 if (nd.ni_dvp == nd.ni_vp) 868 vrele(nd.ni_dvp); 869 else 870 vput(nd.ni_dvp); 871 vrele(nd.ni_vp); 872 error = EEXIST; 873 goto out; 874 } 875 VATTR_NULL(&vattr); 876 vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask; 877 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 878 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path); 879out: 880 FREE(path, M_NAMEI); 881 return (error); 882} 883 884/* 885 * Delete a name from the filesystem. 886 */ 887struct unlink_args { 888 char *path; 889}; 890/* ARGSUSED */ 891int 892unlink(p, uap, retval) 893 struct proc *p; 894 struct unlink_args *uap; 895 int *retval; 896{ 897 register struct vnode *vp; 898 int error; 899 struct nameidata nd; 900 901 NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, uap->path, p); 902 if (error = namei(&nd)) 903 return (error); 904 vp = nd.ni_vp; 905 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 906 VOP_LOCK(vp); 907 908 if (vp->v_type != VDIR || 909 (error = suser(p->p_ucred, &p->p_acflag)) == 0) { 910 /* 911 * The root of a mounted filesystem cannot be deleted. 912 */ 913 if (vp->v_flag & VROOT) 914 error = EBUSY; 915 else 916 (void)vnode_pager_uncache(vp); 917 } 918 919 if (!error) { 920 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 921 error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 922 } else { 923 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 924 if (nd.ni_dvp == vp) 925 vrele(nd.ni_dvp); 926 else 927 vput(nd.ni_dvp); 928 vput(vp); 929 } 930 return (error); 931} 932 933/* 934 * Reposition read/write file offset. 935 */ 936struct lseek_args { 937 int fd; 938 int pad; 939 off_t offset; 940 int whence; 941}; 942int 943lseek(p, uap, retval) 944 struct proc *p; 945 register struct lseek_args *uap; 946 int *retval; 947{ 948 struct ucred *cred = p->p_ucred; 949 register struct filedesc *fdp = p->p_fd; 950 register struct file *fp; 951 struct vattr vattr; 952 int error; 953 954 if ((u_int)uap->fd >= fdp->fd_nfiles || 955 (fp = fdp->fd_ofiles[uap->fd]) == NULL) 956 return (EBADF); 957 if (fp->f_type != DTYPE_VNODE) 958 return (ESPIPE); 959 switch (uap->whence) { 960 case L_INCR: 961 fp->f_offset += uap->offset; 962 break; 963 case L_XTND: 964 if (error = 965 VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p)) 966 return (error); 967 fp->f_offset = uap->offset + vattr.va_size; 968 break; 969 case L_SET: 970 fp->f_offset = uap->offset; 971 break; 972 default: 973 return (EINVAL); 974 } 975 *(off_t *)retval = fp->f_offset; 976 return (0); 977} 978 979#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 980/* 981 * Reposition read/write file offset. 982 */ 983struct olseek_args { 984 int fd; 985 long offset; 986 int whence; 987}; 988int 989olseek(p, uap, retval) 990 struct proc *p; 991 register struct olseek_args *uap; 992 int *retval; 993{ 994 struct lseek_args nuap; 995 off_t qret; 996 int error; 997 998 nuap.fd = uap->fd; 999 nuap.offset = uap->offset; 1000 nuap.whence = uap->whence; 1001 error = lseek(p, &nuap, &qret); 1002 *(long *)retval = qret; 1003 return (error); 1004} 1005#endif /* COMPAT_43 */ 1006 1007/* 1008 * Check access permissions. 1009 */ 1010struct access_args { 1011 char *path; 1012 int flags; 1013}; 1014int 1015access(p, uap, retval) 1016 struct proc *p; 1017 register struct access_args *uap; 1018 int *retval; 1019{ 1020 register struct ucred *cred = p->p_ucred; 1021 register struct vnode *vp; 1022 int error, flags, t_gid, t_uid; 1023 struct nameidata nd; 1024 1025 t_uid = cred->cr_uid; 1026 t_gid = cred->cr_groups[0]; 1027 cred->cr_uid = p->p_cred->p_ruid; 1028 cred->cr_groups[0] = p->p_cred->p_rgid; 1029 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); 1030 if (error = namei(&nd)) 1031 goto out1; 1032 vp = nd.ni_vp; 1033 1034 /* Flags == 0 means only check for existence. */ 1035 if (uap->flags) { 1036 flags = 0; 1037 if (uap->flags & R_OK) 1038 flags |= VREAD; 1039 if (uap->flags & W_OK) 1040 flags |= VWRITE; 1041 if (uap->flags & X_OK) 1042 flags |= VEXEC; 1043 if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0) 1044 error = VOP_ACCESS(vp, flags, cred, p); 1045 } 1046 vput(vp); 1047out1: 1048 cred->cr_uid = t_uid; 1049 cred->cr_groups[0] = t_gid; 1050 return (error); 1051} 1052 1053#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1054/* 1055 * Get file status; this version follows links. 1056 */ 1057struct ostat_args { 1058 char *path; 1059 struct ostat *ub; 1060}; 1061/* ARGSUSED */ 1062int 1063ostat(p, uap, retval) 1064 struct proc *p; 1065 register struct ostat_args *uap; 1066 int *retval; 1067{ 1068 struct stat sb; 1069 struct ostat osb; 1070 int error; 1071 struct nameidata nd; 1072 1073 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); 1074 if (error = namei(&nd)) 1075 return (error); 1076 error = vn_stat(nd.ni_vp, &sb, p); 1077 vput(nd.ni_vp); 1078 if (error) 1079 return (error); 1080 cvtstat(&sb, &osb); 1081 error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb)); 1082 return (error); 1083} 1084 1085/* 1086 * Get file status; this version does not follow links. 1087 */ 1088struct olstat_args { 1089 char *path; 1090 struct ostat *ub; 1091}; 1092/* ARGSUSED */ 1093int 1094olstat(p, uap, retval) 1095 struct proc *p; 1096 register struct olstat_args *uap; 1097 int *retval; 1098{ 1099 struct vnode *vp, *dvp; 1100 struct stat sb, sb1; 1101 struct ostat osb; 1102 int error; 1103 struct nameidata nd; 1104 1105 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE, 1106 uap->path, p); 1107 if (error = namei(&nd)) 1108 return (error); 1109 /* 1110 * For symbolic links, always return the attributes of its 1111 * containing directory, except for mode, size, and links. 1112 */ 1113 vp = nd.ni_vp; 1114 dvp = nd.ni_dvp; 1115 if (vp->v_type != VLNK) { 1116 if (dvp == vp) 1117 vrele(dvp); 1118 else 1119 vput(dvp); 1120 error = vn_stat(vp, &sb, p); 1121 vput(vp); 1122 if (error) 1123 return (error); 1124 } else { 1125 error = vn_stat(dvp, &sb, p); 1126 vput(dvp); 1127 if (error) { 1128 vput(vp); 1129 return (error); 1130 } 1131 error = vn_stat(vp, &sb1, p); 1132 vput(vp); 1133 if (error) 1134 return (error); 1135 sb.st_mode &= ~S_IFDIR; 1136 sb.st_mode |= S_IFLNK; 1137 sb.st_nlink = sb1.st_nlink; 1138 sb.st_size = sb1.st_size; 1139 sb.st_blocks = sb1.st_blocks; 1140 } 1141 cvtstat(&sb, &osb); 1142 error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb)); 1143 return (error); 1144} 1145 1146/* 1147 * Convert from an old to a new stat structure. 1148 */ 1149void 1150cvtstat(st, ost) 1151 struct stat *st; 1152 struct ostat *ost; 1153{ 1154 1155 ost->st_dev = st->st_dev; 1156 ost->st_ino = st->st_ino; 1157 ost->st_mode = st->st_mode; 1158 ost->st_nlink = st->st_nlink; 1159 ost->st_uid = st->st_uid; 1160 ost->st_gid = st->st_gid; 1161 ost->st_rdev = st->st_rdev; 1162 if (st->st_size < (quad_t)1 << 32) 1163 ost->st_size = st->st_size; 1164 else 1165 ost->st_size = -2; 1166 ost->st_atime = st->st_atime; 1167 ost->st_mtime = st->st_mtime; 1168 ost->st_ctime = st->st_ctime; 1169 ost->st_blksize = st->st_blksize; 1170 ost->st_blocks = st->st_blocks; 1171 ost->st_flags = st->st_flags; 1172 ost->st_gen = st->st_gen; 1173} 1174#endif /* COMPAT_43 || COMPAT_SUNOS */ 1175 1176/* 1177 * Get file status; this version follows links. 1178 */ 1179struct stat_args { 1180 char *path; 1181 struct stat *ub; 1182}; 1183/* ARGSUSED */ 1184int 1185stat(p, uap, retval) 1186 struct proc *p; 1187 register struct stat_args *uap; 1188 int *retval; 1189{ 1190 struct stat sb; 1191 int error; 1192 struct nameidata nd; 1193 1194 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); 1195 if (error = namei(&nd)) 1196 return (error); 1197 error = vn_stat(nd.ni_vp, &sb, p); 1198 vput(nd.ni_vp); 1199 if (error) 1200 return (error); 1201 error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb)); 1202 return (error); 1203} 1204 1205/* 1206 * Get file status; this version does not follow links. 1207 */ 1208struct lstat_args { 1209 char *path; 1210 struct stat *ub; 1211}; 1212/* ARGSUSED */ 1213int 1214lstat(p, uap, retval) 1215 struct proc *p; 1216 register struct lstat_args *uap; 1217 int *retval; 1218{ 1219 int error; 1220 struct vnode *vp, *dvp; 1221 struct stat sb, sb1; 1222 struct nameidata nd; 1223 1224 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE, 1225 uap->path, p); 1226 if (error = namei(&nd)) 1227 return (error); 1228 /* 1229 * For symbolic links, always return the attributes of its 1230 * containing directory, except for mode, size, and links. 1231 */ 1232 vp = nd.ni_vp; 1233 dvp = nd.ni_dvp; 1234 if (vp->v_type != VLNK) { 1235 if (dvp == vp) 1236 vrele(dvp); 1237 else 1238 vput(dvp); 1239 error = vn_stat(vp, &sb, p); 1240 vput(vp); 1241 if (error) 1242 return (error); 1243 } else { 1244 error = vn_stat(dvp, &sb, p); 1245 vput(dvp); 1246 if (error) { 1247 vput(vp); 1248 return (error); 1249 } 1250 error = vn_stat(vp, &sb1, p); 1251 vput(vp); 1252 if (error) 1253 return (error); 1254 sb.st_mode &= ~S_IFDIR; 1255 sb.st_mode |= S_IFLNK; 1256 sb.st_nlink = sb1.st_nlink; 1257 sb.st_size = sb1.st_size; 1258 sb.st_blocks = sb1.st_blocks; 1259 } 1260 error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb)); 1261 return (error); 1262} 1263 1264/* 1265 * Get configurable pathname variables. 1266 */ 1267struct pathconf_args { 1268 char *path; 1269 int name; 1270}; 1271/* ARGSUSED */ 1272int 1273pathconf(p, uap, retval) 1274 struct proc *p; 1275 register struct pathconf_args *uap; 1276 int *retval; 1277{ 1278 int error; 1279 struct nameidata nd; 1280 1281 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); 1282 if (error = namei(&nd)) 1283 return (error); 1284 error = VOP_PATHCONF(nd.ni_vp, uap->name, retval); 1285 vput(nd.ni_vp); 1286 return (error); 1287} 1288 1289/* 1290 * Return target name of a symbolic link. 1291 */ 1292struct readlink_args { 1293 char *path; 1294 char *buf; 1295 int count; 1296}; 1297/* ARGSUSED */ 1298int 1299readlink(p, uap, retval) 1300 struct proc *p; 1301 register struct readlink_args *uap; 1302 int *retval; 1303{ 1304 register struct vnode *vp; 1305 struct iovec aiov; 1306 struct uio auio; 1307 int error; 1308 struct nameidata nd; 1309 1310 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); 1311 if (error = namei(&nd)) 1312 return (error); 1313 vp = nd.ni_vp; 1314 if (vp->v_type != VLNK) 1315 error = EINVAL; 1316 else { 1317 aiov.iov_base = uap->buf; 1318 aiov.iov_len = uap->count; 1319 auio.uio_iov = &aiov; 1320 auio.uio_iovcnt = 1; 1321 auio.uio_offset = 0; 1322 auio.uio_rw = UIO_READ; 1323 auio.uio_segflg = UIO_USERSPACE; 1324 auio.uio_procp = p; 1325 auio.uio_resid = uap->count; 1326 error = VOP_READLINK(vp, &auio, p->p_ucred); 1327 } 1328 vput(vp); 1329 *retval = uap->count - auio.uio_resid; 1330 return (error); 1331} 1332 1333/* 1334 * Change flags of a file given a path name. 1335 */ 1336struct chflags_args { 1337 char *path; 1338 int flags; 1339}; 1340/* ARGSUSED */ 1341int 1342chflags(p, uap, retval) 1343 struct proc *p; 1344 register struct chflags_args *uap; 1345 int *retval; 1346{ 1347 register struct vnode *vp; 1348 struct vattr vattr; 1349 int error; 1350 struct nameidata nd; 1351 1352 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 1353 if (error = namei(&nd)) 1354 return (error); 1355 vp = nd.ni_vp; 1356 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1357 VOP_LOCK(vp); 1358 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1359 error = EROFS; 1360 else { 1361 VATTR_NULL(&vattr); 1362 vattr.va_flags = uap->flags; 1363 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1364 } 1365 vput(vp); 1366 return (error); 1367} 1368 1369/* 1370 * Change flags of a file given a file descriptor. 1371 */ 1372struct fchflags_args { 1373 int fd; 1374 int flags; 1375}; 1376/* ARGSUSED */ 1377int 1378fchflags(p, uap, retval) 1379 struct proc *p; 1380 register struct fchflags_args *uap; 1381 int *retval; 1382{ 1383 struct vattr vattr; 1384 struct vnode *vp; 1385 struct file *fp; 1386 int error; 1387 1388 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1389 return (error); 1390 vp = (struct vnode *)fp->f_data; 1391 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1392 VOP_LOCK(vp); 1393 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1394 error = EROFS; 1395 else { 1396 VATTR_NULL(&vattr); 1397 vattr.va_flags = uap->flags; 1398 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1399 } 1400 VOP_UNLOCK(vp); 1401 return (error); 1402} 1403 1404/* 1405 * Change mode of a file given path name. 1406 */ 1407struct chmod_args { 1408 char *path; 1409 int mode; 1410}; 1411/* ARGSUSED */ 1412int 1413chmod(p, uap, retval) 1414 struct proc *p; 1415 register struct chmod_args *uap; 1416 int *retval; 1417{ 1418 register struct vnode *vp; 1419 struct vattr vattr; 1420 int error; 1421 struct nameidata nd; 1422 1423 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 1424 if (error = namei(&nd)) 1425 return (error); 1426 vp = nd.ni_vp; 1427 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1428 VOP_LOCK(vp); 1429 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1430 error = EROFS; 1431 else { 1432 VATTR_NULL(&vattr); 1433 vattr.va_mode = uap->mode & ALLPERMS; 1434 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1435 } 1436 vput(vp); 1437 return (error); 1438} 1439 1440/* 1441 * Change mode of a file given a file descriptor. 1442 */ 1443struct fchmod_args { 1444 int fd; 1445 int mode; 1446}; 1447/* ARGSUSED */ 1448int 1449fchmod(p, uap, retval) 1450 struct proc *p; 1451 register struct fchmod_args *uap; 1452 int *retval; 1453{ 1454 struct vattr vattr; 1455 struct vnode *vp; 1456 struct file *fp; 1457 int error; 1458 1459 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1460 return (error); 1461 vp = (struct vnode *)fp->f_data; 1462 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1463 VOP_LOCK(vp); 1464 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1465 error = EROFS; 1466 else { 1467 VATTR_NULL(&vattr); 1468 vattr.va_mode = uap->mode & ALLPERMS; 1469 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1470 } 1471 VOP_UNLOCK(vp); 1472 return (error); 1473} 1474 1475/* 1476 * Set ownership given a path name. 1477 */ 1478struct chown_args { 1479 char *path; 1480 int uid; 1481 int gid; 1482}; 1483/* ARGSUSED */ 1484int 1485chown(p, uap, retval) 1486 struct proc *p; 1487 register struct chown_args *uap; 1488 int *retval; 1489{ 1490 register struct vnode *vp; 1491 struct vattr vattr; 1492 int error; 1493 struct nameidata nd; 1494 1495 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 1496 if (error = namei(&nd)) 1497 return (error); 1498 vp = nd.ni_vp; 1499 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1500 VOP_LOCK(vp); 1501 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1502 error = EROFS; 1503 else { 1504 VATTR_NULL(&vattr); 1505 vattr.va_uid = uap->uid; 1506 vattr.va_gid = uap->gid; 1507 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1508 } 1509 vput(vp); 1510 return (error); 1511} 1512 1513/* 1514 * Set ownership given a file descriptor. 1515 */ 1516struct fchown_args { 1517 int fd; 1518 int uid; 1519 int gid; 1520}; 1521/* ARGSUSED */ 1522int 1523fchown(p, uap, retval) 1524 struct proc *p; 1525 register struct fchown_args *uap; 1526 int *retval; 1527{ 1528 struct vattr vattr; 1529 struct vnode *vp; 1530 struct file *fp; 1531 int error; 1532 1533 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1534 return (error); 1535 vp = (struct vnode *)fp->f_data; 1536 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1537 VOP_LOCK(vp); 1538 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1539 error = EROFS; 1540 else { 1541 VATTR_NULL(&vattr); 1542 vattr.va_uid = uap->uid; 1543 vattr.va_gid = uap->gid; 1544 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1545 } 1546 VOP_UNLOCK(vp); 1547 return (error); 1548} 1549 1550/* 1551 * Set the access and modification times of a file. 1552 */ 1553struct utimes_args { 1554 char *path; 1555 struct timeval *tptr; 1556}; 1557/* ARGSUSED */ 1558int 1559utimes(p, uap, retval) 1560 struct proc *p; 1561 register struct utimes_args *uap; 1562 int *retval; 1563{ 1564 register struct vnode *vp; 1565 struct timeval tv[2]; 1566 struct vattr vattr; 1567 int error; 1568 struct nameidata nd; 1569 1570 VATTR_NULL(&vattr); 1571 if (uap->tptr == NULL) { 1572 microtime(&tv[0]); 1573 tv[1] = tv[0]; 1574 vattr.va_vaflags |= VA_UTIMES_NULL; 1575 } else if (error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv))) 1576 return (error); 1577 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 1578 if (error = namei(&nd)) 1579 return (error); 1580 vp = nd.ni_vp; 1581 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1582 VOP_LOCK(vp); 1583 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1584 error = EROFS; 1585 else { 1586 vattr.va_atime.ts_sec = tv[0].tv_sec; 1587 vattr.va_atime.ts_nsec = tv[0].tv_usec * 1000; 1588 vattr.va_mtime.ts_sec = tv[1].tv_sec; 1589 vattr.va_mtime.ts_nsec = tv[1].tv_usec * 1000; 1590 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1591 } 1592 vput(vp); 1593 return (error); 1594} 1595 1596/* 1597 * Truncate a file given its path name. 1598 */ 1599struct truncate_args { 1600 char *path; 1601 int pad; 1602 off_t length; 1603}; 1604/* ARGSUSED */ 1605int 1606truncate(p, uap, retval) 1607 struct proc *p; 1608 register struct truncate_args *uap; 1609 int *retval; 1610{ 1611 register struct vnode *vp; 1612 struct vattr vattr; 1613 int error; 1614 struct nameidata nd; 1615 1616 if (uap->length < 0) 1617 return(EINVAL); 1618 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 1619 if (error = namei(&nd)) 1620 return (error); 1621 vp = nd.ni_vp; 1622 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1623 VOP_LOCK(vp); 1624 if (vp->v_type == VDIR) 1625 error = EISDIR; 1626 else if ((error = vn_writechk(vp)) == 0 && 1627 (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) { 1628 VATTR_NULL(&vattr); 1629 vattr.va_size = uap->length; 1630 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1631 } 1632 vput(vp); 1633 return (error); 1634} 1635 1636/* 1637 * Truncate a file given a file descriptor. 1638 */ 1639struct ftruncate_args { 1640 int fd; 1641 int pad; 1642 off_t length; 1643}; 1644/* ARGSUSED */ 1645int 1646ftruncate(p, uap, retval) 1647 struct proc *p; 1648 register struct ftruncate_args *uap; 1649 int *retval; 1650{ 1651 struct vattr vattr; 1652 struct vnode *vp; 1653 struct file *fp; 1654 int error; 1655 1656 if (uap->length < 0) 1657 return(EINVAL); 1658 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1659 return (error); 1660 if ((fp->f_flag & FWRITE) == 0) 1661 return (EINVAL); 1662 vp = (struct vnode *)fp->f_data; 1663 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1664 VOP_LOCK(vp); 1665 if (vp->v_type == VDIR) 1666 error = EISDIR; 1667 else if ((error = vn_writechk(vp)) == 0) { 1668 VATTR_NULL(&vattr); 1669 vattr.va_size = uap->length; 1670 error = VOP_SETATTR(vp, &vattr, fp->f_cred, p); 1671 } 1672 VOP_UNLOCK(vp); 1673 return (error); 1674} 1675 1676#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1677/* 1678 * Truncate a file given its path name. 1679 */ 1680struct otruncate_args { 1681 char *path; 1682 long length; 1683}; 1684/* ARGSUSED */ 1685int 1686otruncate(p, uap, retval) 1687 struct proc *p; 1688 register struct otruncate_args *uap; 1689 int *retval; 1690{ 1691 struct truncate_args nuap; 1692 1693 nuap.path = uap->path; 1694 nuap.length = uap->length; 1695 return (truncate(p, &nuap, retval)); 1696} 1697 1698/* 1699 * Truncate a file given a file descriptor. 1700 */ 1701struct oftruncate_args { 1702 int fd; 1703 long length; 1704}; 1705/* ARGSUSED */ 1706int 1707oftruncate(p, uap, retval) 1708 struct proc *p; 1709 register struct oftruncate_args *uap; 1710 int *retval; 1711{ 1712 struct ftruncate_args nuap; 1713 1714 nuap.fd = uap->fd; 1715 nuap.length = uap->length; 1716 return (ftruncate(p, &nuap, retval)); 1717} 1718#endif /* COMPAT_43 || COMPAT_SUNOS */ 1719 1720/* 1721 * Sync an open file. 1722 */ 1723struct fsync_args { 1724 int fd; 1725}; 1726/* ARGSUSED */ 1727int 1728fsync(p, uap, retval) 1729 struct proc *p; 1730 struct fsync_args *uap; 1731 int *retval; 1732{ 1733 register struct vnode *vp; 1734 struct file *fp; 1735 int error; 1736 1737 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1738 return (error); 1739 vp = (struct vnode *)fp->f_data; 1740 VOP_LOCK(vp); 1741 error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p); 1742 VOP_UNLOCK(vp); 1743 return (error); 1744} 1745 1746/* 1747 * Rename files. Source and destination must either both be directories, 1748 * or both not be directories. If target is a directory, it must be empty. 1749 */ 1750struct rename_args { 1751 char *from; 1752 char *to; 1753}; 1754/* ARGSUSED */ 1755int 1756rename(p, uap, retval) 1757 struct proc *p; 1758 register struct rename_args *uap; 1759 int *retval; 1760{ 1761 register struct vnode *tvp, *fvp, *tdvp; 1762 struct nameidata fromnd, tond; 1763 int error; 1764 1765 NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE, 1766 uap->from, p); 1767 if (error = namei(&fromnd)) 1768 return (error); 1769 fvp = fromnd.ni_vp; 1770 NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART, 1771 UIO_USERSPACE, uap->to, p); 1772 if (error = namei(&tond)) { 1773 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 1774 vrele(fromnd.ni_dvp); 1775 vrele(fvp); 1776 goto out1; 1777 } 1778 tdvp = tond.ni_dvp; 1779 tvp = tond.ni_vp; 1780 if (tvp != NULL) { 1781 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 1782 error = ENOTDIR; 1783 goto out; 1784 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 1785 error = EISDIR; 1786 goto out; 1787 } 1788 } 1789 if (fvp == tdvp) 1790 error = EINVAL; 1791 /* 1792 * If source is the same as the destination (that is the 1793 * same inode number with the same name in the same directory), 1794 * then there is nothing to do. 1795 */ 1796 if (fvp == tvp && fromnd.ni_dvp == tdvp && 1797 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen && 1798 !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr, 1799 fromnd.ni_cnd.cn_namelen)) 1800 error = -1; 1801out: 1802 if (!error) { 1803 LEASE_CHECK(tdvp, p, p->p_ucred, LEASE_WRITE); 1804 if (fromnd.ni_dvp != tdvp) 1805 LEASE_CHECK(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1806 if (tvp) 1807 LEASE_CHECK(tvp, p, p->p_ucred, LEASE_WRITE); 1808 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd, 1809 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd); 1810 } else { 1811 VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd); 1812 if (tdvp == tvp) 1813 vrele(tdvp); 1814 else 1815 vput(tdvp); 1816 if (tvp) 1817 vput(tvp); 1818 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 1819 vrele(fromnd.ni_dvp); 1820 vrele(fvp); 1821 } 1822 vrele(tond.ni_startdir); 1823 FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI); 1824out1: 1825 if (fromnd.ni_startdir) 1826 vrele(fromnd.ni_startdir); 1827 FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI); 1828 if (error == -1) 1829 return (0); 1830 return (error); 1831} 1832 1833/* 1834 * Make a directory file. 1835 */ 1836struct mkdir_args { 1837 char *path; 1838 int mode; 1839}; 1840/* ARGSUSED */ 1841int 1842mkdir(p, uap, retval) 1843 struct proc *p; 1844 register struct mkdir_args *uap; 1845 int *retval; 1846{ 1847 register struct vnode *vp; 1848 struct vattr vattr; 1849 int error; 1850 struct nameidata nd; 1851 1852 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p); 1853 if (error = namei(&nd)) 1854 return (error); 1855 vp = nd.ni_vp; 1856 if (vp != NULL) { 1857 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1858 if (nd.ni_dvp == vp) 1859 vrele(nd.ni_dvp); 1860 else 1861 vput(nd.ni_dvp); 1862 vrele(vp); 1863 return (EEXIST); 1864 } 1865 VATTR_NULL(&vattr); 1866 vattr.va_type = VDIR; 1867 vattr.va_mode = (uap->mode & ACCESSPERMS) &~ p->p_fd->fd_cmask; 1868 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1869 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 1870 if (!error) 1871 vput(nd.ni_vp); 1872 return (error); 1873} 1874 1875/* 1876 * Remove a directory file. 1877 */ 1878struct rmdir_args { 1879 char *path; 1880}; 1881/* ARGSUSED */ 1882int 1883rmdir(p, uap, retval) 1884 struct proc *p; 1885 struct rmdir_args *uap; 1886 int *retval; 1887{ 1888 register struct vnode *vp; 1889 int error; 1890 struct nameidata nd; 1891 1892 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, uap->path, p); 1893 if (error = namei(&nd)) 1894 return (error); 1895 vp = nd.ni_vp; 1896 if (vp->v_type != VDIR) { 1897 error = ENOTDIR; 1898 goto out; 1899 } 1900 /* 1901 * No rmdir "." please. 1902 */ 1903 if (nd.ni_dvp == vp) { 1904 error = EINVAL; 1905 goto out; 1906 } 1907 /* 1908 * The root of a mounted filesystem cannot be deleted. 1909 */ 1910 if (vp->v_flag & VROOT) 1911 error = EBUSY; 1912out: 1913 if (!error) { 1914 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1915 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1916 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 1917 } else { 1918 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1919 if (nd.ni_dvp == vp) 1920 vrele(nd.ni_dvp); 1921 else 1922 vput(nd.ni_dvp); 1923 vput(vp); 1924 } 1925 return (error); 1926} 1927 1928#ifdef COMPAT_43 1929/* 1930 * Read a block of directory entries in a file system independent format. 1931 */ 1932struct ogetdirentries_args { 1933 int fd; 1934 char *buf; 1935 u_int count; 1936 long *basep; 1937}; 1938int 1939ogetdirentries(p, uap, retval) 1940 struct proc *p; 1941 register struct ogetdirentries_args *uap; 1942 int *retval; 1943{ 1944 register struct vnode *vp; 1945 struct file *fp; 1946 struct uio auio, kuio; 1947 struct iovec aiov, kiov; 1948 struct dirent *dp, *edp; 1949 caddr_t dirbuf; 1950 int error, readcnt; 1951 long loff; 1952 1953 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1954 return (error); 1955 if ((fp->f_flag & FREAD) == 0) 1956 return (EBADF); 1957 vp = (struct vnode *)fp->f_data; 1958 if (vp->v_type != VDIR) 1959 return (EINVAL); 1960 aiov.iov_base = uap->buf; 1961 aiov.iov_len = uap->count; 1962 auio.uio_iov = &aiov; 1963 auio.uio_iovcnt = 1; 1964 auio.uio_rw = UIO_READ; 1965 auio.uio_segflg = UIO_USERSPACE; 1966 auio.uio_procp = p; 1967 auio.uio_resid = uap->count; 1968 VOP_LOCK(vp); 1969 loff = auio.uio_offset = fp->f_offset; 1970# if (BYTE_ORDER != LITTLE_ENDIAN) 1971 if (vp->v_mount->mnt_maxsymlinklen <= 0) { 1972 error = VOP_READDIR(vp, &auio, fp->f_cred); 1973 fp->f_offset = auio.uio_offset; 1974 } else 1975# endif 1976 { 1977 kuio = auio; 1978 kuio.uio_iov = &kiov; 1979 kuio.uio_segflg = UIO_SYSSPACE; 1980 kiov.iov_len = uap->count; 1981 MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK); 1982 kiov.iov_base = dirbuf; 1983 error = VOP_READDIR(vp, &kuio, fp->f_cred); 1984 fp->f_offset = kuio.uio_offset; 1985 if (error == 0) { 1986 readcnt = uap->count - kuio.uio_resid; 1987 edp = (struct dirent *)&dirbuf[readcnt]; 1988 for (dp = (struct dirent *)dirbuf; dp < edp; ) { 1989# if (BYTE_ORDER == LITTLE_ENDIAN) 1990 /* 1991 * The expected low byte of 1992 * dp->d_namlen is our dp->d_type. 1993 * The high MBZ byte of dp->d_namlen 1994 * is our dp->d_namlen. 1995 */ 1996 dp->d_type = dp->d_namlen; 1997 dp->d_namlen = 0; 1998# else 1999 /* 2000 * The dp->d_type is the high byte 2001 * of the expected dp->d_namlen, 2002 * so must be zero'ed. 2003 */ 2004 dp->d_type = 0; 2005# endif 2006 if (dp->d_reclen > 0) { 2007 dp = (struct dirent *) 2008 ((char *)dp + dp->d_reclen); 2009 } else { 2010 error = EIO; 2011 break; 2012 } 2013 } 2014 if (dp >= edp) 2015 error = uiomove(dirbuf, readcnt, &auio); 2016 } 2017 FREE(dirbuf, M_TEMP); 2018 } 2019 VOP_UNLOCK(vp); 2020 if (error) 2021 return (error); 2022 error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long)); 2023 *retval = uap->count - auio.uio_resid; 2024 return (error); 2025} 2026#endif 2027 2028/* 2029 * Read a block of directory entries in a file system independent format. 2030 */ 2031struct getdirentries_args { 2032 int fd; 2033 char *buf; 2034 u_int count; 2035 long *basep; 2036}; 2037int 2038getdirentries(p, uap, retval) 2039 struct proc *p; 2040 register struct getdirentries_args *uap; 2041 int *retval; 2042{ 2043 register struct vnode *vp; 2044 struct file *fp; 2045 struct uio auio; 2046 struct iovec aiov; 2047 long loff; 2048 int error; 2049 2050 if (error = getvnode(p->p_fd, uap->fd, &fp)) 2051 return (error); 2052 if ((fp->f_flag & FREAD) == 0) 2053 return (EBADF); 2054 vp = (struct vnode *)fp->f_data; 2055unionread: 2056 if (vp->v_type != VDIR) 2057 return (EINVAL); 2058 aiov.iov_base = uap->buf; 2059 aiov.iov_len = uap->count; 2060 auio.uio_iov = &aiov; 2061 auio.uio_iovcnt = 1; 2062 auio.uio_rw = UIO_READ; 2063 auio.uio_segflg = UIO_USERSPACE; 2064 auio.uio_procp = p; 2065 auio.uio_resid = uap->count; 2066 VOP_LOCK(vp); 2067 loff = auio.uio_offset = fp->f_offset; 2068 error = VOP_READDIR(vp, &auio, fp->f_cred); 2069 fp->f_offset = auio.uio_offset; 2070 VOP_UNLOCK(vp); 2071 if (error) 2072 return (error); 2073 2074#ifdef UNION 2075{ 2076 extern int (**union_vnodeop_p)(); 2077 extern struct vnode *union_lowervp __P((struct vnode *)); 2078 2079 if ((uap->count == auio.uio_resid) && 2080 (vp->v_op == union_vnodeop_p)) { 2081 struct vnode *tvp = vp; 2082 2083 vp = union_lowervp(vp); 2084 if (vp != NULLVP) { 2085 VOP_LOCK(vp); 2086 error = VOP_OPEN(vp, FREAD); 2087 VOP_UNLOCK(vp); 2088 2089 if (error) { 2090 vrele(vp); 2091 return (error); 2092 } 2093 fp->f_data = (caddr_t) vp; 2094 fp->f_offset = 0; 2095 error = vn_close(tvp, FREAD, fp->f_cred, p); 2096 if (error) 2097 return (error); 2098 goto unionread; 2099 } 2100 } 2101} 2102#endif 2103 2104 if ((uap->count == auio.uio_resid) && 2105 (vp->v_flag & VROOT) && 2106 (vp->v_mount->mnt_flag & MNT_UNION)) { 2107 struct vnode *tvp = vp; 2108 vp = vp->v_mount->mnt_vnodecovered; 2109 VREF(vp); 2110 fp->f_data = (caddr_t) vp; 2111 fp->f_offset = 0; 2112 vrele(tvp); 2113 goto unionread; 2114 } 2115 error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long)); 2116 *retval = uap->count - auio.uio_resid; 2117 return (error); 2118} 2119 2120/* 2121 * Set the mode mask for creation of filesystem nodes. 2122 */ 2123struct umask_args { 2124 int newmask; 2125}; 2126mode_t /* XXX */ 2127umask(p, uap, retval) 2128 struct proc *p; 2129 struct umask_args *uap; 2130 int *retval; 2131{ 2132 register struct filedesc *fdp; 2133 2134 fdp = p->p_fd; 2135 *retval = fdp->fd_cmask; 2136 fdp->fd_cmask = uap->newmask & ALLPERMS; 2137 return (0); 2138} 2139 2140/* 2141 * Void all references to file by ripping underlying filesystem 2142 * away from vnode. 2143 */ 2144struct revoke_args { 2145 char *path; 2146}; 2147/* ARGSUSED */ 2148int 2149revoke(p, uap, retval) 2150 struct proc *p; 2151 register struct revoke_args *uap; 2152 int *retval; 2153{ 2154 register struct vnode *vp; 2155 struct vattr vattr; 2156 int error; 2157 struct nameidata nd; 2158 2159 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 2160 if (error = namei(&nd)) 2161 return (error); 2162 vp = nd.ni_vp; 2163 if (vp->v_type != VCHR && vp->v_type != VBLK) { 2164 error = EINVAL; 2165 goto out; 2166 } 2167 if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) 2168 goto out; 2169 if (p->p_ucred->cr_uid != vattr.va_uid && 2170 (error = suser(p->p_ucred, &p->p_acflag))) 2171 goto out; 2172 if (vp->v_usecount > 1 || (vp->v_flag & VALIASED)) 2173 vgoneall(vp); 2174out: 2175 vrele(vp); 2176 return (error); 2177} 2178 2179/* 2180 * Convert a user file descriptor to a kernel file entry. 2181 */ 2182int 2183getvnode(fdp, fd, fpp) 2184 struct filedesc *fdp; 2185 struct file **fpp; 2186 int fd; 2187{ 2188 struct file *fp; 2189 2190 if ((u_int)fd >= fdp->fd_nfiles || 2191 (fp = fdp->fd_ofiles[fd]) == NULL) 2192 return (EBADF); 2193 if (fp->f_type != DTYPE_VNODE) 2194 return (EINVAL); 2195 *fpp = fp; 2196 return (0); 2197}
| 290 if (mp->mnt_vnodelist.lh_first != NULL) 291 panic("unmount: dangling vnode"); 292 free((caddr_t)mp, M_MOUNT); 293 } 294 return (error); 295} 296 297/* 298 * Sync each mounted filesystem. 299 */ 300#ifdef DIAGNOSTIC 301int syncprt = 0; 302struct ctldebug debug0 = { "syncprt", &syncprt }; 303#endif 304 305struct sync_args { 306 int dummy; 307}; 308/* ARGSUSED */ 309int 310sync(p, uap, retval) 311 struct proc *p; 312 struct sync_args *uap; 313 int *retval; 314{ 315 register struct mount *mp, *nmp; 316 int asyncflag; 317 318 for (mp = mountlist.tqh_first; mp != NULL; mp = nmp) { 319 nmp = mp->mnt_list.tqe_next; 320 /* 321 * The lock check below is to avoid races with mount 322 * and unmount. 323 */ 324 if ((mp->mnt_flag & (MNT_MLOCK|MNT_RDONLY|MNT_MPBUSY)) == 0 && 325 !vfs_busy(mp)) { 326 asyncflag = mp->mnt_flag & MNT_ASYNC; 327 mp->mnt_flag &= ~MNT_ASYNC; 328 VFS_SYNC(mp, MNT_NOWAIT, p->p_ucred, p); 329 if (asyncflag) 330 mp->mnt_flag |= MNT_ASYNC; 331 vfs_unbusy(mp); 332 } 333 } 334#ifdef DIAGNOSTIC 335 if (syncprt) 336 vfs_bufstats(); 337#endif /* DIAGNOSTIC */ 338 return (0); 339} 340 341/* 342 * Change filesystem quotas. 343 */ 344struct quotactl_args { 345 char *path; 346 int cmd; 347 int uid; 348 caddr_t arg; 349}; 350/* ARGSUSED */ 351int 352quotactl(p, uap, retval) 353 struct proc *p; 354 register struct quotactl_args *uap; 355 int *retval; 356{ 357 register struct mount *mp; 358 int error; 359 struct nameidata nd; 360 361 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 362 if (error = namei(&nd)) 363 return (error); 364 mp = nd.ni_vp->v_mount; 365 vrele(nd.ni_vp); 366 return (VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg, p)); 367} 368 369/* 370 * Get filesystem statistics. 371 */ 372struct statfs_args { 373 char *path; 374 struct statfs *buf; 375}; 376/* ARGSUSED */ 377int 378statfs(p, uap, retval) 379 struct proc *p; 380 register struct statfs_args *uap; 381 int *retval; 382{ 383 register struct mount *mp; 384 register struct statfs *sp; 385 int error; 386 struct nameidata nd; 387 388 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 389 if (error = namei(&nd)) 390 return (error); 391 mp = nd.ni_vp->v_mount; 392 sp = &mp->mnt_stat; 393 vrele(nd.ni_vp); 394 if (error = VFS_STATFS(mp, sp, p)) 395 return (error); 396 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 397 return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp))); 398} 399 400/* 401 * Get filesystem statistics. 402 */ 403struct fstatfs_args { 404 int fd; 405 struct statfs *buf; 406}; 407/* ARGSUSED */ 408int 409fstatfs(p, uap, retval) 410 struct proc *p; 411 register struct fstatfs_args *uap; 412 int *retval; 413{ 414 struct file *fp; 415 struct mount *mp; 416 register struct statfs *sp; 417 int error; 418 419 if (error = getvnode(p->p_fd, uap->fd, &fp)) 420 return (error); 421 mp = ((struct vnode *)fp->f_data)->v_mount; 422 sp = &mp->mnt_stat; 423 if (error = VFS_STATFS(mp, sp, p)) 424 return (error); 425 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 426 return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp))); 427} 428 429/* 430 * Get statistics on all filesystems. 431 */ 432struct getfsstat_args { 433 struct statfs *buf; 434 long bufsize; 435 int flags; 436}; 437int 438getfsstat(p, uap, retval) 439 struct proc *p; 440 register struct getfsstat_args *uap; 441 int *retval; 442{ 443 register struct mount *mp, *nmp; 444 register struct statfs *sp; 445 caddr_t sfsp; 446 long count, maxcount, error; 447 448 maxcount = uap->bufsize / sizeof(struct statfs); 449 sfsp = (caddr_t)uap->buf; 450 for (count = 0, mp = mountlist.tqh_first; mp != NULL; mp = nmp) { 451 nmp = mp->mnt_list.tqe_next; 452 if (sfsp && count < maxcount && 453 ((mp->mnt_flag & MNT_MLOCK) == 0)) { 454 sp = &mp->mnt_stat; 455 /* 456 * If MNT_NOWAIT is specified, do not refresh the 457 * fsstat cache. MNT_WAIT overrides MNT_NOWAIT. 458 */ 459 if (((uap->flags & MNT_NOWAIT) == 0 || 460 (uap->flags & MNT_WAIT)) && 461 (error = VFS_STATFS(mp, sp, p))) 462 continue; 463 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 464 if (error = copyout((caddr_t)sp, sfsp, sizeof(*sp))) 465 return (error); 466 sfsp += sizeof(*sp); 467 } 468 count++; 469 } 470 if (sfsp && count > maxcount) 471 *retval = maxcount; 472 else 473 *retval = count; 474 return (0); 475} 476 477/* 478 * Change current working directory to a given file descriptor. 479 */ 480struct fchdir_args { 481 int fd; 482}; 483/* ARGSUSED */ 484int 485fchdir(p, uap, retval) 486 struct proc *p; 487 struct fchdir_args *uap; 488 int *retval; 489{ 490 register struct filedesc *fdp = p->p_fd; 491 register struct vnode *vp; 492 struct file *fp; 493 int error; 494 495 if (error = getvnode(fdp, uap->fd, &fp)) 496 return (error); 497 vp = (struct vnode *)fp->f_data; 498 VOP_LOCK(vp); 499 if (vp->v_type != VDIR) 500 error = ENOTDIR; 501 else 502 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); 503 VOP_UNLOCK(vp); 504 if (error) 505 return (error); 506 VREF(vp); 507 vrele(fdp->fd_cdir); 508 fdp->fd_cdir = vp; 509 return (0); 510} 511 512/* 513 * Change current working directory (``.''). 514 */ 515struct chdir_args { 516 char *path; 517}; 518/* ARGSUSED */ 519int 520chdir(p, uap, retval) 521 struct proc *p; 522 struct chdir_args *uap; 523 int *retval; 524{ 525 register struct filedesc *fdp = p->p_fd; 526 int error; 527 struct nameidata nd; 528 529 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); 530 if (error = change_dir(&nd, p)) 531 return (error); 532 vrele(fdp->fd_cdir); 533 fdp->fd_cdir = nd.ni_vp; 534 return (0); 535} 536 537/* 538 * Change notion of root (``/'') directory. 539 */ 540struct chroot_args { 541 char *path; 542}; 543/* ARGSUSED */ 544int 545chroot(p, uap, retval) 546 struct proc *p; 547 struct chroot_args *uap; 548 int *retval; 549{ 550 register struct filedesc *fdp = p->p_fd; 551 int error; 552 struct nameidata nd; 553 554 if (error = suser(p->p_ucred, &p->p_acflag)) 555 return (error); 556 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); 557 if (error = change_dir(&nd, p)) 558 return (error); 559 if (fdp->fd_rdir != NULL) 560 vrele(fdp->fd_rdir); 561 fdp->fd_rdir = nd.ni_vp; 562 return (0); 563} 564 565/* 566 * Common routine for chroot and chdir. 567 */ 568static int 569change_dir(ndp, p) 570 register struct nameidata *ndp; 571 struct proc *p; 572{ 573 struct vnode *vp; 574 int error; 575 576 if (error = namei(ndp)) 577 return (error); 578 vp = ndp->ni_vp; 579 if (vp->v_type != VDIR) 580 error = ENOTDIR; 581 else 582 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); 583 VOP_UNLOCK(vp); 584 if (error) 585 vrele(vp); 586 return (error); 587} 588 589/* 590 * Check permissions, allocate an open file structure, 591 * and call the device open routine if any. 592 */ 593struct open_args { 594 char *path; 595 int flags; 596 int mode; 597}; 598int 599open(p, uap, retval) 600 struct proc *p; 601 register struct open_args *uap; 602 int *retval; 603{ 604 register struct filedesc *fdp = p->p_fd; 605 register struct file *fp; 606 register struct vnode *vp; 607 int flags, cmode; 608 struct file *nfp; 609 int type, indx, error; 610 struct flock lf; 611 struct nameidata nd; 612 extern struct fileops vnops; 613 614 if (error = falloc(p, &nfp, &indx)) 615 return (error); 616 fp = nfp; 617 flags = FFLAGS(uap->flags); 618 cmode = ((uap->mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT; 619 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 620 p->p_dupfd = -indx - 1; /* XXX check for fdopen */ 621 if (error = vn_open(&nd, flags, cmode)) { 622 ffree(fp); 623 if ((error == ENODEV || error == ENXIO) && 624 p->p_dupfd >= 0 && /* XXX from fdopen */ 625 (error = 626 dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) { 627 *retval = indx; 628 return (0); 629 } 630 if (error == ERESTART) 631 error = EINTR; 632 fdp->fd_ofiles[indx] = NULL; 633 return (error); 634 } 635 p->p_dupfd = 0; 636 vp = nd.ni_vp; 637 fp->f_flag = flags & FMASK; 638 fp->f_type = DTYPE_VNODE; 639 fp->f_ops = &vnops; 640 fp->f_data = (caddr_t)vp; 641 if (flags & (O_EXLOCK | O_SHLOCK)) { 642 lf.l_whence = SEEK_SET; 643 lf.l_start = 0; 644 lf.l_len = 0; 645 if (flags & O_EXLOCK) 646 lf.l_type = F_WRLCK; 647 else 648 lf.l_type = F_RDLCK; 649 type = F_FLOCK; 650 if ((flags & FNONBLOCK) == 0) 651 type |= F_WAIT; 652 VOP_UNLOCK(vp); 653 if (error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) { 654 (void) vn_close(vp, fp->f_flag, fp->f_cred, p); 655 ffree(fp); 656 fdp->fd_ofiles[indx] = NULL; 657 return (error); 658 } 659 VOP_LOCK(vp); 660 fp->f_flag |= FHASLOCK; 661 } 662 VOP_UNLOCK(vp); 663 *retval = indx; 664 return (0); 665} 666 667#ifdef COMPAT_43 668/* 669 * Create a file. 670 */ 671struct ocreat_args { 672 char *path; 673 int mode; 674}; 675int 676ocreat(p, uap, retval) 677 struct proc *p; 678 register struct ocreat_args *uap; 679 int *retval; 680{ 681 struct open_args openuap; 682 683 openuap.path = uap->path; 684 openuap.mode = uap->mode; 685 openuap.flags = O_WRONLY | O_CREAT | O_TRUNC; 686 return (open(p, &openuap, retval)); 687} 688#endif /* COMPAT_43 */ 689 690/* 691 * Create a special file. 692 */ 693struct mknod_args { 694 char *path; 695 int mode; 696 int dev; 697}; 698/* ARGSUSED */ 699int 700mknod(p, uap, retval) 701 struct proc *p; 702 register struct mknod_args *uap; 703 int *retval; 704{ 705 register struct vnode *vp; 706 struct vattr vattr; 707 int error; 708 struct nameidata nd; 709 710 if (error = suser(p->p_ucred, &p->p_acflag)) 711 return (error); 712 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p); 713 if (error = namei(&nd)) 714 return (error); 715 vp = nd.ni_vp; 716 if (vp != NULL) 717 error = EEXIST; 718 else { 719 VATTR_NULL(&vattr); 720 vattr.va_mode = (uap->mode & ALLPERMS) &~ p->p_fd->fd_cmask; 721 vattr.va_rdev = uap->dev; 722 723 switch (uap->mode & S_IFMT) { 724 case S_IFMT: /* used by badsect to flag bad sectors */ 725 vattr.va_type = VBAD; 726 break; 727 case S_IFCHR: 728 vattr.va_type = VCHR; 729 break; 730 case S_IFBLK: 731 vattr.va_type = VBLK; 732 break; 733 default: 734 error = EINVAL; 735 break; 736 } 737 } 738 if (!error) { 739 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 740 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 741 } else { 742 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 743 if (nd.ni_dvp == vp) 744 vrele(nd.ni_dvp); 745 else 746 vput(nd.ni_dvp); 747 if (vp) 748 vrele(vp); 749 } 750 return (error); 751} 752 753/* 754 * Create named pipe. 755 */ 756struct mkfifo_args { 757 char *path; 758 int mode; 759}; 760/* ARGSUSED */ 761int 762mkfifo(p, uap, retval) 763 struct proc *p; 764 register struct mkfifo_args *uap; 765 int *retval; 766{ 767 struct vattr vattr; 768 int error; 769 struct nameidata nd; 770 771#ifndef FIFO 772 return (EOPNOTSUPP); 773#else 774 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p); 775 if (error = namei(&nd)) 776 return (error); 777 if (nd.ni_vp != NULL) { 778 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 779 if (nd.ni_dvp == nd.ni_vp) 780 vrele(nd.ni_dvp); 781 else 782 vput(nd.ni_dvp); 783 vrele(nd.ni_vp); 784 return (EEXIST); 785 } 786 VATTR_NULL(&vattr); 787 vattr.va_type = VFIFO; 788 vattr.va_mode = (uap->mode & ALLPERMS) &~ p->p_fd->fd_cmask; 789 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 790 return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr)); 791#endif /* FIFO */ 792} 793 794/* 795 * Make a hard file link. 796 */ 797struct link_args { 798 char *path; 799 char *link; 800}; 801/* ARGSUSED */ 802int 803link(p, uap, retval) 804 struct proc *p; 805 register struct link_args *uap; 806 int *retval; 807{ 808 register struct vnode *vp; 809 struct nameidata nd; 810 int error; 811 812 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 813 if (error = namei(&nd)) 814 return (error); 815 vp = nd.ni_vp; 816 if (vp->v_type != VDIR || 817 (error = suser(p->p_ucred, &p->p_acflag)) == 0) { 818 nd.ni_cnd.cn_nameiop = CREATE; 819 nd.ni_cnd.cn_flags = LOCKPARENT; 820 nd.ni_dirp = uap->link; 821 if ((error = namei(&nd)) == 0) { 822 if (nd.ni_vp != NULL) 823 error = EEXIST; 824 if (!error) { 825 LEASE_CHECK(nd.ni_dvp, 826 p, p->p_ucred, LEASE_WRITE); 827 LEASE_CHECK(vp, 828 p, p->p_ucred, LEASE_WRITE); 829 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd); 830 } else { 831 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 832 if (nd.ni_dvp == nd.ni_vp) 833 vrele(nd.ni_dvp); 834 else 835 vput(nd.ni_dvp); 836 if (nd.ni_vp) 837 vrele(nd.ni_vp); 838 } 839 } 840 } 841 vrele(vp); 842 return (error); 843} 844 845/* 846 * Make a symbolic link. 847 */ 848struct symlink_args { 849 char *path; 850 char *link; 851}; 852/* ARGSUSED */ 853int 854symlink(p, uap, retval) 855 struct proc *p; 856 register struct symlink_args *uap; 857 int *retval; 858{ 859 struct vattr vattr; 860 char *path; 861 int error; 862 struct nameidata nd; 863 864 MALLOC(path, char *, MAXPATHLEN, M_NAMEI, M_WAITOK); 865 if (error = copyinstr(uap->path, path, MAXPATHLEN, NULL)) 866 goto out; 867 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->link, p); 868 if (error = namei(&nd)) 869 goto out; 870 if (nd.ni_vp) { 871 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 872 if (nd.ni_dvp == nd.ni_vp) 873 vrele(nd.ni_dvp); 874 else 875 vput(nd.ni_dvp); 876 vrele(nd.ni_vp); 877 error = EEXIST; 878 goto out; 879 } 880 VATTR_NULL(&vattr); 881 vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask; 882 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 883 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path); 884out: 885 FREE(path, M_NAMEI); 886 return (error); 887} 888 889/* 890 * Delete a name from the filesystem. 891 */ 892struct unlink_args { 893 char *path; 894}; 895/* ARGSUSED */ 896int 897unlink(p, uap, retval) 898 struct proc *p; 899 struct unlink_args *uap; 900 int *retval; 901{ 902 register struct vnode *vp; 903 int error; 904 struct nameidata nd; 905 906 NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, uap->path, p); 907 if (error = namei(&nd)) 908 return (error); 909 vp = nd.ni_vp; 910 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 911 VOP_LOCK(vp); 912 913 if (vp->v_type != VDIR || 914 (error = suser(p->p_ucred, &p->p_acflag)) == 0) { 915 /* 916 * The root of a mounted filesystem cannot be deleted. 917 */ 918 if (vp->v_flag & VROOT) 919 error = EBUSY; 920 else 921 (void)vnode_pager_uncache(vp); 922 } 923 924 if (!error) { 925 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 926 error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 927 } else { 928 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 929 if (nd.ni_dvp == vp) 930 vrele(nd.ni_dvp); 931 else 932 vput(nd.ni_dvp); 933 vput(vp); 934 } 935 return (error); 936} 937 938/* 939 * Reposition read/write file offset. 940 */ 941struct lseek_args { 942 int fd; 943 int pad; 944 off_t offset; 945 int whence; 946}; 947int 948lseek(p, uap, retval) 949 struct proc *p; 950 register struct lseek_args *uap; 951 int *retval; 952{ 953 struct ucred *cred = p->p_ucred; 954 register struct filedesc *fdp = p->p_fd; 955 register struct file *fp; 956 struct vattr vattr; 957 int error; 958 959 if ((u_int)uap->fd >= fdp->fd_nfiles || 960 (fp = fdp->fd_ofiles[uap->fd]) == NULL) 961 return (EBADF); 962 if (fp->f_type != DTYPE_VNODE) 963 return (ESPIPE); 964 switch (uap->whence) { 965 case L_INCR: 966 fp->f_offset += uap->offset; 967 break; 968 case L_XTND: 969 if (error = 970 VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p)) 971 return (error); 972 fp->f_offset = uap->offset + vattr.va_size; 973 break; 974 case L_SET: 975 fp->f_offset = uap->offset; 976 break; 977 default: 978 return (EINVAL); 979 } 980 *(off_t *)retval = fp->f_offset; 981 return (0); 982} 983 984#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 985/* 986 * Reposition read/write file offset. 987 */ 988struct olseek_args { 989 int fd; 990 long offset; 991 int whence; 992}; 993int 994olseek(p, uap, retval) 995 struct proc *p; 996 register struct olseek_args *uap; 997 int *retval; 998{ 999 struct lseek_args nuap; 1000 off_t qret; 1001 int error; 1002 1003 nuap.fd = uap->fd; 1004 nuap.offset = uap->offset; 1005 nuap.whence = uap->whence; 1006 error = lseek(p, &nuap, &qret); 1007 *(long *)retval = qret; 1008 return (error); 1009} 1010#endif /* COMPAT_43 */ 1011 1012/* 1013 * Check access permissions. 1014 */ 1015struct access_args { 1016 char *path; 1017 int flags; 1018}; 1019int 1020access(p, uap, retval) 1021 struct proc *p; 1022 register struct access_args *uap; 1023 int *retval; 1024{ 1025 register struct ucred *cred = p->p_ucred; 1026 register struct vnode *vp; 1027 int error, flags, t_gid, t_uid; 1028 struct nameidata nd; 1029 1030 t_uid = cred->cr_uid; 1031 t_gid = cred->cr_groups[0]; 1032 cred->cr_uid = p->p_cred->p_ruid; 1033 cred->cr_groups[0] = p->p_cred->p_rgid; 1034 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); 1035 if (error = namei(&nd)) 1036 goto out1; 1037 vp = nd.ni_vp; 1038 1039 /* Flags == 0 means only check for existence. */ 1040 if (uap->flags) { 1041 flags = 0; 1042 if (uap->flags & R_OK) 1043 flags |= VREAD; 1044 if (uap->flags & W_OK) 1045 flags |= VWRITE; 1046 if (uap->flags & X_OK) 1047 flags |= VEXEC; 1048 if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0) 1049 error = VOP_ACCESS(vp, flags, cred, p); 1050 } 1051 vput(vp); 1052out1: 1053 cred->cr_uid = t_uid; 1054 cred->cr_groups[0] = t_gid; 1055 return (error); 1056} 1057 1058#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1059/* 1060 * Get file status; this version follows links. 1061 */ 1062struct ostat_args { 1063 char *path; 1064 struct ostat *ub; 1065}; 1066/* ARGSUSED */ 1067int 1068ostat(p, uap, retval) 1069 struct proc *p; 1070 register struct ostat_args *uap; 1071 int *retval; 1072{ 1073 struct stat sb; 1074 struct ostat osb; 1075 int error; 1076 struct nameidata nd; 1077 1078 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); 1079 if (error = namei(&nd)) 1080 return (error); 1081 error = vn_stat(nd.ni_vp, &sb, p); 1082 vput(nd.ni_vp); 1083 if (error) 1084 return (error); 1085 cvtstat(&sb, &osb); 1086 error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb)); 1087 return (error); 1088} 1089 1090/* 1091 * Get file status; this version does not follow links. 1092 */ 1093struct olstat_args { 1094 char *path; 1095 struct ostat *ub; 1096}; 1097/* ARGSUSED */ 1098int 1099olstat(p, uap, retval) 1100 struct proc *p; 1101 register struct olstat_args *uap; 1102 int *retval; 1103{ 1104 struct vnode *vp, *dvp; 1105 struct stat sb, sb1; 1106 struct ostat osb; 1107 int error; 1108 struct nameidata nd; 1109 1110 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE, 1111 uap->path, p); 1112 if (error = namei(&nd)) 1113 return (error); 1114 /* 1115 * For symbolic links, always return the attributes of its 1116 * containing directory, except for mode, size, and links. 1117 */ 1118 vp = nd.ni_vp; 1119 dvp = nd.ni_dvp; 1120 if (vp->v_type != VLNK) { 1121 if (dvp == vp) 1122 vrele(dvp); 1123 else 1124 vput(dvp); 1125 error = vn_stat(vp, &sb, p); 1126 vput(vp); 1127 if (error) 1128 return (error); 1129 } else { 1130 error = vn_stat(dvp, &sb, p); 1131 vput(dvp); 1132 if (error) { 1133 vput(vp); 1134 return (error); 1135 } 1136 error = vn_stat(vp, &sb1, p); 1137 vput(vp); 1138 if (error) 1139 return (error); 1140 sb.st_mode &= ~S_IFDIR; 1141 sb.st_mode |= S_IFLNK; 1142 sb.st_nlink = sb1.st_nlink; 1143 sb.st_size = sb1.st_size; 1144 sb.st_blocks = sb1.st_blocks; 1145 } 1146 cvtstat(&sb, &osb); 1147 error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb)); 1148 return (error); 1149} 1150 1151/* 1152 * Convert from an old to a new stat structure. 1153 */ 1154void 1155cvtstat(st, ost) 1156 struct stat *st; 1157 struct ostat *ost; 1158{ 1159 1160 ost->st_dev = st->st_dev; 1161 ost->st_ino = st->st_ino; 1162 ost->st_mode = st->st_mode; 1163 ost->st_nlink = st->st_nlink; 1164 ost->st_uid = st->st_uid; 1165 ost->st_gid = st->st_gid; 1166 ost->st_rdev = st->st_rdev; 1167 if (st->st_size < (quad_t)1 << 32) 1168 ost->st_size = st->st_size; 1169 else 1170 ost->st_size = -2; 1171 ost->st_atime = st->st_atime; 1172 ost->st_mtime = st->st_mtime; 1173 ost->st_ctime = st->st_ctime; 1174 ost->st_blksize = st->st_blksize; 1175 ost->st_blocks = st->st_blocks; 1176 ost->st_flags = st->st_flags; 1177 ost->st_gen = st->st_gen; 1178} 1179#endif /* COMPAT_43 || COMPAT_SUNOS */ 1180 1181/* 1182 * Get file status; this version follows links. 1183 */ 1184struct stat_args { 1185 char *path; 1186 struct stat *ub; 1187}; 1188/* ARGSUSED */ 1189int 1190stat(p, uap, retval) 1191 struct proc *p; 1192 register struct stat_args *uap; 1193 int *retval; 1194{ 1195 struct stat sb; 1196 int error; 1197 struct nameidata nd; 1198 1199 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); 1200 if (error = namei(&nd)) 1201 return (error); 1202 error = vn_stat(nd.ni_vp, &sb, p); 1203 vput(nd.ni_vp); 1204 if (error) 1205 return (error); 1206 error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb)); 1207 return (error); 1208} 1209 1210/* 1211 * Get file status; this version does not follow links. 1212 */ 1213struct lstat_args { 1214 char *path; 1215 struct stat *ub; 1216}; 1217/* ARGSUSED */ 1218int 1219lstat(p, uap, retval) 1220 struct proc *p; 1221 register struct lstat_args *uap; 1222 int *retval; 1223{ 1224 int error; 1225 struct vnode *vp, *dvp; 1226 struct stat sb, sb1; 1227 struct nameidata nd; 1228 1229 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE, 1230 uap->path, p); 1231 if (error = namei(&nd)) 1232 return (error); 1233 /* 1234 * For symbolic links, always return the attributes of its 1235 * containing directory, except for mode, size, and links. 1236 */ 1237 vp = nd.ni_vp; 1238 dvp = nd.ni_dvp; 1239 if (vp->v_type != VLNK) { 1240 if (dvp == vp) 1241 vrele(dvp); 1242 else 1243 vput(dvp); 1244 error = vn_stat(vp, &sb, p); 1245 vput(vp); 1246 if (error) 1247 return (error); 1248 } else { 1249 error = vn_stat(dvp, &sb, p); 1250 vput(dvp); 1251 if (error) { 1252 vput(vp); 1253 return (error); 1254 } 1255 error = vn_stat(vp, &sb1, p); 1256 vput(vp); 1257 if (error) 1258 return (error); 1259 sb.st_mode &= ~S_IFDIR; 1260 sb.st_mode |= S_IFLNK; 1261 sb.st_nlink = sb1.st_nlink; 1262 sb.st_size = sb1.st_size; 1263 sb.st_blocks = sb1.st_blocks; 1264 } 1265 error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb)); 1266 return (error); 1267} 1268 1269/* 1270 * Get configurable pathname variables. 1271 */ 1272struct pathconf_args { 1273 char *path; 1274 int name; 1275}; 1276/* ARGSUSED */ 1277int 1278pathconf(p, uap, retval) 1279 struct proc *p; 1280 register struct pathconf_args *uap; 1281 int *retval; 1282{ 1283 int error; 1284 struct nameidata nd; 1285 1286 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); 1287 if (error = namei(&nd)) 1288 return (error); 1289 error = VOP_PATHCONF(nd.ni_vp, uap->name, retval); 1290 vput(nd.ni_vp); 1291 return (error); 1292} 1293 1294/* 1295 * Return target name of a symbolic link. 1296 */ 1297struct readlink_args { 1298 char *path; 1299 char *buf; 1300 int count; 1301}; 1302/* ARGSUSED */ 1303int 1304readlink(p, uap, retval) 1305 struct proc *p; 1306 register struct readlink_args *uap; 1307 int *retval; 1308{ 1309 register struct vnode *vp; 1310 struct iovec aiov; 1311 struct uio auio; 1312 int error; 1313 struct nameidata nd; 1314 1315 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); 1316 if (error = namei(&nd)) 1317 return (error); 1318 vp = nd.ni_vp; 1319 if (vp->v_type != VLNK) 1320 error = EINVAL; 1321 else { 1322 aiov.iov_base = uap->buf; 1323 aiov.iov_len = uap->count; 1324 auio.uio_iov = &aiov; 1325 auio.uio_iovcnt = 1; 1326 auio.uio_offset = 0; 1327 auio.uio_rw = UIO_READ; 1328 auio.uio_segflg = UIO_USERSPACE; 1329 auio.uio_procp = p; 1330 auio.uio_resid = uap->count; 1331 error = VOP_READLINK(vp, &auio, p->p_ucred); 1332 } 1333 vput(vp); 1334 *retval = uap->count - auio.uio_resid; 1335 return (error); 1336} 1337 1338/* 1339 * Change flags of a file given a path name. 1340 */ 1341struct chflags_args { 1342 char *path; 1343 int flags; 1344}; 1345/* ARGSUSED */ 1346int 1347chflags(p, uap, retval) 1348 struct proc *p; 1349 register struct chflags_args *uap; 1350 int *retval; 1351{ 1352 register struct vnode *vp; 1353 struct vattr vattr; 1354 int error; 1355 struct nameidata nd; 1356 1357 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 1358 if (error = namei(&nd)) 1359 return (error); 1360 vp = nd.ni_vp; 1361 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1362 VOP_LOCK(vp); 1363 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1364 error = EROFS; 1365 else { 1366 VATTR_NULL(&vattr); 1367 vattr.va_flags = uap->flags; 1368 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1369 } 1370 vput(vp); 1371 return (error); 1372} 1373 1374/* 1375 * Change flags of a file given a file descriptor. 1376 */ 1377struct fchflags_args { 1378 int fd; 1379 int flags; 1380}; 1381/* ARGSUSED */ 1382int 1383fchflags(p, uap, retval) 1384 struct proc *p; 1385 register struct fchflags_args *uap; 1386 int *retval; 1387{ 1388 struct vattr vattr; 1389 struct vnode *vp; 1390 struct file *fp; 1391 int error; 1392 1393 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1394 return (error); 1395 vp = (struct vnode *)fp->f_data; 1396 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1397 VOP_LOCK(vp); 1398 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1399 error = EROFS; 1400 else { 1401 VATTR_NULL(&vattr); 1402 vattr.va_flags = uap->flags; 1403 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1404 } 1405 VOP_UNLOCK(vp); 1406 return (error); 1407} 1408 1409/* 1410 * Change mode of a file given path name. 1411 */ 1412struct chmod_args { 1413 char *path; 1414 int mode; 1415}; 1416/* ARGSUSED */ 1417int 1418chmod(p, uap, retval) 1419 struct proc *p; 1420 register struct chmod_args *uap; 1421 int *retval; 1422{ 1423 register struct vnode *vp; 1424 struct vattr vattr; 1425 int error; 1426 struct nameidata nd; 1427 1428 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 1429 if (error = namei(&nd)) 1430 return (error); 1431 vp = nd.ni_vp; 1432 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1433 VOP_LOCK(vp); 1434 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1435 error = EROFS; 1436 else { 1437 VATTR_NULL(&vattr); 1438 vattr.va_mode = uap->mode & ALLPERMS; 1439 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1440 } 1441 vput(vp); 1442 return (error); 1443} 1444 1445/* 1446 * Change mode of a file given a file descriptor. 1447 */ 1448struct fchmod_args { 1449 int fd; 1450 int mode; 1451}; 1452/* ARGSUSED */ 1453int 1454fchmod(p, uap, retval) 1455 struct proc *p; 1456 register struct fchmod_args *uap; 1457 int *retval; 1458{ 1459 struct vattr vattr; 1460 struct vnode *vp; 1461 struct file *fp; 1462 int error; 1463 1464 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1465 return (error); 1466 vp = (struct vnode *)fp->f_data; 1467 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1468 VOP_LOCK(vp); 1469 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1470 error = EROFS; 1471 else { 1472 VATTR_NULL(&vattr); 1473 vattr.va_mode = uap->mode & ALLPERMS; 1474 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1475 } 1476 VOP_UNLOCK(vp); 1477 return (error); 1478} 1479 1480/* 1481 * Set ownership given a path name. 1482 */ 1483struct chown_args { 1484 char *path; 1485 int uid; 1486 int gid; 1487}; 1488/* ARGSUSED */ 1489int 1490chown(p, uap, retval) 1491 struct proc *p; 1492 register struct chown_args *uap; 1493 int *retval; 1494{ 1495 register struct vnode *vp; 1496 struct vattr vattr; 1497 int error; 1498 struct nameidata nd; 1499 1500 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 1501 if (error = namei(&nd)) 1502 return (error); 1503 vp = nd.ni_vp; 1504 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1505 VOP_LOCK(vp); 1506 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1507 error = EROFS; 1508 else { 1509 VATTR_NULL(&vattr); 1510 vattr.va_uid = uap->uid; 1511 vattr.va_gid = uap->gid; 1512 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1513 } 1514 vput(vp); 1515 return (error); 1516} 1517 1518/* 1519 * Set ownership given a file descriptor. 1520 */ 1521struct fchown_args { 1522 int fd; 1523 int uid; 1524 int gid; 1525}; 1526/* ARGSUSED */ 1527int 1528fchown(p, uap, retval) 1529 struct proc *p; 1530 register struct fchown_args *uap; 1531 int *retval; 1532{ 1533 struct vattr vattr; 1534 struct vnode *vp; 1535 struct file *fp; 1536 int error; 1537 1538 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1539 return (error); 1540 vp = (struct vnode *)fp->f_data; 1541 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1542 VOP_LOCK(vp); 1543 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1544 error = EROFS; 1545 else { 1546 VATTR_NULL(&vattr); 1547 vattr.va_uid = uap->uid; 1548 vattr.va_gid = uap->gid; 1549 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1550 } 1551 VOP_UNLOCK(vp); 1552 return (error); 1553} 1554 1555/* 1556 * Set the access and modification times of a file. 1557 */ 1558struct utimes_args { 1559 char *path; 1560 struct timeval *tptr; 1561}; 1562/* ARGSUSED */ 1563int 1564utimes(p, uap, retval) 1565 struct proc *p; 1566 register struct utimes_args *uap; 1567 int *retval; 1568{ 1569 register struct vnode *vp; 1570 struct timeval tv[2]; 1571 struct vattr vattr; 1572 int error; 1573 struct nameidata nd; 1574 1575 VATTR_NULL(&vattr); 1576 if (uap->tptr == NULL) { 1577 microtime(&tv[0]); 1578 tv[1] = tv[0]; 1579 vattr.va_vaflags |= VA_UTIMES_NULL; 1580 } else if (error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv))) 1581 return (error); 1582 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 1583 if (error = namei(&nd)) 1584 return (error); 1585 vp = nd.ni_vp; 1586 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1587 VOP_LOCK(vp); 1588 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1589 error = EROFS; 1590 else { 1591 vattr.va_atime.ts_sec = tv[0].tv_sec; 1592 vattr.va_atime.ts_nsec = tv[0].tv_usec * 1000; 1593 vattr.va_mtime.ts_sec = tv[1].tv_sec; 1594 vattr.va_mtime.ts_nsec = tv[1].tv_usec * 1000; 1595 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1596 } 1597 vput(vp); 1598 return (error); 1599} 1600 1601/* 1602 * Truncate a file given its path name. 1603 */ 1604struct truncate_args { 1605 char *path; 1606 int pad; 1607 off_t length; 1608}; 1609/* ARGSUSED */ 1610int 1611truncate(p, uap, retval) 1612 struct proc *p; 1613 register struct truncate_args *uap; 1614 int *retval; 1615{ 1616 register struct vnode *vp; 1617 struct vattr vattr; 1618 int error; 1619 struct nameidata nd; 1620 1621 if (uap->length < 0) 1622 return(EINVAL); 1623 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 1624 if (error = namei(&nd)) 1625 return (error); 1626 vp = nd.ni_vp; 1627 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1628 VOP_LOCK(vp); 1629 if (vp->v_type == VDIR) 1630 error = EISDIR; 1631 else if ((error = vn_writechk(vp)) == 0 && 1632 (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) { 1633 VATTR_NULL(&vattr); 1634 vattr.va_size = uap->length; 1635 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1636 } 1637 vput(vp); 1638 return (error); 1639} 1640 1641/* 1642 * Truncate a file given a file descriptor. 1643 */ 1644struct ftruncate_args { 1645 int fd; 1646 int pad; 1647 off_t length; 1648}; 1649/* ARGSUSED */ 1650int 1651ftruncate(p, uap, retval) 1652 struct proc *p; 1653 register struct ftruncate_args *uap; 1654 int *retval; 1655{ 1656 struct vattr vattr; 1657 struct vnode *vp; 1658 struct file *fp; 1659 int error; 1660 1661 if (uap->length < 0) 1662 return(EINVAL); 1663 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1664 return (error); 1665 if ((fp->f_flag & FWRITE) == 0) 1666 return (EINVAL); 1667 vp = (struct vnode *)fp->f_data; 1668 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1669 VOP_LOCK(vp); 1670 if (vp->v_type == VDIR) 1671 error = EISDIR; 1672 else if ((error = vn_writechk(vp)) == 0) { 1673 VATTR_NULL(&vattr); 1674 vattr.va_size = uap->length; 1675 error = VOP_SETATTR(vp, &vattr, fp->f_cred, p); 1676 } 1677 VOP_UNLOCK(vp); 1678 return (error); 1679} 1680 1681#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1682/* 1683 * Truncate a file given its path name. 1684 */ 1685struct otruncate_args { 1686 char *path; 1687 long length; 1688}; 1689/* ARGSUSED */ 1690int 1691otruncate(p, uap, retval) 1692 struct proc *p; 1693 register struct otruncate_args *uap; 1694 int *retval; 1695{ 1696 struct truncate_args nuap; 1697 1698 nuap.path = uap->path; 1699 nuap.length = uap->length; 1700 return (truncate(p, &nuap, retval)); 1701} 1702 1703/* 1704 * Truncate a file given a file descriptor. 1705 */ 1706struct oftruncate_args { 1707 int fd; 1708 long length; 1709}; 1710/* ARGSUSED */ 1711int 1712oftruncate(p, uap, retval) 1713 struct proc *p; 1714 register struct oftruncate_args *uap; 1715 int *retval; 1716{ 1717 struct ftruncate_args nuap; 1718 1719 nuap.fd = uap->fd; 1720 nuap.length = uap->length; 1721 return (ftruncate(p, &nuap, retval)); 1722} 1723#endif /* COMPAT_43 || COMPAT_SUNOS */ 1724 1725/* 1726 * Sync an open file. 1727 */ 1728struct fsync_args { 1729 int fd; 1730}; 1731/* ARGSUSED */ 1732int 1733fsync(p, uap, retval) 1734 struct proc *p; 1735 struct fsync_args *uap; 1736 int *retval; 1737{ 1738 register struct vnode *vp; 1739 struct file *fp; 1740 int error; 1741 1742 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1743 return (error); 1744 vp = (struct vnode *)fp->f_data; 1745 VOP_LOCK(vp); 1746 error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p); 1747 VOP_UNLOCK(vp); 1748 return (error); 1749} 1750 1751/* 1752 * Rename files. Source and destination must either both be directories, 1753 * or both not be directories. If target is a directory, it must be empty. 1754 */ 1755struct rename_args { 1756 char *from; 1757 char *to; 1758}; 1759/* ARGSUSED */ 1760int 1761rename(p, uap, retval) 1762 struct proc *p; 1763 register struct rename_args *uap; 1764 int *retval; 1765{ 1766 register struct vnode *tvp, *fvp, *tdvp; 1767 struct nameidata fromnd, tond; 1768 int error; 1769 1770 NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE, 1771 uap->from, p); 1772 if (error = namei(&fromnd)) 1773 return (error); 1774 fvp = fromnd.ni_vp; 1775 NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART, 1776 UIO_USERSPACE, uap->to, p); 1777 if (error = namei(&tond)) { 1778 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 1779 vrele(fromnd.ni_dvp); 1780 vrele(fvp); 1781 goto out1; 1782 } 1783 tdvp = tond.ni_dvp; 1784 tvp = tond.ni_vp; 1785 if (tvp != NULL) { 1786 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 1787 error = ENOTDIR; 1788 goto out; 1789 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 1790 error = EISDIR; 1791 goto out; 1792 } 1793 } 1794 if (fvp == tdvp) 1795 error = EINVAL; 1796 /* 1797 * If source is the same as the destination (that is the 1798 * same inode number with the same name in the same directory), 1799 * then there is nothing to do. 1800 */ 1801 if (fvp == tvp && fromnd.ni_dvp == tdvp && 1802 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen && 1803 !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr, 1804 fromnd.ni_cnd.cn_namelen)) 1805 error = -1; 1806out: 1807 if (!error) { 1808 LEASE_CHECK(tdvp, p, p->p_ucred, LEASE_WRITE); 1809 if (fromnd.ni_dvp != tdvp) 1810 LEASE_CHECK(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1811 if (tvp) 1812 LEASE_CHECK(tvp, p, p->p_ucred, LEASE_WRITE); 1813 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd, 1814 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd); 1815 } else { 1816 VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd); 1817 if (tdvp == tvp) 1818 vrele(tdvp); 1819 else 1820 vput(tdvp); 1821 if (tvp) 1822 vput(tvp); 1823 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 1824 vrele(fromnd.ni_dvp); 1825 vrele(fvp); 1826 } 1827 vrele(tond.ni_startdir); 1828 FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI); 1829out1: 1830 if (fromnd.ni_startdir) 1831 vrele(fromnd.ni_startdir); 1832 FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI); 1833 if (error == -1) 1834 return (0); 1835 return (error); 1836} 1837 1838/* 1839 * Make a directory file. 1840 */ 1841struct mkdir_args { 1842 char *path; 1843 int mode; 1844}; 1845/* ARGSUSED */ 1846int 1847mkdir(p, uap, retval) 1848 struct proc *p; 1849 register struct mkdir_args *uap; 1850 int *retval; 1851{ 1852 register struct vnode *vp; 1853 struct vattr vattr; 1854 int error; 1855 struct nameidata nd; 1856 1857 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p); 1858 if (error = namei(&nd)) 1859 return (error); 1860 vp = nd.ni_vp; 1861 if (vp != NULL) { 1862 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1863 if (nd.ni_dvp == vp) 1864 vrele(nd.ni_dvp); 1865 else 1866 vput(nd.ni_dvp); 1867 vrele(vp); 1868 return (EEXIST); 1869 } 1870 VATTR_NULL(&vattr); 1871 vattr.va_type = VDIR; 1872 vattr.va_mode = (uap->mode & ACCESSPERMS) &~ p->p_fd->fd_cmask; 1873 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1874 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 1875 if (!error) 1876 vput(nd.ni_vp); 1877 return (error); 1878} 1879 1880/* 1881 * Remove a directory file. 1882 */ 1883struct rmdir_args { 1884 char *path; 1885}; 1886/* ARGSUSED */ 1887int 1888rmdir(p, uap, retval) 1889 struct proc *p; 1890 struct rmdir_args *uap; 1891 int *retval; 1892{ 1893 register struct vnode *vp; 1894 int error; 1895 struct nameidata nd; 1896 1897 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, uap->path, p); 1898 if (error = namei(&nd)) 1899 return (error); 1900 vp = nd.ni_vp; 1901 if (vp->v_type != VDIR) { 1902 error = ENOTDIR; 1903 goto out; 1904 } 1905 /* 1906 * No rmdir "." please. 1907 */ 1908 if (nd.ni_dvp == vp) { 1909 error = EINVAL; 1910 goto out; 1911 } 1912 /* 1913 * The root of a mounted filesystem cannot be deleted. 1914 */ 1915 if (vp->v_flag & VROOT) 1916 error = EBUSY; 1917out: 1918 if (!error) { 1919 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1920 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1921 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 1922 } else { 1923 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1924 if (nd.ni_dvp == vp) 1925 vrele(nd.ni_dvp); 1926 else 1927 vput(nd.ni_dvp); 1928 vput(vp); 1929 } 1930 return (error); 1931} 1932 1933#ifdef COMPAT_43 1934/* 1935 * Read a block of directory entries in a file system independent format. 1936 */ 1937struct ogetdirentries_args { 1938 int fd; 1939 char *buf; 1940 u_int count; 1941 long *basep; 1942}; 1943int 1944ogetdirentries(p, uap, retval) 1945 struct proc *p; 1946 register struct ogetdirentries_args *uap; 1947 int *retval; 1948{ 1949 register struct vnode *vp; 1950 struct file *fp; 1951 struct uio auio, kuio; 1952 struct iovec aiov, kiov; 1953 struct dirent *dp, *edp; 1954 caddr_t dirbuf; 1955 int error, readcnt; 1956 long loff; 1957 1958 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1959 return (error); 1960 if ((fp->f_flag & FREAD) == 0) 1961 return (EBADF); 1962 vp = (struct vnode *)fp->f_data; 1963 if (vp->v_type != VDIR) 1964 return (EINVAL); 1965 aiov.iov_base = uap->buf; 1966 aiov.iov_len = uap->count; 1967 auio.uio_iov = &aiov; 1968 auio.uio_iovcnt = 1; 1969 auio.uio_rw = UIO_READ; 1970 auio.uio_segflg = UIO_USERSPACE; 1971 auio.uio_procp = p; 1972 auio.uio_resid = uap->count; 1973 VOP_LOCK(vp); 1974 loff = auio.uio_offset = fp->f_offset; 1975# if (BYTE_ORDER != LITTLE_ENDIAN) 1976 if (vp->v_mount->mnt_maxsymlinklen <= 0) { 1977 error = VOP_READDIR(vp, &auio, fp->f_cred); 1978 fp->f_offset = auio.uio_offset; 1979 } else 1980# endif 1981 { 1982 kuio = auio; 1983 kuio.uio_iov = &kiov; 1984 kuio.uio_segflg = UIO_SYSSPACE; 1985 kiov.iov_len = uap->count; 1986 MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK); 1987 kiov.iov_base = dirbuf; 1988 error = VOP_READDIR(vp, &kuio, fp->f_cred); 1989 fp->f_offset = kuio.uio_offset; 1990 if (error == 0) { 1991 readcnt = uap->count - kuio.uio_resid; 1992 edp = (struct dirent *)&dirbuf[readcnt]; 1993 for (dp = (struct dirent *)dirbuf; dp < edp; ) { 1994# if (BYTE_ORDER == LITTLE_ENDIAN) 1995 /* 1996 * The expected low byte of 1997 * dp->d_namlen is our dp->d_type. 1998 * The high MBZ byte of dp->d_namlen 1999 * is our dp->d_namlen. 2000 */ 2001 dp->d_type = dp->d_namlen; 2002 dp->d_namlen = 0; 2003# else 2004 /* 2005 * The dp->d_type is the high byte 2006 * of the expected dp->d_namlen, 2007 * so must be zero'ed. 2008 */ 2009 dp->d_type = 0; 2010# endif 2011 if (dp->d_reclen > 0) { 2012 dp = (struct dirent *) 2013 ((char *)dp + dp->d_reclen); 2014 } else { 2015 error = EIO; 2016 break; 2017 } 2018 } 2019 if (dp >= edp) 2020 error = uiomove(dirbuf, readcnt, &auio); 2021 } 2022 FREE(dirbuf, M_TEMP); 2023 } 2024 VOP_UNLOCK(vp); 2025 if (error) 2026 return (error); 2027 error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long)); 2028 *retval = uap->count - auio.uio_resid; 2029 return (error); 2030} 2031#endif 2032 2033/* 2034 * Read a block of directory entries in a file system independent format. 2035 */ 2036struct getdirentries_args { 2037 int fd; 2038 char *buf; 2039 u_int count; 2040 long *basep; 2041}; 2042int 2043getdirentries(p, uap, retval) 2044 struct proc *p; 2045 register struct getdirentries_args *uap; 2046 int *retval; 2047{ 2048 register struct vnode *vp; 2049 struct file *fp; 2050 struct uio auio; 2051 struct iovec aiov; 2052 long loff; 2053 int error; 2054 2055 if (error = getvnode(p->p_fd, uap->fd, &fp)) 2056 return (error); 2057 if ((fp->f_flag & FREAD) == 0) 2058 return (EBADF); 2059 vp = (struct vnode *)fp->f_data; 2060unionread: 2061 if (vp->v_type != VDIR) 2062 return (EINVAL); 2063 aiov.iov_base = uap->buf; 2064 aiov.iov_len = uap->count; 2065 auio.uio_iov = &aiov; 2066 auio.uio_iovcnt = 1; 2067 auio.uio_rw = UIO_READ; 2068 auio.uio_segflg = UIO_USERSPACE; 2069 auio.uio_procp = p; 2070 auio.uio_resid = uap->count; 2071 VOP_LOCK(vp); 2072 loff = auio.uio_offset = fp->f_offset; 2073 error = VOP_READDIR(vp, &auio, fp->f_cred); 2074 fp->f_offset = auio.uio_offset; 2075 VOP_UNLOCK(vp); 2076 if (error) 2077 return (error); 2078 2079#ifdef UNION 2080{ 2081 extern int (**union_vnodeop_p)(); 2082 extern struct vnode *union_lowervp __P((struct vnode *)); 2083 2084 if ((uap->count == auio.uio_resid) && 2085 (vp->v_op == union_vnodeop_p)) { 2086 struct vnode *tvp = vp; 2087 2088 vp = union_lowervp(vp); 2089 if (vp != NULLVP) { 2090 VOP_LOCK(vp); 2091 error = VOP_OPEN(vp, FREAD); 2092 VOP_UNLOCK(vp); 2093 2094 if (error) { 2095 vrele(vp); 2096 return (error); 2097 } 2098 fp->f_data = (caddr_t) vp; 2099 fp->f_offset = 0; 2100 error = vn_close(tvp, FREAD, fp->f_cred, p); 2101 if (error) 2102 return (error); 2103 goto unionread; 2104 } 2105 } 2106} 2107#endif 2108 2109 if ((uap->count == auio.uio_resid) && 2110 (vp->v_flag & VROOT) && 2111 (vp->v_mount->mnt_flag & MNT_UNION)) { 2112 struct vnode *tvp = vp; 2113 vp = vp->v_mount->mnt_vnodecovered; 2114 VREF(vp); 2115 fp->f_data = (caddr_t) vp; 2116 fp->f_offset = 0; 2117 vrele(tvp); 2118 goto unionread; 2119 } 2120 error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long)); 2121 *retval = uap->count - auio.uio_resid; 2122 return (error); 2123} 2124 2125/* 2126 * Set the mode mask for creation of filesystem nodes. 2127 */ 2128struct umask_args { 2129 int newmask; 2130}; 2131mode_t /* XXX */ 2132umask(p, uap, retval) 2133 struct proc *p; 2134 struct umask_args *uap; 2135 int *retval; 2136{ 2137 register struct filedesc *fdp; 2138 2139 fdp = p->p_fd; 2140 *retval = fdp->fd_cmask; 2141 fdp->fd_cmask = uap->newmask & ALLPERMS; 2142 return (0); 2143} 2144 2145/* 2146 * Void all references to file by ripping underlying filesystem 2147 * away from vnode. 2148 */ 2149struct revoke_args { 2150 char *path; 2151}; 2152/* ARGSUSED */ 2153int 2154revoke(p, uap, retval) 2155 struct proc *p; 2156 register struct revoke_args *uap; 2157 int *retval; 2158{ 2159 register struct vnode *vp; 2160 struct vattr vattr; 2161 int error; 2162 struct nameidata nd; 2163 2164 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 2165 if (error = namei(&nd)) 2166 return (error); 2167 vp = nd.ni_vp; 2168 if (vp->v_type != VCHR && vp->v_type != VBLK) { 2169 error = EINVAL; 2170 goto out; 2171 } 2172 if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) 2173 goto out; 2174 if (p->p_ucred->cr_uid != vattr.va_uid && 2175 (error = suser(p->p_ucred, &p->p_acflag))) 2176 goto out; 2177 if (vp->v_usecount > 1 || (vp->v_flag & VALIASED)) 2178 vgoneall(vp); 2179out: 2180 vrele(vp); 2181 return (error); 2182} 2183 2184/* 2185 * Convert a user file descriptor to a kernel file entry. 2186 */ 2187int 2188getvnode(fdp, fd, fpp) 2189 struct filedesc *fdp; 2190 struct file **fpp; 2191 int fd; 2192{ 2193 struct file *fp; 2194 2195 if ((u_int)fd >= fdp->fd_nfiles || 2196 (fp = fdp->fd_ofiles[fd]) == NULL) 2197 return (EBADF); 2198 if (fp->f_type != DTYPE_VNODE) 2199 return (EINVAL); 2200 *fpp = fp; 2201 return (0); 2202}
|