Skip to content

Commit 25d77a1

Browse files
committed
mkdir
1 parent 4d63af8 commit 25d77a1

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
@@ -692,18 +692,59 @@ pub(crate) mod module {
692692
raw_set_handle_inheritable(handle, inheritable).map_err(|e| e.to_pyexception(vm))
693693
}
694694

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

0 commit comments

Comments
 (0)