Skip to content

Commit

Permalink
tr: generate an error for real if the input is a directory
Browse files Browse the repository at this point in the history
  • Loading branch information
sylvestre committed Dec 3, 2024
1 parent 9dec29f commit 14cf462
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 4 deletions.
2 changes: 1 addition & 1 deletion src/uu/tr/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ path = "src/tr.rs"
[dependencies]
nom = { workspace = true }
clap = { workspace = true }
uucore = { workspace = true }
uucore = { workspace = true, features = ["fs"] }

[[bin]]
name = "tr"
Expand Down
13 changes: 10 additions & 3 deletions src/uu/tr/src/tr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@
mod operation;
mod unicode_table;

use crate::operation::DeleteOperation;
use clap::{crate_version, value_parser, Arg, ArgAction, Command};
use operation::{
translate_input, Sequence, SqueezeOperation, SymbolTranslator, TranslateOperation,
};
use std::ffi::OsString;
use std::io::{stdin, stdout, BufWriter};
use uucore::{format_usage, help_about, help_section, help_usage, os_str_as_bytes, show};

use crate::operation::DeleteOperation;
use uucore::display::Quotable;
use uucore::error::{UResult, USimpleError, UUsageError};
use uucore::fs::is_stdin_directory;
use uucore::{format_usage, help_about, help_section, help_usage, os_str_as_bytes, show};

const ABOUT: &str = help_about!("tr.md");
const AFTER_HELP: &str = help_section!("after help", "tr.md");
Expand Down Expand Up @@ -126,6 +126,13 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
translating,
)?;

if is_stdin_directory(&stdin) {
return Err(USimpleError::new(
1,
format!("{}: read error: Is a directory", uucore::util_name()),
));
}

// '*_op' are the operations that need to be applied, in order.
if delete_flag {
if squeeze_flag {
Expand Down
29 changes: 29 additions & 0 deletions src/uucore/src/lib/features/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use std::ffi::{OsStr, OsString};
use std::fs;
use std::fs::read_dir;
use std::hash::Hash;
use std::io::Stdin;
use std::io::{Error, ErrorKind, Result as IOResult};
#[cfg(unix)]
use std::os::unix::{fs::MetadataExt, io::AsRawFd};
Expand Down Expand Up @@ -721,6 +722,34 @@ pub fn path_ends_with_terminator(path: &Path) -> bool {
.map_or(false, |wide| wide == b'/'.into() || wide == b'\\'.into())
}

/// Checks if the standard input (stdin) is a directory.
///
/// # Arguments
///
/// * `stdin` - A reference to the standard input handle.
///
/// # Returns
///
/// * `bool` - Returns `true` if stdin is a directory, `false` otherwise.
pub fn is_stdin_directory(stdin: &Stdin) -> bool {
#[cfg(unix)]
{
use nix::sys::stat::fstat;
let mode = fstat(stdin.as_raw_fd()).unwrap().st_mode as mode_t;
has!(mode, S_IFDIR)
}

#[cfg(windows)]
{
use std::os::windows::io::AsRawHandle;
let handle = stdin.as_raw_handle();
if let Ok(metadata) = fs::metadata(format!("{}", handle as usize)) {
return metadata.is_dir();
}
false
}
}

pub mod sane_blksize {

#[cfg(not(target_os = "windows"))]
Expand Down
8 changes: 8 additions & 0 deletions tests/by-util/test_tr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ fn test_invalid_input() {
.fails()
.code_is(1)
.stderr_contains("tr: extra operand '<'");
#[cfg(unix)]
new_ucmd!()
.args(&["1", "1"])
// will test "tr 1 1 < ."
.set_stdin(std::process::Stdio::from(std::fs::File::open(".").unwrap()))
.fails()
.code_is(1)
.stderr_contains("tr: read error: Is a directory");
}

#[test]
Expand Down

0 comments on commit 14cf462

Please sign in to comment.