mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 10:44:36 +08:00
Implement os.pread and os.pwrite (#8730)
Assisted-by: Codex:gpt-6-astra
This commit is contained in:
1 parent
c382a607bb
commit
ce470e3928
2 files changed
+73
-2
No files matched your search
@@ -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,
|
||||
|
||||
@@ -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))
|
||||
|
||||
Reference in new issue
Block a user