Skip to content

Commit 64762d3

Browse files
uniq: honor stdbuf mode
1 parent c79e686 commit 64762d3

3 files changed

Lines changed: 71 additions & 4 deletions

File tree

src/uu/stdbuf/src/libstdbuf/src/libstdbuf.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,22 @@
44
// file that was distributed with this source code.
55
// spell-checker:ignore (ToDO) getreent reent IOFBF IOLBF IONBF setvbuf stderrp stdinp stdoutp
66

7+
#![feature(stdout_switchable_buffering)]
8+
79
use ctor::ctor;
810
use libc::{_IOFBF, _IOLBF, _IONBF, FILE, c_char, c_int, fileno, size_t};
911
use std::env;
12+
use std::io::{self, BufferMode};
1013
use std::ptr;
1114

15+
fn value_to_buffer_mode(value: &str) -> BufferMode {
16+
match value {
17+
"0" => BufferMode::Immediate,
18+
"L" => BufferMode::Line,
19+
_ => BufferMode::Block,
20+
}
21+
}
22+
1223
// This runs automatically when the library is loaded via LD_PRELOAD
1324
#[ctor]
1425
fn init() {
@@ -224,6 +235,9 @@ pub unsafe extern "C" fn __stdbuf() {
224235
set_buffer(unsafe { __stdbuf_get_stdin() }, &val);
225236
}
226237
if let Ok(val) = env::var("_STDBUF_O") {
238+
io::stdout()
239+
.lock()
240+
.set_buffer_mode(value_to_buffer_mode(&val));
227241
set_buffer(unsafe { __stdbuf_get_stdout() }, &val);
228242
}
229243
}

src/uu/uniq/src/uniq.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -843,9 +843,6 @@ fn open_output_file(out_file_name: Option<&OsStr>) -> UResult<Box<dyn Write>> {
843843
)?;
844844
Box::new(BufWriter::with_capacity(OUTPUT_BUFFER_CAPACITY, out_file))
845845
}
846-
_ => Box::new(BufWriter::with_capacity(
847-
OUTPUT_BUFFER_CAPACITY,
848-
stdout().lock(),
849-
)),
846+
_ => Box::new(stdout().lock()),
850847
})
851848
}

test-stdbuf-poc.sh

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#!/usr/bin/env bash
2+
# requires stage1 rustc built from https://github.com/victor-prokhorov/rust/commit/a9d5767288d132bc3688799ad45c4647b7043f7d
3+
# which is a clone of https://github.com/rust-lang/rust/pull/78515
4+
set -euo pipefail
5+
6+
COREUTILS_DIR=/home/victorprokhorov/coreutils
7+
RUST_DIR=/home/victorprokhorov/rust-lang/rust
8+
GNU_DIR=/home/victorprokhorov/gnu
9+
STAGE1_SYSROOT_LIB="$RUST_DIR/build/aarch64-unknown-linux-gnu/stage1/lib/rustlib/aarch64-unknown-linux-gnu/lib"
10+
STAGE1_RUSTC="$RUST_DIR/build/aarch64-unknown-linux-gnu/stage1/bin/rustc"
11+
12+
ok() { echo " OK $*"; }
13+
fail() { echo "FAIL $*"; exit 1; }
14+
step() { echo; echo "$*"; }
15+
16+
step "build stdlib"
17+
cd "$RUST_DIR"
18+
python3 x.py build library
19+
ok "stdlib built"
20+
21+
step "toolchain check"
22+
rustup run stage1 rustc --version | grep -q 'rustc' \
23+
|| fail "stage1 toolchain not found"
24+
ok "$(rustup run stage1 rustc --version)"
25+
rustup run stage1 rustc --edition 2021 -C prefer-dynamic \
26+
-o /tmp/poc_api_check - <<'RUST' \
27+
|| fail "stdout_switchable_buffering or set_buffer_mode not found in stage1 stdlib"
28+
#![feature(stdout_switchable_buffering)]
29+
use std::io::{self, BufferMode};
30+
fn main() { io::stdout().lock().set_buffer_mode(BufferMode::Line); }
31+
RUST
32+
ok "stage1 stdlib has stdout_switchable_buffering and set_buffer_mode"
33+
34+
step "cargo +stage1 build"
35+
cd "$COREUTILS_DIR"
36+
RUSTC="$STAGE1_RUSTC" cargo build -p uu_stdbuf_libstdbuf -p uu_stdbuf -p uu_uniq
37+
38+
step "block buffering test all lines must appear together at the end"
39+
rustup run stage1 rustc --edition 2021 -C prefer-dynamic \
40+
-o /tmp/poc_block_test - <<'RUST' || fail "compile poc_block_test"
41+
#![feature(stdout_switchable_buffering)]
42+
use std::io::{self, BufferMode};
43+
fn main() {
44+
io::stdout().lock().set_buffer_mode(BufferMode::Block);
45+
for line in ["1", "2", "3", "soleil"] {
46+
println!("{line}");
47+
std::thread::sleep(std::time::Duration::from_secs(1));
48+
}
49+
}
50+
RUST
51+
LD_LIBRARY_PATH="$STAGE1_SYSROOT_LIB" /tmp/poc_block_test
52+
53+
step "GNU compliance tests/misc/stdbuf.sh"
54+
cd "$COREUTILS_DIR"
55+
path_UUTILS="$COREUTILS_DIR" path_GNU="$GNU_DIR" PROFILE=debug \
56+
util/run-gnu-test.sh tests/misc/stdbuf.sh

0 commit comments

Comments
 (0)