1d0b88b7eSopenharmony_ci//! is-terminal is a simple utility that answers one question: 2d0b88b7eSopenharmony_ci//! 3d0b88b7eSopenharmony_ci//! > Is this a terminal? 4d0b88b7eSopenharmony_ci//! 5d0b88b7eSopenharmony_ci//! A "terminal", also known as a "tty", is an I/O device which may be 6d0b88b7eSopenharmony_ci//! interactive and may support color and other special features. This crate 7d0b88b7eSopenharmony_ci//! doesn't provide any of those features; it just answers this one question. 8d0b88b7eSopenharmony_ci//! 9d0b88b7eSopenharmony_ci//! On Unix-family platforms, this is effectively the same as the [`isatty`] 10d0b88b7eSopenharmony_ci//! function for testing whether a given stream is a terminal, though it 11d0b88b7eSopenharmony_ci//! accepts high-level stream types instead of raw file descriptors. 12d0b88b7eSopenharmony_ci//! 13d0b88b7eSopenharmony_ci//! On Windows, it uses a variety of techniques to determine whether the 14d0b88b7eSopenharmony_ci//! given stream is a terminal. 15d0b88b7eSopenharmony_ci//! 16d0b88b7eSopenharmony_ci//! # Example 17d0b88b7eSopenharmony_ci//! 18d0b88b7eSopenharmony_ci//! ```rust 19d0b88b7eSopenharmony_ci//! use is_terminal::IsTerminal; 20d0b88b7eSopenharmony_ci//! 21d0b88b7eSopenharmony_ci//! if std::io::stdout().is_terminal() { 22d0b88b7eSopenharmony_ci//! println!("stdout is a terminal") 23d0b88b7eSopenharmony_ci//! } 24d0b88b7eSopenharmony_ci//! ``` 25d0b88b7eSopenharmony_ci//! 26d0b88b7eSopenharmony_ci//! [`isatty`]: https://man7.org/linux/man-pages/man3/isatty.3.html 27d0b88b7eSopenharmony_ci 28d0b88b7eSopenharmony_ci#![cfg_attr(unix, no_std)] 29d0b88b7eSopenharmony_ci 30d0b88b7eSopenharmony_ci#[cfg(not(target_os = "unknown"))] 31d0b88b7eSopenharmony_ciuse io_lifetimes::AsFilelike; 32d0b88b7eSopenharmony_ci#[cfg(windows)] 33d0b88b7eSopenharmony_ciuse io_lifetimes::BorrowedHandle; 34d0b88b7eSopenharmony_ci#[cfg(windows)] 35d0b88b7eSopenharmony_ciuse windows_sys::Win32::Foundation::HANDLE; 36d0b88b7eSopenharmony_ci#[cfg(windows)] 37d0b88b7eSopenharmony_ciuse windows_sys::Win32::System::Console::STD_HANDLE; 38d0b88b7eSopenharmony_ci 39d0b88b7eSopenharmony_cipub trait IsTerminal { 40d0b88b7eSopenharmony_ci /// Returns true if this is a terminal. 41d0b88b7eSopenharmony_ci /// 42d0b88b7eSopenharmony_ci /// # Example 43d0b88b7eSopenharmony_ci /// 44d0b88b7eSopenharmony_ci /// ``` 45d0b88b7eSopenharmony_ci /// use is_terminal::IsTerminal; 46d0b88b7eSopenharmony_ci /// 47d0b88b7eSopenharmony_ci /// if std::io::stdout().is_terminal() { 48d0b88b7eSopenharmony_ci /// println!("stdout is a terminal") 49d0b88b7eSopenharmony_ci /// } 50d0b88b7eSopenharmony_ci /// ``` 51d0b88b7eSopenharmony_ci fn is_terminal(&self) -> bool; 52d0b88b7eSopenharmony_ci} 53d0b88b7eSopenharmony_ci 54d0b88b7eSopenharmony_ci#[cfg(not(target_os = "unknown"))] 55d0b88b7eSopenharmony_ciimpl<Stream: AsFilelike> IsTerminal for Stream { 56d0b88b7eSopenharmony_ci #[inline] 57d0b88b7eSopenharmony_ci fn is_terminal(&self) -> bool { 58d0b88b7eSopenharmony_ci #[cfg(any(unix, target_os = "wasi"))] 59d0b88b7eSopenharmony_ci { 60d0b88b7eSopenharmony_ci rustix::termios::isatty(self) 61d0b88b7eSopenharmony_ci } 62d0b88b7eSopenharmony_ci 63d0b88b7eSopenharmony_ci #[cfg(target_os = "hermit")] 64d0b88b7eSopenharmony_ci { 65d0b88b7eSopenharmony_ci hermit_abi::isatty(self.as_filelike().as_fd()) 66d0b88b7eSopenharmony_ci } 67d0b88b7eSopenharmony_ci 68d0b88b7eSopenharmony_ci #[cfg(windows)] 69d0b88b7eSopenharmony_ci { 70d0b88b7eSopenharmony_ci _is_terminal(self.as_filelike()) 71d0b88b7eSopenharmony_ci } 72d0b88b7eSopenharmony_ci } 73d0b88b7eSopenharmony_ci} 74d0b88b7eSopenharmony_ci 75d0b88b7eSopenharmony_ci// The Windows implementation here is copied from atty, with #51 and #54 76d0b88b7eSopenharmony_ci// applied. The only significant modification is to take a `BorrowedHandle` 77d0b88b7eSopenharmony_ci// argument instead of using a `Stream` enum. 78d0b88b7eSopenharmony_ci 79d0b88b7eSopenharmony_ci#[cfg(windows)] 80d0b88b7eSopenharmony_cifn _is_terminal(stream: BorrowedHandle<'_>) -> bool { 81d0b88b7eSopenharmony_ci use std::os::windows::io::AsRawHandle; 82d0b88b7eSopenharmony_ci use windows_sys::Win32::System::Console::GetStdHandle; 83d0b88b7eSopenharmony_ci use windows_sys::Win32::System::Console::{ 84d0b88b7eSopenharmony_ci STD_ERROR_HANDLE as STD_ERROR, STD_INPUT_HANDLE as STD_INPUT, 85d0b88b7eSopenharmony_ci STD_OUTPUT_HANDLE as STD_OUTPUT, 86d0b88b7eSopenharmony_ci }; 87d0b88b7eSopenharmony_ci 88d0b88b7eSopenharmony_ci let (fd, others) = unsafe { 89d0b88b7eSopenharmony_ci if stream.as_raw_handle() == GetStdHandle(STD_INPUT) as _ { 90d0b88b7eSopenharmony_ci (STD_INPUT, [STD_ERROR, STD_OUTPUT]) 91d0b88b7eSopenharmony_ci } else if stream.as_raw_handle() == GetStdHandle(STD_OUTPUT) as _ { 92d0b88b7eSopenharmony_ci (STD_OUTPUT, [STD_INPUT, STD_ERROR]) 93d0b88b7eSopenharmony_ci } else if stream.as_raw_handle() == GetStdHandle(STD_ERROR) as _ { 94d0b88b7eSopenharmony_ci (STD_ERROR, [STD_INPUT, STD_OUTPUT]) 95d0b88b7eSopenharmony_ci } else { 96d0b88b7eSopenharmony_ci return false; 97d0b88b7eSopenharmony_ci } 98d0b88b7eSopenharmony_ci }; 99d0b88b7eSopenharmony_ci if unsafe { console_on_any(&[fd]) } { 100d0b88b7eSopenharmony_ci // False positives aren't possible. If we got a console then 101d0b88b7eSopenharmony_ci // we definitely have a tty on stdin. 102d0b88b7eSopenharmony_ci return true; 103d0b88b7eSopenharmony_ci } 104d0b88b7eSopenharmony_ci 105d0b88b7eSopenharmony_ci // At this point, we *could* have a false negative. We can determine that 106d0b88b7eSopenharmony_ci // this is true negative if we can detect the presence of a console on 107d0b88b7eSopenharmony_ci // any of the other streams. If another stream has a console, then we know 108d0b88b7eSopenharmony_ci // we're in a Windows console and can therefore trust the negative. 109d0b88b7eSopenharmony_ci if unsafe { console_on_any(&others) } { 110d0b88b7eSopenharmony_ci return false; 111d0b88b7eSopenharmony_ci } 112d0b88b7eSopenharmony_ci 113d0b88b7eSopenharmony_ci // Otherwise, we fall back to a very strange msys hack to see if we can 114d0b88b7eSopenharmony_ci // sneakily detect the presence of a tty. 115d0b88b7eSopenharmony_ci // Safety: function has no invariants. an invalid handle id will cause 116d0b88b7eSopenharmony_ci // GetFileInformationByHandleEx to return an error. 117d0b88b7eSopenharmony_ci let handle = unsafe { GetStdHandle(fd) }; 118d0b88b7eSopenharmony_ci unsafe { msys_tty_on(handle) } 119d0b88b7eSopenharmony_ci} 120d0b88b7eSopenharmony_ci 121d0b88b7eSopenharmony_ci/// Returns true if any of the given fds are on a console. 122d0b88b7eSopenharmony_ci#[cfg(windows)] 123d0b88b7eSopenharmony_ciunsafe fn console_on_any(fds: &[STD_HANDLE]) -> bool { 124d0b88b7eSopenharmony_ci use windows_sys::Win32::System::Console::{GetConsoleMode, GetStdHandle}; 125d0b88b7eSopenharmony_ci 126d0b88b7eSopenharmony_ci for &fd in fds { 127d0b88b7eSopenharmony_ci let mut out = 0; 128d0b88b7eSopenharmony_ci let handle = GetStdHandle(fd); 129d0b88b7eSopenharmony_ci if GetConsoleMode(handle, &mut out) != 0 { 130d0b88b7eSopenharmony_ci return true; 131d0b88b7eSopenharmony_ci } 132d0b88b7eSopenharmony_ci } 133d0b88b7eSopenharmony_ci false 134d0b88b7eSopenharmony_ci} 135d0b88b7eSopenharmony_ci 136d0b88b7eSopenharmony_ci/// Returns true if there is an MSYS tty on the given handle. 137d0b88b7eSopenharmony_ci#[cfg(windows)] 138d0b88b7eSopenharmony_ciunsafe fn msys_tty_on(handle: HANDLE) -> bool { 139d0b88b7eSopenharmony_ci use std::ffi::c_void; 140d0b88b7eSopenharmony_ci use windows_sys::Win32::{ 141d0b88b7eSopenharmony_ci Foundation::MAX_PATH, 142d0b88b7eSopenharmony_ci Storage::FileSystem::{FileNameInfo, GetFileInformationByHandleEx}, 143d0b88b7eSopenharmony_ci }; 144d0b88b7eSopenharmony_ci 145d0b88b7eSopenharmony_ci /// Mirrors windows_sys::Win32::Storage::FileSystem::FILE_NAME_INFO, giving 146d0b88b7eSopenharmony_ci /// it a fixed length that we can stack allocate 147d0b88b7eSopenharmony_ci #[repr(C)] 148d0b88b7eSopenharmony_ci #[allow(non_snake_case)] 149d0b88b7eSopenharmony_ci struct FILE_NAME_INFO { 150d0b88b7eSopenharmony_ci FileNameLength: u32, 151d0b88b7eSopenharmony_ci FileName: [u16; MAX_PATH as usize], 152d0b88b7eSopenharmony_ci } 153d0b88b7eSopenharmony_ci let mut name_info = FILE_NAME_INFO { 154d0b88b7eSopenharmony_ci FileNameLength: 0, 155d0b88b7eSopenharmony_ci FileName: [0; MAX_PATH as usize], 156d0b88b7eSopenharmony_ci }; 157d0b88b7eSopenharmony_ci // Safety: buffer length is fixed. 158d0b88b7eSopenharmony_ci let res = GetFileInformationByHandleEx( 159d0b88b7eSopenharmony_ci handle, 160d0b88b7eSopenharmony_ci FileNameInfo, 161d0b88b7eSopenharmony_ci &mut name_info as *mut _ as *mut c_void, 162d0b88b7eSopenharmony_ci std::mem::size_of::<FILE_NAME_INFO>() as u32, 163d0b88b7eSopenharmony_ci ); 164d0b88b7eSopenharmony_ci if res == 0 { 165d0b88b7eSopenharmony_ci return false; 166d0b88b7eSopenharmony_ci } 167d0b88b7eSopenharmony_ci 168d0b88b7eSopenharmony_ci let s = &name_info.FileName[..name_info.FileNameLength as usize / 2]; 169d0b88b7eSopenharmony_ci let name = String::from_utf16_lossy(s); 170d0b88b7eSopenharmony_ci // This checks whether 'pty' exists in the file name, which indicates that 171d0b88b7eSopenharmony_ci // a pseudo-terminal is attached. To mitigate against false positives 172d0b88b7eSopenharmony_ci // (e.g., an actual file name that contains 'pty'), we also require that 173d0b88b7eSopenharmony_ci // either the strings 'msys-' or 'cygwin-' are in the file name as well.) 174d0b88b7eSopenharmony_ci let is_msys = name.contains("msys-") || name.contains("cygwin-"); 175d0b88b7eSopenharmony_ci let is_pty = name.contains("-pty"); 176d0b88b7eSopenharmony_ci is_msys && is_pty 177d0b88b7eSopenharmony_ci} 178d0b88b7eSopenharmony_ci 179d0b88b7eSopenharmony_ci#[cfg(target_os = "unknown")] 180d0b88b7eSopenharmony_ciimpl IsTerminal for std::io::Stdin { 181d0b88b7eSopenharmony_ci #[inline] 182d0b88b7eSopenharmony_ci fn is_terminal(&self) -> bool { 183d0b88b7eSopenharmony_ci false 184d0b88b7eSopenharmony_ci } 185d0b88b7eSopenharmony_ci} 186d0b88b7eSopenharmony_ci 187d0b88b7eSopenharmony_ci#[cfg(target_os = "unknown")] 188d0b88b7eSopenharmony_ciimpl IsTerminal for std::io::Stdout { 189d0b88b7eSopenharmony_ci #[inline] 190d0b88b7eSopenharmony_ci fn is_terminal(&self) -> bool { 191d0b88b7eSopenharmony_ci false 192d0b88b7eSopenharmony_ci } 193d0b88b7eSopenharmony_ci} 194d0b88b7eSopenharmony_ci 195d0b88b7eSopenharmony_ci#[cfg(target_os = "unknown")] 196d0b88b7eSopenharmony_ciimpl IsTerminal for std::io::Stderr { 197d0b88b7eSopenharmony_ci #[inline] 198d0b88b7eSopenharmony_ci fn is_terminal(&self) -> bool { 199d0b88b7eSopenharmony_ci false 200d0b88b7eSopenharmony_ci } 201d0b88b7eSopenharmony_ci} 202d0b88b7eSopenharmony_ci 203d0b88b7eSopenharmony_ci#[cfg(target_os = "unknown")] 204d0b88b7eSopenharmony_ciimpl<'a> IsTerminal for std::io::StdinLock<'a> { 205d0b88b7eSopenharmony_ci #[inline] 206d0b88b7eSopenharmony_ci fn is_terminal(&self) -> bool { 207d0b88b7eSopenharmony_ci false 208d0b88b7eSopenharmony_ci } 209d0b88b7eSopenharmony_ci} 210d0b88b7eSopenharmony_ci 211d0b88b7eSopenharmony_ci#[cfg(target_os = "unknown")] 212d0b88b7eSopenharmony_ciimpl<'a> IsTerminal for std::io::StdoutLock<'a> { 213d0b88b7eSopenharmony_ci #[inline] 214d0b88b7eSopenharmony_ci fn is_terminal(&self) -> bool { 215d0b88b7eSopenharmony_ci false 216d0b88b7eSopenharmony_ci } 217d0b88b7eSopenharmony_ci} 218d0b88b7eSopenharmony_ci 219d0b88b7eSopenharmony_ci#[cfg(target_os = "unknown")] 220d0b88b7eSopenharmony_ciimpl<'a> IsTerminal for std::io::StderrLock<'a> { 221d0b88b7eSopenharmony_ci #[inline] 222d0b88b7eSopenharmony_ci fn is_terminal(&self) -> bool { 223d0b88b7eSopenharmony_ci false 224d0b88b7eSopenharmony_ci } 225d0b88b7eSopenharmony_ci} 226d0b88b7eSopenharmony_ci 227d0b88b7eSopenharmony_ci#[cfg(target_os = "unknown")] 228d0b88b7eSopenharmony_ciimpl<'a> IsTerminal for std::fs::File { 229d0b88b7eSopenharmony_ci #[inline] 230d0b88b7eSopenharmony_ci fn is_terminal(&self) -> bool { 231d0b88b7eSopenharmony_ci false 232d0b88b7eSopenharmony_ci } 233d0b88b7eSopenharmony_ci} 234d0b88b7eSopenharmony_ci 235d0b88b7eSopenharmony_ci#[cfg(target_os = "unknown")] 236d0b88b7eSopenharmony_ciimpl IsTerminal for std::process::ChildStdin { 237d0b88b7eSopenharmony_ci #[inline] 238d0b88b7eSopenharmony_ci fn is_terminal(&self) -> bool { 239d0b88b7eSopenharmony_ci false 240d0b88b7eSopenharmony_ci } 241d0b88b7eSopenharmony_ci} 242d0b88b7eSopenharmony_ci 243d0b88b7eSopenharmony_ci#[cfg(target_os = "unknown")] 244d0b88b7eSopenharmony_ciimpl IsTerminal for std::process::ChildStdout { 245d0b88b7eSopenharmony_ci #[inline] 246d0b88b7eSopenharmony_ci fn is_terminal(&self) -> bool { 247d0b88b7eSopenharmony_ci false 248d0b88b7eSopenharmony_ci } 249d0b88b7eSopenharmony_ci} 250d0b88b7eSopenharmony_ci 251d0b88b7eSopenharmony_ci#[cfg(target_os = "unknown")] 252d0b88b7eSopenharmony_ciimpl IsTerminal for std::process::ChildStderr { 253d0b88b7eSopenharmony_ci #[inline] 254d0b88b7eSopenharmony_ci fn is_terminal(&self) -> bool { 255d0b88b7eSopenharmony_ci false 256d0b88b7eSopenharmony_ci } 257d0b88b7eSopenharmony_ci} 258d0b88b7eSopenharmony_ci 259d0b88b7eSopenharmony_ci#[cfg(test)] 260d0b88b7eSopenharmony_cimod tests { 261d0b88b7eSopenharmony_ci #[cfg(not(target_os = "unknown"))] 262d0b88b7eSopenharmony_ci use super::IsTerminal; 263d0b88b7eSopenharmony_ci 264d0b88b7eSopenharmony_ci #[test] 265d0b88b7eSopenharmony_ci #[cfg(windows)] 266d0b88b7eSopenharmony_ci fn stdin() { 267d0b88b7eSopenharmony_ci assert_eq!( 268d0b88b7eSopenharmony_ci atty::is(atty::Stream::Stdin), 269d0b88b7eSopenharmony_ci std::io::stdin().is_terminal() 270d0b88b7eSopenharmony_ci ) 271d0b88b7eSopenharmony_ci } 272d0b88b7eSopenharmony_ci 273d0b88b7eSopenharmony_ci #[test] 274d0b88b7eSopenharmony_ci #[cfg(windows)] 275d0b88b7eSopenharmony_ci fn stdout() { 276d0b88b7eSopenharmony_ci assert_eq!( 277d0b88b7eSopenharmony_ci atty::is(atty::Stream::Stdout), 278d0b88b7eSopenharmony_ci std::io::stdout().is_terminal() 279d0b88b7eSopenharmony_ci ) 280d0b88b7eSopenharmony_ci } 281d0b88b7eSopenharmony_ci 282d0b88b7eSopenharmony_ci #[test] 283d0b88b7eSopenharmony_ci #[cfg(windows)] 284d0b88b7eSopenharmony_ci fn stderr() { 285d0b88b7eSopenharmony_ci assert_eq!( 286d0b88b7eSopenharmony_ci atty::is(atty::Stream::Stderr), 287d0b88b7eSopenharmony_ci std::io::stderr().is_terminal() 288d0b88b7eSopenharmony_ci ) 289d0b88b7eSopenharmony_ci } 290d0b88b7eSopenharmony_ci 291d0b88b7eSopenharmony_ci #[test] 292d0b88b7eSopenharmony_ci #[cfg(any(unix, target_os = "wasi"))] 293d0b88b7eSopenharmony_ci fn stdin() { 294d0b88b7eSopenharmony_ci unsafe { 295d0b88b7eSopenharmony_ci assert_eq!( 296d0b88b7eSopenharmony_ci atty::is(atty::Stream::Stdin), 297d0b88b7eSopenharmony_ci rustix::io::stdin().is_terminal() 298d0b88b7eSopenharmony_ci ) 299d0b88b7eSopenharmony_ci } 300d0b88b7eSopenharmony_ci } 301d0b88b7eSopenharmony_ci 302d0b88b7eSopenharmony_ci #[test] 303d0b88b7eSopenharmony_ci #[cfg(any(unix, target_os = "wasi"))] 304d0b88b7eSopenharmony_ci fn stdout() { 305d0b88b7eSopenharmony_ci unsafe { 306d0b88b7eSopenharmony_ci assert_eq!( 307d0b88b7eSopenharmony_ci atty::is(atty::Stream::Stdout), 308d0b88b7eSopenharmony_ci rustix::io::stdout().is_terminal() 309d0b88b7eSopenharmony_ci ) 310d0b88b7eSopenharmony_ci } 311d0b88b7eSopenharmony_ci } 312d0b88b7eSopenharmony_ci 313d0b88b7eSopenharmony_ci #[test] 314d0b88b7eSopenharmony_ci #[cfg(any(unix, target_os = "wasi"))] 315d0b88b7eSopenharmony_ci fn stderr() { 316d0b88b7eSopenharmony_ci unsafe { 317d0b88b7eSopenharmony_ci assert_eq!( 318d0b88b7eSopenharmony_ci atty::is(atty::Stream::Stderr), 319d0b88b7eSopenharmony_ci rustix::io::stderr().is_terminal() 320d0b88b7eSopenharmony_ci ) 321d0b88b7eSopenharmony_ci } 322d0b88b7eSopenharmony_ci } 323d0b88b7eSopenharmony_ci 324d0b88b7eSopenharmony_ci #[test] 325d0b88b7eSopenharmony_ci #[cfg(any(unix, target_os = "wasi"))] 326d0b88b7eSopenharmony_ci fn stdin_vs_libc() { 327d0b88b7eSopenharmony_ci unsafe { 328d0b88b7eSopenharmony_ci assert_eq!( 329d0b88b7eSopenharmony_ci libc::isatty(libc::STDIN_FILENO) != 0, 330d0b88b7eSopenharmony_ci rustix::io::stdin().is_terminal() 331d0b88b7eSopenharmony_ci ) 332d0b88b7eSopenharmony_ci } 333d0b88b7eSopenharmony_ci } 334d0b88b7eSopenharmony_ci 335d0b88b7eSopenharmony_ci #[test] 336d0b88b7eSopenharmony_ci #[cfg(any(unix, target_os = "wasi"))] 337d0b88b7eSopenharmony_ci fn stdout_vs_libc() { 338d0b88b7eSopenharmony_ci unsafe { 339d0b88b7eSopenharmony_ci assert_eq!( 340d0b88b7eSopenharmony_ci libc::isatty(libc::STDOUT_FILENO) != 0, 341d0b88b7eSopenharmony_ci rustix::io::stdout().is_terminal() 342d0b88b7eSopenharmony_ci ) 343d0b88b7eSopenharmony_ci } 344d0b88b7eSopenharmony_ci } 345d0b88b7eSopenharmony_ci 346d0b88b7eSopenharmony_ci #[test] 347d0b88b7eSopenharmony_ci #[cfg(any(unix, target_os = "wasi"))] 348d0b88b7eSopenharmony_ci fn stderr_vs_libc() { 349d0b88b7eSopenharmony_ci unsafe { 350d0b88b7eSopenharmony_ci assert_eq!( 351d0b88b7eSopenharmony_ci libc::isatty(libc::STDERR_FILENO) != 0, 352d0b88b7eSopenharmony_ci rustix::io::stderr().is_terminal() 353d0b88b7eSopenharmony_ci ) 354d0b88b7eSopenharmony_ci } 355d0b88b7eSopenharmony_ci } 356d0b88b7eSopenharmony_ci 357d0b88b7eSopenharmony_ci // Verify that the msys_tty_on function works with long path. 358d0b88b7eSopenharmony_ci #[test] 359d0b88b7eSopenharmony_ci #[cfg(windows)] 360d0b88b7eSopenharmony_ci fn msys_tty_on_path_length() { 361d0b88b7eSopenharmony_ci use std::{fs::File, os::windows::io::AsRawHandle}; 362d0b88b7eSopenharmony_ci use windows_sys::Win32::Foundation::MAX_PATH; 363d0b88b7eSopenharmony_ci 364d0b88b7eSopenharmony_ci let dir = tempfile::tempdir().expect("Unable to create temporary directory"); 365d0b88b7eSopenharmony_ci let file_path = dir.path().join("ten_chars_".repeat(25)); 366d0b88b7eSopenharmony_ci // Ensure that the path is longer than MAX_PATH. 367d0b88b7eSopenharmony_ci assert!(file_path.to_string_lossy().len() > MAX_PATH as usize); 368d0b88b7eSopenharmony_ci let file = File::create(file_path).expect("Unable to create file"); 369d0b88b7eSopenharmony_ci 370d0b88b7eSopenharmony_ci assert!(!unsafe { crate::msys_tty_on(file.as_raw_handle() as isize) }); 371d0b88b7eSopenharmony_ci } 372d0b88b7eSopenharmony_ci} 373