diff --git a/src/uu/mcookie/src/mcookie.rs b/src/uu/mcookie/src/mcookie.rs index abbb857..07d9b71 100644 --- a/src/uu/mcookie/src/mcookie.rs +++ b/src/uu/mcookie/src/mcookie.rs @@ -3,6 +3,8 @@ // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. +#[cfg(unix)] +use std::os::unix::fs::FileTypeExt; use std::{fs::File, io::Read}; use clap::{crate_version, Arg, ArgAction, Command}; @@ -57,7 +59,22 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { let mut handle = f.take(*max_bytes); handle.read_to_end(&mut buffer)?; } else { - f.read_to_end(&mut buffer)?; + #[cfg(unix)] + { + const DEFAULT_SEED_READ_BYTES: u64 = 1024; + let metadata = f.metadata()?; + + if metadata.file_type().is_char_device() { + let mut handle = f.take(DEFAULT_SEED_READ_BYTES); + handle.read_to_end(&mut buffer)?; + } else { + f.read_to_end(&mut buffer)?; + } + } + #[cfg(not(unix))] + { + f.read_to_end(&mut buffer)?; + } } if verbose { diff --git a/tests/by-util/test_mcookie.rs b/tests/by-util/test_mcookie.rs index 4766a95..e711c43 100644 --- a/tests/by-util/test_mcookie.rs +++ b/tests/by-util/test_mcookie.rs @@ -64,6 +64,31 @@ fn test_seed_files_and_max_size_raw() { )); } +#[test] +#[cfg(unix)] // Character devices like /dev/zero are a Unix concept +fn test_char_device_input() { + let res_no_limit = new_ucmd!().arg("-f").arg("/dev/zero").succeeds(); + + let stdout_no_limit = res_no_limit.no_stderr().stdout_str().trim_end(); + assert_eq!(stdout_no_limit.len(), 32); + assert!(stdout_no_limit.chars().all(|c| c.is_ascii_hexdigit())); + + let res_verbose = new_ucmd!() + .arg("--verbose") + .arg("-f") + .arg("/dev/zero") + .succeeds(); + + res_verbose.stderr_contains("Got 1024 bytes from /dev/zero"); + res_verbose.stderr_contains("Got 128 bytes from randomness source"); // Ensure internal randomness is still added + + let stdout_verbose = res_verbose.stdout_str().trim_end(); + assert_eq!(stdout_verbose.len(), 32); + assert!(stdout_verbose.chars().all(|c| c.is_ascii_hexdigit())); + + assert_ne!(stdout_no_limit, stdout_verbose); +} + #[test] fn test_seed_files_and_max_size_human_readable() { let mut file = NamedTempFile::new().unwrap();