Repository: uutils/coreutils (language: rust)

Issue:
dd: should error on reading stdin when iflag=directory option is given
GNU coreutils dd 9.4.113-c01ee

```sh
$ : | dd iflag=directory
dd: setting flags for 'standard input': Not a directory
```

uutils dd:

```sh
$ : | ./target/debug/dd iflag=directory
0+0 records in
0+0 records out
0 bytes copied, 2.37402e-04 s, 0.0 B/s
```

Test case found in GNU test suite `tests/dd/misc.sh`.

*Edit:* tested on Ubuntu 20.04, where the `iflag=directory` option is allowed.


Discussion / hints:
Hello @jfinkels, I tested this issue on current main

And get output 
```sh
$ : | ./target/debug/coreutils dd iflag=directory
dd: feature not implemented on this system -> directory
```

May be this issue to close?
I should have mentioned in the description that I am testing on Ubuntu, so the `iflag=directory` option should be allowed. I'll update the description to mention my environment. On my machine, the issue remains.
This does seem to error as expected when a file is redirected to stdin:
```
$ touch f && < f ./target/debug/dd iflag=directory count=0
./target/debug/dd: standard input: not a directory
```
(The error message differs from that of GNU dd though)

Fix patch:
diff --git a/src/uu/dd/src/dd.rs b/src/uu/dd/src/dd.rs
index ca8c2a8b570..aaa4684617a 100644
--- a/src/uu/dd/src/dd.rs
+++ b/src/uu/dd/src/dd.rs
@@ -54,7 +54,7 @@ use nix::{
 };
 use uucore::display::Quotable;
 #[cfg(unix)]
-use uucore::error::set_exit_code;
+use uucore::error::{set_exit_code, USimpleError};
 use uucore::error::{FromIo, UResult};
 #[cfg(target_os = "linux")]
 use uucore::show_if_err;
@@ -338,11 +338,11 @@ impl<'a> Input<'a> {
         let mut src = Source::stdin_as_file();
         #[cfg(unix)]
         if let Source::StdinFile(f) = &src {
-            // GNU compatibility:
-            // this will check whether stdin points to a folder or not
-            if f.metadata()?.is_file() && settings.iflags.directory {
-                show_error!("standard input: not a directory");
-                return Err(1.into());
+            if settings.iflags.directory && !f.metadata()?.is_dir() {
+                return Err(USimpleError::new(
+                    1,
+                    "setting flags for 'standard input': Not a directory",
+                ));
             }
         };
         if settings.skip > 0 {


Test patch:
diff --git a/tests/by-util/test_dd.rs b/tests/by-util/test_dd.rs
index 64ca7603bf7..57a2933201e 100644
--- a/tests/by-util/test_dd.rs
+++ b/tests/by-util/test_dd.rs
@@ -1728,7 +1728,26 @@ fn test_iflag_directory_fails_when_file_is_passed_via_std_in() {
         .args(&["iflag=directory", "count=0"])
         .set_stdin(std::process::Stdio::from(File::open(filename).unwrap()))
         .fails()
-        .stderr_contains("standard input: not a directory");
+        .stderr_only("dd: setting flags for 'standard input': Not a directory\n");
+}
+
+#[test]
+#[cfg(any(target_os = "linux", target_os = "android"))]
+fn test_iflag_directory_passes_when_dir_is_redirected() {
+    new_ucmd!()
+        .args(&["iflag=directory", "count=0"])
+        .set_stdin(std::process::Stdio::from(File::open(".").unwrap()))
+        .succeeds();
+}
+
+#[test]
+#[cfg(any(target_os = "linux", target_os = "android"))]
+fn test_iflag_directory_fails_when_file_is_piped_via_std_in() {
+    new_ucmd!()
+        .arg("iflag=directory")
+        .pipe_in("")
+        .fails()
+        .stderr_only("dd: setting flags for 'standard input': Not a directory\n");
 }
 
 #[test]