@@ -251,6 +251,42 @@ pub(crate) fn linkat(
251
251
new_path : & CStr ,
252
252
flags : AtFlags ,
253
253
) -> io:: Result < ( ) > {
254
+ // macOS <= 10.9 lacks `linkat`.
255
+ #[ cfg( target_os = "macos" ) ]
256
+ unsafe {
257
+ weak ! {
258
+ fn linkat(
259
+ c:: c_int,
260
+ * const c:: c_char,
261
+ c:: c_int,
262
+ * const c:: c_char,
263
+ c:: c_int
264
+ ) -> c:: c_int
265
+ }
266
+ // If we have `linkat`, use it.
267
+ if let Some ( libc_linkat) = linkat. get ( ) {
268
+ return ret ( libc_linkat (
269
+ borrowed_fd ( old_dirfd) ,
270
+ c_str ( old_path) ,
271
+ borrowed_fd ( new_dirfd) ,
272
+ c_str ( new_path) ,
273
+ flags. bits ( ) ,
274
+ ) ) ;
275
+ }
276
+ // Otherwise, see if we can emulate the `AT_FDCWD` case.
277
+ if borrowed_fd ( old_dirfd) != c:: AT_FDCWD || borrowed_fd ( new_dirfd) != c:: AT_FDCWD {
278
+ return Err ( io:: Errno :: NOSYS ) ;
279
+ }
280
+ if flags. intersects ( !AtFlags :: SYMLINK_FOLLOW ) {
281
+ return Err ( io:: Errno :: INVAL ) ;
282
+ }
283
+ if !flags. is_empty ( ) {
284
+ return Err ( io:: Errno :: OPNOTSUPP ) ;
285
+ }
286
+ ret ( c:: link ( c_str ( old_path) , c_str ( new_path) ) )
287
+ }
288
+
289
+ #[ cfg( not( target_os = "macos" ) ) ]
254
290
unsafe {
255
291
ret ( c:: linkat (
256
292
borrowed_fd ( old_dirfd) ,
@@ -264,7 +300,38 @@ pub(crate) fn linkat(
264
300
265
301
#[ cfg( not( target_os = "redox" ) ) ]
266
302
pub ( crate ) fn unlinkat ( dirfd : BorrowedFd < ' _ > , path : & CStr , flags : AtFlags ) -> io:: Result < ( ) > {
267
- unsafe { ret ( c:: unlinkat ( borrowed_fd ( dirfd) , c_str ( path) , flags. bits ( ) ) ) }
303
+ // macOS <= 10.9 lacks `unlinkat`.
304
+ #[ cfg( target_os = "macos" ) ]
305
+ unsafe {
306
+ weak ! {
307
+ fn unlinkat(
308
+ c:: c_int,
309
+ * const c:: c_char,
310
+ c:: c_int
311
+ ) -> c:: c_int
312
+ }
313
+ // If we have `unlinkat`, use it.
314
+ if let Some ( libc_unlinkat) = unlinkat. get ( ) {
315
+ return ret ( libc_unlinkat ( borrowed_fd ( dirfd) , c_str ( path) , flags. bits ( ) ) ) ;
316
+ }
317
+ // Otherwise, see if we can emulate the `AT_FDCWD` case.
318
+ if borrowed_fd ( dirfd) != c:: AT_FDCWD {
319
+ return Err ( io:: Errno :: NOSYS ) ;
320
+ }
321
+ if flags. intersects ( !AtFlags :: REMOVEDIR ) {
322
+ return Err ( io:: Errno :: INVAL ) ;
323
+ }
324
+ if flags. contains ( AtFlags :: REMOVEDIR ) {
325
+ ret ( c:: rmdir ( c_str ( path) ) )
326
+ } else {
327
+ ret ( c:: unlink ( c_str ( path) ) )
328
+ }
329
+ }
330
+
331
+ #[ cfg( not( target_os = "macos" ) ) ]
332
+ unsafe {
333
+ ret ( c:: unlinkat ( borrowed_fd ( dirfd) , c_str ( path) , flags. bits ( ) ) )
334
+ }
268
335
}
269
336
270
337
#[ cfg( not( target_os = "redox" ) ) ]
@@ -274,6 +341,34 @@ pub(crate) fn renameat(
274
341
new_dirfd : BorrowedFd < ' _ > ,
275
342
new_path : & CStr ,
276
343
) -> io:: Result < ( ) > {
344
+ // macOS <= 10.9 lacks `renameat`.
345
+ #[ cfg( target_os = "macos" ) ]
346
+ unsafe {
347
+ weak ! {
348
+ fn renameat(
349
+ c:: c_int,
350
+ * const c:: c_char,
351
+ c:: c_int,
352
+ * const c:: c_char
353
+ ) -> c:: c_int
354
+ }
355
+ // If we have `renameat`, use it.
356
+ if let Some ( libc_renameat) = renameat. get ( ) {
357
+ return ret ( libc_renameat (
358
+ borrowed_fd ( old_dirfd) ,
359
+ c_str ( old_path) ,
360
+ borrowed_fd ( new_dirfd) ,
361
+ c_str ( new_path) ,
362
+ ) ) ;
363
+ }
364
+ // Otherwise, see if we can emulate the `AT_FDCWD` case.
365
+ if borrowed_fd ( old_dirfd) != c:: AT_FDCWD || borrowed_fd ( new_dirfd) != c:: AT_FDCWD {
366
+ return Err ( io:: Errno :: NOSYS ) ;
367
+ }
368
+ ret ( c:: rename ( c_str ( old_path) , c_str ( new_path) ) )
369
+ }
370
+
371
+ #[ cfg( not( target_os = "macos" ) ) ]
277
372
unsafe {
278
373
ret ( c:: renameat (
279
374
borrowed_fd ( old_dirfd) ,
@@ -405,6 +500,40 @@ pub(crate) fn accessat(
405
500
access : Access ,
406
501
flags : AtFlags ,
407
502
) -> io:: Result < ( ) > {
503
+ // macOS <= 10.9 lacks `faccessat`.
504
+ #[ cfg( target_os = "macos" ) ]
505
+ unsafe {
506
+ weak ! {
507
+ fn faccessat(
508
+ c:: c_int,
509
+ * const c:: c_char,
510
+ c:: c_int,
511
+ c:: c_int
512
+ ) -> c:: c_int
513
+ }
514
+ // If we have `faccessat`, use it.
515
+ if let Some ( libc_faccessat) = faccessat. get ( ) {
516
+ return ret ( libc_faccessat (
517
+ borrowed_fd ( dirfd) ,
518
+ c_str ( path) ,
519
+ access. bits ( ) ,
520
+ flags. bits ( ) ,
521
+ ) ) ;
522
+ }
523
+ // Otherwise, see if we can emulate the `AT_FDCWD` case.
524
+ if borrowed_fd ( dirfd) != c:: AT_FDCWD {
525
+ return Err ( io:: Errno :: NOSYS ) ;
526
+ }
527
+ if flags. intersects ( !( AtFlags :: EACCESS | AtFlags :: SYMLINK_NOFOLLOW ) ) {
528
+ return Err ( io:: Errno :: INVAL ) ;
529
+ }
530
+ if !flags. is_empty ( ) {
531
+ return Err ( io:: Errno :: OPNOTSUPP ) ;
532
+ }
533
+ ret ( c:: access ( c_str ( path) , access. bits ( ) ) )
534
+ }
535
+
536
+ #[ cfg( not( target_os = "macos" ) ) ]
408
537
unsafe {
409
538
ret ( c:: faccessat (
410
539
borrowed_fd ( dirfd) ,
0 commit comments