@@ -1267,13 +1267,24 @@ pub(super) mod _os {
12671267 }
12681268 }
12691269
1270- #[ pyfunction]
1271- fn link (
1270+ #[ derive( FromArgs ) ]
1271+ struct LinkArgs {
1272+ #[ pyarg( any) ]
12721273 src : OsPath ,
1274+ #[ pyarg( any) ]
12731275 dst : OsPath ,
1274- follow_symlinks : FollowSymlinks ,
1275- vm : & VirtualMachine ,
1276- ) -> PyResult < ( ) > {
1276+ #[ pyarg( named, name = "follow_symlinks" , optional) ]
1277+ follow_symlinks : OptionalArg < bool > ,
1278+ }
1279+
1280+ #[ pyfunction]
1281+ fn link ( args : LinkArgs , vm : & VirtualMachine ) -> PyResult < ( ) > {
1282+ let LinkArgs {
1283+ src,
1284+ dst,
1285+ follow_symlinks,
1286+ } = args;
1287+
12771288 #[ cfg( unix) ]
12781289 {
12791290 use std:: os:: unix:: ffi:: OsStrExt ;
@@ -1282,7 +1293,8 @@ pub(super) mod _os {
12821293 let dst_cstr = std:: ffi:: CString :: new ( dst. path . as_os_str ( ) . as_bytes ( ) )
12831294 . map_err ( |_| vm. new_value_error ( "embedded null byte" ) ) ?;
12841295
1285- let flags = if follow_symlinks. 0 {
1296+ let follow = follow_symlinks. into_option ( ) . unwrap_or ( true ) ;
1297+ let flags = if follow {
12861298 libc:: AT_SYMLINK_FOLLOW
12871299 } else {
12881300 0
@@ -1311,15 +1323,19 @@ pub(super) mod _os {
13111323
13121324 #[ cfg( not( unix) ) ]
13131325 {
1314- // On non-Unix platforms, ignore follow_symlinks if it's the default value
1315- // or raise NotImplementedError if explicitly set to False
1316- if !follow_symlinks. 0 {
1317- return Err ( vm. new_not_implemented_error (
1318- "link: follow_symlinks unavailable on this platform" ,
1319- ) ) ;
1320- }
1326+ let src_path = match follow_symlinks. into_option ( ) {
1327+ Some ( true ) => {
1328+ // Explicit follow_symlinks=True: resolve symlinks
1329+ fs:: canonicalize ( & src. path )
1330+ . unwrap_or_else ( |_| PathBuf :: from ( src. path . clone ( ) ) )
1331+ }
1332+ Some ( false ) | None => {
1333+ // Default or explicit no-follow: native hard_link behavior
1334+ PathBuf :: from ( src. path . clone ( ) )
1335+ }
1336+ } ;
13211337
1322- fs:: hard_link ( & src . path , & dst. path ) . map_err ( |err| {
1338+ fs:: hard_link ( & src_path , & dst. path ) . map_err ( |err| {
13231339 let builder = err. to_os_error_builder ( vm) ;
13241340 let builder = builder. filename ( src. filename ( vm) ) ;
13251341 let builder = builder. filename2 ( dst. filename ( vm) ) ;
0 commit comments