Skip to content

Commit

Permalink
unistd: add fchdir(2)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
lucab committed Jan 19, 2017
1 parent 3b07168 commit be1ae93
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 0 deletions.
13 changes: 13 additions & 0 deletions src/unistd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,19 @@ pub fn chdir<P: ?Sized + NixPath>(path: &P) -> Result<()> {
Errno::result(res).map(drop)
}

/// Change the current working directory of the process to the one
/// given as an open file descriptor (see
/// [fchdir(2)](http://man7.org/linux/man-pages/man2/fchdir.2.html)).
///
/// This function may fail in a number of different scenarios. See the man
/// pages for additional details on possible failure cases.
#[inline]
pub fn fchdir(dirfd: RawFd) -> Result<()> {
let res = unsafe { libc::fchdir(dirfd) };

Errno::result(res).map(drop)
}

/// Creates new directory `path` with access rights `mode`.
///
/// # Errors
Expand Down
19 changes: 19 additions & 0 deletions test/test_unistd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use nix::sys::wait::*;
use nix::sys::stat;
use std::iter;
use std::ffi::CString;
use std::fs::File;
use std::io::{Write, Read};
use std::os::unix::prelude::*;
use std::env::current_dir;
Expand Down Expand Up @@ -141,6 +142,24 @@ macro_rules! execve_test_factory(
)
);

#[test]
fn test_fchdir() {
let tmpdir = TempDir::new("test_fchdir").unwrap();
let tmpdir_path = tmpdir.path().canonicalize().unwrap();
let tmpdir_fd = File::open(&tmpdir_path).unwrap().into_raw_fd();
let olddir_path = getcwd().unwrap();
let olddir_fd = File::open(&olddir_path).unwrap().into_raw_fd();

assert!(fchdir(tmpdir_fd).is_ok());
assert_eq!(getcwd().unwrap(), tmpdir_path);

assert!(fchdir(olddir_fd).is_ok());
assert_eq!(getcwd().unwrap(), olddir_path);

assert!(close(olddir_fd).is_ok());
assert!(close(tmpdir_fd).is_ok());
}

#[test]
fn test_getcwd() {
let tmp_dir = TempDir::new("test_getcwd").unwrap();
Expand Down

0 comments on commit be1ae93

Please sign in to comment.