Skip to content

Commit bd85062

Browse files
Copilotyouknowone
andcommitted
refactor: expand phase 2 and 4 host extraction
Agent-Logs-Url: https://github.com/RustPython/RustPython/sessions/b05407a9-7edd-4747-8691-3a9228d67b75 Co-authored-by: youknowone <69878+youknowone@users.noreply.github.com>
1 parent 9a6d5a6 commit bd85062

19 files changed

Lines changed: 671 additions & 421 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/host_env/Cargo.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,23 @@ num-traits = { workspace = true }
1616

1717
[target.'cfg(unix)'.dependencies]
1818
nix = { workspace = true }
19+
termios = "0.3.3"
1920

2021
[target.'cfg(windows)'.dependencies]
2122
widestring = { workspace = true }
2223
windows-sys = { workspace = true, features = [
2324
"Win32_Foundation",
25+
"Win32_Globalization",
2426
"Win32_Networking_WinSock",
2527
"Win32_Storage_FileSystem",
28+
"Win32_System_Console",
29+
"Win32_System_Diagnostics_Debug",
2630
"Win32_System_Ioctl",
2731
"Win32_System_LibraryLoader",
32+
"Win32_System_SystemInformation",
2833
"Win32_System_SystemServices",
34+
"Win32_System_Threading",
35+
"Win32_System_Time",
2936
] }
3037

3138
[lints]

crates/host_env/src/fcntl.rs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
use std::io;
2+
3+
#[cfg(target_os = "wasi")]
4+
fn ioctl_request(request: libc::c_ulong) -> libc::c_int {
5+
request as _
6+
}
7+
8+
#[cfg(not(target_os = "wasi"))]
9+
fn ioctl_request(request: libc::c_ulong) -> libc::c_ulong {
10+
request
11+
}
12+
13+
pub fn fcntl_int(fd: i32, cmd: i32, arg: i32) -> io::Result<i32> {
14+
let ret = unsafe { libc::fcntl(fd, cmd, arg) };
15+
if ret < 0 {
16+
Err(io::Error::last_os_error())
17+
} else {
18+
Ok(ret)
19+
}
20+
}
21+
22+
pub fn fcntl_with_bytes(fd: i32, cmd: i32, arg: &mut [u8]) -> io::Result<i32> {
23+
let ret = unsafe { libc::fcntl(fd, cmd, arg.as_mut_ptr()) };
24+
if ret < 0 {
25+
Err(io::Error::last_os_error())
26+
} else {
27+
Ok(ret)
28+
}
29+
}
30+
31+
/// # Safety
32+
///
33+
/// `arg` must be a valid pointer for the `request` passed to `ioctl` and must
34+
/// satisfy the platform ABI requirements for that request.
35+
pub unsafe fn ioctl_ptr(
36+
fd: i32,
37+
request: libc::c_ulong,
38+
arg: *mut libc::c_void,
39+
) -> io::Result<i32> {
40+
let ret = unsafe { libc::ioctl(fd, ioctl_request(request), arg) };
41+
if ret < 0 {
42+
Err(io::Error::last_os_error())
43+
} else {
44+
Ok(ret)
45+
}
46+
}
47+
48+
pub fn ioctl_int(fd: i32, request: libc::c_ulong, arg: i32) -> io::Result<i32> {
49+
let ret = unsafe { libc::ioctl(fd, ioctl_request(request), arg) };
50+
if ret < 0 {
51+
Err(io::Error::last_os_error())
52+
} else {
53+
Ok(ret)
54+
}
55+
}
56+
57+
#[cfg(not(any(target_os = "wasi", target_os = "redox")))]
58+
pub fn flock(fd: i32, operation: i32) -> io::Result<i32> {
59+
let ret = unsafe { libc::flock(fd, operation) };
60+
if ret < 0 {
61+
Err(io::Error::last_os_error())
62+
} else {
63+
Ok(ret)
64+
}
65+
}
66+
67+
#[cfg(not(any(target_os = "wasi", target_os = "redox")))]
68+
pub fn lockf(fd: i32, cmd: i32, lock: &libc::flock) -> io::Result<i32> {
69+
let ret = unsafe {
70+
libc::fcntl(
71+
fd,
72+
if (cmd & libc::LOCK_NB) != 0 {
73+
libc::F_SETLK
74+
} else {
75+
libc::F_SETLKW
76+
},
77+
lock,
78+
)
79+
};
80+
if ret < 0 {
81+
Err(io::Error::last_os_error())
82+
} else {
83+
Ok(ret)
84+
}
85+
}

crates/host_env/src/lib.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,26 @@ pub mod fileutils;
1515
#[cfg(windows)]
1616
pub mod windows;
1717

18+
#[cfg(any(unix, target_os = "wasi"))]
19+
pub mod fcntl;
20+
#[cfg(any(unix, windows, target_os = "wasi"))]
21+
pub mod select;
22+
#[cfg(unix)]
23+
pub mod syslog;
24+
#[cfg(all(unix, not(target_os = "redox"), not(target_os = "ios")))]
25+
pub mod termios;
26+
1827
#[cfg(unix)]
1928
pub mod posix;
2029
#[cfg(all(unix, not(target_os = "redox"), not(target_os = "android")))]
2130
pub mod shm;
2231
#[cfg(unix)]
2332
pub mod signal;
2433
pub mod time;
34+
35+
#[cfg(windows)]
36+
pub mod msvcrt;
37+
#[cfg(windows)]
38+
pub mod nt;
39+
#[cfg(windows)]
40+
pub mod winapi;

crates/host_env/src/msvcrt.rs

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
use alloc::{string::String, vec::Vec};
2+
use std::io;
3+
4+
use crate::{crt_fd, suppress_iph};
5+
use windows_sys::Win32::System::Diagnostics::Debug;
6+
7+
pub const LK_UNLCK: i32 = 0;
8+
pub const LK_LOCK: i32 = 1;
9+
pub const LK_NBLCK: i32 = 2;
10+
pub const LK_RLCK: i32 = 3;
11+
pub const LK_NBRLCK: i32 = 4;
12+
13+
unsafe extern "C" {
14+
fn _getch() -> i32;
15+
fn _getwch() -> u32;
16+
fn _getche() -> i32;
17+
fn _getwche() -> u32;
18+
fn _putch(c: u32) -> i32;
19+
fn _putwch(c: u16) -> u32;
20+
fn _ungetch(c: i32) -> i32;
21+
fn _ungetwch(c: u32) -> u32;
22+
fn _locking(fd: i32, mode: i32, nbytes: i64) -> i32;
23+
fn _heapmin() -> i32;
24+
fn _kbhit() -> i32;
25+
fn _setmode(fd: crt_fd::Borrowed<'_>, flags: i32) -> i32;
26+
}
27+
28+
pub fn setmode_binary(fd: crt_fd::Borrowed<'_>) {
29+
unsafe { suppress_iph!(_setmode(fd, libc::O_BINARY)) };
30+
}
31+
32+
pub fn getch() -> Vec<u8> {
33+
vec![unsafe { _getch() } as u8]
34+
}
35+
36+
pub fn getwch() -> String {
37+
let value = unsafe { _getwch() };
38+
char::from_u32(value)
39+
.unwrap_or_else(|| panic!("invalid unicode {value:#x} from _getwch"))
40+
.to_string()
41+
}
42+
43+
pub fn getche() -> Vec<u8> {
44+
vec![unsafe { _getche() } as u8]
45+
}
46+
47+
pub fn getwche() -> String {
48+
let value = unsafe { _getwche() };
49+
char::from_u32(value)
50+
.unwrap_or_else(|| panic!("invalid unicode {value:#x} from _getwche"))
51+
.to_string()
52+
}
53+
54+
pub fn putch(c: u8) {
55+
unsafe { suppress_iph!(_putch(c.into())) };
56+
}
57+
58+
pub fn putwch(c: char) {
59+
unsafe { suppress_iph!(_putwch(c as u16)) };
60+
}
61+
62+
pub fn ungetch(c: u8) -> io::Result<()> {
63+
let ret = unsafe { suppress_iph!(_ungetch(c as i32)) };
64+
if ret == -1 {
65+
Err(io::Error::from_raw_os_error(libc::ENOSPC))
66+
} else {
67+
Ok(())
68+
}
69+
}
70+
71+
pub fn ungetwch(c: char) -> io::Result<()> {
72+
let ret = unsafe { suppress_iph!(_ungetwch(c as u32)) };
73+
if ret == 0xFFFF {
74+
Err(io::Error::from_raw_os_error(libc::ENOSPC))
75+
} else {
76+
Ok(())
77+
}
78+
}
79+
80+
pub fn kbhit() -> i32 {
81+
unsafe { _kbhit() }
82+
}
83+
84+
pub fn locking(fd: i32, mode: i32, nbytes: i64) -> io::Result<()> {
85+
let ret = unsafe { suppress_iph!(_locking(fd, mode, nbytes)) };
86+
if ret == -1 {
87+
Err(io::Error::last_os_error())
88+
} else {
89+
Ok(())
90+
}
91+
}
92+
93+
pub fn heapmin() -> io::Result<()> {
94+
let ret = unsafe { suppress_iph!(_heapmin()) };
95+
if ret == -1 {
96+
Err(io::Error::last_os_error())
97+
} else {
98+
Ok(())
99+
}
100+
}
101+
102+
pub fn setmode(fd: crt_fd::Borrowed<'_>, flags: i32) -> io::Result<i32> {
103+
let ret = unsafe { suppress_iph!(_setmode(fd, flags)) };
104+
if ret == -1 {
105+
Err(io::Error::last_os_error())
106+
} else {
107+
Ok(ret)
108+
}
109+
}
110+
111+
pub fn open_osfhandle(handle: isize, flags: i32) -> io::Result<i32> {
112+
let ret = unsafe { suppress_iph!(libc::open_osfhandle(handle, flags)) };
113+
if ret == -1 {
114+
Err(io::Error::last_os_error())
115+
} else {
116+
Ok(ret)
117+
}
118+
}
119+
120+
pub fn get_error_mode() -> u32 {
121+
unsafe { suppress_iph!(Debug::GetErrorMode()) }
122+
}
123+
124+
pub fn set_error_mode(mode: Debug::THREAD_ERROR_MODE) -> u32 {
125+
unsafe { suppress_iph!(Debug::SetErrorMode(mode)) }
126+
}

crates/host_env/src/nt.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
use std::{ffi::OsStr, io, os::windows::io::AsRawHandle};
2+
3+
use crate::{crt_fd, windows::ToWideString};
4+
use windows_sys::Win32::{
5+
Foundation::HANDLE,
6+
Storage::FileSystem::{
7+
FILE_ATTRIBUTE_READONLY, FILE_BASIC_INFO, FileBasicInfo, GetFileAttributesW,
8+
GetFileInformationByHandleEx, INVALID_FILE_ATTRIBUTES, SetFileAttributesW,
9+
SetFileInformationByHandle,
10+
},
11+
};
12+
13+
pub fn win32_hchmod(handle: HANDLE, mode: u32, write_bit: u32) -> io::Result<()> {
14+
let mut info: FILE_BASIC_INFO = unsafe { core::mem::zeroed() };
15+
let ret = unsafe {
16+
GetFileInformationByHandleEx(
17+
handle,
18+
FileBasicInfo,
19+
(&mut info as *mut FILE_BASIC_INFO).cast(),
20+
core::mem::size_of::<FILE_BASIC_INFO>() as u32,
21+
)
22+
};
23+
if ret == 0 {
24+
return Err(io::Error::last_os_error());
25+
}
26+
27+
if mode & write_bit != 0 {
28+
info.FileAttributes &= !FILE_ATTRIBUTE_READONLY;
29+
} else {
30+
info.FileAttributes |= FILE_ATTRIBUTE_READONLY;
31+
}
32+
33+
let ret = unsafe {
34+
SetFileInformationByHandle(
35+
handle,
36+
FileBasicInfo,
37+
(&info as *const FILE_BASIC_INFO).cast(),
38+
core::mem::size_of::<FILE_BASIC_INFO>() as u32,
39+
)
40+
};
41+
if ret == 0 {
42+
Err(io::Error::last_os_error())
43+
} else {
44+
Ok(())
45+
}
46+
}
47+
48+
pub fn fchmod(fd: i32, mode: u32, write_bit: u32) -> io::Result<()> {
49+
let borrowed = unsafe { crt_fd::Borrowed::borrow_raw(fd) };
50+
let handle = crt_fd::as_handle(borrowed)?;
51+
win32_hchmod(handle.as_raw_handle() as HANDLE, mode, write_bit)
52+
}
53+
54+
pub fn win32_lchmod(path: &OsStr, mode: u32, write_bit: u32) -> io::Result<()> {
55+
let wide = path.to_wide_with_nul();
56+
let attr = unsafe { GetFileAttributesW(wide.as_ptr()) };
57+
if attr == INVALID_FILE_ATTRIBUTES {
58+
return Err(io::Error::last_os_error());
59+
}
60+
let new_attr = if mode & write_bit != 0 {
61+
attr & !FILE_ATTRIBUTE_READONLY
62+
} else {
63+
attr | FILE_ATTRIBUTE_READONLY
64+
};
65+
let ret = unsafe { SetFileAttributesW(wide.as_ptr(), new_attr) };
66+
if ret == 0 {
67+
Err(io::Error::last_os_error())
68+
} else {
69+
Ok(())
70+
}
71+
}

0 commit comments

Comments
 (0)