(args: LinkArgs, vm: &VirtualMachine)
| 1645 | |
| 1646 | #[pyfunction] |
| 1647 | fn link(args: LinkArgs, vm: &VirtualMachine) -> PyResult<()> { |
| 1648 | let LinkArgs { |
| 1649 | src, |
| 1650 | dst, |
| 1651 | follow_symlinks, |
| 1652 | } = args; |
| 1653 | |
| 1654 | #[cfg(unix)] |
| 1655 | { |
| 1656 | use std::os::unix::ffi::OsStrExt; |
| 1657 | let src_cstr = alloc::ffi::CString::new(src.path.as_os_str().as_bytes()) |
| 1658 | .map_err(|_| vm.new_value_error("embedded null byte"))?; |
| 1659 | let dst_cstr = alloc::ffi::CString::new(dst.path.as_os_str().as_bytes()) |
| 1660 | .map_err(|_| vm.new_value_error("embedded null byte"))?; |
| 1661 | |
| 1662 | let follow = follow_symlinks.into_option().unwrap_or(true); |
| 1663 | let flags = if follow { libc::AT_SYMLINK_FOLLOW } else { 0 }; |
| 1664 | |
| 1665 | let ret = unsafe { |
| 1666 | libc::linkat( |
| 1667 | libc::AT_FDCWD, |
| 1668 | src_cstr.as_ptr(), |
| 1669 | libc::AT_FDCWD, |
| 1670 | dst_cstr.as_ptr(), |
| 1671 | flags, |
| 1672 | ) |
| 1673 | }; |
| 1674 | |
| 1675 | if ret != 0 { |
| 1676 | let err = std::io::Error::last_os_error(); |
| 1677 | let builder = err.to_os_error_builder(vm); |
| 1678 | let builder = builder.filename(src.filename(vm)); |
| 1679 | let builder = builder.filename2(dst.filename(vm)); |
| 1680 | return Err(builder.build(vm).upcast()); |
| 1681 | } |
| 1682 | |
| 1683 | Ok(()) |
| 1684 | } |
| 1685 | |
| 1686 | #[cfg(not(unix))] |
| 1687 | { |
| 1688 | let src_path = match follow_symlinks.into_option() { |
| 1689 | Some(true) => { |
| 1690 | // Explicit follow_symlinks=True: resolve symlinks |
| 1691 | fs::canonicalize(&src.path).unwrap_or_else(|_| PathBuf::from(src.path.clone())) |
| 1692 | } |
| 1693 | Some(false) | None => { |
| 1694 | // Default or explicit no-follow: native hard_link behavior |
| 1695 | PathBuf::from(src.path.clone()) |
| 1696 | } |
| 1697 | }; |
| 1698 | |
| 1699 | fs::hard_link(&src_path, &dst.path).map_err(|err| { |
| 1700 | let builder = err.to_os_error_builder(vm); |
| 1701 | let builder = builder.filename(src.filename(vm)); |
| 1702 | let builder = builder.filename2(dst.filename(vm)); |
| 1703 | builder.build(vm).upcast() |
| 1704 | }) |
nothing calls this directly
no test coverage detected