diff --git a/Lib/test/test_posix.py b/Lib/test/test_posix.py index 89362ba0a..bb76f2dba 100644 --- a/Lib/test/test_posix.py +++ b/Lib/test/test_posix.py @@ -1172,11 +1172,8 @@ class PosixTester(unittest.TestCase): posix.close(f) support.rmtree(support.TESTFN + 'dir') - # TODO: RUSTPYTHON: AttributeError: module 'os' has no attribute 'mknod' - # - # @unittest.skipUnless((os.mknod in os.supports_dir_fd) and hasattr(stat, 'S_IFIFO'), - # "test requires both stat.S_IFIFO and dir_fd support for os.mknod()") - @unittest.expectedFailure + @unittest.skipUnless((os.mknod in os.supports_dir_fd) and hasattr(stat, 'S_IFIFO'), + "test requires both stat.S_IFIFO and dir_fd support for os.mknod()") def test_mknod_dir_fd(self): # Test using mknodat() to create a FIFO (the only use specified # by POSIX). diff --git a/vm/src/stdlib/posix.rs b/vm/src/stdlib/posix.rs index 267ecf6f0..90e244de5 100644 --- a/vm/src/stdlib/posix.rs +++ b/vm/src/stdlib/posix.rs @@ -413,6 +413,64 @@ pub mod module { ) } + #[derive(FromArgs)] + struct MknodArgs { + #[pyarg(any)] + path: PyPathLike, + #[pyarg(any)] + mode: libc::mode_t, + #[pyarg(any)] + device: libc::dev_t, + #[allow(unused)] + #[pyarg(flatten)] + dir_fd: DirFd<1>, + } + + impl MknodArgs { + fn _mknod(self, vm: &VirtualMachine) -> PyResult { + Ok(unsafe { + libc::mknod( + self.path.clone().into_cstring(vm)?.as_ptr(), + self.mode, + self.device, + ) + }) + } + #[cfg(not(target_os = "macos"))] + fn mknod(self, vm: &VirtualMachine) -> PyResult<()> { + let ret = match self.dir_fd.get_opt() { + None => self._mknod(vm)?, + Some(non_default_fd) => unsafe { + libc::mknodat( + non_default_fd, + self.path.clone().into_cstring(vm)?.as_ptr(), + self.mode, + self.device, + ) + }, + }; + if ret != 0 { + Err(errno_err(vm)) + } else { + Ok(()) + } + } + #[cfg(target_os = "macos")] + fn mknod(self, vm: &VirtualMachine) -> PyResult<()> { + let ret = self._mknod(vm)?; + if ret != 0 { + Err(errno_err(vm)) + } else { + Ok(()) + } + } + } + + #[pyfunction] + fn mknod(args: MknodArgs, vm: &VirtualMachine) -> PyResult<()> { + args.mknod(vm) + } + #[cfg(not(target_os = "redox"))] #[pyfunction] fn nice(increment: i32, vm: &VirtualMachine) -> PyResult { @@ -1497,6 +1555,10 @@ pub mod module { SupportFunc::new("lchown", None, None, None), #[cfg(not(target_os = "redox"))] SupportFunc::new("fchown", Some(true), None, Some(true)), + #[cfg(not(target_os = "macos"))] + SupportFunc::new("mknod", Some(true), Some(true), Some(false)), + #[cfg(target_os = "macos")] + SupportFunc::new("mknod", Some(true), Some(false), Some(false)), SupportFunc::new("umask", Some(false), Some(false), Some(false)), SupportFunc::new("execv", None, None, None), SupportFunc::new("pathconf", Some(true), None, None),