@@ -427,7 +427,7 @@ extern char *ctermid_r(char *);
427
427
/* Something to implement in autoconf, not present in autoconf 2.69 */
428
428
# define HAVE_STRUCT_STAT_ST_FSTYPE 1
429
429
#endif
430
-
430
+ #undef HAVE_LINKAT
431
431
432
432
// --- Apple __builtin_available() macros -----------------------------------
433
433
@@ -4323,7 +4323,7 @@ os.link
4323
4323
*
4324
4324
src_dir_fd : dir_fd = None
4325
4325
dst_dir_fd : dir_fd = None
4326
- follow_symlinks: bool = True
4326
+ follow_symlinks: bool(c_default="-1", py_default="(os.name != 'nt')") = PLACEHOLDER
4327
4327
4328
4328
Create a hard link to a file.
4329
4329
@@ -4341,25 +4341,48 @@ src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your
4341
4341
static PyObject *
4342
4342
os_link_impl (PyObject * module , path_t * src , path_t * dst , int src_dir_fd ,
4343
4343
int dst_dir_fd , int follow_symlinks )
4344
- /*[clinic end generated code: output=7f00f6007fd5269a input=b0095ebbcbaa7e04 ]*/
4344
+ /*[clinic end generated code: output=7f00f6007fd5269a input=f6a681a558380a15 ]*/
4345
4345
{
4346
4346
#ifdef MS_WINDOWS
4347
4347
BOOL result = FALSE;
4348
4348
#else
4349
4349
int result ;
4350
4350
#endif
4351
- #if defined(HAVE_LINKAT )
4352
- int linkat_unavailable = 0 ;
4353
- #endif
4354
4351
4355
- #ifndef HAVE_LINKAT
4356
- if ((src_dir_fd != DEFAULT_DIR_FD ) || (dst_dir_fd != DEFAULT_DIR_FD )) {
4357
- argument_unavailable_error ("link" , "src_dir_fd and dst_dir_fd" );
4358
- return NULL ;
4352
+ #ifdef HAVE_LINKAT
4353
+ if (HAVE_LINKAT_RUNTIME ) {
4354
+ if (follow_symlinks < 0 ) {
4355
+ follow_symlinks = 1 ;
4356
+ }
4359
4357
}
4358
+ else
4360
4359
#endif
4360
+ {
4361
+ if ((src_dir_fd != DEFAULT_DIR_FD ) || (dst_dir_fd != DEFAULT_DIR_FD )) {
4362
+ argument_unavailable_error ("link" , "src_dir_fd and dst_dir_fd" );
4363
+ return NULL ;
4364
+ }
4365
+ /* See issue 41355: link() on Linux works like linkat without AT_SYMLINK_FOLLOW,
4366
+ but on Mac it works like linkat *with* AT_SYMLINK_FOLLOW. */
4367
+ #if defined(MS_WINDOWS ) || defined(__linux__ ) || (defined(__sun ) && defined(__SVR4 ))
4368
+ if (follow_symlinks == 1 ) {
4369
+ argument_unavailable_error ("link" , "follow_symlinks=True" );
4370
+ return NULL ;
4371
+ }
4372
+ #elif defined(__APPLE__ ) || defined(__FreeBSD__ ) || defined(__NetBSD__ ) || defined(__OpenBSD__ ) || defined(__DragonFly__ )
4373
+ if (follow_symlinks == 0 ) {
4374
+ argument_unavailable_error ("link" , "follow_symlinks=False" );
4375
+ return NULL ;
4376
+ }
4377
+ #else
4378
+ if (follow_symlinks >= 0 ) {
4379
+ argument_unavailable_error ("link" , "follow_symlinks" );
4380
+ return NULL ;
4381
+ }
4382
+ #endif
4383
+ }
4361
4384
4362
- #ifndef MS_WINDOWS
4385
+ #ifdef MS_WINDOWS
4363
4386
if ((src -> narrow && dst -> wide ) || (src -> wide && dst -> narrow )) {
4364
4387
PyErr_SetString (PyExc_NotImplementedError ,
4365
4388
"link: src and dst must be the same type" );
@@ -4383,44 +4406,18 @@ os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4383
4406
#else
4384
4407
Py_BEGIN_ALLOW_THREADS
4385
4408
#ifdef HAVE_LINKAT
4386
- if ((src_dir_fd != DEFAULT_DIR_FD ) ||
4387
- (dst_dir_fd != DEFAULT_DIR_FD ) ||
4388
- (!follow_symlinks )) {
4389
-
4390
- if (HAVE_LINKAT_RUNTIME ) {
4391
-
4392
- result = linkat (src_dir_fd , src -> narrow ,
4393
- dst_dir_fd , dst -> narrow ,
4394
- follow_symlinks ? AT_SYMLINK_FOLLOW : 0 );
4395
-
4396
- }
4397
- #ifdef __APPLE__
4398
- else {
4399
- if (src_dir_fd == DEFAULT_DIR_FD && dst_dir_fd == DEFAULT_DIR_FD ) {
4400
- /* See issue 41355: This matches the behaviour of !HAVE_LINKAT */
4401
- result = link (src -> narrow , dst -> narrow );
4402
- } else {
4403
- linkat_unavailable = 1 ;
4404
- }
4405
- }
4406
- #endif
4409
+ if (HAVE_LINKAT_RUNTIME ) {
4410
+ result = linkat (src_dir_fd , src -> narrow ,
4411
+ dst_dir_fd , dst -> narrow ,
4412
+ follow_symlinks ? AT_SYMLINK_FOLLOW : 0 );
4407
4413
}
4408
4414
else
4409
- #endif /* HAVE_LINKAT */
4415
+ #endif
4416
+ {
4417
+ /* linkat not available */
4410
4418
result = link (src -> narrow , dst -> narrow );
4411
- Py_END_ALLOW_THREADS
4412
-
4413
- #ifdef HAVE_LINKAT
4414
- if (linkat_unavailable ) {
4415
- /* Either or both dir_fd arguments were specified */
4416
- if (src_dir_fd != DEFAULT_DIR_FD ) {
4417
- argument_unavailable_error ("link" , "src_dir_fd" );
4418
- } else {
4419
- argument_unavailable_error ("link" , "dst_dir_fd" );
4420
- }
4421
- return NULL ;
4422
4419
}
4423
- #endif
4420
+ Py_END_ALLOW_THREADS
4424
4421
4425
4422
if (result )
4426
4423
return path_error2 (src , dst );
0 commit comments