mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 19:47:45 +00:00
Merge pull request #6907 from sylvestre/tr2
tr: generate an error for real if the input is a directory
This commit is contained in:
commit
d878f6c774
4 changed files with 45 additions and 4 deletions
|
@ -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"
|
||||
|
|
|
@ -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");
|
||||
|
@ -126,6 +126,10 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
|||
translating,
|
||||
)?;
|
||||
|
||||
if is_stdin_directory(&stdin) {
|
||||
return Err(USimpleError::new(1, "read error: Is a directory"));
|
||||
}
|
||||
|
||||
// '*_op' are the operations that need to be applied, in order.
|
||||
if delete_flag {
|
||||
if squeeze_flag {
|
||||
|
|
|
@ -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};
|
||||
|
@ -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"))]
|
||||
|
|
|
@ -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]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue