Skip to content

Commit 9a2ee94

Browse files
who: fixed panic in who > /dev/full (#11767)
* Fixed panic in who > /dev/full * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * More sctrictly test --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 36ac85b commit 9a2ee94

2 files changed

Lines changed: 52 additions & 25 deletions

File tree

src/uu/who/src/platform/unix.rs

Lines changed: 35 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use uucore::utmpx::{self, UtmpxRecord, time};
1818
use std::borrow::Cow;
1919
use std::ffi::CStr;
2020
use std::fmt::Write;
21+
use std::io::{Write as _, stdout};
2122
use std::os::unix::fs::MetadataExt;
2223
use std::path::PathBuf;
2324

@@ -114,7 +115,8 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
114115
args: files,
115116
};
116117

117-
who.exec()
118+
who.exec()?;
119+
Ok(())
118120
}
119121

120122
struct Who {
@@ -214,7 +216,7 @@ impl Who {
214216
let records = utmpx::Utmpx::iter_all_records_from(f);
215217

216218
if self.include_heading {
217-
self.print_heading();
219+
self.print_heading()?;
218220
}
219221
let cur_tty = if self.my_line_only {
220222
current_tty()
@@ -230,23 +232,23 @@ impl Who {
230232
match ut.record_type() {
231233
rt if self.need_runlevel && run_level_chk(rt) => {
232234
if cfg!(target_os = "linux") {
233-
self.print_runlevel(&ut);
235+
self.print_runlevel(&ut)?;
234236
}
235237
}
236238
x if x == utmpx::BOOT_TIME && self.need_boottime => {
237-
self.print_boottime(&ut);
239+
self.print_boottime(&ut)?;
238240
}
239241
x if x == utmpx::NEW_TIME && self.need_clockchange => {
240-
self.print_clockchange(&ut);
242+
self.print_clockchange(&ut)?;
241243
}
242244
x if x == utmpx::INIT_PROCESS && self.need_initspawn => {
243-
self.print_initspawn(&ut);
245+
self.print_initspawn(&ut)?;
244246
}
245247
x if x == utmpx::LOGIN_PROCESS && self.need_login => {
246-
self.print_login(&ut);
248+
self.print_login(&ut)?;
247249
}
248250
x if x == utmpx::DEAD_PROCESS && self.need_deadprocs => {
249-
self.print_deadprocs(&ut);
251+
self.print_deadprocs(&ut)?;
250252
}
251253
_ => {}
252254
}
@@ -260,7 +262,7 @@ impl Who {
260262
}
261263

262264
#[inline]
263-
fn print_runlevel(&self, ut: &UtmpxRecord) {
265+
fn print_runlevel(&self, ut: &UtmpxRecord) -> UResult<()> {
264266
let last = (ut.pid() / 256) as u8 as char;
265267
let curr = (ut.pid() % 256) as u8 as char;
266268
let runlevel_line = translate!("who-runlevel", "level" => curr);
@@ -276,11 +278,12 @@ impl Who {
276278
"",
277279
if last.is_control() { "" } else { &comment },
278280
"",
279-
);
281+
)?;
282+
Ok(())
280283
}
281284

282285
#[inline]
283-
fn print_clockchange(&self, ut: &UtmpxRecord) {
286+
fn print_clockchange(&self, ut: &UtmpxRecord) -> UResult<()> {
284287
self.print_line(
285288
"",
286289
' ',
@@ -290,11 +293,12 @@ impl Who {
290293
"",
291294
"",
292295
"",
293-
);
296+
)?;
297+
Ok(())
294298
}
295299

296300
#[inline]
297-
fn print_login(&self, ut: &UtmpxRecord) {
301+
fn print_login(&self, ut: &UtmpxRecord) -> UResult<()> {
298302
let comment = translate!("who-login-id", "id" => ut.terminal_suffix());
299303
let pidstr = format!("{}", ut.pid());
300304
self.print_line(
@@ -306,11 +310,12 @@ impl Who {
306310
&pidstr,
307311
&comment,
308312
"",
309-
);
313+
)?;
314+
Ok(())
310315
}
311316

312317
#[inline]
313-
fn print_deadprocs(&self, ut: &UtmpxRecord) {
318+
fn print_deadprocs(&self, ut: &UtmpxRecord) -> UResult<()> {
314319
let comment = translate!("who-login-id", "id" => ut.terminal_suffix());
315320
let pidstr = format!("{}", ut.pid());
316321
let e = ut.exit_status();
@@ -324,11 +329,12 @@ impl Who {
324329
&pidstr,
325330
&comment,
326331
&exitstr,
327-
);
332+
)?;
333+
Ok(())
328334
}
329335

330336
#[inline]
331-
fn print_initspawn(&self, ut: &UtmpxRecord) {
337+
fn print_initspawn(&self, ut: &UtmpxRecord) -> UResult<()> {
332338
let comment = translate!("who-login-id", "id" => ut.terminal_suffix());
333339
let pidstr = format!("{}", ut.pid());
334340
self.print_line(
@@ -340,11 +346,12 @@ impl Who {
340346
&pidstr,
341347
&comment,
342348
"",
343-
);
349+
)?;
350+
Ok(())
344351
}
345352

346353
#[inline]
347-
fn print_boottime(&self, ut: &UtmpxRecord) {
354+
fn print_boottime(&self, ut: &UtmpxRecord) -> UResult<()> {
348355
self.print_line(
349356
"",
350357
' ',
@@ -354,7 +361,8 @@ impl Who {
354361
"",
355362
"",
356363
"",
357-
);
364+
)?;
365+
Ok(())
358366
}
359367

360368
fn print_user(&self, ut: &UtmpxRecord) -> UResult<()> {
@@ -404,7 +412,7 @@ impl Who {
404412
format!("{}", ut.pid()).as_str(),
405413
hoststr.as_str(),
406414
"",
407-
);
415+
)?;
408416

409417
Ok(())
410418
}
@@ -420,7 +428,7 @@ impl Who {
420428
pid: &str,
421429
comment: &str,
422430
exit: &str,
423-
) {
431+
) -> UResult<()> {
424432
let mut buf = String::with_capacity(64);
425433
let msg = vec![' ', state].into_iter().collect::<String>();
426434

@@ -443,11 +451,12 @@ impl Who {
443451
if self.include_exit {
444452
write!(buf, " {exit:<12}").unwrap();
445453
}
446-
println!("{}", buf.trim_end());
454+
writeln!(stdout(), "{}", buf.trim_end())?;
455+
Ok(())
447456
}
448457

449458
#[inline]
450-
fn print_heading(&self) {
459+
fn print_heading(&self) -> UResult<()> {
451460
self.print_line(
452461
&translate!("who-heading-name"),
453462
' ',
@@ -457,6 +466,7 @@ impl Who {
457466
&translate!("who-heading-pid"),
458467
&translate!("who-heading-comment"),
459468
&translate!("who-heading-exit"),
460-
);
469+
)?;
470+
Ok(())
461471
}
462472
}

tests/by-util/test_who.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,3 +275,20 @@ fn test_locale() {
275275
.succeeds()
276276
.stdout_is(&expected_stdout);
277277
}
278+
279+
#[cfg(target_os = "linux")]
280+
#[test]
281+
fn test_piped_to_dev_full() {
282+
let ts = TestScenario::new(util_name!());
283+
284+
let dev_full = std::fs::OpenOptions::new()
285+
.write(true)
286+
.open("/dev/full")
287+
.unwrap();
288+
289+
ts.ucmd()
290+
.arg("--heading")
291+
.set_stdout(dev_full)
292+
.fails()
293+
.stderr_is("who: No space left on device\n");
294+
}

0 commit comments

Comments
 (0)