From 8d0ba74d12bef75f26572a1b2bd0090c08ca312d Mon Sep 17 00:00:00 2001 From: Padraic Fanning Date: Mon, 2 May 2022 20:53:34 -0400 Subject: [PATCH 1/5] Add flock and lockf to fcntl module --- stdlib/src/fcntl.rs | 70 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/stdlib/src/fcntl.rs b/stdlib/src/fcntl.rs index 43f170c58..aa71416ee 100644 --- a/stdlib/src/fcntl.rs +++ b/stdlib/src/fcntl.rs @@ -2,6 +2,8 @@ pub(crate) use fcntl::make_module; #[pymodule] mod fcntl { + use std::mem; + use crate::vm::{ builtins::PyIntRef, function::{ArgMemoryBuffer, ArgStrOrBytesLike, Either, OptionalArg}, @@ -139,4 +141,72 @@ mod fcntl { } } } + + #[pyfunction] + fn flock(fd: i32, operation: i32, vm: &VirtualMachine) -> PyResult { + let ret = unsafe { libc::flock(fd, operation) }; + // TODO: add support for platforms that don't have a builtin `flock` syscall + if ret < 0 { + return Err(os::errno_err(vm)); + } + Ok(vm.ctx.new_int(ret).into()) + } + + // XXX: at the time of writing, wasi and redox don't have the necessary constants + #[cfg(not(any(target_os = "wasi", target_os = "redox")))] + #[pyfunction] + fn lockf( + fd: i32, + cmd: i32, + len: OptionalArg, + start: OptionalArg, + whence: OptionalArg, + vm: &VirtualMachine, + ) -> PyResult { + let mut l: libc::flock = unsafe { mem::zeroed() }; + if cmd == libc::LOCK_UN { + l.l_type = libc::F_UNLCK + .try_into() + .map_err(|e| vm.new_overflow_error(format!("{e}")))?; + } else if (cmd & libc::LOCK_SH) != 0 { + l.l_type = libc::F_RDLCK + .try_into() + .map_err(|e| vm.new_overflow_error(format!("{e}")))?; + } else if (cmd & libc::LOCK_EX) != 0 { + l.l_type = libc::F_WRLCK + .try_into() + .map_err(|e| vm.new_overflow_error(format!("{e}")))?; + } else { + return Err(vm.new_value_error("unrecognized lockf argument".to_owned())); + } + l.l_start = match start { + OptionalArg::Present(s) => s.try_to_primitive(vm)?, + OptionalArg::Missing => 0, + }; + l.l_len = match len { + OptionalArg::Present(l_) => l_.try_to_primitive(vm)?, + OptionalArg::Missing => 0, + }; + l.l_whence = match whence { + OptionalArg::Present(w) => w + .try_into() + .map_err(|e| vm.new_overflow_error(format!("{e}")))?, + OptionalArg::Missing => 0, + }; + let ret = unsafe { + libc::fcntl( + fd, + if (cmd & libc::LOCK_NB) != 0 { + libc::F_SETLK + } else { + libc::F_SETLKW + }, + &l, + ) + }; + if ret < 0 { + return Err(os::errno_err(vm)); + } + Ok(vm.ctx.new_int(ret).into()) + } } From 188f82c00900a55818809ac450d35bb149390e52 Mon Sep 17 00:00:00 2001 From: Padraic Fanning Date: Tue, 3 May 2022 18:13:18 -0400 Subject: [PATCH 2/5] Change reasons for expected failures in test_fcntl --- Lib/test/test_fcntl.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_fcntl.py b/Lib/test/test_fcntl.py index 380faf7ca..444502835 100644 --- a/Lib/test/test_fcntl.py +++ b/Lib/test/test_fcntl.py @@ -141,7 +141,7 @@ class TestFcntl(unittest.TestCase): finally: os.close(fd) - # TODO: RUSTPYTHON, AttributeError: module 'fcntl' has no attribute 'flock' + # TODO: RUSTPYTHON, TypeError: 'BufferedRandom' object cannot be interpreted as an integer @unittest.expectedFailure def test_flock(self): # Solaris needs readable file for shared lock @@ -157,7 +157,7 @@ class TestFcntl(unittest.TestCase): self.assertRaises(ValueError, fcntl.flock, -1, fcntl.LOCK_SH) self.assertRaises(TypeError, fcntl.flock, 'spam', fcntl.LOCK_SH) - # TODO: RUSTPYTHON, AttributeError: module 'fcntl' has no attribute 'lockf' + # TODO: RUSTPYTHON, TypeError: 'BufferedRandom' object cannot be interpreted as an integer @unittest.expectedFailure @unittest.skipIf(platform.system() == "AIX", "AIX returns PermissionError") def test_lockf_exclusive(self): @@ -170,7 +170,7 @@ class TestFcntl(unittest.TestCase): fcntl.lockf(self.f, fcntl.LOCK_UN) self.assertEqual(p.exitcode, 0) - # TODO: RUSTPYTHON, AttributeError: module 'fcntl' has no attribute 'lockf' + # TODO: RUSTPYTHON, TypeError: 'BufferedRandom' object cannot be interpreted as an integer @unittest.expectedFailure @unittest.skipIf(platform.system() == "AIX", "AIX returns PermissionError") def test_lockf_share(self): From 2c8588db2e4bfef9f0e91fb744ac80d7a3da64b3 Mon Sep 17 00:00:00 2001 From: Padraic Fanning Date: Tue, 3 May 2022 18:25:00 -0400 Subject: [PATCH 3/5] Group imports together and cargo fmt --- stdlib/src/fcntl.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/stdlib/src/fcntl.rs b/stdlib/src/fcntl.rs index aa71416ee..4580536bf 100644 --- a/stdlib/src/fcntl.rs +++ b/stdlib/src/fcntl.rs @@ -2,14 +2,13 @@ pub(crate) use fcntl::make_module; #[pymodule] mod fcntl { - use std::mem; - use crate::vm::{ builtins::PyIntRef, function::{ArgMemoryBuffer, ArgStrOrBytesLike, Either, OptionalArg}, stdlib::{io, os}, PyResult, VirtualMachine, }; + use std::mem; // TODO: supply these from (please file an issue/PR upstream): // LOCK_MAND, LOCK_READ, LOCK_WRITE, LOCK_RW, F_GETSIG, F_SETSIG, F_GETLK64, F_SETLK64, From 46a0dea503612ddb64483e04b5c9e4368d6c2948 Mon Sep 17 00:00:00 2001 From: Padraic Fanning Date: Tue, 3 May 2022 18:27:23 -0400 Subject: [PATCH 4/5] Exclude `flock()` from wasi/redox --- stdlib/src/fcntl.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/stdlib/src/fcntl.rs b/stdlib/src/fcntl.rs index 4580536bf..639c355ec 100644 --- a/stdlib/src/fcntl.rs +++ b/stdlib/src/fcntl.rs @@ -141,6 +141,8 @@ mod fcntl { } } + // XXX: at the time of writing, wasi and redox don't have the necessary constants/function + #[cfg(not(any(target_os = "wasi", target_os = "redox")))] #[pyfunction] fn flock(fd: i32, operation: i32, vm: &VirtualMachine) -> PyResult { let ret = unsafe { libc::flock(fd, operation) }; From 36ab937e53e8157ea7f8486f5e4c5f5f7ecb4eaf Mon Sep 17 00:00:00 2001 From: Padraic Fanning Date: Tue, 3 May 2022 20:14:55 -0400 Subject: [PATCH 5/5] Avoid unused import error on wasi and redox --- stdlib/src/fcntl.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/stdlib/src/fcntl.rs b/stdlib/src/fcntl.rs index 639c355ec..502071a09 100644 --- a/stdlib/src/fcntl.rs +++ b/stdlib/src/fcntl.rs @@ -8,7 +8,6 @@ mod fcntl { stdlib::{io, os}, PyResult, VirtualMachine, }; - use std::mem; // TODO: supply these from (please file an issue/PR upstream): // LOCK_MAND, LOCK_READ, LOCK_WRITE, LOCK_RW, F_GETSIG, F_SETSIG, F_GETLK64, F_SETLK64, @@ -164,7 +163,7 @@ mod fcntl { whence: OptionalArg, vm: &VirtualMachine, ) -> PyResult { - let mut l: libc::flock = unsafe { mem::zeroed() }; + let mut l: libc::flock = unsafe { std::mem::zeroed() }; if cmd == libc::LOCK_UN { l.l_type = libc::F_UNLCK .try_into()