summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Wern <kevin.m.wern@gmail.com>2019-06-09 21:10:10 -0400
committerKevin Wern <kevin.m.wern@gmail.com>2019-06-15 23:13:20 -0400
commitc00649152177ef9e6c9b647655eb676c766fe375 (patch)
tree6817c1f4d3121edd8d5f4e51875ec9c66eab55e5
parent582846e501c7de184351ddf4f22a143648e8c675 (diff)
downloadnix-c00649152177ef9e6c9b647655eb676c766fe375.zip
sys/stat: implement mkdirat
-rw-r--r--CHANGELOG.md2
-rw-r--r--src/sys/stat.rs8
-rw-r--r--test/test_stat.rs42
3 files changed, 48 insertions, 4 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 16b7992d..c7295756 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
types that support them. ([#1035](https://github.com/nix-rust/nix/pull/1035))
- Added `copy_file_range` wrapper
([#1069](https://github.com/nix-rust/nix/pull/1069))
+- Add `mkdirat`.
+ ([#1084](https://github.com/nix-rust/nix/pull/1084))
### Changed
- Support for `ifaddrs` now present when building for Android.
diff --git a/src/sys/stat.rs b/src/sys/stat.rs
index 1e0936ed..66c8c9dd 100644
--- a/src/sys/stat.rs
+++ b/src/sys/stat.rs
@@ -284,3 +284,11 @@ pub fn utimensat<P: ?Sized + NixPath>(
Errno::result(res).map(drop)
}
+
+pub fn mkdirat<P: ?Sized + NixPath>(fd: RawFd, path: &P, mode: Mode) -> Result<()> {
+ let res = path.with_nix_path(|cstr| {
+ unsafe { libc::mkdirat(fd, cstr.as_ptr(), mode.bits() as mode_t) }
+ })?;
+
+ Errno::result(res).map(drop)
+}
diff --git a/test/test_stat.rs b/test/test_stat.rs
index b9da7fc3..1173455f 100644
--- a/test/test_stat.rs
+++ b/test/test_stat.rs
@@ -1,13 +1,15 @@
use std::fs::{self, File};
-use std::os::unix::fs::symlink;
+use std::os::unix::fs::{symlink, PermissionsExt};
use std::os::unix::prelude::AsRawFd;
use std::time::{Duration, UNIX_EPOCH};
+use std::path::Path;
#[cfg(not(any(target_os = "netbsd")))]
-use libc::{S_IFMT, S_IFLNK};
+use libc::{S_IFMT, S_IFLNK, mode_t};
-use nix::fcntl;
-use nix::sys::stat::{self, fchmod, fchmodat, futimens, stat, utimes, utimensat};
+use nix::{fcntl, Error};
+use nix::errno::{Errno};
+use nix::sys::stat::{self, fchmod, fchmodat, futimens, stat, utimes, utimensat, mkdirat};
#[cfg(any(target_os = "linux",
target_os = "haiku",
target_os = "ios",
@@ -260,3 +262,35 @@ fn test_utimensat() {
UtimensatFlags::FollowSymlink).unwrap();
assert_times_eq(500, 800, &fs::metadata(&fullpath).unwrap());
}
+
+#[test]
+fn test_mkdirat_success_path() {
+ let tempdir = tempfile::tempdir().unwrap();
+ let filename = "example_subdir";
+ let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
+ assert!((mkdirat(dirfd, filename, Mode::S_IRWXU)).is_ok());
+ assert!(Path::exists(&tempdir.path().join(filename)));
+}
+
+#[test]
+fn test_mkdirat_success_mode() {
+ let expected_bits = stat::SFlag::S_IFDIR.bits() | stat::Mode::S_IRWXU.bits();
+ let tempdir = tempfile::tempdir().unwrap();
+ let filename = "example_subdir";
+ let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
+ assert!((mkdirat(dirfd, filename, Mode::S_IRWXU)).is_ok());
+ let permissions = fs::metadata(tempdir.path().join(filename)).unwrap().permissions();
+ let mode = permissions.mode();
+ assert_eq!(mode as mode_t, expected_bits)
+}
+
+#[test]
+fn test_mkdirat_fail() {
+ let tempdir = tempfile::tempdir().unwrap();
+ let not_dir_filename= "example_not_dir";
+ let filename = "example_subdir_dir";
+ let dirfd = fcntl::open(&tempdir.path().join(not_dir_filename), fcntl::OFlag::O_CREAT,
+ stat::Mode::empty()).unwrap();
+ let result = mkdirat(dirfd, filename, Mode::S_IRWXU).unwrap_err();
+ assert_eq!(result, Error::Sys(Errno::ENOTDIR));
+}