fix: uptime > /dev/full panic fix (#10827)

* fix: uptime > /dev/full panic fix

* style: fmt

* fix: writeln -> write

* uptime: prints replacement

* uptime(test): remove pipe_in from test

---------

Co-authored-by: Sylvestre Ledru <sylvestre@debian.org>
This commit is contained in:
hlsxx
2026-02-12 11:51:47 +01:00
committed by GitHub
parent 1c023bfad9
commit 07567b1c63
2 changed files with 48 additions and 29 deletions
+33 -29
View File
@@ -10,7 +10,7 @@ use jiff::tz::TimeZone;
use jiff::{Timestamp, ToSpan};
#[cfg(unix)]
use std::ffi::OsString;
use std::io;
use std::io::{self, Write, stdout};
use thiserror::Error;
use uucore::error::{UError, UResult};
use uucore::format_usage;
@@ -144,24 +144,24 @@ fn uptime_with_file(file_path: &OsString) -> UResult<()> {
if bytes[bytes.len() - 1] != b'x' {
show_error!("{}", translate!("uptime-error-couldnt-get-boot-time"));
print_time();
print!("{}", translate!("uptime-output-unknown-uptime"));
print_nusers(Some(0));
print_loadavg();
print_time()?;
write!(stdout(), "{}", translate!("uptime-output-unknown-uptime"))?;
print_nusers(Some(0))?;
print_loadavg()?;
set_exit_code(1);
return Ok(());
}
}
if non_fatal_error {
print_time();
print!("{}", translate!("uptime-output-unknown-uptime"));
print_nusers(Some(0));
print_loadavg();
print_time()?;
write!(stdout(), "{}", translate!("uptime-output-unknown-uptime"))?;
print_nusers(Some(0))?;
print_loadavg()?;
return Ok(());
}
print_time();
print_time()?;
let user_count;
#[cfg(not(target_os = "openbsd"))]
@@ -173,7 +173,7 @@ fn uptime_with_file(file_path: &OsString) -> UResult<()> {
show_error!("{}", translate!("uptime-error-couldnt-get-boot-time"));
set_exit_code(1);
print!("{}", translate!("uptime-output-unknown-uptime"));
write!(stdout(), "{}", translate!("uptime-output-unknown-uptime"))?;
}
user_count = count;
}
@@ -187,14 +187,14 @@ fn uptime_with_file(file_path: &OsString) -> UResult<()> {
show_error!("{}", translate!("uptime-error-couldnt-get-boot-time"));
set_exit_code(1);
print!("{}", translate!("uptime-output-unknown-uptime"));
write!(stdout(), "{}", translate!("uptime-output-unknown-uptime"))?;
}
user_count =
uucore::uptime::get_nusers(file_path.to_str().expect("invalid utmp path file"));
}
print_nusers(Some(user_count));
print_loadavg();
print_nusers(Some(user_count))?;
print_loadavg()?;
Ok(())
}
@@ -210,27 +210,27 @@ fn uptime_since() -> UResult<()> {
let uptime = get_uptime(None)?;
let since_date = (Timestamp::now() - uptime.seconds()).to_zoned(TimeZone::system());
println!("{}", since_date.strftime("%Y-%m-%d %H:%M:%S"));
writeln!(stdout(), "{}", since_date.strftime("%Y-%m-%d %H:%M:%S"))?;
Ok(())
}
/// Default uptime behaviour i.e. when no file argument is given.
fn default_uptime() -> UResult<()> {
print_time();
print_time()?;
print_uptime(None)?;
print_nusers(None);
print_loadavg();
print_nusers(None)?;
print_loadavg()?;
Ok(())
}
#[inline]
fn print_loadavg() {
match get_formatted_loadavg() {
Err(_) => {}
Ok(s) => println!("{s}"),
fn print_loadavg() -> UResult<()> {
if let Ok(s) = get_formatted_loadavg() {
writeln!(stdout(), "{s}")?;
}
Ok(())
}
#[cfg(unix)]
@@ -259,8 +259,9 @@ fn process_utmpx(file: Option<&OsString>) -> (Option<time_t>, usize) {
(boot_time, nusers)
}
fn print_nusers(nusers: Option<usize>) {
print!(
fn print_nusers(nusers: Option<usize>) -> UResult<()> {
write!(
stdout(),
"{}, ",
match nusers {
None => {
@@ -270,18 +271,21 @@ fn print_nusers(nusers: Option<usize>) {
format_nusers(nusers)
}
}
);
)?;
Ok(())
}
fn print_time() {
print!(" {} ", get_formatted_time());
fn print_time() -> UResult<()> {
write!(stdout(), " {} ", get_formatted_time())?;
Ok(())
}
fn print_uptime(boot_time: Option<time_t>) -> UResult<()> {
let localized_text = translate!("uptime-output-up-text");
let uptime_message = get_formatted_uptime(boot_time, OutputFormat::HumanReadable)?;
print!("{localized_text} {uptime_message}, ");
write!(stdout(), "{localized_text} {uptime_message}, ")?;
Ok(())
}
@@ -289,6 +293,6 @@ fn pretty_print_uptime() -> UResult<()> {
let localized_text = translate!("uptime-output-up-text");
let uptime_message = get_formatted_uptime(None, OutputFormat::PrettyPrint)?;
println!("{localized_text} {uptime_message}");
writeln!(stdout(), "{localized_text} {uptime_message}")?;
Ok(())
}
+15
View File
@@ -25,6 +25,21 @@ fn test_uptime() {
// Don't check for users as it doesn't show in some CI
}
#[test]
#[cfg(target_os = "linux")]
fn test_write_error_handling() {
use std::fs::File;
let dev_full =
File::create("/dev/full").expect("Failed to open /dev/full - test must run on Linux");
new_ucmd!()
.set_stdout(dev_full)
.fails()
.code_is(1)
.stderr_contains("No space left on device");
}
/// Checks for files without utmpx records for which boot time cannot be calculated
#[test]
#[cfg(not(any(target_os = "openbsd", target_os = "freebsd")))]