mirror of
https://github.com/uutils/coreutils.git
synced 2026-05-06 07:26:38 -04:00
tty: support printing msys2 tty path
This commit is contained in:
committed by
Daniel Hofstetter
parent
b3d8706a2c
commit
a07879b8ab
@@ -61,6 +61,7 @@ MinGW
|
||||
Minix
|
||||
MS-DOS
|
||||
MSDOS
|
||||
msys
|
||||
NetBSD
|
||||
Novell
|
||||
Nushell
|
||||
|
||||
Generated
+1
@@ -4374,6 +4374,7 @@ dependencies = [
|
||||
"fluent",
|
||||
"rustix",
|
||||
"uucore",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -27,6 +27,12 @@ fluent = { workspace = true }
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
rustix = { workspace = true, features = ["fs", "termios"] }
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
windows-sys = { workspace = true, features = [
|
||||
"Win32_Storage_FileSystem",
|
||||
"Win32_Foundation",
|
||||
] }
|
||||
|
||||
[[bin]]
|
||||
name = "tty"
|
||||
path = "src/main.rs"
|
||||
|
||||
+52
-5
@@ -58,11 +58,20 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
writeln!(stdout, "{}", translate!("tty-not-a-tty"))
|
||||
};
|
||||
#[cfg(target_os = "windows")]
|
||||
let write_result = if std::io::stdin().is_terminal() {
|
||||
writeln!(stdout, r"\\.\CON")
|
||||
} else {
|
||||
set_exit_code(1);
|
||||
writeln!(stdout, "{}", translate!("tty-not-a-tty"))
|
||||
let write_result = {
|
||||
use std::os::windows::io::AsHandle;
|
||||
let stdin = std::io::stdin();
|
||||
let stdin_handle = stdin.as_handle();
|
||||
if stdin_handle.is_terminal() {
|
||||
writeln!(
|
||||
stdout,
|
||||
"{}",
|
||||
file_name(stdin_handle).as_deref().unwrap_or(r"\\.\CON")
|
||||
)
|
||||
} else {
|
||||
set_exit_code(1);
|
||||
writeln!(stdout, "{}", translate!("tty-not-a-tty"))
|
||||
}
|
||||
};
|
||||
|
||||
if write_result.is_err() || stdout.flush().is_err() {
|
||||
@@ -74,6 +83,44 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
fn file_name(handle: std::os::windows::io::BorrowedHandle) -> Option<String> {
|
||||
// This code is adapted from rust's standard library
|
||||
// https://github.com/rust-lang/rust/blob/0424cc16731e6141a18077f8ccde77ba148d9649/library/std/src/sys/io/is_terminal/windows.rs#L25
|
||||
use std::mem::MaybeUninit;
|
||||
use std::os::windows::io::AsRawHandle;
|
||||
use windows_sys::Win32::Foundation::MAX_PATH;
|
||||
use windows_sys::Win32::Storage::FileSystem::{FileNameInfo, GetFileInformationByHandleEx};
|
||||
// Manually define FILE_NAME_INFO so we can more easily construct a stack buffer.
|
||||
#[repr(C)]
|
||||
#[allow(non_snake_case)]
|
||||
struct FILE_NAME_INFO {
|
||||
FileNameLength: u32,
|
||||
FileName: [MaybeUninit<u16>; MAX_PATH as usize],
|
||||
}
|
||||
let mut name = FILE_NAME_INFO {
|
||||
FileNameLength: 0,
|
||||
FileName: [MaybeUninit::uninit(); MAX_PATH as usize],
|
||||
};
|
||||
unsafe {
|
||||
let result = GetFileInformationByHandleEx(
|
||||
handle.as_raw_handle(),
|
||||
FileNameInfo,
|
||||
(&raw mut name).cast(),
|
||||
size_of::<FILE_NAME_INFO>() as u32,
|
||||
);
|
||||
if result == 0 {
|
||||
None
|
||||
} else {
|
||||
let name = name.FileName.get(..name.FileNameLength as usize / 2)?;
|
||||
// SAFETY: all elements up to FileNameLength have been initialized
|
||||
let name: &[u16] = &*(std::ptr::from_ref::<[MaybeUninit<u16>]>(name) as *const [u16]);
|
||||
// This should never fail for a valid msys terminal because they use ASCII names.
|
||||
String::from_utf16(name).ok()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn uu_app() -> Command {
|
||||
let cmd = Command::new("tty")
|
||||
.version(uucore::crate_version!())
|
||||
|
||||
Reference in New Issue
Block a user