summaryrefslogtreecommitdiff
path: root/ext/node/ops/util.rs
diff options
context:
space:
mode:
authorDivy Srivastava <dj.srivastava23@gmail.com>2023-10-30 08:53:08 -0700
committerGitHub <noreply@github.com>2023-10-30 15:53:08 +0000
commit09204107d85351dae07a45f6a9684b5b6e573652 (patch)
tree5a04f3a877e677e382e34684784ddf832838bd77 /ext/node/ops/util.rs
parent1acef755ca8a0a0433a98e4a66433c63ee0a3b09 (diff)
fix: implement node:tty (#20892)
Fixes #21012 Closes https://github.com/denoland/deno/issues/20855 Fixes https://github.com/denoland/deno/issues/20890 Fixes https://github.com/denoland/deno/issues/20611 Fixes https://github.com/denoland/deno/issues/20336 Fixes `create-svelte` from https://github.com/denoland/deno/issues/17248 Fixes more reports here: - https://github.com/denoland/deno/issues/6529#issuecomment-1432690559 - https://github.com/denoland/deno/issues/6529#issuecomment-1522059006 - https://github.com/denoland/deno/issues/6529#issuecomment-1695803570
Diffstat (limited to 'ext/node/ops/util.rs')
-rw-r--r--ext/node/ops/util.rs83
1 files changed, 83 insertions, 0 deletions
diff --git a/ext/node/ops/util.rs b/ext/node/ops/util.rs
new file mode 100644
index 000000000..1cb80e0e3
--- /dev/null
+++ b/ext/node/ops/util.rs
@@ -0,0 +1,83 @@
+// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
+
+use deno_core::error::AnyError;
+use deno_core::op2;
+use deno_core::OpState;
+use deno_core::ResourceHandle;
+use deno_core::ResourceHandleFd;
+
+#[repr(u32)]
+enum HandleType {
+ #[allow(dead_code)]
+ Tcp = 0,
+ Tty,
+ #[allow(dead_code)]
+ Udp,
+ File,
+ Pipe,
+ Unknown,
+}
+
+#[op2(fast)]
+pub fn op_node_guess_handle_type(
+ state: &mut OpState,
+ rid: u32,
+) -> Result<u32, AnyError> {
+ let handle = state.resource_table.get_handle(rid)?;
+
+ let handle_type = match handle {
+ ResourceHandle::Fd(handle) => guess_handle_type(handle),
+ _ => HandleType::Unknown,
+ };
+
+ Ok(handle_type as u32)
+}
+
+#[cfg(windows)]
+fn guess_handle_type(handle: ResourceHandleFd) -> HandleType {
+ use winapi::um::consoleapi::GetConsoleMode;
+ use winapi::um::fileapi::GetFileType;
+ use winapi::um::winbase::FILE_TYPE_CHAR;
+ use winapi::um::winbase::FILE_TYPE_DISK;
+ use winapi::um::winbase::FILE_TYPE_PIPE;
+
+ // SAFETY: Call to win32 fileapi. `handle` is a valid fd.
+ match unsafe { GetFileType(handle) } {
+ FILE_TYPE_DISK => HandleType::File,
+ FILE_TYPE_CHAR => {
+ let mut mode = 0;
+ // SAFETY: Call to win32 consoleapi. `handle` is a valid fd.
+ // `mode` is a valid pointer.
+ if unsafe { GetConsoleMode(handle, &mut mode) } == 1 {
+ HandleType::Tty
+ } else {
+ HandleType::File
+ }
+ }
+ FILE_TYPE_PIPE => HandleType::Pipe,
+ _ => HandleType::Unknown,
+ }
+}
+
+#[cfg(unix)]
+fn guess_handle_type(handle: ResourceHandleFd) -> HandleType {
+ use std::io::IsTerminal;
+ // SAFETY: The resource remains open for the duration of borrow_raw.
+ if unsafe { std::os::fd::BorrowedFd::borrow_raw(handle).is_terminal() } {
+ return HandleType::Tty;
+ }
+
+ // SAFETY: It is safe to zero-initialize a `libc::stat` struct.
+ let mut s = unsafe { std::mem::zeroed() };
+ // SAFETY: Call to libc
+ if unsafe { libc::fstat(handle, &mut s) } == 1 {
+ return HandleType::Unknown;
+ }
+
+ match s.st_mode & 61440 {
+ libc::S_IFREG | libc::S_IFCHR => HandleType::File,
+ libc::S_IFIFO => HandleType::Pipe,
+ libc::S_IFSOCK => HandleType::Tcp,
+ _ => HandleType::Unknown,
+ }
+}