Skip to content

Commit be1ae93

Browse files
committed
unistd: add fchdir(2)
This introduces a wrapper for fchdir(2), allowing a process to change directory based on an open file descriptor. The underlying function is available in libc crate since 0.2.20.
1 parent 3b07168 commit be1ae93

File tree

2 files changed

+32
-0
lines changed

2 files changed

+32
-0
lines changed

src/unistd.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,19 @@ pub fn chdir<P: ?Sized + NixPath>(path: &P) -> Result<()> {
249249
Errno::result(res).map(drop)
250250
}
251251

252+
/// Change the current working directory of the process to the one
253+
/// given as an open file descriptor (see
254+
/// [fchdir(2)](http://man7.org/linux/man-pages/man2/fchdir.2.html)).
255+
///
256+
/// This function may fail in a number of different scenarios. See the man
257+
/// pages for additional details on possible failure cases.
258+
#[inline]
259+
pub fn fchdir(dirfd: RawFd) -> Result<()> {
260+
let res = unsafe { libc::fchdir(dirfd) };
261+
262+
Errno::result(res).map(drop)
263+
}
264+
252265
/// Creates new directory `path` with access rights `mode`.
253266
///
254267
/// # Errors

test/test_unistd.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use nix::sys::wait::*;
66
use nix::sys::stat;
77
use std::iter;
88
use std::ffi::CString;
9+
use std::fs::File;
910
use std::io::{Write, Read};
1011
use std::os::unix::prelude::*;
1112
use std::env::current_dir;
@@ -141,6 +142,24 @@ macro_rules! execve_test_factory(
141142
)
142143
);
143144

145+
#[test]
146+
fn test_fchdir() {
147+
let tmpdir = TempDir::new("test_fchdir").unwrap();
148+
let tmpdir_path = tmpdir.path().canonicalize().unwrap();
149+
let tmpdir_fd = File::open(&tmpdir_path).unwrap().into_raw_fd();
150+
let olddir_path = getcwd().unwrap();
151+
let olddir_fd = File::open(&olddir_path).unwrap().into_raw_fd();
152+
153+
assert!(fchdir(tmpdir_fd).is_ok());
154+
assert_eq!(getcwd().unwrap(), tmpdir_path);
155+
156+
assert!(fchdir(olddir_fd).is_ok());
157+
assert_eq!(getcwd().unwrap(), olddir_path);
158+
159+
assert!(close(olddir_fd).is_ok());
160+
assert!(close(tmpdir_fd).is_ok());
161+
}
162+
144163
#[test]
145164
fn test_getcwd() {
146165
let tmp_dir = TempDir::new("test_getcwd").unwrap();

0 commit comments

Comments
 (0)