Skip to content

Commit 673b584

Browse files
committed
vm::windows
1 parent 7d276da commit 673b584

File tree

6 files changed

+115
-116
lines changed

6 files changed

+115
-116
lines changed

stdlib/src/select.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::{io, mem};
66

77
pub(crate) fn make_module(vm: &VirtualMachine) -> PyRef<PyModule> {
88
#[cfg(windows)]
9-
crate::vm::stdlib::nt::init_winsock();
9+
crate::vm::windows::init_winsock();
1010

1111
#[cfg(unix)]
1212
{

stdlib/src/socket.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ pub(super) use _socket::{sock_select, timeout_error_msg, PySocket, SelectKind};
44

55
pub fn make_module(vm: &VirtualMachine) -> PyRef<PyModule> {
66
#[cfg(windows)]
7-
crate::vm::stdlib::nt::init_winsock();
7+
crate::vm::windows::init_winsock();
88
_socket::make_module(vm)
99
}
1010

vm/src/stdlib/nt.rs

Lines changed: 0 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -420,114 +420,3 @@ pub(crate) mod module {
420420
Vec::new()
421421
}
422422
}
423-
424-
pub fn init_winsock() {
425-
static WSA_INIT: parking_lot::Once = parking_lot::Once::new();
426-
WSA_INIT.call_once(|| unsafe {
427-
let mut wsa_data = std::mem::MaybeUninit::uninit();
428-
let _ = windows_sys::Win32::Networking::WinSock::WSAStartup(0x0101, wsa_data.as_mut_ptr());
429-
})
430-
}
431-
432-
// win32_xstat in cpython
433-
pub fn win32_xstat(path: &OsStr, traverse: bool) -> std::io::Result<StatStruct> {
434-
let mut result = match win32_xstat_impl(path, traverse) {
435-
Ok(r) => r,
436-
Err(e) => {
437-
// TODO: cpython comments say GetLastError must be called here.
438-
return Err(e);
439-
}
440-
};
441-
// ctime is only deprecated from 3.12, so we copy birthtime across
442-
result.st_ctime = result.st_birthtime;
443-
result.st_ctime_nsec = result.st_birthtime_nsec;
444-
return Ok(result);
445-
}
446-
447-
fn is_reparse_tag_name_surrogate(tag: u32) -> bool {
448-
(tag & 0x20000000) > 0
449-
}
450-
451-
use crate::common::fileutils::StatStruct;
452-
use std::{ffi::OsStr, time::SystemTime};
453-
454-
fn win32_xstat_impl(path: &OsStr, traverse: bool) -> std::io::Result<StatStruct> {
455-
use crate::common::fileutils::windows::{
456-
get_file_information_by_name, FILE_INFO_BY_NAME_CLASS,
457-
};
458-
use windows_sys::Win32::{Foundation, Storage::FileSystem::FILE_ATTRIBUTE_REPARSE_POINT};
459-
460-
let stat_info =
461-
get_file_information_by_name(&path, FILE_INFO_BY_NAME_CLASS::FileStatBasicByNameInfo);
462-
match stat_info {
463-
Ok(stat_info) => {
464-
if !(stat_info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT != 0)
465-
|| (!traverse && is_reparse_tag_name_surrogate(stat_info.ReparseTag))
466-
{
467-
let mut result =
468-
crate::common::fileutils::windows::stat_basic_info_to_stat(&stat_info);
469-
result.update_st_mode_from_path(&path, stat_info.FileAttributes);
470-
return Ok(result);
471-
}
472-
}
473-
Err(e) => {
474-
if let Some(errno) = e.raw_os_error() {
475-
if matches!(
476-
errno as u32,
477-
Foundation::ERROR_FILE_NOT_FOUND
478-
| Foundation::ERROR_PATH_NOT_FOUND
479-
| Foundation::ERROR_NOT_READY
480-
| Foundation::ERROR_BAD_NET_NAME
481-
) {
482-
return Err(e);
483-
}
484-
}
485-
}
486-
}
487-
488-
// TODO: win32_xstat_slow_impl(&path, result, traverse)
489-
meta_to_stat(&crate::stdlib::os::fs_metadata(path, traverse)?)
490-
}
491-
492-
fn meta_to_stat(meta: &std::fs::Metadata) -> std::io::Result<StatStruct> {
493-
let st_mode = {
494-
// Based on CPython fileutils.c' attributes_to_mode
495-
let mut m = 0;
496-
if meta.is_dir() {
497-
m |= libc::S_IFDIR | 0o111; /* IFEXEC for user,group,other */
498-
} else {
499-
m |= libc::S_IFREG;
500-
}
501-
if meta.permissions().readonly() {
502-
m |= 0o444;
503-
} else {
504-
m |= 0o666;
505-
}
506-
m as _
507-
};
508-
let (atime, mtime, ctime) = (meta.accessed()?, meta.modified()?, meta.created()?);
509-
let sec = |systime: SystemTime| match systime.duration_since(SystemTime::UNIX_EPOCH) {
510-
Ok(d) => d.as_secs() as libc::time_t,
511-
Err(e) => -(e.duration().as_secs() as libc::time_t),
512-
};
513-
let nsec = |systime: SystemTime| match systime.duration_since(SystemTime::UNIX_EPOCH) {
514-
Ok(d) => d.subsec_nanos() as i32,
515-
Err(e) => -(e.duration().subsec_nanos() as i32),
516-
};
517-
Ok(StatStruct {
518-
st_dev: 0,
519-
st_ino: 0,
520-
st_mode,
521-
st_nlink: 0,
522-
st_uid: 0,
523-
st_gid: 0,
524-
st_size: meta.len(),
525-
st_atime: sec(atime),
526-
st_mtime: sec(mtime),
527-
st_ctime: sec(ctime),
528-
st_atime_nsec: nsec(atime),
529-
st_mtime_nsec: nsec(mtime),
530-
st_ctime_nsec: nsec(ctime),
531-
..Default::default()
532-
})
533-
}

vm/src/stdlib/os.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::{
77
};
88
use std::{ffi, fs, io, path::Path};
99

10-
pub(super) fn fs_metadata<P: AsRef<Path>>(
10+
pub(crate) fn fs_metadata<P: AsRef<Path>>(
1111
path: P,
1212
follow_symlink: bool,
1313
) -> io::Result<fs::Metadata> {
@@ -821,7 +821,7 @@ pub(super) mod _os {
821821
// TODO: replicate CPython's win32_xstat
822822
let [] = dir_fd.0;
823823
match file {
824-
OsPathOrFd::Path(path) => crate::stdlib::nt::win32_xstat(&path.path, follow_symlinks.0),
824+
OsPathOrFd::Path(path) => crate::windows::win32_xstat(&path.path, follow_symlinks.0),
825825
OsPathOrFd::Fd(fd) => crate::common::fileutils::fstat(fd),
826826
}
827827
.map(Some)

vm/src/stdlib/signal.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ pub(crate) mod _signal {
201201
let is_socket = if fd != INVALID_WAKEUP {
202202
use windows_sys::Win32::Networking::WinSock;
203203

204-
crate::stdlib::nt::init_winsock();
204+
crate::windows::init_winsock();
205205
let mut res = 0i32;
206206
let mut res_size = std::mem::size_of::<i32>() as i32;
207207
let res = unsafe {

vm/src/windows.rs

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1+
use crate::common::fileutils::{
2+
StatStruct,
3+
windows::{get_file_information_by_name, FILE_INFO_BY_NAME_CLASS},
4+
};
15
use crate::{
26
convert::{ToPyObject, ToPyResult},
37
stdlib::os::errno_err,
48
PyObjectRef, PyResult, TryFromObject, VirtualMachine,
59
};
10+
use std::{ffi::OsStr, time::SystemTime};
611
use windows::Win32::Foundation::HANDLE;
712
use windows_sys::Win32::Foundation::{BOOL, HANDLE as RAW_HANDLE, INVALID_HANDLE_VALUE};
813

@@ -66,3 +71,108 @@ impl ToPyObject for HANDLE {
6671
(self.0 as HandleInt).to_pyobject(vm)
6772
}
6873
}
74+
75+
pub fn init_winsock() {
76+
static WSA_INIT: parking_lot::Once = parking_lot::Once::new();
77+
WSA_INIT.call_once(|| unsafe {
78+
let mut wsa_data = std::mem::MaybeUninit::uninit();
79+
let _ = windows_sys::Win32::Networking::WinSock::WSAStartup(0x0101, wsa_data.as_mut_ptr());
80+
})
81+
}
82+
83+
// win32_xstat in cpython
84+
pub fn win32_xstat(path: &OsStr, traverse: bool) -> std::io::Result<StatStruct> {
85+
let mut result = match win32_xstat_impl(path, traverse) {
86+
Ok(r) => r,
87+
Err(e) => {
88+
// TODO: cpython comments say GetLastError must be called here.
89+
return Err(e);
90+
}
91+
};
92+
// ctime is only deprecated from 3.12, so we copy birthtime across
93+
result.st_ctime = result.st_birthtime;
94+
result.st_ctime_nsec = result.st_birthtime_nsec;
95+
Ok(result)
96+
}
97+
98+
fn is_reparse_tag_name_surrogate(tag: u32) -> bool {
99+
(tag & 0x20000000) > 0
100+
}
101+
102+
fn win32_xstat_impl(path: &OsStr, traverse: bool) -> std::io::Result<StatStruct> {
103+
use windows_sys::Win32::{Foundation, Storage::FileSystem::FILE_ATTRIBUTE_REPARSE_POINT};
104+
105+
let stat_info =
106+
get_file_information_by_name(path, FILE_INFO_BY_NAME_CLASS::FileStatBasicByNameInfo);
107+
match stat_info {
108+
Ok(stat_info) => {
109+
if (stat_info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT == 0)
110+
|| (!traverse && is_reparse_tag_name_surrogate(stat_info.ReparseTag))
111+
{
112+
let mut result =
113+
crate::common::fileutils::windows::stat_basic_info_to_stat(&stat_info);
114+
result.update_st_mode_from_path(path, stat_info.FileAttributes);
115+
return Ok(result);
116+
}
117+
}
118+
Err(e) => {
119+
if let Some(errno) = e.raw_os_error() {
120+
if matches!(
121+
errno as u32,
122+
Foundation::ERROR_FILE_NOT_FOUND
123+
| Foundation::ERROR_PATH_NOT_FOUND
124+
| Foundation::ERROR_NOT_READY
125+
| Foundation::ERROR_BAD_NET_NAME
126+
) {
127+
return Err(e);
128+
}
129+
}
130+
}
131+
}
132+
133+
// TODO: replace it with win32_xstat_slow_impl(&path, result, traverse)
134+
meta_to_stat(&crate::stdlib::os::fs_metadata(path, traverse)?)
135+
}
136+
137+
fn meta_to_stat(meta: &std::fs::Metadata) -> std::io::Result<StatStruct> {
138+
let st_mode = {
139+
// Based on CPython fileutils.c' attributes_to_mode
140+
let mut m = 0;
141+
if meta.is_dir() {
142+
m |= libc::S_IFDIR | 0o111; /* IFEXEC for user,group,other */
143+
} else {
144+
m |= libc::S_IFREG;
145+
}
146+
if meta.permissions().readonly() {
147+
m |= 0o444;
148+
} else {
149+
m |= 0o666;
150+
}
151+
m as _
152+
};
153+
let (atime, mtime, ctime) = (meta.accessed()?, meta.modified()?, meta.created()?);
154+
let sec = |systime: SystemTime| match systime.duration_since(SystemTime::UNIX_EPOCH) {
155+
Ok(d) => d.as_secs() as libc::time_t,
156+
Err(e) => -(e.duration().as_secs() as libc::time_t),
157+
};
158+
let nsec = |systime: SystemTime| match systime.duration_since(SystemTime::UNIX_EPOCH) {
159+
Ok(d) => d.subsec_nanos() as i32,
160+
Err(e) => -(e.duration().subsec_nanos() as i32),
161+
};
162+
Ok(StatStruct {
163+
st_dev: 0,
164+
st_ino: 0,
165+
st_mode,
166+
st_nlink: 0,
167+
st_uid: 0,
168+
st_gid: 0,
169+
st_size: meta.len(),
170+
st_atime: sec(atime),
171+
st_mtime: sec(mtime),
172+
st_birthtime: sec(ctime),
173+
st_atime_nsec: nsec(atime),
174+
st_mtime_nsec: nsec(mtime),
175+
st_birthtime_nsec: nsec(ctime),
176+
..Default::default()
177+
})
178+
}

0 commit comments

Comments
 (0)