(
path: OsPath,
dir_fd: DirFd<'static, 0>,
vm: &VirtualMachine,
)
| 76 | #[pyfunction] |
| 77 | #[pyfunction(name = "unlink")] |
| 78 | pub(super) fn remove( |
| 79 | path: OsPath, |
| 80 | dir_fd: DirFd<'static, 0>, |
| 81 | vm: &VirtualMachine, |
| 82 | ) -> PyResult<()> { |
| 83 | // On Windows, use DeleteFileW directly. |
| 84 | // Rust's std::fs::remove_file may have different behavior for read-only files. |
| 85 | // See Py_DeleteFileW. |
| 86 | use windows_sys::Win32::Storage::FileSystem::{ |
| 87 | DeleteFileW, FindClose, FindFirstFileW, RemoveDirectoryW, WIN32_FIND_DATAW, |
| 88 | }; |
| 89 | use windows_sys::Win32::System::SystemServices::{ |
| 90 | IO_REPARSE_TAG_MOUNT_POINT, IO_REPARSE_TAG_SYMLINK, |
| 91 | }; |
| 92 | |
| 93 | let [] = dir_fd.0; |
| 94 | let wide_path = path.to_wide_cstring(vm)?; |
| 95 | let attrs = unsafe { FileSystem::GetFileAttributesW(wide_path.as_ptr()) }; |
| 96 | |
| 97 | let mut is_directory = false; |
| 98 | let mut is_link = false; |
| 99 | |
| 100 | if attrs != FileSystem::INVALID_FILE_ATTRIBUTES { |
| 101 | is_directory = (attrs & FileSystem::FILE_ATTRIBUTE_DIRECTORY) != 0; |
| 102 | |
| 103 | // Check if it's a symlink or junction point |
| 104 | if is_directory && (attrs & FileSystem::FILE_ATTRIBUTE_REPARSE_POINT) != 0 { |
| 105 | let mut find_data: WIN32_FIND_DATAW = unsafe { core::mem::zeroed() }; |
| 106 | let handle = unsafe { FindFirstFileW(wide_path.as_ptr(), &mut find_data) }; |
| 107 | if handle != INVALID_HANDLE_VALUE { |
| 108 | is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK |
| 109 | || find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT; |
| 110 | unsafe { FindClose(handle) }; |
| 111 | } |
| 112 | } |
| 113 | } |
| 114 | |
| 115 | let result = if is_directory && is_link { |
| 116 | unsafe { RemoveDirectoryW(wide_path.as_ptr()) } |
| 117 | } else { |
| 118 | unsafe { DeleteFileW(wide_path.as_ptr()) } |
| 119 | }; |
| 120 | |
| 121 | if result == 0 { |
| 122 | let err = io::Error::last_os_error(); |
| 123 | return Err(OSErrorBuilder::with_filename(&err, path, vm)); |
| 124 | } |
| 125 | Ok(()) |
| 126 | } |
| 127 | |
| 128 | #[pyfunction] |
| 129 | pub(super) fn _supports_virtual_terminal() -> PyResult<bool> { |
nothing calls this directly
no test coverage detected