Skip to content

Commit f3641df

Browse files
authored
Rollup merge of #140143 - thaliaarchi:move-env-pal, r=joboet
Move `sys::pal::os::Env` into `sys::env` Although `Env` (as `Vars`), `Args`, path functions, and OS constants are publicly exposed via `std::env`, their implementations are each self-contained. Keep them separate in `std::sys` and make a new module, `sys::env`, for `Env`. Also fix `unsafe_op_in_unsafe_fn` for Unix and update the `!DynSend` and `!DynSync` impls which had grown out of sync with the platforms (see #48005 for discussion on that). r? joboet Tracked in #117276.
2 parents 8868163 + 01485c9 commit f3641df

File tree

35 files changed

+980
-1222
lines changed

35 files changed

+980
-1222
lines changed

compiler/rustc_data_structures/src/marker.rs

+18-4
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,15 @@ impls_dyn_send_neg!(
3939
[std::io::StderrLock<'_>]
4040
);
4141

42-
#[cfg(any(unix, target_os = "hermit", target_os = "wasi", target_os = "solid_asp3"))]
43-
// Consistent with `std`, `os_imp::Env` is `!Sync` in these platforms
42+
#[cfg(any(
43+
unix,
44+
target_os = "hermit",
45+
all(target_vendor = "fortanix", target_env = "sgx"),
46+
target_os = "solid_asp3",
47+
target_os = "wasi",
48+
target_os = "xous"
49+
))]
50+
// Consistent with `std`, `env_imp::Env` is `!Sync` in these platforms
4451
impl !DynSend for std::env::VarsOs {}
4552

4653
macro_rules! already_send {
@@ -106,8 +113,15 @@ impls_dyn_sync_neg!(
106113
[std::sync::mpsc::Sender<T> where T]
107114
);
108115

109-
#[cfg(any(unix, target_os = "hermit", target_os = "wasi", target_os = "solid_asp3"))]
110-
// Consistent with `std`, `os_imp::Env` is `!Sync` in these platforms
116+
#[cfg(any(
117+
unix,
118+
target_os = "hermit",
119+
all(target_vendor = "fortanix", target_env = "sgx"),
120+
target_os = "solid_asp3",
121+
target_os = "wasi",
122+
target_os = "xous"
123+
))]
124+
// Consistent with `std`, `env_imp::Env` is `!Sync` in these platforms
111125
impl !DynSync for std::env::VarsOs {}
112126

113127
macro_rules! already_sync {

library/std/src/env.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
use crate::error::Error;
1414
use crate::ffi::{OsStr, OsString};
1515
use crate::path::{Path, PathBuf};
16-
use crate::sys::os as os_imp;
16+
use crate::sys::{env as env_imp, os as os_imp};
1717
use crate::{fmt, io, sys};
1818

1919
/// Returns the current working directory as a [`PathBuf`].
@@ -96,7 +96,7 @@ pub struct Vars {
9696
/// [`env::vars_os()`]: vars_os
9797
#[stable(feature = "env", since = "1.0.0")]
9898
pub struct VarsOs {
99-
inner: os_imp::Env,
99+
inner: env_imp::Env,
100100
}
101101

102102
/// Returns an iterator of (variable, value) pairs of strings, for all the
@@ -150,7 +150,7 @@ pub fn vars() -> Vars {
150150
#[must_use]
151151
#[stable(feature = "env", since = "1.0.0")]
152152
pub fn vars_os() -> VarsOs {
153-
VarsOs { inner: os_imp::env() }
153+
VarsOs { inner: env_imp::env() }
154154
}
155155

156156
#[stable(feature = "env", since = "1.0.0")]
@@ -259,7 +259,7 @@ pub fn var_os<K: AsRef<OsStr>>(key: K) -> Option<OsString> {
259259
}
260260

261261
fn _var_os(key: &OsStr) -> Option<OsString> {
262-
os_imp::getenv(key)
262+
env_imp::getenv(key)
263263
}
264264

265265
/// The error type for operations interacting with environment variables.
@@ -363,7 +363,7 @@ impl Error for VarError {
363363
#[stable(feature = "env", since = "1.0.0")]
364364
pub unsafe fn set_var<K: AsRef<OsStr>, V: AsRef<OsStr>>(key: K, value: V) {
365365
let (key, value) = (key.as_ref(), value.as_ref());
366-
unsafe { os_imp::setenv(key, value) }.unwrap_or_else(|e| {
366+
unsafe { env_imp::setenv(key, value) }.unwrap_or_else(|e| {
367367
panic!("failed to set environment variable `{key:?}` to `{value:?}`: {e}")
368368
})
369369
}
@@ -434,7 +434,7 @@ pub unsafe fn set_var<K: AsRef<OsStr>, V: AsRef<OsStr>>(key: K, value: V) {
434434
#[stable(feature = "env", since = "1.0.0")]
435435
pub unsafe fn remove_var<K: AsRef<OsStr>>(key: K) {
436436
let key = key.as_ref();
437-
unsafe { os_imp::unsetenv(key) }
437+
unsafe { env_imp::unsetenv(key) }
438438
.unwrap_or_else(|e| panic!("failed to remove environment variable `{key:?}`: {e}"))
439439
}
440440

library/std/src/sys/args/mod.rs

+10
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,16 @@
22
33
#![forbid(unsafe_op_in_unsafe_fn)]
44

5+
#[cfg(any(
6+
all(target_family = "unix", not(any(target_os = "espidf", target_os = "vita"))),
7+
target_family = "windows",
8+
target_os = "hermit",
9+
target_os = "uefi",
10+
target_os = "wasi",
11+
target_os = "xous",
12+
))]
13+
mod common;
14+
515
cfg_if::cfg_if! {
616
if #[cfg(any(
717
all(target_family = "unix", not(any(target_os = "espidf", target_os = "vita"))),

library/std/src/sys/args/uefi.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
use r_efi::protocols::loaded_image;
22

3+
pub use super::common::Args;
34
use crate::env::current_exe;
45
use crate::ffi::OsString;
56
use crate::iter::Iterator;
67
use crate::sys::pal::helpers;
78

8-
#[path = "common.rs"]
9-
mod common;
10-
pub use common::Args;
11-
129
pub fn args() -> Args {
1310
let lazy_current_exe = || Vec::from([current_exe().map(Into::into).unwrap_or_default()]);
1411

library/std/src/sys/args/unix.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,13 @@
55
66
#![allow(dead_code)] // runtime init functions not used during testing
77

8+
pub use super::common::Args;
89
use crate::ffi::CStr;
910
#[cfg(target_os = "hermit")]
1011
use crate::os::hermit::ffi::OsStringExt;
1112
#[cfg(not(target_os = "hermit"))]
1213
use crate::os::unix::ffi::OsStringExt;
1314

14-
#[path = "common.rs"]
15-
mod common;
16-
pub use common::Args;
17-
1815
/// One-time global initialization.
1916
pub unsafe fn init(argc: isize, argv: *const *const u8) {
2017
unsafe { imp::init(argc, argv) }

library/std/src/sys/args/wasi.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
#![forbid(unsafe_op_in_unsafe_fn)]
22

3+
pub use super::common::Args;
34
use crate::ffi::{CStr, OsStr, OsString};
45
use crate::os::wasi::ffi::OsStrExt;
56

6-
#[path = "common.rs"]
7-
mod common;
8-
pub use common::Args;
9-
107
/// Returns the command line arguments
118
pub fn args() -> Args {
129
Args::new(maybe_args().unwrap_or(Vec::new()))

library/std/src/sys/args/windows.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#[cfg(test)]
77
mod tests;
88

9+
pub use super::common::Args;
910
use crate::ffi::{OsStr, OsString};
1011
use crate::num::NonZero;
1112
use crate::os::windows::prelude::*;
@@ -18,10 +19,6 @@ use crate::sys_common::AsInner;
1819
use crate::sys_common::wstr::WStrUnits;
1920
use crate::{io, iter, ptr};
2021

21-
#[path = "common.rs"]
22-
mod common;
23-
pub use common::Args;
24-
2522
pub fn args() -> Args {
2623
// SAFETY: `GetCommandLineW` returns a pointer to a null terminated UTF-16
2724
// string so it's safe for `WStrUnits` to use.

library/std/src/sys/args/xous.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
1+
pub use super::common::Args;
12
use crate::sys::pal::os::get_application_parameters;
23
use crate::sys::pal::os::params::ArgumentList;
34

4-
#[path = "common.rs"]
5-
mod common;
6-
pub use common::Args;
7-
85
pub fn args() -> Args {
96
let Some(params) = get_application_parameters() else {
107
return Args::new(vec![]);

library/std/src/sys/env/common.rs

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
use crate::ffi::OsString;
2+
use crate::{fmt, vec};
3+
4+
pub struct Env {
5+
iter: vec::IntoIter<(OsString, OsString)>,
6+
}
7+
8+
// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
9+
pub struct EnvStrDebug<'a> {
10+
slice: &'a [(OsString, OsString)],
11+
}
12+
13+
impl fmt::Debug for EnvStrDebug<'_> {
14+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
15+
f.debug_list()
16+
.entries(self.slice.iter().map(|(a, b)| (a.to_str().unwrap(), b.to_str().unwrap())))
17+
.finish()
18+
}
19+
}
20+
21+
impl Env {
22+
pub(super) fn new(env: Vec<(OsString, OsString)>) -> Self {
23+
Env { iter: env.into_iter() }
24+
}
25+
26+
pub fn str_debug(&self) -> impl fmt::Debug + '_ {
27+
EnvStrDebug { slice: self.iter.as_slice() }
28+
}
29+
}
30+
31+
impl fmt::Debug for Env {
32+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33+
f.debug_list().entries(self.iter.as_slice()).finish()
34+
}
35+
}
36+
37+
impl !Send for Env {}
38+
impl !Sync for Env {}
39+
40+
impl Iterator for Env {
41+
type Item = (OsString, OsString);
42+
fn next(&mut self) -> Option<(OsString, OsString)> {
43+
self.iter.next()
44+
}
45+
fn size_hint(&self) -> (usize, Option<usize>) {
46+
self.iter.size_hint()
47+
}
48+
}

library/std/src/sys/env/hermit.rs

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
use core::slice::memchr;
2+
3+
pub use super::common::Env;
4+
use crate::collections::HashMap;
5+
use crate::ffi::{CStr, OsStr, OsString, c_char};
6+
use crate::io;
7+
use crate::os::hermit::ffi::OsStringExt;
8+
use crate::sync::Mutex;
9+
10+
static ENV: Mutex<Option<HashMap<OsString, OsString>>> = Mutex::new(None);
11+
12+
pub fn init(env: *const *const c_char) {
13+
let mut guard = ENV.lock().unwrap();
14+
let map = guard.insert(HashMap::new());
15+
16+
if env.is_null() {
17+
return;
18+
}
19+
20+
unsafe {
21+
let mut environ = env;
22+
while !(*environ).is_null() {
23+
if let Some((key, value)) = parse(CStr::from_ptr(*environ).to_bytes()) {
24+
map.insert(key, value);
25+
}
26+
environ = environ.add(1);
27+
}
28+
}
29+
30+
fn parse(input: &[u8]) -> Option<(OsString, OsString)> {
31+
// Strategy (copied from glibc): Variable name and value are separated
32+
// by an ASCII equals sign '='. Since a variable name must not be
33+
// empty, allow variable names starting with an equals sign. Skip all
34+
// malformed lines.
35+
if input.is_empty() {
36+
return None;
37+
}
38+
let pos = memchr::memchr(b'=', &input[1..]).map(|p| p + 1);
39+
pos.map(|p| {
40+
(
41+
OsStringExt::from_vec(input[..p].to_vec()),
42+
OsStringExt::from_vec(input[p + 1..].to_vec()),
43+
)
44+
})
45+
}
46+
}
47+
48+
/// Returns a vector of (variable, value) byte-vector pairs for all the
49+
/// environment variables of the current process.
50+
pub fn env() -> Env {
51+
let guard = ENV.lock().unwrap();
52+
let env = guard.as_ref().unwrap();
53+
54+
let result = env.iter().map(|(key, value)| (key.clone(), value.clone())).collect();
55+
56+
Env::new(result)
57+
}
58+
59+
pub fn getenv(k: &OsStr) -> Option<OsString> {
60+
ENV.lock().unwrap().as_ref().unwrap().get(k).cloned()
61+
}
62+
63+
pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
64+
let (k, v) = (k.to_owned(), v.to_owned());
65+
ENV.lock().unwrap().as_mut().unwrap().insert(k, v);
66+
Ok(())
67+
}
68+
69+
pub unsafe fn unsetenv(k: &OsStr) -> io::Result<()> {
70+
ENV.lock().unwrap().as_mut().unwrap().remove(k);
71+
Ok(())
72+
}

library/std/src/sys/env/mod.rs

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//! Platform-dependent environment variables abstraction.
2+
3+
#![forbid(unsafe_op_in_unsafe_fn)]
4+
5+
#[cfg(any(
6+
target_family = "unix",
7+
target_os = "hermit",
8+
all(target_vendor = "fortanix", target_env = "sgx"),
9+
target_os = "solid_asp3",
10+
target_os = "uefi",
11+
target_os = "wasi",
12+
target_os = "xous",
13+
))]
14+
mod common;
15+
16+
cfg_if::cfg_if! {
17+
if #[cfg(target_family = "unix")] {
18+
mod unix;
19+
pub use unix::*;
20+
} else if #[cfg(target_family = "windows")] {
21+
mod windows;
22+
pub use windows::*;
23+
} else if #[cfg(target_os = "hermit")] {
24+
mod hermit;
25+
pub use hermit::*;
26+
} else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] {
27+
mod sgx;
28+
pub use sgx::*;
29+
} else if #[cfg(target_os = "solid_asp3")] {
30+
mod solid;
31+
pub use solid::*;
32+
} else if #[cfg(target_os = "uefi")] {
33+
mod uefi;
34+
pub use uefi::*;
35+
} else if #[cfg(target_os = "wasi")] {
36+
mod wasi;
37+
pub use wasi::*;
38+
} else if #[cfg(target_os = "xous")] {
39+
mod xous;
40+
pub use xous::*;
41+
} else if #[cfg(target_os = "zkvm")] {
42+
mod zkvm;
43+
pub use zkvm::*;
44+
} else {
45+
mod unsupported;
46+
pub use unsupported::*;
47+
}
48+
}

0 commit comments

Comments
 (0)