1 #![deny(unsafe_op_in_unsafe_fn)]
4 use crate::error
::Error
as StdError
;
5 use crate::ffi
::{CStr, CString, OsStr, OsString}
;
8 use crate::marker
::PhantomData
;
9 use crate::os
::wasi
::prelude
::*;
10 use crate::path
::{self, PathBuf}
;
12 use crate::sys
::memchr
;
13 use crate::sys
::{unsupported, Void}
;
16 #[cfg(not(target_feature = "atomics"))]
17 pub unsafe fn env_lock() -> impl Any
{
18 // No need for a lock if we're single-threaded, but this function will need
19 // to get implemented for multi-threaded scenarios
22 pub fn errno() -> i32 {
25 static errno
: libc
::c_int
;
28 unsafe { errno as i32 }
31 pub fn error_string(errno
: i32) -> String
{
32 let mut buf
= [0 as libc
::c_char
; 1024];
34 let p
= buf
.as_mut_ptr();
36 if libc
::strerror_r(errno
as libc
::c_int
, p
, buf
.len()) < 0 {
37 panic
!("strerror_r failure");
39 str::from_utf8(CStr
::from_ptr(p
).to_bytes()).unwrap().to_owned()
43 pub fn getcwd() -> io
::Result
<PathBuf
> {
47 pub fn chdir(_
: &path
::Path
) -> io
::Result
<()> {
51 pub struct SplitPaths
<'a
>(&'a Void
);
53 pub fn split_paths(_unparsed
: &OsStr
) -> SplitPaths
<'_
> {
57 impl<'a
> Iterator
for SplitPaths
<'a
> {
59 fn next(&mut self) -> Option
<PathBuf
> {
65 pub struct JoinPathsError
;
67 pub fn join_paths
<I
, T
>(_paths
: I
) -> Result
<OsString
, JoinPathsError
>
69 I
: Iterator
<Item
= T
>,
75 impl fmt
::Display
for JoinPathsError
{
76 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
77 "not supported on wasm yet".fmt(f
)
81 impl StdError
for JoinPathsError
{
83 fn description(&self) -> &str {
84 "not supported on wasm yet"
88 pub fn current_exe() -> io
::Result
<PathBuf
> {
92 iter
: vec
::IntoIter
<(OsString
, OsString
)>,
93 _dont_send_or_sync_me
: PhantomData
<*mut ()>,
96 impl Iterator
for Env
{
97 type Item
= (OsString
, OsString
);
98 fn next(&mut self) -> Option
<(OsString
, OsString
)> {
101 fn size_hint(&self) -> (usize, Option
<usize>) {
102 self.iter
.size_hint()
106 pub fn env() -> Env
{
108 let _guard
= env_lock();
109 let mut environ
= libc
::environ
;
110 let mut result
= Vec
::new();
111 if !environ
.is_null() {
112 while !(*environ
).is_null() {
113 if let Some(key_value
) = parse(CStr
::from_ptr(*environ
).to_bytes()) {
114 result
.push(key_value
);
116 environ
= environ
.add(1);
119 return Env { iter: result.into_iter(), _dont_send_or_sync_me: PhantomData }
;
122 // See src/libstd/sys/unix/os.rs, same as that
123 fn parse(input
: &[u8]) -> Option
<(OsString
, OsString
)> {
124 if input
.is_empty() {
127 let pos
= memchr
::memchr(b'
='
, &input
[1..]).map(|p
| p
+ 1);
130 OsStringExt
::from_vec(input
[..p
].to_vec()),
131 OsStringExt
::from_vec(input
[p
+ 1..].to_vec()),
137 pub fn getenv(k
: &OsStr
) -> io
::Result
<Option
<OsString
>> {
138 let k
= CString
::new(k
.as_bytes())?
;
140 let _guard
= env_lock();
141 let s
= libc
::getenv(k
.as_ptr()) as *const libc
::c_char
;
142 let ret
= if s
.is_null() {
145 Some(OsStringExt
::from_vec(CStr
::from_ptr(s
).to_bytes().to_vec()))
151 pub fn setenv(k
: &OsStr
, v
: &OsStr
) -> io
::Result
<()> {
152 let k
= CString
::new(k
.as_bytes())?
;
153 let v
= CString
::new(v
.as_bytes())?
;
156 let _guard
= env_lock();
157 cvt(libc
::setenv(k
.as_ptr(), v
.as_ptr(), 1)).map(drop
)
161 pub fn unsetenv(n
: &OsStr
) -> io
::Result
<()> {
162 let nbuf
= CString
::new(n
.as_bytes())?
;
165 let _guard
= env_lock();
166 cvt(libc
::unsetenv(nbuf
.as_ptr())).map(drop
)
170 pub fn temp_dir() -> PathBuf
{
171 panic
!("no filesystem on wasm")
174 pub fn home_dir() -> Option
<PathBuf
> {
178 pub fn exit(code
: i32) -> ! {
179 unsafe { libc::exit(code) }
182 pub fn getpid() -> u32 {
183 panic
!("unsupported");
187 pub trait IsMinusOne
{
188 fn is_minus_one(&self) -> bool
;
191 macro_rules
! impl_is_minus_one
{
192 ($
($t
:ident
)*) => ($
(impl IsMinusOne
for $t
{
193 fn is_minus_one(&self) -> bool
{
199 impl_is_minus_one
! { i8 i16 i32 i64 isize }
201 fn cvt
<T
: IsMinusOne
>(t
: T
) -> io
::Result
<T
> {
202 if t
.is_minus_one() { Err(io::Error::last_os_error()) }
else { Ok(t) }