mirror of
https://github.com/denoland/deno.git
synced 2024-11-22 15:06:54 -05:00
83 lines
2.1 KiB
Rust
83 lines
2.1 KiB
Rust
// Copyright 2018-2024 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,
|
|
}
|
|
}
|