Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 12 additions & 14 deletions src/uu/yes/src/yes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,9 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let matches = uucore::clap_localization::handle_clap_result(uu_app(), args)?;

#[allow(clippy::unwrap_used, reason = "clap provides 'y' by default")]
let mut buffer = args_into_buffer(matches.get_many::<OsString>("STRING").unwrap())?;
#[cfg(any(target_os = "linux", target_os = "android"))]
let aligned_before_growing = PAGE_SIZE.is_multiple_of(buffer.len());

prepare_buffer(&mut buffer);
#[cfg(any(target_os = "linux", target_os = "android"))]
let res = exec(&buffer, aligned_before_growing);
#[cfg(not(any(target_os = "linux", target_os = "android")))]
let res = exec(&buffer);
match res {
let buffer = args_into_buffer(matches.get_many::<OsString>("STRING").unwrap())?;

match exec(buffer) {
Ok(()) => Ok(()),
// On Windows, silently handle broken pipe since there's no SIGPIPE
#[cfg(windows)]
Expand Down Expand Up @@ -98,7 +91,7 @@ fn args_into_buffer<'a>(i: impl Iterator<Item = &'a OsString>) -> UResult<Vec<u8

/// Assumes buf holds a single output line forged from the command line arguments, copies it
/// repeatedly until the buffer holds as many copies as it can
fn prepare_buffer(buf: &mut Vec<u8>) {
fn repeat_content_to_capacity(buf: &mut Vec<u8>) {
let line_len = buf.len();
debug_assert!(line_len > 0, "buffer is not empty since we have newline");
let target_size = line_len * (buf.capacity() / line_len); // 0 if line_len is already large enough
Expand All @@ -111,16 +104,21 @@ fn prepare_buffer(buf: &mut Vec<u8>) {
}

#[cfg(not(any(target_os = "linux", target_os = "android")))]
pub fn exec(bytes: &[u8]) -> io::Result<()> {
pub fn exec(mut bytes: Vec<u8>) -> io::Result<()> {
repeat_content_to_capacity(&mut bytes);
let bytes = bytes.as_slice();
let mut stdout = io::stdout().lock();
loop {
stdout.write_all(bytes)?;
}
}

#[cfg(any(target_os = "linux", target_os = "android"))]
pub fn exec(bytes: &[u8], aligned: bool) -> io::Result<()> {
pub fn exec(mut bytes: Vec<u8>) -> io::Result<()> {
use uucore::pipes::{pipe, splice, tee};
let aligned = PAGE_SIZE.is_multiple_of(bytes.len());
repeat_content_to_capacity(&mut bytes);
let bytes = bytes.as_slice();
let mut stdout = io::stdout(); // no need to lock with zero-copy
// don't show any error from fast-path and fallback to write for proper message
if let Ok((p_read, mut p_write)) = pipe()
Expand Down Expand Up @@ -181,7 +179,7 @@ mod tests {
for (line, final_len) in tests {
let mut v = Vec::with_capacity(BUF_SIZE);
v.extend(std::iter::repeat_n(b'a', line));
prepare_buffer(&mut v);
repeat_content_to_capacity(&mut v);
assert_eq!(v.len(), final_len);
}
}
Expand Down
Loading