Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Windows fixes
  • Loading branch information
coolreader18 committed Aug 29, 2025
commit dc4be4775101ec413cc0f91905e98bd553eb1f00
5 changes: 3 additions & 2 deletions common/src/crt_fd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,12 +335,13 @@ pub fn ftruncate(fd: Borrowed<'_>, len: Offset) -> io::Result<()> {

#[cfg(windows)]
pub fn as_handle(fd: Borrowed<'_>) -> io::Result<BorrowedHandle<'_>> {
use windows_sys::Win32::Foundation::{HANDLE, INVALID_HANDLE_VALUE};
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())
if handle as HANDLE == INVALID_HANDLE_VALUE {
Err(crate::os::last_os_error())
} else {
Ok(unsafe { BorrowedHandle::borrow_raw(handle as _) })
}
Expand Down
28 changes: 8 additions & 20 deletions common/src/fileutils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ pub use libc::stat as StatStruct;
pub use windows::{StatStruct, fstat};

#[cfg(not(windows))]
pub fn fstat(fd: libc::c_int) -> std::io::Result<StatStruct> {
pub fn fstat(fd: crate::crt_fd::Borrowed<'_>) -> std::io::Result<StatStruct> {
let mut stat = std::mem::MaybeUninit::uninit();
unsafe {
let ret = libc::fstat(fd, stat.as_mut_ptr());
let ret = libc::fstat(fd.as_raw(), stat.as_mut_ptr());
if ret == -1 {
Err(crate::os::last_os_error())
} else {
Expand All @@ -22,15 +22,15 @@ pub fn fstat(fd: libc::c_int) -> std::io::Result<StatStruct> {

#[cfg(windows)]
pub mod windows {
use crate::suppress_iph;
use crate::crt_fd;
use crate::windows::ToWideString;
use libc::{S_IFCHR, S_IFDIR, S_IFMT};
use std::ffi::{CString, OsStr, OsString};
use std::os::windows::ffi::OsStrExt;
use std::os::windows::io::AsRawHandle;
use std::sync::OnceLock;
use windows_sys::Win32::Foundation::{
BOOL, ERROR_INVALID_HANDLE, ERROR_NOT_SUPPORTED, FILETIME, FreeLibrary, HANDLE,
INVALID_HANDLE_VALUE, SetLastError,
BOOL, ERROR_INVALID_HANDLE, ERROR_NOT_SUPPORTED, FILETIME, FreeLibrary, SetLastError,
};
use windows_sys::Win32::Storage::FileSystem::{
BY_HANDLE_FILE_INFORMATION, FILE_ATTRIBUTE_DIRECTORY, FILE_ATTRIBUTE_READONLY,
Expand Down Expand Up @@ -94,26 +94,14 @@ pub mod windows {
}
}

unsafe extern "C" {
fn _get_osfhandle(fd: i32) -> libc::intptr_t;
}

fn get_osfhandle(fd: i32) -> std::io::Result<isize> {
let ret = unsafe { suppress_iph!(_get_osfhandle(fd)) };
if ret as HANDLE == INVALID_HANDLE_VALUE {
Err(crate::os::last_os_error())
} else {
Ok(ret)
}
}

// _Py_fstat_noraise in cpython
pub fn fstat(fd: libc::c_int) -> std::io::Result<StatStruct> {
let h = get_osfhandle(fd);
pub fn fstat(fd: crt_fd::Borrowed<'_>) -> std::io::Result<StatStruct> {
let h = crt_fd::as_handle(fd);
if h.is_err() {
unsafe { SetLastError(ERROR_INVALID_HANDLE) };
}
let h = h?;
let h = h.as_raw_handle();
// reset stat?

let file_type = unsafe { GetFileType(h as _) };
Expand Down
2 changes: 1 addition & 1 deletion vm/src/stdlib/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4339,7 +4339,7 @@ mod fileio {

// TODO: _Py_set_inheritable

let fd_fstat = crate::common::fileutils::fstat(fd.as_raw());
let fd_fstat = crate::common::fileutils::fstat(fd);

#[cfg(windows)]
{
Expand Down
27 changes: 11 additions & 16 deletions vm/src/stdlib/msvcrt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,21 @@ mod msvcrt {
use crate::{
PyRef, PyResult, VirtualMachine,
builtins::{PyBytes, PyStrRef},
common::suppress_iph,
common::{crt_fd, suppress_iph},
convert::IntoPyException,
stdlib::os::errno_err,
};
use itertools::Itertools;
use windows_sys::Win32::{
Foundation::{HANDLE, INVALID_HANDLE_VALUE},
System::Diagnostics::Debug,
};
use std::os::windows::io::AsRawHandle;
use windows_sys::Win32::System::Diagnostics::Debug;

#[pyattr]
use windows_sys::Win32::System::Diagnostics::Debug::{
SEM_FAILCRITICALERRORS, SEM_NOALIGNMENTFAULTEXCEPT, SEM_NOGPFAULTERRORBOX,
SEM_NOOPENFILEERRORBOX,
};

pub fn setmode_binary(fd: i32) {
pub fn setmode_binary(fd: crt_fd::Borrowed<'_>) {
unsafe { suppress_iph!(_setmode(fd, libc::O_BINARY)) };
}

Expand Down Expand Up @@ -76,11 +75,11 @@ mod msvcrt {
}

unsafe extern "C" {
fn _setmode(fd: i32, flags: i32) -> i32;
fn _setmode(fd: crt_fd::Borrowed<'_>, flags: i32) -> i32;
}

#[pyfunction]
fn setmode(fd: i32, flags: i32, vm: &VirtualMachine) -> PyResult<i32> {
fn setmode(fd: crt_fd::Borrowed<'_>, flags: i32, vm: &VirtualMachine) -> PyResult<i32> {
let flags = unsafe { suppress_iph!(_setmode(fd, flags)) };
if flags == -1 {
Err(errno_err(vm))
Expand All @@ -91,7 +90,6 @@ mod msvcrt {

unsafe extern "C" {
fn _open_osfhandle(osfhandle: isize, flags: i32) -> i32;
fn _get_osfhandle(fd: i32) -> libc::intptr_t;
}

#[pyfunction]
Expand All @@ -105,13 +103,10 @@ mod msvcrt {
}

#[pyfunction]
fn get_osfhandle(fd: i32, vm: &VirtualMachine) -> PyResult<isize> {
let ret = unsafe { suppress_iph!(_get_osfhandle(fd)) };
if ret as HANDLE == INVALID_HANDLE_VALUE {
Err(errno_err(vm))
} else {
Ok(ret)
}
fn get_osfhandle(fd: crt_fd::Borrowed<'_>, vm: &VirtualMachine) -> PyResult<isize> {
crt_fd::as_handle(fd)
.map(|h| h.as_raw_handle() as _)
.map_err(|e| e.into_pyexception(vm))
}

#[allow(non_snake_case)]
Expand Down
23 changes: 14 additions & 9 deletions vm/src/stdlib/nt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,14 @@ pub(crate) mod module {
use crate::{
PyResult, TryFromObject, VirtualMachine,
builtins::{PyDictRef, PyListRef, PyStrRef, PyTupleRef},
common::{crt_fd::Fd, os::last_os_error, suppress_iph},
common::{crt_fd, os::last_os_error, suppress_iph},
convert::ToPyException,
function::{Either, OptionalArg},
ospath::OsPath,
stdlib::os::{_os, DirFd, FollowSymlinks, SupportFunc, TargetIsDirectory, errno_err},
};
use libc::intptr_t;
use std::os::windows::io::AsRawHandle;
use std::{
env, fs, io,
mem::MaybeUninit,
Expand Down Expand Up @@ -61,17 +62,17 @@ pub(crate) 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<()> {
use std::os::windows::fs as win_fs;
let dir = args.target_is_directory.target_is_directory
|| args
Expand All @@ -89,9 +90,13 @@ pub(crate) mod module {
}

#[pyfunction]
fn set_inheritable(fd: i32, inheritable: bool, vm: &VirtualMachine) -> PyResult<()> {
let handle = Fd(fd).to_raw_handle().map_err(|e| e.to_pyexception(vm))?;
set_handle_inheritable(handle as _, inheritable, vm)
fn set_inheritable(
fd: crt_fd::Borrowed<'_>,
inheritable: bool,
vm: &VirtualMachine,
) -> PyResult<()> {
let handle = crt_fd::as_handle(fd).map_err(|e| e.to_pyexception(vm))?;
set_handle_inheritable(handle.as_raw_handle() as _, inheritable, vm)
}

#[pyattr]
Expand All @@ -107,7 +112,7 @@ pub(crate) mod module {
#[pyfunction]
fn chmod(
path: OsPath,
dir_fd: DirFd<0>,
dir_fd: DirFd<'_, 0>,
mode: u32,
follow_symlinks: FollowSymlinks,
vm: &VirtualMachine,
Expand Down Expand Up @@ -456,7 +461,7 @@ pub(crate) mod module {
fn mkdir(
path: OsPath,
mode: OptionalArg<i32>,
dir_fd: DirFd<{ _os::MKDIR_DIR_FD as usize }>,
dir_fd: DirFd<'_, { _os::MKDIR_DIR_FD as usize }>,
vm: &VirtualMachine,
) -> PyResult<()> {
let mode = mode.unwrap_or(0o777);
Expand Down
6 changes: 3 additions & 3 deletions vm/src/stdlib/os.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ pub(super) mod _os {
let [] = dir_fd.0;
let name = name.to_wide_cstring(vm)?;
let flags = flags | libc::O_NOINHERIT;
Fd::wopen(&name, flags, mode)
crt_fd::wopen(&name, flags, mode)
};
#[cfg(not(windows))]
let fd = {
Expand Down Expand Up @@ -853,8 +853,8 @@ pub(super) mod _os {

#[cfg(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>> {
// TODO: replicate CPython's win32_xstat
Expand Down