diff --git a/src/uu/stdbuf/src/libstdbuf/src/libstdbuf.rs b/src/uu/stdbuf/src/libstdbuf/src/libstdbuf.rs index 26d8a9829d5..bada158d665 100644 --- a/src/uu/stdbuf/src/libstdbuf/src/libstdbuf.rs +++ b/src/uu/stdbuf/src/libstdbuf/src/libstdbuf.rs @@ -4,11 +4,22 @@ // file that was distributed with this source code. // spell-checker:ignore (ToDO) getreent reent IOFBF IOLBF IONBF setvbuf stderrp stdinp stdoutp +#![feature(stdout_switchable_buffering)] + use ctor::ctor; use libc::{_IOFBF, _IOLBF, _IONBF, FILE, c_char, c_int, fileno, size_t}; use std::env; +use std::io::{self, BufferMode}; use std::ptr; +fn value_to_buffer_mode(value: &str) -> BufferMode { + match value { + "0" => BufferMode::Immediate, + "L" => BufferMode::Line, + _ => BufferMode::Block, + } +} + // This runs automatically when the library is loaded via LD_PRELOAD #[ctor] fn init() { @@ -224,6 +235,9 @@ pub unsafe extern "C" fn __stdbuf() { set_buffer(unsafe { __stdbuf_get_stdin() }, &val); } if let Ok(val) = env::var("_STDBUF_O") { + io::stdout() + .lock() + .set_buffer_mode(value_to_buffer_mode(&val)); set_buffer(unsafe { __stdbuf_get_stdout() }, &val); } } diff --git a/src/uu/uniq/src/uniq.rs b/src/uu/uniq/src/uniq.rs index 109e49d6224..5172dd40fe5 100644 --- a/src/uu/uniq/src/uniq.rs +++ b/src/uu/uniq/src/uniq.rs @@ -843,9 +843,6 @@ fn open_output_file(out_file_name: Option<&OsStr>) -> UResult> { )?; Box::new(BufWriter::with_capacity(OUTPUT_BUFFER_CAPACITY, out_file)) } - _ => Box::new(BufWriter::with_capacity( - OUTPUT_BUFFER_CAPACITY, - stdout().lock(), - )), + _ => Box::new(stdout().lock()), }) } diff --git a/test-stdbuf-poc.sh b/test-stdbuf-poc.sh new file mode 100755 index 00000000000..6be5ea56458 --- /dev/null +++ b/test-stdbuf-poc.sh @@ -0,0 +1,56 @@ +#!/usr/bin/env bash +# requires stage1 rustc built from https://github.com/victor-prokhorov/rust/commit/a9d5767288d132bc3688799ad45c4647b7043f7d +# which is a clone of https://github.com/rust-lang/rust/pull/78515 +set -euo pipefail + +COREUTILS_DIR=/home/victorprokhorov/coreutils +RUST_DIR=/home/victorprokhorov/rust-lang/rust +GNU_DIR=/home/victorprokhorov/gnu +STAGE1_SYSROOT_LIB="$RUST_DIR/build/aarch64-unknown-linux-gnu/stage1/lib/rustlib/aarch64-unknown-linux-gnu/lib" +STAGE1_RUSTC="$RUST_DIR/build/aarch64-unknown-linux-gnu/stage1/bin/rustc" + +ok() { echo " OK $*"; } +fail() { echo "FAIL $*"; exit 1; } +step() { echo; echo "$*"; } + +step "build stdlib" +cd "$RUST_DIR" +python3 x.py build library +ok "stdlib built" + +step "toolchain check" +rustup run stage1 rustc --version | grep -q 'rustc' \ + || fail "stage1 toolchain not found" +ok "$(rustup run stage1 rustc --version)" +rustup run stage1 rustc --edition 2021 -C prefer-dynamic \ + -o /tmp/poc_api_check - <<'RUST' \ + || fail "stdout_switchable_buffering or set_buffer_mode not found in stage1 stdlib" +#![feature(stdout_switchable_buffering)] +use std::io::{self, BufferMode}; +fn main() { io::stdout().lock().set_buffer_mode(BufferMode::Line); } +RUST +ok "stage1 stdlib has stdout_switchable_buffering and set_buffer_mode" + +step "cargo +stage1 build" +cd "$COREUTILS_DIR" +RUSTC="$STAGE1_RUSTC" cargo build -p uu_stdbuf_libstdbuf -p uu_stdbuf -p uu_uniq + +step "block buffering test all lines must appear together at the end" +rustup run stage1 rustc --edition 2021 -C prefer-dynamic \ + -o /tmp/poc_block_test - <<'RUST' || fail "compile poc_block_test" +#![feature(stdout_switchable_buffering)] +use std::io::{self, BufferMode}; +fn main() { + io::stdout().lock().set_buffer_mode(BufferMode::Block); + for line in ["1", "2", "3", "soleil"] { + println!("{line}"); + std::thread::sleep(std::time::Duration::from_secs(1)); + } +} +RUST +LD_LIBRARY_PATH="$STAGE1_SYSROOT_LIB" /tmp/poc_block_test + +step "GNU compliance tests/misc/stdbuf.sh" +cd "$COREUTILS_DIR" +path_UUTILS="$COREUTILS_DIR" path_GNU="$GNU_DIR" PROFILE=debug \ + util/run-gnu-test.sh tests/misc/stdbuf.sh