From 912dc47bef2363ce256e79ae253d00322f17a90b Mon Sep 17 00:00:00 2001 From: Karl McDowall Date: Tue, 25 Mar 2025 21:48:23 -0600 Subject: [PATCH] sum: Rework some error handling Update sum to properly propagate errors from file-reads, including implementing a retry on ErrorKind::Interrupted. Also switch to using writeln! rather than println! to prevent crashes if stdout is directed to /dev/full --- src/uu/sum/src/sum.rs | 43 ++++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/src/uu/sum/src/sum.rs b/src/uu/sum/src/sum.rs index 1b09afca9..1aec0ef98 100644 --- a/src/uu/sum/src/sum.rs +++ b/src/uu/sum/src/sum.rs @@ -7,7 +7,7 @@ use clap::{Arg, ArgAction, Command}; use std::fs::File; -use std::io::{Read, stdin}; +use std::io::{ErrorKind, Read, Write, stdin, stdout}; use std::path::Path; use uucore::display::Quotable; use uucore::error::{FromIo, UResult, USimpleError}; @@ -16,42 +16,46 @@ use uucore::{format_usage, help_about, help_usage, show}; const USAGE: &str = help_usage!("sum.md"); const ABOUT: &str = help_about!("sum.md"); -fn bsd_sum(mut reader: Box) -> (usize, u16) { +fn bsd_sum(mut reader: impl Read) -> std::io::Result<(usize, u16)> { let mut buf = [0; 4096]; let mut bytes_read = 0; let mut checksum: u16 = 0; loop { match reader.read(&mut buf) { - Ok(n) if n != 0 => { + Ok(0) => break, + Ok(n) => { bytes_read += n; - for &byte in &buf[..n] { - checksum = checksum.rotate_right(1); - checksum = checksum.wrapping_add(u16::from(byte)); - } + checksum = buf[..n].iter().fold(checksum, |acc, &byte| { + let rotated = acc.rotate_right(1); + rotated.wrapping_add(u16::from(byte)) + }); } - _ => break, + Err(e) if e.kind() == ErrorKind::Interrupted => continue, + Err(e) => return Err(e), } } // Report blocks read in terms of 1024-byte blocks. let blocks_read = bytes_read.div_ceil(1024); - (blocks_read, checksum) + Ok((blocks_read, checksum)) } -fn sysv_sum(mut reader: Box) -> (usize, u16) { +fn sysv_sum(mut reader: impl Read) -> std::io::Result<(usize, u16)> { let mut buf = [0; 4096]; let mut bytes_read = 0; let mut ret = 0u32; loop { match reader.read(&mut buf) { - Ok(n) if n != 0 => { + Ok(0) => break, + Ok(n) => { bytes_read += n; - for &byte in &buf[..n] { - ret = ret.wrapping_add(u32::from(byte)); - } + ret = buf[..n] + .iter() + .fold(ret, |acc, &byte| acc.wrapping_add(u32::from(byte))); } - _ => break, + Err(e) if e.kind() == ErrorKind::Interrupted => continue, + Err(e) => return Err(e), } } @@ -60,7 +64,7 @@ fn sysv_sum(mut reader: Box) -> (usize, u16) { // Report blocks read in terms of 512-byte blocks. let blocks_read = bytes_read.div_ceil(512); - (blocks_read, ret as u16) + Ok((blocks_read, ret as u16)) } fn open(name: &str) -> UResult> { @@ -119,12 +123,13 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { sysv_sum(reader) } else { bsd_sum(reader) - }; + }?; + let mut stdout = stdout().lock(); if print_names { - println!("{sum:0width$} {blocks:width$} {file}"); + writeln!(stdout, "{sum:0width$} {blocks:width$} {file}")?; } else { - println!("{sum:0width$} {blocks:width$}"); + writeln!(stdout, "{sum:0width$} {blocks:width$}")?; } } Ok(())