mirror of
https://github.com/uutils/coreutils.git
synced 2026-06-10 15:48:22 -07:00
*sum: Fix read_byte_lines discarding read errors (#10671)
* *sum: Fix read_byte_lines discarding read errors * test(*sum): test IOerror handling in checkfile
This commit is contained in:
@@ -15,7 +15,7 @@ use std::io::{self, BufReader, Read, Write, stderr, stdin};
|
||||
use os_display::Quotable;
|
||||
|
||||
use crate::checksum::{AlgoKind, ChecksumError, SizedAlgoKind, digest_reader, unescape_filename};
|
||||
use crate::error::{FromIo, UError, UResult, USimpleError};
|
||||
use crate::error::{FromIo, UError, UIoError, UResult, USimpleError};
|
||||
use crate::quoting_style::{QuotingStyle, locale_aware_escape_name};
|
||||
use crate::sum::DigestOutput;
|
||||
use crate::{
|
||||
@@ -851,7 +851,6 @@ fn process_checksum_file(
|
||||
};
|
||||
|
||||
let reader = BufReader::new(file);
|
||||
let lines = read_os_string_lines(reader).collect::<Vec<_>>();
|
||||
|
||||
// cached_line_format is used to ensure that several non algo-based checksum line
|
||||
// will use the same parser.
|
||||
@@ -861,9 +860,16 @@ fn process_checksum_file(
|
||||
// Behavior tested in gnu_cksum_c::test_warn
|
||||
let mut last_algo = None;
|
||||
|
||||
for (i, line) in lines.iter().enumerate() {
|
||||
for (i, line_res) in read_os_string_lines(reader).enumerate() {
|
||||
let line = line_res.map_err(|e| {
|
||||
USimpleError::new(
|
||||
UIoError::from(e).code(),
|
||||
format!("{}: read error", filename_input.maybe_quote()),
|
||||
)
|
||||
})?;
|
||||
|
||||
let line_result = process_checksum_line(
|
||||
line,
|
||||
&line,
|
||||
i,
|
||||
cli_algo_kind,
|
||||
cli_algo_length,
|
||||
|
||||
+16
-14
@@ -513,24 +513,25 @@ pub fn os_string_to_vec(s: OsString) -> mods::error::UResult<Vec<u8>> {
|
||||
/// which avoids panicking on non UTF-8 input.
|
||||
pub fn read_byte_lines<R: std::io::Read>(
|
||||
mut buf_reader: BufReader<R>,
|
||||
) -> impl Iterator<Item = Vec<u8>> {
|
||||
) -> impl Iterator<Item = std::io::Result<Vec<u8>>> {
|
||||
iter::from_fn(move || {
|
||||
let mut buf = Vec::with_capacity(256);
|
||||
let size = buf_reader.read_until(b'\n', &mut buf).ok()?;
|
||||
|
||||
if size == 0 {
|
||||
return None;
|
||||
}
|
||||
match buf_reader.read_until(b'\n', &mut buf) {
|
||||
Ok(0) => None,
|
||||
Err(e) => Some(Err(e)),
|
||||
Ok(_) => {
|
||||
// Trim (\r)\n
|
||||
if buf.ends_with(b"\n") {
|
||||
buf.pop();
|
||||
if buf.ends_with(b"\r") {
|
||||
buf.pop();
|
||||
}
|
||||
}
|
||||
|
||||
// Trim (\r)\n
|
||||
if buf.ends_with(b"\n") {
|
||||
buf.pop();
|
||||
if buf.ends_with(b"\r") {
|
||||
buf.pop();
|
||||
Some(Ok(buf))
|
||||
}
|
||||
}
|
||||
|
||||
Some(buf)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -539,8 +540,9 @@ pub fn read_byte_lines<R: std::io::Read>(
|
||||
/// but it still will on Windows.
|
||||
pub fn read_os_string_lines<R: std::io::Read>(
|
||||
buf_reader: BufReader<R>,
|
||||
) -> impl Iterator<Item = OsString> {
|
||||
read_byte_lines(buf_reader).map(|byte_line| os_string_from_vec(byte_line).expect("UTF-8 error"))
|
||||
) -> impl Iterator<Item = std::io::Result<OsString>> {
|
||||
read_byte_lines(buf_reader)
|
||||
.map(|byte_line_res| byte_line_res.map(|bl| os_string_from_vec(bl).expect("UTF-8 error")))
|
||||
}
|
||||
|
||||
/// Prompt the user with a formatted string and returns `true` if they reply `'y'` or `'Y'`
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
//
|
||||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
// spell-checker:ignore (words) asdf algo algos asha mgmt xffname hexa GFYEQ HYQK Yqxb dont
|
||||
// spell-checker:ignore (words) asdf algo algos asha mgmt xffname hexa GFYEQ HYQK Yqxb dont checkfile
|
||||
|
||||
use uutests::at_and_ucmd;
|
||||
use uutests::new_ucmd;
|
||||
@@ -3060,3 +3060,17 @@ fn test_check_file_with_io_error() {
|
||||
.stderr_contains("Input/output error")
|
||||
.stdout_contains("FAILED open or read");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(all(target_os = "linux", not(target_env = "musl")))]
|
||||
fn test_check_checkfile_with_io_error() {
|
||||
// /proc/self/mem causes EIO when read without proper seeking
|
||||
new_ucmd!()
|
||||
.arg("-a")
|
||||
.arg("md5")
|
||||
.arg("--check")
|
||||
.arg("/proc/self/mem")
|
||||
.fails()
|
||||
.stderr_contains("/proc/self/mem: read error")
|
||||
.no_stdout();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user