summaryrefslogtreecommitdiff
path: root/ext/node/ops/util.rs
diff options
context:
space:
mode:
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,
+ }
+}