@@ -22,8 +22,8 @@ pub use self::tasks::*;
22
22
pub use self :: timer:: * ;
23
23
use crate :: executor:: block_on;
24
24
use crate :: fd:: {
25
- self , AccessPermission , EventFlags , FileDescriptor , OpenOption , PollFd , dup_object ,
26
- dup_object2, get_object, isatty, remove_object,
25
+ self , AccessOption , AccessPermission , EventFlags , FileDescriptor , OpenOption , PollFd ,
26
+ dup_object , dup_object2, get_object, isatty, remove_object,
27
27
} ;
28
28
use crate :: fs:: { self , FileAttr , SeekWhence } ;
29
29
#[ cfg( all( target_os = "none" , not( feature = "common-os" ) ) ) ]
@@ -390,6 +390,84 @@ pub unsafe extern "C" fn sys_umask(umask: u32) -> u32 {
390
390
391
391
#[ hermit_macro:: system( errno) ]
392
392
#[ unsafe( no_mangle) ]
393
+ pub unsafe extern "C" fn sys_faccessat (
394
+ dirfd : FileDescriptor ,
395
+ name : * const c_char ,
396
+ _mode : i32 ,
397
+ flags : i32 ,
398
+ ) -> i32 {
399
+ let access_option = AccessOption :: from_bits_truncate ( flags) ;
400
+ if access_option. bits ( ) != flags {
401
+ return -crate :: errno:: EINVAL ;
402
+ }
403
+
404
+ let Ok ( name) = unsafe { CStr :: from_ptr ( name) } . to_str ( ) else {
405
+ return -crate :: errno:: EINVAL ;
406
+ } ;
407
+
408
+ const AT_SYMLINK_NOFOLLOW : i32 = 0x100 ;
409
+ const AT_FDCWD : i32 = -100 ;
410
+
411
+ let stat = if name. starts_with ( "/" ) || dirfd == AT_FDCWD {
412
+ let no_follow: bool = ( flags & AT_SYMLINK_NOFOLLOW ) != 0 ;
413
+
414
+ if no_follow {
415
+ crate :: fs:: read_stat ( name)
416
+ } else {
417
+ crate :: fs:: read_lstat ( name)
418
+ }
419
+ } else {
420
+ warn ! ( "faccessat with directory relative to fd is not implemented!" ) ;
421
+ return -crate :: errno:: ENOSYS ;
422
+ } ;
423
+
424
+ if let Err ( e) = stat {
425
+ return -i32:: from ( e) ;
426
+ }
427
+
428
+ let Ok ( stat) = stat else { unreachable ! ( ) } ;
429
+ if access_option. can_access ( stat. st_mode ) {
430
+ 0
431
+ } else {
432
+ -crate :: errno:: EACCES
433
+ }
434
+ }
435
+
436
+ #[ hermit_macro:: system]
437
+ #[ unsafe( no_mangle) ]
438
+ pub unsafe extern "C" fn sys_access ( name : * const c_char , flags : i32 ) -> i32 {
439
+ // This is an implementation of libc's access, not of linux's faccessat
440
+ // See https://linux.die.net/man/2/faccessat for differences
441
+
442
+ let access_option = AccessOption :: from_bits_truncate ( flags) ;
443
+ if access_option. bits ( ) != flags {
444
+ return -crate :: errno:: EINVAL ;
445
+ }
446
+
447
+ if access_option. contains ( AccessOption :: F_OK ) && access_option != AccessOption :: F_OK {
448
+ return -crate :: errno:: EINVAL ;
449
+ }
450
+
451
+ let Ok ( name) = unsafe { CStr :: from_ptr ( name) } . to_str ( ) else {
452
+ return -crate :: errno:: EINVAL ;
453
+ } ;
454
+ let stat = crate :: fs:: read_lstat ( name) ;
455
+
456
+ if let Err ( e) = stat {
457
+ return -i32:: from ( e) ;
458
+ }
459
+
460
+ let Ok ( stat) = stat else { unreachable ! ( ) } ;
461
+
462
+ if access_option. can_access ( stat. st_mode ) {
463
+ 0
464
+ } else {
465
+ -crate :: errno:: EACCES
466
+ }
467
+ }
468
+
469
+ #[ hermit_macro:: system]
470
+ #[ unsafe( no_mangle) ]
393
471
pub extern "C" fn sys_close ( fd : FileDescriptor ) -> i32 {
394
472
let obj = remove_object ( fd) ;
395
473
obj. map_or_else ( |e| -i32:: from ( e) , |_| 0 )
0 commit comments