summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md2
-rw-r--r--src/unistd.rs13
-rw-r--r--test/test_unistd.rs19
3 files changed, 34 insertions, 0 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 02b07899..1a090b35 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -28,6 +28,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
([#457](https://github.com/nix-rust/nix/pull/457))
- Added `getpgrp` in `::nix::unistd`
([#491](https://github.com/nix-rust/nix/pull/491))
+- Added `fchdir` in `::nix::unistd`
+ ([#497](https://github.com/nix-rust/nix/pull/497))
### Changed
- `epoll_ctl` now could accept None as argument `event`
diff --git a/src/unistd.rs b/src/unistd.rs
index 6382267f..187154bd 100644
--- a/src/unistd.rs
+++ b/src/unistd.rs
@@ -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
diff --git a/test/test_unistd.rs b/test/test_unistd.rs
index d281f9b2..76ab442a 100644
--- a/test/test_unistd.rs
+++ b/test/test_unistd.rs
@@ -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;
@@ -142,6 +143,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();
assert!(chdir(tmp_dir.path()).is_ok());