diff --git a/Cargo.toml b/Cargo.toml index e508b0b62..be3ae529c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -131,6 +131,7 @@ feat_common_core = [ "unexpand", "uniq", "unlink", + "uptime", "vdir", "wc", "yes", @@ -209,7 +210,7 @@ feat_require_unix = [ ] # "feat_require_unix_utmpx" == set of utilities requiring unix utmp/utmpx support # * ref: -feat_require_unix_utmpx = ["pinky", "uptime", "users", "who"] +feat_require_unix_utmpx = ["pinky", "users", "who"] # "feat_require_unix_hostid" == set of utilities requiring gethostid in libc (only some unixes provide) feat_require_unix_hostid = ["hostid"] # "feat_require_selinux" == set of utilities depending on SELinux. diff --git a/src/uu/uptime/src/uptime.rs b/src/uu/uptime/src/uptime.rs index 6e028fbd6..af409b164 100644 --- a/src/uu/uptime/src/uptime.rs +++ b/src/uu/uptime/src/uptime.rs @@ -6,7 +6,6 @@ // spell-checker:ignore getloadavg behaviour loadavg uptime upsecs updays upmins uphours boottime nusers utmpxname gettime clockid couldnt use chrono::{Local, TimeZone, Utc}; -#[cfg(unix)] use std::ffi::OsString; use std::io; use thiserror::Error; @@ -15,13 +14,13 @@ use uucore::libc::time_t; use uucore::translate; use uucore::uptime::*; -use clap::{Arg, ArgAction, Command, ValueHint, builder::ValueParser}; +use clap::{Arg, ArgAction, Command}; use uucore::LocalizedCommand; use uucore::format_usage; #[cfg(unix)] -#[cfg(not(target_os = "openbsd"))] +#[cfg(not(any(target_os = "openbsd", target_os = "redox", target_os = "android")))] use uucore::utmpx::*; pub mod options { @@ -83,15 +82,26 @@ pub fn uu_app() -> Command { .help(translate!("uptime-help-since")) .action(ArgAction::SetTrue), ); + #[cfg(unix)] - cmd.arg( - Arg::new(options::PATH) - .help(translate!("uptime-help-path")) - .action(ArgAction::Set) - .num_args(0..=1) - .value_parser(ValueParser::os_string()) - .value_hint(ValueHint::AnyPath), - ) + let cmd = { + use clap::{ValueHint, builder::ValueParser}; + cmd.arg( + Arg::new(options::PATH) + .help(translate!("uptime-help-path")) + .action(ArgAction::Set) + .num_args(0..=1) + .value_parser(ValueParser::os_string()) + .value_hint(ValueHint::AnyPath), + ) + }; + + cmd +} + +#[cfg(windows)] +fn uptime_with_file(_: &OsString) -> UResult<()> { + unreachable!("The function should never be called on Windows") } #[cfg(unix)] @@ -153,7 +163,7 @@ fn uptime_with_file(file_path: &OsString) -> UResult<()> { print_time(); let user_count; - #[cfg(not(target_os = "openbsd"))] + #[cfg(not(any(target_os = "openbsd", target_os = "redox", target_os = "android")))] { let (boot_time, count) = process_utmpx(Some(file_path)); if let Some(time) = boot_time { @@ -167,7 +177,7 @@ fn uptime_with_file(file_path: &OsString) -> UResult<()> { user_count = count; } - #[cfg(target_os = "openbsd")] + #[cfg(any(target_os = "openbsd", target_os = "redox", target_os = "android"))] { let upsecs = get_uptime(None); if upsecs >= 0 { @@ -189,12 +199,17 @@ fn uptime_with_file(file_path: &OsString) -> UResult<()> { fn uptime_since() -> UResult<()> { #[cfg(unix)] - #[cfg(not(target_os = "openbsd"))] + #[cfg(not(any(target_os = "openbsd", target_os = "redox", target_os = "android")))] let uptime = { let (boot_time, _) = process_utmpx(None); get_uptime(boot_time)? }; - #[cfg(any(windows, target_os = "openbsd"))] + #[cfg(any( + windows, + target_os = "openbsd", + target_os = "redox", + target_os = "android" + ))] let uptime = get_uptime(None)?; let since_date = Local @@ -224,7 +239,7 @@ fn print_loadavg() { } #[cfg(unix)] -#[cfg(not(target_os = "openbsd"))] +#[cfg(not(any(target_os = "openbsd", target_os = "redox", target_os = "android")))] fn process_utmpx(file: Option<&OsString>) -> (Option, usize) { let mut nusers = 0; let mut boot_time = None; diff --git a/src/uucore/src/lib/features/uptime.rs b/src/uucore/src/lib/features/uptime.rs index 38991a923..2b479b392 100644 --- a/src/uucore/src/lib/features/uptime.rs +++ b/src/uucore/src/lib/features/uptime.rs @@ -79,6 +79,12 @@ pub fn get_uptime(_boot_time: Option) -> UResult { } } +// TODO implement functionality +#[cfg(any(target_os = "android", target_os = "redox"))] +pub fn get_uptime(_boot_time: Option) -> UResult { + Err(UptimeError::SystemUptime)? +} + /// Get the system uptime /// /// # Arguments @@ -89,7 +95,7 @@ pub fn get_uptime(_boot_time: Option) -> UResult { /// /// Returns a UResult with the uptime in seconds if successful, otherwise an UptimeError. #[cfg(unix)] -#[cfg(not(target_os = "openbsd"))] +#[cfg(not(any(target_os = "openbsd", target_os = "android", target_os = "redox")))] pub fn get_uptime(boot_time: Option) -> UResult { use crate::utmpx::Utmpx; use libc::BOOT_TIME; @@ -189,7 +195,7 @@ pub fn get_formatted_uptime(boot_time: Option) -> UResult { /// /// Returns the number of users currently logged in if successful, otherwise 0. #[cfg(unix)] -#[cfg(not(target_os = "openbsd"))] +#[cfg(not(any(target_os = "openbsd", target_os = "android", target_os = "redox")))] // see: https://gitlab.com/procps-ng/procps/-/blob/4740a0efa79cade867cfc7b32955fe0f75bf5173/library/uptime.c#L63-L115 pub fn get_nusers() -> usize { use crate::utmpx::Utmpx; @@ -236,6 +242,12 @@ pub fn get_nusers(file: &str) -> usize { nusers } +// TODO implement functionality +#[cfg(any(target_os = "android", target_os = "redox"))] +pub fn get_nusers() -> usize { + 0 +} + /// Get the number of users currently logged in /// /// # Returns @@ -334,6 +346,7 @@ pub fn get_formatted_nusers() -> String { /// Returns a UResult with the load average if successful, otherwise an UptimeError. /// The load average is a tuple of three floating point numbers representing the 1-minute, 5-minute, and 15-minute load averages. #[cfg(unix)] +#[cfg(not(any(target_os = "android", target_os = "redox")))] pub fn get_loadavg() -> UResult<(f64, f64, f64)> { use crate::libc::c_double; use libc::getloadavg; @@ -349,6 +362,12 @@ pub fn get_loadavg() -> UResult<(f64, f64, f64)> { } } +// TODO implement functionality +#[cfg(any(target_os = "android", target_os = "redox"))] +pub fn get_loadavg() -> UResult<(f64, f64, f64)> { + Err(UptimeError::SystemLoadavg)? +} + /// Get the system load average /// Windows does not have an equivalent to the load average on Unix-like systems. /// diff --git a/tests/by-util/test_uptime.rs b/tests/by-util/test_uptime.rs index e179f64eb..6cc5fea6a 100644 --- a/tests/by-util/test_uptime.rs +++ b/tests/by-util/test_uptime.rs @@ -6,10 +6,9 @@ // spell-checker:ignore bincode serde utmp runlevel testusr testx #![allow(clippy::cast_possible_wrap, clippy::unreadable_literal)] -#[cfg(not(target_os = "openbsd"))] +#[cfg(not(any(windows, target_os = "openbsd", target_os = "freebsd")))] use uutests::at_and_ucmd; -use uutests::util::TestScenario; -use uutests::{new_ucmd, util_name}; +use uutests::new_ucmd; use regex::Regex; @@ -20,17 +19,21 @@ fn test_invalid_arg() { #[test] fn test_uptime() { - new_ucmd!() - .succeeds() - .stdout_contains("load average:") - .stdout_contains(" up "); + let result = new_ucmd!().succeeds(); + + result.stdout_contains(" up "); + + #[cfg(not(windows))] + result.stdout_contains("load average:"); + #[cfg(windows)] + result.stdout_does_not_contain("load average:"); // Don't check for users as it doesn't show in some CI } /// Checks for files without utmpx records for which boot time cannot be calculated #[test] -#[cfg(not(any(target_os = "openbsd", target_os = "freebsd")))] +#[cfg(not(any(windows, target_os = "openbsd", target_os = "freebsd")))] // Disabled for freebsd, since it doesn't use the utmpxname() sys call to change the default utmpx // file that is accessed using getutxent() fn test_uptime_for_file_without_utmpx_records() { @@ -48,6 +51,7 @@ fn test_uptime_for_file_without_utmpx_records() { #[test] #[cfg(all(unix, feature = "cp"))] fn test_uptime_with_fifo() { + use uutests::{util::TestScenario, util_name}; // This test can go on forever in the CI in some cases, might need aborting // Sometimes writing to the pipe is broken let ts = TestScenario::new(util_name!()); @@ -74,7 +78,7 @@ fn test_uptime_with_fifo() { } #[test] -#[cfg(not(target_os = "freebsd"))] +#[cfg(not(any(windows, target_os = "freebsd")))] fn test_uptime_with_non_existent_file() { // Disabled for freebsd, since it doesn't use the utmpxname() sys call to change the default utmpx // file that is accessed using getutxent() @@ -88,7 +92,7 @@ fn test_uptime_with_non_existent_file() { // TODO create a similar test for macos // This will pass #[test] -#[cfg(not(any(target_os = "openbsd", target_os = "macos")))] +#[cfg(not(any(windows, target_os = "openbsd", target_os = "macos")))] #[cfg(not(target_env = "musl"))] #[cfg_attr( all(target_arch = "aarch64", target_os = "linux"), @@ -235,6 +239,7 @@ fn test_uptime_with_file_containing_valid_boot_time_utmpx_record() { } #[test] +#[cfg(not(windows))] fn test_uptime_with_extra_argument() { new_ucmd!() .arg("a") @@ -242,8 +247,10 @@ fn test_uptime_with_extra_argument() { .fails() .stderr_contains("unexpected value 'b'"); } + /// Checks whether uptime displays the correct stderr msg when its called with a directory #[test] +#[cfg(not(windows))] fn test_uptime_with_dir() { let (at, mut ucmd) = at_and_ucmd!();