mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 03:27:44 +00:00
tr: generate an error for real if the input is a directory
This commit is contained in:
parent
8a481ccf1c
commit
3e4221a461
4 changed files with 45 additions and 4 deletions
|
@ -19,7 +19,7 @@ path = "src/tr.rs"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
nom = { workspace = true }
|
nom = { workspace = true }
|
||||||
clap = { workspace = true }
|
clap = { workspace = true }
|
||||||
uucore = { workspace = true }
|
uucore = { workspace = true, features = ["fs"] }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "tr"
|
name = "tr"
|
||||||
|
|
|
@ -8,17 +8,17 @@
|
||||||
mod operation;
|
mod operation;
|
||||||
mod unicode_table;
|
mod unicode_table;
|
||||||
|
|
||||||
|
use crate::operation::DeleteOperation;
|
||||||
use clap::{crate_version, value_parser, Arg, ArgAction, Command};
|
use clap::{crate_version, value_parser, Arg, ArgAction, Command};
|
||||||
use operation::{
|
use operation::{
|
||||||
translate_input, Sequence, SqueezeOperation, SymbolTranslator, TranslateOperation,
|
translate_input, Sequence, SqueezeOperation, SymbolTranslator, TranslateOperation,
|
||||||
};
|
};
|
||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
use std::io::{stdin, stdout, BufWriter};
|
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::display::Quotable;
|
||||||
use uucore::error::{UResult, USimpleError, UUsageError};
|
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 ABOUT: &str = help_about!("tr.md");
|
||||||
const AFTER_HELP: &str = help_section!("after help", "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,
|
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.
|
// '*_op' are the operations that need to be applied, in order.
|
||||||
if delete_flag {
|
if delete_flag {
|
||||||
if squeeze_flag {
|
if squeeze_flag {
|
||||||
|
|
|
@ -20,6 +20,7 @@ use std::ffi::{OsStr, OsString};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::fs::read_dir;
|
use std::fs::read_dir;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
use std::io::Stdin;
|
||||||
use std::io::{Error, ErrorKind, Result as IOResult};
|
use std::io::{Error, ErrorKind, Result as IOResult};
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use std::os::unix::{fs::MetadataExt, io::AsRawFd};
|
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())
|
.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 {
|
pub mod sane_blksize {
|
||||||
|
|
||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
|
|
@ -20,6 +20,14 @@ fn test_invalid_input() {
|
||||||
.fails()
|
.fails()
|
||||||
.code_is(1)
|
.code_is(1)
|
||||||
.stderr_contains("tr: extra operand '<'");
|
.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]
|
#[test]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue