1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 03:27:44 +00:00

Merge pull request #7892 from cakebaker/uptime_refactor_uumain

uptime: refactor `uumain`
This commit is contained in:
Sylvestre Ledru 2025-05-09 22:11:44 +02:00 committed by GitHub
commit 45b0c39ed7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 47 additions and 65 deletions

View file

@ -6,7 +6,8 @@
// spell-checker:ignore getloadavg behaviour loadavg uptime upsecs updays upmins uphours boottime nusers utmpxname gettime clockid // spell-checker:ignore getloadavg behaviour loadavg uptime upsecs updays upmins uphours boottime nusers utmpxname gettime clockid
use chrono::{Local, TimeZone, Utc}; use chrono::{Local, TimeZone, Utc};
use clap::ArgMatches; #[cfg(unix)]
use std::ffi::OsString;
use std::io; use std::io;
use thiserror::Error; use thiserror::Error;
use uucore::error::{UError, UResult}; use uucore::error::{UError, UResult};
@ -44,14 +45,10 @@ pub enum UptimeError {
// io::Error wrapper // io::Error wrapper
#[error("couldn't get boot time: {0}")] #[error("couldn't get boot time: {0}")]
IoErr(#[from] io::Error), IoErr(#[from] io::Error),
#[error("couldn't get boot time: Is a directory")] #[error("couldn't get boot time: Is a directory")]
TargetIsDir, TargetIsDir,
#[error("couldn't get boot time: Illegal seek")] #[error("couldn't get boot time: Illegal seek")]
TargetIsFifo, TargetIsFifo,
#[error("extra operand '{0}'")]
ExtraOperandError(String),
} }
impl UError for UptimeError { impl UError for UptimeError {
@ -64,41 +61,22 @@ impl UError for UptimeError {
pub fn uumain(args: impl uucore::Args) -> UResult<()> { pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let matches = uu_app().try_get_matches_from(args)?; let matches = uu_app().try_get_matches_from(args)?;
#[cfg(windows)]
return default_uptime(&matches);
#[cfg(unix)] #[cfg(unix)]
{ let file_path = matches.get_one::<OsString>(options::PATH);
use std::ffi::OsString; #[cfg(windows)]
use uucore::error::set_exit_code; let file_path = None;
use uucore::show_error;
let argument = matches.get_many::<OsString>(options::PATH); if matches.get_flag(options::SINCE) {
uptime_since()
// Switches to default uptime behaviour if there is no argument } else if let Some(path) = file_path {
if argument.is_none() { uptime_with_file(path)
return default_uptime(&matches); } else {
} default_uptime()
let mut arg_iter = argument.unwrap();
let file_path = arg_iter.next().unwrap();
if let Some(path) = arg_iter.next() {
// Uptime doesn't attempt to calculate boot time if there is extra arguments.
// Its a fatal error
show_error!(
"{}",
UptimeError::ExtraOperandError(path.to_owned().into_string().unwrap())
);
set_exit_code(1);
return Ok(());
}
uptime_with_file(file_path)
} }
} }
pub fn uu_app() -> Command { pub fn uu_app() -> Command {
Command::new(uucore::util_name()) let cmd = Command::new(uucore::util_name())
.version(uucore::crate_version!()) .version(uucore::crate_version!())
.about(ABOUT) .about(ABOUT)
.override_usage(format_usage(USAGE)) .override_usage(format_usage(USAGE))
@ -109,18 +87,20 @@ pub fn uu_app() -> Command {
.long(options::SINCE) .long(options::SINCE)
.help("system up since") .help("system up since")
.action(ArgAction::SetTrue), .action(ArgAction::SetTrue),
) );
.arg( #[cfg(unix)]
Arg::new(options::PATH) cmd.arg(
.help("file to search boot time from") Arg::new(options::PATH)
.action(ArgAction::Append) .help("file to search boot time from")
.value_parser(ValueParser::os_string()) .action(ArgAction::Set)
.value_hint(ValueHint::AnyPath), .num_args(0..=1)
) .value_parser(ValueParser::os_string())
.value_hint(ValueHint::AnyPath),
)
} }
#[cfg(unix)] #[cfg(unix)]
fn uptime_with_file(file_path: &std::ffi::OsString) -> UResult<()> { fn uptime_with_file(file_path: &OsString) -> UResult<()> {
use std::fs; use std::fs;
use std::os::unix::fs::FileTypeExt; use std::os::unix::fs::FileTypeExt;
use uucore::error::set_exit_code; use uucore::error::set_exit_code;
@ -212,27 +192,29 @@ fn uptime_with_file(file_path: &std::ffi::OsString) -> UResult<()> {
Ok(()) Ok(())
} }
fn uptime_since() -> UResult<()> {
#[cfg(unix)]
#[cfg(not(target_os = "openbsd"))]
let (boot_time, _) = process_utmpx(None);
#[cfg(target_os = "openbsd")]
let uptime = get_uptime(None)?;
#[cfg(unix)]
#[cfg(not(target_os = "openbsd"))]
let uptime = get_uptime(boot_time)?;
#[cfg(target_os = "windows")]
let uptime = get_uptime(None)?;
let initial_date = Local
.timestamp_opt(Utc::now().timestamp() - uptime, 0)
.unwrap();
println!("{}", initial_date.format("%Y-%m-%d %H:%M:%S"));
Ok(())
}
/// Default uptime behaviour i.e. when no file argument is given. /// Default uptime behaviour i.e. when no file argument is given.
fn default_uptime(matches: &ArgMatches) -> UResult<()> { fn default_uptime() -> UResult<()> {
if matches.get_flag(options::SINCE) {
#[cfg(unix)]
#[cfg(not(target_os = "openbsd"))]
let (boot_time, _) = process_utmpx(None);
#[cfg(target_os = "openbsd")]
let uptime = get_uptime(None)?;
#[cfg(unix)]
#[cfg(not(target_os = "openbsd"))]
let uptime = get_uptime(boot_time)?;
#[cfg(target_os = "windows")]
let uptime = get_uptime(None)?;
let initial_date = Local
.timestamp_opt(Utc::now().timestamp() - uptime, 0)
.unwrap();
println!("{}", initial_date.format("%Y-%m-%d %H:%M:%S"));
return Ok(());
}
print_time(); print_time();
print_uptime(None)?; print_uptime(None)?;
print_nusers(None); print_nusers(None);
@ -251,7 +233,7 @@ fn print_loadavg() {
#[cfg(unix)] #[cfg(unix)]
#[cfg(not(target_os = "openbsd"))] #[cfg(not(target_os = "openbsd"))]
fn process_utmpx(file: Option<&std::ffi::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;

View file

@ -251,7 +251,7 @@ fn test_uptime_with_extra_argument() {
.arg("a") .arg("a")
.arg("b") .arg("b")
.fails() .fails()
.stderr_contains("extra operand '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]