2 use crate::error
::Error
as StdError
;
3 use crate::ffi
::{CStr, CString, OsStr, OsString}
;
6 use crate::marker
::PhantomData
;
7 use crate::os
::wasi
::prelude
::*;
8 use crate::path
::{self, PathBuf}
;
10 use crate::sys
::memchr
;
11 use crate::sys
::{unsupported, Void}
;
14 #[cfg(not(target_feature = "atomics"))]
15 pub unsafe fn env_lock() -> impl Any
{
16 // No need for a lock if we're single-threaded, but this function will need
17 // to get implemented for multi-threaded scenarios
20 pub fn errno() -> i32 {
23 static errno
: libc
::c_int
;
26 unsafe { errno as i32 }
29 pub fn error_string(errno
: i32) -> String
{
30 let mut buf
= [0 as libc
::c_char
; 1024];
32 let p
= buf
.as_mut_ptr();
34 if libc
::strerror_r(errno
as libc
::c_int
, p
, buf
.len()) < 0 {
35 panic
!("strerror_r failure");
37 str::from_utf8(CStr
::from_ptr(p
).to_bytes()).unwrap().to_owned()
41 pub fn getcwd() -> io
::Result
<PathBuf
> {
45 pub fn chdir(_
: &path
::Path
) -> io
::Result
<()> {
49 pub struct SplitPaths
<'a
>(&'a Void
);
51 pub fn split_paths(_unparsed
: &OsStr
) -> SplitPaths
<'_
> {
55 impl<'a
> Iterator
for SplitPaths
<'a
> {
57 fn next(&mut self) -> Option
<PathBuf
> {
63 pub struct JoinPathsError
;
65 pub fn join_paths
<I
, T
>(_paths
: I
) -> Result
<OsString
, JoinPathsError
>
67 I
: Iterator
<Item
= T
>,
73 impl fmt
::Display
for JoinPathsError
{
74 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
75 "not supported on wasm yet".fmt(f
)
79 impl StdError
for JoinPathsError
{
81 fn description(&self) -> &str {
82 "not supported on wasm yet"
86 pub fn current_exe() -> io
::Result
<PathBuf
> {
90 iter
: vec
::IntoIter
<(OsString
, OsString
)>,
91 _dont_send_or_sync_me
: PhantomData
<*mut ()>,
94 impl Iterator
for Env
{
95 type Item
= (OsString
, OsString
);
96 fn next(&mut self) -> Option
<(OsString
, OsString
)> {
99 fn size_hint(&self) -> (usize, Option
<usize>) {
100 self.iter
.size_hint()
104 pub fn env() -> Env
{
106 let _guard
= env_lock();
107 let mut environ
= libc
::environ
;
108 let mut result
= Vec
::new();
109 if !environ
.is_null() {
110 while !(*environ
).is_null() {
111 if let Some(key_value
) = parse(CStr
::from_ptr(*environ
).to_bytes()) {
112 result
.push(key_value
);
114 environ
= environ
.add(1);
117 return Env { iter: result.into_iter(), _dont_send_or_sync_me: PhantomData }
;
120 // See src/libstd/sys/unix/os.rs, same as that
121 fn parse(input
: &[u8]) -> Option
<(OsString
, OsString
)> {
122 if input
.is_empty() {
125 let pos
= memchr
::memchr(b'
='
, &input
[1..]).map(|p
| p
+ 1);
128 OsStringExt
::from_vec(input
[..p
].to_vec()),
129 OsStringExt
::from_vec(input
[p
+ 1..].to_vec()),
135 pub fn getenv(k
: &OsStr
) -> io
::Result
<Option
<OsString
>> {
136 let k
= CString
::new(k
.as_bytes())?
;
138 let _guard
= env_lock();
139 let s
= libc
::getenv(k
.as_ptr()) as *const libc
::c_char
;
140 let ret
= if s
.is_null() {
143 Some(OsStringExt
::from_vec(CStr
::from_ptr(s
).to_bytes().to_vec()))
149 pub fn setenv(k
: &OsStr
, v
: &OsStr
) -> io
::Result
<()> {
150 let k
= CString
::new(k
.as_bytes())?
;
151 let v
= CString
::new(v
.as_bytes())?
;
154 let _guard
= env_lock();
155 cvt(libc
::setenv(k
.as_ptr(), v
.as_ptr(), 1)).map(drop
)
159 pub fn unsetenv(n
: &OsStr
) -> io
::Result
<()> {
160 let nbuf
= CString
::new(n
.as_bytes())?
;
163 let _guard
= env_lock();
164 cvt(libc
::unsetenv(nbuf
.as_ptr())).map(drop
)
168 pub fn temp_dir() -> PathBuf
{
169 panic
!("no filesystem on wasm")
172 pub fn home_dir() -> Option
<PathBuf
> {
176 pub fn exit(code
: i32) -> ! {
177 unsafe { libc::exit(code) }
180 pub fn getpid() -> u32 {
181 panic
!("unsupported");
185 pub trait IsMinusOne
{
186 fn is_minus_one(&self) -> bool
;
189 macro_rules
! impl_is_minus_one
{
190 ($
($t
:ident
)*) => ($
(impl IsMinusOne
for $t
{
191 fn is_minus_one(&self) -> bool
{
197 impl_is_minus_one
! { i8 i16 i32 i64 isize }
199 fn cvt
<T
: IsMinusOne
>(t
: T
) -> io
::Result
<T
> {
200 if t
.is_minus_one() { Err(io::Error::last_os_error()) }
else { Ok(t) }