use crate::error::{Result, SandboxError};
use std::path::Path;
pub fn is_root() -> bool {
unsafe { libc::geteuid() == 0 }
}
pub fn get_uid() -> u32 {
unsafe { libc::geteuid() }
}
pub fn get_gid() -> u32 {
unsafe { libc::getegid() }
}
pub fn require_root() -> Result<()> {
if !is_root() {
Err(SandboxError::PermissionDenied(
"This operation requires root privileges".to_string(),
))
} else {
Ok(())
}
}
pub fn has_cgroup_v2() -> bool {
Path::new("/sys/fs/cgroup/cgroup.controllers").exists()
}
pub fn cgroup_exists(path: &Path) -> bool {
path.exists()
}
pub fn parse_memory_size(s: &str) -> Result<u64> {
let s = s.trim().to_uppercase();
let (num_str, multiplier) = if s.ends_with("G") {
(&s[..s.len() - 1], 1024u64 * 1024 * 1024)
} else if s.ends_with("M") {
(&s[..s.len() - 1], 1024u64 * 1024)
} else if s.ends_with("K") {
(&s[..s.len() - 1], 1024u64)
} else if s.ends_with("B") {
(&s[..s.len() - 1], 1u64)
} else {
(s.as_str(), 1u64)
};
let num: u64 = num_str
.parse()
.map_err(|_| SandboxError::InvalidConfig(format!("Invalid memory size: {}", s)))?;
num.checked_mul(multiplier)
.ok_or_else(|| SandboxError::InvalidConfig(format!("Memory size overflow: {}", s)))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_memory_size_bytes() {
assert_eq!(parse_memory_size("100").unwrap(), 100);
assert_eq!(parse_memory_size("100B").unwrap(), 100);
}
#[test]
fn test_parse_memory_size_kilobytes() {
assert_eq!(parse_memory_size("1K").unwrap(), 1024);
assert_eq!(parse_memory_size("10K").unwrap(), 10 * 1024);
}
#[test]
fn test_parse_memory_size_megabytes() {
assert_eq!(parse_memory_size("1M").unwrap(), 1024 * 1024);
assert_eq!(parse_memory_size("100M").unwrap(), 100 * 1024 * 1024);
}
#[test]
fn test_parse_memory_size_gigabytes() {
assert_eq!(parse_memory_size("1G").unwrap(), 1024 * 1024 * 1024);
assert_eq!(parse_memory_size("2G").unwrap(), 2 * 1024 * 1024 * 1024);
}
#[test]
fn test_parse_memory_size_case_insensitive() {
assert_eq!(parse_memory_size("1m").unwrap(), 1024 * 1024);
assert_eq!(parse_memory_size("1g").unwrap(), 1024 * 1024 * 1024);
}
#[test]
fn test_parse_memory_size_whitespace() {
assert_eq!(parse_memory_size(" 100M ").unwrap(), 100 * 1024 * 1024);
}
#[test]
fn test_parse_memory_size_invalid() {
assert!(parse_memory_size("not_a_number").is_err());
assert!(parse_memory_size("10X").is_err());
}
#[test]
fn test_get_uid_gid() {
let uid = get_uid();
let gid = get_gid();
assert!(uid < u32::MAX);
assert!(gid < u32::MAX);
}
#[test]
fn test_is_root() {
let is_root_val = is_root();
assert_eq!(is_root_val, get_uid() == 0);
}
#[test]
fn test_has_cgroup_v2() {
let _ = has_cgroup_v2();
}
#[test]
fn test_cgroup_exists() {
assert!(cgroup_exists(Path::new("/")));
assert!(!cgroup_exists(Path::new(
"/nonexistent/path/that/should/not/exist"
)));
}
}