Skip to content

Commit 925be25

Browse files
littledivybartlomieju
authored andcommitted
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 #23824
1 parent b46e81b commit 925be25

File tree

7 files changed

+29
-17
lines changed

7 files changed

+29
-17
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/node/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ errno = "0.2.8"
3636
faster-hex.workspace = true
3737
h2 = { version = "0.3.26", features = ["unstable"] }
3838
hkdf.workspace = true
39+
home = "0.5.9"
3940
http_v02.workspace = true
4041
idna = "0.3.0"
4142
indexmap.workspace = true

ext/node/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ deno_core::extension!(deno_node,
309309
ops::os::op_node_os_username<P>,
310310
ops::os::op_geteuid<P>,
311311
ops::os::op_cpus<P>,
312+
ops::os::op_homedir<P>,
312313
op_node_build_os,
313314
op_node_is_promise_rejected,
314315
op_npm_process_state,

ext/node/ops/os/mod.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,3 +88,17 @@ where
8888

8989
cpus::cpu_info().ok_or_else(|| type_error("Failed to get cpu info"))
9090
}
91+
92+
#[op2]
93+
#[string]
94+
pub fn op_homedir<P>(state: &mut OpState) -> Result<Option<String>, AnyError>
95+
where
96+
P: NodePermissions + 'static,
97+
{
98+
{
99+
let permissions = state.borrow_mut::<P>();
100+
permissions.check_sys("homedir", "node:os.homedir()")?;
101+
}
102+
103+
Ok(home::home_dir().map(|path| path.to_string_lossy().to_string()))
104+
}

ext/node/polyfills/os.ts

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,15 @@
2525

2626
import {
2727
op_cpus,
28+
op_homedir,
2829
op_node_os_get_priority,
2930
op_node_os_set_priority,
3031
op_node_os_username,
3132
} from "ext:core/ops";
3233

3334
import { validateIntegerRange } from "ext:deno_node/_utils.ts";
3435
import process from "node:process";
35-
import { isWindows, osType } from "ext:deno_node/_util/os.ts";
36+
import { isWindows } from "ext:deno_node/_util/os.ts";
3637
import { ERR_OS_NO_HOMEDIR } from "ext:deno_node/internal/errors.ts";
3738
import { os } from "ext:deno_node/internal_binding/constants.ts";
3839
import { osUptime } from "ext:runtime/30_os.js";
@@ -173,21 +174,7 @@ export function getPriority(pid = 0): number {
173174

174175
/** Returns the string path of the current user's home directory. */
175176
export function homedir(): string | null {
176-
// Note: Node/libuv calls getpwuid() / GetUserProfileDirectory() when the
177-
// environment variable isn't set but that's the (very uncommon) fallback
178-
// path. IMO, it's okay to punt on that for now.
179-
switch (osType) {
180-
case "windows":
181-
return Deno.env.get("USERPROFILE") || null;
182-
case "linux":
183-
case "android":
184-
case "darwin":
185-
case "freebsd":
186-
case "openbsd":
187-
return Deno.env.get("HOME") || null;
188-
default:
189-
throw Error("unreachable");
190-
}
177+
return op_homedir();
191178
}
192179

193180
/** Returns the host name of the operating system as a string. */

runtime/permissions/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -913,7 +913,7 @@ impl Descriptor for SysDescriptor {
913913
pub fn parse_sys_kind(kind: &str) -> Result<&str, AnyError> {
914914
match kind {
915915
"hostname" | "osRelease" | "osUptime" | "loadavg" | "networkInterfaces"
916-
| "systemMemoryInfo" | "uid" | "gid" | "cpus" => Ok(kind),
916+
| "systemMemoryInfo" | "uid" | "gid" | "cpus" | "homedir" => Ok(kind),
917917
_ => Err(type_error(format!("unknown system info kind \"{kind}\""))),
918918
}
919919
}

tests/unit_node/os_test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,14 @@ Deno.test({
4747
},
4848
});
4949

50+
Deno.test({
51+
name: "home directory when HOME is not set",
52+
fn() {
53+
Deno.env.delete("HOME");
54+
assertEquals(typeof os.homedir(), "string");
55+
},
56+
});
57+
5058
Deno.test({
5159
name: "tmp directory is a string",
5260
fn() {

0 commit comments

Comments
 (0)