mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Rework crt_fd to be more aligned with io-safety
This commit is contained in:
6 files changed
+541
-230
No files matched your search
+351
-72
@@ -1,112 +1,391 @@
|
||||
//! A module implementing an io type backed by the C runtime's file descriptors, i.e. what's
|
||||
//! returned from libc::open, even on windows.
|
||||
|
||||
use std::{cmp, ffi, io};
|
||||
use std::{cmp, ffi, fmt, io};
|
||||
|
||||
#[cfg(windows)]
|
||||
use libc::commit as fsync;
|
||||
#[cfg(windows)]
|
||||
unsafe extern "C" {
|
||||
#[link_name = "_chsize_s"]
|
||||
fn ftruncate(fd: i32, len: i64) -> i32;
|
||||
}
|
||||
#[cfg(not(windows))]
|
||||
use libc::{fsync, ftruncate};
|
||||
use std::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
|
||||
#[cfg(windows)]
|
||||
use std::os::windows::io::BorrowedHandle;
|
||||
|
||||
mod c {
|
||||
pub(super) use libc::*;
|
||||
|
||||
#[cfg(windows)]
|
||||
pub(super) use libc::commit as fsync;
|
||||
#[cfg(windows)]
|
||||
unsafe extern "C" {
|
||||
#[link_name = "_chsize_s"]
|
||||
pub(super) fn ftruncate(fd: i32, len: i64) -> i32;
|
||||
}
|
||||
}
|
||||
|
||||
// this is basically what CPython has for Py_off_t; windows uses long long
|
||||
// for offsets, other platforms just use off_t
|
||||
#[cfg(not(windows))]
|
||||
pub type Offset = libc::off_t;
|
||||
pub type Offset = c::off_t;
|
||||
#[cfg(windows)]
|
||||
pub type Offset = libc::c_longlong;
|
||||
pub type Offset = c::c_longlong;
|
||||
|
||||
#[cfg(not(windows))]
|
||||
pub type Raw = RawFd;
|
||||
#[cfg(windows)]
|
||||
pub type Raw = i32;
|
||||
|
||||
#[inline]
|
||||
fn cvt<T, I: num_traits::PrimInt>(ret: I, f: impl FnOnce(I) -> T) -> io::Result<T> {
|
||||
fn cvt<I: num_traits::PrimInt>(ret: I) -> io::Result<I> {
|
||||
if ret < I::zero() {
|
||||
Err(crate::os::last_os_error())
|
||||
} else {
|
||||
Ok(f(ret))
|
||||
Ok(ret)
|
||||
}
|
||||
}
|
||||
|
||||
fn cvt_fd(ret: Raw) -> io::Result<Owned> {
|
||||
cvt(ret).map(|fd| unsafe { Owned::from_raw(fd) })
|
||||
}
|
||||
|
||||
const MAX_RW: usize = if cfg!(any(windows, target_vendor = "apple")) {
|
||||
i32::MAX as usize
|
||||
} else {
|
||||
isize::MAX as usize
|
||||
};
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
#[repr(transparent)]
|
||||
pub struct Fd(pub i32);
|
||||
#[cfg(not(windows))]
|
||||
type OwnedInner = OwnedFd;
|
||||
#[cfg(not(windows))]
|
||||
type BorrowedInner<'fd> = BorrowedFd<'fd>;
|
||||
|
||||
impl Fd {
|
||||
pub fn open(path: &ffi::CStr, flags: i32, mode: i32) -> io::Result<Self> {
|
||||
cvt(unsafe { libc::open(path.as_ptr(), flags, mode) }, Fd)
|
||||
}
|
||||
#[cfg(windows)]
|
||||
mod win {
|
||||
use super::*;
|
||||
use std::marker::PhantomData;
|
||||
use std::mem::ManuallyDrop;
|
||||
|
||||
#[cfg(windows)]
|
||||
pub fn wopen(path: &widestring::WideCStr, flags: i32, mode: i32) -> io::Result<Self> {
|
||||
cvt(
|
||||
unsafe { suppress_iph!(libc::wopen(path.as_ptr(), flags, mode)) },
|
||||
Fd,
|
||||
)
|
||||
}
|
||||
#[repr(transparent)]
|
||||
pub(super) struct OwnedInner(i32);
|
||||
|
||||
#[cfg(all(any(unix, target_os = "wasi"), not(target_os = "redox")))]
|
||||
pub fn openat(&self, path: &ffi::CStr, flags: i32, mode: i32) -> io::Result<Self> {
|
||||
cvt(
|
||||
unsafe { libc::openat(self.0, path.as_ptr(), flags, mode) },
|
||||
Fd,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn fsync(&self) -> io::Result<()> {
|
||||
cvt(unsafe { suppress_iph!(fsync(self.0)) }, drop)
|
||||
}
|
||||
|
||||
pub fn close(&self) -> io::Result<()> {
|
||||
cvt(unsafe { suppress_iph!(libc::close(self.0)) }, drop)
|
||||
}
|
||||
|
||||
pub fn ftruncate(&self, len: Offset) -> io::Result<()> {
|
||||
cvt(unsafe { suppress_iph!(ftruncate(self.0, len)) }, drop)
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
pub fn to_raw_handle(&self) -> io::Result<std::os::windows::io::RawHandle> {
|
||||
unsafe extern "C" {
|
||||
fn _get_osfhandle(fd: i32) -> libc::intptr_t;
|
||||
impl OwnedInner {
|
||||
#[inline]
|
||||
pub unsafe fn from_raw_fd(fd: Raw) -> Self {
|
||||
Self(fd)
|
||||
}
|
||||
let handle = unsafe { suppress_iph!(_get_osfhandle(self.0)) };
|
||||
if handle == -1 {
|
||||
Err(io::Error::last_os_error())
|
||||
} else {
|
||||
Ok(handle as _)
|
||||
#[inline]
|
||||
pub fn as_raw_fd(&self) -> Raw {
|
||||
self.0
|
||||
}
|
||||
#[inline]
|
||||
pub fn into_raw_fd(self) -> Raw {
|
||||
let me = ManuallyDrop::new(self);
|
||||
me.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for OwnedInner {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
let _ = _close(self.0);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(transparent)]
|
||||
pub(super) struct BorrowedInner<'fd> {
|
||||
fd: Raw,
|
||||
_marker: PhantomData<&'fd Owned>,
|
||||
}
|
||||
|
||||
impl BorrowedInner<'_> {
|
||||
#[inline]
|
||||
pub const unsafe fn borrow_raw(fd: Raw) -> Self {
|
||||
Self {
|
||||
fd,
|
||||
_marker: PhantomData,
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
pub fn as_raw_fd(&self) -> Raw {
|
||||
self.fd
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl io::Write for Fd {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
let count = cmp::min(buf.len(), MAX_RW);
|
||||
cvt(
|
||||
unsafe { suppress_iph!(libc::write(self.0, buf.as_ptr() as _, count as _)) },
|
||||
|i| i as usize,
|
||||
)
|
||||
#[cfg(windows)]
|
||||
use self::win::{BorrowedInner, OwnedInner};
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct Owned {
|
||||
inner: OwnedInner,
|
||||
}
|
||||
|
||||
impl fmt::Debug for Owned {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("crt_fd::Owned")
|
||||
.field(&self.as_raw())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(transparent)]
|
||||
pub struct Borrowed<'fd> {
|
||||
inner: BorrowedInner<'fd>,
|
||||
}
|
||||
|
||||
impl<'fd> PartialEq for Borrowed<'fd> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.as_raw() == other.as_raw()
|
||||
}
|
||||
}
|
||||
impl<'fd> Eq for Borrowed<'fd> {}
|
||||
|
||||
impl fmt::Debug for Borrowed<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("crt_fd::Borrowed")
|
||||
.field(&self.as_raw())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Owned {
|
||||
/// Create a `crt_fd::Owned` from a raw file descriptor.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `fd` must be a valid file descriptor.
|
||||
#[inline]
|
||||
pub unsafe fn from_raw(fd: Raw) -> Self {
|
||||
let inner = unsafe { OwnedInner::from_raw_fd(fd) };
|
||||
Self { inner }
|
||||
}
|
||||
|
||||
/// Create a `crt_fd::Owned` from a raw file descriptor.
|
||||
///
|
||||
/// Returns an error if `fd` is -1.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `fd` must be a valid file descriptor.
|
||||
#[inline]
|
||||
pub unsafe fn try_from_raw(fd: Raw) -> io::Result<Self> {
|
||||
if fd == -1 {
|
||||
Err(ebadf())
|
||||
} else {
|
||||
Ok(unsafe { Self::from_raw(fd) })
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
pub fn borrow(&self) -> Borrowed<'_> {
|
||||
unsafe { Borrowed::borrow_raw(self.as_raw()) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_raw(&self) -> Raw {
|
||||
self.inner.as_raw_fd()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn into_raw(self) -> Raw {
|
||||
self.inner.into_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl io::Read for Fd {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
let count = cmp::min(buf.len(), MAX_RW);
|
||||
cvt(
|
||||
unsafe { suppress_iph!(libc::read(self.0, buf.as_mut_ptr() as _, count as _)) },
|
||||
|i| i as usize,
|
||||
)
|
||||
#[cfg(unix)]
|
||||
impl From<Owned> for OwnedFd {
|
||||
fn from(fd: Owned) -> Self {
|
||||
fd.inner
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
impl From<OwnedFd> for Owned {
|
||||
fn from(fd: OwnedFd) -> Self {
|
||||
Self { inner: fd }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
impl AsFd for Owned {
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.inner.as_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
impl AsRawFd for Owned {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.as_raw()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
impl FromRawFd for Owned {
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> Self {
|
||||
unsafe { Self::from_raw(fd) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
impl IntoRawFd for Owned {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.into_raw()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'fd> Borrowed<'fd> {
|
||||
/// Create a `crt_fd::Borrowed` from a raw file descriptor.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `fd` must be a valid file descriptor.
|
||||
#[inline]
|
||||
pub const unsafe fn borrow_raw(fd: Raw) -> Self {
|
||||
let inner = unsafe { BorrowedInner::borrow_raw(fd) };
|
||||
Self { inner }
|
||||
}
|
||||
|
||||
/// Create a `crt_fd::Borrowed` from a raw file descriptor.
|
||||
///
|
||||
/// Returns an error if `fd` is -1.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `fd` must be a valid file descriptor.
|
||||
#[inline]
|
||||
pub unsafe fn try_borrow_raw(fd: Raw) -> io::Result<Self> {
|
||||
if fd == -1 {
|
||||
Err(ebadf())
|
||||
} else {
|
||||
Ok(unsafe { Self::borrow_raw(fd) })
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_raw(self) -> Raw {
|
||||
self.inner.as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
impl<'fd> From<Borrowed<'fd>> for BorrowedFd<'fd> {
|
||||
fn from(fd: Borrowed<'fd>) -> Self {
|
||||
fd.inner
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
impl<'fd> From<BorrowedFd<'fd>> for Borrowed<'fd> {
|
||||
fn from(fd: BorrowedFd<'fd>) -> Self {
|
||||
Self { inner: fd }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
impl AsFd for Borrowed<'_> {
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.inner.as_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
impl AsRawFd for Borrowed<'_> {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.as_raw()
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn ebadf() -> io::Error {
|
||||
io::Error::from_raw_os_error(c::EBADF)
|
||||
}
|
||||
|
||||
pub fn open(path: &ffi::CStr, flags: i32, mode: i32) -> io::Result<Owned> {
|
||||
cvt_fd(unsafe { c::open(path.as_ptr(), flags, mode) })
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
pub fn wopen(path: &widestring::WideCStr, flags: i32, mode: i32) -> io::Result<Owned> {
|
||||
cvt_fd(unsafe { suppress_iph!(c::wopen(path.as_ptr(), flags, mode)) })
|
||||
}
|
||||
|
||||
#[cfg(all(any(unix, target_os = "wasi"), not(target_os = "redox")))]
|
||||
pub fn openat(dir: Borrowed<'_>, path: &ffi::CStr, flags: i32, mode: i32) -> io::Result<Owned> {
|
||||
cvt_fd(unsafe { c::openat(dir.as_raw(), path.as_ptr(), flags, mode) })
|
||||
}
|
||||
|
||||
pub fn fsync(fd: Borrowed<'_>) -> io::Result<()> {
|
||||
cvt(unsafe { suppress_iph!(c::fsync(fd.as_raw())) })?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn _close(fd: Raw) -> io::Result<()> {
|
||||
cvt(unsafe { suppress_iph!(c::close(fd)) })?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn close(fd: Owned) -> io::Result<()> {
|
||||
_close(fd.into_raw())
|
||||
}
|
||||
|
||||
pub fn ftruncate(fd: Borrowed<'_>, len: Offset) -> io::Result<()> {
|
||||
cvt(unsafe { suppress_iph!(c::ftruncate(fd.as_raw(), len)) })?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
pub fn as_handle(fd: Borrowed<'_>) -> io::Result<BorrowedHandle<'_>> {
|
||||
unsafe extern "C" {
|
||||
fn _get_osfhandle(fd: Borrowed<'_>) -> c::intptr_t;
|
||||
}
|
||||
let handle = unsafe { suppress_iph!(_get_osfhandle(fd)) };
|
||||
if handle == -1 {
|
||||
Err(io::Error::last_os_error())
|
||||
} else {
|
||||
Ok(unsafe { BorrowedHandle::borrow_raw(handle as _) })
|
||||
}
|
||||
}
|
||||
|
||||
fn _write(fd: Raw, buf: &[u8]) -> io::Result<usize> {
|
||||
let count = cmp::min(buf.len(), MAX_RW);
|
||||
let n = cvt(unsafe { suppress_iph!(c::write(fd, buf.as_ptr() as _, count as _)) })?;
|
||||
Ok(n as usize)
|
||||
}
|
||||
|
||||
fn _read(fd: Raw, buf: &mut [u8]) -> io::Result<usize> {
|
||||
let count = cmp::min(buf.len(), MAX_RW);
|
||||
let n = cvt(unsafe { suppress_iph!(libc::read(fd, buf.as_mut_ptr() as _, count as _)) })?;
|
||||
Ok(n as usize)
|
||||
}
|
||||
|
||||
pub fn write(fd: Borrowed<'_>, buf: &[u8]) -> io::Result<usize> {
|
||||
_write(fd.as_raw(), buf)
|
||||
}
|
||||
|
||||
pub fn read(fd: Borrowed<'_>, buf: &mut [u8]) -> io::Result<usize> {
|
||||
_read(fd.as_raw(), buf)
|
||||
}
|
||||
|
||||
macro_rules! impl_rw {
|
||||
($t:ty) => {
|
||||
impl io::Write for $t {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
_write(self.as_raw(), buf)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl io::Read for $t {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
_read(self.as_raw(), buf)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_rw!(Owned);
|
||||
impl_rw!(Borrowed<'_>);
|
||||
+24
-18
@@ -1,7 +1,9 @@
|
||||
use rustpython_common::crt_fd;
|
||||
|
||||
use crate::{
|
||||
PyObjectRef, PyResult, VirtualMachine,
|
||||
builtins::PyBaseExceptionRef,
|
||||
convert::{ToPyException, TryFromObject},
|
||||
convert::{IntoPyException, ToPyException, ToPyObject, TryFromObject},
|
||||
function::FsPath,
|
||||
object::AsObject,
|
||||
};
|
||||
@@ -95,32 +97,36 @@ impl TryFromObject for OsPath {
|
||||
|
||||
// path_t with allow_fd in CPython
|
||||
#[derive(Clone)]
|
||||
pub(crate) enum OsPathOrFd {
|
||||
pub(crate) enum OsPathOrFd<'fd> {
|
||||
Path(OsPath),
|
||||
Fd(i32),
|
||||
Fd(crt_fd::Borrowed<'fd>),
|
||||
}
|
||||
|
||||
impl TryFromObject for OsPathOrFd {
|
||||
impl TryFromObject for OsPathOrFd<'_> {
|
||||
fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
|
||||
let r = match obj.try_index_opt(vm) {
|
||||
Some(int) => Self::Fd(int?.try_to_primitive(vm)?),
|
||||
None => Self::Path(obj.try_into_value(vm)?),
|
||||
};
|
||||
Ok(r)
|
||||
match obj.try_index_opt(vm) {
|
||||
Some(int) => {
|
||||
let fd = int?.try_to_primitive(vm)?;
|
||||
unsafe { crt_fd::Borrowed::try_borrow_raw(fd) }
|
||||
.map(Self::Fd)
|
||||
.map_err(|e| e.into_pyexception(vm))
|
||||
}
|
||||
None => obj.try_into_value(vm).map(Self::Path),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OsPath> for OsPathOrFd {
|
||||
impl From<OsPath> for OsPathOrFd<'_> {
|
||||
fn from(path: OsPath) -> Self {
|
||||
Self::Path(path)
|
||||
}
|
||||
}
|
||||
|
||||
impl OsPathOrFd {
|
||||
impl OsPathOrFd<'_> {
|
||||
pub fn filename(&self, vm: &VirtualMachine) -> PyObjectRef {
|
||||
match self {
|
||||
Self::Path(path) => path.filename(vm),
|
||||
Self::Fd(fd) => vm.ctx.new_int(*fd).into(),
|
||||
Self::Fd(fd) => fd.to_pyobject(vm),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -128,8 +134,8 @@ impl OsPathOrFd {
|
||||
// TODO: preserve the input `PyObjectRef` of filename and filename2 (Failing check `self.assertIs(err.filename, name, str(func)`)
|
||||
pub struct IOErrorBuilder<'a> {
|
||||
error: &'a std::io::Error,
|
||||
filename: Option<OsPathOrFd>,
|
||||
filename2: Option<OsPathOrFd>,
|
||||
filename: Option<OsPathOrFd<'a>>,
|
||||
filename2: Option<OsPathOrFd<'a>>,
|
||||
}
|
||||
|
||||
impl<'a> IOErrorBuilder<'a> {
|
||||
@@ -141,13 +147,13 @@ impl<'a> IOErrorBuilder<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn filename(mut self, filename: impl Into<OsPathOrFd>) -> Self {
|
||||
pub(crate) fn filename(mut self, filename: impl Into<OsPathOrFd<'a>>) -> Self {
|
||||
let filename = filename.into();
|
||||
self.filename.replace(filename);
|
||||
self
|
||||
}
|
||||
|
||||
pub(crate) fn filename2(mut self, filename: impl Into<OsPathOrFd>) -> Self {
|
||||
pub(crate) fn filename2(mut self, filename: impl Into<OsPathOrFd<'a>>) -> Self {
|
||||
let filename = filename.into();
|
||||
self.filename2.replace(filename);
|
||||
self
|
||||
@@ -155,10 +161,10 @@ impl<'a> IOErrorBuilder<'a> {
|
||||
|
||||
pub(crate) fn with_filename(
|
||||
error: &'a std::io::Error,
|
||||
filename: impl Into<OsPathOrFd>,
|
||||
filename: impl Into<OsPathOrFd<'a>>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyBaseExceptionRef {
|
||||
let zelf = Self {
|
||||
let zelf = IOErrorBuilder {
|
||||
error,
|
||||
filename: Some(filename.into()),
|
||||
filename2: None,
|
||||
|
||||
+21
-22
@@ -3972,7 +3972,7 @@ mod _io {
|
||||
// check file descriptor validity
|
||||
#[cfg(unix)]
|
||||
if let Ok(crate::ospath::OsPathOrFd::Fd(fd)) = file.clone().try_into_value(vm) {
|
||||
nix::fcntl::fcntl(fd, nix::fcntl::F_GETFD)
|
||||
nix::fcntl::fcntl(fd.as_raw(), nix::fcntl::F_GETFD)
|
||||
.map_err(|_| crate::stdlib::os::errno_err(vm))?;
|
||||
}
|
||||
|
||||
@@ -4131,8 +4131,8 @@ mod fileio {
|
||||
use crate::{
|
||||
AsObject, Py, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject, VirtualMachine,
|
||||
builtins::{PyBaseExceptionRef, PyUtf8Str, PyUtf8StrRef},
|
||||
common::crt_fd::Fd,
|
||||
convert::ToPyException,
|
||||
common::crt_fd,
|
||||
convert::{IntoPyException, ToPyException},
|
||||
function::{ArgBytesLike, ArgMemoryBuffer, OptionalArg, OptionalOption},
|
||||
ospath::{IOErrorBuilder, OsPath, OsPathOrFd},
|
||||
stdlib::os,
|
||||
@@ -4303,7 +4303,7 @@ mod fileio {
|
||||
|
||||
let (fd, filename) = if let Some(fd) = arg_fd {
|
||||
zelf.closefd.store(args.closefd);
|
||||
(fd, OsPathOrFd::Fd(fd))
|
||||
(fd, None)
|
||||
} else {
|
||||
zelf.closefd.store(true);
|
||||
if !args.closefd {
|
||||
@@ -4319,28 +4319,27 @@ mod fileio {
|
||||
if fd < 0 {
|
||||
return Err(vm.new_value_error(format!("opener returned {fd}")));
|
||||
}
|
||||
(
|
||||
fd,
|
||||
OsPathOrFd::try_from_object(vm, name.clone()).unwrap_or(OsPathOrFd::Fd(fd)),
|
||||
)
|
||||
(fd, None)
|
||||
} else {
|
||||
let path = OsPath::try_from_object(vm, name.clone())?;
|
||||
#[cfg(any(unix, target_os = "wasi"))]
|
||||
let fd = Fd::open(&path.clone().into_cstring(vm)?, flags, 0o666);
|
||||
let fd = crt_fd::open(&path.clone().into_cstring(vm)?, flags, 0o666);
|
||||
#[cfg(windows)]
|
||||
let fd = Fd::wopen(&path.to_wide_cstring(vm)?, flags, 0o666);
|
||||
let fd = crt_fd::wopen(&path.to_wide_cstring(vm)?, flags, 0o666);
|
||||
let filename = OsPathOrFd::Path(path);
|
||||
match fd {
|
||||
Ok(fd) => (fd.0, filename),
|
||||
Ok(fd) => (fd.into_raw(), Some(filename)),
|
||||
Err(e) => return Err(IOErrorBuilder::with_filename(&e, filename, vm)),
|
||||
}
|
||||
}
|
||||
};
|
||||
zelf.fd.store(fd);
|
||||
let fd = unsafe { crt_fd::Borrowed::borrow_raw(fd) };
|
||||
let filename = filename.unwrap_or(OsPathOrFd::Fd(fd));
|
||||
|
||||
// TODO: _Py_set_inheritable
|
||||
|
||||
let fd_fstat = crate::common::fileutils::fstat(fd);
|
||||
let fd_fstat = crate::common::fileutils::fstat(fd.as_raw());
|
||||
|
||||
#[cfg(windows)]
|
||||
{
|
||||
@@ -4370,7 +4369,7 @@ mod fileio {
|
||||
zelf.as_object().set_attr("name", name, vm)?;
|
||||
|
||||
if mode.contains(Mode::APPENDING) {
|
||||
let _ = os::lseek(fd as _, 0, libc::SEEK_END, vm);
|
||||
let _ = os::lseek(fd, 0, libc::SEEK_END, vm);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -4435,8 +4434,9 @@ mod fileio {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_fd(&self, vm: &VirtualMachine) -> PyResult<Fd> {
|
||||
self.fileno(vm).map(Fd)
|
||||
fn get_fd(&self, vm: &VirtualMachine) -> PyResult<crt_fd::Borrowed<'_>> {
|
||||
self.fileno(vm)
|
||||
.map(|fd| unsafe { crt_fd::Borrowed::borrow_raw(fd) })
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
@@ -4554,8 +4554,7 @@ mod fileio {
|
||||
}
|
||||
let fd = zelf.fd.swap(-1);
|
||||
if fd >= 0 {
|
||||
Fd(fd)
|
||||
.close()
|
||||
crt_fd::close(unsafe { crt_fd::Owned::from_raw(fd) })
|
||||
.map_err(|err| Self::io_error(zelf, err, vm))?;
|
||||
}
|
||||
res
|
||||
@@ -4563,7 +4562,7 @@ mod fileio {
|
||||
|
||||
#[pymethod]
|
||||
fn seekable(&self, vm: &VirtualMachine) -> PyResult<bool> {
|
||||
let fd = self.fileno(vm)?;
|
||||
let fd = self.get_fd(vm)?;
|
||||
Ok(self.seekable.load().unwrap_or_else(|| {
|
||||
let seekable = os::lseek(fd, 0, libc::SEEK_CUR, vm).is_ok();
|
||||
self.seekable.store(Some(seekable));
|
||||
@@ -4579,7 +4578,7 @@ mod fileio {
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<Offset> {
|
||||
let how = how.unwrap_or(0);
|
||||
let fd = self.fileno(vm)?;
|
||||
let fd = self.get_fd(vm)?;
|
||||
let offset = get_offset(offset, vm)?;
|
||||
|
||||
os::lseek(fd, offset, how, vm)
|
||||
@@ -4587,18 +4586,18 @@ mod fileio {
|
||||
|
||||
#[pymethod]
|
||||
fn tell(&self, vm: &VirtualMachine) -> PyResult<Offset> {
|
||||
let fd = self.fileno(vm)?;
|
||||
let fd = self.get_fd(vm)?;
|
||||
os::lseek(fd, 0, libc::SEEK_CUR, vm)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn truncate(&self, len: OptionalOption, vm: &VirtualMachine) -> PyResult<Offset> {
|
||||
let fd = self.fileno(vm)?;
|
||||
let fd = self.get_fd(vm)?;
|
||||
let len = match len.flatten() {
|
||||
Some(l) => get_offset(l, vm)?,
|
||||
None => os::lseek(fd, 0, libc::SEEK_CUR, vm)?,
|
||||
};
|
||||
os::ftruncate(fd, len, vm)?;
|
||||
os::ftruncate(fd, len).map_err(|e| e.into_pyexception(vm))?;
|
||||
Ok(len)
|
||||
}
|
||||
|
||||
|
||||
+116
-89
@@ -1,10 +1,10 @@
|
||||
// spell-checker:disable
|
||||
|
||||
use crate::{
|
||||
AsObject, Py, PyPayload, PyResult, VirtualMachine,
|
||||
AsObject, Py, PyObjectRef, PyPayload, PyResult, TryFromObject, VirtualMachine,
|
||||
builtins::{PyBaseExceptionRef, PyModule, PySet},
|
||||
common::crt_fd::Fd,
|
||||
convert::ToPyException,
|
||||
common::crt_fd,
|
||||
convert::{IntoPyException, ToPyException, ToPyObject},
|
||||
function::{ArgumentError, FromArgs, FuncArgs},
|
||||
};
|
||||
use std::{ffi, fs, io, path::Path};
|
||||
@@ -54,13 +54,13 @@ cfg_if::cfg_if! {
|
||||
const AT_FDCWD: i32 = -100;
|
||||
}
|
||||
}
|
||||
const DEFAULT_DIR_FD: Fd = Fd(AT_FDCWD);
|
||||
const DEFAULT_DIR_FD: crt_fd::Borrowed<'static> = unsafe { crt_fd::Borrowed::borrow_raw(AT_FDCWD) };
|
||||
|
||||
// XXX: AVAILABLE should be a bool, but we can't yet have it as a bool and just cast it to usize
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
pub struct DirFd<const AVAILABLE: usize>(pub(crate) [Fd; AVAILABLE]);
|
||||
pub struct DirFd<'fd, const AVAILABLE: usize>(pub(crate) [crt_fd::Borrowed<'fd>; AVAILABLE]);
|
||||
|
||||
impl<const AVAILABLE: usize> Default for DirFd<AVAILABLE> {
|
||||
impl<const AVAILABLE: usize> Default for DirFd<'_, AVAILABLE> {
|
||||
fn default() -> Self {
|
||||
Self([DEFAULT_DIR_FD; AVAILABLE])
|
||||
}
|
||||
@@ -68,33 +68,30 @@ impl<const AVAILABLE: usize> Default for DirFd<AVAILABLE> {
|
||||
|
||||
// not used on all platforms
|
||||
#[allow(unused)]
|
||||
impl DirFd<1> {
|
||||
impl<'fd> DirFd<'fd, 1> {
|
||||
#[inline(always)]
|
||||
pub(crate) fn fd_opt(&self) -> Option<Fd> {
|
||||
self.get_opt().map(Fd)
|
||||
pub(crate) fn get_opt(self) -> Option<crt_fd::Borrowed<'fd>> {
|
||||
let [fd] = self.0;
|
||||
(fd != DEFAULT_DIR_FD).then_some(fd)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn get_opt(&self) -> Option<i32> {
|
||||
let fd = self.fd();
|
||||
if fd == DEFAULT_DIR_FD {
|
||||
None
|
||||
} else {
|
||||
Some(fd.0)
|
||||
}
|
||||
pub(crate) fn raw_opt(self) -> Option<i32> {
|
||||
self.get_opt().map(|fd| fd.as_raw())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) const fn fd(&self) -> Fd {
|
||||
self.0[0]
|
||||
pub(crate) const fn get(self) -> crt_fd::Borrowed<'fd> {
|
||||
let [fd] = self.0;
|
||||
fd
|
||||
}
|
||||
}
|
||||
|
||||
impl<const AVAILABLE: usize> FromArgs for DirFd<AVAILABLE> {
|
||||
impl<const AVAILABLE: usize> FromArgs for DirFd<'_, AVAILABLE> {
|
||||
fn from_args(vm: &VirtualMachine, args: &mut FuncArgs) -> Result<Self, ArgumentError> {
|
||||
let fd = match args.take_keyword("dir_fd") {
|
||||
Some(o) if vm.is_none(&o) => DEFAULT_DIR_FD,
|
||||
None => DEFAULT_DIR_FD,
|
||||
Some(o) if vm.is_none(&o) => Ok(DEFAULT_DIR_FD),
|
||||
None => Ok(DEFAULT_DIR_FD),
|
||||
Some(o) => {
|
||||
let fd = o.try_index_opt(vm).unwrap_or_else(|| {
|
||||
Err(vm.new_type_error(format!(
|
||||
@@ -103,14 +100,15 @@ impl<const AVAILABLE: usize> FromArgs for DirFd<AVAILABLE> {
|
||||
)))
|
||||
})?;
|
||||
let fd = fd.try_to_primitive(vm)?;
|
||||
Fd(fd)
|
||||
unsafe { crt_fd::Borrowed::try_borrow_raw(fd) }
|
||||
}
|
||||
};
|
||||
if AVAILABLE == 0 && fd != DEFAULT_DIR_FD {
|
||||
if AVAILABLE == 0 && fd.as_ref().is_ok_and(|&fd| fd != DEFAULT_DIR_FD) {
|
||||
return Err(vm
|
||||
.new_not_implemented_error("dir_fd unavailable on this platform")
|
||||
.into());
|
||||
}
|
||||
let fd = fd.map_err(|e| e.to_pyexception(vm))?;
|
||||
Ok(Self([fd; AVAILABLE]))
|
||||
}
|
||||
}
|
||||
@@ -125,6 +123,32 @@ fn bytes_as_os_str<'a>(b: &'a [u8], vm: &VirtualMachine) -> PyResult<&'a ffi::Os
|
||||
.map_err(|_| vm.new_unicode_decode_error("can't decode path for utf-8"))
|
||||
}
|
||||
|
||||
impl TryFromObject for crt_fd::Owned {
|
||||
fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
|
||||
let fd = crt_fd::Raw::try_from_object(vm, obj)?;
|
||||
unsafe { crt_fd::Owned::try_from_raw(fd) }.map_err(|e| e.into_pyexception(vm))
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFromObject for crt_fd::Borrowed<'_> {
|
||||
fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
|
||||
let fd = crt_fd::Raw::try_from_object(vm, obj)?;
|
||||
unsafe { crt_fd::Borrowed::try_borrow_raw(fd) }.map_err(|e| e.into_pyexception(vm))
|
||||
}
|
||||
}
|
||||
|
||||
impl ToPyObject for crt_fd::Owned {
|
||||
fn to_pyobject(self, vm: &VirtualMachine) -> PyObjectRef {
|
||||
self.into_raw().to_pyobject(vm)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToPyObject for crt_fd::Borrowed<'_> {
|
||||
fn to_pyobject(self, vm: &VirtualMachine) -> PyObjectRef {
|
||||
self.as_raw().to_pyobject(vm)
|
||||
}
|
||||
}
|
||||
|
||||
#[pymodule(sub)]
|
||||
pub(super) mod _os {
|
||||
use super::{DirFd, FollowSymlinks, SupportFunc, errno_err};
|
||||
@@ -134,7 +158,7 @@ pub(super) mod _os {
|
||||
PyBytesRef, PyGenericAlias, PyIntRef, PyStrRef, PyTuple, PyTupleRef, PyTypeRef,
|
||||
},
|
||||
common::{
|
||||
crt_fd::{Fd, Offset},
|
||||
crt_fd,
|
||||
fileutils::StatStruct,
|
||||
lock::{OnceCell, PyRwLock},
|
||||
suppress_iph,
|
||||
@@ -153,7 +177,7 @@ pub(super) mod _os {
|
||||
use std::{
|
||||
env, ffi, fs,
|
||||
fs::OpenOptions,
|
||||
io::{self, Read, Write},
|
||||
io,
|
||||
path::PathBuf,
|
||||
time::{Duration, SystemTime},
|
||||
};
|
||||
@@ -180,30 +204,32 @@ pub(super) mod _os {
|
||||
pub(crate) const X_OK: u8 = 1 << 0;
|
||||
|
||||
#[pyfunction]
|
||||
fn close(fileno: i32, vm: &VirtualMachine) -> PyResult<()> {
|
||||
Fd(fileno).close().map_err(|e| e.into_pyexception(vm))
|
||||
fn close(fileno: crt_fd::Owned) -> io::Result<()> {
|
||||
crt_fd::close(fileno)
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn closerange(fd_low: i32, fd_high: i32) {
|
||||
for fileno in fd_low..fd_high {
|
||||
let _ = Fd(fileno).close();
|
||||
if let Ok(fd) = unsafe { crt_fd::Owned::try_from_raw(fileno) } {
|
||||
drop(fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(unix, windows, target_os = "wasi"))]
|
||||
#[derive(FromArgs)]
|
||||
struct OpenArgs {
|
||||
struct OpenArgs<'fd> {
|
||||
path: OsPath,
|
||||
flags: i32,
|
||||
#[pyarg(any, default)]
|
||||
mode: Option<i32>,
|
||||
#[pyarg(flatten)]
|
||||
dir_fd: DirFd<{ OPEN_DIR_FD as usize }>,
|
||||
dir_fd: DirFd<'fd, { OPEN_DIR_FD as usize }>,
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn open(args: OpenArgs, vm: &VirtualMachine) -> PyResult<i32> {
|
||||
fn open(args: OpenArgs<'_>, vm: &VirtualMachine) -> PyResult<crt_fd::Owned> {
|
||||
os_open(args.path, args.flags, args.mode, args.dir_fd, vm)
|
||||
}
|
||||
|
||||
@@ -212,9 +238,9 @@ pub(super) mod _os {
|
||||
name: OsPath,
|
||||
flags: i32,
|
||||
mode: Option<i32>,
|
||||
dir_fd: DirFd<{ OPEN_DIR_FD as usize }>,
|
||||
dir_fd: DirFd<'_, { OPEN_DIR_FD as usize }>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<i32> {
|
||||
) -> PyResult<crt_fd::Owned> {
|
||||
let mode = mode.unwrap_or(0o777);
|
||||
#[cfg(windows)]
|
||||
let fd = {
|
||||
@@ -229,51 +255,42 @@ pub(super) mod _os {
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
let flags = flags | libc::O_CLOEXEC;
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
if let Some(dir_fd) = dir_fd.fd_opt() {
|
||||
dir_fd.openat(&name, flags, mode)
|
||||
if let Some(dir_fd) = dir_fd.get_opt() {
|
||||
crt_fd::openat(dir_fd, &name, flags, mode)
|
||||
} else {
|
||||
Fd::open(&name, flags, mode)
|
||||
crt_fd::open(&name, flags, mode)
|
||||
}
|
||||
#[cfg(target_os = "redox")]
|
||||
{
|
||||
let [] = dir_fd.0;
|
||||
Fd::open(&name, flags, mode)
|
||||
crt_fd::open(&name, flags, mode)
|
||||
}
|
||||
};
|
||||
fd.map(|fd| fd.0)
|
||||
.map_err(|err| IOErrorBuilder::with_filename(&err, name, vm))
|
||||
fd.map_err(|err| IOErrorBuilder::with_filename(&err, name, vm))
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn fsync(fd: i32, vm: &VirtualMachine) -> PyResult<()> {
|
||||
Fd(fd).fsync().map_err(|err| err.into_pyexception(vm))
|
||||
fn fsync(fd: crt_fd::Borrowed<'_>) -> io::Result<()> {
|
||||
crt_fd::fsync(fd)
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn read(fd: i32, n: usize, vm: &VirtualMachine) -> PyResult<PyBytesRef> {
|
||||
fn read(fd: crt_fd::Borrowed<'_>, n: usize, vm: &VirtualMachine) -> io::Result<PyBytesRef> {
|
||||
let mut buffer = vec![0u8; n];
|
||||
let mut file = Fd(fd);
|
||||
let n = file
|
||||
.read(&mut buffer)
|
||||
.map_err(|err| err.into_pyexception(vm))?;
|
||||
let n = crt_fd::read(fd, &mut buffer)?;
|
||||
buffer.truncate(n);
|
||||
|
||||
Ok(vm.ctx.new_bytes(buffer))
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn write(fd: i32, data: ArgBytesLike, vm: &VirtualMachine) -> PyResult {
|
||||
let mut file = Fd(fd);
|
||||
let written = data
|
||||
.with_ref(|b| file.write(b))
|
||||
.map_err(|err| err.into_pyexception(vm))?;
|
||||
|
||||
Ok(vm.ctx.new_int(written).into())
|
||||
fn write(fd: crt_fd::Borrowed<'_>, data: ArgBytesLike) -> io::Result<usize> {
|
||||
data.with_ref(|b| crt_fd::write(fd, b))
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
#[pyfunction(name = "unlink")]
|
||||
fn remove(path: OsPath, dir_fd: DirFd<0>, vm: &VirtualMachine) -> PyResult<()> {
|
||||
fn remove(path: OsPath, dir_fd: DirFd<'_, 0>, vm: &VirtualMachine) -> PyResult<()> {
|
||||
let [] = dir_fd.0;
|
||||
let is_junction = cfg!(windows)
|
||||
&& fs::metadata(&path).is_ok_and(|meta| meta.file_type().is_dir())
|
||||
@@ -291,13 +308,13 @@ pub(super) mod _os {
|
||||
fn mkdir(
|
||||
path: OsPath,
|
||||
mode: OptionalArg<i32>,
|
||||
dir_fd: DirFd<{ MKDIR_DIR_FD as usize }>,
|
||||
dir_fd: DirFd<'_, { MKDIR_DIR_FD as usize }>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<()> {
|
||||
let mode = mode.unwrap_or(0o777);
|
||||
let c_path = path.clone().into_cstring(vm)?;
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
if let Some(fd) = dir_fd.get_opt() {
|
||||
if let Some(fd) = dir_fd.raw_opt() {
|
||||
let res = unsafe { libc::mkdirat(fd, c_path.as_ptr(), mode as _) };
|
||||
return if res < 0 {
|
||||
let err = crate::common::os::last_os_error();
|
||||
@@ -322,7 +339,7 @@ pub(super) mod _os {
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn rmdir(path: OsPath, dir_fd: DirFd<0>, vm: &VirtualMachine) -> PyResult<()> {
|
||||
fn rmdir(path: OsPath, dir_fd: DirFd<'_, 0>, vm: &VirtualMachine) -> PyResult<()> {
|
||||
let [] = dir_fd.0;
|
||||
fs::remove_dir(&path).map_err(|err| IOErrorBuilder::with_filename(&err, path, vm))
|
||||
}
|
||||
@@ -330,7 +347,10 @@ pub(super) mod _os {
|
||||
const LISTDIR_FD: bool = cfg!(all(unix, not(target_os = "redox")));
|
||||
|
||||
#[pyfunction]
|
||||
fn listdir(path: OptionalArg<OsPathOrFd>, vm: &VirtualMachine) -> PyResult<Vec<PyObjectRef>> {
|
||||
fn listdir(
|
||||
path: OptionalArg<OsPathOrFd<'_>>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<Vec<PyObjectRef>> {
|
||||
let path = path.unwrap_or_else(|| OsPathOrFd::Path(OsPath::new_str(".")));
|
||||
let list = match path {
|
||||
OsPathOrFd::Path(path) => {
|
||||
@@ -358,7 +378,8 @@ pub(super) mod _os {
|
||||
#[cfg(all(unix, not(target_os = "redox")))]
|
||||
{
|
||||
use rustpython_common::os::ffi::OsStrExt;
|
||||
let new_fd = nix::unistd::dup(fno).map_err(|e| e.into_pyexception(vm))?;
|
||||
let new_fd =
|
||||
nix::unistd::dup(fno.as_raw()).map_err(|e| e.into_pyexception(vm))?;
|
||||
let mut dir =
|
||||
nix::dir::Dir::from_fd(new_fd).map_err(|e| e.into_pyexception(vm))?;
|
||||
dir.iter()
|
||||
@@ -430,7 +451,7 @@ pub(super) mod _os {
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn readlink(path: OsPath, dir_fd: DirFd<0>, vm: &VirtualMachine) -> PyResult {
|
||||
fn readlink(path: OsPath, dir_fd: DirFd<'_, 0>, vm: &VirtualMachine) -> PyResult {
|
||||
let mode = path.mode;
|
||||
let [] = dir_fd.0;
|
||||
let path =
|
||||
@@ -515,7 +536,7 @@ pub(super) mod _os {
|
||||
#[pymethod]
|
||||
fn stat(
|
||||
&self,
|
||||
dir_fd: DirFd<{ STAT_DIR_FD as usize }>,
|
||||
dir_fd: DirFd<'_, { STAT_DIR_FD as usize }>,
|
||||
follow_symlinks: FollowSymlinks,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult {
|
||||
@@ -847,8 +868,8 @@ pub(super) mod _os {
|
||||
|
||||
#[cfg(not(windows))]
|
||||
fn stat_inner(
|
||||
file: OsPathOrFd,
|
||||
dir_fd: DirFd<{ STAT_DIR_FD as usize }>,
|
||||
file: OsPathOrFd<'_>,
|
||||
dir_fd: DirFd<'_, { STAT_DIR_FD as usize }>,
|
||||
follow_symlinks: FollowSymlinks,
|
||||
) -> io::Result<Option<StatStruct>> {
|
||||
let mut stat = std::mem::MaybeUninit::uninit();
|
||||
@@ -862,7 +883,7 @@ pub(super) mod _os {
|
||||
};
|
||||
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
let fstatat_ret = dir_fd.get_opt().map(|dir_fd| {
|
||||
let fstatat_ret = dir_fd.raw_opt().map(|dir_fd| {
|
||||
let flags = if follow_symlinks.0 {
|
||||
0
|
||||
} else {
|
||||
@@ -881,7 +902,7 @@ pub(super) mod _os {
|
||||
}
|
||||
})
|
||||
}
|
||||
OsPathOrFd::Fd(fd) => unsafe { libc::fstat(fd, stat.as_mut_ptr()) },
|
||||
OsPathOrFd::Fd(fd) => unsafe { libc::fstat(fd.as_raw(), stat.as_mut_ptr()) },
|
||||
};
|
||||
if ret < 0 {
|
||||
return Err(io::Error::last_os_error());
|
||||
@@ -892,8 +913,8 @@ pub(super) mod _os {
|
||||
#[pyfunction]
|
||||
#[pyfunction(name = "fstat")]
|
||||
fn stat(
|
||||
file: OsPathOrFd,
|
||||
dir_fd: DirFd<{ STAT_DIR_FD as usize }>,
|
||||
file: OsPathOrFd<'_>,
|
||||
dir_fd: DirFd<'_, { STAT_DIR_FD as usize }>,
|
||||
follow_symlinks: FollowSymlinks,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult {
|
||||
@@ -905,8 +926,8 @@ pub(super) mod _os {
|
||||
|
||||
#[pyfunction]
|
||||
fn lstat(
|
||||
file: OsPathOrFd,
|
||||
dir_fd: DirFd<{ STAT_DIR_FD as usize }>,
|
||||
file: OsPathOrFd<'_>,
|
||||
dir_fd: DirFd<'_, { STAT_DIR_FD as usize }>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult {
|
||||
stat(file, dir_fd, FollowSymlinks(false), vm)
|
||||
@@ -996,16 +1017,22 @@ pub(super) mod _os {
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
pub fn lseek(fd: i32, position: Offset, how: i32, vm: &VirtualMachine) -> PyResult<Offset> {
|
||||
pub fn lseek(
|
||||
fd: crt_fd::Borrowed<'_>,
|
||||
position: crt_fd::Offset,
|
||||
how: i32,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<crt_fd::Offset> {
|
||||
#[cfg(not(windows))]
|
||||
let res = unsafe { suppress_iph!(libc::lseek(fd, position, how)) };
|
||||
let res = unsafe { suppress_iph!(libc::lseek(fd.as_raw(), position, how)) };
|
||||
#[cfg(windows)]
|
||||
let res = unsafe {
|
||||
use std::os::windows::io::AsRawHandle;
|
||||
use windows_sys::Win32::Storage::FileSystem;
|
||||
let handle = Fd(fd).to_raw_handle().map_err(|e| e.into_pyexception(vm))?;
|
||||
let handle = crt_fd::as_handle(fd).map_err(|e| e.into_pyexception(vm))?;
|
||||
let mut distance_to_move: [i32; 2] = std::mem::transmute(position);
|
||||
let ret = FileSystem::SetFilePointer(
|
||||
handle as _,
|
||||
handle.as_raw_handle(),
|
||||
distance_to_move[0],
|
||||
&mut distance_to_move[1],
|
||||
how as _,
|
||||
@@ -1039,20 +1066,20 @@ pub(super) mod _os {
|
||||
}
|
||||
|
||||
#[derive(FromArgs)]
|
||||
struct UtimeArgs {
|
||||
struct UtimeArgs<'fd> {
|
||||
path: OsPath,
|
||||
#[pyarg(any, default)]
|
||||
times: Option<PyTupleRef>,
|
||||
#[pyarg(named, default)]
|
||||
ns: Option<PyTupleRef>,
|
||||
#[pyarg(flatten)]
|
||||
dir_fd: DirFd<{ UTIME_DIR_FD as usize }>,
|
||||
dir_fd: DirFd<'fd, { UTIME_DIR_FD as usize }>,
|
||||
#[pyarg(flatten)]
|
||||
follow_symlinks: FollowSymlinks,
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn utime(args: UtimeArgs, vm: &VirtualMachine) -> PyResult<()> {
|
||||
fn utime(args: UtimeArgs<'_>, vm: &VirtualMachine) -> PyResult<()> {
|
||||
let parse_tup = |tup: &Py<PyTuple>| -> Option<(PyObjectRef, PyObjectRef)> {
|
||||
if tup.len() != 2 {
|
||||
None
|
||||
@@ -1108,7 +1135,7 @@ pub(super) mod _os {
|
||||
path: OsPath,
|
||||
acc: Duration,
|
||||
modif: Duration,
|
||||
dir_fd: DirFd<{ UTIME_DIR_FD as usize }>,
|
||||
dir_fd: DirFd<'_, { UTIME_DIR_FD as usize }>,
|
||||
_follow_symlinks: FollowSymlinks,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<()> {
|
||||
@@ -1126,7 +1153,7 @@ pub(super) mod _os {
|
||||
|
||||
let ret = unsafe {
|
||||
libc::utimensat(
|
||||
dir_fd.fd().0,
|
||||
dir_fd.get().as_raw(),
|
||||
path.as_ptr(),
|
||||
times.as_ptr(),
|
||||
if _follow_symlinks.0 {
|
||||
@@ -1273,22 +1300,22 @@ pub(super) mod _os {
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[derive(FromArgs)]
|
||||
struct CopyFileRangeArgs {
|
||||
struct CopyFileRangeArgs<'fd> {
|
||||
#[pyarg(positional)]
|
||||
src: i32,
|
||||
src: crt_fd::Borrowed<'fd>,
|
||||
#[pyarg(positional)]
|
||||
dst: i32,
|
||||
dst: crt_fd::Borrowed<'fd>,
|
||||
#[pyarg(positional)]
|
||||
count: i64,
|
||||
#[pyarg(any, default)]
|
||||
offset_src: Option<Offset>,
|
||||
offset_src: Option<crt_fd::Offset>,
|
||||
#[pyarg(any, default)]
|
||||
offset_dst: Option<Offset>,
|
||||
offset_dst: Option<crt_fd::Offset>,
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[pyfunction]
|
||||
fn copy_file_range(args: CopyFileRangeArgs, vm: &VirtualMachine) -> PyResult<usize> {
|
||||
fn copy_file_range(args: CopyFileRangeArgs<'_>, vm: &VirtualMachine) -> PyResult<usize> {
|
||||
let p_offset_src = args.offset_src.as_ref().map_or_else(std::ptr::null, |x| x);
|
||||
let p_offset_dst = args.offset_dst.as_ref().map_or_else(std::ptr::null, |x| x);
|
||||
let count: usize = args
|
||||
@@ -1328,14 +1355,14 @@ pub(super) mod _os {
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
pub fn ftruncate(fd: i32, length: Offset, vm: &VirtualMachine) -> PyResult<()> {
|
||||
Fd(fd).ftruncate(length).map_err(|e| e.into_pyexception(vm))
|
||||
pub fn ftruncate(fd: crt_fd::Borrowed<'_>, length: crt_fd::Offset) -> io::Result<()> {
|
||||
crt_fd::ftruncate(fd, length)
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn truncate(path: PyObjectRef, length: Offset, vm: &VirtualMachine) -> PyResult<()> {
|
||||
if let Ok(fd) = path.try_to_value(vm) {
|
||||
return ftruncate(fd, length, vm);
|
||||
fn truncate(path: PyObjectRef, length: crt_fd::Offset, vm: &VirtualMachine) -> PyResult<()> {
|
||||
if let Ok(fd) = path.clone().try_into_value(vm) {
|
||||
return ftruncate(fd, length).map_err(|e| e.into_pyexception(vm));
|
||||
}
|
||||
|
||||
#[cold]
|
||||
|
||||
+26
-26
@@ -355,22 +355,22 @@ pub mod module {
|
||||
}
|
||||
|
||||
#[derive(FromArgs)]
|
||||
pub(super) struct SymlinkArgs {
|
||||
pub(super) struct SymlinkArgs<'fd> {
|
||||
src: OsPath,
|
||||
dst: OsPath,
|
||||
#[pyarg(flatten)]
|
||||
_target_is_directory: TargetIsDirectory,
|
||||
#[pyarg(flatten)]
|
||||
dir_fd: DirFd<{ _os::SYMLINK_DIR_FD as usize }>,
|
||||
dir_fd: DirFd<'fd, { _os::SYMLINK_DIR_FD as usize }>,
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
pub(super) fn symlink(args: SymlinkArgs, vm: &VirtualMachine) -> PyResult<()> {
|
||||
pub(super) fn symlink(args: SymlinkArgs<'_>, vm: &VirtualMachine) -> PyResult<()> {
|
||||
let src = args.src.into_cstring(vm)?;
|
||||
let dst = args.dst.into_cstring(vm)?;
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
{
|
||||
nix::unistd::symlinkat(&*src, args.dir_fd.get_opt(), &*dst)
|
||||
nix::unistd::symlinkat(&*src, args.dir_fd.raw_opt(), &*dst)
|
||||
.map_err(|err| err.into_pyexception(vm))
|
||||
}
|
||||
#[cfg(target_os = "redox")]
|
||||
@@ -403,10 +403,10 @@ pub mod module {
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
#[pyfunction]
|
||||
fn chown(
|
||||
path: OsPathOrFd,
|
||||
path: OsPathOrFd<'_>,
|
||||
uid: isize,
|
||||
gid: isize,
|
||||
dir_fd: DirFd<1>,
|
||||
dir_fd: DirFd<'_, 1>,
|
||||
follow_symlinks: FollowSymlinks,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<()> {
|
||||
@@ -432,12 +432,12 @@ pub mod module {
|
||||
nix::fcntl::AtFlags::AT_SYMLINK_NOFOLLOW
|
||||
};
|
||||
|
||||
let dir_fd = dir_fd.get_opt();
|
||||
let dir_fd = dir_fd.raw_opt();
|
||||
match path {
|
||||
OsPathOrFd::Path(ref p) => {
|
||||
nix::unistd::fchownat(dir_fd, p.path.as_os_str(), uid, gid, flag)
|
||||
}
|
||||
OsPathOrFd::Fd(fd) => nix::unistd::fchown(fd, uid, gid),
|
||||
OsPathOrFd::Fd(fd) => nix::unistd::fchown(fd.as_raw(), uid, gid),
|
||||
}
|
||||
.map_err(|err| {
|
||||
// Use `From<nix::Error> for io::Error` when it is available
|
||||
@@ -461,9 +461,9 @@ pub mod module {
|
||||
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
#[pyfunction]
|
||||
fn fchown(fd: i32, uid: isize, gid: isize, vm: &VirtualMachine) -> PyResult<()> {
|
||||
fn fchown(fd: BorrowedFd<'_>, uid: isize, gid: isize, vm: &VirtualMachine) -> PyResult<()> {
|
||||
chown(
|
||||
OsPathOrFd::Fd(fd),
|
||||
OsPathOrFd::Fd(fd.into()),
|
||||
uid,
|
||||
gid,
|
||||
DirFd::default(),
|
||||
@@ -590,7 +590,7 @@ pub mod module {
|
||||
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
#[derive(FromArgs)]
|
||||
struct MknodArgs {
|
||||
struct MknodArgs<'fd> {
|
||||
#[pyarg(any)]
|
||||
path: OsPath,
|
||||
#[pyarg(any)]
|
||||
@@ -598,11 +598,11 @@ pub mod module {
|
||||
#[pyarg(any)]
|
||||
device: libc::dev_t,
|
||||
#[pyarg(flatten)]
|
||||
dir_fd: DirFd<{ MKNOD_DIR_FD as usize }>,
|
||||
dir_fd: DirFd<'fd, { MKNOD_DIR_FD as usize }>,
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
impl MknodArgs {
|
||||
impl MknodArgs<'_> {
|
||||
fn _mknod(self, vm: &VirtualMachine) -> PyResult<i32> {
|
||||
Ok(unsafe {
|
||||
libc::mknod(
|
||||
@@ -615,7 +615,7 @@ pub mod module {
|
||||
|
||||
#[cfg(not(target_vendor = "apple"))]
|
||||
fn mknod(self, vm: &VirtualMachine) -> PyResult<()> {
|
||||
let ret = match self.dir_fd.get_opt() {
|
||||
let ret = match self.dir_fd.raw_opt() {
|
||||
None => self._mknod(vm)?,
|
||||
Some(non_default_fd) => unsafe {
|
||||
libc::mknodat(
|
||||
@@ -639,7 +639,7 @@ pub mod module {
|
||||
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
#[pyfunction]
|
||||
fn mknod(args: MknodArgs, vm: &VirtualMachine) -> PyResult<()> {
|
||||
fn mknod(args: MknodArgs<'_>, vm: &VirtualMachine) -> PyResult<()> {
|
||||
args.mknod(vm)
|
||||
}
|
||||
|
||||
@@ -920,7 +920,7 @@ pub mod module {
|
||||
|
||||
fn _chmod(
|
||||
path: OsPath,
|
||||
dir_fd: DirFd<0>,
|
||||
dir_fd: DirFd<'_, 0>,
|
||||
mode: u32,
|
||||
follow_symlinks: FollowSymlinks,
|
||||
vm: &VirtualMachine,
|
||||
@@ -938,9 +938,9 @@ pub mod module {
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
fn _fchmod(fd: RawFd, mode: u32, vm: &VirtualMachine) -> PyResult<()> {
|
||||
fn _fchmod(fd: BorrowedFd<'_>, mode: u32, vm: &VirtualMachine) -> PyResult<()> {
|
||||
nix::sys::stat::fchmod(
|
||||
fd,
|
||||
fd.as_raw_fd(),
|
||||
nix::sys::stat::Mode::from_bits(mode as libc::mode_t).unwrap(),
|
||||
)
|
||||
.map_err(|err| err.into_pyexception(vm))
|
||||
@@ -949,8 +949,8 @@ pub mod module {
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
#[pyfunction]
|
||||
fn chmod(
|
||||
path: OsPathOrFd,
|
||||
dir_fd: DirFd<0>,
|
||||
path: OsPathOrFd<'_>,
|
||||
dir_fd: DirFd<'_, 0>,
|
||||
mode: u32,
|
||||
follow_symlinks: FollowSymlinks,
|
||||
vm: &VirtualMachine,
|
||||
@@ -963,7 +963,7 @@ pub mod module {
|
||||
}
|
||||
_chmod(path, dir_fd, mode, follow_symlinks, vm)
|
||||
}
|
||||
OsPathOrFd::Fd(fd) => _fchmod(fd, mode, vm),
|
||||
OsPathOrFd::Fd(fd) => _fchmod(fd.into(), mode, vm),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -981,7 +981,7 @@ pub mod module {
|
||||
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
#[pyfunction]
|
||||
fn fchmod(fd: RawFd, mode: u32, vm: &VirtualMachine) -> PyResult<()> {
|
||||
fn fchmod(fd: BorrowedFd<'_>, mode: u32, vm: &VirtualMachine) -> PyResult<()> {
|
||||
_fchmod(fd, mode, vm)
|
||||
}
|
||||
|
||||
@@ -2065,7 +2065,7 @@ pub mod module {
|
||||
#[cfg(unix)]
|
||||
#[pyfunction]
|
||||
fn pathconf(
|
||||
path: OsPathOrFd,
|
||||
path: OsPathOrFd<'_>,
|
||||
PathconfName(name): PathconfName,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<Option<libc::c_long>> {
|
||||
@@ -2078,7 +2078,7 @@ pub mod module {
|
||||
let path = path.clone().into_cstring(vm)?;
|
||||
unsafe { libc::pathconf(path.as_ptr(), name) }
|
||||
}
|
||||
OsPathOrFd::Fd(fd) => unsafe { libc::fpathconf(*fd, name) },
|
||||
OsPathOrFd::Fd(fd) => unsafe { libc::fpathconf(fd.as_raw(), name) },
|
||||
};
|
||||
|
||||
if raw == -1 {
|
||||
@@ -2098,11 +2098,11 @@ pub mod module {
|
||||
|
||||
#[pyfunction]
|
||||
fn fpathconf(
|
||||
fd: i32,
|
||||
fd: BorrowedFd<'_>,
|
||||
name: PathconfName,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<Option<libc::c_long>> {
|
||||
pathconf(OsPathOrFd::Fd(fd), name, vm)
|
||||
pathconf(OsPathOrFd::Fd(fd.into()), name, vm)
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
|
||||
@@ -26,17 +26,17 @@ pub(crate) mod module {
|
||||
|
||||
#[derive(FromArgs)]
|
||||
#[allow(unused)]
|
||||
pub(super) struct SymlinkArgs {
|
||||
pub(super) struct SymlinkArgs<'a> {
|
||||
src: OsPath,
|
||||
dst: OsPath,
|
||||
#[pyarg(flatten)]
|
||||
_target_is_directory: TargetIsDirectory,
|
||||
#[pyarg(flatten)]
|
||||
_dir_fd: DirFd<{ _os::SYMLINK_DIR_FD as usize }>,
|
||||
_dir_fd: DirFd<'a, { _os::SYMLINK_DIR_FD as usize }>,
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
pub(super) fn symlink(_args: SymlinkArgs, vm: &VirtualMachine) -> PyResult<()> {
|
||||
pub(super) fn symlink(_args: SymlinkArgs<'_>, vm: &VirtualMachine) -> PyResult<()> {
|
||||
os_unimpl("os.symlink", vm)
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user