| 883 | }; |
| 884 | #endif |
| 885 | int |
| 886 | sys_fchdir(struct thread *td, struct fchdir_args *uap) |
| 887 | { |
| 888 | struct vnode *vp, *tdp; |
| 889 | struct mount *mp; |
| 890 | struct file *fp; |
| 891 | int error; |
| 892 | |
| 893 | AUDIT_ARG_FD(uap->fd); |
| 894 | error = getvnode(td, uap->fd, &cap_fchdir_rights, |
| 895 | &fp); |
| 896 | if (error != 0) |
| 897 | return (error); |
| 898 | vp = fp->f_vnode; |
| 899 | vrefact(vp); |
| 900 | fdrop(fp, td); |
| 901 | vn_lock(vp, LK_SHARED | LK_RETRY); |
| 902 | AUDIT_ARG_VNODE1(vp); |
| 903 | error = change_dir(vp, td); |
| 904 | while (!error && (mp = vp->v_mountedhere) != NULL) { |
| 905 | if (vfs_busy(mp, 0)) |
| 906 | continue; |
| 907 | error = VFS_ROOT(mp, LK_SHARED, &tdp); |
| 908 | vfs_unbusy(mp); |
| 909 | if (error != 0) |
| 910 | break; |
| 911 | vput(vp); |
| 912 | vp = tdp; |
| 913 | } |
| 914 | if (error != 0) { |
| 915 | vput(vp); |
| 916 | return (error); |
| 917 | } |
| 918 | VOP_UNLOCK(vp); |
| 919 | pwd_chdir(td, vp); |
| 920 | return (0); |
| 921 | } |
| 922 | |
| 923 | /* |
| 924 | * Change current working directory (``.''). |
nothing calls this directly
no test coverage detected