diff options
author | Kevin Wern <kevin.m.wern@gmail.com> | 2019-06-09 21:10:10 -0400 |
---|---|---|
committer | Kevin Wern <kevin.m.wern@gmail.com> | 2019-06-15 23:13:20 -0400 |
commit | c00649152177ef9e6c9b647655eb676c766fe375 (patch) | |
tree | 6817c1f4d3121edd8d5f4e51875ec9c66eab55e5 | |
parent | 582846e501c7de184351ddf4f22a143648e8c675 (diff) | |
download | nix-c00649152177ef9e6c9b647655eb676c766fe375.zip |
sys/stat: implement mkdirat
-rw-r--r-- | CHANGELOG.md | 2 | ||||
-rw-r--r-- | src/sys/stat.rs | 8 | ||||
-rw-r--r-- | test/test_stat.rs | 42 |
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)); +} |