@@ -6,18 +6,63 @@ pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
66 sys_fill_exact ( dest, getrandom_syscall)
77}
88
9+ // The value of `EINTR` is not architecture-specific. It is checked against
10+ // `libc::EINTR` by linux_android_with_fallback.rs.
11+ pub const EINTR : i32 = 4 ;
12+
913// Also used by linux_android_with_fallback to check if the syscall is available.
10- pub fn getrandom_syscall ( buf : & mut [ MaybeUninit < u8 > ] ) -> Result < usize , Error > {
11- use crate :: util_libc:: last_os_error;
14+ cfg_if ! {
15+ // TODO: Expand inilne assembly to other architectures to avoid depending
16+ // on libc on Linux.
17+ if #[ cfg( target_arch = "x86_64" ) ] {
18+ type Word = u64 ;
19+ type IWord = i64 ;
20+
21+ #[ allow( non_upper_case_globals) ]
22+ pub const SYS_getrandom : IWord = if cfg!( target_arch = "x86_64" ) { 318 } else { unimplemented!( ) } ;
23+
24+ pub fn getrandom_syscall( buf: & mut [ MaybeUninit <u8 >] ) -> Result <usize , Error > {
25+ const _: ( ) = assert!( core:: mem:: size_of:: <Word >( ) == core:: mem:: size_of:: <usize >( ) ) ;
26+
27+ let mut ret: IWord ;
28+ let flags = 0 ;
29+ unsafe {
30+ core:: arch:: asm!(
31+ "syscall" ,
32+ inout( "rax" ) SYS_getrandom => ret,
33+ in( "rdi" ) buf. as_mut_ptr( ) ,
34+ in( "rsi" ) buf. len( ) ,
35+ in( "rdx" ) flags,
36+ lateout( "rcx" ) _,
37+ lateout( "r11" ) _,
38+ options( nostack) ,
39+ ) ;
40+ }
41+ match Word :: try_from( ret) {
42+ Ok ( written) => {
43+ const _: ( ) = assert!( core:: mem:: size_of:: <Word >( ) <= core:: mem:: size_of:: <usize >( ) ) ;
44+ Ok ( written as usize )
45+ } ,
46+ Err ( _) => {
47+ Err ( u32 :: try_from( ret. unsigned_abs( ) ) . map_or(
48+ Error :: UNEXPECTED , Error :: from_os_error) )
49+ }
50+ }
51+ }
52+ } else {
53+ use crate :: util_libc:: last_os_error;
1254
13- let ret: libc:: c_long = unsafe {
14- libc:: syscall (
15- libc:: SYS_getrandom ,
16- buf. as_mut_ptr ( ) . cast :: < core:: ffi:: c_void > ( ) ,
17- buf. len ( ) ,
18- 0 ,
19- )
20- } ;
21- const _: ( ) = assert ! ( core:: mem:: size_of:: <libc:: c_long>( ) == core:: mem:: size_of:: <isize >( ) ) ;
22- usize:: try_from ( ret as isize ) . map_err ( |_| last_os_error ( ) )
55+ pub fn getrandom_syscall( buf: & mut [ MaybeUninit <u8 >] ) -> Result <usize , Error > {
56+ let ret: libc:: c_long = unsafe {
57+ libc:: syscall(
58+ libc:: SYS_getrandom ,
59+ buf. as_mut_ptr( ) . cast:: <core:: ffi:: c_void>( ) ,
60+ buf. len( ) ,
61+ 0 ,
62+ )
63+ } ;
64+ const _: ( ) = assert!( core:: mem:: size_of:: <libc:: c_long>( ) == core:: mem:: size_of:: <isize >( ) ) ;
65+ usize :: try_from( ret as isize ) . map_err( |_| last_os_error( ) )
66+ }
67+ }
2368}
0 commit comments