Skip to content

Commit 436843a

Browse files
committed
mkdir
1 parent 8f50134 commit 436843a

File tree

2 files changed

+53
-11
lines changed

2 files changed

+53
-11
lines changed

crates/vm/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ features = [
129129
"Win32_Globalization",
130130
"Win32_Networking_WinSock",
131131
"Win32_Security",
132+
"Win32_Security_Authorization",
132133
"Win32_Storage_FileSystem",
133134
"Win32_System_Console",
134135
"Win32_System_Diagnostics_Debug",

crates/vm/src/stdlib/nt.rs

Lines changed: 52 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -685,18 +685,59 @@ pub(crate) mod module {
685685
raw_set_handle_inheritable(handle, inheritable).map_err(|e| e.to_pyexception(vm))
686686
}
687687

688-
#[pyfunction]
689-
fn mkdir(
688+
#[derive(FromArgs)]
689+
struct MkdirArgs<'a> {
690+
#[pyarg(any)]
690691
path: OsPath,
691-
mode: OptionalArg<i32>,
692-
dir_fd: DirFd<'_, { _os::MKDIR_DIR_FD as usize }>,
693-
vm: &VirtualMachine,
694-
) -> PyResult<()> {
695-
let mode = mode.unwrap_or(0o777);
696-
let [] = dir_fd.0;
697-
let _ = mode;
698-
let wide = path.to_wide_cstring(vm)?;
699-
let res = unsafe { FileSystem::CreateDirectoryW(wide.as_ptr(), std::ptr::null_mut()) };
692+
#[pyarg(any, default = 0o777)]
693+
mode: i32,
694+
#[pyarg(flatten)]
695+
dir_fd: DirFd<'a, { _os::MKDIR_DIR_FD as usize }>,
696+
}
697+
698+
#[pyfunction]
699+
fn mkdir(args: MkdirArgs<'_>, vm: &VirtualMachine) -> PyResult<()> {
700+
use windows_sys::Win32::Foundation::LocalFree;
701+
use windows_sys::Win32::Security::Authorization::{
702+
ConvertStringSecurityDescriptorToSecurityDescriptorW, SDDL_REVISION_1,
703+
};
704+
use windows_sys::Win32::Security::SECURITY_ATTRIBUTES;
705+
706+
let [] = args.dir_fd.0;
707+
let wide = args.path.to_wide_cstring(vm)?;
708+
709+
// CPython special case: mode 0o700 sets a protected ACL
710+
let res = if args.mode == 0o700 {
711+
let mut sec_attr = SECURITY_ATTRIBUTES {
712+
nLength: std::mem::size_of::<SECURITY_ATTRIBUTES>() as u32,
713+
lpSecurityDescriptor: std::ptr::null_mut(),
714+
bInheritHandle: 0,
715+
};
716+
// Set a discretionary ACL (D) that is protected (P) and includes
717+
// inheritable (OICI) entries that allow (A) full control (FA) to
718+
// SYSTEM (SY), Administrators (BA), and the owner (OW).
719+
let sddl: Vec<u16> = "D:P(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;FA;;;OW)\0"
720+
.encode_utf16()
721+
.collect();
722+
let convert_result = unsafe {
723+
ConvertStringSecurityDescriptorToSecurityDescriptorW(
724+
sddl.as_ptr(),
725+
SDDL_REVISION_1,
726+
&mut sec_attr.lpSecurityDescriptor,
727+
std::ptr::null_mut(),
728+
)
729+
};
730+
if convert_result == 0 {
731+
return Err(errno_err(vm));
732+
}
733+
let res =
734+
unsafe { FileSystem::CreateDirectoryW(wide.as_ptr(), &sec_attr as *const _ as _) };
735+
unsafe { LocalFree(sec_attr.lpSecurityDescriptor) };
736+
res
737+
} else {
738+
unsafe { FileSystem::CreateDirectoryW(wide.as_ptr(), std::ptr::null_mut()) }
739+
};
740+
700741
if res == 0 {
701742
return Err(errno_err(vm));
702743
}

0 commit comments

Comments
 (0)