Skip to content

Commit 515bee4

Browse files
committed
sys/stat: implement mkdirat
1 parent 83407c5 commit 515bee4

File tree

3 files changed

+47
-3
lines changed

3 files changed

+47
-3
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
77
### Added
88
- Added `MSG_WAITALL` to `MsgFlags` in `sys::socket`.
99
([#1079](https://github.com/nix-rust/nix/pull/1079))
10+
- Add `mkdirat`.
11+
([#1084](https://github.com/nix-rust/nix/pull/1084))
1012

1113
### Changed
1214
- Support for `ifaddrs` now present when building for Android.

src/sys/stat.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,3 +284,11 @@ pub fn utimensat<P: ?Sized + NixPath>(
284284

285285
Errno::result(res).map(drop)
286286
}
287+
288+
pub fn mkdirat<P: ?Sized + NixPath>(fd: RawFd, path: &P, mode: Mode) -> Result<()> {
289+
let res = path.with_nix_path(|cstr| {
290+
unsafe { libc::mkdirat(fd, cstr.as_ptr(), mode.bits() as mode_t) }
291+
})?;
292+
293+
Errno::result(res).map(drop)
294+
}

test/test_stat.rs

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
use std::fs::{self, File};
2-
use std::os::unix::fs::symlink;
2+
use std::os::unix::fs::{symlink, PermissionsExt};
33
use std::os::unix::prelude::AsRawFd;
44
use std::time::{Duration, UNIX_EPOCH};
5+
use std::path::Path;
56

67
#[cfg(not(any(target_os = "netbsd")))]
7-
use libc::{S_IFMT, S_IFLNK};
8+
use libc::{S_IFMT, S_IFLNK, mode_t};
89

910
use nix::fcntl;
10-
use nix::sys::stat::{self, fchmod, fchmodat, futimens, stat, utimes, utimensat};
11+
use nix::sys::stat::{self, fchmod, fchmodat, futimens, stat, utimes, utimensat, mkdirat};
1112
#[cfg(any(target_os = "linux",
1213
target_os = "haiku",
1314
target_os = "ios",
@@ -260,3 +261,36 @@ fn test_utimensat() {
260261
UtimensatFlags::FollowSymlink).unwrap();
261262
assert_times_eq(500, 800, &fs::metadata(&fullpath).unwrap());
262263
}
264+
265+
#[test]
266+
fn test_mkdirat_success_path() {
267+
let tempdir = tempfile::tempdir().unwrap();
268+
let filename = "example_subdir";
269+
let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
270+
assert!((mkdirat(dirfd, filename, Mode::S_IRWXU)).is_ok());
271+
assert!(Path::exists(&tempdir.path().join(filename)));
272+
}
273+
274+
#[test]
275+
fn test_mkdirat_success_mode() {
276+
let expected_bits = stat::SFlag::S_IFDIR.bits() | stat::Mode::S_IRWXU.bits();
277+
let tempdir = tempfile::tempdir().unwrap();
278+
let filename = "example_subdir";
279+
let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
280+
assert!((mkdirat(dirfd, filename, Mode::S_IRWXU)).is_ok());
281+
let permissions = fs::metadata(tempdir.path().join(filename)).unwrap().permissions();
282+
let mode = permissions.mode();
283+
assert_eq!(mode as mode_t, expected_bits)
284+
}
285+
286+
#[test]
287+
#[should_panic="EACCES"]
288+
fn test_mkdirat_fail() {
289+
let tempdir = tempfile::tempdir().unwrap();
290+
let filename = "example_subdir";
291+
let mut perms = fs::metadata(tempdir.path()).unwrap().permissions();
292+
perms.set_readonly(true);
293+
fs::set_permissions(tempdir.path(), perms).unwrap();
294+
let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
295+
let result = mkdirat(dirfd, filename, Mode::S_IRWXU).unwrap();
296+
}

0 commit comments

Comments
 (0)