mirror of
https://github.com/uutils/coreutils.git
synced 2025-08-26 05:24:47 +00:00
Merge f580003a62
into 59fd744723
This commit is contained in:
commit
2012ec0bb7
4 changed files with 71 additions and 29 deletions
|
@ -131,6 +131,7 @@ feat_common_core = [
|
||||||
"unexpand",
|
"unexpand",
|
||||||
"uniq",
|
"uniq",
|
||||||
"unlink",
|
"unlink",
|
||||||
|
"uptime",
|
||||||
"vdir",
|
"vdir",
|
||||||
"wc",
|
"wc",
|
||||||
"yes",
|
"yes",
|
||||||
|
@ -209,7 +210,7 @@ feat_require_unix = [
|
||||||
]
|
]
|
||||||
# "feat_require_unix_utmpx" == set of utilities requiring unix utmp/utmpx support
|
# "feat_require_unix_utmpx" == set of utilities requiring unix utmp/utmpx support
|
||||||
# * ref: <https://wiki.musl-libc.org/faq.html#Q:-Why-is-the-utmp/wtmp-functionality-only-implemented-as-stubs?>
|
# * ref: <https://wiki.musl-libc.org/faq.html#Q:-Why-is-the-utmp/wtmp-functionality-only-implemented-as-stubs?>
|
||||||
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" == set of utilities requiring gethostid in libc (only some unixes provide)
|
||||||
feat_require_unix_hostid = ["hostid"]
|
feat_require_unix_hostid = ["hostid"]
|
||||||
# "feat_require_selinux" == set of utilities depending on SELinux.
|
# "feat_require_selinux" == set of utilities depending on SELinux.
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
// spell-checker:ignore getloadavg behaviour loadavg uptime upsecs updays upmins uphours boottime nusers utmpxname gettime clockid couldnt
|
// spell-checker:ignore getloadavg behaviour loadavg uptime upsecs updays upmins uphours boottime nusers utmpxname gettime clockid couldnt
|
||||||
|
|
||||||
use chrono::{Local, TimeZone, Utc};
|
use chrono::{Local, TimeZone, Utc};
|
||||||
#[cfg(unix)]
|
|
||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
use std::io;
|
use std::io;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
@ -15,13 +14,13 @@ use uucore::libc::time_t;
|
||||||
use uucore::translate;
|
use uucore::translate;
|
||||||
use uucore::uptime::*;
|
use uucore::uptime::*;
|
||||||
|
|
||||||
use clap::{Arg, ArgAction, Command, ValueHint, builder::ValueParser};
|
use clap::{Arg, ArgAction, Command};
|
||||||
|
|
||||||
use uucore::LocalizedCommand;
|
use uucore::LocalizedCommand;
|
||||||
use uucore::format_usage;
|
use uucore::format_usage;
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
#[cfg(not(target_os = "openbsd"))]
|
#[cfg(not(any(target_os = "openbsd", target_os = "redox", target_os = "android")))]
|
||||||
use uucore::utmpx::*;
|
use uucore::utmpx::*;
|
||||||
|
|
||||||
pub mod options {
|
pub mod options {
|
||||||
|
@ -83,7 +82,10 @@ pub fn uu_app() -> Command {
|
||||||
.help(translate!("uptime-help-since"))
|
.help(translate!("uptime-help-since"))
|
||||||
.action(ArgAction::SetTrue),
|
.action(ArgAction::SetTrue),
|
||||||
);
|
);
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
|
let cmd = {
|
||||||
|
use clap::{ValueHint, builder::ValueParser};
|
||||||
cmd.arg(
|
cmd.arg(
|
||||||
Arg::new(options::PATH)
|
Arg::new(options::PATH)
|
||||||
.help(translate!("uptime-help-path"))
|
.help(translate!("uptime-help-path"))
|
||||||
|
@ -92,6 +94,14 @@ pub fn uu_app() -> Command {
|
||||||
.value_parser(ValueParser::os_string())
|
.value_parser(ValueParser::os_string())
|
||||||
.value_hint(ValueHint::AnyPath),
|
.value_hint(ValueHint::AnyPath),
|
||||||
)
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
fn uptime_with_file(_: &OsString) -> UResult<()> {
|
||||||
|
unreachable!("The function should never be called on Windows")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
|
@ -153,7 +163,7 @@ fn uptime_with_file(file_path: &OsString) -> UResult<()> {
|
||||||
print_time();
|
print_time();
|
||||||
let user_count;
|
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));
|
let (boot_time, count) = process_utmpx(Some(file_path));
|
||||||
if let Some(time) = boot_time {
|
if let Some(time) = boot_time {
|
||||||
|
@ -167,7 +177,7 @@ fn uptime_with_file(file_path: &OsString) -> UResult<()> {
|
||||||
user_count = count;
|
user_count = count;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "openbsd")]
|
#[cfg(any(target_os = "openbsd", target_os = "redox", target_os = "android"))]
|
||||||
{
|
{
|
||||||
let upsecs = get_uptime(None);
|
let upsecs = get_uptime(None);
|
||||||
if upsecs >= 0 {
|
if upsecs >= 0 {
|
||||||
|
@ -189,12 +199,17 @@ fn uptime_with_file(file_path: &OsString) -> UResult<()> {
|
||||||
|
|
||||||
fn uptime_since() -> UResult<()> {
|
fn uptime_since() -> UResult<()> {
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
#[cfg(not(target_os = "openbsd"))]
|
#[cfg(not(any(target_os = "openbsd", target_os = "redox", target_os = "android")))]
|
||||||
let uptime = {
|
let uptime = {
|
||||||
let (boot_time, _) = process_utmpx(None);
|
let (boot_time, _) = process_utmpx(None);
|
||||||
get_uptime(boot_time)?
|
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 uptime = get_uptime(None)?;
|
||||||
|
|
||||||
let since_date = Local
|
let since_date = Local
|
||||||
|
@ -224,7 +239,7 @@ fn print_loadavg() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[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<time_t>, usize) {
|
fn process_utmpx(file: Option<&OsString>) -> (Option<time_t>, usize) {
|
||||||
let mut nusers = 0;
|
let mut nusers = 0;
|
||||||
let mut boot_time = None;
|
let mut boot_time = None;
|
||||||
|
|
|
@ -79,6 +79,12 @@ pub fn get_uptime(_boot_time: Option<time_t>) -> UResult<i64> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO implement functionality
|
||||||
|
#[cfg(any(target_os = "android", target_os = "redox"))]
|
||||||
|
pub fn get_uptime(_boot_time: Option<time_t>) -> UResult<i64> {
|
||||||
|
Err(UptimeError::SystemUptime)?
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the system uptime
|
/// Get the system uptime
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
|
@ -89,7 +95,7 @@ pub fn get_uptime(_boot_time: Option<time_t>) -> UResult<i64> {
|
||||||
///
|
///
|
||||||
/// Returns a UResult with the uptime in seconds if successful, otherwise an UptimeError.
|
/// Returns a UResult with the uptime in seconds if successful, otherwise an UptimeError.
|
||||||
#[cfg(unix)]
|
#[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<time_t>) -> UResult<i64> {
|
pub fn get_uptime(boot_time: Option<time_t>) -> UResult<i64> {
|
||||||
use crate::utmpx::Utmpx;
|
use crate::utmpx::Utmpx;
|
||||||
use libc::BOOT_TIME;
|
use libc::BOOT_TIME;
|
||||||
|
@ -189,7 +195,7 @@ pub fn get_formatted_uptime(boot_time: Option<time_t>) -> UResult<String> {
|
||||||
///
|
///
|
||||||
/// Returns the number of users currently logged in if successful, otherwise 0.
|
/// Returns the number of users currently logged in if successful, otherwise 0.
|
||||||
#[cfg(unix)]
|
#[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
|
// see: https://gitlab.com/procps-ng/procps/-/blob/4740a0efa79cade867cfc7b32955fe0f75bf5173/library/uptime.c#L63-L115
|
||||||
pub fn get_nusers() -> usize {
|
pub fn get_nusers() -> usize {
|
||||||
use crate::utmpx::Utmpx;
|
use crate::utmpx::Utmpx;
|
||||||
|
@ -236,6 +242,12 @@ pub fn get_nusers(file: &str) -> usize {
|
||||||
nusers
|
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
|
/// Get the number of users currently logged in
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
|
@ -334,6 +346,7 @@ pub fn get_formatted_nusers() -> String {
|
||||||
/// Returns a UResult with the load average if successful, otherwise an UptimeError.
|
/// 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.
|
/// 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(unix)]
|
||||||
|
#[cfg(not(any(target_os = "android", target_os = "redox")))]
|
||||||
pub fn get_loadavg() -> UResult<(f64, f64, f64)> {
|
pub fn get_loadavg() -> UResult<(f64, f64, f64)> {
|
||||||
use crate::libc::c_double;
|
use crate::libc::c_double;
|
||||||
use libc::getloadavg;
|
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
|
/// Get the system load average
|
||||||
/// Windows does not have an equivalent to the load average on Unix-like systems.
|
/// Windows does not have an equivalent to the load average on Unix-like systems.
|
||||||
///
|
///
|
||||||
|
|
|
@ -6,10 +6,9 @@
|
||||||
// spell-checker:ignore bincode serde utmp runlevel testusr testx
|
// spell-checker:ignore bincode serde utmp runlevel testusr testx
|
||||||
#![allow(clippy::cast_possible_wrap, clippy::unreadable_literal)]
|
#![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::at_and_ucmd;
|
||||||
use uutests::util::TestScenario;
|
use uutests::new_ucmd;
|
||||||
use uutests::{new_ucmd, util_name};
|
|
||||||
|
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
|
||||||
|
@ -20,17 +19,21 @@ fn test_invalid_arg() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_uptime() {
|
fn test_uptime() {
|
||||||
new_ucmd!()
|
let result = new_ucmd!().succeeds();
|
||||||
.succeeds()
|
|
||||||
.stdout_contains("load average:")
|
result.stdout_contains(" up ");
|
||||||
.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
|
// 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
|
/// Checks for files without utmpx records for which boot time cannot be calculated
|
||||||
#[test]
|
#[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
|
// Disabled for freebsd, since it doesn't use the utmpxname() sys call to change the default utmpx
|
||||||
// file that is accessed using getutxent()
|
// file that is accessed using getutxent()
|
||||||
fn test_uptime_for_file_without_utmpx_records() {
|
fn test_uptime_for_file_without_utmpx_records() {
|
||||||
|
@ -48,6 +51,7 @@ fn test_uptime_for_file_without_utmpx_records() {
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(all(unix, feature = "cp"))]
|
#[cfg(all(unix, feature = "cp"))]
|
||||||
fn test_uptime_with_fifo() {
|
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
|
// This test can go on forever in the CI in some cases, might need aborting
|
||||||
// Sometimes writing to the pipe is broken
|
// Sometimes writing to the pipe is broken
|
||||||
let ts = TestScenario::new(util_name!());
|
let ts = TestScenario::new(util_name!());
|
||||||
|
@ -74,7 +78,7 @@ fn test_uptime_with_fifo() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(not(target_os = "freebsd"))]
|
#[cfg(not(any(windows, target_os = "freebsd")))]
|
||||||
fn test_uptime_with_non_existent_file() {
|
fn test_uptime_with_non_existent_file() {
|
||||||
// Disabled for freebsd, since it doesn't use the utmpxname() sys call to change the default utmpx
|
// Disabled for freebsd, since it doesn't use the utmpxname() sys call to change the default utmpx
|
||||||
// file that is accessed using getutxent()
|
// file that is accessed using getutxent()
|
||||||
|
@ -88,7 +92,7 @@ fn test_uptime_with_non_existent_file() {
|
||||||
// TODO create a similar test for macos
|
// TODO create a similar test for macos
|
||||||
// This will pass
|
// This will pass
|
||||||
#[test]
|
#[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(not(target_env = "musl"))]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
all(target_arch = "aarch64", target_os = "linux"),
|
all(target_arch = "aarch64", target_os = "linux"),
|
||||||
|
@ -235,6 +239,7 @@ fn test_uptime_with_file_containing_valid_boot_time_utmpx_record() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[cfg(not(windows))]
|
||||||
fn test_uptime_with_extra_argument() {
|
fn test_uptime_with_extra_argument() {
|
||||||
new_ucmd!()
|
new_ucmd!()
|
||||||
.arg("a")
|
.arg("a")
|
||||||
|
@ -242,8 +247,10 @@ fn test_uptime_with_extra_argument() {
|
||||||
.fails()
|
.fails()
|
||||||
.stderr_contains("unexpected value 'b'");
|
.stderr_contains("unexpected value 'b'");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks whether uptime displays the correct stderr msg when its called with a directory
|
/// Checks whether uptime displays the correct stderr msg when its called with a directory
|
||||||
#[test]
|
#[test]
|
||||||
|
#[cfg(not(windows))]
|
||||||
fn test_uptime_with_dir() {
|
fn test_uptime_with_dir() {
|
||||||
let (at, mut ucmd) = at_and_ucmd!();
|
let (at, mut ucmd) = at_and_ucmd!();
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue