@@ -573,7 +573,11 @@ extern char *ctermid_r(char *);
573
573
# define HAVE_FACCESSAT_RUNTIME 1
574
574
# define HAVE_FCHMODAT_RUNTIME 1
575
575
# define HAVE_FCHOWNAT_RUNTIME 1
576
+ #ifdef __wasi__
577
+ # define HAVE_LINKAT_RUNTIME 0
578
+ # else
576
579
# define HAVE_LINKAT_RUNTIME 1
580
+ # endif
577
581
# define HAVE_FDOPENDIR_RUNTIME 1
578
582
# define HAVE_MKDIRAT_RUNTIME 1
579
583
# define HAVE_RENAMEAT_RUNTIME 1
@@ -4346,7 +4350,7 @@ os.link
4346
4350
*
4347
4351
src_dir_fd : dir_fd = None
4348
4352
dst_dir_fd : dir_fd = None
4349
- follow_symlinks: bool = True
4353
+ follow_symlinks: bool(c_default="-1", py_default="(os.name != 'nt')") = PLACEHOLDER
4350
4354
4351
4355
Create a hard link to a file.
4352
4356
@@ -4364,31 +4368,46 @@ src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your
4364
4368
static PyObject *
4365
4369
os_link_impl (PyObject * module , path_t * src , path_t * dst , int src_dir_fd ,
4366
4370
int dst_dir_fd , int follow_symlinks )
4367
- /*[clinic end generated code: output=7f00f6007fd5269a input=b0095ebbcbaa7e04 ]*/
4371
+ /*[clinic end generated code: output=7f00f6007fd5269a input=1d5e602d115fed7b ]*/
4368
4372
{
4369
4373
#ifdef MS_WINDOWS
4370
4374
BOOL result = FALSE;
4371
4375
#else
4372
4376
int result ;
4373
4377
#endif
4374
- #if defined(HAVE_LINKAT )
4375
- int linkat_unavailable = 0 ;
4376
- #endif
4377
4378
4378
- #ifndef HAVE_LINKAT
4379
- if ((src_dir_fd != DEFAULT_DIR_FD ) || (dst_dir_fd != DEFAULT_DIR_FD )) {
4380
- argument_unavailable_error ("link" , "src_dir_fd and dst_dir_fd" );
4381
- return NULL ;
4379
+ #ifdef HAVE_LINKAT
4380
+ if (HAVE_LINKAT_RUNTIME ) {
4381
+ if (follow_symlinks < 0 ) {
4382
+ follow_symlinks = 1 ;
4383
+ }
4382
4384
}
4385
+ else
4383
4386
#endif
4384
-
4385
- #ifndef MS_WINDOWS
4386
- if ((src -> narrow && dst -> wide ) || (src -> wide && dst -> narrow )) {
4387
- PyErr_SetString (PyExc_NotImplementedError ,
4388
- "link: src and dst must be the same type" );
4389
- return NULL ;
4390
- }
4387
+ {
4388
+ if ((src_dir_fd != DEFAULT_DIR_FD ) || (dst_dir_fd != DEFAULT_DIR_FD )) {
4389
+ argument_unavailable_error ("link" , "src_dir_fd and dst_dir_fd" );
4390
+ return NULL ;
4391
+ }
4392
+ /* See issue 85527: link() on Linux works like linkat without AT_SYMLINK_FOLLOW,
4393
+ but on Mac it works like linkat *with* AT_SYMLINK_FOLLOW. */
4394
+ #if defined(MS_WINDOWS ) || defined(__linux__ )
4395
+ if (follow_symlinks == 1 ) {
4396
+ argument_unavailable_error ("link" , "follow_symlinks=True" );
4397
+ return NULL ;
4398
+ }
4399
+ #elif defined(__APPLE__ ) || defined(__FreeBSD__ ) || defined(__NetBSD__ ) || defined(__OpenBSD__ ) || defined(__DragonFly__ ) || (defined(__sun ) && defined(__SVR4 ))
4400
+ if (follow_symlinks == 0 ) {
4401
+ argument_unavailable_error ("link" , "follow_symlinks=False" );
4402
+ return NULL ;
4403
+ }
4404
+ #else
4405
+ if (follow_symlinks >= 0 ) {
4406
+ argument_unavailable_error ("link" , "follow_symlinks" );
4407
+ return NULL ;
4408
+ }
4391
4409
#endif
4410
+ }
4392
4411
4393
4412
if (PySys_Audit ("os.link" , "OOii" , src -> object , dst -> object ,
4394
4413
src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd ,
@@ -4406,44 +4425,18 @@ os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4406
4425
#else
4407
4426
Py_BEGIN_ALLOW_THREADS
4408
4427
#ifdef HAVE_LINKAT
4409
- if ((src_dir_fd != DEFAULT_DIR_FD ) ||
4410
- (dst_dir_fd != DEFAULT_DIR_FD ) ||
4411
- (!follow_symlinks )) {
4412
-
4413
- if (HAVE_LINKAT_RUNTIME ) {
4414
-
4415
- result = linkat (src_dir_fd , src -> narrow ,
4416
- dst_dir_fd , dst -> narrow ,
4417
- follow_symlinks ? AT_SYMLINK_FOLLOW : 0 );
4418
-
4419
- }
4420
- #ifdef __APPLE__
4421
- else {
4422
- if (src_dir_fd == DEFAULT_DIR_FD && dst_dir_fd == DEFAULT_DIR_FD ) {
4423
- /* See issue 41355: This matches the behaviour of !HAVE_LINKAT */
4424
- result = link (src -> narrow , dst -> narrow );
4425
- } else {
4426
- linkat_unavailable = 1 ;
4427
- }
4428
- }
4429
- #endif
4428
+ if (HAVE_LINKAT_RUNTIME ) {
4429
+ result = linkat (src_dir_fd , src -> narrow ,
4430
+ dst_dir_fd , dst -> narrow ,
4431
+ follow_symlinks ? AT_SYMLINK_FOLLOW : 0 );
4430
4432
}
4431
4433
else
4432
- #endif /* HAVE_LINKAT */
4434
+ #endif
4435
+ {
4436
+ /* linkat not available */
4433
4437
result = link (src -> narrow , dst -> narrow );
4434
- Py_END_ALLOW_THREADS
4435
-
4436
- #ifdef HAVE_LINKAT
4437
- if (linkat_unavailable ) {
4438
- /* Either or both dir_fd arguments were specified */
4439
- if (src_dir_fd != DEFAULT_DIR_FD ) {
4440
- argument_unavailable_error ("link" , "src_dir_fd" );
4441
- } else {
4442
- argument_unavailable_error ("link" , "dst_dir_fd" );
4443
- }
4444
- return NULL ;
4445
4438
}
4446
- #endif
4439
+ Py_END_ALLOW_THREADS
4447
4440
4448
4441
if (result )
4449
4442
return path_error2 (src , dst );
@@ -5935,12 +5928,6 @@ internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is
5935
5928
return path_error2 (src , dst );
5936
5929
5937
5930
#else
5938
- if ((src -> narrow && dst -> wide ) || (src -> wide && dst -> narrow )) {
5939
- PyErr_Format (PyExc_ValueError ,
5940
- "%s: src and dst must be the same type" , function_name );
5941
- return NULL ;
5942
- }
5943
-
5944
5931
Py_BEGIN_ALLOW_THREADS
5945
5932
#ifdef HAVE_RENAMEAT
5946
5933
if (dir_fd_specified ) {
@@ -10613,12 +10600,6 @@ os_symlink_impl(PyObject *module, path_t *src, path_t *dst,
10613
10600
10614
10601
#else
10615
10602
10616
- if ((src -> narrow && dst -> wide ) || (src -> wide && dst -> narrow )) {
10617
- PyErr_SetString (PyExc_ValueError ,
10618
- "symlink: src and dst must be the same type" );
10619
- return NULL ;
10620
- }
10621
-
10622
10603
Py_BEGIN_ALLOW_THREADS
10623
10604
#ifdef HAVE_SYMLINKAT
10624
10605
if (dir_fd != DEFAULT_DIR_FD ) {
0 commit comments