From cf2625f57c4ead1a1996ee37edbfa1d480efcfb5 Mon Sep 17 00:00:00 2001 From: xtqqczze <45661989+xtqqczze@users.noreply.github.com> Date: Tue, 12 May 2026 15:23:49 +0100 Subject: [PATCH] dd: enable WASI support for StdinFile on nightly --- .../workspace.wordlist.txt | 1 + Cargo.lock | 31 +++++++++----- Cargo.toml | 2 + src/uu/dd/Cargo.toml | 4 ++ src/uu/dd/build.rs | 10 +++++ src/uu/dd/src/dd.rs | 41 +++++++++++-------- 6 files changed, 61 insertions(+), 28 deletions(-) create mode 100644 src/uu/dd/build.rs diff --git a/.vscode/cspell.dictionaries/workspace.wordlist.txt b/.vscode/cspell.dictionaries/workspace.wordlist.txt index af535072095..2572f7616e9 100644 --- a/.vscode/cspell.dictionaries/workspace.wordlist.txt +++ b/.vscode/cspell.dictionaries/workspace.wordlist.txt @@ -5,6 +5,7 @@ doctest # * crates aho-corasick blake2b_simd +rsconf rustix # * uutils project diff --git a/Cargo.lock b/Cargo.lock index 3de0ea0ccb3..d2f93f792d0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -77,7 +77,7 @@ version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -88,7 +88,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -1001,7 +1001,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1730,7 +1730,7 @@ dependencies = [ "portable-atomic", "portable-atomic-util", "serde_core", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -2046,7 +2046,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -2570,6 +2570,15 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "323c417e1d9665a65b263ec744ba09030cfb277e9daa0b018a4ab62e57bc8189" +[[package]] +name = "rsconf" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06cbd984e96cc891aa018958ac3d09986c0ea7635eedfff670b99a90970f159f" +dependencies = [ + "cc", +] + [[package]] name = "rstest" version = "0.26.1" @@ -2645,7 +2654,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -2866,7 +2875,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -2945,7 +2954,7 @@ dependencies = [ "getrandom 0.4.2", "once_cell", "rustix", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -2955,7 +2964,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "230a1b821ccbd75b185820a1f1ff7b14d21da1e442e22c0863ea5f08771a8874" dependencies = [ "rustix", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -3447,6 +3456,8 @@ dependencies = [ "gcd", "libc", "nix", + "rsconf", + "rustc_version", "tempfile", "thiserror 2.0.18", "uucore", @@ -4747,7 +4758,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index a775c1e7ef7..f12ae07f6c9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -446,8 +446,10 @@ rand_chacha = { version = "0.10.0" } rayon = "1.10" regex = "1.10.4" rlimit = "0.11.0" +rsconf = "0.3.0" rstest = "0.26.0" rstest_reuse = "0.7.0" +rustc_version = "0.4.1" rustc-hash = "2.1.1" rust-ini = "0.21.0" # binary name of coreutils can be hijacked by overriding getauxval via LD_PRELOAD diff --git a/src/uu/dd/Cargo.toml b/src/uu/dd/Cargo.toml index 438b9ccf552..916e929eb36 100644 --- a/src/uu/dd/Cargo.toml +++ b/src/uu/dd/Cargo.toml @@ -44,6 +44,10 @@ divan = { workspace = true } tempfile = { workspace = true } uucore = { workspace = true, features = ["benchmark"] } +[build-dependencies] +rsconf = { workspace = true } +rustc_version = { workspace = true } + [[bench]] name = "dd_bench" harness = false diff --git a/src/uu/dd/build.rs b/src/uu/dd/build.rs new file mode 100644 index 00000000000..b4fefaaf856 --- /dev/null +++ b/src/uu/dd/build.rs @@ -0,0 +1,10 @@ +// This file is part of the uutils coreutils package. +// +// For the full copyright and license information, please view the LICENSE +// file that was distributed with this source code. + +fn main() { + let is_nightly = + rustc_version::version_meta().unwrap().channel == rustc_version::Channel::Nightly; + rsconf::declare_cfg("nightly", is_nightly); +} diff --git a/src/uu/dd/src/dd.rs b/src/uu/dd/src/dd.rs index 6bf2b49ff34..a56d0bc2b95 100644 --- a/src/uu/dd/src/dd.rs +++ b/src/uu/dd/src/dd.rs @@ -5,6 +5,8 @@ // spell-checker:ignore fname, ftype, tname, fpath, specfile, testfile, unspec, ifile, ofile, outfile, fullblock, urand, fileio, atoe, atoibm, behaviour, bmax, bremain, cflags, creat, ctable, ctty, datastructures, doesnt, etoa, fileout, fname, gnudd, iconvflags, iseek, nocache, noctty, noerror, nofollow, nolinks, nonblock, oconvflags, oseek, outfile, parseargs, rlen, rmax, rremain, rsofar, rstat, sigusr, wlen, wstat oconv canonicalized fadvise Fadvise FADV DONTNEED ESPIPE bufferedoutput, SETFL +#![cfg_attr(all(target_os = "wasi", nightly), feature(wasi_ext))] + mod blocks; mod bufferedoutput; mod conversion_tables; @@ -31,19 +33,20 @@ use uucore::translate; use std::cmp; use std::env; use std::ffi::OsString; -#[cfg(unix)] +#[cfg(any(unix, all(target_os = "wasi", nightly)))] use std::fs::Metadata; use std::fs::{File, OpenOptions}; use std::io::{self, Read, Seek, SeekFrom, Write}; #[cfg(any(target_os = "linux", target_os = "android"))] use std::os::fd::AsFd; +#[cfg(any(unix, all(target_os = "wasi", nightly)))] +use std::os::fd::{AsRawFd, FromRawFd}; +#[cfg(unix)] +use std::os::unix::fs::FileTypeExt; #[cfg(any(target_os = "linux", target_os = "android"))] use std::os::unix::fs::OpenOptionsExt; -#[cfg(unix)] -use std::os::unix::{ - fs::FileTypeExt, - io::{AsRawFd, FromRawFd}, -}; +#[cfg(all(target_os = "wasi", nightly))] +use std::os::wasi::fs::FileTypeExt; #[cfg(windows)] use std::os::windows::{fs::MetadataExt, io::AsHandle}; use std::path::Path; @@ -60,9 +63,11 @@ use nix::{ fcntl::{PosixFadviseAdvice, posix_fadvise}, }; use uucore::display::Quotable; -use uucore::error::{FromIo, UResult}; #[cfg(unix)] -use uucore::error::{USimpleError, set_exit_code}; +use uucore::error::USimpleError; +#[cfg(any(unix, all(target_os = "wasi", nightly)))] +use uucore::error::set_exit_code; +use uucore::error::{FromIo, UResult}; #[cfg(target_os = "linux")] use uucore::show_if_err; use uucore::{format_usage, show_error}; @@ -211,14 +216,14 @@ fn read_and_discard(reader: &mut R, n: u64, buf_size: usize) -> io::Res /// fine-grained access to reading from stdin. enum Source { /// Input from stdin. - #[cfg(not(unix))] + #[cfg(not(any(unix, all(target_os = "wasi", nightly))))] Stdin(io::Stdin), /// Input from a file. File(File), /// Input from stdin, opened from its file descriptor. - #[cfg(unix)] + #[cfg(any(unix, all(target_os = "wasi", nightly)))] StdinFile(File), /// Input from a named pipe, also known as a FIFO. @@ -234,7 +239,7 @@ impl Source { /// the [`File`] parameter. You can use this instead of /// `Source::Stdin` to allow reading from stdin without consuming /// the entire contents of stdin when this process terminates. - #[cfg(unix)] + #[cfg(any(unix, all(target_os = "wasi", nightly)))] fn stdin_as_file() -> Self { let fd = io::stdin().as_raw_fd(); let f = unsafe { File::from_raw_fd(fd) }; @@ -243,7 +248,7 @@ impl Source { fn skip(&mut self, n: u64, ibs: usize) -> io::Result { match self { - #[cfg(not(unix))] + #[cfg(not(any(unix, all(target_os = "wasi", nightly))))] Self::Stdin(stdin) => { let m = read_and_discard(stdin, n, ibs)?; if m < n { @@ -254,7 +259,7 @@ impl Source { } Ok(m) } - #[cfg(unix)] + #[cfg(any(unix, all(target_os = "wasi", nightly)))] Self::StdinFile(f) => { if let Ok(Some(len)) = try_get_len_of_block_device(f) && len < n @@ -331,10 +336,10 @@ impl Source { impl Read for Source { fn read(&mut self, buf: &mut [u8]) -> io::Result { match self { - #[cfg(not(unix))] + #[cfg(not(any(unix, all(target_os = "wasi", nightly))))] Self::Stdin(stdin) => stdin.read(buf), Self::File(f) => f.read(buf), - #[cfg(unix)] + #[cfg(any(unix, all(target_os = "wasi", nightly)))] Self::StdinFile(f) => f.read(buf), #[cfg(unix)] Self::Fifo(f) => f.read(buf), @@ -378,9 +383,9 @@ impl<'a> Input<'a> { Source::Stdin(io::stdin()) } }; - #[cfg(all(not(unix), not(windows)))] + #[cfg(all(not(unix), not(windows), not(all(target_os = "wasi", nightly))))] let mut src = Source::Stdin(io::stdin()); - #[cfg(unix)] + #[cfg(any(unix, all(target_os = "wasi", nightly)))] let mut src = Source::stdin_as_file(); #[cfg(unix)] if let Source::StdinFile(f) = &src @@ -1490,7 +1495,7 @@ fn is_stdout_redirected_to_seekable_file() -> bool { } /// Try to get the len if it is a block device -#[cfg(unix)] +#[cfg(any(unix, all(target_os = "wasi", nightly)))] fn try_get_len_of_block_device(file: &mut File) -> io::Result> { let ftype = file.metadata()?.file_type(); if !ftype.is_block_device() {