Merge pull request #3686 from fanninpm/fcntl-flock-lockf

Add flock and lockf to fcntl module
This commit is contained in:
Jeong YunWon authored and GitHub committed 2022-05-04 14:43:37 +09:00
commit 2ba1d93550
2 files changed
+73 -3

No files matched your search

+3 -3
View File
@@ -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):
+70
View File
@@ -139,4 +139,74 @@ 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) };
// 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<PyIntRef>,
start: OptionalArg<PyIntRef>,
whence: OptionalArg<i32>,
vm: &VirtualMachine,
) -> PyResult {
let mut l: libc::flock = unsafe { std::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())
}
}