diff --git a/CHANGELOG.md b/CHANGELOG.md index d5d4528bff..c89eaac580 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). ([#739](https://github.com/nix-rust/nix/pull/739)) - Added nix::sys::ptrace::detach. ([#749](https://github.com/nix-rust/nix/pull/749)) +- Added nix::sys::stat::mknod + ([#747](https://github.com/nix-rust/nix/pull/747)) ### Changed - Renamed existing `ptrace` wrappers to encourage namespacing ([#692](https://github.com/nix-rust/nix/pull/692)) diff --git a/src/sys/stat.rs b/src/sys/stat.rs index 7a0b3970ce..001f931c68 100644 --- a/src/sys/stat.rs +++ b/src/sys/stat.rs @@ -50,6 +50,19 @@ pub fn mknod(path: &P, kind: SFlag, perm: Mode, dev: dev_t) Errno::result(res).map(drop) } +/// Create a special or ordinary file +/// ([posix specification](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mknod.html)). +#[cfg(not(any(target_os = "ios", target_os = "macos")))] +pub fn mknodat(dirfd: &RawFd, path: &P, kind: SFlag, perm: Mode, dev: dev_t) -> Result<()> { + let res = try!(path.with_nix_path(|cstr| { + unsafe { + libc::mknodat(*dirfd, cstr.as_ptr(), kind.bits | perm.bits() as mode_t, dev) + } + })); + + Errno::result(res).map(drop) +} + #[cfg(target_os = "linux")] pub fn major(dev: dev_t) -> u64 { ((dev >> 32) & 0xfffff000) | diff --git a/test/test_stat.rs b/test/test_stat.rs index 765d4fa191..95da635552 100644 --- a/test/test_stat.rs +++ b/test/test_stat.rs @@ -1,11 +1,12 @@ use std::fs::File; use std::os::unix::fs::symlink; use std::os::unix::prelude::AsRawFd; +use std::path::Path; use libc::{S_IFMT, S_IFLNK}; use nix::fcntl; -use nix::sys::stat::{self, stat, fstat, lstat}; +use nix::sys::stat::{self, stat, fstat, lstat, mknod}; use nix::sys::stat::FileStat; use nix::Result; use tempdir::TempDir; @@ -110,3 +111,28 @@ fn test_stat_fstat_lstat() { let fstat_result = fstat(link.as_raw_fd()); assert_stat_results(fstat_result); } + +fn assert_fifo(path: &Path) { + let stats = stat(path).unwrap(); + let typ = stat::SFlag::from_bits_truncate(stats.st_mode); + assert!(typ == stat::S_IFIFO); +} + +#[test] +fn test_mknod() { + let tempdir = TempDir::new("nix-test_mknodat").unwrap(); + let mknod_fifo = tempdir.path().join("mknod"); + + mknod(&mknod_fifo, stat::S_IFIFO, stat::S_IRUSR, 0).unwrap(); + assert_fifo(&mknod_fifo); +} + +#[test] +#[cfg(not(any(target_os = "ios", target_os = "macos")))] +fn test_mknod_mknodat() { + let tempdir = TempDir::new("nix-test_mknodat").unwrap(); + let mknodat_fifo = tempdir.path().join("mknodat"); + + stat::mknodat(&0, &mknodat_fifo, stat::S_IFIFO, stat::S_IRUSR, 0).unwrap(); + assert_fifo(&mknodat_fifo); +}