c_scape/process/
system.rs

1use crate::convert_res;
2use core::ptr::{addr_of_mut, copy_nonoverlapping};
3use core::slice;
4use errno::{set_errno, Errno};
5use libc::{c_char, c_double, c_int, c_long};
6use memoffset::span_of;
7
8#[no_mangle]
9unsafe extern "C" fn uname(buf: *mut libc::utsname) -> c_int {
10    libc!(libc::uname(buf));
11
12    let uname = rustix::system::uname();
13
14    let sysname = uname.sysname().to_bytes_with_nul();
15    assert!(sysname.len() <= span_of!(libc::utsname, sysname).len());
16    copy_nonoverlapping(
17        sysname.as_ptr(),
18        addr_of_mut!((*buf).sysname).cast::<u8>(),
19        sysname.len(),
20    );
21
22    let nodename = uname.nodename().to_bytes_with_nul();
23    assert!(nodename.len() <= span_of!(libc::utsname, nodename).len());
24    copy_nonoverlapping(
25        nodename.as_ptr(),
26        addr_of_mut!((*buf).nodename).cast::<u8>(),
27        nodename.len(),
28    );
29
30    let release = uname.release().to_bytes_with_nul();
31    assert!(release.len() <= span_of!(libc::utsname, release).len());
32    copy_nonoverlapping(
33        release.as_ptr(),
34        addr_of_mut!((*buf).release).cast::<u8>(),
35        release.len(),
36    );
37
38    let version = uname.version().to_bytes_with_nul();
39    assert!(version.len() <= span_of!(libc::utsname, version).len());
40    copy_nonoverlapping(
41        version.as_ptr(),
42        addr_of_mut!((*buf).version).cast::<u8>(),
43        version.len(),
44    );
45
46    let machine = uname.machine().to_bytes_with_nul();
47    assert!(machine.len() <= span_of!(libc::utsname, machine).len());
48    copy_nonoverlapping(
49        machine.as_ptr(),
50        addr_of_mut!((*buf).machine).cast::<u8>(),
51        machine.len(),
52    );
53
54    let domainname = uname.domainname().to_bytes_with_nul();
55    assert!(domainname.len() <= span_of!(libc::utsname, domainname).len());
56    copy_nonoverlapping(
57        domainname.as_ptr(),
58        addr_of_mut!((*buf).domainname).cast::<u8>(),
59        domainname.len(),
60    );
61
62    0
63}
64
65#[no_mangle]
66unsafe extern "C" fn getloadavg(a: *mut c_double, n: c_int) -> c_int {
67    libc!(libc::getloadavg(a, n));
68
69    if n == 0 {
70        return 0;
71    }
72    if n < 0 {
73        return -1;
74    }
75
76    let info = rustix::system::sysinfo();
77    let mut a = a;
78
79    for i in 0..core::cmp::min(n as usize, info.loads.len()) {
80        a.write((info.loads[i] as f64) / ((1 << libc::SI_LOAD_SHIFT) as f64));
81        a = a.add(1);
82    }
83
84    n
85}
86
87#[cfg(not(target_os = "wasi"))]
88#[no_mangle]
89unsafe extern "C" fn gethostname(name: *mut c_char, len: usize) -> c_int {
90    libc!(libc::gethostname(name, len));
91
92    let uname = rustix::system::uname();
93    let nodename = uname.nodename();
94    if nodename.to_bytes().len() + 1 > len {
95        set_errno(Errno(libc::ENAMETOOLONG));
96        return -1;
97    }
98    copy_nonoverlapping(
99        nodename.to_bytes().as_ptr().cast::<u8>(),
100        name.cast::<u8>(),
101        nodename.to_bytes().len(),
102    );
103    *name.add(nodename.to_bytes().len()) = 0;
104    0
105}
106
107#[cfg(not(target_os = "wasi"))]
108#[no_mangle]
109unsafe extern "C" fn sethostname(name: *mut c_char, len: usize) -> c_int {
110    libc!(libc::sethostname(name, len));
111
112    let slice = slice::from_raw_parts(name.cast(), len);
113    match convert_res(rustix::system::sethostname(slice)) {
114        Some(()) => 0,
115        None => -1,
116    }
117}
118
119#[deprecated]
120#[no_mangle]
121unsafe extern "C" fn gethostid() -> c_long {
122    libc!(libc::gethostid());
123
124    // 32 bits isn't enough to uniquely identify a "host".
125    0
126}
127
128#[cfg(not(target_env = "musl"))]
129#[deprecated]
130#[no_mangle]
131unsafe extern "C" fn sethostid(id: c_long) -> c_int {
132    libc!(libc::sethostid(id));
133
134    if id == 0 {
135        0
136    } else {
137        set_errno(Errno(libc::EACCES));
138        -1
139    }
140}