Implement os.pread and os.pwrite (#8730)

Assisted-by: Codex:gpt-6-astra
This commit is contained in:
sijun-yang authored and GitHub committed 2026-09-18 11:02:55 +09:00
1 parent c382a607bb
commit ce470e3928
2 files changed
+73 -2

No files matched your search

+18
View File
@@ -341,6 +341,24 @@ pub fn write_fd(fd: BorrowedFd<'_>, buf: &[u8]) -> std::io::Result<usize> {
nix::unistd::write(fd, buf).map_err(std::io::Error::from)
}
pub fn pread(fd: i32, buf: &mut [u8], offset: libc::off_t) -> std::io::Result<usize> {
let ret = unsafe { libc::pread(fd, buf.as_mut_ptr().cast(), buf.len(), offset) };
if ret == -1 {
Err(std::io::Error::last_os_error())
} else {
Ok(ret as usize)
}
}
pub fn pwrite(fd: i32, buf: &[u8], offset: libc::off_t) -> std::io::Result<usize> {
let ret = unsafe { libc::pwrite(fd, buf.as_ptr().cast(), buf.len(), offset) };
if ret == -1 {
Err(std::io::Error::last_os_error())
} else {
Ok(ret as usize)
}
}
pub fn fchownat(
dir_fd: BorrowedFd<'_>,
path: &OsStr,
+55 -2
View File
@@ -18,10 +18,12 @@ pub use rustpython_host_env::posix::set_inheritable;
pub mod module {
use crate::{
AsObject, Py, PyObjectRef, PyResult, VirtualMachine,
builtins::{PyDictRef, PyInt, PyListRef, PyTuple, PyTupleRef, PyUtf8Str},
builtins::{PyBytesRef, PyDictRef, PyInt, PyListRef, PyTuple, PyTupleRef, PyUtf8Str},
convert::{IntoPyException, ToPyException, ToPyObject, TryFromObject},
exceptions::OSErrorBuilder,
function::{ArgMapping, Either, KwArgs, OptionalArg},
function::{
ArgBytesLike, ArgMapping, ArgPrimitiveIndex, ArgSize, Either, KwArgs, OptionalArg,
},
ospath::{OsPath, OsPathOrFd},
stdlib::os::{
_os, DirFd, FollowSymlinks, SupportFunc, SymlinkArgs, fs_metadata, warn_if_bool_fd,
@@ -962,6 +964,57 @@ pub mod module {
.map_err(|err| err.into_pyexception(vm))
}
#[pyfunction]
fn pread(
fd: ArgPrimitiveIndex<i32>,
n: ArgSize,
offset: ArgPrimitiveIndex<libc::off_t>,
vm: &VirtualMachine,
) -> PyResult<PyBytesRef> {
let (fd, n, offset) = (fd.value, n.value, offset.value);
if n < 0 {
return Err(io::Error::from_raw_os_error(libc::EINVAL).into_pyexception(vm));
}
let mut buffer = vm.new_zeroed_bytes(n as usize)?;
loop {
match vm.allow_threads(|| rustpython_host_env::posix::pread(fd, &mut buffer, offset)) {
Ok(n) => {
buffer.truncate(n);
return Ok(vm.ctx.new_bytes(buffer));
}
Err(err) if err.raw_os_error() == Some(libc::EINTR) => {
vm.check_signals()?;
continue;
}
Err(err) => return Err(err.into_pyexception(vm)),
}
}
}
#[pyfunction]
fn pwrite(
fd: ArgPrimitiveIndex<i32>,
buffer: ArgBytesLike,
offset: ArgPrimitiveIndex<libc::off_t>,
vm: &VirtualMachine,
) -> PyResult<usize> {
// Avoid holding a buffer lock across blocking I/O,
// which can prevent other threads from reaching GC safepoints.
let data = buffer.borrow_buf_unlocked(vm)?;
loop {
match vm
.allow_threads(|| rustpython_host_env::posix::pwrite(fd.value, &data, offset.value))
{
Ok(n) => return Ok(n),
Err(err) if err.raw_os_error() == Some(libc::EINTR) => {
vm.check_signals()?;
continue;
}
Err(err) => return Err(err.into_pyexception(vm)),
}
}
}
#[pyfunction]
fn pipe(vm: &VirtualMachine) -> PyResult<(OwnedFd, OwnedFd)> {
rustpython_host_env::posix::pipe().map_err(|err| err.into_pyexception(vm))