From 2af5f082ce8f41a7b857d93987e86e834642d46d Mon Sep 17 00:00:00 2001 From: Andrew Liebenow Date: Mon, 9 Sep 2024 07:47:56 -0500 Subject: [PATCH] Make changes needed to build on musl --- plib/src/lib.rs | 2 ++ plib/src/libc_aliases.rs | 10 ++++++++ plib/src/libc_aliases/musl.rs | 22 ++++++++++++++++++ plib/src/utmpx.rs | 5 +++- process/renice.rs | 43 ++++++++++++++++++++++++++++------- sys/ipcrm.rs | 9 ++++++++ sys/ipcs.rs | 42 ++++++++++++++++++++++++++++++---- sys/who.rs | 28 +++++++++++++++-------- tree/ls.rs | 19 ++++++++++++---- users/write.rs | 12 ++++++---- 10 files changed, 159 insertions(+), 33 deletions(-) create mode 100644 plib/src/libc_aliases.rs create mode 100644 plib/src/libc_aliases/musl.rs diff --git a/plib/src/lib.rs b/plib/src/lib.rs index beab1774..c6e9429e 100644 --- a/plib/src/lib.rs +++ b/plib/src/lib.rs @@ -10,6 +10,8 @@ pub mod curuser; pub mod group; pub mod io; +// TODO: Remove "libc_aliases" when https://github.com/rust-lang/libc/issues/3190 is resolved +pub mod libc_aliases; pub mod lzw; pub mod modestr; pub mod sccsfile; diff --git a/plib/src/libc_aliases.rs b/plib/src/libc_aliases.rs new file mode 100644 index 00000000..ebecfd3f --- /dev/null +++ b/plib/src/libc_aliases.rs @@ -0,0 +1,10 @@ +#[cfg(target_env = "musl")] +pub mod musl; +#[cfg(target_env = "musl")] +pub use musl::*; + +#[cfg(not(target_env = "musl"))] +pub use libc::{ + endutxent, getutxent, setutxent, BOOT_TIME, DEAD_PROCESS, EMPTY, INIT_PROCESS, LOGIN_PROCESS, + NEW_TIME, OLD_TIME, RUN_LVL, USER_PROCESS, +}; diff --git a/plib/src/libc_aliases/musl.rs b/plib/src/libc_aliases/musl.rs new file mode 100644 index 00000000..185fe3ab --- /dev/null +++ b/plib/src/libc_aliases/musl.rs @@ -0,0 +1,22 @@ +use libc::{c_short, utmpx}; + +// https://git.musl-libc.org/cgit/musl/tree/include/utmpx.h?id=1e7f0fcd7ff2096904fd93a2ee6d12a2392be392 +pub const EMPTY: c_short = 0_i16; +pub const RUN_LVL: c_short = 1_i16; +pub const BOOT_TIME: c_short = 2_i16; +pub const NEW_TIME: c_short = 3_i16; +pub const OLD_TIME: c_short = 4_i16; +pub const INIT_PROCESS: c_short = 5_i16; +pub const LOGIN_PROCESS: c_short = 6_i16; +pub const USER_PROCESS: c_short = 7_i16; +pub const DEAD_PROCESS: c_short = 8_i16; + +// https://github.com/rust-lang/libc/commit/e3caaf6b0ea08ae294e25a861022c256a7535ec4#diff-5822a2981791fb0bb7689a921abdc2133cc73116ee125eabefad3a9374056b7a +extern "C" { + pub fn getutxent() -> *mut utmpx; + pub fn getutxid(ut: *const utmpx) -> *mut utmpx; + pub fn getutxline(ut: *const utmpx) -> *mut utmpx; + pub fn pututxline(ut: *const utmpx) -> *mut utmpx; + pub fn setutxent(); + pub fn endutxent(); +} diff --git a/plib/src/utmpx.rs b/plib/src/utmpx.rs index 42922dd5..79892893 100644 --- a/plib/src/utmpx.rs +++ b/plib/src/utmpx.rs @@ -8,7 +8,8 @@ // extern crate libc; -use libc::{endutxent, getutxent, setutxent}; +// TODO: Remove "libc_aliases" when https://github.com/rust-lang/libc/issues/3190 is resolved +use crate::libc_aliases::{endutxent, getutxent, setutxent}; use std::ffi::CStr; #[derive(Debug)] @@ -23,6 +24,8 @@ pub struct Utmpx { } pub fn ut_type_str(typ: libc::c_short) -> &'static str { + // TODO: Remove "libc_aliases" when https://github.com/rust-lang/libc/issues/3190 is resolved + use crate::libc_aliases as libc; match typ { libc::BOOT_TIME => "BOOT_TIME", libc::DEAD_PROCESS => "DEAD_PROCESS", diff --git a/process/renice.rs b/process/renice.rs index 4100aa43..871b5bd3 100644 --- a/process/renice.rs +++ b/process/renice.rs @@ -82,11 +82,24 @@ fn parse_id(which: u32, input: &str) -> Result { fn xgetpriority(which: u32, id: u32) -> io::Result { set_errno(errno::Errno(0)); - #[cfg(not(target_os = "macos"))] - let res = unsafe { libc::getpriority(which, id) }; + // Prevent accidental shadowing by using a block + let which_cast = { + #[cfg(all(not(target_os = "macos"), not(target_env = "musl")))] + { + which + } + + #[cfg(all(not(target_os = "macos"), target_env = "musl"))] + { + which as i32 + } - #[cfg(target_os = "macos")] - let res = unsafe { libc::getpriority(which as i32, id) }; + #[cfg(target_os = "macos")] + { + which as i32 + } + }; + let res = unsafe { libc::getpriority(which_cast, id) }; let errno_res = errno().0; if errno_res == 0 { @@ -99,11 +112,25 @@ fn xgetpriority(which: u32, id: u32) -> io::Result { } fn xsetpriority(which: u32, id: u32, prio: i32) -> io::Result<()> { - #[cfg(not(target_os = "macos"))] - let res = unsafe { libc::setpriority(which, id, prio) }; + // Prevent accidental shadowing by using a block + let which_cast = { + #[cfg(all(not(target_os = "macos"), not(target_env = "musl")))] + { + which + } + + #[cfg(all(not(target_os = "macos"), target_env = "musl"))] + { + which as i32 + } + + #[cfg(target_os = "macos")] + { + which as i32 + } + }; - #[cfg(target_os = "macos")] - let res = unsafe { libc::setpriority(which as i32, id, prio) }; + let res = unsafe { libc::setpriority(which_cast, id, prio) }; if res < 0 { let e = io::Error::last_os_error(); diff --git a/sys/ipcrm.rs b/sys/ipcrm.rs index 13b7d287..ef4e3a21 100644 --- a/sys/ipcrm.rs +++ b/sys/ipcrm.rs @@ -126,6 +126,7 @@ fn sem_key_lookup(semkey: i32) -> io::Result { } // Define the union semun as per your requirements +#[cfg(not(target_env = "musl"))] #[repr(C)] union semun { val: c_int, // for SETVAL @@ -134,6 +135,7 @@ union semun { // Depending on your platform, you might need to add other fields as well } +#[cfg(not(target_env = "musl"))] fn sem_rm(semid: i32) -> io::Result { let arg = semun { val: 0 }; @@ -146,6 +148,7 @@ fn sem_rm(semid: i32) -> io::Result { } } +#[cfg(not(target_env = "musl"))] fn remove_ipcs(args: &Args) -> io::Result<()> { // remove semaphores if let Some(semkey) = args.semkey { @@ -180,6 +183,12 @@ fn remove_ipcs(args: &Args) -> io::Result<()> { Ok(()) } +#[cfg(target_env = "musl")] +fn remove_ipcs(_args: &Args) -> io::Result<()> { + // TODO + unimplemented!(); +} + fn main() -> Result<(), Box> { // parse command line arguments let args = Args::parse(); diff --git a/sys/ipcs.rs b/sys/ipcs.rs index de0645f3..3309b47d 100644 --- a/sys/ipcs.rs +++ b/sys/ipcs.rs @@ -90,7 +90,18 @@ fn display_message_queues(_args: &Args) { break; } - let key = msg_ds.msg_perm.__key; // Ensure the correct field name for your system + let key = { + #[cfg(not(target_env = "musl"))] + { + msg_ds.msg_perm.__key // Ensure the correct field name for your system + } + + // TODO: What placeholder value should go here? + #[cfg(target_env = "musl")] + { + 0_i32 + } + }; let mode = msg_ds.msg_perm.mode; let uid = msg_ds.msg_perm.uid; let gid = msg_ds.msg_perm.gid; @@ -154,10 +165,24 @@ fn display_shared_memory(_args: &Args) { continue; } - #[cfg(target_os = "macos")] - let key = shmbuf.shm_perm._key; // Check for the correct field name on your system - #[cfg(not(target_os = "macos"))] - let key = shmbuf.shm_perm.__key; // Check for the correct field name on your system + // Prevent accidental shadowing by using a block + let key = { + #[cfg(target_os = "macos")] + { + shmbuf.shm_perm._key // Check for the correct field name on your system + } + + #[cfg(all(not(target_os = "macos"), not(target_env = "musl")))] + { + shmbuf.shm_perm.__key // Check for the correct field name on your system + } + + // TODO: What placeholder value should go here? + #[cfg(all(not(target_os = "macos"), target_env = "musl"))] + { + 0_i32 + } + }; let mode = shmbuf.shm_perm.mode; let uid = shmbuf.shm_perm.uid; let gid = shmbuf.shm_perm.gid; @@ -187,6 +212,7 @@ fn display_shared_memory(_args: &Args) { } } +#[cfg(not(target_env = "musl"))] fn display_semaphores(_args: &Args) { use libc::{semctl, semid_ds, IPC_STAT}; use std::ffi::CStr; @@ -238,6 +264,12 @@ fn display_semaphores(_args: &Args) { } } +#[cfg(target_env = "musl")] +fn display_semaphores(_args: &Args) { + // TODO + unimplemented!(); +} + fn get_current_date() -> String { // Retrieve the current date and time in a human-readable format let now = Local::now(); diff --git a/sys/who.rs b/sys/who.rs index ed69d6c9..ff267c7e 100644 --- a/sys/who.rs +++ b/sys/who.rs @@ -129,23 +129,31 @@ fn print_entry(args: &Args, entry: &plib::utmpx::Utmpx) { } let mut selected = false; - if (args.boot && entry.typ == libc::BOOT_TIME) - || (args.userproc && entry.typ == libc::USER_PROCESS) - || (args.dead && entry.typ == libc::DEAD_PROCESS) - || (args.login && entry.typ == libc::LOGIN_PROCESS) - || (args.runlevel && entry.typ == libc::RUN_LVL) - || (args.process && entry.typ == libc::INIT_PROCESS) { - selected = true; + // TODO: Remove "libc_aliases" when https://github.com/rust-lang/libc/issues/3190 is resolved + use plib::libc_aliases as libc; + if (args.boot && entry.typ == libc::BOOT_TIME) + || (args.userproc && entry.typ == libc::USER_PROCESS) + || (args.dead && entry.typ == libc::DEAD_PROCESS) + || (args.login && entry.typ == libc::LOGIN_PROCESS) + || (args.runlevel && entry.typ == libc::RUN_LVL) + || (args.process && entry.typ == libc::INIT_PROCESS) + { + selected = true; + } } if !selected { return; } - let line = match entry.typ { - libc::BOOT_TIME => "system boot", - _ => entry.line.as_str(), + let line = { + // TODO: Remove "libc_aliases" when https://github.com/rust-lang/libc/issues/3190 is resolved + use plib::libc_aliases as libc; + match entry.typ { + libc::BOOT_TIME => "system boot", + _ => entry.line.as_str(), + } }; if args.short_format { diff --git a/tree/ls.rs b/tree/ls.rs index f09ec41b..a8e2c09f 100644 --- a/tree/ls.rs +++ b/tree/ls.rs @@ -582,11 +582,20 @@ fn get_terminal_width() -> usize { // Fallback to manually querying via `ioctl`. unsafe { let mut winsize: MaybeUninit = MaybeUninit::zeroed(); - let ret = libc::ioctl( - libc::STDOUT_FILENO, - winsize_request_code(), - winsize.as_mut_ptr(), - ); + let request_cast = { + let request = winsize_request_code(); + + #[cfg(target_env = "musl")] + { + request as i32 + } + + #[cfg(not(target_env = "musl"))] + { + request + } + }; + let ret = libc::ioctl(libc::STDOUT_FILENO, request_cast, winsize.as_mut_ptr()); // We're only interested in stdout here unlike `term_size::dimensions` // so we won't query further if the first `ioctl` call fails. diff --git a/users/write.rs b/users/write.rs index 17d81b1c..c421a41b 100644 --- a/users/write.rs +++ b/users/write.rs @@ -44,10 +44,14 @@ fn select_terminal(user_name: &str) -> String { let entries = plib::utmpx::load(); // Filter the entries to find terminals for the specified user - let user_entries: Vec<_> = entries - .into_iter() - .filter(|entry| entry.user == user_name && entry.typ == libc::USER_PROCESS) - .collect(); + let user_entries: Vec<_> = { + // TODO: Remove "libc_aliases" when https://github.com/rust-lang/libc/issues/3190 is resolved + use plib::libc_aliases as libc; + entries + .into_iter() + .filter(|entry| entry.user == user_name && entry.typ == libc::USER_PROCESS) + .collect() + }; if user_entries.is_empty() { eprintln!("{}: {}", gettext("No terminals found for user"), user_name);