Skip to content

Commit 2ba1d93

Browse files
authored
Merge pull request RustPython#3686 from fanninpm/fcntl-flock-lockf
Add flock and lockf to fcntl module
2 parents 392a947 + 36ab937 commit 2ba1d93

File tree

2 files changed

+73
-3
lines changed

2 files changed

+73
-3
lines changed

Lib/test/test_fcntl.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ def test_fcntl_64_bit(self):
141141
finally:
142142
os.close(fd)
143143

144-
# TODO: RUSTPYTHON, AttributeError: module 'fcntl' has no attribute 'flock'
144+
# TODO: RUSTPYTHON, TypeError: 'BufferedRandom' object cannot be interpreted as an integer
145145
@unittest.expectedFailure
146146
def test_flock(self):
147147
# Solaris needs readable file for shared lock
@@ -157,7 +157,7 @@ def test_flock(self):
157157
self.assertRaises(ValueError, fcntl.flock, -1, fcntl.LOCK_SH)
158158
self.assertRaises(TypeError, fcntl.flock, 'spam', fcntl.LOCK_SH)
159159

160-
# TODO: RUSTPYTHON, AttributeError: module 'fcntl' has no attribute 'lockf'
160+
# TODO: RUSTPYTHON, TypeError: 'BufferedRandom' object cannot be interpreted as an integer
161161
@unittest.expectedFailure
162162
@unittest.skipIf(platform.system() == "AIX", "AIX returns PermissionError")
163163
def test_lockf_exclusive(self):
@@ -170,7 +170,7 @@ def test_lockf_exclusive(self):
170170
fcntl.lockf(self.f, fcntl.LOCK_UN)
171171
self.assertEqual(p.exitcode, 0)
172172

173-
# TODO: RUSTPYTHON, AttributeError: module 'fcntl' has no attribute 'lockf'
173+
# TODO: RUSTPYTHON, TypeError: 'BufferedRandom' object cannot be interpreted as an integer
174174
@unittest.expectedFailure
175175
@unittest.skipIf(platform.system() == "AIX", "AIX returns PermissionError")
176176
def test_lockf_share(self):

stdlib/src/fcntl.rs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,4 +139,74 @@ mod fcntl {
139139
}
140140
}
141141
}
142+
143+
// XXX: at the time of writing, wasi and redox don't have the necessary constants/function
144+
#[cfg(not(any(target_os = "wasi", target_os = "redox")))]
145+
#[pyfunction]
146+
fn flock(fd: i32, operation: i32, vm: &VirtualMachine) -> PyResult {
147+
let ret = unsafe { libc::flock(fd, operation) };
148+
// TODO: add support for platforms that don't have a builtin `flock` syscall
149+
if ret < 0 {
150+
return Err(os::errno_err(vm));
151+
}
152+
Ok(vm.ctx.new_int(ret).into())
153+
}
154+
155+
// XXX: at the time of writing, wasi and redox don't have the necessary constants
156+
#[cfg(not(any(target_os = "wasi", target_os = "redox")))]
157+
#[pyfunction]
158+
fn lockf(
159+
fd: i32,
160+
cmd: i32,
161+
len: OptionalArg<PyIntRef>,
162+
start: OptionalArg<PyIntRef>,
163+
whence: OptionalArg<i32>,
164+
vm: &VirtualMachine,
165+
) -> PyResult {
166+
let mut l: libc::flock = unsafe { std::mem::zeroed() };
167+
if cmd == libc::LOCK_UN {
168+
l.l_type = libc::F_UNLCK
169+
.try_into()
170+
.map_err(|e| vm.new_overflow_error(format!("{e}")))?;
171+
} else if (cmd & libc::LOCK_SH) != 0 {
172+
l.l_type = libc::F_RDLCK
173+
.try_into()
174+
.map_err(|e| vm.new_overflow_error(format!("{e}")))?;
175+
} else if (cmd & libc::LOCK_EX) != 0 {
176+
l.l_type = libc::F_WRLCK
177+
.try_into()
178+
.map_err(|e| vm.new_overflow_error(format!("{e}")))?;
179+
} else {
180+
return Err(vm.new_value_error("unrecognized lockf argument".to_owned()));
181+
}
182+
l.l_start = match start {
183+
OptionalArg::Present(s) => s.try_to_primitive(vm)?,
184+
OptionalArg::Missing => 0,
185+
};
186+
l.l_len = match len {
187+
OptionalArg::Present(l_) => l_.try_to_primitive(vm)?,
188+
OptionalArg::Missing => 0,
189+
};
190+
l.l_whence = match whence {
191+
OptionalArg::Present(w) => w
192+
.try_into()
193+
.map_err(|e| vm.new_overflow_error(format!("{e}")))?,
194+
OptionalArg::Missing => 0,
195+
};
196+
let ret = unsafe {
197+
libc::fcntl(
198+
fd,
199+
if (cmd & libc::LOCK_NB) != 0 {
200+
libc::F_SETLK
201+
} else {
202+
libc::F_SETLKW
203+
},
204+
&l,
205+
)
206+
};
207+
if ret < 0 {
208+
return Err(os::errno_err(vm));
209+
}
210+
Ok(vm.ctx.new_int(ret).into())
211+
}
142212
}

0 commit comments

Comments
 (0)