1use linux_syscall::{Result as _, syscall};
2use num_enum::{IntoPrimitive, TryFromPrimitive};
3use shadow_pod::Pod;
4
5use crate::{
6    bindings,
7    errno::Errno,
8    posix_types::{Pid, kernel_pid_t},
9};
10
11#[allow(non_camel_case_types)]
12pub type rusage = crate::bindings::linux_rusage;
13unsafe impl Pod for rusage {}
14
15#[allow(non_camel_case_types)]
16pub type rlimit = crate::bindings::linux_rlimit;
17unsafe impl Pod for rlimit {}
18
19#[allow(non_camel_case_types)]
20pub type rlimit64 = crate::bindings::linux_rlimit64;
21unsafe impl Pod for rlimit64 {}
22
23pub const RLIM64_INFINITY: u64 = bindings::LINUX_RLIM64_INFINITY as u64;
26const _: () = assert!(RLIM64_INFINITY == !0);
27
28pub const RLIM_INFINITY: u64 = bindings::LINUX_RLIM_INFINITY as u64;
31const _: () = assert!(RLIM_INFINITY == !0);
32
33pub const RLIM_NLIMITS: u32 = crate::bindings::LINUX_RLIM_NLIMITS;
34
35#[derive(Debug, Copy, Clone, Eq, PartialEq, IntoPrimitive, TryFromPrimitive)]
37#[repr(u32)]
38#[allow(non_camel_case_types)]
39pub enum Resource {
40    RLIMIT_CPU = bindings::LINUX_RLIMIT_CPU,
41    RLIMIT_FSIZE = bindings::LINUX_RLIMIT_FSIZE,
42    RLIMIT_DATA = bindings::LINUX_RLIMIT_DATA,
43    RLIMIT_STACK = bindings::LINUX_RLIMIT_STACK,
44    RLIMIT_CORE = bindings::LINUX_RLIMIT_CORE,
45    RLIMIT_RSS = bindings::LINUX_RLIMIT_RSS,
46    RLIMIT_NPROC = bindings::LINUX_RLIMIT_NPROC,
47    RLIMIT_NOFILE = bindings::LINUX_RLIMIT_NOFILE,
48    RLIMIT_MEMLOCK = bindings::LINUX_RLIMIT_MEMLOCK,
49    RLIMIT_AS = bindings::LINUX_RLIMIT_AS,
50    RLIMIT_LOCKS = bindings::LINUX_RLIMIT_LOCKS,
51    RLIMIT_SIGPENDING = bindings::LINUX_RLIMIT_SIGPENDING,
52    RLIMIT_MSGQUEUE = bindings::LINUX_RLIMIT_MSGQUEUE,
53    RLIMIT_NICE = bindings::LINUX_RLIMIT_NICE,
54    RLIMIT_RTPRIO = bindings::LINUX_RLIMIT_RTPRIO,
55    RLIMIT_RTTIME = bindings::LINUX_RLIMIT_RTTIME,
56}
57
58pub unsafe fn prlimit64_raw(
73    pid: kernel_pid_t,
74    resource: core::ffi::c_uint,
75    new_rlim: *const rlimit64,
76    old_rlim: *mut rlimit64,
77) -> Result<(), Errno> {
78    unsafe {
79        syscall!(
80            linux_syscall::SYS_prlimit64,
81            pid,
82            resource,
83            new_rlim,
84            old_rlim
85        )
86    }
87    .check()
88    .map_err(Errno::from)
89}
90
91pub unsafe fn prlimit64(
102    pid: Pid,
103    resource: Resource,
104    new_rlim: Option<&rlimit64>,
105    old_rlim: Option<&mut rlimit64>,
106) -> Result<(), Errno> {
107    let pid = kernel_pid_t::from(pid.as_raw_nonzero());
108    let resource = core::ffi::c_uint::from(resource);
109    let new_rlim = match new_rlim {
110        Some(x) => core::ptr::from_ref(x),
111        None => core::ptr::null(),
112    };
113    let old_rlim = match old_rlim {
114        Some(x) => core::ptr::from_mut(x),
115        None => core::ptr::null_mut(),
116    };
117    unsafe { prlimit64_raw(pid, resource, new_rlim, old_rlim) }
118}