MCPcopy Index your code
hub / github.com/RustPython/RustPython / symlink

Function symlink

crates/vm/src/stdlib/nt.rs:149–222  ·  view source on GitHub ↗
(args: SymlinkArgs<'_>, vm: &VirtualMachine)

Source from the content-addressed store, hash-verified

147
148 #[pyfunction]
149 pub(super) fn symlink(args: SymlinkArgs<'_>, vm: &VirtualMachine) -> PyResult<()> {
150 use crate::exceptions::ToOSErrorBuilder;
151 use core::sync::atomic::{AtomicBool, Ordering};
152 use windows_sys::Win32::Storage::FileSystem::WIN32_FILE_ATTRIBUTE_DATA;
153 use windows_sys::Win32::Storage::FileSystem::{
154 CreateSymbolicLinkW, FILE_ATTRIBUTE_DIRECTORY, GetFileAttributesExW,
155 SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE, SYMBOLIC_LINK_FLAG_DIRECTORY,
156 };
157
158 static HAS_UNPRIVILEGED_FLAG: AtomicBool = AtomicBool::new(true);
159
160 fn check_dir(src: &OsPath, dst: &OsPath) -> bool {
161 use windows_sys::Win32::Storage::FileSystem::GetFileExInfoStandard;
162
163 let dst_parent = dst.as_path().parent();
164 let Some(dst_parent) = dst_parent else {
165 return false;
166 };
167 let resolved = if src.as_path().is_absolute() {
168 src.as_path().to_path_buf()
169 } else {
170 dst_parent.join(src.as_path())
171 };
172 let wide = match widestring::WideCString::from_os_str(&resolved) {
173 Ok(wide) => wide,
174 Err(_) => return false,
175 };
176 let mut info: WIN32_FILE_ATTRIBUTE_DATA = unsafe { core::mem::zeroed() };
177 let ok = unsafe {
178 GetFileAttributesExW(
179 wide.as_ptr(),
180 GetFileExInfoStandard,
181 &mut info as *mut _ as *mut _,
182 )
183 };
184 ok != 0 && (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0
185 }
186
187 let mut flags = 0u32;
188 if HAS_UNPRIVILEGED_FLAG.load(Ordering::Relaxed) {
189 flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
190 }
191 if args.target_is_directory.target_is_directory || check_dir(&args.src, &args.dst) {
192 flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
193 }
194
195 let src = args.src.to_wide_cstring(vm)?;
196 let dst = args.dst.to_wide_cstring(vm)?;
197
198 let mut result = unsafe { CreateSymbolicLinkW(dst.as_ptr(), src.as_ptr(), flags) };
199 if !result
200 && HAS_UNPRIVILEGED_FLAG.load(Ordering::Relaxed)
201 && unsafe { Foundation::GetLastError() } == Foundation::ERROR_INVALID_PARAMETER
202 {
203 let flags = flags & !SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
204 result = unsafe { CreateSymbolicLinkW(dst.as_ptr(), src.as_ptr(), flags) };
205 if result
206 || unsafe { Foundation::GetLastError() } != Foundation::ERROR_INVALID_PARAMETER

Callers 1

test_symlink_keywordsMethod · 0.50

Calls 13

newFunction · 0.85
check_dirFunction · 0.85
to_os_error_builderMethod · 0.80
filename2Method · 0.80
upcastMethod · 0.80
GetLastErrorFunction · 0.70
ErrClass · 0.50
loadMethod · 0.45
to_wide_cstringMethod · 0.45
as_ptrMethod · 0.45
storeMethod · 0.45
filenameMethod · 0.45

Tested by 1

test_symlink_keywordsMethod · 0.40