@@ -251,6 +251,42 @@ pub(crate) fn linkat(
251251 new_path : & CStr ,
252252 flags : AtFlags ,
253253) -> 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" ) ) ]
254290 unsafe {
255291 ret ( c:: linkat (
256292 borrowed_fd ( old_dirfd) ,
@@ -264,7 +300,38 @@ pub(crate) fn linkat(
264300
265301#[ cfg( not( target_os = "redox" ) ) ]
266302pub ( 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+ }
268335}
269336
270337#[ cfg( not( target_os = "redox" ) ) ]
@@ -274,6 +341,34 @@ pub(crate) fn renameat(
274341 new_dirfd : BorrowedFd < ' _ > ,
275342 new_path : & CStr ,
276343) -> 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" ) ) ]
277372 unsafe {
278373 ret ( c:: renameat (
279374 borrowed_fd ( old_dirfd) ,
@@ -405,6 +500,40 @@ pub(crate) fn accessat(
405500 access : Access ,
406501 flags : AtFlags ,
407502) -> 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" ) ) ]
408537 unsafe {
409538 ret ( c:: faccessat (
410539 borrowed_fd ( dirfd) ,
0 commit comments