summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDivy Srivastava <dj.srivastava23@gmail.com>2024-05-15 22:22:40 -0700
committerGitHub <noreply@github.com>2024-05-16 10:52:40 +0530
commitbba553bea5938932518dc6382e464968ce8374b4 (patch)
treeefd68b86734bf8703608f0165a473ac04c300272
parenta31b81394b7d78e6a0e678ba4d18dda62a3b2bc5 (diff)
fix(ext/node): homedir() `getpwuid`/`SHGetKnownFolderPath` fallback (#23841)
**Unix**: Returns the value of the HOME environment variable if it is set even if it is an empty string. Otherwise, it tries to determine the home directory by invoking the [getpwuid_r](https://linux.die.net/man/3/getpwuid_r) function with the UID of the current user. **Windows**: Returns the value of the USERPROFILE environment variable if it is set and it is not an empty string. Otherwise, it tries to determine the home directory by invoking the [SHGetKnownFolderPath](https://learn.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shgetknownfolderpath) function with [FOLDERID_Profile](https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid). Fixes https://github.com/denoland/deno/issues/23824
-rw-r--r--Cargo.lock1
-rw-r--r--ext/node/Cargo.toml1
-rw-r--r--ext/node/lib.rs1
-rw-r--r--ext/node/ops/os/mod.rs14
-rw-r--r--ext/node/polyfills/os.ts19
-rw-r--r--runtime/permissions/lib.rs2
-rw-r--r--tests/unit_node/os_test.ts8
7 files changed, 29 insertions, 17 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 1d31de8be..2dd72b353 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1680,6 +1680,7 @@ dependencies = [
"faster-hex",
"h2 0.3.26",
"hkdf",
+ "home",
"http 0.2.12",
"idna 0.3.0",
"indexmap",
diff --git a/ext/node/Cargo.toml b/ext/node/Cargo.toml
index acc5e758c..f930f3f3a 100644
--- a/ext/node/Cargo.toml
+++ b/ext/node/Cargo.toml
@@ -36,6 +36,7 @@ errno = "0.2.8"
faster-hex.workspace = true
h2 = { version = "0.3.26", features = ["unstable"] }
hkdf.workspace = true
+home = "0.5.9"
http_v02.workspace = true
idna = "0.3.0"
indexmap.workspace = true
diff --git a/ext/node/lib.rs b/ext/node/lib.rs
index 43a5b158e..b4eeb71c2 100644
--- a/ext/node/lib.rs
+++ b/ext/node/lib.rs
@@ -309,6 +309,7 @@ deno_core::extension!(deno_node,
ops::os::op_node_os_username<P>,
ops::os::op_geteuid<P>,
ops::os::op_cpus<P>,
+ ops::os::op_homedir<P>,
op_node_build_os,
op_node_is_promise_rejected,
op_npm_process_state,
diff --git a/ext/node/ops/os/mod.rs b/ext/node/ops/os/mod.rs
index 603f678e0..5b32113e5 100644
--- a/ext/node/ops/os/mod.rs
+++ b/ext/node/ops/os/mod.rs
@@ -88,3 +88,17 @@ where
cpus::cpu_info().ok_or_else(|| type_error("Failed to get cpu info"))
}
+
+#[op2]
+#[string]
+pub fn op_homedir<P>(state: &mut OpState) -> Result<Option<String>, AnyError>
+where
+ P: NodePermissions + 'static,
+{
+ {
+ let permissions = state.borrow_mut::<P>();
+ permissions.check_sys("homedir", "node:os.homedir()")?;
+ }
+
+ Ok(home::home_dir().map(|path| path.to_string_lossy().to_string()))
+}
diff --git a/ext/node/polyfills/os.ts b/ext/node/polyfills/os.ts
index bc88b0601..753e39319 100644
--- a/ext/node/polyfills/os.ts
+++ b/ext/node/polyfills/os.ts
@@ -25,6 +25,7 @@
import {
op_cpus,
+ op_homedir,
op_node_os_get_priority,
op_node_os_set_priority,
op_node_os_username,
@@ -32,7 +33,7 @@ import {
import { validateIntegerRange } from "ext:deno_node/_utils.ts";
import process from "node:process";
-import { isWindows, osType } from "ext:deno_node/_util/os.ts";
+import { isWindows } from "ext:deno_node/_util/os.ts";
import { ERR_OS_NO_HOMEDIR } from "ext:deno_node/internal/errors.ts";
import { os } from "ext:deno_node/internal_binding/constants.ts";
import { osUptime } from "ext:runtime/30_os.js";
@@ -173,21 +174,7 @@ export function getPriority(pid = 0): number {
/** Returns the string path of the current user's home directory. */
export function homedir(): string | null {
- // Note: Node/libuv calls getpwuid() / GetUserProfileDirectory() when the
- // environment variable isn't set but that's the (very uncommon) fallback
- // path. IMO, it's okay to punt on that for now.
- switch (osType) {
- case "windows":
- return Deno.env.get("USERPROFILE") || null;
- case "linux":
- case "android":
- case "darwin":
- case "freebsd":
- case "openbsd":
- return Deno.env.get("HOME") || null;
- default:
- throw Error("unreachable");
- }
+ return op_homedir();
}
/** Returns the host name of the operating system as a string. */
diff --git a/runtime/permissions/lib.rs b/runtime/permissions/lib.rs
index 06db9958c..2e94e3aec 100644
--- a/runtime/permissions/lib.rs
+++ b/runtime/permissions/lib.rs
@@ -913,7 +913,7 @@ impl Descriptor for SysDescriptor {
pub fn parse_sys_kind(kind: &str) -> Result<&str, AnyError> {
match kind {
"hostname" | "osRelease" | "osUptime" | "loadavg" | "networkInterfaces"
- | "systemMemoryInfo" | "uid" | "gid" | "cpus" => Ok(kind),
+ | "systemMemoryInfo" | "uid" | "gid" | "cpus" | "homedir" => Ok(kind),
_ => Err(type_error(format!("unknown system info kind \"{kind}\""))),
}
}
diff --git a/tests/unit_node/os_test.ts b/tests/unit_node/os_test.ts
index 9ce9fc9eb..810c22518 100644
--- a/tests/unit_node/os_test.ts
+++ b/tests/unit_node/os_test.ts
@@ -48,6 +48,14 @@ Deno.test({
});
Deno.test({
+ name: "home directory when HOME is not set",
+ fn() {
+ Deno.env.delete("HOME");
+ assertEquals(typeof os.homedir(), "string");
+ },
+});
+
+Deno.test({
name: "tmp directory is a string",
fn() {
assertEquals(typeof os.tmpdir(), "string");