1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-26 16:09:27 -05:00
denoland-deno/ext/node/ops/os.rs
2023-08-01 16:08:41 -04:00

192 lines
5.8 KiB
Rust

// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
use crate::NodePermissions;
use deno_core::error::AnyError;
use deno_core::op;
use deno_core::OpState;
#[op]
pub fn op_node_os_get_priority<P>(
state: &mut OpState,
pid: u32,
) -> Result<i32, AnyError>
where
P: NodePermissions + 'static,
{
{
let permissions = state.borrow_mut::<P>();
permissions.check_sys("getPriority", "node:os.getPriority()")?;
}
priority::get_priority(pid)
}
#[op]
pub fn op_node_os_set_priority<P>(
state: &mut OpState,
pid: u32,
priority: i32,
) -> Result<(), AnyError>
where
P: NodePermissions + 'static,
{
{
let permissions = state.borrow_mut::<P>();
permissions.check_sys("setPriority", "node:os.setPriority()")?;
}
priority::set_priority(pid, priority)
}
#[op]
pub fn op_node_os_username<P>(state: &mut OpState) -> Result<String, AnyError>
where
P: NodePermissions + 'static,
{
{
let permissions = state.borrow_mut::<P>();
permissions.check_sys("userInfo", "node:os.userInfo()")?;
}
Ok(whoami::username())
}
#[cfg(unix)]
mod priority {
use super::*;
use errno::errno;
use errno::set_errno;
use errno::Errno;
use libc::id_t;
use libc::PRIO_PROCESS;
#[cfg(target_os = "macos")]
#[allow(non_camel_case_types)]
type priority_t = i32;
#[cfg(target_os = "linux")]
#[allow(non_camel_case_types)]
type priority_t = u32;
const PRIORITY_HIGH: i32 = -14;
// Ref: https://github.com/libuv/libuv/blob/55376b044b74db40772e8a6e24d67a8673998e02/src/unix/core.c#L1533-L1547
pub fn get_priority(pid: u32) -> Result<i32, AnyError> {
set_errno(Errno(0));
match (
// SAFETY: libc::getpriority is unsafe
unsafe { libc::getpriority(PRIO_PROCESS as priority_t, pid as id_t) },
errno(),
) {
(-1, Errno(0)) => Ok(PRIORITY_HIGH),
(-1, _) => Err(std::io::Error::last_os_error().into()),
(priority, _) => Ok(priority),
}
}
pub fn set_priority(pid: u32, priority: i32) -> Result<(), AnyError> {
// SAFETY: libc::setpriority is unsafe
match unsafe {
libc::setpriority(PRIO_PROCESS as priority_t, pid as id_t, priority)
} {
-1 => Err(std::io::Error::last_os_error().into()),
_ => Ok(()),
}
}
}
#[cfg(windows)]
mod priority {
use super::*;
use deno_core::error::type_error;
use winapi::shared::minwindef::DWORD;
use winapi::shared::minwindef::FALSE;
use winapi::shared::ntdef::NULL;
use winapi::um::handleapi::CloseHandle;
use winapi::um::processthreadsapi::GetCurrentProcess;
use winapi::um::processthreadsapi::GetPriorityClass;
use winapi::um::processthreadsapi::OpenProcess;
use winapi::um::processthreadsapi::SetPriorityClass;
use winapi::um::winbase::ABOVE_NORMAL_PRIORITY_CLASS;
use winapi::um::winbase::BELOW_NORMAL_PRIORITY_CLASS;
use winapi::um::winbase::HIGH_PRIORITY_CLASS;
use winapi::um::winbase::IDLE_PRIORITY_CLASS;
use winapi::um::winbase::NORMAL_PRIORITY_CLASS;
use winapi::um::winbase::REALTIME_PRIORITY_CLASS;
use winapi::um::winnt::PROCESS_QUERY_LIMITED_INFORMATION;
// Taken from: https://github.com/libuv/libuv/blob/a877ca2435134ef86315326ef4ef0c16bdbabf17/include/uv.h#L1318-L1323
const PRIORITY_LOW: i32 = 19;
const PRIORITY_BELOW_NORMAL: i32 = 10;
const PRIORITY_NORMAL: i32 = 0;
const PRIORITY_ABOVE_NORMAL: i32 = -7;
const PRIORITY_HIGH: i32 = -14;
const PRIORITY_HIGHEST: i32 = -20;
// Ported from: https://github.com/libuv/libuv/blob/a877ca2435134ef86315326ef4ef0c16bdbabf17/src/win/util.c#L1649-L1685
pub fn get_priority(pid: u32) -> Result<i32, AnyError> {
// SAFETY: Windows API calls
unsafe {
let handle = if pid == 0 {
GetCurrentProcess()
} else {
OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid as DWORD)
};
if handle == NULL {
Err(std::io::Error::last_os_error().into())
} else {
let result = match GetPriorityClass(handle) {
0 => Err(std::io::Error::last_os_error().into()),
REALTIME_PRIORITY_CLASS => Ok(PRIORITY_HIGHEST),
HIGH_PRIORITY_CLASS => Ok(PRIORITY_HIGH),
ABOVE_NORMAL_PRIORITY_CLASS => Ok(PRIORITY_ABOVE_NORMAL),
NORMAL_PRIORITY_CLASS => Ok(PRIORITY_NORMAL),
BELOW_NORMAL_PRIORITY_CLASS => Ok(PRIORITY_BELOW_NORMAL),
IDLE_PRIORITY_CLASS => Ok(PRIORITY_LOW),
_ => Ok(PRIORITY_LOW),
};
CloseHandle(handle);
result
}
}
}
// Ported from: https://github.com/libuv/libuv/blob/a877ca2435134ef86315326ef4ef0c16bdbabf17/src/win/util.c#L1688-L1719
pub fn set_priority(pid: u32, priority: i32) -> Result<(), AnyError> {
// SAFETY: Windows API calls
unsafe {
let handle = if pid == 0 {
GetCurrentProcess()
} else {
OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid as DWORD)
};
if handle == NULL {
Err(std::io::Error::last_os_error().into())
} else {
#[allow(clippy::manual_range_contains)]
let priority_class =
if priority < PRIORITY_HIGHEST || priority > PRIORITY_LOW {
return Err(type_error("Invalid priority"));
} else if priority < PRIORITY_HIGH {
REALTIME_PRIORITY_CLASS
} else if priority < PRIORITY_ABOVE_NORMAL {
HIGH_PRIORITY_CLASS
} else if priority < PRIORITY_NORMAL {
ABOVE_NORMAL_PRIORITY_CLASS
} else if priority < PRIORITY_BELOW_NORMAL {
NORMAL_PRIORITY_CLASS
} else if priority < PRIORITY_LOW {
BELOW_NORMAL_PRIORITY_CLASS
} else {
IDLE_PRIORITY_CLASS
};
let result = match SetPriorityClass(handle, priority_class) {
FALSE => Err(std::io::Error::last_os_error().into()),
_ => Ok(()),
};
CloseHandle(handle);
result
}
}
}
}