595 panic("unmount: dangling vnode"); 596 lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK, &mountlist_mtx, td); 597 lockdestroy(&mp->mnt_lock); 598 if (coveredvp != NULL) 599 vrele(coveredvp); 600 if (mp->mnt_kern_flag & MNTK_MWAIT) 601 wakeup((caddr_t)mp); 602 free((caddr_t)mp, M_MOUNT); 603 return (0); 604} 605 606/* 607 * Sync each mounted filesystem. 608 */ 609#ifndef _SYS_SYSPROTO_H_ 610struct sync_args { 611 int dummy; 612}; 613#endif 614 615#ifdef DEBUG 616static int syncprt = 0; 617SYSCTL_INT(_debug, OID_AUTO, syncprt, CTLFLAG_RW, &syncprt, 0, ""); 618#endif 619 620/* ARGSUSED */ 621int 622sync(td, uap) 623 struct thread *td; 624 struct sync_args *uap; 625{ 626 struct mount *mp, *nmp; 627 int asyncflag; 628 629 mtx_lock(&mountlist_mtx); 630 for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) { 631 if (vfs_busy(mp, LK_NOWAIT, &mountlist_mtx, td)) { 632 nmp = TAILQ_NEXT(mp, mnt_list); 633 continue; 634 } 635 if ((mp->mnt_flag & MNT_RDONLY) == 0 && 636 vn_start_write(NULL, &mp, V_NOWAIT) == 0) { 637 asyncflag = mp->mnt_flag & MNT_ASYNC; 638 mp->mnt_flag &= ~MNT_ASYNC; 639 vfs_msync(mp, MNT_NOWAIT); 640 VFS_SYNC(mp, MNT_NOWAIT, 641 ((td != NULL) ? td->td_proc->p_ucred : NOCRED), td); 642 mp->mnt_flag |= asyncflag; 643 vn_finished_write(mp); 644 } 645 mtx_lock(&mountlist_mtx); 646 nmp = TAILQ_NEXT(mp, mnt_list); 647 vfs_unbusy(mp, td); 648 } 649 mtx_unlock(&mountlist_mtx); 650#if 0 651/* 652 * XXX don't call vfs_bufstats() yet because that routine 653 * was not imported in the Lite2 merge. 654 */ 655#ifdef DIAGNOSTIC 656 if (syncprt) 657 vfs_bufstats(); 658#endif /* DIAGNOSTIC */ 659#endif 660 return (0); 661} 662 663/* XXX PRISON: could be per prison flag */ 664static int prison_quotas; 665#if 0 666SYSCTL_INT(_kern_prison, OID_AUTO, quotas, CTLFLAG_RW, &prison_quotas, 0, ""); 667#endif 668 669/* 670 * Change filesystem quotas. 671 */ 672#ifndef _SYS_SYSPROTO_H_ 673struct quotactl_args { 674 char *path; 675 int cmd; 676 int uid; 677 caddr_t arg; 678}; 679#endif 680/* ARGSUSED */ 681int 682quotactl(td, uap) 683 struct thread *td; 684 register struct quotactl_args /* { 685 syscallarg(char *) path; 686 syscallarg(int) cmd; 687 syscallarg(int) uid; 688 syscallarg(caddr_t) arg; 689 } */ *uap; 690{ 691 struct mount *mp; 692 int error; 693 struct nameidata nd; 694 695 if (jailed(td->td_proc->p_ucred) && !prison_quotas) 696 return (EPERM); 697 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 698 if ((error = namei(&nd)) != 0) 699 return (error); 700 NDFREE(&nd, NDF_ONLY_PNBUF); 701 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 702 vrele(nd.ni_vp); 703 if (error) 704 return (error); 705 error = VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid), 706 SCARG(uap, arg), td); 707 vn_finished_write(mp); 708 return (error); 709} 710 711/* 712 * Get filesystem statistics. 713 */ 714#ifndef _SYS_SYSPROTO_H_ 715struct statfs_args { 716 char *path; 717 struct statfs *buf; 718}; 719#endif 720/* ARGSUSED */ 721int 722statfs(td, uap) 723 struct thread *td; 724 register struct statfs_args /* { 725 syscallarg(char *) path; 726 syscallarg(struct statfs *) buf; 727 } */ *uap; 728{ 729 register struct mount *mp; 730 register struct statfs *sp; 731 int error; 732 struct nameidata nd; 733 struct statfs sb; 734 735 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 736 if ((error = namei(&nd)) != 0) 737 return (error); 738 mp = nd.ni_vp->v_mount; 739 sp = &mp->mnt_stat; 740 NDFREE(&nd, NDF_ONLY_PNBUF); 741 vrele(nd.ni_vp); 742 error = VFS_STATFS(mp, sp, td); 743 if (error) 744 return (error); 745 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 746 if (suser_xxx(td->td_proc->p_ucred, 0, 0)) { 747 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); 748 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; 749 sp = &sb; 750 } 751 return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp))); 752} 753 754/* 755 * Get filesystem statistics. 756 */ 757#ifndef _SYS_SYSPROTO_H_ 758struct fstatfs_args { 759 int fd; 760 struct statfs *buf; 761}; 762#endif 763/* ARGSUSED */ 764int 765fstatfs(td, uap) 766 struct thread *td; 767 register struct fstatfs_args /* { 768 syscallarg(int) fd; 769 syscallarg(struct statfs *) buf; 770 } */ *uap; 771{ 772 struct file *fp; 773 struct mount *mp; 774 register struct statfs *sp; 775 int error; 776 struct statfs sb; 777 778 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 779 return (error); 780 mp = ((struct vnode *)fp->f_data)->v_mount; 781 sp = &mp->mnt_stat; 782 error = VFS_STATFS(mp, sp, td); 783 if (error) 784 return (error); 785 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 786 if (suser_xxx(td->td_proc->p_ucred, 0, 0)) { 787 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); 788 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; 789 sp = &sb; 790 } 791 return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp))); 792} 793 794/* 795 * Get statistics on all filesystems. 796 */ 797#ifndef _SYS_SYSPROTO_H_ 798struct getfsstat_args { 799 struct statfs *buf; 800 long bufsize; 801 int flags; 802}; 803#endif 804int 805getfsstat(td, uap) 806 struct thread *td; 807 register struct getfsstat_args /* { 808 syscallarg(struct statfs *) buf; 809 syscallarg(long) bufsize; 810 syscallarg(int) flags; 811 } */ *uap; 812{ 813 register struct mount *mp, *nmp; 814 register struct statfs *sp; 815 caddr_t sfsp; 816 long count, maxcount, error; 817 818 maxcount = SCARG(uap, bufsize) / sizeof(struct statfs); 819 sfsp = (caddr_t)SCARG(uap, buf); 820 count = 0; 821 mtx_lock(&mountlist_mtx); 822 for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) { 823 if (vfs_busy(mp, LK_NOWAIT, &mountlist_mtx, td)) { 824 nmp = TAILQ_NEXT(mp, mnt_list); 825 continue; 826 } 827 if (sfsp && count < maxcount) { 828 sp = &mp->mnt_stat; 829 /* 830 * If MNT_NOWAIT or MNT_LAZY is specified, do not 831 * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY 832 * overrides MNT_WAIT. 833 */ 834 if (((SCARG(uap, flags) & (MNT_LAZY|MNT_NOWAIT)) == 0 || 835 (SCARG(uap, flags) & MNT_WAIT)) && 836 (error = VFS_STATFS(mp, sp, td))) { 837 mtx_lock(&mountlist_mtx); 838 nmp = TAILQ_NEXT(mp, mnt_list); 839 vfs_unbusy(mp, td); 840 continue; 841 } 842 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 843 error = copyout((caddr_t)sp, sfsp, sizeof(*sp)); 844 if (error) { 845 vfs_unbusy(mp, td); 846 return (error); 847 } 848 sfsp += sizeof(*sp); 849 } 850 count++; 851 mtx_lock(&mountlist_mtx); 852 nmp = TAILQ_NEXT(mp, mnt_list); 853 vfs_unbusy(mp, td); 854 } 855 mtx_unlock(&mountlist_mtx); 856 if (sfsp && count > maxcount) 857 td->td_retval[0] = maxcount; 858 else 859 td->td_retval[0] = count; 860 return (0); 861} 862 863/* 864 * Change current working directory to a given file descriptor. 865 */ 866#ifndef _SYS_SYSPROTO_H_ 867struct fchdir_args { 868 int fd; 869}; 870#endif 871/* ARGSUSED */ 872int 873fchdir(td, uap) 874 struct thread *td; 875 struct fchdir_args /* { 876 syscallarg(int) fd; 877 } */ *uap; 878{ 879 register struct filedesc *fdp = td->td_proc->p_fd; 880 struct vnode *vp, *tdp; 881 struct mount *mp; 882 struct file *fp; 883 int error; 884 885 if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0) 886 return (error); 887 vp = (struct vnode *)fp->f_data; 888 VREF(vp); 889 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 890 if (vp->v_type != VDIR) 891 error = ENOTDIR; 892 else 893 error = VOP_ACCESS(vp, VEXEC, td->td_proc->p_ucred, td); 894 while (!error && (mp = vp->v_mountedhere) != NULL) { 895 if (vfs_busy(mp, 0, 0, td)) 896 continue; 897 error = VFS_ROOT(mp, &tdp); 898 vfs_unbusy(mp, td); 899 if (error) 900 break; 901 vput(vp); 902 vp = tdp; 903 } 904 if (error) { 905 vput(vp); 906 return (error); 907 } 908 VOP_UNLOCK(vp, 0, td); 909 vrele(fdp->fd_cdir); 910 fdp->fd_cdir = vp; 911 return (0); 912} 913 914/* 915 * Change current working directory (``.''). 916 */ 917#ifndef _SYS_SYSPROTO_H_ 918struct chdir_args { 919 char *path; 920}; 921#endif 922/* ARGSUSED */ 923int 924chdir(td, uap) 925 struct thread *td; 926 struct chdir_args /* { 927 syscallarg(char *) path; 928 } */ *uap; 929{ 930 register struct filedesc *fdp = td->td_proc->p_fd; 931 int error; 932 struct nameidata nd; 933 934 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 935 SCARG(uap, path), td); 936 if ((error = change_dir(&nd, td)) != 0) 937 return (error); 938 NDFREE(&nd, NDF_ONLY_PNBUF); 939 vrele(fdp->fd_cdir); 940 fdp->fd_cdir = nd.ni_vp; 941 return (0); 942} 943 944/* 945 * Helper function for raised chroot(2) security function: Refuse if 946 * any filedescriptors are open directories. 947 */ 948static int 949chroot_refuse_vdir_fds(fdp) 950 struct filedesc *fdp; 951{ 952 struct vnode *vp; 953 struct file *fp; 954 int error; 955 int fd; 956 957 for (fd = 0; fd < fdp->fd_nfiles ; fd++) { 958 error = getvnode(fdp, fd, &fp); 959 if (error) 960 continue; 961 vp = (struct vnode *)fp->f_data; 962 if (vp->v_type != VDIR) 963 continue; 964 return(EPERM); 965 } 966 return (0); 967} 968 969/* 970 * This sysctl determines if we will allow a process to chroot(2) if it 971 * has a directory open: 972 * 0: disallowed for all processes. 973 * 1: allowed for processes that were not already chroot(2)'ed. 974 * 2: allowed for all processes. 975 */ 976 977static int chroot_allow_open_directories = 1; 978 979SYSCTL_INT(_kern, OID_AUTO, chroot_allow_open_directories, CTLFLAG_RW, 980 &chroot_allow_open_directories, 0, ""); 981 982/* 983 * Change notion of root (``/'') directory. 984 */ 985#ifndef _SYS_SYSPROTO_H_ 986struct chroot_args { 987 char *path; 988}; 989#endif 990/* ARGSUSED */ 991int 992chroot(td, uap) 993 struct thread *td; 994 struct chroot_args /* { 995 syscallarg(char *) path; 996 } */ *uap; 997{ 998 register struct filedesc *fdp = td->td_proc->p_fd; 999 int error; 1000 struct nameidata nd; 1001 1002 error = suser_xxx(0, td->td_proc, PRISON_ROOT); 1003 if (error) 1004 return (error); 1005 if (chroot_allow_open_directories == 0 || 1006 (chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode)) 1007 error = chroot_refuse_vdir_fds(fdp); 1008 if (error) 1009 return (error); 1010 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 1011 SCARG(uap, path), td); 1012 if ((error = change_dir(&nd, td)) != 0) 1013 return (error); 1014 NDFREE(&nd, NDF_ONLY_PNBUF); 1015 vrele(fdp->fd_rdir); 1016 fdp->fd_rdir = nd.ni_vp; 1017 if (!fdp->fd_jdir) { 1018 fdp->fd_jdir = nd.ni_vp; 1019 VREF(fdp->fd_jdir); 1020 } 1021 return (0); 1022} 1023 1024/* 1025 * Common routine for chroot and chdir. 1026 */ 1027static int 1028change_dir(ndp, td) 1029 register struct nameidata *ndp; 1030 struct thread *td; 1031{ 1032 struct vnode *vp; 1033 int error; 1034 1035 error = namei(ndp); 1036 if (error) 1037 return (error); 1038 vp = ndp->ni_vp; 1039 if (vp->v_type != VDIR) 1040 error = ENOTDIR; 1041 else 1042 error = VOP_ACCESS(vp, VEXEC, td->td_proc->p_ucred, td); 1043 if (error) 1044 vput(vp); 1045 else 1046 VOP_UNLOCK(vp, 0, td); 1047 return (error); 1048} 1049 1050/* 1051 * Check permissions, allocate an open file structure, 1052 * and call the device open routine if any. 1053 */ 1054#ifndef _SYS_SYSPROTO_H_ 1055struct open_args { 1056 char *path; 1057 int flags; 1058 int mode; 1059}; 1060#endif 1061int 1062open(td, uap) 1063 struct thread *td; 1064 register struct open_args /* { 1065 syscallarg(char *) path; 1066 syscallarg(int) flags; 1067 syscallarg(int) mode; 1068 } */ *uap; 1069{ 1070 struct proc *p = td->td_proc; 1071 struct filedesc *fdp = p->p_fd; 1072 struct file *fp; 1073 struct vnode *vp; 1074 struct vattr vat; 1075 struct mount *mp; 1076 int cmode, flags, oflags; 1077 struct file *nfp; 1078 int type, indx, error; 1079 struct flock lf; 1080 struct nameidata nd; 1081 1082 oflags = SCARG(uap, flags); 1083 if ((oflags & O_ACCMODE) == O_ACCMODE) 1084 return (EINVAL); 1085 flags = FFLAGS(oflags); 1086 error = falloc(td, &nfp, &indx); 1087 if (error) 1088 return (error); 1089 fp = nfp; 1090 cmode = ((SCARG(uap, mode) &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT; 1091 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 1092 td->td_dupfd = -indx - 1; /* XXX check for fdopen */ 1093 /* 1094 * Bump the ref count to prevent another process from closing 1095 * the descriptor while we are blocked in vn_open() 1096 */ 1097 fhold(fp); 1098 error = vn_open(&nd, &flags, cmode); 1099 if (error) { 1100 /* 1101 * release our own reference 1102 */ 1103 fdrop(fp, td); 1104 1105 /* 1106 * handle special fdopen() case. bleh. dupfdopen() is 1107 * responsible for dropping the old contents of ofiles[indx] 1108 * if it succeeds. 1109 */ 1110 if ((error == ENODEV || error == ENXIO) && 1111 td->td_dupfd >= 0 && /* XXX from fdopen */ 1112 (error = 1113 dupfdopen(td, fdp, indx, td->td_dupfd, flags, error)) == 0) { 1114 td->td_retval[0] = indx; 1115 return (0); 1116 } 1117 /* 1118 * Clean up the descriptor, but only if another thread hadn't 1119 * replaced or closed it. 1120 */ 1121 if (fdp->fd_ofiles[indx] == fp) { 1122 fdp->fd_ofiles[indx] = NULL; 1123 fdrop(fp, td); 1124 } 1125 1126 if (error == ERESTART) 1127 error = EINTR; 1128 return (error); 1129 } 1130 td->td_dupfd = 0; 1131 NDFREE(&nd, NDF_ONLY_PNBUF); 1132 vp = nd.ni_vp; 1133 1134 /* 1135 * There should be 2 references on the file, one from the descriptor 1136 * table, and one for us. 1137 * 1138 * Handle the case where someone closed the file (via its file 1139 * descriptor) while we were blocked. The end result should look 1140 * like opening the file succeeded but it was immediately closed. 1141 */ 1142 if (fp->f_count == 1) { 1143 KASSERT(fdp->fd_ofiles[indx] != fp, 1144 ("Open file descriptor lost all refs")); 1145 VOP_UNLOCK(vp, 0, td); 1146 vn_close(vp, flags & FMASK, fp->f_cred, td); 1147 fdrop(fp, td); 1148 td->td_retval[0] = indx; 1149 return 0; 1150 } 1151 1152 fp->f_data = (caddr_t)vp; 1153 fp->f_flag = flags & FMASK; 1154 fp->f_ops = &vnops; 1155 fp->f_type = (vp->v_type == VFIFO ? DTYPE_FIFO : DTYPE_VNODE); 1156 VOP_UNLOCK(vp, 0, td); 1157 if (flags & (O_EXLOCK | O_SHLOCK)) { 1158 lf.l_whence = SEEK_SET; 1159 lf.l_start = 0; 1160 lf.l_len = 0; 1161 if (flags & O_EXLOCK) 1162 lf.l_type = F_WRLCK; 1163 else 1164 lf.l_type = F_RDLCK; 1165 type = F_FLOCK; 1166 if ((flags & FNONBLOCK) == 0) 1167 type |= F_WAIT; 1168 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0) 1169 goto bad; 1170 fp->f_flag |= FHASLOCK; 1171 } 1172 if (flags & O_TRUNC) { 1173 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 1174 goto bad; 1175 VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE); 1176 VATTR_NULL(&vat); 1177 vat.va_size = 0; 1178 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 1179 error = VOP_SETATTR(vp, &vat, p->p_ucred, td); 1180 VOP_UNLOCK(vp, 0, td); 1181 vn_finished_write(mp); 1182 if (error) 1183 goto bad; 1184 } 1185 /* assert that vn_open created a backing object if one is needed */ 1186 KASSERT(!vn_canvmio(vp) || VOP_GETVOBJECT(vp, NULL) == 0, 1187 ("open: vmio vnode has no backing object after vn_open")); 1188 /* 1189 * Release our private reference, leaving the one associated with 1190 * the descriptor table intact. 1191 */ 1192 fdrop(fp, td); 1193 td->td_retval[0] = indx; 1194 return (0); 1195bad: 1196 if (fdp->fd_ofiles[indx] == fp) { 1197 fdp->fd_ofiles[indx] = NULL; 1198 fdrop(fp, td); 1199 } 1200 fdrop(fp, td); 1201 return (error); 1202} 1203 1204#ifdef COMPAT_43 1205/* 1206 * Create a file. 1207 */ 1208#ifndef _SYS_SYSPROTO_H_ 1209struct ocreat_args { 1210 char *path; 1211 int mode; 1212}; 1213#endif 1214int 1215ocreat(td, uap) 1216 struct thread *td; 1217 register struct ocreat_args /* { 1218 syscallarg(char *) path; 1219 syscallarg(int) mode; 1220 } */ *uap; 1221{ 1222 struct open_args /* { 1223 syscallarg(char *) path; 1224 syscallarg(int) flags; 1225 syscallarg(int) mode; 1226 } */ nuap; 1227 1228 SCARG(&nuap, path) = SCARG(uap, path); 1229 SCARG(&nuap, mode) = SCARG(uap, mode); 1230 SCARG(&nuap, flags) = O_WRONLY | O_CREAT | O_TRUNC; 1231 return (open(td, &nuap)); 1232} 1233#endif /* COMPAT_43 */ 1234 1235/* 1236 * Create a special file. 1237 */ 1238#ifndef _SYS_SYSPROTO_H_ 1239struct mknod_args { 1240 char *path; 1241 int mode; 1242 int dev; 1243}; 1244#endif 1245/* ARGSUSED */ 1246int 1247mknod(td, uap) 1248 struct thread *td; 1249 register struct mknod_args /* { 1250 syscallarg(char *) path; 1251 syscallarg(int) mode; 1252 syscallarg(int) dev; 1253 } */ *uap; 1254{ 1255 struct vnode *vp; 1256 struct mount *mp; 1257 struct vattr vattr; 1258 int error; 1259 int whiteout = 0; 1260 struct nameidata nd; 1261 1262 switch (SCARG(uap, mode) & S_IFMT) { 1263 case S_IFCHR: 1264 case S_IFBLK: 1265 error = suser_td(td); 1266 break; 1267 default: 1268 error = suser_xxx(0, td->td_proc, PRISON_ROOT); 1269 break; 1270 } 1271 if (error) 1272 return (error); 1273restart: 1274 bwillwrite(); 1275 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), td); 1276 if ((error = namei(&nd)) != 0) 1277 return (error); 1278 vp = nd.ni_vp; 1279 if (vp != NULL) { 1280 vrele(vp); 1281 error = EEXIST; 1282 } else { 1283 VATTR_NULL(&vattr); 1284 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ td->td_proc->p_fd->fd_cmask; 1285 vattr.va_rdev = SCARG(uap, dev); 1286 whiteout = 0; 1287 1288 switch (SCARG(uap, mode) & S_IFMT) { 1289 case S_IFMT: /* used by badsect to flag bad sectors */ 1290 vattr.va_type = VBAD; 1291 break; 1292 case S_IFCHR: 1293 vattr.va_type = VCHR; 1294 break; 1295 case S_IFBLK: 1296 vattr.va_type = VBLK; 1297 break; 1298 case S_IFWHT: 1299 whiteout = 1; 1300 break; 1301 default: 1302 error = EINVAL; 1303 break; 1304 } 1305 } 1306 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 1307 NDFREE(&nd, NDF_ONLY_PNBUF); 1308 vput(nd.ni_dvp); 1309 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) 1310 return (error); 1311 goto restart; 1312 } 1313 if (!error) { 1314 VOP_LEASE(nd.ni_dvp, td, td->td_proc->p_ucred, LEASE_WRITE); 1315 if (whiteout) 1316 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE); 1317 else { 1318 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, 1319 &nd.ni_cnd, &vattr); 1320 if (error == 0) 1321 vput(nd.ni_vp); 1322 } 1323 } 1324 NDFREE(&nd, NDF_ONLY_PNBUF); 1325 vput(nd.ni_dvp); 1326 vn_finished_write(mp); 1327 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mknod"); 1328 ASSERT_VOP_UNLOCKED(nd.ni_vp, "mknod"); 1329 return (error); 1330} 1331 1332/* 1333 * Create a named pipe. 1334 */ 1335#ifndef _SYS_SYSPROTO_H_ 1336struct mkfifo_args { 1337 char *path; 1338 int mode; 1339}; 1340#endif 1341/* ARGSUSED */ 1342int 1343mkfifo(td, uap) 1344 struct thread *td; 1345 register struct mkfifo_args /* { 1346 syscallarg(char *) path; 1347 syscallarg(int) mode; 1348 } */ *uap; 1349{ 1350 struct mount *mp; 1351 struct vattr vattr; 1352 int error; 1353 struct nameidata nd; 1354 1355restart: 1356 bwillwrite(); 1357 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), td); 1358 if ((error = namei(&nd)) != 0) 1359 return (error); 1360 if (nd.ni_vp != NULL) { 1361 NDFREE(&nd, NDF_ONLY_PNBUF); 1362 vrele(nd.ni_vp); 1363 vput(nd.ni_dvp); 1364 return (EEXIST); 1365 } 1366 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 1367 NDFREE(&nd, NDF_ONLY_PNBUF); 1368 vput(nd.ni_dvp); 1369 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) 1370 return (error); 1371 goto restart; 1372 } 1373 VATTR_NULL(&vattr); 1374 vattr.va_type = VFIFO; 1375 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ td->td_proc->p_fd->fd_cmask; 1376 VOP_LEASE(nd.ni_dvp, td, td->td_proc->p_ucred, LEASE_WRITE); 1377 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 1378 if (error == 0) 1379 vput(nd.ni_vp); 1380 NDFREE(&nd, NDF_ONLY_PNBUF); 1381 vput(nd.ni_dvp); 1382 vn_finished_write(mp); 1383 return (error); 1384} 1385 1386/* 1387 * Make a hard file link. 1388 */ 1389#ifndef _SYS_SYSPROTO_H_ 1390struct link_args { 1391 char *path; 1392 char *link; 1393}; 1394#endif 1395/* ARGSUSED */ 1396int 1397link(td, uap) 1398 struct thread *td; 1399 register struct link_args /* { 1400 syscallarg(char *) path; 1401 syscallarg(char *) link; 1402 } */ *uap; 1403{ 1404 struct vnode *vp; 1405 struct mount *mp; 1406 struct nameidata nd; 1407 int error; 1408 1409 bwillwrite(); 1410 NDINIT(&nd, LOOKUP, FOLLOW|NOOBJ, UIO_USERSPACE, SCARG(uap, path), td); 1411 if ((error = namei(&nd)) != 0) 1412 return (error); 1413 NDFREE(&nd, NDF_ONLY_PNBUF); 1414 vp = nd.ni_vp; 1415 if (vp->v_type == VDIR) { 1416 vrele(vp); 1417 return (EPERM); /* POSIX */ 1418 } 1419 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) { 1420 vrele(vp); 1421 return (error); 1422 } 1423 NDINIT(&nd, CREATE, LOCKPARENT|NOOBJ, UIO_USERSPACE, SCARG(uap, link), td); 1424 if ((error = namei(&nd)) == 0) { 1425 if (nd.ni_vp != NULL) { 1426 vrele(nd.ni_vp); 1427 error = EEXIST; 1428 } else { 1429 VOP_LEASE(nd.ni_dvp, td, td->td_proc->p_ucred, LEASE_WRITE); 1430 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE); 1431 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd); 1432 } 1433 NDFREE(&nd, NDF_ONLY_PNBUF); 1434 vput(nd.ni_dvp); 1435 } 1436 vrele(vp); 1437 vn_finished_write(mp); 1438 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "link"); 1439 ASSERT_VOP_UNLOCKED(nd.ni_vp, "link"); 1440 return (error); 1441} 1442 1443/* 1444 * Make a symbolic link. 1445 */ 1446#ifndef _SYS_SYSPROTO_H_ 1447struct symlink_args { 1448 char *path; 1449 char *link; 1450}; 1451#endif 1452/* ARGSUSED */ 1453int 1454symlink(td, uap) 1455 struct thread *td; 1456 register struct symlink_args /* { 1457 syscallarg(char *) path; 1458 syscallarg(char *) link; 1459 } */ *uap; 1460{ 1461 struct mount *mp; 1462 struct vattr vattr; 1463 char *path; 1464 int error; 1465 struct nameidata nd; 1466 1467 path = zalloc(namei_zone); 1468 if ((error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL)) != 0) 1469 goto out; 1470restart: 1471 bwillwrite(); 1472 NDINIT(&nd, CREATE, LOCKPARENT|NOOBJ, UIO_USERSPACE, SCARG(uap, link), td); 1473 if ((error = namei(&nd)) != 0) 1474 goto out; 1475 if (nd.ni_vp) { 1476 NDFREE(&nd, NDF_ONLY_PNBUF); 1477 vrele(nd.ni_vp); 1478 vput(nd.ni_dvp); 1479 error = EEXIST; 1480 goto out; 1481 } 1482 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 1483 NDFREE(&nd, NDF_ONLY_PNBUF); 1484 vput(nd.ni_dvp); 1485 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) 1486 return (error); 1487 goto restart; 1488 } 1489 VATTR_NULL(&vattr); 1490 vattr.va_mode = ACCESSPERMS &~ td->td_proc->p_fd->fd_cmask; 1491 VOP_LEASE(nd.ni_dvp, td, td->td_proc->p_ucred, LEASE_WRITE); 1492 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path); 1493 NDFREE(&nd, NDF_ONLY_PNBUF); 1494 if (error == 0) 1495 vput(nd.ni_vp); 1496 vput(nd.ni_dvp); 1497 vn_finished_write(mp); 1498 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "symlink"); 1499 ASSERT_VOP_UNLOCKED(nd.ni_vp, "symlink"); 1500out: 1501 zfree(namei_zone, path); 1502 return (error); 1503} 1504 1505/* 1506 * Delete a whiteout from the filesystem. 1507 */ 1508/* ARGSUSED */ 1509int 1510undelete(td, uap) 1511 struct thread *td; 1512 register struct undelete_args /* { 1513 syscallarg(char *) path; 1514 } */ *uap; 1515{ 1516 int error; 1517 struct mount *mp; 1518 struct nameidata nd; 1519 1520restart: 1521 bwillwrite(); 1522 NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE, 1523 SCARG(uap, path), td); 1524 error = namei(&nd); 1525 if (error) 1526 return (error); 1527 1528 if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) { 1529 NDFREE(&nd, NDF_ONLY_PNBUF); 1530 if (nd.ni_vp) 1531 vrele(nd.ni_vp); 1532 vput(nd.ni_dvp); 1533 return (EEXIST); 1534 } 1535 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 1536 NDFREE(&nd, NDF_ONLY_PNBUF); 1537 vput(nd.ni_dvp); 1538 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) 1539 return (error); 1540 goto restart; 1541 } 1542 VOP_LEASE(nd.ni_dvp, td, td->td_proc->p_ucred, LEASE_WRITE); 1543 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE); 1544 NDFREE(&nd, NDF_ONLY_PNBUF); 1545 vput(nd.ni_dvp); 1546 vn_finished_write(mp); 1547 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "undelete"); 1548 ASSERT_VOP_UNLOCKED(nd.ni_vp, "undelete"); 1549 return (error); 1550} 1551 1552/* 1553 * Delete a name from the filesystem. 1554 */ 1555#ifndef _SYS_SYSPROTO_H_ 1556struct unlink_args { 1557 char *path; 1558}; 1559#endif 1560/* ARGSUSED */ 1561int 1562unlink(td, uap) 1563 struct thread *td; 1564 struct unlink_args /* { 1565 syscallarg(char *) path; 1566 } */ *uap; 1567{ 1568 struct mount *mp; 1569 struct vnode *vp; 1570 int error; 1571 struct nameidata nd; 1572 1573restart: 1574 bwillwrite(); 1575 NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), td); 1576 if ((error = namei(&nd)) != 0) 1577 return (error); 1578 vp = nd.ni_vp; 1579 if (vp->v_type == VDIR) 1580 error = EPERM; /* POSIX */ 1581 else { 1582 /* 1583 * The root of a mounted filesystem cannot be deleted. 1584 * 1585 * XXX: can this only be a VDIR case? 1586 */ 1587 if (vp->v_flag & VROOT) 1588 error = EBUSY; 1589 } 1590 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 1591 NDFREE(&nd, NDF_ONLY_PNBUF); 1592 vrele(vp); 1593 vput(nd.ni_dvp); 1594 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) 1595 return (error); 1596 goto restart; 1597 } 1598 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE); 1599 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 1600 if (!error) { 1601 VOP_LEASE(nd.ni_dvp, td, td->td_proc->p_ucred, LEASE_WRITE); 1602 error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd); 1603 } 1604 NDFREE(&nd, NDF_ONLY_PNBUF); 1605 vput(nd.ni_dvp); 1606 vput(vp); 1607 vn_finished_write(mp); 1608 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "unlink"); 1609 ASSERT_VOP_UNLOCKED(nd.ni_vp, "unlink"); 1610 return (error); 1611} 1612 1613/* 1614 * Reposition read/write file offset. 1615 */ 1616#ifndef _SYS_SYSPROTO_H_ 1617struct lseek_args { 1618 int fd; 1619 int pad; 1620 off_t offset; 1621 int whence; 1622}; 1623#endif 1624int 1625lseek(td, uap) 1626 struct thread *td; 1627 register struct lseek_args /* { 1628 syscallarg(int) fd; 1629 syscallarg(int) pad; 1630 syscallarg(off_t) offset; 1631 syscallarg(int) whence; 1632 } */ *uap; 1633{ 1634 struct ucred *cred = td->td_proc->p_ucred; 1635 register struct filedesc *fdp = td->td_proc->p_fd; 1636 register struct file *fp; 1637 struct vattr vattr; 1638 struct vnode *vp; 1639 off_t offset; 1640 int error, noneg; 1641 1642 if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles || 1643 (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL) 1644 return (EBADF); 1645 if (fp->f_type != DTYPE_VNODE) 1646 return (ESPIPE); 1647 vp = (struct vnode *)fp->f_data; 1648 noneg = (vp->v_type != VCHR); 1649 offset = SCARG(uap, offset); 1650 switch (SCARG(uap, whence)) { 1651 case L_INCR: 1652 if (noneg && 1653 (fp->f_offset < 0 || 1654 (offset > 0 && fp->f_offset > OFF_MAX - offset))) 1655 return (EOVERFLOW); 1656 offset += fp->f_offset; 1657 break; 1658 case L_XTND: 1659 error = VOP_GETATTR(vp, &vattr, cred, td); 1660 if (error) 1661 return (error); 1662 if (noneg && 1663 (vattr.va_size > OFF_MAX || 1664 (offset > 0 && vattr.va_size > OFF_MAX - offset))) 1665 return (EOVERFLOW); 1666 offset += vattr.va_size; 1667 break; 1668 case L_SET: 1669 break; 1670 default: 1671 return (EINVAL); 1672 } 1673 if (noneg && offset < 0) 1674 return (EINVAL); 1675 fp->f_offset = offset; 1676 *(off_t *)(td->td_retval) = fp->f_offset; 1677 return (0); 1678} 1679 1680#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1681/* 1682 * Reposition read/write file offset. 1683 */ 1684#ifndef _SYS_SYSPROTO_H_ 1685struct olseek_args { 1686 int fd; 1687 long offset; 1688 int whence; 1689}; 1690#endif 1691int 1692olseek(td, uap) 1693 struct thread *td; 1694 register struct olseek_args /* { 1695 syscallarg(int) fd; 1696 syscallarg(long) offset; 1697 syscallarg(int) whence; 1698 } */ *uap; 1699{ 1700 struct lseek_args /* { 1701 syscallarg(int) fd; 1702 syscallarg(int) pad; 1703 syscallarg(off_t) offset; 1704 syscallarg(int) whence; 1705 } */ nuap; 1706 int error; 1707 1708 SCARG(&nuap, fd) = SCARG(uap, fd); 1709 SCARG(&nuap, offset) = SCARG(uap, offset); 1710 SCARG(&nuap, whence) = SCARG(uap, whence); 1711 error = lseek(td, &nuap); 1712 return (error); 1713} 1714#endif /* COMPAT_43 */ 1715 1716/* 1717 * Check access permissions using passed credentials. 1718 */ 1719static int 1720vn_access(vp, user_flags, cred, td) 1721 struct vnode *vp; 1722 int user_flags; 1723 struct ucred *cred; 1724 struct thread *td; 1725{ 1726 int error, flags; 1727 1728 /* Flags == 0 means only check for existence. */ 1729 error = 0; 1730 if (user_flags) { 1731 flags = 0; 1732 if (user_flags & R_OK) 1733 flags |= VREAD; 1734 if (user_flags & W_OK) 1735 flags |= VWRITE; 1736 if (user_flags & X_OK) 1737 flags |= VEXEC; 1738 if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0) 1739 error = VOP_ACCESS(vp, flags, cred, td); 1740 } 1741 return (error); 1742} 1743 1744/* 1745 * Check access permissions using "real" credentials. 1746 */ 1747#ifndef _SYS_SYSPROTO_H_ 1748struct access_args { 1749 char *path; 1750 int flags; 1751}; 1752#endif 1753int 1754access(td, uap) 1755 struct thread *td; 1756 register struct access_args /* { 1757 syscallarg(char *) path; 1758 syscallarg(int) flags; 1759 } */ *uap; 1760{ 1761 struct ucred *cred, *tmpcred; 1762 register struct vnode *vp; 1763 int error; 1764 struct nameidata nd; 1765 1766 cred = td->td_proc->p_ucred; 1767 /* 1768 * Create and modify a temporary credential instead of one that 1769 * is potentially shared. This could also mess up socket 1770 * buffer accounting which can run in an interrupt context. 1771 * 1772 * XXX - Depending on how "threads" are finally implemented, it 1773 * may be better to explicitly pass the credential to namei() 1774 * rather than to modify the potentially shared process structure. 1775 */ 1776 tmpcred = crdup(cred); 1777 tmpcred->cr_uid = cred->cr_ruid; 1778 tmpcred->cr_groups[0] = cred->cr_rgid; 1779 td->td_proc->p_ucred = tmpcred; 1780 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1781 SCARG(uap, path), td); 1782 if ((error = namei(&nd)) != 0) 1783 goto out1; 1784 vp = nd.ni_vp; 1785 1786 error = vn_access(vp, SCARG(uap, flags), tmpcred, td); 1787 NDFREE(&nd, NDF_ONLY_PNBUF); 1788 vput(vp); 1789out1: 1790 td->td_proc->p_ucred = cred; 1791 crfree(tmpcred); 1792 return (error); 1793} 1794 1795/* 1796 * Check access permissions using "effective" credentials. 1797 */ 1798#ifndef _SYS_SYSPROTO_H_ 1799struct eaccess_args { 1800 char *path; 1801 int flags; 1802}; 1803#endif 1804int 1805eaccess(td, uap) 1806 struct thread *td; 1807 register struct eaccess_args /* { 1808 syscallarg(char *) path; 1809 syscallarg(int) flags; 1810 } */ *uap; 1811{ 1812 struct nameidata nd; 1813 struct vnode *vp; 1814 int error; 1815 1816 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1817 SCARG(uap, path), td); 1818 if ((error = namei(&nd)) != 0) 1819 return (error); 1820 vp = nd.ni_vp; 1821 1822 error = vn_access(vp, SCARG(uap, flags), td->td_proc->p_ucred, td); 1823 NDFREE(&nd, NDF_ONLY_PNBUF); 1824 vput(vp); 1825 return (error); 1826} 1827 1828#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1829/* 1830 * Get file status; this version follows links. 1831 */ 1832#ifndef _SYS_SYSPROTO_H_ 1833struct ostat_args { 1834 char *path; 1835 struct ostat *ub; 1836}; 1837#endif 1838/* ARGSUSED */ 1839int 1840ostat(td, uap) 1841 struct thread *td; 1842 register struct ostat_args /* { 1843 syscallarg(char *) path; 1844 syscallarg(struct ostat *) ub; 1845 } */ *uap; 1846{ 1847 struct stat sb; 1848 struct ostat osb; 1849 int error; 1850 struct nameidata nd; 1851 1852 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1853 SCARG(uap, path), td); 1854 if ((error = namei(&nd)) != 0) 1855 return (error); 1856 NDFREE(&nd, NDF_ONLY_PNBUF); 1857 error = vn_stat(nd.ni_vp, &sb, td); 1858 vput(nd.ni_vp); 1859 if (error) 1860 return (error); 1861 cvtstat(&sb, &osb); 1862 error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb)); 1863 return (error); 1864} 1865 1866/* 1867 * Get file status; this version does not follow links. 1868 */ 1869#ifndef _SYS_SYSPROTO_H_ 1870struct olstat_args { 1871 char *path; 1872 struct ostat *ub; 1873}; 1874#endif 1875/* ARGSUSED */ 1876int 1877olstat(td, uap) 1878 struct thread *td; 1879 register struct olstat_args /* { 1880 syscallarg(char *) path; 1881 syscallarg(struct ostat *) ub; 1882 } */ *uap; 1883{ 1884 struct vnode *vp; 1885 struct stat sb; 1886 struct ostat osb; 1887 int error; 1888 struct nameidata nd; 1889 1890 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1891 SCARG(uap, path), td); 1892 if ((error = namei(&nd)) != 0) 1893 return (error); 1894 vp = nd.ni_vp; 1895 error = vn_stat(vp, &sb, td); 1896 NDFREE(&nd, NDF_ONLY_PNBUF); 1897 vput(vp); 1898 if (error) 1899 return (error); 1900 cvtstat(&sb, &osb); 1901 error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb)); 1902 return (error); 1903} 1904 1905/* 1906 * Convert from an old to a new stat structure. 1907 */ 1908void 1909cvtstat(st, ost) 1910 struct stat *st; 1911 struct ostat *ost; 1912{ 1913 1914 ost->st_dev = st->st_dev; 1915 ost->st_ino = st->st_ino; 1916 ost->st_mode = st->st_mode; 1917 ost->st_nlink = st->st_nlink; 1918 ost->st_uid = st->st_uid; 1919 ost->st_gid = st->st_gid; 1920 ost->st_rdev = st->st_rdev; 1921 if (st->st_size < (quad_t)1 << 32) 1922 ost->st_size = st->st_size; 1923 else 1924 ost->st_size = -2; 1925 ost->st_atime = st->st_atime; 1926 ost->st_mtime = st->st_mtime; 1927 ost->st_ctime = st->st_ctime; 1928 ost->st_blksize = st->st_blksize; 1929 ost->st_blocks = st->st_blocks; 1930 ost->st_flags = st->st_flags; 1931 ost->st_gen = st->st_gen; 1932} 1933#endif /* COMPAT_43 || COMPAT_SUNOS */ 1934 1935/* 1936 * Get file status; this version follows links. 1937 */ 1938#ifndef _SYS_SYSPROTO_H_ 1939struct stat_args { 1940 char *path; 1941 struct stat *ub; 1942}; 1943#endif 1944/* ARGSUSED */ 1945int 1946stat(td, uap) 1947 struct thread *td; 1948 register struct stat_args /* { 1949 syscallarg(char *) path; 1950 syscallarg(struct stat *) ub; 1951 } */ *uap; 1952{ 1953 struct stat sb; 1954 int error; 1955 struct nameidata nd; 1956 1957 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1958 SCARG(uap, path), td); 1959 if ((error = namei(&nd)) != 0) 1960 return (error); 1961 error = vn_stat(nd.ni_vp, &sb, td); 1962 NDFREE(&nd, NDF_ONLY_PNBUF); 1963 vput(nd.ni_vp); 1964 if (error) 1965 return (error); 1966 error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb)); 1967 return (error); 1968} 1969 1970/* 1971 * Get file status; this version does not follow links. 1972 */ 1973#ifndef _SYS_SYSPROTO_H_ 1974struct lstat_args { 1975 char *path; 1976 struct stat *ub; 1977}; 1978#endif 1979/* ARGSUSED */ 1980int 1981lstat(td, uap) 1982 struct thread *td; 1983 register struct lstat_args /* { 1984 syscallarg(char *) path; 1985 syscallarg(struct stat *) ub; 1986 } */ *uap; 1987{ 1988 int error; 1989 struct vnode *vp; 1990 struct stat sb; 1991 struct nameidata nd; 1992 1993 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1994 SCARG(uap, path), td); 1995 if ((error = namei(&nd)) != 0) 1996 return (error); 1997 vp = nd.ni_vp; 1998 error = vn_stat(vp, &sb, td); 1999 NDFREE(&nd, NDF_ONLY_PNBUF); 2000 vput(vp); 2001 if (error) 2002 return (error); 2003 error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb)); 2004 return (error); 2005} 2006 2007/* 2008 * Implementation of the NetBSD stat() function. 2009 * XXX This should probably be collapsed with the FreeBSD version, 2010 * as the differences are only due to vn_stat() clearing spares at 2011 * the end of the structures. vn_stat could be split to avoid this, 2012 * and thus collapse the following to close to zero code. 2013 */ 2014void 2015cvtnstat(sb, nsb) 2016 struct stat *sb; 2017 struct nstat *nsb; 2018{ 2019 nsb->st_dev = sb->st_dev; 2020 nsb->st_ino = sb->st_ino; 2021 nsb->st_mode = sb->st_mode; 2022 nsb->st_nlink = sb->st_nlink; 2023 nsb->st_uid = sb->st_uid; 2024 nsb->st_gid = sb->st_gid; 2025 nsb->st_rdev = sb->st_rdev; 2026 nsb->st_atimespec = sb->st_atimespec; 2027 nsb->st_mtimespec = sb->st_mtimespec; 2028 nsb->st_ctimespec = sb->st_ctimespec; 2029 nsb->st_size = sb->st_size; 2030 nsb->st_blocks = sb->st_blocks; 2031 nsb->st_blksize = sb->st_blksize; 2032 nsb->st_flags = sb->st_flags; 2033 nsb->st_gen = sb->st_gen; 2034 nsb->st_qspare[0] = sb->st_qspare[0]; 2035 nsb->st_qspare[1] = sb->st_qspare[1]; 2036} 2037 2038#ifndef _SYS_SYSPROTO_H_ 2039struct nstat_args { 2040 char *path; 2041 struct nstat *ub; 2042}; 2043#endif 2044/* ARGSUSED */ 2045int 2046nstat(td, uap) 2047 struct thread *td; 2048 register struct nstat_args /* { 2049 syscallarg(char *) path; 2050 syscallarg(struct nstat *) ub; 2051 } */ *uap; 2052{ 2053 struct stat sb; 2054 struct nstat nsb; 2055 int error; 2056 struct nameidata nd; 2057 2058 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 2059 SCARG(uap, path), td); 2060 if ((error = namei(&nd)) != 0) 2061 return (error); 2062 NDFREE(&nd, NDF_ONLY_PNBUF); 2063 error = vn_stat(nd.ni_vp, &sb, td); 2064 vput(nd.ni_vp); 2065 if (error) 2066 return (error); 2067 cvtnstat(&sb, &nsb); 2068 error = copyout((caddr_t)&nsb, (caddr_t)SCARG(uap, ub), sizeof (nsb)); 2069 return (error); 2070} 2071 2072/* 2073 * NetBSD lstat. Get file status; this version does not follow links. 2074 */ 2075#ifndef _SYS_SYSPROTO_H_ 2076struct lstat_args { 2077 char *path; 2078 struct stat *ub; 2079}; 2080#endif 2081/* ARGSUSED */ 2082int 2083nlstat(td, uap) 2084 struct thread *td; 2085 register struct nlstat_args /* { 2086 syscallarg(char *) path; 2087 syscallarg(struct nstat *) ub; 2088 } */ *uap; 2089{ 2090 int error; 2091 struct vnode *vp; 2092 struct stat sb; 2093 struct nstat nsb; 2094 struct nameidata nd; 2095 2096 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 2097 SCARG(uap, path), td); 2098 if ((error = namei(&nd)) != 0) 2099 return (error); 2100 vp = nd.ni_vp; 2101 NDFREE(&nd, NDF_ONLY_PNBUF); 2102 error = vn_stat(vp, &sb, td); 2103 vput(vp); 2104 if (error) 2105 return (error); 2106 cvtnstat(&sb, &nsb); 2107 error = copyout((caddr_t)&nsb, (caddr_t)SCARG(uap, ub), sizeof (nsb)); 2108 return (error); 2109} 2110 2111/* 2112 * Get configurable pathname variables. 2113 */ 2114#ifndef _SYS_SYSPROTO_H_ 2115struct pathconf_args { 2116 char *path; 2117 int name; 2118}; 2119#endif 2120/* ARGSUSED */ 2121int 2122pathconf(td, uap) 2123 struct thread *td; 2124 register struct pathconf_args /* { 2125 syscallarg(char *) path; 2126 syscallarg(int) name; 2127 } */ *uap; 2128{ 2129 int error; 2130 struct nameidata nd; 2131 2132 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 2133 SCARG(uap, path), td); 2134 if ((error = namei(&nd)) != 0) 2135 return (error); 2136 NDFREE(&nd, NDF_ONLY_PNBUF); 2137 error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), td->td_retval); 2138 vput(nd.ni_vp); 2139 return (error); 2140} 2141 2142/* 2143 * Return target name of a symbolic link. 2144 */ 2145#ifndef _SYS_SYSPROTO_H_ 2146struct readlink_args { 2147 char *path; 2148 char *buf; 2149 int count; 2150}; 2151#endif 2152/* ARGSUSED */ 2153int 2154readlink(td, uap) 2155 struct thread *td; 2156 register struct readlink_args /* { 2157 syscallarg(char *) path; 2158 syscallarg(char *) buf; 2159 syscallarg(int) count; 2160 } */ *uap; 2161{ 2162 register struct vnode *vp; 2163 struct iovec aiov; 2164 struct uio auio; 2165 int error; 2166 struct nameidata nd; 2167 2168 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 2169 SCARG(uap, path), td); 2170 if ((error = namei(&nd)) != 0) 2171 return (error); 2172 NDFREE(&nd, NDF_ONLY_PNBUF); 2173 vp = nd.ni_vp; 2174 if (vp->v_type != VLNK) 2175 error = EINVAL; 2176 else { 2177 aiov.iov_base = SCARG(uap, buf); 2178 aiov.iov_len = SCARG(uap, count); 2179 auio.uio_iov = &aiov; 2180 auio.uio_iovcnt = 1; 2181 auio.uio_offset = 0; 2182 auio.uio_rw = UIO_READ; 2183 auio.uio_segflg = UIO_USERSPACE; 2184 auio.uio_td = td; 2185 auio.uio_resid = SCARG(uap, count); 2186 error = VOP_READLINK(vp, &auio, td->td_proc->p_ucred); 2187 } 2188 vput(vp); 2189 td->td_retval[0] = SCARG(uap, count) - auio.uio_resid; 2190 return (error); 2191} 2192 2193/* 2194 * Common implementation code for chflags() and fchflags(). 2195 */ 2196static int 2197setfflags(td, vp, flags) 2198 struct thread *td; 2199 struct vnode *vp; 2200 int flags; 2201{ 2202 int error; 2203 struct mount *mp; 2204 struct vattr vattr; 2205 2206 /* 2207 * Prevent non-root users from setting flags on devices. When 2208 * a device is reused, users can retain ownership of the device 2209 * if they are allowed to set flags and programs assume that 2210 * chown can't fail when done as root. 2211 */ 2212 if (vp->v_type == VCHR || vp->v_type == VBLK) { 2213 error = suser_xxx(td->td_proc->p_ucred, td->td_proc, 2214 PRISON_ROOT); 2215 if (error) 2216 return (error); 2217 } 2218 2219 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 2220 return (error); 2221 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE); 2222 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2223 VATTR_NULL(&vattr); 2224 vattr.va_flags = flags; 2225 error = VOP_SETATTR(vp, &vattr, td->td_proc->p_ucred, td); 2226 VOP_UNLOCK(vp, 0, td); 2227 vn_finished_write(mp); 2228 return (error); 2229} 2230 2231/* 2232 * Change flags of a file given a path name. 2233 */ 2234#ifndef _SYS_SYSPROTO_H_ 2235struct chflags_args { 2236 char *path; 2237 int flags; 2238}; 2239#endif 2240/* ARGSUSED */ 2241int 2242chflags(td, uap) 2243 struct thread *td; 2244 register struct chflags_args /* { 2245 syscallarg(char *) path; 2246 syscallarg(int) flags; 2247 } */ *uap; 2248{ 2249 int error; 2250 struct nameidata nd; 2251 2252 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 2253 if ((error = namei(&nd)) != 0) 2254 return (error); 2255 NDFREE(&nd, NDF_ONLY_PNBUF); 2256 error = setfflags(td, nd.ni_vp, SCARG(uap, flags)); 2257 vrele(nd.ni_vp); 2258 return error; 2259} 2260 2261/* 2262 * Change flags of a file given a file descriptor. 2263 */ 2264#ifndef _SYS_SYSPROTO_H_ 2265struct fchflags_args { 2266 int fd; 2267 int flags; 2268}; 2269#endif 2270/* ARGSUSED */ 2271int 2272fchflags(td, uap) 2273 struct thread *td; 2274 register struct fchflags_args /* { 2275 syscallarg(int) fd; 2276 syscallarg(int) flags; 2277 } */ *uap; 2278{ 2279 struct file *fp; 2280 int error; 2281 2282 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 2283 return (error); 2284 return setfflags(td, (struct vnode *) fp->f_data, SCARG(uap, flags)); 2285} 2286 2287/* 2288 * Common implementation code for chmod(), lchmod() and fchmod(). 2289 */ 2290static int 2291setfmode(td, vp, mode) 2292 struct thread *td; 2293 struct vnode *vp; 2294 int mode; 2295{ 2296 int error; 2297 struct mount *mp; 2298 struct vattr vattr; 2299 2300 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 2301 return (error); 2302 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE); 2303 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2304 VATTR_NULL(&vattr); 2305 vattr.va_mode = mode & ALLPERMS; 2306 error = VOP_SETATTR(vp, &vattr, td->td_proc->p_ucred, td); 2307 VOP_UNLOCK(vp, 0, td); 2308 vn_finished_write(mp); 2309 return error; 2310} 2311 2312/* 2313 * Change mode of a file given path name. 2314 */ 2315#ifndef _SYS_SYSPROTO_H_ 2316struct chmod_args { 2317 char *path; 2318 int mode; 2319}; 2320#endif 2321/* ARGSUSED */ 2322int 2323chmod(td, uap) 2324 struct thread *td; 2325 register struct chmod_args /* { 2326 syscallarg(char *) path; 2327 syscallarg(int) mode; 2328 } */ *uap; 2329{ 2330 int error; 2331 struct nameidata nd; 2332 2333 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 2334 if ((error = namei(&nd)) != 0) 2335 return (error); 2336 NDFREE(&nd, NDF_ONLY_PNBUF); 2337 error = setfmode(td, nd.ni_vp, SCARG(uap, mode)); 2338 vrele(nd.ni_vp); 2339 return error; 2340} 2341 2342/* 2343 * Change mode of a file given path name (don't follow links.) 2344 */ 2345#ifndef _SYS_SYSPROTO_H_ 2346struct lchmod_args { 2347 char *path; 2348 int mode; 2349}; 2350#endif 2351/* ARGSUSED */ 2352int 2353lchmod(td, uap) 2354 struct thread *td; 2355 register struct lchmod_args /* { 2356 syscallarg(char *) path; 2357 syscallarg(int) mode; 2358 } */ *uap; 2359{ 2360 int error; 2361 struct nameidata nd; 2362 2363 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 2364 if ((error = namei(&nd)) != 0) 2365 return (error); 2366 NDFREE(&nd, NDF_ONLY_PNBUF); 2367 error = setfmode(td, nd.ni_vp, SCARG(uap, mode)); 2368 vrele(nd.ni_vp); 2369 return error; 2370} 2371 2372/* 2373 * Change mode of a file given a file descriptor. 2374 */ 2375#ifndef _SYS_SYSPROTO_H_ 2376struct fchmod_args { 2377 int fd; 2378 int mode; 2379}; 2380#endif 2381/* ARGSUSED */ 2382int 2383fchmod(td, uap) 2384 struct thread *td; 2385 register struct fchmod_args /* { 2386 syscallarg(int) fd; 2387 syscallarg(int) mode; 2388 } */ *uap; 2389{ 2390 struct file *fp; 2391 int error; 2392 2393 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 2394 return (error); 2395 return setfmode(td, (struct vnode *)fp->f_data, SCARG(uap, mode)); 2396} 2397 2398/* 2399 * Common implementation for chown(), lchown(), and fchown() 2400 */ 2401static int 2402setfown(td, vp, uid, gid) 2403 struct thread *td; 2404 struct vnode *vp; 2405 uid_t uid; 2406 gid_t gid; 2407{ 2408 int error; 2409 struct mount *mp; 2410 struct vattr vattr; 2411 2412 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 2413 return (error); 2414 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE); 2415 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2416 VATTR_NULL(&vattr); 2417 vattr.va_uid = uid; 2418 vattr.va_gid = gid; 2419 error = VOP_SETATTR(vp, &vattr, td->td_proc->p_ucred, td); 2420 VOP_UNLOCK(vp, 0, td); 2421 vn_finished_write(mp); 2422 return error; 2423} 2424 2425/* 2426 * Set ownership given a path name. 2427 */ 2428#ifndef _SYS_SYSPROTO_H_ 2429struct chown_args { 2430 char *path; 2431 int uid; 2432 int gid; 2433}; 2434#endif 2435/* ARGSUSED */ 2436int 2437chown(td, uap) 2438 struct thread *td; 2439 register struct chown_args /* { 2440 syscallarg(char *) path; 2441 syscallarg(int) uid; 2442 syscallarg(int) gid; 2443 } */ *uap; 2444{ 2445 int error; 2446 struct nameidata nd; 2447 2448 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 2449 if ((error = namei(&nd)) != 0) 2450 return (error); 2451 NDFREE(&nd, NDF_ONLY_PNBUF); 2452 error = setfown(td, nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid)); 2453 vrele(nd.ni_vp); 2454 return (error); 2455} 2456 2457/* 2458 * Set ownership given a path name, do not cross symlinks. 2459 */ 2460#ifndef _SYS_SYSPROTO_H_ 2461struct lchown_args { 2462 char *path; 2463 int uid; 2464 int gid; 2465}; 2466#endif 2467/* ARGSUSED */ 2468int 2469lchown(td, uap) 2470 struct thread *td; 2471 register struct lchown_args /* { 2472 syscallarg(char *) path; 2473 syscallarg(int) uid; 2474 syscallarg(int) gid; 2475 } */ *uap; 2476{ 2477 int error; 2478 struct nameidata nd; 2479 2480 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 2481 if ((error = namei(&nd)) != 0) 2482 return (error); 2483 NDFREE(&nd, NDF_ONLY_PNBUF); 2484 error = setfown(td, nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid)); 2485 vrele(nd.ni_vp); 2486 return (error); 2487} 2488 2489/* 2490 * Set ownership given a file descriptor. 2491 */ 2492#ifndef _SYS_SYSPROTO_H_ 2493struct fchown_args { 2494 int fd; 2495 int uid; 2496 int gid; 2497}; 2498#endif 2499/* ARGSUSED */ 2500int 2501fchown(td, uap) 2502 struct thread *td; 2503 register struct fchown_args /* { 2504 syscallarg(int) fd; 2505 syscallarg(int) uid; 2506 syscallarg(int) gid; 2507 } */ *uap; 2508{ 2509 struct file *fp; 2510 int error; 2511 2512 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 2513 return (error); 2514 return setfown(td, (struct vnode *)fp->f_data, 2515 SCARG(uap, uid), SCARG(uap, gid)); 2516} 2517 2518/* 2519 * Common implementation code for utimes(), lutimes(), and futimes(). 2520 */ 2521static int 2522getutimes(usrtvp, tsp) 2523 const struct timeval *usrtvp; 2524 struct timespec *tsp; 2525{ 2526 struct timeval tv[2]; 2527 int error; 2528 2529 if (usrtvp == NULL) { 2530 microtime(&tv[0]); 2531 TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]); 2532 tsp[1] = tsp[0]; 2533 } else { 2534 if ((error = copyin(usrtvp, tv, sizeof (tv))) != 0) 2535 return (error); 2536 TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]); 2537 TIMEVAL_TO_TIMESPEC(&tv[1], &tsp[1]); 2538 } 2539 return 0; 2540} 2541 2542/* 2543 * Common implementation code for utimes(), lutimes(), and futimes(). 2544 */ 2545static int 2546setutimes(td, vp, ts, nullflag) 2547 struct thread *td; 2548 struct vnode *vp; 2549 const struct timespec *ts; 2550 int nullflag; 2551{ 2552 int error; 2553 struct mount *mp; 2554 struct vattr vattr; 2555 2556 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 2557 return (error); 2558 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE); 2559 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2560 VATTR_NULL(&vattr); 2561 vattr.va_atime = ts[0]; 2562 vattr.va_mtime = ts[1]; 2563 if (nullflag) 2564 vattr.va_vaflags |= VA_UTIMES_NULL; 2565 error = VOP_SETATTR(vp, &vattr, td->td_proc->p_ucred, td); 2566 VOP_UNLOCK(vp, 0, td); 2567 vn_finished_write(mp); 2568 return error; 2569} 2570 2571/* 2572 * Set the access and modification times of a file. 2573 */ 2574#ifndef _SYS_SYSPROTO_H_ 2575struct utimes_args { 2576 char *path; 2577 struct timeval *tptr; 2578}; 2579#endif 2580/* ARGSUSED */ 2581int 2582utimes(td, uap) 2583 struct thread *td; 2584 register struct utimes_args /* { 2585 syscallarg(char *) path; 2586 syscallarg(struct timeval *) tptr; 2587 } */ *uap; 2588{ 2589 struct timespec ts[2]; 2590 struct timeval *usrtvp; 2591 int error; 2592 struct nameidata nd; 2593 2594 usrtvp = SCARG(uap, tptr); 2595 if ((error = getutimes(usrtvp, ts)) != 0) 2596 return (error); 2597 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 2598 if ((error = namei(&nd)) != 0) 2599 return (error); 2600 NDFREE(&nd, NDF_ONLY_PNBUF); 2601 error = setutimes(td, nd.ni_vp, ts, usrtvp == NULL); 2602 vrele(nd.ni_vp); 2603 return (error); 2604} 2605 2606/* 2607 * Set the access and modification times of a file. 2608 */ 2609#ifndef _SYS_SYSPROTO_H_ 2610struct lutimes_args { 2611 char *path; 2612 struct timeval *tptr; 2613}; 2614#endif 2615/* ARGSUSED */ 2616int 2617lutimes(td, uap) 2618 struct thread *td; 2619 register struct lutimes_args /* { 2620 syscallarg(char *) path; 2621 syscallarg(struct timeval *) tptr; 2622 } */ *uap; 2623{ 2624 struct timespec ts[2]; 2625 struct timeval *usrtvp; 2626 int error; 2627 struct nameidata nd; 2628 2629 usrtvp = SCARG(uap, tptr); 2630 if ((error = getutimes(usrtvp, ts)) != 0) 2631 return (error); 2632 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 2633 if ((error = namei(&nd)) != 0) 2634 return (error); 2635 NDFREE(&nd, NDF_ONLY_PNBUF); 2636 error = setutimes(td, nd.ni_vp, ts, usrtvp == NULL); 2637 vrele(nd.ni_vp); 2638 return (error); 2639} 2640 2641/* 2642 * Set the access and modification times of a file. 2643 */ 2644#ifndef _SYS_SYSPROTO_H_ 2645struct futimes_args { 2646 int fd; 2647 struct timeval *tptr; 2648}; 2649#endif 2650/* ARGSUSED */ 2651int 2652futimes(td, uap) 2653 struct thread *td; 2654 register struct futimes_args /* { 2655 syscallarg(int ) fd; 2656 syscallarg(struct timeval *) tptr; 2657 } */ *uap; 2658{ 2659 struct timespec ts[2]; 2660 struct file *fp; 2661 struct timeval *usrtvp; 2662 int error; 2663 2664 usrtvp = SCARG(uap, tptr); 2665 if ((error = getutimes(usrtvp, ts)) != 0) 2666 return (error); 2667 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 2668 return (error); 2669 return setutimes(td, (struct vnode *)fp->f_data, ts, usrtvp == NULL); 2670} 2671 2672/* 2673 * Truncate a file given its path name. 2674 */ 2675#ifndef _SYS_SYSPROTO_H_ 2676struct truncate_args { 2677 char *path; 2678 int pad; 2679 off_t length; 2680}; 2681#endif 2682/* ARGSUSED */ 2683int 2684truncate(td, uap) 2685 struct thread *td; 2686 register struct truncate_args /* { 2687 syscallarg(char *) path; 2688 syscallarg(int) pad; 2689 syscallarg(off_t) length; 2690 } */ *uap; 2691{ 2692 struct mount *mp; 2693 struct vnode *vp; 2694 struct vattr vattr; 2695 int error; 2696 struct nameidata nd; 2697 2698 if (uap->length < 0) 2699 return(EINVAL); 2700 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 2701 if ((error = namei(&nd)) != 0) 2702 return (error); 2703 vp = nd.ni_vp; 2704 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) { 2705 vrele(vp); 2706 return (error); 2707 } 2708 NDFREE(&nd, NDF_ONLY_PNBUF); 2709 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE); 2710 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2711 if (vp->v_type == VDIR) 2712 error = EISDIR; 2713 else if ((error = vn_writechk(vp)) == 0 && 2714 (error = VOP_ACCESS(vp, VWRITE, td->td_proc->p_ucred, td)) == 0) { 2715 VATTR_NULL(&vattr); 2716 vattr.va_size = SCARG(uap, length); 2717 error = VOP_SETATTR(vp, &vattr, td->td_proc->p_ucred, td); 2718 } 2719 vput(vp); 2720 vn_finished_write(mp); 2721 return (error); 2722} 2723 2724/* 2725 * Truncate a file given a file descriptor. 2726 */ 2727#ifndef _SYS_SYSPROTO_H_ 2728struct ftruncate_args { 2729 int fd; 2730 int pad; 2731 off_t length; 2732}; 2733#endif 2734/* ARGSUSED */ 2735int 2736ftruncate(td, uap) 2737 struct thread *td; 2738 register struct ftruncate_args /* { 2739 syscallarg(int) fd; 2740 syscallarg(int) pad; 2741 syscallarg(off_t) length; 2742 } */ *uap; 2743{ 2744 struct mount *mp; 2745 struct vattr vattr; 2746 struct vnode *vp; 2747 struct file *fp; 2748 int error; 2749 2750 if (uap->length < 0) 2751 return(EINVAL); 2752 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 2753 return (error); 2754 if ((fp->f_flag & FWRITE) == 0) 2755 return (EINVAL); 2756 vp = (struct vnode *)fp->f_data; 2757 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 2758 return (error); 2759 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE); 2760 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2761 if (vp->v_type == VDIR) 2762 error = EISDIR; 2763 else if ((error = vn_writechk(vp)) == 0) { 2764 VATTR_NULL(&vattr); 2765 vattr.va_size = SCARG(uap, length); 2766 error = VOP_SETATTR(vp, &vattr, fp->f_cred, td); 2767 } 2768 VOP_UNLOCK(vp, 0, td); 2769 vn_finished_write(mp); 2770 return (error); 2771} 2772 2773#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 2774/* 2775 * Truncate a file given its path name. 2776 */ 2777#ifndef _SYS_SYSPROTO_H_ 2778struct otruncate_args { 2779 char *path; 2780 long length; 2781}; 2782#endif 2783/* ARGSUSED */ 2784int 2785otruncate(td, uap) 2786 struct thread *td; 2787 register struct otruncate_args /* { 2788 syscallarg(char *) path; 2789 syscallarg(long) length; 2790 } */ *uap; 2791{ 2792 struct truncate_args /* { 2793 syscallarg(char *) path; 2794 syscallarg(int) pad; 2795 syscallarg(off_t) length; 2796 } */ nuap; 2797 2798 SCARG(&nuap, path) = SCARG(uap, path); 2799 SCARG(&nuap, length) = SCARG(uap, length); 2800 return (truncate(td, &nuap)); 2801} 2802 2803/* 2804 * Truncate a file given a file descriptor. 2805 */ 2806#ifndef _SYS_SYSPROTO_H_ 2807struct oftruncate_args { 2808 int fd; 2809 long length; 2810}; 2811#endif 2812/* ARGSUSED */ 2813int 2814oftruncate(td, uap) 2815 struct thread *td; 2816 register struct oftruncate_args /* { 2817 syscallarg(int) fd; 2818 syscallarg(long) length; 2819 } */ *uap; 2820{ 2821 struct ftruncate_args /* { 2822 syscallarg(int) fd; 2823 syscallarg(int) pad; 2824 syscallarg(off_t) length; 2825 } */ nuap; 2826 2827 SCARG(&nuap, fd) = SCARG(uap, fd); 2828 SCARG(&nuap, length) = SCARG(uap, length); 2829 return (ftruncate(td, &nuap)); 2830} 2831#endif /* COMPAT_43 || COMPAT_SUNOS */ 2832 2833/* 2834 * Sync an open file. 2835 */ 2836#ifndef _SYS_SYSPROTO_H_ 2837struct fsync_args { 2838 int fd; 2839}; 2840#endif 2841/* ARGSUSED */ 2842int 2843fsync(td, uap) 2844 struct thread *td; 2845 struct fsync_args /* { 2846 syscallarg(int) fd; 2847 } */ *uap; 2848{ 2849 struct vnode *vp; 2850 struct mount *mp; 2851 struct file *fp; 2852 vm_object_t obj; 2853 int error; 2854 2855 GIANT_REQUIRED; 2856 2857 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 2858 return (error); 2859 vp = (struct vnode *)fp->f_data; 2860 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 2861 return (error); 2862 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2863 if (VOP_GETVOBJECT(vp, &obj) == 0) { 2864 vm_object_page_clean(obj, 0, 0, 0); 2865 } 2866 error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, td); 2867#ifdef SOFTUPDATES 2868 if (error == 0 && vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP)) 2869 error = softdep_fsync(vp); 2870#endif 2871 2872 VOP_UNLOCK(vp, 0, td); 2873 vn_finished_write(mp); 2874 return (error); 2875} 2876 2877/* 2878 * Rename files. Source and destination must either both be directories, 2879 * or both not be directories. If target is a directory, it must be empty. 2880 */ 2881#ifndef _SYS_SYSPROTO_H_ 2882struct rename_args { 2883 char *from; 2884 char *to; 2885}; 2886#endif 2887/* ARGSUSED */ 2888int 2889rename(td, uap) 2890 struct thread *td; 2891 register struct rename_args /* { 2892 syscallarg(char *) from; 2893 syscallarg(char *) to; 2894 } */ *uap; 2895{ 2896 struct mount *mp; 2897 struct vnode *tvp, *fvp, *tdvp; 2898 struct nameidata fromnd, tond; 2899 int error; 2900 2901 bwillwrite(); 2902 NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE, 2903 SCARG(uap, from), td); 2904 if ((error = namei(&fromnd)) != 0) 2905 return (error); 2906 fvp = fromnd.ni_vp; 2907 if ((error = vn_start_write(fvp, &mp, V_WAIT | PCATCH)) != 0) { 2908 NDFREE(&fromnd, NDF_ONLY_PNBUF); 2909 vrele(fromnd.ni_dvp); 2910 vrele(fvp); 2911 goto out1; 2912 } 2913 NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART | NOOBJ, 2914 UIO_USERSPACE, SCARG(uap, to), td); 2915 if (fromnd.ni_vp->v_type == VDIR) 2916 tond.ni_cnd.cn_flags |= WILLBEDIR; 2917 if ((error = namei(&tond)) != 0) { 2918 /* Translate error code for rename("dir1", "dir2/."). */ 2919 if (error == EISDIR && fvp->v_type == VDIR) 2920 error = EINVAL; 2921 NDFREE(&fromnd, NDF_ONLY_PNBUF); 2922 vrele(fromnd.ni_dvp); 2923 vrele(fvp); 2924 goto out1; 2925 } 2926 tdvp = tond.ni_dvp; 2927 tvp = tond.ni_vp; 2928 if (tvp != NULL) { 2929 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 2930 error = ENOTDIR; 2931 goto out; 2932 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 2933 error = EISDIR; 2934 goto out; 2935 } 2936 } 2937 if (fvp == tdvp) 2938 error = EINVAL; 2939 /* 2940 * If source is the same as the destination (that is the 2941 * same inode number with the same name in the same directory), 2942 * then there is nothing to do. 2943 */ 2944 if (fvp == tvp && fromnd.ni_dvp == tdvp && 2945 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen && 2946 !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr, 2947 fromnd.ni_cnd.cn_namelen)) 2948 error = -1; 2949out: 2950 if (!error) { 2951 VOP_LEASE(tdvp, td, td->td_proc->p_ucred, LEASE_WRITE); 2952 if (fromnd.ni_dvp != tdvp) { 2953 VOP_LEASE(fromnd.ni_dvp, td, td->td_proc->p_ucred, LEASE_WRITE); 2954 } 2955 if (tvp) { 2956 VOP_LEASE(tvp, td, td->td_proc->p_ucred, LEASE_WRITE); 2957 } 2958 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd, 2959 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd); 2960 NDFREE(&fromnd, NDF_ONLY_PNBUF); 2961 NDFREE(&tond, NDF_ONLY_PNBUF); 2962 } else { 2963 NDFREE(&fromnd, NDF_ONLY_PNBUF); 2964 NDFREE(&tond, NDF_ONLY_PNBUF); 2965 if (tdvp == tvp) 2966 vrele(tdvp); 2967 else 2968 vput(tdvp); 2969 if (tvp) 2970 vput(tvp); 2971 vrele(fromnd.ni_dvp); 2972 vrele(fvp); 2973 } 2974 vrele(tond.ni_startdir); 2975 vn_finished_write(mp); 2976 ASSERT_VOP_UNLOCKED(fromnd.ni_dvp, "rename"); 2977 ASSERT_VOP_UNLOCKED(fromnd.ni_vp, "rename"); 2978 ASSERT_VOP_UNLOCKED(tond.ni_dvp, "rename"); 2979 ASSERT_VOP_UNLOCKED(tond.ni_vp, "rename"); 2980out1: 2981 if (fromnd.ni_startdir) 2982 vrele(fromnd.ni_startdir); 2983 if (error == -1) 2984 return (0); 2985 return (error); 2986} 2987 2988/* 2989 * Make a directory file. 2990 */ 2991#ifndef _SYS_SYSPROTO_H_ 2992struct mkdir_args { 2993 char *path; 2994 int mode; 2995}; 2996#endif 2997/* ARGSUSED */ 2998int 2999mkdir(td, uap) 3000 struct thread *td; 3001 register struct mkdir_args /* { 3002 syscallarg(char *) path; 3003 syscallarg(int) mode; 3004 } */ *uap; 3005{ 3006 3007 return vn_mkdir(uap->path, uap->mode, UIO_USERSPACE, td); 3008} 3009 3010int 3011vn_mkdir(path, mode, segflg, td) 3012 char *path; 3013 int mode; 3014 enum uio_seg segflg; 3015 struct thread *td; 3016{ 3017 struct mount *mp; 3018 struct vnode *vp; 3019 struct vattr vattr; 3020 int error; 3021 struct nameidata nd; 3022 3023restart: 3024 bwillwrite(); 3025 NDINIT(&nd, CREATE, LOCKPARENT, segflg, path, td); 3026 nd.ni_cnd.cn_flags |= WILLBEDIR; 3027 if ((error = namei(&nd)) != 0) 3028 return (error); 3029 vp = nd.ni_vp; 3030 if (vp != NULL) { 3031 NDFREE(&nd, NDF_ONLY_PNBUF); 3032 vrele(vp); 3033 vput(nd.ni_dvp); 3034 return (EEXIST); 3035 } 3036 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 3037 NDFREE(&nd, NDF_ONLY_PNBUF); 3038 vput(nd.ni_dvp); 3039 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) 3040 return (error); 3041 goto restart; 3042 } 3043 VATTR_NULL(&vattr); 3044 vattr.va_type = VDIR; 3045 vattr.va_mode = (mode & ACCESSPERMS) &~ td->td_proc->p_fd->fd_cmask; 3046 VOP_LEASE(nd.ni_dvp, td, td->td_proc->p_ucred, LEASE_WRITE); 3047 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 3048 NDFREE(&nd, NDF_ONLY_PNBUF); 3049 vput(nd.ni_dvp); 3050 if (!error) 3051 vput(nd.ni_vp); 3052 vn_finished_write(mp); 3053 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mkdir"); 3054 ASSERT_VOP_UNLOCKED(nd.ni_vp, "mkdir"); 3055 return (error); 3056} 3057 3058/* 3059 * Remove a directory file. 3060 */ 3061#ifndef _SYS_SYSPROTO_H_ 3062struct rmdir_args { 3063 char *path; 3064}; 3065#endif 3066/* ARGSUSED */ 3067int 3068rmdir(td, uap) 3069 struct thread *td; 3070 struct rmdir_args /* { 3071 syscallarg(char *) path; 3072 } */ *uap; 3073{ 3074 struct mount *mp; 3075 struct vnode *vp; 3076 int error; 3077 struct nameidata nd; 3078 3079restart: 3080 bwillwrite(); 3081 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, 3082 SCARG(uap, path), td); 3083 if ((error = namei(&nd)) != 0) 3084 return (error); 3085 vp = nd.ni_vp; 3086 if (vp->v_type != VDIR) { 3087 error = ENOTDIR; 3088 goto out; 3089 } 3090 /* 3091 * No rmdir "." please. 3092 */ 3093 if (nd.ni_dvp == vp) { 3094 error = EINVAL; 3095 goto out; 3096 } 3097 /* 3098 * The root of a mounted filesystem cannot be deleted. 3099 */ 3100 if (vp->v_flag & VROOT) { 3101 error = EBUSY; 3102 goto out; 3103 } 3104 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 3105 NDFREE(&nd, NDF_ONLY_PNBUF); 3106 if (nd.ni_dvp == vp) 3107 vrele(nd.ni_dvp); 3108 else 3109 vput(nd.ni_dvp); 3110 vput(vp); 3111 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) 3112 return (error); 3113 goto restart; 3114 } 3115 VOP_LEASE(nd.ni_dvp, td, td->td_proc->p_ucred, LEASE_WRITE); 3116 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE); 3117 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 3118 vn_finished_write(mp); 3119out: 3120 NDFREE(&nd, NDF_ONLY_PNBUF); 3121 if (nd.ni_dvp == vp) 3122 vrele(nd.ni_dvp); 3123 else 3124 vput(nd.ni_dvp); 3125 vput(vp); 3126 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "rmdir"); 3127 ASSERT_VOP_UNLOCKED(nd.ni_vp, "rmdir"); 3128 return (error); 3129} 3130 3131#ifdef COMPAT_43 3132/* 3133 * Read a block of directory entries in a file system independent format. 3134 */ 3135#ifndef _SYS_SYSPROTO_H_ 3136struct ogetdirentries_args { 3137 int fd; 3138 char *buf; 3139 u_int count; 3140 long *basep; 3141}; 3142#endif 3143int 3144ogetdirentries(td, uap) 3145 struct thread *td; 3146 register struct ogetdirentries_args /* { 3147 syscallarg(int) fd; 3148 syscallarg(char *) buf; 3149 syscallarg(u_int) count; 3150 syscallarg(long *) basep; 3151 } */ *uap; 3152{ 3153 struct vnode *vp; 3154 struct file *fp; 3155 struct uio auio, kuio; 3156 struct iovec aiov, kiov; 3157 struct dirent *dp, *edp; 3158 caddr_t dirbuf; 3159 int error, eofflag, readcnt; 3160 long loff; 3161 3162 /* XXX arbitrary sanity limit on `count'. */ 3163 if (SCARG(uap, count) > 64 * 1024) 3164 return (EINVAL); 3165 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 3166 return (error); 3167 if ((fp->f_flag & FREAD) == 0) 3168 return (EBADF); 3169 vp = (struct vnode *)fp->f_data; 3170unionread: 3171 if (vp->v_type != VDIR) 3172 return (EINVAL); 3173 aiov.iov_base = SCARG(uap, buf); 3174 aiov.iov_len = SCARG(uap, count); 3175 auio.uio_iov = &aiov; 3176 auio.uio_iovcnt = 1; 3177 auio.uio_rw = UIO_READ; 3178 auio.uio_segflg = UIO_USERSPACE; 3179 auio.uio_td = td; 3180 auio.uio_resid = SCARG(uap, count); 3181 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3182 loff = auio.uio_offset = fp->f_offset; 3183# if (BYTE_ORDER != LITTLE_ENDIAN) 3184 if (vp->v_mount->mnt_maxsymlinklen <= 0) { 3185 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, 3186 NULL, NULL); 3187 fp->f_offset = auio.uio_offset; 3188 } else 3189# endif 3190 { 3191 kuio = auio; 3192 kuio.uio_iov = &kiov; 3193 kuio.uio_segflg = UIO_SYSSPACE; 3194 kiov.iov_len = SCARG(uap, count); 3195 MALLOC(dirbuf, caddr_t, SCARG(uap, count), M_TEMP, M_WAITOK); 3196 kiov.iov_base = dirbuf; 3197 error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag, 3198 NULL, NULL); 3199 fp->f_offset = kuio.uio_offset; 3200 if (error == 0) { 3201 readcnt = SCARG(uap, count) - kuio.uio_resid; 3202 edp = (struct dirent *)&dirbuf[readcnt]; 3203 for (dp = (struct dirent *)dirbuf; dp < edp; ) { 3204# if (BYTE_ORDER == LITTLE_ENDIAN) 3205 /* 3206 * The expected low byte of 3207 * dp->d_namlen is our dp->d_type. 3208 * The high MBZ byte of dp->d_namlen 3209 * is our dp->d_namlen. 3210 */ 3211 dp->d_type = dp->d_namlen; 3212 dp->d_namlen = 0; 3213# else 3214 /* 3215 * The dp->d_type is the high byte 3216 * of the expected dp->d_namlen, 3217 * so must be zero'ed. 3218 */ 3219 dp->d_type = 0; 3220# endif 3221 if (dp->d_reclen > 0) { 3222 dp = (struct dirent *) 3223 ((char *)dp + dp->d_reclen); 3224 } else { 3225 error = EIO; 3226 break; 3227 } 3228 } 3229 if (dp >= edp) 3230 error = uiomove(dirbuf, readcnt, &auio); 3231 } 3232 FREE(dirbuf, M_TEMP); 3233 } 3234 VOP_UNLOCK(vp, 0, td); 3235 if (error) 3236 return (error); 3237 if (SCARG(uap, count) == auio.uio_resid) { 3238 if (union_dircheckp) { 3239 error = union_dircheckp(td, &vp, fp); 3240 if (error == -1) 3241 goto unionread; 3242 if (error) 3243 return (error); 3244 } 3245 if ((vp->v_flag & VROOT) && 3246 (vp->v_mount->mnt_flag & MNT_UNION)) { 3247 struct vnode *tvp = vp; 3248 vp = vp->v_mount->mnt_vnodecovered; 3249 VREF(vp); 3250 fp->f_data = (caddr_t) vp; 3251 fp->f_offset = 0; 3252 vrele(tvp); 3253 goto unionread; 3254 } 3255 } 3256 error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep), 3257 sizeof(long)); 3258 td->td_retval[0] = SCARG(uap, count) - auio.uio_resid; 3259 return (error); 3260} 3261#endif /* COMPAT_43 */ 3262 3263/* 3264 * Read a block of directory entries in a file system independent format. 3265 */ 3266#ifndef _SYS_SYSPROTO_H_ 3267struct getdirentries_args { 3268 int fd; 3269 char *buf; 3270 u_int count; 3271 long *basep; 3272}; 3273#endif 3274int 3275getdirentries(td, uap) 3276 struct thread *td; 3277 register struct getdirentries_args /* { 3278 syscallarg(int) fd; 3279 syscallarg(char *) buf; 3280 syscallarg(u_int) count; 3281 syscallarg(long *) basep; 3282 } */ *uap; 3283{ 3284 struct vnode *vp; 3285 struct file *fp; 3286 struct uio auio; 3287 struct iovec aiov; 3288 long loff; 3289 int error, eofflag; 3290 3291 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 3292 return (error); 3293 if ((fp->f_flag & FREAD) == 0) 3294 return (EBADF); 3295 vp = (struct vnode *)fp->f_data; 3296unionread: 3297 if (vp->v_type != VDIR) 3298 return (EINVAL); 3299 aiov.iov_base = SCARG(uap, buf); 3300 aiov.iov_len = SCARG(uap, count); 3301 auio.uio_iov = &aiov; 3302 auio.uio_iovcnt = 1; 3303 auio.uio_rw = UIO_READ; 3304 auio.uio_segflg = UIO_USERSPACE; 3305 auio.uio_td = td; 3306 auio.uio_resid = SCARG(uap, count); 3307 /* vn_lock(vp, LK_SHARED | LK_RETRY, td); */ 3308 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3309 loff = auio.uio_offset = fp->f_offset; 3310 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL, NULL); 3311 fp->f_offset = auio.uio_offset; 3312 VOP_UNLOCK(vp, 0, td); 3313 if (error) 3314 return (error); 3315 if (SCARG(uap, count) == auio.uio_resid) { 3316 if (union_dircheckp) { 3317 error = union_dircheckp(td, &vp, fp); 3318 if (error == -1) 3319 goto unionread; 3320 if (error) 3321 return (error); 3322 } 3323 if ((vp->v_flag & VROOT) && 3324 (vp->v_mount->mnt_flag & MNT_UNION)) { 3325 struct vnode *tvp = vp; 3326 vp = vp->v_mount->mnt_vnodecovered; 3327 VREF(vp); 3328 fp->f_data = (caddr_t) vp; 3329 fp->f_offset = 0; 3330 vrele(tvp); 3331 goto unionread; 3332 } 3333 } 3334 if (SCARG(uap, basep) != NULL) { 3335 error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep), 3336 sizeof(long)); 3337 } 3338 td->td_retval[0] = SCARG(uap, count) - auio.uio_resid; 3339 return (error); 3340} 3341#ifndef _SYS_SYSPROTO_H_ 3342struct getdents_args { 3343 int fd; 3344 char *buf; 3345 size_t count; 3346}; 3347#endif 3348int 3349getdents(td, uap) 3350 struct thread *td; 3351 register struct getdents_args /* { 3352 syscallarg(int) fd; 3353 syscallarg(char *) buf; 3354 syscallarg(u_int) count; 3355 } */ *uap; 3356{ 3357 struct getdirentries_args ap; 3358 ap.fd = uap->fd; 3359 ap.buf = uap->buf; 3360 ap.count = uap->count; 3361 ap.basep = NULL; 3362 return getdirentries(td, &ap); 3363} 3364 3365/* 3366 * Set the mode mask for creation of filesystem nodes. 3367 * 3368 * MP SAFE 3369 */ 3370#ifndef _SYS_SYSPROTO_H_ 3371struct umask_args { 3372 int newmask; 3373}; 3374#endif 3375int 3376umask(td, uap) 3377 struct thread *td; 3378 struct umask_args /* { 3379 syscallarg(int) newmask; 3380 } */ *uap; 3381{ 3382 register struct filedesc *fdp; 3383 3384 fdp = td->td_proc->p_fd; 3385 td->td_retval[0] = fdp->fd_cmask; 3386 fdp->fd_cmask = SCARG(uap, newmask) & ALLPERMS; 3387 return (0); 3388} 3389 3390/* 3391 * Void all references to file by ripping underlying filesystem 3392 * away from vnode. 3393 */ 3394#ifndef _SYS_SYSPROTO_H_ 3395struct revoke_args { 3396 char *path; 3397}; 3398#endif 3399/* ARGSUSED */ 3400int 3401revoke(td, uap) 3402 struct thread *td; 3403 register struct revoke_args /* { 3404 syscallarg(char *) path; 3405 } */ *uap; 3406{ 3407 struct mount *mp; 3408 struct vnode *vp; 3409 struct vattr vattr; 3410 int error; 3411 struct nameidata nd; 3412 3413 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 3414 if ((error = namei(&nd)) != 0) 3415 return (error); 3416 vp = nd.ni_vp; 3417 NDFREE(&nd, NDF_ONLY_PNBUF); 3418 if (vp->v_type != VCHR) { 3419 error = EINVAL; 3420 goto out; 3421 } 3422 error = VOP_GETATTR(vp, &vattr, td->td_proc->p_ucred, td); 3423 if (error) 3424 goto out; 3425 if (td->td_proc->p_ucred->cr_uid != vattr.va_uid) { 3426 error = suser_xxx(0, td->td_proc, PRISON_ROOT); 3427 if (error) 3428 goto out; 3429 } 3430 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 3431 goto out; 3432 if (vcount(vp) > 1) 3433 VOP_REVOKE(vp, REVOKEALL); 3434 vn_finished_write(mp); 3435out: 3436 vrele(vp); 3437 return (error); 3438} 3439 3440/* 3441 * Convert a user file descriptor to a kernel file entry. 3442 */ 3443int 3444getvnode(fdp, fd, fpp) 3445 struct filedesc *fdp; 3446 int fd; 3447 struct file **fpp; 3448{ 3449 struct file *fp; 3450 3451 if ((u_int)fd >= fdp->fd_nfiles || 3452 (fp = fdp->fd_ofiles[fd]) == NULL) 3453 return (EBADF); 3454 if (fp->f_type != DTYPE_VNODE && fp->f_type != DTYPE_FIFO) 3455 return (EINVAL); 3456 *fpp = fp; 3457 return (0); 3458} 3459/* 3460 * Get (NFS) file handle 3461 */ 3462#ifndef _SYS_SYSPROTO_H_ 3463struct getfh_args { 3464 char *fname; 3465 fhandle_t *fhp; 3466}; 3467#endif 3468int 3469getfh(td, uap) 3470 struct thread *td; 3471 register struct getfh_args *uap; 3472{ 3473 struct nameidata nd; 3474 fhandle_t fh; 3475 register struct vnode *vp; 3476 int error; 3477 3478 /* 3479 * Must be super user 3480 */ 3481 error = suser_td(td); 3482 if (error) 3483 return (error); 3484 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, td); 3485 error = namei(&nd); 3486 if (error) 3487 return (error); 3488 NDFREE(&nd, NDF_ONLY_PNBUF); 3489 vp = nd.ni_vp; 3490 bzero(&fh, sizeof(fh)); 3491 fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid; 3492 error = VFS_VPTOFH(vp, &fh.fh_fid); 3493 vput(vp); 3494 if (error) 3495 return (error); 3496 error = copyout(&fh, uap->fhp, sizeof (fh)); 3497 return (error); 3498} 3499 3500/* 3501 * syscall for the rpc.lockd to use to translate a NFS file handle into 3502 * an open descriptor. 3503 * 3504 * warning: do not remove the suser() call or this becomes one giant 3505 * security hole. 3506 */ 3507#ifndef _SYS_SYSPROTO_H_ 3508struct fhopen_args { 3509 const struct fhandle *u_fhp; 3510 int flags; 3511}; 3512#endif 3513int 3514fhopen(td, uap) 3515 struct thread *td; 3516 struct fhopen_args /* { 3517 syscallarg(const struct fhandle *) u_fhp; 3518 syscallarg(int) flags; 3519 } */ *uap; 3520{ 3521 struct proc *p = td->td_proc; 3522 struct mount *mp; 3523 struct vnode *vp; 3524 struct fhandle fhp; 3525 struct vattr vat; 3526 struct vattr *vap = &vat; 3527 struct flock lf; 3528 struct file *fp; 3529 register struct filedesc *fdp = p->p_fd; 3530 int fmode, mode, error, type; 3531 struct file *nfp; 3532 int indx; 3533 3534 /* 3535 * Must be super user 3536 */ 3537 error = suser_td(td); 3538 if (error) 3539 return (error); 3540 3541 fmode = FFLAGS(SCARG(uap, flags)); 3542 /* why not allow a non-read/write open for our lockd? */ 3543 if (((fmode & (FREAD | FWRITE)) == 0) || (fmode & O_CREAT)) 3544 return (EINVAL); 3545 error = copyin(SCARG(uap,u_fhp), &fhp, sizeof(fhp)); 3546 if (error) 3547 return(error); 3548 /* find the mount point */ 3549 mp = vfs_getvfs(&fhp.fh_fsid); 3550 if (mp == NULL) 3551 return (ESTALE); 3552 /* now give me my vnode, it gets returned to me locked */ 3553 error = VFS_FHTOVP(mp, &fhp.fh_fid, &vp); 3554 if (error) 3555 return (error); 3556 /* 3557 * from now on we have to make sure not 3558 * to forget about the vnode 3559 * any error that causes an abort must vput(vp) 3560 * just set error = err and 'goto bad;'. 3561 */ 3562 3563 /* 3564 * from vn_open 3565 */ 3566 if (vp->v_type == VLNK) { 3567 error = EMLINK; 3568 goto bad; 3569 } 3570 if (vp->v_type == VSOCK) { 3571 error = EOPNOTSUPP; 3572 goto bad; 3573 } 3574 mode = 0; 3575 if (fmode & (FWRITE | O_TRUNC)) { 3576 if (vp->v_type == VDIR) { 3577 error = EISDIR; 3578 goto bad; 3579 } 3580 error = vn_writechk(vp); 3581 if (error) 3582 goto bad; 3583 mode |= VWRITE; 3584 } 3585 if (fmode & FREAD) 3586 mode |= VREAD; 3587 if (mode) { 3588 error = VOP_ACCESS(vp, mode, p->p_ucred, td); 3589 if (error) 3590 goto bad; 3591 } 3592 if (fmode & O_TRUNC) { 3593 VOP_UNLOCK(vp, 0, td); /* XXX */ 3594 if ((error = vn_start_write(NULL, &mp, V_WAIT | PCATCH)) != 0) { 3595 vrele(vp); 3596 return (error); 3597 } 3598 VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE); 3599 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); /* XXX */ 3600 VATTR_NULL(vap); 3601 vap->va_size = 0; 3602 error = VOP_SETATTR(vp, vap, p->p_ucred, td); 3603 vn_finished_write(mp); 3604 if (error) 3605 goto bad; 3606 } 3607 error = VOP_OPEN(vp, fmode, p->p_ucred, td); 3608 if (error) 3609 goto bad; 3610 /* 3611 * Make sure that a VM object is created for VMIO support. 3612 */ 3613 if (vn_canvmio(vp) == TRUE) { 3614 if ((error = vfs_object_create(vp, td, p->p_ucred)) != 0) 3615 goto bad; 3616 } 3617 if (fmode & FWRITE) 3618 vp->v_writecount++; 3619 3620 /* 3621 * end of vn_open code 3622 */ 3623 3624 if ((error = falloc(td, &nfp, &indx)) != 0) 3625 goto bad; 3626 fp = nfp; 3627 3628 /* 3629 * Hold an extra reference to avoid having fp ripped out 3630 * from under us while we block in the lock op 3631 */ 3632 fhold(fp); 3633 nfp->f_data = (caddr_t)vp; 3634 nfp->f_flag = fmode & FMASK; 3635 nfp->f_ops = &vnops; 3636 nfp->f_type = DTYPE_VNODE; 3637 if (fmode & (O_EXLOCK | O_SHLOCK)) { 3638 lf.l_whence = SEEK_SET; 3639 lf.l_start = 0; 3640 lf.l_len = 0; 3641 if (fmode & O_EXLOCK) 3642 lf.l_type = F_WRLCK; 3643 else 3644 lf.l_type = F_RDLCK; 3645 type = F_FLOCK; 3646 if ((fmode & FNONBLOCK) == 0) 3647 type |= F_WAIT; 3648 VOP_UNLOCK(vp, 0, td); 3649 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0) { 3650 /* 3651 * The lock request failed. Normally close the 3652 * descriptor but handle the case where someone might 3653 * have dup()d or close()d it when we weren't looking. 3654 */ 3655 if (fdp->fd_ofiles[indx] == fp) { 3656 fdp->fd_ofiles[indx] = NULL; 3657 fdrop(fp, td); 3658 } 3659 /* 3660 * release our private reference 3661 */ 3662 fdrop(fp, td); 3663 return(error); 3664 } 3665 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3666 fp->f_flag |= FHASLOCK; 3667 } 3668 if ((vp->v_type == VREG) && (VOP_GETVOBJECT(vp, NULL) != 0)) 3669 vfs_object_create(vp, td, p->p_ucred); 3670 3671 VOP_UNLOCK(vp, 0, td); 3672 fdrop(fp, td); 3673 td->td_retval[0] = indx; 3674 return (0); 3675 3676bad: 3677 vput(vp); 3678 return (error); 3679} 3680 3681/* 3682 * Stat an (NFS) file handle. 3683 */ 3684#ifndef _SYS_SYSPROTO_H_ 3685struct fhstat_args { 3686 struct fhandle *u_fhp; 3687 struct stat *sb; 3688}; 3689#endif 3690int 3691fhstat(td, uap) 3692 struct thread *td; 3693 register struct fhstat_args /* { 3694 syscallarg(struct fhandle *) u_fhp; 3695 syscallarg(struct stat *) sb; 3696 } */ *uap; 3697{ 3698 struct stat sb; 3699 fhandle_t fh; 3700 struct mount *mp; 3701 struct vnode *vp; 3702 int error; 3703 3704 /* 3705 * Must be super user 3706 */ 3707 error = suser_td(td); 3708 if (error) 3709 return (error); 3710 3711 error = copyin(SCARG(uap, u_fhp), &fh, sizeof(fhandle_t)); 3712 if (error) 3713 return (error); 3714 3715 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) 3716 return (ESTALE); 3717 if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp))) 3718 return (error); 3719 error = vn_stat(vp, &sb, td); 3720 vput(vp); 3721 if (error) 3722 return (error); 3723 error = copyout(&sb, SCARG(uap, sb), sizeof(sb)); 3724 return (error); 3725} 3726 3727/* 3728 * Implement fstatfs() for (NFS) file handles. 3729 */ 3730#ifndef _SYS_SYSPROTO_H_ 3731struct fhstatfs_args { 3732 struct fhandle *u_fhp; 3733 struct statfs *buf; 3734}; 3735#endif 3736int 3737fhstatfs(td, uap) 3738 struct thread *td; 3739 struct fhstatfs_args /* { 3740 syscallarg(struct fhandle) *u_fhp; 3741 syscallarg(struct statfs) *buf; 3742 } */ *uap; 3743{ 3744 struct statfs *sp; 3745 struct mount *mp; 3746 struct vnode *vp; 3747 struct statfs sb; 3748 fhandle_t fh; 3749 int error; 3750 3751 /* 3752 * Must be super user 3753 */ 3754 error = suser_td(td); 3755 if (error) 3756 return (error); 3757 3758 if ((error = copyin(SCARG(uap, u_fhp), &fh, sizeof(fhandle_t))) != 0) 3759 return (error); 3760 3761 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) 3762 return (ESTALE); 3763 if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp))) 3764 return (error); 3765 mp = vp->v_mount; 3766 sp = &mp->mnt_stat; 3767 vput(vp); 3768 if ((error = VFS_STATFS(mp, sp, td)) != 0) 3769 return (error); 3770 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 3771 if (suser_xxx(td->td_proc->p_ucred, 0, 0)) { 3772 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); 3773 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; 3774 sp = &sb; 3775 } 3776 return (copyout(sp, SCARG(uap, buf), sizeof(*sp))); 3777} 3778 3779/* 3780 * Syscall to push extended attribute configuration information into the 3781 * VFS. Accepts a path, which it converts to a mountpoint, as well as 3782 * a command (int cmd), and attribute name and misc data. For now, the 3783 * attribute name is left in userspace for consumption by the VFS_op. 3784 * It will probably be changed to be copied into sysspace by the 3785 * syscall in the future, once issues with various consumers of the 3786 * attribute code have raised their hands. 3787 * 3788 * Currently this is used only by UFS Extended Attributes. 3789 */ 3790int 3791extattrctl(td, uap) 3792 struct thread *td; 3793 struct extattrctl_args *uap; 3794{ 3795 struct vnode *filename_vp; 3796 struct nameidata nd; 3797 struct mount *mp; 3798 char attrname[EXTATTR_MAXNAMELEN]; 3799 int error; 3800 3801 /* 3802 * SCARG(uap, attrname) not always defined. We check again later 3803 * when we invoke the VFS call so as to pass in NULL there if needed. 3804 */ 3805 if (SCARG(uap, attrname) != NULL) { 3806 error = copyinstr(SCARG(uap, attrname), attrname, 3807 EXTATTR_MAXNAMELEN, NULL); 3808 if (error) 3809 return (error); 3810 } 3811 3812 /* 3813 * SCARG(uap, filename) not always defined. If it is, grab 3814 * a vnode lock, which VFS_EXTATTRCTL() will later release. 3815 */ 3816 filename_vp = NULL; 3817 if (SCARG(uap, filename) != NULL) { 3818 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 3819 SCARG(uap, filename), td); 3820 if ((error = namei(&nd)) != 0) 3821 return (error); 3822 filename_vp = nd.ni_vp; 3823 NDFREE(&nd, NDF_NO_VP_RELE | NDF_NO_VP_UNLOCK); 3824 } 3825 3826 /* SCARG(uap, path) always defined. */ 3827 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 3828 if ((error = namei(&nd)) != 0) 3829 return (error); 3830 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 3831 NDFREE(&nd, 0); 3832 if (error) { 3833 if (filename_vp) 3834 vrele(filename_vp); 3835 return (error); 3836 } 3837 3838 if (SCARG(uap, attrname) != NULL) { 3839 error = VFS_EXTATTRCTL(mp, SCARG(uap, cmd), filename_vp, 3840 SCARG(uap, attrnamespace), attrname, td); 3841 } else { 3842 error = VFS_EXTATTRCTL(mp, SCARG(uap, cmd), filename_vp, 3843 SCARG(uap, attrnamespace), NULL, td); 3844 } 3845 3846 vn_finished_write(mp); 3847 /* 3848 * VFS_EXTATTRCTL will have unlocked, but not de-ref'd, 3849 * filename_vp, so vrele it if it is defined. 3850 */ 3851 if (filename_vp != NULL) 3852 vrele(filename_vp); 3853 3854 return (error); 3855} 3856 3857/* 3858 * extattr_set_vp(): Set a named extended attribute on a file or directory 3859 * 3860 * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace", 3861 * kernelspace string pointer "attrname", 3862 * userspace iovec array pointer "iovp", unsigned int iovcnt 3863 * proc "p" 3864 * Returns: 0 on success, an error number otherwise 3865 * Locks: none 3866 * References: vp must be a valid reference for the duration of the call 3867 */ 3868static int 3869extattr_set_vp(struct vnode *vp, int attrnamespace, const char *attrname, 3870 struct iovec *iovp, unsigned iovcnt, struct thread *td) 3871{ 3872 struct mount *mp; 3873 struct uio auio; 3874 struct iovec *iov, *needfree = NULL, aiov[UIO_SMALLIOV]; 3875 u_int iovlen, cnt; 3876 int error, i; 3877 3878 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 3879 return (error); 3880 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE); 3881 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3882 3883 iovlen = iovcnt * sizeof(struct iovec); 3884 if (iovcnt > UIO_SMALLIOV) { 3885 if (iovcnt > UIO_MAXIOV) { 3886 error = EINVAL; 3887 goto done; 3888 } 3889 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); 3890 needfree = iov; 3891 } else 3892 iov = aiov; 3893 auio.uio_iov = iov; 3894 auio.uio_iovcnt = iovcnt; 3895 auio.uio_rw = UIO_WRITE; 3896 auio.uio_segflg = UIO_USERSPACE; 3897 auio.uio_td = td; 3898 auio.uio_offset = 0; 3899 if ((error = copyin((caddr_t)iovp, (caddr_t)iov, iovlen))) 3900 goto done; 3901 auio.uio_resid = 0; 3902 for (i = 0; i < iovcnt; i++) { 3903 if (iov->iov_len > INT_MAX - auio.uio_resid) { 3904 error = EINVAL; 3905 goto done; 3906 } 3907 auio.uio_resid += iov->iov_len; 3908 iov++; 3909 } 3910 cnt = auio.uio_resid; 3911 error = VOP_SETEXTATTR(vp, attrnamespace, attrname, &auio, 3912 td->td_proc->p_ucred, td); 3913 cnt -= auio.uio_resid; 3914 td->td_retval[0] = cnt; 3915done: 3916 if (needfree) 3917 FREE(needfree, M_IOV); 3918 VOP_UNLOCK(vp, 0, td); 3919 vn_finished_write(mp); 3920 return (error); 3921} 3922 3923int 3924extattr_set_file(td, uap) 3925 struct thread *td; 3926 struct extattr_set_file_args *uap; 3927{ 3928 struct nameidata nd; 3929 char attrname[EXTATTR_MAXNAMELEN]; 3930 int error; 3931 3932 error = copyinstr(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN, 3933 NULL); 3934 if (error) 3935 return (error); 3936 3937 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 3938 if ((error = namei(&nd)) != 0) 3939 return (error); 3940 NDFREE(&nd, NDF_ONLY_PNBUF); 3941 3942 error = extattr_set_vp(nd.ni_vp, SCARG(uap, attrnamespace), attrname, 3943 SCARG(uap, iovp), SCARG(uap, iovcnt), td); 3944 3945 vrele(nd.ni_vp); 3946 return (error); 3947} 3948 3949int 3950extattr_set_fd(td, uap) 3951 struct thread *td; 3952 struct extattr_set_fd_args *uap; 3953{ 3954 struct file *fp; 3955 char attrname[EXTATTR_MAXNAMELEN]; 3956 int error; 3957 3958 error = copyinstr(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN, 3959 NULL); 3960 if (error) 3961 return (error); 3962 3963 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 3964 return (error); 3965 3966 error = extattr_set_vp((struct vnode *)fp->f_data, 3967 SCARG(uap, attrnamespace), attrname, SCARG(uap, iovp), 3968 SCARG(uap, iovcnt), td); 3969 3970 return (error); 3971} 3972 3973/* 3974 * extattr_get_vp(): Get a named extended attribute on a file or directory 3975 * 3976 * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace", 3977 * kernelspace string pointer "attrname", 3978 * userspace iovec array pointer "iovp", unsigned int iovcnt, 3979 * proc "p" 3980 * Returns: 0 on success, an error number otherwise 3981 * Locks: none 3982 * References: vp must be a valid reference for the duration of the call 3983 */ 3984static int 3985extattr_get_vp(struct vnode *vp, int attrnamespace, const char *attrname, 3986 struct iovec *iovp, unsigned iovcnt, struct thread *td) 3987{ 3988 struct uio auio; 3989 struct iovec *iov, *needfree = NULL, aiov[UIO_SMALLIOV]; 3990 u_int iovlen, cnt; 3991 int error, i; 3992 3993 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_READ); 3994 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3995 3996 iovlen = iovcnt * sizeof (struct iovec); 3997 if (iovcnt > UIO_SMALLIOV) { 3998 if (iovcnt > UIO_MAXIOV) { 3999 error = EINVAL; 4000 goto done; 4001 } 4002 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); 4003 needfree = iov; 4004 } else 4005 iov = aiov; 4006 auio.uio_iov = iov; 4007 auio.uio_iovcnt = iovcnt; 4008 auio.uio_rw = UIO_READ; 4009 auio.uio_segflg = UIO_USERSPACE; 4010 auio.uio_td = td; 4011 auio.uio_offset = 0; 4012 if ((error = copyin((caddr_t)iovp, (caddr_t)iov, iovlen))) 4013 goto done; 4014 auio.uio_resid = 0; 4015 for (i = 0; i < iovcnt; i++) { 4016 if (iov->iov_len > INT_MAX - auio.uio_resid) { 4017 error = EINVAL; 4018 goto done; 4019 } 4020 auio.uio_resid += iov->iov_len; 4021 iov++; 4022 } 4023 cnt = auio.uio_resid; 4024 error = VOP_GETEXTATTR(vp, attrnamespace, attrname, &auio, 4025 td->td_proc->p_ucred, td); 4026 cnt -= auio.uio_resid; 4027 td->td_retval[0] = cnt; 4028done: 4029 if (needfree) 4030 FREE(needfree, M_IOV); 4031 VOP_UNLOCK(vp, 0, td); 4032 return (error); 4033} 4034 4035int 4036extattr_get_file(td, uap) 4037 struct thread *td; 4038 struct extattr_get_file_args *uap; 4039{ 4040 struct nameidata nd; 4041 char attrname[EXTATTR_MAXNAMELEN]; 4042 int error; 4043 4044 error = copyinstr(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN, 4045 NULL); 4046 if (error) 4047 return (error); 4048 4049 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 4050 if ((error = namei(&nd)) != 0) 4051 return (error); 4052 NDFREE(&nd, NDF_ONLY_PNBUF); 4053 4054 error = extattr_get_vp(nd.ni_vp, SCARG(uap, attrnamespace), attrname, 4055 SCARG(uap, iovp), SCARG(uap, iovcnt), td); 4056 4057 vrele(nd.ni_vp); 4058 return (error); 4059} 4060 4061int 4062extattr_get_fd(td, uap) 4063 struct thread *td; 4064 struct extattr_get_fd_args *uap; 4065{ 4066 struct file *fp; 4067 char attrname[EXTATTR_MAXNAMELEN]; 4068 int error; 4069 4070 error = copyinstr(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN, 4071 NULL); 4072 if (error) 4073 return (error); 4074 4075 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 4076 return (error); 4077 4078 error = extattr_get_vp((struct vnode *)fp->f_data, 4079 SCARG(uap, attrnamespace), attrname, SCARG(uap, iovp), 4080 SCARG(uap, iovcnt), td); 4081 4082 return (error); 4083} 4084 4085/* 4086 * extattr_delete_vp(): Delete a named extended attribute on a file or 4087 * directory 4088 * 4089 * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace", 4090 * kernelspace string pointer "attrname", proc "p" 4091 * Returns: 0 on success, an error number otherwise 4092 * Locks: none 4093 * References: vp must be a valid reference for the duration of the call 4094 */ 4095static int 4096extattr_delete_vp(struct vnode *vp, int attrnamespace, const char *attrname, 4097 struct thread *td) 4098{ 4099 struct mount *mp; 4100 int error; 4101 4102 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 4103 return (error); 4104 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE); 4105 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 4106 4107 error = VOP_SETEXTATTR(vp, attrnamespace, attrname, NULL, 4108 td->td_proc->p_ucred, td); 4109 4110 VOP_UNLOCK(vp, 0, td); 4111 vn_finished_write(mp); 4112 return (error); 4113} 4114 4115int 4116extattr_delete_file(td, uap) 4117 struct thread *td; 4118 struct extattr_delete_file_args *uap; 4119{ 4120 struct nameidata nd; 4121 char attrname[EXTATTR_MAXNAMELEN]; 4122 int error; 4123 4124 error = copyinstr(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN, 4125 NULL); 4126 if (error) 4127 return(error); 4128 4129 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 4130 if ((error = namei(&nd)) != 0) 4131 return(error); 4132 NDFREE(&nd, NDF_ONLY_PNBUF); 4133 4134 error = extattr_delete_vp(nd.ni_vp, SCARG(uap, attrnamespace), 4135 attrname, td); 4136 4137 vrele(nd.ni_vp); 4138 return(error); 4139} 4140 4141int 4142extattr_delete_fd(td, uap) 4143 struct thread *td; 4144 struct extattr_delete_fd_args *uap; 4145{ 4146 struct file *fp; 4147 char attrname[EXTATTR_MAXNAMELEN]; 4148 int error; 4149 4150 error = copyinstr(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN, 4151 NULL); 4152 if (error) 4153 return (error); 4154 4155 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 4156 return (error); 4157 4158 error = extattr_delete_vp((struct vnode *)fp->f_data, 4159 SCARG(uap, attrnamespace), attrname, td); 4160 4161 return (error); 4162}
| 596 panic("unmount: dangling vnode"); 597 lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK, &mountlist_mtx, td); 598 lockdestroy(&mp->mnt_lock); 599 if (coveredvp != NULL) 600 vrele(coveredvp); 601 if (mp->mnt_kern_flag & MNTK_MWAIT) 602 wakeup((caddr_t)mp); 603 free((caddr_t)mp, M_MOUNT); 604 return (0); 605} 606 607/* 608 * Sync each mounted filesystem. 609 */ 610#ifndef _SYS_SYSPROTO_H_ 611struct sync_args { 612 int dummy; 613}; 614#endif 615 616#ifdef DEBUG 617static int syncprt = 0; 618SYSCTL_INT(_debug, OID_AUTO, syncprt, CTLFLAG_RW, &syncprt, 0, ""); 619#endif 620 621/* ARGSUSED */ 622int 623sync(td, uap) 624 struct thread *td; 625 struct sync_args *uap; 626{ 627 struct mount *mp, *nmp; 628 int asyncflag; 629 630 mtx_lock(&mountlist_mtx); 631 for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) { 632 if (vfs_busy(mp, LK_NOWAIT, &mountlist_mtx, td)) { 633 nmp = TAILQ_NEXT(mp, mnt_list); 634 continue; 635 } 636 if ((mp->mnt_flag & MNT_RDONLY) == 0 && 637 vn_start_write(NULL, &mp, V_NOWAIT) == 0) { 638 asyncflag = mp->mnt_flag & MNT_ASYNC; 639 mp->mnt_flag &= ~MNT_ASYNC; 640 vfs_msync(mp, MNT_NOWAIT); 641 VFS_SYNC(mp, MNT_NOWAIT, 642 ((td != NULL) ? td->td_proc->p_ucred : NOCRED), td); 643 mp->mnt_flag |= asyncflag; 644 vn_finished_write(mp); 645 } 646 mtx_lock(&mountlist_mtx); 647 nmp = TAILQ_NEXT(mp, mnt_list); 648 vfs_unbusy(mp, td); 649 } 650 mtx_unlock(&mountlist_mtx); 651#if 0 652/* 653 * XXX don't call vfs_bufstats() yet because that routine 654 * was not imported in the Lite2 merge. 655 */ 656#ifdef DIAGNOSTIC 657 if (syncprt) 658 vfs_bufstats(); 659#endif /* DIAGNOSTIC */ 660#endif 661 return (0); 662} 663 664/* XXX PRISON: could be per prison flag */ 665static int prison_quotas; 666#if 0 667SYSCTL_INT(_kern_prison, OID_AUTO, quotas, CTLFLAG_RW, &prison_quotas, 0, ""); 668#endif 669 670/* 671 * Change filesystem quotas. 672 */ 673#ifndef _SYS_SYSPROTO_H_ 674struct quotactl_args { 675 char *path; 676 int cmd; 677 int uid; 678 caddr_t arg; 679}; 680#endif 681/* ARGSUSED */ 682int 683quotactl(td, uap) 684 struct thread *td; 685 register struct quotactl_args /* { 686 syscallarg(char *) path; 687 syscallarg(int) cmd; 688 syscallarg(int) uid; 689 syscallarg(caddr_t) arg; 690 } */ *uap; 691{ 692 struct mount *mp; 693 int error; 694 struct nameidata nd; 695 696 if (jailed(td->td_proc->p_ucred) && !prison_quotas) 697 return (EPERM); 698 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 699 if ((error = namei(&nd)) != 0) 700 return (error); 701 NDFREE(&nd, NDF_ONLY_PNBUF); 702 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 703 vrele(nd.ni_vp); 704 if (error) 705 return (error); 706 error = VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid), 707 SCARG(uap, arg), td); 708 vn_finished_write(mp); 709 return (error); 710} 711 712/* 713 * Get filesystem statistics. 714 */ 715#ifndef _SYS_SYSPROTO_H_ 716struct statfs_args { 717 char *path; 718 struct statfs *buf; 719}; 720#endif 721/* ARGSUSED */ 722int 723statfs(td, uap) 724 struct thread *td; 725 register struct statfs_args /* { 726 syscallarg(char *) path; 727 syscallarg(struct statfs *) buf; 728 } */ *uap; 729{ 730 register struct mount *mp; 731 register struct statfs *sp; 732 int error; 733 struct nameidata nd; 734 struct statfs sb; 735 736 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 737 if ((error = namei(&nd)) != 0) 738 return (error); 739 mp = nd.ni_vp->v_mount; 740 sp = &mp->mnt_stat; 741 NDFREE(&nd, NDF_ONLY_PNBUF); 742 vrele(nd.ni_vp); 743 error = VFS_STATFS(mp, sp, td); 744 if (error) 745 return (error); 746 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 747 if (suser_xxx(td->td_proc->p_ucred, 0, 0)) { 748 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); 749 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; 750 sp = &sb; 751 } 752 return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp))); 753} 754 755/* 756 * Get filesystem statistics. 757 */ 758#ifndef _SYS_SYSPROTO_H_ 759struct fstatfs_args { 760 int fd; 761 struct statfs *buf; 762}; 763#endif 764/* ARGSUSED */ 765int 766fstatfs(td, uap) 767 struct thread *td; 768 register struct fstatfs_args /* { 769 syscallarg(int) fd; 770 syscallarg(struct statfs *) buf; 771 } */ *uap; 772{ 773 struct file *fp; 774 struct mount *mp; 775 register struct statfs *sp; 776 int error; 777 struct statfs sb; 778 779 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 780 return (error); 781 mp = ((struct vnode *)fp->f_data)->v_mount; 782 sp = &mp->mnt_stat; 783 error = VFS_STATFS(mp, sp, td); 784 if (error) 785 return (error); 786 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 787 if (suser_xxx(td->td_proc->p_ucred, 0, 0)) { 788 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); 789 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; 790 sp = &sb; 791 } 792 return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp))); 793} 794 795/* 796 * Get statistics on all filesystems. 797 */ 798#ifndef _SYS_SYSPROTO_H_ 799struct getfsstat_args { 800 struct statfs *buf; 801 long bufsize; 802 int flags; 803}; 804#endif 805int 806getfsstat(td, uap) 807 struct thread *td; 808 register struct getfsstat_args /* { 809 syscallarg(struct statfs *) buf; 810 syscallarg(long) bufsize; 811 syscallarg(int) flags; 812 } */ *uap; 813{ 814 register struct mount *mp, *nmp; 815 register struct statfs *sp; 816 caddr_t sfsp; 817 long count, maxcount, error; 818 819 maxcount = SCARG(uap, bufsize) / sizeof(struct statfs); 820 sfsp = (caddr_t)SCARG(uap, buf); 821 count = 0; 822 mtx_lock(&mountlist_mtx); 823 for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) { 824 if (vfs_busy(mp, LK_NOWAIT, &mountlist_mtx, td)) { 825 nmp = TAILQ_NEXT(mp, mnt_list); 826 continue; 827 } 828 if (sfsp && count < maxcount) { 829 sp = &mp->mnt_stat; 830 /* 831 * If MNT_NOWAIT or MNT_LAZY is specified, do not 832 * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY 833 * overrides MNT_WAIT. 834 */ 835 if (((SCARG(uap, flags) & (MNT_LAZY|MNT_NOWAIT)) == 0 || 836 (SCARG(uap, flags) & MNT_WAIT)) && 837 (error = VFS_STATFS(mp, sp, td))) { 838 mtx_lock(&mountlist_mtx); 839 nmp = TAILQ_NEXT(mp, mnt_list); 840 vfs_unbusy(mp, td); 841 continue; 842 } 843 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 844 error = copyout((caddr_t)sp, sfsp, sizeof(*sp)); 845 if (error) { 846 vfs_unbusy(mp, td); 847 return (error); 848 } 849 sfsp += sizeof(*sp); 850 } 851 count++; 852 mtx_lock(&mountlist_mtx); 853 nmp = TAILQ_NEXT(mp, mnt_list); 854 vfs_unbusy(mp, td); 855 } 856 mtx_unlock(&mountlist_mtx); 857 if (sfsp && count > maxcount) 858 td->td_retval[0] = maxcount; 859 else 860 td->td_retval[0] = count; 861 return (0); 862} 863 864/* 865 * Change current working directory to a given file descriptor. 866 */ 867#ifndef _SYS_SYSPROTO_H_ 868struct fchdir_args { 869 int fd; 870}; 871#endif 872/* ARGSUSED */ 873int 874fchdir(td, uap) 875 struct thread *td; 876 struct fchdir_args /* { 877 syscallarg(int) fd; 878 } */ *uap; 879{ 880 register struct filedesc *fdp = td->td_proc->p_fd; 881 struct vnode *vp, *tdp; 882 struct mount *mp; 883 struct file *fp; 884 int error; 885 886 if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0) 887 return (error); 888 vp = (struct vnode *)fp->f_data; 889 VREF(vp); 890 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 891 if (vp->v_type != VDIR) 892 error = ENOTDIR; 893 else 894 error = VOP_ACCESS(vp, VEXEC, td->td_proc->p_ucred, td); 895 while (!error && (mp = vp->v_mountedhere) != NULL) { 896 if (vfs_busy(mp, 0, 0, td)) 897 continue; 898 error = VFS_ROOT(mp, &tdp); 899 vfs_unbusy(mp, td); 900 if (error) 901 break; 902 vput(vp); 903 vp = tdp; 904 } 905 if (error) { 906 vput(vp); 907 return (error); 908 } 909 VOP_UNLOCK(vp, 0, td); 910 vrele(fdp->fd_cdir); 911 fdp->fd_cdir = vp; 912 return (0); 913} 914 915/* 916 * Change current working directory (``.''). 917 */ 918#ifndef _SYS_SYSPROTO_H_ 919struct chdir_args { 920 char *path; 921}; 922#endif 923/* ARGSUSED */ 924int 925chdir(td, uap) 926 struct thread *td; 927 struct chdir_args /* { 928 syscallarg(char *) path; 929 } */ *uap; 930{ 931 register struct filedesc *fdp = td->td_proc->p_fd; 932 int error; 933 struct nameidata nd; 934 935 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 936 SCARG(uap, path), td); 937 if ((error = change_dir(&nd, td)) != 0) 938 return (error); 939 NDFREE(&nd, NDF_ONLY_PNBUF); 940 vrele(fdp->fd_cdir); 941 fdp->fd_cdir = nd.ni_vp; 942 return (0); 943} 944 945/* 946 * Helper function for raised chroot(2) security function: Refuse if 947 * any filedescriptors are open directories. 948 */ 949static int 950chroot_refuse_vdir_fds(fdp) 951 struct filedesc *fdp; 952{ 953 struct vnode *vp; 954 struct file *fp; 955 int error; 956 int fd; 957 958 for (fd = 0; fd < fdp->fd_nfiles ; fd++) { 959 error = getvnode(fdp, fd, &fp); 960 if (error) 961 continue; 962 vp = (struct vnode *)fp->f_data; 963 if (vp->v_type != VDIR) 964 continue; 965 return(EPERM); 966 } 967 return (0); 968} 969 970/* 971 * This sysctl determines if we will allow a process to chroot(2) if it 972 * has a directory open: 973 * 0: disallowed for all processes. 974 * 1: allowed for processes that were not already chroot(2)'ed. 975 * 2: allowed for all processes. 976 */ 977 978static int chroot_allow_open_directories = 1; 979 980SYSCTL_INT(_kern, OID_AUTO, chroot_allow_open_directories, CTLFLAG_RW, 981 &chroot_allow_open_directories, 0, ""); 982 983/* 984 * Change notion of root (``/'') directory. 985 */ 986#ifndef _SYS_SYSPROTO_H_ 987struct chroot_args { 988 char *path; 989}; 990#endif 991/* ARGSUSED */ 992int 993chroot(td, uap) 994 struct thread *td; 995 struct chroot_args /* { 996 syscallarg(char *) path; 997 } */ *uap; 998{ 999 register struct filedesc *fdp = td->td_proc->p_fd; 1000 int error; 1001 struct nameidata nd; 1002 1003 error = suser_xxx(0, td->td_proc, PRISON_ROOT); 1004 if (error) 1005 return (error); 1006 if (chroot_allow_open_directories == 0 || 1007 (chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode)) 1008 error = chroot_refuse_vdir_fds(fdp); 1009 if (error) 1010 return (error); 1011 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 1012 SCARG(uap, path), td); 1013 if ((error = change_dir(&nd, td)) != 0) 1014 return (error); 1015 NDFREE(&nd, NDF_ONLY_PNBUF); 1016 vrele(fdp->fd_rdir); 1017 fdp->fd_rdir = nd.ni_vp; 1018 if (!fdp->fd_jdir) { 1019 fdp->fd_jdir = nd.ni_vp; 1020 VREF(fdp->fd_jdir); 1021 } 1022 return (0); 1023} 1024 1025/* 1026 * Common routine for chroot and chdir. 1027 */ 1028static int 1029change_dir(ndp, td) 1030 register struct nameidata *ndp; 1031 struct thread *td; 1032{ 1033 struct vnode *vp; 1034 int error; 1035 1036 error = namei(ndp); 1037 if (error) 1038 return (error); 1039 vp = ndp->ni_vp; 1040 if (vp->v_type != VDIR) 1041 error = ENOTDIR; 1042 else 1043 error = VOP_ACCESS(vp, VEXEC, td->td_proc->p_ucred, td); 1044 if (error) 1045 vput(vp); 1046 else 1047 VOP_UNLOCK(vp, 0, td); 1048 return (error); 1049} 1050 1051/* 1052 * Check permissions, allocate an open file structure, 1053 * and call the device open routine if any. 1054 */ 1055#ifndef _SYS_SYSPROTO_H_ 1056struct open_args { 1057 char *path; 1058 int flags; 1059 int mode; 1060}; 1061#endif 1062int 1063open(td, uap) 1064 struct thread *td; 1065 register struct open_args /* { 1066 syscallarg(char *) path; 1067 syscallarg(int) flags; 1068 syscallarg(int) mode; 1069 } */ *uap; 1070{ 1071 struct proc *p = td->td_proc; 1072 struct filedesc *fdp = p->p_fd; 1073 struct file *fp; 1074 struct vnode *vp; 1075 struct vattr vat; 1076 struct mount *mp; 1077 int cmode, flags, oflags; 1078 struct file *nfp; 1079 int type, indx, error; 1080 struct flock lf; 1081 struct nameidata nd; 1082 1083 oflags = SCARG(uap, flags); 1084 if ((oflags & O_ACCMODE) == O_ACCMODE) 1085 return (EINVAL); 1086 flags = FFLAGS(oflags); 1087 error = falloc(td, &nfp, &indx); 1088 if (error) 1089 return (error); 1090 fp = nfp; 1091 cmode = ((SCARG(uap, mode) &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT; 1092 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 1093 td->td_dupfd = -indx - 1; /* XXX check for fdopen */ 1094 /* 1095 * Bump the ref count to prevent another process from closing 1096 * the descriptor while we are blocked in vn_open() 1097 */ 1098 fhold(fp); 1099 error = vn_open(&nd, &flags, cmode); 1100 if (error) { 1101 /* 1102 * release our own reference 1103 */ 1104 fdrop(fp, td); 1105 1106 /* 1107 * handle special fdopen() case. bleh. dupfdopen() is 1108 * responsible for dropping the old contents of ofiles[indx] 1109 * if it succeeds. 1110 */ 1111 if ((error == ENODEV || error == ENXIO) && 1112 td->td_dupfd >= 0 && /* XXX from fdopen */ 1113 (error = 1114 dupfdopen(td, fdp, indx, td->td_dupfd, flags, error)) == 0) { 1115 td->td_retval[0] = indx; 1116 return (0); 1117 } 1118 /* 1119 * Clean up the descriptor, but only if another thread hadn't 1120 * replaced or closed it. 1121 */ 1122 if (fdp->fd_ofiles[indx] == fp) { 1123 fdp->fd_ofiles[indx] = NULL; 1124 fdrop(fp, td); 1125 } 1126 1127 if (error == ERESTART) 1128 error = EINTR; 1129 return (error); 1130 } 1131 td->td_dupfd = 0; 1132 NDFREE(&nd, NDF_ONLY_PNBUF); 1133 vp = nd.ni_vp; 1134 1135 /* 1136 * There should be 2 references on the file, one from the descriptor 1137 * table, and one for us. 1138 * 1139 * Handle the case where someone closed the file (via its file 1140 * descriptor) while we were blocked. The end result should look 1141 * like opening the file succeeded but it was immediately closed. 1142 */ 1143 if (fp->f_count == 1) { 1144 KASSERT(fdp->fd_ofiles[indx] != fp, 1145 ("Open file descriptor lost all refs")); 1146 VOP_UNLOCK(vp, 0, td); 1147 vn_close(vp, flags & FMASK, fp->f_cred, td); 1148 fdrop(fp, td); 1149 td->td_retval[0] = indx; 1150 return 0; 1151 } 1152 1153 fp->f_data = (caddr_t)vp; 1154 fp->f_flag = flags & FMASK; 1155 fp->f_ops = &vnops; 1156 fp->f_type = (vp->v_type == VFIFO ? DTYPE_FIFO : DTYPE_VNODE); 1157 VOP_UNLOCK(vp, 0, td); 1158 if (flags & (O_EXLOCK | O_SHLOCK)) { 1159 lf.l_whence = SEEK_SET; 1160 lf.l_start = 0; 1161 lf.l_len = 0; 1162 if (flags & O_EXLOCK) 1163 lf.l_type = F_WRLCK; 1164 else 1165 lf.l_type = F_RDLCK; 1166 type = F_FLOCK; 1167 if ((flags & FNONBLOCK) == 0) 1168 type |= F_WAIT; 1169 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0) 1170 goto bad; 1171 fp->f_flag |= FHASLOCK; 1172 } 1173 if (flags & O_TRUNC) { 1174 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 1175 goto bad; 1176 VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE); 1177 VATTR_NULL(&vat); 1178 vat.va_size = 0; 1179 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 1180 error = VOP_SETATTR(vp, &vat, p->p_ucred, td); 1181 VOP_UNLOCK(vp, 0, td); 1182 vn_finished_write(mp); 1183 if (error) 1184 goto bad; 1185 } 1186 /* assert that vn_open created a backing object if one is needed */ 1187 KASSERT(!vn_canvmio(vp) || VOP_GETVOBJECT(vp, NULL) == 0, 1188 ("open: vmio vnode has no backing object after vn_open")); 1189 /* 1190 * Release our private reference, leaving the one associated with 1191 * the descriptor table intact. 1192 */ 1193 fdrop(fp, td); 1194 td->td_retval[0] = indx; 1195 return (0); 1196bad: 1197 if (fdp->fd_ofiles[indx] == fp) { 1198 fdp->fd_ofiles[indx] = NULL; 1199 fdrop(fp, td); 1200 } 1201 fdrop(fp, td); 1202 return (error); 1203} 1204 1205#ifdef COMPAT_43 1206/* 1207 * Create a file. 1208 */ 1209#ifndef _SYS_SYSPROTO_H_ 1210struct ocreat_args { 1211 char *path; 1212 int mode; 1213}; 1214#endif 1215int 1216ocreat(td, uap) 1217 struct thread *td; 1218 register struct ocreat_args /* { 1219 syscallarg(char *) path; 1220 syscallarg(int) mode; 1221 } */ *uap; 1222{ 1223 struct open_args /* { 1224 syscallarg(char *) path; 1225 syscallarg(int) flags; 1226 syscallarg(int) mode; 1227 } */ nuap; 1228 1229 SCARG(&nuap, path) = SCARG(uap, path); 1230 SCARG(&nuap, mode) = SCARG(uap, mode); 1231 SCARG(&nuap, flags) = O_WRONLY | O_CREAT | O_TRUNC; 1232 return (open(td, &nuap)); 1233} 1234#endif /* COMPAT_43 */ 1235 1236/* 1237 * Create a special file. 1238 */ 1239#ifndef _SYS_SYSPROTO_H_ 1240struct mknod_args { 1241 char *path; 1242 int mode; 1243 int dev; 1244}; 1245#endif 1246/* ARGSUSED */ 1247int 1248mknod(td, uap) 1249 struct thread *td; 1250 register struct mknod_args /* { 1251 syscallarg(char *) path; 1252 syscallarg(int) mode; 1253 syscallarg(int) dev; 1254 } */ *uap; 1255{ 1256 struct vnode *vp; 1257 struct mount *mp; 1258 struct vattr vattr; 1259 int error; 1260 int whiteout = 0; 1261 struct nameidata nd; 1262 1263 switch (SCARG(uap, mode) & S_IFMT) { 1264 case S_IFCHR: 1265 case S_IFBLK: 1266 error = suser_td(td); 1267 break; 1268 default: 1269 error = suser_xxx(0, td->td_proc, PRISON_ROOT); 1270 break; 1271 } 1272 if (error) 1273 return (error); 1274restart: 1275 bwillwrite(); 1276 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), td); 1277 if ((error = namei(&nd)) != 0) 1278 return (error); 1279 vp = nd.ni_vp; 1280 if (vp != NULL) { 1281 vrele(vp); 1282 error = EEXIST; 1283 } else { 1284 VATTR_NULL(&vattr); 1285 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ td->td_proc->p_fd->fd_cmask; 1286 vattr.va_rdev = SCARG(uap, dev); 1287 whiteout = 0; 1288 1289 switch (SCARG(uap, mode) & S_IFMT) { 1290 case S_IFMT: /* used by badsect to flag bad sectors */ 1291 vattr.va_type = VBAD; 1292 break; 1293 case S_IFCHR: 1294 vattr.va_type = VCHR; 1295 break; 1296 case S_IFBLK: 1297 vattr.va_type = VBLK; 1298 break; 1299 case S_IFWHT: 1300 whiteout = 1; 1301 break; 1302 default: 1303 error = EINVAL; 1304 break; 1305 } 1306 } 1307 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 1308 NDFREE(&nd, NDF_ONLY_PNBUF); 1309 vput(nd.ni_dvp); 1310 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) 1311 return (error); 1312 goto restart; 1313 } 1314 if (!error) { 1315 VOP_LEASE(nd.ni_dvp, td, td->td_proc->p_ucred, LEASE_WRITE); 1316 if (whiteout) 1317 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE); 1318 else { 1319 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, 1320 &nd.ni_cnd, &vattr); 1321 if (error == 0) 1322 vput(nd.ni_vp); 1323 } 1324 } 1325 NDFREE(&nd, NDF_ONLY_PNBUF); 1326 vput(nd.ni_dvp); 1327 vn_finished_write(mp); 1328 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mknod"); 1329 ASSERT_VOP_UNLOCKED(nd.ni_vp, "mknod"); 1330 return (error); 1331} 1332 1333/* 1334 * Create a named pipe. 1335 */ 1336#ifndef _SYS_SYSPROTO_H_ 1337struct mkfifo_args { 1338 char *path; 1339 int mode; 1340}; 1341#endif 1342/* ARGSUSED */ 1343int 1344mkfifo(td, uap) 1345 struct thread *td; 1346 register struct mkfifo_args /* { 1347 syscallarg(char *) path; 1348 syscallarg(int) mode; 1349 } */ *uap; 1350{ 1351 struct mount *mp; 1352 struct vattr vattr; 1353 int error; 1354 struct nameidata nd; 1355 1356restart: 1357 bwillwrite(); 1358 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), td); 1359 if ((error = namei(&nd)) != 0) 1360 return (error); 1361 if (nd.ni_vp != NULL) { 1362 NDFREE(&nd, NDF_ONLY_PNBUF); 1363 vrele(nd.ni_vp); 1364 vput(nd.ni_dvp); 1365 return (EEXIST); 1366 } 1367 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 1368 NDFREE(&nd, NDF_ONLY_PNBUF); 1369 vput(nd.ni_dvp); 1370 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) 1371 return (error); 1372 goto restart; 1373 } 1374 VATTR_NULL(&vattr); 1375 vattr.va_type = VFIFO; 1376 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ td->td_proc->p_fd->fd_cmask; 1377 VOP_LEASE(nd.ni_dvp, td, td->td_proc->p_ucred, LEASE_WRITE); 1378 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 1379 if (error == 0) 1380 vput(nd.ni_vp); 1381 NDFREE(&nd, NDF_ONLY_PNBUF); 1382 vput(nd.ni_dvp); 1383 vn_finished_write(mp); 1384 return (error); 1385} 1386 1387/* 1388 * Make a hard file link. 1389 */ 1390#ifndef _SYS_SYSPROTO_H_ 1391struct link_args { 1392 char *path; 1393 char *link; 1394}; 1395#endif 1396/* ARGSUSED */ 1397int 1398link(td, uap) 1399 struct thread *td; 1400 register struct link_args /* { 1401 syscallarg(char *) path; 1402 syscallarg(char *) link; 1403 } */ *uap; 1404{ 1405 struct vnode *vp; 1406 struct mount *mp; 1407 struct nameidata nd; 1408 int error; 1409 1410 bwillwrite(); 1411 NDINIT(&nd, LOOKUP, FOLLOW|NOOBJ, UIO_USERSPACE, SCARG(uap, path), td); 1412 if ((error = namei(&nd)) != 0) 1413 return (error); 1414 NDFREE(&nd, NDF_ONLY_PNBUF); 1415 vp = nd.ni_vp; 1416 if (vp->v_type == VDIR) { 1417 vrele(vp); 1418 return (EPERM); /* POSIX */ 1419 } 1420 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) { 1421 vrele(vp); 1422 return (error); 1423 } 1424 NDINIT(&nd, CREATE, LOCKPARENT|NOOBJ, UIO_USERSPACE, SCARG(uap, link), td); 1425 if ((error = namei(&nd)) == 0) { 1426 if (nd.ni_vp != NULL) { 1427 vrele(nd.ni_vp); 1428 error = EEXIST; 1429 } else { 1430 VOP_LEASE(nd.ni_dvp, td, td->td_proc->p_ucred, LEASE_WRITE); 1431 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE); 1432 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd); 1433 } 1434 NDFREE(&nd, NDF_ONLY_PNBUF); 1435 vput(nd.ni_dvp); 1436 } 1437 vrele(vp); 1438 vn_finished_write(mp); 1439 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "link"); 1440 ASSERT_VOP_UNLOCKED(nd.ni_vp, "link"); 1441 return (error); 1442} 1443 1444/* 1445 * Make a symbolic link. 1446 */ 1447#ifndef _SYS_SYSPROTO_H_ 1448struct symlink_args { 1449 char *path; 1450 char *link; 1451}; 1452#endif 1453/* ARGSUSED */ 1454int 1455symlink(td, uap) 1456 struct thread *td; 1457 register struct symlink_args /* { 1458 syscallarg(char *) path; 1459 syscallarg(char *) link; 1460 } */ *uap; 1461{ 1462 struct mount *mp; 1463 struct vattr vattr; 1464 char *path; 1465 int error; 1466 struct nameidata nd; 1467 1468 path = zalloc(namei_zone); 1469 if ((error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL)) != 0) 1470 goto out; 1471restart: 1472 bwillwrite(); 1473 NDINIT(&nd, CREATE, LOCKPARENT|NOOBJ, UIO_USERSPACE, SCARG(uap, link), td); 1474 if ((error = namei(&nd)) != 0) 1475 goto out; 1476 if (nd.ni_vp) { 1477 NDFREE(&nd, NDF_ONLY_PNBUF); 1478 vrele(nd.ni_vp); 1479 vput(nd.ni_dvp); 1480 error = EEXIST; 1481 goto out; 1482 } 1483 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 1484 NDFREE(&nd, NDF_ONLY_PNBUF); 1485 vput(nd.ni_dvp); 1486 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) 1487 return (error); 1488 goto restart; 1489 } 1490 VATTR_NULL(&vattr); 1491 vattr.va_mode = ACCESSPERMS &~ td->td_proc->p_fd->fd_cmask; 1492 VOP_LEASE(nd.ni_dvp, td, td->td_proc->p_ucred, LEASE_WRITE); 1493 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path); 1494 NDFREE(&nd, NDF_ONLY_PNBUF); 1495 if (error == 0) 1496 vput(nd.ni_vp); 1497 vput(nd.ni_dvp); 1498 vn_finished_write(mp); 1499 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "symlink"); 1500 ASSERT_VOP_UNLOCKED(nd.ni_vp, "symlink"); 1501out: 1502 zfree(namei_zone, path); 1503 return (error); 1504} 1505 1506/* 1507 * Delete a whiteout from the filesystem. 1508 */ 1509/* ARGSUSED */ 1510int 1511undelete(td, uap) 1512 struct thread *td; 1513 register struct undelete_args /* { 1514 syscallarg(char *) path; 1515 } */ *uap; 1516{ 1517 int error; 1518 struct mount *mp; 1519 struct nameidata nd; 1520 1521restart: 1522 bwillwrite(); 1523 NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE, 1524 SCARG(uap, path), td); 1525 error = namei(&nd); 1526 if (error) 1527 return (error); 1528 1529 if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) { 1530 NDFREE(&nd, NDF_ONLY_PNBUF); 1531 if (nd.ni_vp) 1532 vrele(nd.ni_vp); 1533 vput(nd.ni_dvp); 1534 return (EEXIST); 1535 } 1536 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 1537 NDFREE(&nd, NDF_ONLY_PNBUF); 1538 vput(nd.ni_dvp); 1539 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) 1540 return (error); 1541 goto restart; 1542 } 1543 VOP_LEASE(nd.ni_dvp, td, td->td_proc->p_ucred, LEASE_WRITE); 1544 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE); 1545 NDFREE(&nd, NDF_ONLY_PNBUF); 1546 vput(nd.ni_dvp); 1547 vn_finished_write(mp); 1548 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "undelete"); 1549 ASSERT_VOP_UNLOCKED(nd.ni_vp, "undelete"); 1550 return (error); 1551} 1552 1553/* 1554 * Delete a name from the filesystem. 1555 */ 1556#ifndef _SYS_SYSPROTO_H_ 1557struct unlink_args { 1558 char *path; 1559}; 1560#endif 1561/* ARGSUSED */ 1562int 1563unlink(td, uap) 1564 struct thread *td; 1565 struct unlink_args /* { 1566 syscallarg(char *) path; 1567 } */ *uap; 1568{ 1569 struct mount *mp; 1570 struct vnode *vp; 1571 int error; 1572 struct nameidata nd; 1573 1574restart: 1575 bwillwrite(); 1576 NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), td); 1577 if ((error = namei(&nd)) != 0) 1578 return (error); 1579 vp = nd.ni_vp; 1580 if (vp->v_type == VDIR) 1581 error = EPERM; /* POSIX */ 1582 else { 1583 /* 1584 * The root of a mounted filesystem cannot be deleted. 1585 * 1586 * XXX: can this only be a VDIR case? 1587 */ 1588 if (vp->v_flag & VROOT) 1589 error = EBUSY; 1590 } 1591 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 1592 NDFREE(&nd, NDF_ONLY_PNBUF); 1593 vrele(vp); 1594 vput(nd.ni_dvp); 1595 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) 1596 return (error); 1597 goto restart; 1598 } 1599 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE); 1600 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 1601 if (!error) { 1602 VOP_LEASE(nd.ni_dvp, td, td->td_proc->p_ucred, LEASE_WRITE); 1603 error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd); 1604 } 1605 NDFREE(&nd, NDF_ONLY_PNBUF); 1606 vput(nd.ni_dvp); 1607 vput(vp); 1608 vn_finished_write(mp); 1609 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "unlink"); 1610 ASSERT_VOP_UNLOCKED(nd.ni_vp, "unlink"); 1611 return (error); 1612} 1613 1614/* 1615 * Reposition read/write file offset. 1616 */ 1617#ifndef _SYS_SYSPROTO_H_ 1618struct lseek_args { 1619 int fd; 1620 int pad; 1621 off_t offset; 1622 int whence; 1623}; 1624#endif 1625int 1626lseek(td, uap) 1627 struct thread *td; 1628 register struct lseek_args /* { 1629 syscallarg(int) fd; 1630 syscallarg(int) pad; 1631 syscallarg(off_t) offset; 1632 syscallarg(int) whence; 1633 } */ *uap; 1634{ 1635 struct ucred *cred = td->td_proc->p_ucred; 1636 register struct filedesc *fdp = td->td_proc->p_fd; 1637 register struct file *fp; 1638 struct vattr vattr; 1639 struct vnode *vp; 1640 off_t offset; 1641 int error, noneg; 1642 1643 if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles || 1644 (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL) 1645 return (EBADF); 1646 if (fp->f_type != DTYPE_VNODE) 1647 return (ESPIPE); 1648 vp = (struct vnode *)fp->f_data; 1649 noneg = (vp->v_type != VCHR); 1650 offset = SCARG(uap, offset); 1651 switch (SCARG(uap, whence)) { 1652 case L_INCR: 1653 if (noneg && 1654 (fp->f_offset < 0 || 1655 (offset > 0 && fp->f_offset > OFF_MAX - offset))) 1656 return (EOVERFLOW); 1657 offset += fp->f_offset; 1658 break; 1659 case L_XTND: 1660 error = VOP_GETATTR(vp, &vattr, cred, td); 1661 if (error) 1662 return (error); 1663 if (noneg && 1664 (vattr.va_size > OFF_MAX || 1665 (offset > 0 && vattr.va_size > OFF_MAX - offset))) 1666 return (EOVERFLOW); 1667 offset += vattr.va_size; 1668 break; 1669 case L_SET: 1670 break; 1671 default: 1672 return (EINVAL); 1673 } 1674 if (noneg && offset < 0) 1675 return (EINVAL); 1676 fp->f_offset = offset; 1677 *(off_t *)(td->td_retval) = fp->f_offset; 1678 return (0); 1679} 1680 1681#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1682/* 1683 * Reposition read/write file offset. 1684 */ 1685#ifndef _SYS_SYSPROTO_H_ 1686struct olseek_args { 1687 int fd; 1688 long offset; 1689 int whence; 1690}; 1691#endif 1692int 1693olseek(td, uap) 1694 struct thread *td; 1695 register struct olseek_args /* { 1696 syscallarg(int) fd; 1697 syscallarg(long) offset; 1698 syscallarg(int) whence; 1699 } */ *uap; 1700{ 1701 struct lseek_args /* { 1702 syscallarg(int) fd; 1703 syscallarg(int) pad; 1704 syscallarg(off_t) offset; 1705 syscallarg(int) whence; 1706 } */ nuap; 1707 int error; 1708 1709 SCARG(&nuap, fd) = SCARG(uap, fd); 1710 SCARG(&nuap, offset) = SCARG(uap, offset); 1711 SCARG(&nuap, whence) = SCARG(uap, whence); 1712 error = lseek(td, &nuap); 1713 return (error); 1714} 1715#endif /* COMPAT_43 */ 1716 1717/* 1718 * Check access permissions using passed credentials. 1719 */ 1720static int 1721vn_access(vp, user_flags, cred, td) 1722 struct vnode *vp; 1723 int user_flags; 1724 struct ucred *cred; 1725 struct thread *td; 1726{ 1727 int error, flags; 1728 1729 /* Flags == 0 means only check for existence. */ 1730 error = 0; 1731 if (user_flags) { 1732 flags = 0; 1733 if (user_flags & R_OK) 1734 flags |= VREAD; 1735 if (user_flags & W_OK) 1736 flags |= VWRITE; 1737 if (user_flags & X_OK) 1738 flags |= VEXEC; 1739 if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0) 1740 error = VOP_ACCESS(vp, flags, cred, td); 1741 } 1742 return (error); 1743} 1744 1745/* 1746 * Check access permissions using "real" credentials. 1747 */ 1748#ifndef _SYS_SYSPROTO_H_ 1749struct access_args { 1750 char *path; 1751 int flags; 1752}; 1753#endif 1754int 1755access(td, uap) 1756 struct thread *td; 1757 register struct access_args /* { 1758 syscallarg(char *) path; 1759 syscallarg(int) flags; 1760 } */ *uap; 1761{ 1762 struct ucred *cred, *tmpcred; 1763 register struct vnode *vp; 1764 int error; 1765 struct nameidata nd; 1766 1767 cred = td->td_proc->p_ucred; 1768 /* 1769 * Create and modify a temporary credential instead of one that 1770 * is potentially shared. This could also mess up socket 1771 * buffer accounting which can run in an interrupt context. 1772 * 1773 * XXX - Depending on how "threads" are finally implemented, it 1774 * may be better to explicitly pass the credential to namei() 1775 * rather than to modify the potentially shared process structure. 1776 */ 1777 tmpcred = crdup(cred); 1778 tmpcred->cr_uid = cred->cr_ruid; 1779 tmpcred->cr_groups[0] = cred->cr_rgid; 1780 td->td_proc->p_ucred = tmpcred; 1781 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1782 SCARG(uap, path), td); 1783 if ((error = namei(&nd)) != 0) 1784 goto out1; 1785 vp = nd.ni_vp; 1786 1787 error = vn_access(vp, SCARG(uap, flags), tmpcred, td); 1788 NDFREE(&nd, NDF_ONLY_PNBUF); 1789 vput(vp); 1790out1: 1791 td->td_proc->p_ucred = cred; 1792 crfree(tmpcred); 1793 return (error); 1794} 1795 1796/* 1797 * Check access permissions using "effective" credentials. 1798 */ 1799#ifndef _SYS_SYSPROTO_H_ 1800struct eaccess_args { 1801 char *path; 1802 int flags; 1803}; 1804#endif 1805int 1806eaccess(td, uap) 1807 struct thread *td; 1808 register struct eaccess_args /* { 1809 syscallarg(char *) path; 1810 syscallarg(int) flags; 1811 } */ *uap; 1812{ 1813 struct nameidata nd; 1814 struct vnode *vp; 1815 int error; 1816 1817 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1818 SCARG(uap, path), td); 1819 if ((error = namei(&nd)) != 0) 1820 return (error); 1821 vp = nd.ni_vp; 1822 1823 error = vn_access(vp, SCARG(uap, flags), td->td_proc->p_ucred, td); 1824 NDFREE(&nd, NDF_ONLY_PNBUF); 1825 vput(vp); 1826 return (error); 1827} 1828 1829#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1830/* 1831 * Get file status; this version follows links. 1832 */ 1833#ifndef _SYS_SYSPROTO_H_ 1834struct ostat_args { 1835 char *path; 1836 struct ostat *ub; 1837}; 1838#endif 1839/* ARGSUSED */ 1840int 1841ostat(td, uap) 1842 struct thread *td; 1843 register struct ostat_args /* { 1844 syscallarg(char *) path; 1845 syscallarg(struct ostat *) ub; 1846 } */ *uap; 1847{ 1848 struct stat sb; 1849 struct ostat osb; 1850 int error; 1851 struct nameidata nd; 1852 1853 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1854 SCARG(uap, path), td); 1855 if ((error = namei(&nd)) != 0) 1856 return (error); 1857 NDFREE(&nd, NDF_ONLY_PNBUF); 1858 error = vn_stat(nd.ni_vp, &sb, td); 1859 vput(nd.ni_vp); 1860 if (error) 1861 return (error); 1862 cvtstat(&sb, &osb); 1863 error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb)); 1864 return (error); 1865} 1866 1867/* 1868 * Get file status; this version does not follow links. 1869 */ 1870#ifndef _SYS_SYSPROTO_H_ 1871struct olstat_args { 1872 char *path; 1873 struct ostat *ub; 1874}; 1875#endif 1876/* ARGSUSED */ 1877int 1878olstat(td, uap) 1879 struct thread *td; 1880 register struct olstat_args /* { 1881 syscallarg(char *) path; 1882 syscallarg(struct ostat *) ub; 1883 } */ *uap; 1884{ 1885 struct vnode *vp; 1886 struct stat sb; 1887 struct ostat osb; 1888 int error; 1889 struct nameidata nd; 1890 1891 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1892 SCARG(uap, path), td); 1893 if ((error = namei(&nd)) != 0) 1894 return (error); 1895 vp = nd.ni_vp; 1896 error = vn_stat(vp, &sb, td); 1897 NDFREE(&nd, NDF_ONLY_PNBUF); 1898 vput(vp); 1899 if (error) 1900 return (error); 1901 cvtstat(&sb, &osb); 1902 error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb)); 1903 return (error); 1904} 1905 1906/* 1907 * Convert from an old to a new stat structure. 1908 */ 1909void 1910cvtstat(st, ost) 1911 struct stat *st; 1912 struct ostat *ost; 1913{ 1914 1915 ost->st_dev = st->st_dev; 1916 ost->st_ino = st->st_ino; 1917 ost->st_mode = st->st_mode; 1918 ost->st_nlink = st->st_nlink; 1919 ost->st_uid = st->st_uid; 1920 ost->st_gid = st->st_gid; 1921 ost->st_rdev = st->st_rdev; 1922 if (st->st_size < (quad_t)1 << 32) 1923 ost->st_size = st->st_size; 1924 else 1925 ost->st_size = -2; 1926 ost->st_atime = st->st_atime; 1927 ost->st_mtime = st->st_mtime; 1928 ost->st_ctime = st->st_ctime; 1929 ost->st_blksize = st->st_blksize; 1930 ost->st_blocks = st->st_blocks; 1931 ost->st_flags = st->st_flags; 1932 ost->st_gen = st->st_gen; 1933} 1934#endif /* COMPAT_43 || COMPAT_SUNOS */ 1935 1936/* 1937 * Get file status; this version follows links. 1938 */ 1939#ifndef _SYS_SYSPROTO_H_ 1940struct stat_args { 1941 char *path; 1942 struct stat *ub; 1943}; 1944#endif 1945/* ARGSUSED */ 1946int 1947stat(td, uap) 1948 struct thread *td; 1949 register struct stat_args /* { 1950 syscallarg(char *) path; 1951 syscallarg(struct stat *) ub; 1952 } */ *uap; 1953{ 1954 struct stat sb; 1955 int error; 1956 struct nameidata nd; 1957 1958 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1959 SCARG(uap, path), td); 1960 if ((error = namei(&nd)) != 0) 1961 return (error); 1962 error = vn_stat(nd.ni_vp, &sb, td); 1963 NDFREE(&nd, NDF_ONLY_PNBUF); 1964 vput(nd.ni_vp); 1965 if (error) 1966 return (error); 1967 error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb)); 1968 return (error); 1969} 1970 1971/* 1972 * Get file status; this version does not follow links. 1973 */ 1974#ifndef _SYS_SYSPROTO_H_ 1975struct lstat_args { 1976 char *path; 1977 struct stat *ub; 1978}; 1979#endif 1980/* ARGSUSED */ 1981int 1982lstat(td, uap) 1983 struct thread *td; 1984 register struct lstat_args /* { 1985 syscallarg(char *) path; 1986 syscallarg(struct stat *) ub; 1987 } */ *uap; 1988{ 1989 int error; 1990 struct vnode *vp; 1991 struct stat sb; 1992 struct nameidata nd; 1993 1994 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1995 SCARG(uap, path), td); 1996 if ((error = namei(&nd)) != 0) 1997 return (error); 1998 vp = nd.ni_vp; 1999 error = vn_stat(vp, &sb, td); 2000 NDFREE(&nd, NDF_ONLY_PNBUF); 2001 vput(vp); 2002 if (error) 2003 return (error); 2004 error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb)); 2005 return (error); 2006} 2007 2008/* 2009 * Implementation of the NetBSD stat() function. 2010 * XXX This should probably be collapsed with the FreeBSD version, 2011 * as the differences are only due to vn_stat() clearing spares at 2012 * the end of the structures. vn_stat could be split to avoid this, 2013 * and thus collapse the following to close to zero code. 2014 */ 2015void 2016cvtnstat(sb, nsb) 2017 struct stat *sb; 2018 struct nstat *nsb; 2019{ 2020 nsb->st_dev = sb->st_dev; 2021 nsb->st_ino = sb->st_ino; 2022 nsb->st_mode = sb->st_mode; 2023 nsb->st_nlink = sb->st_nlink; 2024 nsb->st_uid = sb->st_uid; 2025 nsb->st_gid = sb->st_gid; 2026 nsb->st_rdev = sb->st_rdev; 2027 nsb->st_atimespec = sb->st_atimespec; 2028 nsb->st_mtimespec = sb->st_mtimespec; 2029 nsb->st_ctimespec = sb->st_ctimespec; 2030 nsb->st_size = sb->st_size; 2031 nsb->st_blocks = sb->st_blocks; 2032 nsb->st_blksize = sb->st_blksize; 2033 nsb->st_flags = sb->st_flags; 2034 nsb->st_gen = sb->st_gen; 2035 nsb->st_qspare[0] = sb->st_qspare[0]; 2036 nsb->st_qspare[1] = sb->st_qspare[1]; 2037} 2038 2039#ifndef _SYS_SYSPROTO_H_ 2040struct nstat_args { 2041 char *path; 2042 struct nstat *ub; 2043}; 2044#endif 2045/* ARGSUSED */ 2046int 2047nstat(td, uap) 2048 struct thread *td; 2049 register struct nstat_args /* { 2050 syscallarg(char *) path; 2051 syscallarg(struct nstat *) ub; 2052 } */ *uap; 2053{ 2054 struct stat sb; 2055 struct nstat nsb; 2056 int error; 2057 struct nameidata nd; 2058 2059 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 2060 SCARG(uap, path), td); 2061 if ((error = namei(&nd)) != 0) 2062 return (error); 2063 NDFREE(&nd, NDF_ONLY_PNBUF); 2064 error = vn_stat(nd.ni_vp, &sb, td); 2065 vput(nd.ni_vp); 2066 if (error) 2067 return (error); 2068 cvtnstat(&sb, &nsb); 2069 error = copyout((caddr_t)&nsb, (caddr_t)SCARG(uap, ub), sizeof (nsb)); 2070 return (error); 2071} 2072 2073/* 2074 * NetBSD lstat. Get file status; this version does not follow links. 2075 */ 2076#ifndef _SYS_SYSPROTO_H_ 2077struct lstat_args { 2078 char *path; 2079 struct stat *ub; 2080}; 2081#endif 2082/* ARGSUSED */ 2083int 2084nlstat(td, uap) 2085 struct thread *td; 2086 register struct nlstat_args /* { 2087 syscallarg(char *) path; 2088 syscallarg(struct nstat *) ub; 2089 } */ *uap; 2090{ 2091 int error; 2092 struct vnode *vp; 2093 struct stat sb; 2094 struct nstat nsb; 2095 struct nameidata nd; 2096 2097 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 2098 SCARG(uap, path), td); 2099 if ((error = namei(&nd)) != 0) 2100 return (error); 2101 vp = nd.ni_vp; 2102 NDFREE(&nd, NDF_ONLY_PNBUF); 2103 error = vn_stat(vp, &sb, td); 2104 vput(vp); 2105 if (error) 2106 return (error); 2107 cvtnstat(&sb, &nsb); 2108 error = copyout((caddr_t)&nsb, (caddr_t)SCARG(uap, ub), sizeof (nsb)); 2109 return (error); 2110} 2111 2112/* 2113 * Get configurable pathname variables. 2114 */ 2115#ifndef _SYS_SYSPROTO_H_ 2116struct pathconf_args { 2117 char *path; 2118 int name; 2119}; 2120#endif 2121/* ARGSUSED */ 2122int 2123pathconf(td, uap) 2124 struct thread *td; 2125 register struct pathconf_args /* { 2126 syscallarg(char *) path; 2127 syscallarg(int) name; 2128 } */ *uap; 2129{ 2130 int error; 2131 struct nameidata nd; 2132 2133 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 2134 SCARG(uap, path), td); 2135 if ((error = namei(&nd)) != 0) 2136 return (error); 2137 NDFREE(&nd, NDF_ONLY_PNBUF); 2138 error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), td->td_retval); 2139 vput(nd.ni_vp); 2140 return (error); 2141} 2142 2143/* 2144 * Return target name of a symbolic link. 2145 */ 2146#ifndef _SYS_SYSPROTO_H_ 2147struct readlink_args { 2148 char *path; 2149 char *buf; 2150 int count; 2151}; 2152#endif 2153/* ARGSUSED */ 2154int 2155readlink(td, uap) 2156 struct thread *td; 2157 register struct readlink_args /* { 2158 syscallarg(char *) path; 2159 syscallarg(char *) buf; 2160 syscallarg(int) count; 2161 } */ *uap; 2162{ 2163 register struct vnode *vp; 2164 struct iovec aiov; 2165 struct uio auio; 2166 int error; 2167 struct nameidata nd; 2168 2169 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 2170 SCARG(uap, path), td); 2171 if ((error = namei(&nd)) != 0) 2172 return (error); 2173 NDFREE(&nd, NDF_ONLY_PNBUF); 2174 vp = nd.ni_vp; 2175 if (vp->v_type != VLNK) 2176 error = EINVAL; 2177 else { 2178 aiov.iov_base = SCARG(uap, buf); 2179 aiov.iov_len = SCARG(uap, count); 2180 auio.uio_iov = &aiov; 2181 auio.uio_iovcnt = 1; 2182 auio.uio_offset = 0; 2183 auio.uio_rw = UIO_READ; 2184 auio.uio_segflg = UIO_USERSPACE; 2185 auio.uio_td = td; 2186 auio.uio_resid = SCARG(uap, count); 2187 error = VOP_READLINK(vp, &auio, td->td_proc->p_ucred); 2188 } 2189 vput(vp); 2190 td->td_retval[0] = SCARG(uap, count) - auio.uio_resid; 2191 return (error); 2192} 2193 2194/* 2195 * Common implementation code for chflags() and fchflags(). 2196 */ 2197static int 2198setfflags(td, vp, flags) 2199 struct thread *td; 2200 struct vnode *vp; 2201 int flags; 2202{ 2203 int error; 2204 struct mount *mp; 2205 struct vattr vattr; 2206 2207 /* 2208 * Prevent non-root users from setting flags on devices. When 2209 * a device is reused, users can retain ownership of the device 2210 * if they are allowed to set flags and programs assume that 2211 * chown can't fail when done as root. 2212 */ 2213 if (vp->v_type == VCHR || vp->v_type == VBLK) { 2214 error = suser_xxx(td->td_proc->p_ucred, td->td_proc, 2215 PRISON_ROOT); 2216 if (error) 2217 return (error); 2218 } 2219 2220 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 2221 return (error); 2222 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE); 2223 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2224 VATTR_NULL(&vattr); 2225 vattr.va_flags = flags; 2226 error = VOP_SETATTR(vp, &vattr, td->td_proc->p_ucred, td); 2227 VOP_UNLOCK(vp, 0, td); 2228 vn_finished_write(mp); 2229 return (error); 2230} 2231 2232/* 2233 * Change flags of a file given a path name. 2234 */ 2235#ifndef _SYS_SYSPROTO_H_ 2236struct chflags_args { 2237 char *path; 2238 int flags; 2239}; 2240#endif 2241/* ARGSUSED */ 2242int 2243chflags(td, uap) 2244 struct thread *td; 2245 register struct chflags_args /* { 2246 syscallarg(char *) path; 2247 syscallarg(int) flags; 2248 } */ *uap; 2249{ 2250 int error; 2251 struct nameidata nd; 2252 2253 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 2254 if ((error = namei(&nd)) != 0) 2255 return (error); 2256 NDFREE(&nd, NDF_ONLY_PNBUF); 2257 error = setfflags(td, nd.ni_vp, SCARG(uap, flags)); 2258 vrele(nd.ni_vp); 2259 return error; 2260} 2261 2262/* 2263 * Change flags of a file given a file descriptor. 2264 */ 2265#ifndef _SYS_SYSPROTO_H_ 2266struct fchflags_args { 2267 int fd; 2268 int flags; 2269}; 2270#endif 2271/* ARGSUSED */ 2272int 2273fchflags(td, uap) 2274 struct thread *td; 2275 register struct fchflags_args /* { 2276 syscallarg(int) fd; 2277 syscallarg(int) flags; 2278 } */ *uap; 2279{ 2280 struct file *fp; 2281 int error; 2282 2283 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 2284 return (error); 2285 return setfflags(td, (struct vnode *) fp->f_data, SCARG(uap, flags)); 2286} 2287 2288/* 2289 * Common implementation code for chmod(), lchmod() and fchmod(). 2290 */ 2291static int 2292setfmode(td, vp, mode) 2293 struct thread *td; 2294 struct vnode *vp; 2295 int mode; 2296{ 2297 int error; 2298 struct mount *mp; 2299 struct vattr vattr; 2300 2301 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 2302 return (error); 2303 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE); 2304 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2305 VATTR_NULL(&vattr); 2306 vattr.va_mode = mode & ALLPERMS; 2307 error = VOP_SETATTR(vp, &vattr, td->td_proc->p_ucred, td); 2308 VOP_UNLOCK(vp, 0, td); 2309 vn_finished_write(mp); 2310 return error; 2311} 2312 2313/* 2314 * Change mode of a file given path name. 2315 */ 2316#ifndef _SYS_SYSPROTO_H_ 2317struct chmod_args { 2318 char *path; 2319 int mode; 2320}; 2321#endif 2322/* ARGSUSED */ 2323int 2324chmod(td, uap) 2325 struct thread *td; 2326 register struct chmod_args /* { 2327 syscallarg(char *) path; 2328 syscallarg(int) mode; 2329 } */ *uap; 2330{ 2331 int error; 2332 struct nameidata nd; 2333 2334 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 2335 if ((error = namei(&nd)) != 0) 2336 return (error); 2337 NDFREE(&nd, NDF_ONLY_PNBUF); 2338 error = setfmode(td, nd.ni_vp, SCARG(uap, mode)); 2339 vrele(nd.ni_vp); 2340 return error; 2341} 2342 2343/* 2344 * Change mode of a file given path name (don't follow links.) 2345 */ 2346#ifndef _SYS_SYSPROTO_H_ 2347struct lchmod_args { 2348 char *path; 2349 int mode; 2350}; 2351#endif 2352/* ARGSUSED */ 2353int 2354lchmod(td, uap) 2355 struct thread *td; 2356 register struct lchmod_args /* { 2357 syscallarg(char *) path; 2358 syscallarg(int) mode; 2359 } */ *uap; 2360{ 2361 int error; 2362 struct nameidata nd; 2363 2364 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 2365 if ((error = namei(&nd)) != 0) 2366 return (error); 2367 NDFREE(&nd, NDF_ONLY_PNBUF); 2368 error = setfmode(td, nd.ni_vp, SCARG(uap, mode)); 2369 vrele(nd.ni_vp); 2370 return error; 2371} 2372 2373/* 2374 * Change mode of a file given a file descriptor. 2375 */ 2376#ifndef _SYS_SYSPROTO_H_ 2377struct fchmod_args { 2378 int fd; 2379 int mode; 2380}; 2381#endif 2382/* ARGSUSED */ 2383int 2384fchmod(td, uap) 2385 struct thread *td; 2386 register struct fchmod_args /* { 2387 syscallarg(int) fd; 2388 syscallarg(int) mode; 2389 } */ *uap; 2390{ 2391 struct file *fp; 2392 int error; 2393 2394 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 2395 return (error); 2396 return setfmode(td, (struct vnode *)fp->f_data, SCARG(uap, mode)); 2397} 2398 2399/* 2400 * Common implementation for chown(), lchown(), and fchown() 2401 */ 2402static int 2403setfown(td, vp, uid, gid) 2404 struct thread *td; 2405 struct vnode *vp; 2406 uid_t uid; 2407 gid_t gid; 2408{ 2409 int error; 2410 struct mount *mp; 2411 struct vattr vattr; 2412 2413 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 2414 return (error); 2415 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE); 2416 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2417 VATTR_NULL(&vattr); 2418 vattr.va_uid = uid; 2419 vattr.va_gid = gid; 2420 error = VOP_SETATTR(vp, &vattr, td->td_proc->p_ucred, td); 2421 VOP_UNLOCK(vp, 0, td); 2422 vn_finished_write(mp); 2423 return error; 2424} 2425 2426/* 2427 * Set ownership given a path name. 2428 */ 2429#ifndef _SYS_SYSPROTO_H_ 2430struct chown_args { 2431 char *path; 2432 int uid; 2433 int gid; 2434}; 2435#endif 2436/* ARGSUSED */ 2437int 2438chown(td, uap) 2439 struct thread *td; 2440 register struct chown_args /* { 2441 syscallarg(char *) path; 2442 syscallarg(int) uid; 2443 syscallarg(int) gid; 2444 } */ *uap; 2445{ 2446 int error; 2447 struct nameidata nd; 2448 2449 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 2450 if ((error = namei(&nd)) != 0) 2451 return (error); 2452 NDFREE(&nd, NDF_ONLY_PNBUF); 2453 error = setfown(td, nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid)); 2454 vrele(nd.ni_vp); 2455 return (error); 2456} 2457 2458/* 2459 * Set ownership given a path name, do not cross symlinks. 2460 */ 2461#ifndef _SYS_SYSPROTO_H_ 2462struct lchown_args { 2463 char *path; 2464 int uid; 2465 int gid; 2466}; 2467#endif 2468/* ARGSUSED */ 2469int 2470lchown(td, uap) 2471 struct thread *td; 2472 register struct lchown_args /* { 2473 syscallarg(char *) path; 2474 syscallarg(int) uid; 2475 syscallarg(int) gid; 2476 } */ *uap; 2477{ 2478 int error; 2479 struct nameidata nd; 2480 2481 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 2482 if ((error = namei(&nd)) != 0) 2483 return (error); 2484 NDFREE(&nd, NDF_ONLY_PNBUF); 2485 error = setfown(td, nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid)); 2486 vrele(nd.ni_vp); 2487 return (error); 2488} 2489 2490/* 2491 * Set ownership given a file descriptor. 2492 */ 2493#ifndef _SYS_SYSPROTO_H_ 2494struct fchown_args { 2495 int fd; 2496 int uid; 2497 int gid; 2498}; 2499#endif 2500/* ARGSUSED */ 2501int 2502fchown(td, uap) 2503 struct thread *td; 2504 register struct fchown_args /* { 2505 syscallarg(int) fd; 2506 syscallarg(int) uid; 2507 syscallarg(int) gid; 2508 } */ *uap; 2509{ 2510 struct file *fp; 2511 int error; 2512 2513 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 2514 return (error); 2515 return setfown(td, (struct vnode *)fp->f_data, 2516 SCARG(uap, uid), SCARG(uap, gid)); 2517} 2518 2519/* 2520 * Common implementation code for utimes(), lutimes(), and futimes(). 2521 */ 2522static int 2523getutimes(usrtvp, tsp) 2524 const struct timeval *usrtvp; 2525 struct timespec *tsp; 2526{ 2527 struct timeval tv[2]; 2528 int error; 2529 2530 if (usrtvp == NULL) { 2531 microtime(&tv[0]); 2532 TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]); 2533 tsp[1] = tsp[0]; 2534 } else { 2535 if ((error = copyin(usrtvp, tv, sizeof (tv))) != 0) 2536 return (error); 2537 TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]); 2538 TIMEVAL_TO_TIMESPEC(&tv[1], &tsp[1]); 2539 } 2540 return 0; 2541} 2542 2543/* 2544 * Common implementation code for utimes(), lutimes(), and futimes(). 2545 */ 2546static int 2547setutimes(td, vp, ts, nullflag) 2548 struct thread *td; 2549 struct vnode *vp; 2550 const struct timespec *ts; 2551 int nullflag; 2552{ 2553 int error; 2554 struct mount *mp; 2555 struct vattr vattr; 2556 2557 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 2558 return (error); 2559 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE); 2560 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2561 VATTR_NULL(&vattr); 2562 vattr.va_atime = ts[0]; 2563 vattr.va_mtime = ts[1]; 2564 if (nullflag) 2565 vattr.va_vaflags |= VA_UTIMES_NULL; 2566 error = VOP_SETATTR(vp, &vattr, td->td_proc->p_ucred, td); 2567 VOP_UNLOCK(vp, 0, td); 2568 vn_finished_write(mp); 2569 return error; 2570} 2571 2572/* 2573 * Set the access and modification times of a file. 2574 */ 2575#ifndef _SYS_SYSPROTO_H_ 2576struct utimes_args { 2577 char *path; 2578 struct timeval *tptr; 2579}; 2580#endif 2581/* ARGSUSED */ 2582int 2583utimes(td, uap) 2584 struct thread *td; 2585 register struct utimes_args /* { 2586 syscallarg(char *) path; 2587 syscallarg(struct timeval *) tptr; 2588 } */ *uap; 2589{ 2590 struct timespec ts[2]; 2591 struct timeval *usrtvp; 2592 int error; 2593 struct nameidata nd; 2594 2595 usrtvp = SCARG(uap, tptr); 2596 if ((error = getutimes(usrtvp, ts)) != 0) 2597 return (error); 2598 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 2599 if ((error = namei(&nd)) != 0) 2600 return (error); 2601 NDFREE(&nd, NDF_ONLY_PNBUF); 2602 error = setutimes(td, nd.ni_vp, ts, usrtvp == NULL); 2603 vrele(nd.ni_vp); 2604 return (error); 2605} 2606 2607/* 2608 * Set the access and modification times of a file. 2609 */ 2610#ifndef _SYS_SYSPROTO_H_ 2611struct lutimes_args { 2612 char *path; 2613 struct timeval *tptr; 2614}; 2615#endif 2616/* ARGSUSED */ 2617int 2618lutimes(td, uap) 2619 struct thread *td; 2620 register struct lutimes_args /* { 2621 syscallarg(char *) path; 2622 syscallarg(struct timeval *) tptr; 2623 } */ *uap; 2624{ 2625 struct timespec ts[2]; 2626 struct timeval *usrtvp; 2627 int error; 2628 struct nameidata nd; 2629 2630 usrtvp = SCARG(uap, tptr); 2631 if ((error = getutimes(usrtvp, ts)) != 0) 2632 return (error); 2633 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 2634 if ((error = namei(&nd)) != 0) 2635 return (error); 2636 NDFREE(&nd, NDF_ONLY_PNBUF); 2637 error = setutimes(td, nd.ni_vp, ts, usrtvp == NULL); 2638 vrele(nd.ni_vp); 2639 return (error); 2640} 2641 2642/* 2643 * Set the access and modification times of a file. 2644 */ 2645#ifndef _SYS_SYSPROTO_H_ 2646struct futimes_args { 2647 int fd; 2648 struct timeval *tptr; 2649}; 2650#endif 2651/* ARGSUSED */ 2652int 2653futimes(td, uap) 2654 struct thread *td; 2655 register struct futimes_args /* { 2656 syscallarg(int ) fd; 2657 syscallarg(struct timeval *) tptr; 2658 } */ *uap; 2659{ 2660 struct timespec ts[2]; 2661 struct file *fp; 2662 struct timeval *usrtvp; 2663 int error; 2664 2665 usrtvp = SCARG(uap, tptr); 2666 if ((error = getutimes(usrtvp, ts)) != 0) 2667 return (error); 2668 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 2669 return (error); 2670 return setutimes(td, (struct vnode *)fp->f_data, ts, usrtvp == NULL); 2671} 2672 2673/* 2674 * Truncate a file given its path name. 2675 */ 2676#ifndef _SYS_SYSPROTO_H_ 2677struct truncate_args { 2678 char *path; 2679 int pad; 2680 off_t length; 2681}; 2682#endif 2683/* ARGSUSED */ 2684int 2685truncate(td, uap) 2686 struct thread *td; 2687 register struct truncate_args /* { 2688 syscallarg(char *) path; 2689 syscallarg(int) pad; 2690 syscallarg(off_t) length; 2691 } */ *uap; 2692{ 2693 struct mount *mp; 2694 struct vnode *vp; 2695 struct vattr vattr; 2696 int error; 2697 struct nameidata nd; 2698 2699 if (uap->length < 0) 2700 return(EINVAL); 2701 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 2702 if ((error = namei(&nd)) != 0) 2703 return (error); 2704 vp = nd.ni_vp; 2705 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) { 2706 vrele(vp); 2707 return (error); 2708 } 2709 NDFREE(&nd, NDF_ONLY_PNBUF); 2710 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE); 2711 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2712 if (vp->v_type == VDIR) 2713 error = EISDIR; 2714 else if ((error = vn_writechk(vp)) == 0 && 2715 (error = VOP_ACCESS(vp, VWRITE, td->td_proc->p_ucred, td)) == 0) { 2716 VATTR_NULL(&vattr); 2717 vattr.va_size = SCARG(uap, length); 2718 error = VOP_SETATTR(vp, &vattr, td->td_proc->p_ucred, td); 2719 } 2720 vput(vp); 2721 vn_finished_write(mp); 2722 return (error); 2723} 2724 2725/* 2726 * Truncate a file given a file descriptor. 2727 */ 2728#ifndef _SYS_SYSPROTO_H_ 2729struct ftruncate_args { 2730 int fd; 2731 int pad; 2732 off_t length; 2733}; 2734#endif 2735/* ARGSUSED */ 2736int 2737ftruncate(td, uap) 2738 struct thread *td; 2739 register struct ftruncate_args /* { 2740 syscallarg(int) fd; 2741 syscallarg(int) pad; 2742 syscallarg(off_t) length; 2743 } */ *uap; 2744{ 2745 struct mount *mp; 2746 struct vattr vattr; 2747 struct vnode *vp; 2748 struct file *fp; 2749 int error; 2750 2751 if (uap->length < 0) 2752 return(EINVAL); 2753 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 2754 return (error); 2755 if ((fp->f_flag & FWRITE) == 0) 2756 return (EINVAL); 2757 vp = (struct vnode *)fp->f_data; 2758 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 2759 return (error); 2760 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE); 2761 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2762 if (vp->v_type == VDIR) 2763 error = EISDIR; 2764 else if ((error = vn_writechk(vp)) == 0) { 2765 VATTR_NULL(&vattr); 2766 vattr.va_size = SCARG(uap, length); 2767 error = VOP_SETATTR(vp, &vattr, fp->f_cred, td); 2768 } 2769 VOP_UNLOCK(vp, 0, td); 2770 vn_finished_write(mp); 2771 return (error); 2772} 2773 2774#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 2775/* 2776 * Truncate a file given its path name. 2777 */ 2778#ifndef _SYS_SYSPROTO_H_ 2779struct otruncate_args { 2780 char *path; 2781 long length; 2782}; 2783#endif 2784/* ARGSUSED */ 2785int 2786otruncate(td, uap) 2787 struct thread *td; 2788 register struct otruncate_args /* { 2789 syscallarg(char *) path; 2790 syscallarg(long) length; 2791 } */ *uap; 2792{ 2793 struct truncate_args /* { 2794 syscallarg(char *) path; 2795 syscallarg(int) pad; 2796 syscallarg(off_t) length; 2797 } */ nuap; 2798 2799 SCARG(&nuap, path) = SCARG(uap, path); 2800 SCARG(&nuap, length) = SCARG(uap, length); 2801 return (truncate(td, &nuap)); 2802} 2803 2804/* 2805 * Truncate a file given a file descriptor. 2806 */ 2807#ifndef _SYS_SYSPROTO_H_ 2808struct oftruncate_args { 2809 int fd; 2810 long length; 2811}; 2812#endif 2813/* ARGSUSED */ 2814int 2815oftruncate(td, uap) 2816 struct thread *td; 2817 register struct oftruncate_args /* { 2818 syscallarg(int) fd; 2819 syscallarg(long) length; 2820 } */ *uap; 2821{ 2822 struct ftruncate_args /* { 2823 syscallarg(int) fd; 2824 syscallarg(int) pad; 2825 syscallarg(off_t) length; 2826 } */ nuap; 2827 2828 SCARG(&nuap, fd) = SCARG(uap, fd); 2829 SCARG(&nuap, length) = SCARG(uap, length); 2830 return (ftruncate(td, &nuap)); 2831} 2832#endif /* COMPAT_43 || COMPAT_SUNOS */ 2833 2834/* 2835 * Sync an open file. 2836 */ 2837#ifndef _SYS_SYSPROTO_H_ 2838struct fsync_args { 2839 int fd; 2840}; 2841#endif 2842/* ARGSUSED */ 2843int 2844fsync(td, uap) 2845 struct thread *td; 2846 struct fsync_args /* { 2847 syscallarg(int) fd; 2848 } */ *uap; 2849{ 2850 struct vnode *vp; 2851 struct mount *mp; 2852 struct file *fp; 2853 vm_object_t obj; 2854 int error; 2855 2856 GIANT_REQUIRED; 2857 2858 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 2859 return (error); 2860 vp = (struct vnode *)fp->f_data; 2861 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 2862 return (error); 2863 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2864 if (VOP_GETVOBJECT(vp, &obj) == 0) { 2865 vm_object_page_clean(obj, 0, 0, 0); 2866 } 2867 error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, td); 2868#ifdef SOFTUPDATES 2869 if (error == 0 && vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP)) 2870 error = softdep_fsync(vp); 2871#endif 2872 2873 VOP_UNLOCK(vp, 0, td); 2874 vn_finished_write(mp); 2875 return (error); 2876} 2877 2878/* 2879 * Rename files. Source and destination must either both be directories, 2880 * or both not be directories. If target is a directory, it must be empty. 2881 */ 2882#ifndef _SYS_SYSPROTO_H_ 2883struct rename_args { 2884 char *from; 2885 char *to; 2886}; 2887#endif 2888/* ARGSUSED */ 2889int 2890rename(td, uap) 2891 struct thread *td; 2892 register struct rename_args /* { 2893 syscallarg(char *) from; 2894 syscallarg(char *) to; 2895 } */ *uap; 2896{ 2897 struct mount *mp; 2898 struct vnode *tvp, *fvp, *tdvp; 2899 struct nameidata fromnd, tond; 2900 int error; 2901 2902 bwillwrite(); 2903 NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE, 2904 SCARG(uap, from), td); 2905 if ((error = namei(&fromnd)) != 0) 2906 return (error); 2907 fvp = fromnd.ni_vp; 2908 if ((error = vn_start_write(fvp, &mp, V_WAIT | PCATCH)) != 0) { 2909 NDFREE(&fromnd, NDF_ONLY_PNBUF); 2910 vrele(fromnd.ni_dvp); 2911 vrele(fvp); 2912 goto out1; 2913 } 2914 NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART | NOOBJ, 2915 UIO_USERSPACE, SCARG(uap, to), td); 2916 if (fromnd.ni_vp->v_type == VDIR) 2917 tond.ni_cnd.cn_flags |= WILLBEDIR; 2918 if ((error = namei(&tond)) != 0) { 2919 /* Translate error code for rename("dir1", "dir2/."). */ 2920 if (error == EISDIR && fvp->v_type == VDIR) 2921 error = EINVAL; 2922 NDFREE(&fromnd, NDF_ONLY_PNBUF); 2923 vrele(fromnd.ni_dvp); 2924 vrele(fvp); 2925 goto out1; 2926 } 2927 tdvp = tond.ni_dvp; 2928 tvp = tond.ni_vp; 2929 if (tvp != NULL) { 2930 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 2931 error = ENOTDIR; 2932 goto out; 2933 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 2934 error = EISDIR; 2935 goto out; 2936 } 2937 } 2938 if (fvp == tdvp) 2939 error = EINVAL; 2940 /* 2941 * If source is the same as the destination (that is the 2942 * same inode number with the same name in the same directory), 2943 * then there is nothing to do. 2944 */ 2945 if (fvp == tvp && fromnd.ni_dvp == tdvp && 2946 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen && 2947 !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr, 2948 fromnd.ni_cnd.cn_namelen)) 2949 error = -1; 2950out: 2951 if (!error) { 2952 VOP_LEASE(tdvp, td, td->td_proc->p_ucred, LEASE_WRITE); 2953 if (fromnd.ni_dvp != tdvp) { 2954 VOP_LEASE(fromnd.ni_dvp, td, td->td_proc->p_ucred, LEASE_WRITE); 2955 } 2956 if (tvp) { 2957 VOP_LEASE(tvp, td, td->td_proc->p_ucred, LEASE_WRITE); 2958 } 2959 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd, 2960 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd); 2961 NDFREE(&fromnd, NDF_ONLY_PNBUF); 2962 NDFREE(&tond, NDF_ONLY_PNBUF); 2963 } else { 2964 NDFREE(&fromnd, NDF_ONLY_PNBUF); 2965 NDFREE(&tond, NDF_ONLY_PNBUF); 2966 if (tdvp == tvp) 2967 vrele(tdvp); 2968 else 2969 vput(tdvp); 2970 if (tvp) 2971 vput(tvp); 2972 vrele(fromnd.ni_dvp); 2973 vrele(fvp); 2974 } 2975 vrele(tond.ni_startdir); 2976 vn_finished_write(mp); 2977 ASSERT_VOP_UNLOCKED(fromnd.ni_dvp, "rename"); 2978 ASSERT_VOP_UNLOCKED(fromnd.ni_vp, "rename"); 2979 ASSERT_VOP_UNLOCKED(tond.ni_dvp, "rename"); 2980 ASSERT_VOP_UNLOCKED(tond.ni_vp, "rename"); 2981out1: 2982 if (fromnd.ni_startdir) 2983 vrele(fromnd.ni_startdir); 2984 if (error == -1) 2985 return (0); 2986 return (error); 2987} 2988 2989/* 2990 * Make a directory file. 2991 */ 2992#ifndef _SYS_SYSPROTO_H_ 2993struct mkdir_args { 2994 char *path; 2995 int mode; 2996}; 2997#endif 2998/* ARGSUSED */ 2999int 3000mkdir(td, uap) 3001 struct thread *td; 3002 register struct mkdir_args /* { 3003 syscallarg(char *) path; 3004 syscallarg(int) mode; 3005 } */ *uap; 3006{ 3007 3008 return vn_mkdir(uap->path, uap->mode, UIO_USERSPACE, td); 3009} 3010 3011int 3012vn_mkdir(path, mode, segflg, td) 3013 char *path; 3014 int mode; 3015 enum uio_seg segflg; 3016 struct thread *td; 3017{ 3018 struct mount *mp; 3019 struct vnode *vp; 3020 struct vattr vattr; 3021 int error; 3022 struct nameidata nd; 3023 3024restart: 3025 bwillwrite(); 3026 NDINIT(&nd, CREATE, LOCKPARENT, segflg, path, td); 3027 nd.ni_cnd.cn_flags |= WILLBEDIR; 3028 if ((error = namei(&nd)) != 0) 3029 return (error); 3030 vp = nd.ni_vp; 3031 if (vp != NULL) { 3032 NDFREE(&nd, NDF_ONLY_PNBUF); 3033 vrele(vp); 3034 vput(nd.ni_dvp); 3035 return (EEXIST); 3036 } 3037 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 3038 NDFREE(&nd, NDF_ONLY_PNBUF); 3039 vput(nd.ni_dvp); 3040 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) 3041 return (error); 3042 goto restart; 3043 } 3044 VATTR_NULL(&vattr); 3045 vattr.va_type = VDIR; 3046 vattr.va_mode = (mode & ACCESSPERMS) &~ td->td_proc->p_fd->fd_cmask; 3047 VOP_LEASE(nd.ni_dvp, td, td->td_proc->p_ucred, LEASE_WRITE); 3048 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 3049 NDFREE(&nd, NDF_ONLY_PNBUF); 3050 vput(nd.ni_dvp); 3051 if (!error) 3052 vput(nd.ni_vp); 3053 vn_finished_write(mp); 3054 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mkdir"); 3055 ASSERT_VOP_UNLOCKED(nd.ni_vp, "mkdir"); 3056 return (error); 3057} 3058 3059/* 3060 * Remove a directory file. 3061 */ 3062#ifndef _SYS_SYSPROTO_H_ 3063struct rmdir_args { 3064 char *path; 3065}; 3066#endif 3067/* ARGSUSED */ 3068int 3069rmdir(td, uap) 3070 struct thread *td; 3071 struct rmdir_args /* { 3072 syscallarg(char *) path; 3073 } */ *uap; 3074{ 3075 struct mount *mp; 3076 struct vnode *vp; 3077 int error; 3078 struct nameidata nd; 3079 3080restart: 3081 bwillwrite(); 3082 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, 3083 SCARG(uap, path), td); 3084 if ((error = namei(&nd)) != 0) 3085 return (error); 3086 vp = nd.ni_vp; 3087 if (vp->v_type != VDIR) { 3088 error = ENOTDIR; 3089 goto out; 3090 } 3091 /* 3092 * No rmdir "." please. 3093 */ 3094 if (nd.ni_dvp == vp) { 3095 error = EINVAL; 3096 goto out; 3097 } 3098 /* 3099 * The root of a mounted filesystem cannot be deleted. 3100 */ 3101 if (vp->v_flag & VROOT) { 3102 error = EBUSY; 3103 goto out; 3104 } 3105 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 3106 NDFREE(&nd, NDF_ONLY_PNBUF); 3107 if (nd.ni_dvp == vp) 3108 vrele(nd.ni_dvp); 3109 else 3110 vput(nd.ni_dvp); 3111 vput(vp); 3112 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) 3113 return (error); 3114 goto restart; 3115 } 3116 VOP_LEASE(nd.ni_dvp, td, td->td_proc->p_ucred, LEASE_WRITE); 3117 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE); 3118 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 3119 vn_finished_write(mp); 3120out: 3121 NDFREE(&nd, NDF_ONLY_PNBUF); 3122 if (nd.ni_dvp == vp) 3123 vrele(nd.ni_dvp); 3124 else 3125 vput(nd.ni_dvp); 3126 vput(vp); 3127 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "rmdir"); 3128 ASSERT_VOP_UNLOCKED(nd.ni_vp, "rmdir"); 3129 return (error); 3130} 3131 3132#ifdef COMPAT_43 3133/* 3134 * Read a block of directory entries in a file system independent format. 3135 */ 3136#ifndef _SYS_SYSPROTO_H_ 3137struct ogetdirentries_args { 3138 int fd; 3139 char *buf; 3140 u_int count; 3141 long *basep; 3142}; 3143#endif 3144int 3145ogetdirentries(td, uap) 3146 struct thread *td; 3147 register struct ogetdirentries_args /* { 3148 syscallarg(int) fd; 3149 syscallarg(char *) buf; 3150 syscallarg(u_int) count; 3151 syscallarg(long *) basep; 3152 } */ *uap; 3153{ 3154 struct vnode *vp; 3155 struct file *fp; 3156 struct uio auio, kuio; 3157 struct iovec aiov, kiov; 3158 struct dirent *dp, *edp; 3159 caddr_t dirbuf; 3160 int error, eofflag, readcnt; 3161 long loff; 3162 3163 /* XXX arbitrary sanity limit on `count'. */ 3164 if (SCARG(uap, count) > 64 * 1024) 3165 return (EINVAL); 3166 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 3167 return (error); 3168 if ((fp->f_flag & FREAD) == 0) 3169 return (EBADF); 3170 vp = (struct vnode *)fp->f_data; 3171unionread: 3172 if (vp->v_type != VDIR) 3173 return (EINVAL); 3174 aiov.iov_base = SCARG(uap, buf); 3175 aiov.iov_len = SCARG(uap, count); 3176 auio.uio_iov = &aiov; 3177 auio.uio_iovcnt = 1; 3178 auio.uio_rw = UIO_READ; 3179 auio.uio_segflg = UIO_USERSPACE; 3180 auio.uio_td = td; 3181 auio.uio_resid = SCARG(uap, count); 3182 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3183 loff = auio.uio_offset = fp->f_offset; 3184# if (BYTE_ORDER != LITTLE_ENDIAN) 3185 if (vp->v_mount->mnt_maxsymlinklen <= 0) { 3186 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, 3187 NULL, NULL); 3188 fp->f_offset = auio.uio_offset; 3189 } else 3190# endif 3191 { 3192 kuio = auio; 3193 kuio.uio_iov = &kiov; 3194 kuio.uio_segflg = UIO_SYSSPACE; 3195 kiov.iov_len = SCARG(uap, count); 3196 MALLOC(dirbuf, caddr_t, SCARG(uap, count), M_TEMP, M_WAITOK); 3197 kiov.iov_base = dirbuf; 3198 error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag, 3199 NULL, NULL); 3200 fp->f_offset = kuio.uio_offset; 3201 if (error == 0) { 3202 readcnt = SCARG(uap, count) - kuio.uio_resid; 3203 edp = (struct dirent *)&dirbuf[readcnt]; 3204 for (dp = (struct dirent *)dirbuf; dp < edp; ) { 3205# if (BYTE_ORDER == LITTLE_ENDIAN) 3206 /* 3207 * The expected low byte of 3208 * dp->d_namlen is our dp->d_type. 3209 * The high MBZ byte of dp->d_namlen 3210 * is our dp->d_namlen. 3211 */ 3212 dp->d_type = dp->d_namlen; 3213 dp->d_namlen = 0; 3214# else 3215 /* 3216 * The dp->d_type is the high byte 3217 * of the expected dp->d_namlen, 3218 * so must be zero'ed. 3219 */ 3220 dp->d_type = 0; 3221# endif 3222 if (dp->d_reclen > 0) { 3223 dp = (struct dirent *) 3224 ((char *)dp + dp->d_reclen); 3225 } else { 3226 error = EIO; 3227 break; 3228 } 3229 } 3230 if (dp >= edp) 3231 error = uiomove(dirbuf, readcnt, &auio); 3232 } 3233 FREE(dirbuf, M_TEMP); 3234 } 3235 VOP_UNLOCK(vp, 0, td); 3236 if (error) 3237 return (error); 3238 if (SCARG(uap, count) == auio.uio_resid) { 3239 if (union_dircheckp) { 3240 error = union_dircheckp(td, &vp, fp); 3241 if (error == -1) 3242 goto unionread; 3243 if (error) 3244 return (error); 3245 } 3246 if ((vp->v_flag & VROOT) && 3247 (vp->v_mount->mnt_flag & MNT_UNION)) { 3248 struct vnode *tvp = vp; 3249 vp = vp->v_mount->mnt_vnodecovered; 3250 VREF(vp); 3251 fp->f_data = (caddr_t) vp; 3252 fp->f_offset = 0; 3253 vrele(tvp); 3254 goto unionread; 3255 } 3256 } 3257 error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep), 3258 sizeof(long)); 3259 td->td_retval[0] = SCARG(uap, count) - auio.uio_resid; 3260 return (error); 3261} 3262#endif /* COMPAT_43 */ 3263 3264/* 3265 * Read a block of directory entries in a file system independent format. 3266 */ 3267#ifndef _SYS_SYSPROTO_H_ 3268struct getdirentries_args { 3269 int fd; 3270 char *buf; 3271 u_int count; 3272 long *basep; 3273}; 3274#endif 3275int 3276getdirentries(td, uap) 3277 struct thread *td; 3278 register struct getdirentries_args /* { 3279 syscallarg(int) fd; 3280 syscallarg(char *) buf; 3281 syscallarg(u_int) count; 3282 syscallarg(long *) basep; 3283 } */ *uap; 3284{ 3285 struct vnode *vp; 3286 struct file *fp; 3287 struct uio auio; 3288 struct iovec aiov; 3289 long loff; 3290 int error, eofflag; 3291 3292 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 3293 return (error); 3294 if ((fp->f_flag & FREAD) == 0) 3295 return (EBADF); 3296 vp = (struct vnode *)fp->f_data; 3297unionread: 3298 if (vp->v_type != VDIR) 3299 return (EINVAL); 3300 aiov.iov_base = SCARG(uap, buf); 3301 aiov.iov_len = SCARG(uap, count); 3302 auio.uio_iov = &aiov; 3303 auio.uio_iovcnt = 1; 3304 auio.uio_rw = UIO_READ; 3305 auio.uio_segflg = UIO_USERSPACE; 3306 auio.uio_td = td; 3307 auio.uio_resid = SCARG(uap, count); 3308 /* vn_lock(vp, LK_SHARED | LK_RETRY, td); */ 3309 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3310 loff = auio.uio_offset = fp->f_offset; 3311 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL, NULL); 3312 fp->f_offset = auio.uio_offset; 3313 VOP_UNLOCK(vp, 0, td); 3314 if (error) 3315 return (error); 3316 if (SCARG(uap, count) == auio.uio_resid) { 3317 if (union_dircheckp) { 3318 error = union_dircheckp(td, &vp, fp); 3319 if (error == -1) 3320 goto unionread; 3321 if (error) 3322 return (error); 3323 } 3324 if ((vp->v_flag & VROOT) && 3325 (vp->v_mount->mnt_flag & MNT_UNION)) { 3326 struct vnode *tvp = vp; 3327 vp = vp->v_mount->mnt_vnodecovered; 3328 VREF(vp); 3329 fp->f_data = (caddr_t) vp; 3330 fp->f_offset = 0; 3331 vrele(tvp); 3332 goto unionread; 3333 } 3334 } 3335 if (SCARG(uap, basep) != NULL) { 3336 error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep), 3337 sizeof(long)); 3338 } 3339 td->td_retval[0] = SCARG(uap, count) - auio.uio_resid; 3340 return (error); 3341} 3342#ifndef _SYS_SYSPROTO_H_ 3343struct getdents_args { 3344 int fd; 3345 char *buf; 3346 size_t count; 3347}; 3348#endif 3349int 3350getdents(td, uap) 3351 struct thread *td; 3352 register struct getdents_args /* { 3353 syscallarg(int) fd; 3354 syscallarg(char *) buf; 3355 syscallarg(u_int) count; 3356 } */ *uap; 3357{ 3358 struct getdirentries_args ap; 3359 ap.fd = uap->fd; 3360 ap.buf = uap->buf; 3361 ap.count = uap->count; 3362 ap.basep = NULL; 3363 return getdirentries(td, &ap); 3364} 3365 3366/* 3367 * Set the mode mask for creation of filesystem nodes. 3368 * 3369 * MP SAFE 3370 */ 3371#ifndef _SYS_SYSPROTO_H_ 3372struct umask_args { 3373 int newmask; 3374}; 3375#endif 3376int 3377umask(td, uap) 3378 struct thread *td; 3379 struct umask_args /* { 3380 syscallarg(int) newmask; 3381 } */ *uap; 3382{ 3383 register struct filedesc *fdp; 3384 3385 fdp = td->td_proc->p_fd; 3386 td->td_retval[0] = fdp->fd_cmask; 3387 fdp->fd_cmask = SCARG(uap, newmask) & ALLPERMS; 3388 return (0); 3389} 3390 3391/* 3392 * Void all references to file by ripping underlying filesystem 3393 * away from vnode. 3394 */ 3395#ifndef _SYS_SYSPROTO_H_ 3396struct revoke_args { 3397 char *path; 3398}; 3399#endif 3400/* ARGSUSED */ 3401int 3402revoke(td, uap) 3403 struct thread *td; 3404 register struct revoke_args /* { 3405 syscallarg(char *) path; 3406 } */ *uap; 3407{ 3408 struct mount *mp; 3409 struct vnode *vp; 3410 struct vattr vattr; 3411 int error; 3412 struct nameidata nd; 3413 3414 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 3415 if ((error = namei(&nd)) != 0) 3416 return (error); 3417 vp = nd.ni_vp; 3418 NDFREE(&nd, NDF_ONLY_PNBUF); 3419 if (vp->v_type != VCHR) { 3420 error = EINVAL; 3421 goto out; 3422 } 3423 error = VOP_GETATTR(vp, &vattr, td->td_proc->p_ucred, td); 3424 if (error) 3425 goto out; 3426 if (td->td_proc->p_ucred->cr_uid != vattr.va_uid) { 3427 error = suser_xxx(0, td->td_proc, PRISON_ROOT); 3428 if (error) 3429 goto out; 3430 } 3431 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 3432 goto out; 3433 if (vcount(vp) > 1) 3434 VOP_REVOKE(vp, REVOKEALL); 3435 vn_finished_write(mp); 3436out: 3437 vrele(vp); 3438 return (error); 3439} 3440 3441/* 3442 * Convert a user file descriptor to a kernel file entry. 3443 */ 3444int 3445getvnode(fdp, fd, fpp) 3446 struct filedesc *fdp; 3447 int fd; 3448 struct file **fpp; 3449{ 3450 struct file *fp; 3451 3452 if ((u_int)fd >= fdp->fd_nfiles || 3453 (fp = fdp->fd_ofiles[fd]) == NULL) 3454 return (EBADF); 3455 if (fp->f_type != DTYPE_VNODE && fp->f_type != DTYPE_FIFO) 3456 return (EINVAL); 3457 *fpp = fp; 3458 return (0); 3459} 3460/* 3461 * Get (NFS) file handle 3462 */ 3463#ifndef _SYS_SYSPROTO_H_ 3464struct getfh_args { 3465 char *fname; 3466 fhandle_t *fhp; 3467}; 3468#endif 3469int 3470getfh(td, uap) 3471 struct thread *td; 3472 register struct getfh_args *uap; 3473{ 3474 struct nameidata nd; 3475 fhandle_t fh; 3476 register struct vnode *vp; 3477 int error; 3478 3479 /* 3480 * Must be super user 3481 */ 3482 error = suser_td(td); 3483 if (error) 3484 return (error); 3485 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, td); 3486 error = namei(&nd); 3487 if (error) 3488 return (error); 3489 NDFREE(&nd, NDF_ONLY_PNBUF); 3490 vp = nd.ni_vp; 3491 bzero(&fh, sizeof(fh)); 3492 fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid; 3493 error = VFS_VPTOFH(vp, &fh.fh_fid); 3494 vput(vp); 3495 if (error) 3496 return (error); 3497 error = copyout(&fh, uap->fhp, sizeof (fh)); 3498 return (error); 3499} 3500 3501/* 3502 * syscall for the rpc.lockd to use to translate a NFS file handle into 3503 * an open descriptor. 3504 * 3505 * warning: do not remove the suser() call or this becomes one giant 3506 * security hole. 3507 */ 3508#ifndef _SYS_SYSPROTO_H_ 3509struct fhopen_args { 3510 const struct fhandle *u_fhp; 3511 int flags; 3512}; 3513#endif 3514int 3515fhopen(td, uap) 3516 struct thread *td; 3517 struct fhopen_args /* { 3518 syscallarg(const struct fhandle *) u_fhp; 3519 syscallarg(int) flags; 3520 } */ *uap; 3521{ 3522 struct proc *p = td->td_proc; 3523 struct mount *mp; 3524 struct vnode *vp; 3525 struct fhandle fhp; 3526 struct vattr vat; 3527 struct vattr *vap = &vat; 3528 struct flock lf; 3529 struct file *fp; 3530 register struct filedesc *fdp = p->p_fd; 3531 int fmode, mode, error, type; 3532 struct file *nfp; 3533 int indx; 3534 3535 /* 3536 * Must be super user 3537 */ 3538 error = suser_td(td); 3539 if (error) 3540 return (error); 3541 3542 fmode = FFLAGS(SCARG(uap, flags)); 3543 /* why not allow a non-read/write open for our lockd? */ 3544 if (((fmode & (FREAD | FWRITE)) == 0) || (fmode & O_CREAT)) 3545 return (EINVAL); 3546 error = copyin(SCARG(uap,u_fhp), &fhp, sizeof(fhp)); 3547 if (error) 3548 return(error); 3549 /* find the mount point */ 3550 mp = vfs_getvfs(&fhp.fh_fsid); 3551 if (mp == NULL) 3552 return (ESTALE); 3553 /* now give me my vnode, it gets returned to me locked */ 3554 error = VFS_FHTOVP(mp, &fhp.fh_fid, &vp); 3555 if (error) 3556 return (error); 3557 /* 3558 * from now on we have to make sure not 3559 * to forget about the vnode 3560 * any error that causes an abort must vput(vp) 3561 * just set error = err and 'goto bad;'. 3562 */ 3563 3564 /* 3565 * from vn_open 3566 */ 3567 if (vp->v_type == VLNK) { 3568 error = EMLINK; 3569 goto bad; 3570 } 3571 if (vp->v_type == VSOCK) { 3572 error = EOPNOTSUPP; 3573 goto bad; 3574 } 3575 mode = 0; 3576 if (fmode & (FWRITE | O_TRUNC)) { 3577 if (vp->v_type == VDIR) { 3578 error = EISDIR; 3579 goto bad; 3580 } 3581 error = vn_writechk(vp); 3582 if (error) 3583 goto bad; 3584 mode |= VWRITE; 3585 } 3586 if (fmode & FREAD) 3587 mode |= VREAD; 3588 if (mode) { 3589 error = VOP_ACCESS(vp, mode, p->p_ucred, td); 3590 if (error) 3591 goto bad; 3592 } 3593 if (fmode & O_TRUNC) { 3594 VOP_UNLOCK(vp, 0, td); /* XXX */ 3595 if ((error = vn_start_write(NULL, &mp, V_WAIT | PCATCH)) != 0) { 3596 vrele(vp); 3597 return (error); 3598 } 3599 VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE); 3600 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); /* XXX */ 3601 VATTR_NULL(vap); 3602 vap->va_size = 0; 3603 error = VOP_SETATTR(vp, vap, p->p_ucred, td); 3604 vn_finished_write(mp); 3605 if (error) 3606 goto bad; 3607 } 3608 error = VOP_OPEN(vp, fmode, p->p_ucred, td); 3609 if (error) 3610 goto bad; 3611 /* 3612 * Make sure that a VM object is created for VMIO support. 3613 */ 3614 if (vn_canvmio(vp) == TRUE) { 3615 if ((error = vfs_object_create(vp, td, p->p_ucred)) != 0) 3616 goto bad; 3617 } 3618 if (fmode & FWRITE) 3619 vp->v_writecount++; 3620 3621 /* 3622 * end of vn_open code 3623 */ 3624 3625 if ((error = falloc(td, &nfp, &indx)) != 0) 3626 goto bad; 3627 fp = nfp; 3628 3629 /* 3630 * Hold an extra reference to avoid having fp ripped out 3631 * from under us while we block in the lock op 3632 */ 3633 fhold(fp); 3634 nfp->f_data = (caddr_t)vp; 3635 nfp->f_flag = fmode & FMASK; 3636 nfp->f_ops = &vnops; 3637 nfp->f_type = DTYPE_VNODE; 3638 if (fmode & (O_EXLOCK | O_SHLOCK)) { 3639 lf.l_whence = SEEK_SET; 3640 lf.l_start = 0; 3641 lf.l_len = 0; 3642 if (fmode & O_EXLOCK) 3643 lf.l_type = F_WRLCK; 3644 else 3645 lf.l_type = F_RDLCK; 3646 type = F_FLOCK; 3647 if ((fmode & FNONBLOCK) == 0) 3648 type |= F_WAIT; 3649 VOP_UNLOCK(vp, 0, td); 3650 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0) { 3651 /* 3652 * The lock request failed. Normally close the 3653 * descriptor but handle the case where someone might 3654 * have dup()d or close()d it when we weren't looking. 3655 */ 3656 if (fdp->fd_ofiles[indx] == fp) { 3657 fdp->fd_ofiles[indx] = NULL; 3658 fdrop(fp, td); 3659 } 3660 /* 3661 * release our private reference 3662 */ 3663 fdrop(fp, td); 3664 return(error); 3665 } 3666 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3667 fp->f_flag |= FHASLOCK; 3668 } 3669 if ((vp->v_type == VREG) && (VOP_GETVOBJECT(vp, NULL) != 0)) 3670 vfs_object_create(vp, td, p->p_ucred); 3671 3672 VOP_UNLOCK(vp, 0, td); 3673 fdrop(fp, td); 3674 td->td_retval[0] = indx; 3675 return (0); 3676 3677bad: 3678 vput(vp); 3679 return (error); 3680} 3681 3682/* 3683 * Stat an (NFS) file handle. 3684 */ 3685#ifndef _SYS_SYSPROTO_H_ 3686struct fhstat_args { 3687 struct fhandle *u_fhp; 3688 struct stat *sb; 3689}; 3690#endif 3691int 3692fhstat(td, uap) 3693 struct thread *td; 3694 register struct fhstat_args /* { 3695 syscallarg(struct fhandle *) u_fhp; 3696 syscallarg(struct stat *) sb; 3697 } */ *uap; 3698{ 3699 struct stat sb; 3700 fhandle_t fh; 3701 struct mount *mp; 3702 struct vnode *vp; 3703 int error; 3704 3705 /* 3706 * Must be super user 3707 */ 3708 error = suser_td(td); 3709 if (error) 3710 return (error); 3711 3712 error = copyin(SCARG(uap, u_fhp), &fh, sizeof(fhandle_t)); 3713 if (error) 3714 return (error); 3715 3716 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) 3717 return (ESTALE); 3718 if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp))) 3719 return (error); 3720 error = vn_stat(vp, &sb, td); 3721 vput(vp); 3722 if (error) 3723 return (error); 3724 error = copyout(&sb, SCARG(uap, sb), sizeof(sb)); 3725 return (error); 3726} 3727 3728/* 3729 * Implement fstatfs() for (NFS) file handles. 3730 */ 3731#ifndef _SYS_SYSPROTO_H_ 3732struct fhstatfs_args { 3733 struct fhandle *u_fhp; 3734 struct statfs *buf; 3735}; 3736#endif 3737int 3738fhstatfs(td, uap) 3739 struct thread *td; 3740 struct fhstatfs_args /* { 3741 syscallarg(struct fhandle) *u_fhp; 3742 syscallarg(struct statfs) *buf; 3743 } */ *uap; 3744{ 3745 struct statfs *sp; 3746 struct mount *mp; 3747 struct vnode *vp; 3748 struct statfs sb; 3749 fhandle_t fh; 3750 int error; 3751 3752 /* 3753 * Must be super user 3754 */ 3755 error = suser_td(td); 3756 if (error) 3757 return (error); 3758 3759 if ((error = copyin(SCARG(uap, u_fhp), &fh, sizeof(fhandle_t))) != 0) 3760 return (error); 3761 3762 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) 3763 return (ESTALE); 3764 if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp))) 3765 return (error); 3766 mp = vp->v_mount; 3767 sp = &mp->mnt_stat; 3768 vput(vp); 3769 if ((error = VFS_STATFS(mp, sp, td)) != 0) 3770 return (error); 3771 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 3772 if (suser_xxx(td->td_proc->p_ucred, 0, 0)) { 3773 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); 3774 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; 3775 sp = &sb; 3776 } 3777 return (copyout(sp, SCARG(uap, buf), sizeof(*sp))); 3778} 3779 3780/* 3781 * Syscall to push extended attribute configuration information into the 3782 * VFS. Accepts a path, which it converts to a mountpoint, as well as 3783 * a command (int cmd), and attribute name and misc data. For now, the 3784 * attribute name is left in userspace for consumption by the VFS_op. 3785 * It will probably be changed to be copied into sysspace by the 3786 * syscall in the future, once issues with various consumers of the 3787 * attribute code have raised their hands. 3788 * 3789 * Currently this is used only by UFS Extended Attributes. 3790 */ 3791int 3792extattrctl(td, uap) 3793 struct thread *td; 3794 struct extattrctl_args *uap; 3795{ 3796 struct vnode *filename_vp; 3797 struct nameidata nd; 3798 struct mount *mp; 3799 char attrname[EXTATTR_MAXNAMELEN]; 3800 int error; 3801 3802 /* 3803 * SCARG(uap, attrname) not always defined. We check again later 3804 * when we invoke the VFS call so as to pass in NULL there if needed. 3805 */ 3806 if (SCARG(uap, attrname) != NULL) { 3807 error = copyinstr(SCARG(uap, attrname), attrname, 3808 EXTATTR_MAXNAMELEN, NULL); 3809 if (error) 3810 return (error); 3811 } 3812 3813 /* 3814 * SCARG(uap, filename) not always defined. If it is, grab 3815 * a vnode lock, which VFS_EXTATTRCTL() will later release. 3816 */ 3817 filename_vp = NULL; 3818 if (SCARG(uap, filename) != NULL) { 3819 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 3820 SCARG(uap, filename), td); 3821 if ((error = namei(&nd)) != 0) 3822 return (error); 3823 filename_vp = nd.ni_vp; 3824 NDFREE(&nd, NDF_NO_VP_RELE | NDF_NO_VP_UNLOCK); 3825 } 3826 3827 /* SCARG(uap, path) always defined. */ 3828 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 3829 if ((error = namei(&nd)) != 0) 3830 return (error); 3831 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 3832 NDFREE(&nd, 0); 3833 if (error) { 3834 if (filename_vp) 3835 vrele(filename_vp); 3836 return (error); 3837 } 3838 3839 if (SCARG(uap, attrname) != NULL) { 3840 error = VFS_EXTATTRCTL(mp, SCARG(uap, cmd), filename_vp, 3841 SCARG(uap, attrnamespace), attrname, td); 3842 } else { 3843 error = VFS_EXTATTRCTL(mp, SCARG(uap, cmd), filename_vp, 3844 SCARG(uap, attrnamespace), NULL, td); 3845 } 3846 3847 vn_finished_write(mp); 3848 /* 3849 * VFS_EXTATTRCTL will have unlocked, but not de-ref'd, 3850 * filename_vp, so vrele it if it is defined. 3851 */ 3852 if (filename_vp != NULL) 3853 vrele(filename_vp); 3854 3855 return (error); 3856} 3857 3858/* 3859 * extattr_set_vp(): Set a named extended attribute on a file or directory 3860 * 3861 * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace", 3862 * kernelspace string pointer "attrname", 3863 * userspace iovec array pointer "iovp", unsigned int iovcnt 3864 * proc "p" 3865 * Returns: 0 on success, an error number otherwise 3866 * Locks: none 3867 * References: vp must be a valid reference for the duration of the call 3868 */ 3869static int 3870extattr_set_vp(struct vnode *vp, int attrnamespace, const char *attrname, 3871 struct iovec *iovp, unsigned iovcnt, struct thread *td) 3872{ 3873 struct mount *mp; 3874 struct uio auio; 3875 struct iovec *iov, *needfree = NULL, aiov[UIO_SMALLIOV]; 3876 u_int iovlen, cnt; 3877 int error, i; 3878 3879 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 3880 return (error); 3881 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE); 3882 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3883 3884 iovlen = iovcnt * sizeof(struct iovec); 3885 if (iovcnt > UIO_SMALLIOV) { 3886 if (iovcnt > UIO_MAXIOV) { 3887 error = EINVAL; 3888 goto done; 3889 } 3890 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); 3891 needfree = iov; 3892 } else 3893 iov = aiov; 3894 auio.uio_iov = iov; 3895 auio.uio_iovcnt = iovcnt; 3896 auio.uio_rw = UIO_WRITE; 3897 auio.uio_segflg = UIO_USERSPACE; 3898 auio.uio_td = td; 3899 auio.uio_offset = 0; 3900 if ((error = copyin((caddr_t)iovp, (caddr_t)iov, iovlen))) 3901 goto done; 3902 auio.uio_resid = 0; 3903 for (i = 0; i < iovcnt; i++) { 3904 if (iov->iov_len > INT_MAX - auio.uio_resid) { 3905 error = EINVAL; 3906 goto done; 3907 } 3908 auio.uio_resid += iov->iov_len; 3909 iov++; 3910 } 3911 cnt = auio.uio_resid; 3912 error = VOP_SETEXTATTR(vp, attrnamespace, attrname, &auio, 3913 td->td_proc->p_ucred, td); 3914 cnt -= auio.uio_resid; 3915 td->td_retval[0] = cnt; 3916done: 3917 if (needfree) 3918 FREE(needfree, M_IOV); 3919 VOP_UNLOCK(vp, 0, td); 3920 vn_finished_write(mp); 3921 return (error); 3922} 3923 3924int 3925extattr_set_file(td, uap) 3926 struct thread *td; 3927 struct extattr_set_file_args *uap; 3928{ 3929 struct nameidata nd; 3930 char attrname[EXTATTR_MAXNAMELEN]; 3931 int error; 3932 3933 error = copyinstr(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN, 3934 NULL); 3935 if (error) 3936 return (error); 3937 3938 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 3939 if ((error = namei(&nd)) != 0) 3940 return (error); 3941 NDFREE(&nd, NDF_ONLY_PNBUF); 3942 3943 error = extattr_set_vp(nd.ni_vp, SCARG(uap, attrnamespace), attrname, 3944 SCARG(uap, iovp), SCARG(uap, iovcnt), td); 3945 3946 vrele(nd.ni_vp); 3947 return (error); 3948} 3949 3950int 3951extattr_set_fd(td, uap) 3952 struct thread *td; 3953 struct extattr_set_fd_args *uap; 3954{ 3955 struct file *fp; 3956 char attrname[EXTATTR_MAXNAMELEN]; 3957 int error; 3958 3959 error = copyinstr(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN, 3960 NULL); 3961 if (error) 3962 return (error); 3963 3964 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 3965 return (error); 3966 3967 error = extattr_set_vp((struct vnode *)fp->f_data, 3968 SCARG(uap, attrnamespace), attrname, SCARG(uap, iovp), 3969 SCARG(uap, iovcnt), td); 3970 3971 return (error); 3972} 3973 3974/* 3975 * extattr_get_vp(): Get a named extended attribute on a file or directory 3976 * 3977 * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace", 3978 * kernelspace string pointer "attrname", 3979 * userspace iovec array pointer "iovp", unsigned int iovcnt, 3980 * proc "p" 3981 * Returns: 0 on success, an error number otherwise 3982 * Locks: none 3983 * References: vp must be a valid reference for the duration of the call 3984 */ 3985static int 3986extattr_get_vp(struct vnode *vp, int attrnamespace, const char *attrname, 3987 struct iovec *iovp, unsigned iovcnt, struct thread *td) 3988{ 3989 struct uio auio; 3990 struct iovec *iov, *needfree = NULL, aiov[UIO_SMALLIOV]; 3991 u_int iovlen, cnt; 3992 int error, i; 3993 3994 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_READ); 3995 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3996 3997 iovlen = iovcnt * sizeof (struct iovec); 3998 if (iovcnt > UIO_SMALLIOV) { 3999 if (iovcnt > UIO_MAXIOV) { 4000 error = EINVAL; 4001 goto done; 4002 } 4003 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); 4004 needfree = iov; 4005 } else 4006 iov = aiov; 4007 auio.uio_iov = iov; 4008 auio.uio_iovcnt = iovcnt; 4009 auio.uio_rw = UIO_READ; 4010 auio.uio_segflg = UIO_USERSPACE; 4011 auio.uio_td = td; 4012 auio.uio_offset = 0; 4013 if ((error = copyin((caddr_t)iovp, (caddr_t)iov, iovlen))) 4014 goto done; 4015 auio.uio_resid = 0; 4016 for (i = 0; i < iovcnt; i++) { 4017 if (iov->iov_len > INT_MAX - auio.uio_resid) { 4018 error = EINVAL; 4019 goto done; 4020 } 4021 auio.uio_resid += iov->iov_len; 4022 iov++; 4023 } 4024 cnt = auio.uio_resid; 4025 error = VOP_GETEXTATTR(vp, attrnamespace, attrname, &auio, 4026 td->td_proc->p_ucred, td); 4027 cnt -= auio.uio_resid; 4028 td->td_retval[0] = cnt; 4029done: 4030 if (needfree) 4031 FREE(needfree, M_IOV); 4032 VOP_UNLOCK(vp, 0, td); 4033 return (error); 4034} 4035 4036int 4037extattr_get_file(td, uap) 4038 struct thread *td; 4039 struct extattr_get_file_args *uap; 4040{ 4041 struct nameidata nd; 4042 char attrname[EXTATTR_MAXNAMELEN]; 4043 int error; 4044 4045 error = copyinstr(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN, 4046 NULL); 4047 if (error) 4048 return (error); 4049 4050 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 4051 if ((error = namei(&nd)) != 0) 4052 return (error); 4053 NDFREE(&nd, NDF_ONLY_PNBUF); 4054 4055 error = extattr_get_vp(nd.ni_vp, SCARG(uap, attrnamespace), attrname, 4056 SCARG(uap, iovp), SCARG(uap, iovcnt), td); 4057 4058 vrele(nd.ni_vp); 4059 return (error); 4060} 4061 4062int 4063extattr_get_fd(td, uap) 4064 struct thread *td; 4065 struct extattr_get_fd_args *uap; 4066{ 4067 struct file *fp; 4068 char attrname[EXTATTR_MAXNAMELEN]; 4069 int error; 4070 4071 error = copyinstr(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN, 4072 NULL); 4073 if (error) 4074 return (error); 4075 4076 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 4077 return (error); 4078 4079 error = extattr_get_vp((struct vnode *)fp->f_data, 4080 SCARG(uap, attrnamespace), attrname, SCARG(uap, iovp), 4081 SCARG(uap, iovcnt), td); 4082 4083 return (error); 4084} 4085 4086/* 4087 * extattr_delete_vp(): Delete a named extended attribute on a file or 4088 * directory 4089 * 4090 * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace", 4091 * kernelspace string pointer "attrname", proc "p" 4092 * Returns: 0 on success, an error number otherwise 4093 * Locks: none 4094 * References: vp must be a valid reference for the duration of the call 4095 */ 4096static int 4097extattr_delete_vp(struct vnode *vp, int attrnamespace, const char *attrname, 4098 struct thread *td) 4099{ 4100 struct mount *mp; 4101 int error; 4102 4103 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 4104 return (error); 4105 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE); 4106 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 4107 4108 error = VOP_SETEXTATTR(vp, attrnamespace, attrname, NULL, 4109 td->td_proc->p_ucred, td); 4110 4111 VOP_UNLOCK(vp, 0, td); 4112 vn_finished_write(mp); 4113 return (error); 4114} 4115 4116int 4117extattr_delete_file(td, uap) 4118 struct thread *td; 4119 struct extattr_delete_file_args *uap; 4120{ 4121 struct nameidata nd; 4122 char attrname[EXTATTR_MAXNAMELEN]; 4123 int error; 4124 4125 error = copyinstr(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN, 4126 NULL); 4127 if (error) 4128 return(error); 4129 4130 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 4131 if ((error = namei(&nd)) != 0) 4132 return(error); 4133 NDFREE(&nd, NDF_ONLY_PNBUF); 4134 4135 error = extattr_delete_vp(nd.ni_vp, SCARG(uap, attrnamespace), 4136 attrname, td); 4137 4138 vrele(nd.ni_vp); 4139 return(error); 4140} 4141 4142int 4143extattr_delete_fd(td, uap) 4144 struct thread *td; 4145 struct extattr_delete_fd_args *uap; 4146{ 4147 struct file *fp; 4148 char attrname[EXTATTR_MAXNAMELEN]; 4149 int error; 4150 4151 error = copyinstr(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN, 4152 NULL); 4153 if (error) 4154 return (error); 4155 4156 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 4157 return (error); 4158 4159 error = extattr_delete_vp((struct vnode *)fp->f_data, 4160 SCARG(uap, attrnamespace), attrname, td); 4161 4162 return (error); 4163}
|