mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-23 20:34:06 +00:00
Take sys/vxworks/{os,path,pipe} from sys/unix instead.
This commit is contained in:
parent
71bb1dc2a0
commit
408db0da85
@ -37,7 +37,7 @@ cfg_if::cfg_if! {
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
#[cfg(not(target_os = "dragonfly"))]
|
||||
#[cfg(not(any(target_os = "dragonfly", target_os = "vxworks")))]
|
||||
#[cfg_attr(
|
||||
any(
|
||||
target_os = "linux",
|
||||
@ -67,18 +67,28 @@ extern "C" {
|
||||
}
|
||||
|
||||
/// Returns the platform-specific value of errno
|
||||
#[cfg(not(target_os = "dragonfly"))]
|
||||
#[cfg(not(any(target_os = "dragonfly", target_os = "vxworks")))]
|
||||
pub fn errno() -> i32 {
|
||||
unsafe { (*errno_location()) as i32 }
|
||||
}
|
||||
|
||||
/// Sets the platform-specific value of errno
|
||||
#[cfg(all(not(target_os = "linux"), not(target_os = "dragonfly")))] // needed for readdir and syscall!
|
||||
#[cfg(all(not(target_os = "linux"), not(target_os = "dragonfly"), not(target_os = "vxworks")))] // needed for readdir and syscall!
|
||||
#[allow(dead_code)] // but not all target cfgs actually end up using it
|
||||
pub fn set_errno(e: i32) {
|
||||
unsafe { *errno_location() = e as c_int }
|
||||
}
|
||||
|
||||
#[cfg(target_os = "vxworks")]
|
||||
pub fn errno() -> i32 {
|
||||
unsafe { libc::errnoGet() }
|
||||
}
|
||||
|
||||
#[cfg(target_os = "vxworks")]
|
||||
pub fn set_errno(e: i32) {
|
||||
unsafe { libc::errnoSet(e as c_int) };
|
||||
}
|
||||
|
||||
#[cfg(target_os = "dragonfly")]
|
||||
pub fn errno() -> i32 {
|
||||
extern "C" {
|
||||
@ -439,6 +449,19 @@ pub fn current_exe() -> io::Result<PathBuf> {
|
||||
Err(io::Error::new(ErrorKind::Other, "Not yet implemented!"))
|
||||
}
|
||||
|
||||
#[cfg(target_os = "vxworks")]
|
||||
pub fn current_exe() -> io::Result<PathBuf> {
|
||||
#[cfg(test)]
|
||||
use realstd::env;
|
||||
|
||||
#[cfg(not(test))]
|
||||
use crate::env;
|
||||
|
||||
let exe_path = env::args().next().unwrap();
|
||||
let path = path::Path::new(&exe_path);
|
||||
path.canonicalize()
|
||||
}
|
||||
|
||||
pub struct Env {
|
||||
iter: vec::IntoIter<(OsString, OsString)>,
|
||||
_dont_send_or_sync_me: PhantomData<*mut ()>,
|
||||
@ -568,7 +591,8 @@ pub fn home_dir() -> Option<PathBuf> {
|
||||
target_os = "android",
|
||||
target_os = "ios",
|
||||
target_os = "emscripten",
|
||||
target_os = "redox"
|
||||
target_os = "redox",
|
||||
target_os = "vxworks"
|
||||
))]
|
||||
unsafe fn fallback() -> Option<OsString> {
|
||||
None
|
||||
@ -577,7 +601,8 @@ pub fn home_dir() -> Option<PathBuf> {
|
||||
target_os = "android",
|
||||
target_os = "ios",
|
||||
target_os = "emscripten",
|
||||
target_os = "redox"
|
||||
target_os = "redox",
|
||||
target_os = "vxworks"
|
||||
)))]
|
||||
unsafe fn fallback() -> Option<OsString> {
|
||||
let amt = match libc::sysconf(libc::_SC_GETPW_R_SIZE_MAX) {
|
||||
|
@ -34,8 +34,11 @@ pub mod memchr;
|
||||
pub mod mutex;
|
||||
#[path = "../unix/net.rs"]
|
||||
pub mod net;
|
||||
#[path = "../unix/os.rs"]
|
||||
pub mod os;
|
||||
#[path = "../unix/path.rs"]
|
||||
pub mod path;
|
||||
#[path = "../unix/pipe.rs"]
|
||||
pub mod pipe;
|
||||
pub mod process;
|
||||
pub mod rand;
|
||||
|
@ -1,315 +0,0 @@
|
||||
use crate::error::Error as StdError;
|
||||
use crate::ffi::{CStr, CString, OsStr, OsString};
|
||||
use crate::fmt;
|
||||
use crate::io;
|
||||
use crate::iter;
|
||||
use crate::marker::PhantomData;
|
||||
use crate::mem;
|
||||
use crate::memchr;
|
||||
use crate::path::{self, Path, PathBuf};
|
||||
use crate::slice;
|
||||
use crate::str;
|
||||
use crate::sys::cvt;
|
||||
use crate::sys_common::mutex::{StaticMutex, StaticMutexGuard};
|
||||
use libc::{self, c_char /*,c_void */, c_int};
|
||||
/*use sys::fd; this one is probably important */
|
||||
use crate::vec;
|
||||
|
||||
const TMPBUF_SZ: usize = 128;
|
||||
|
||||
// This is a terrible fix
|
||||
use crate::sys::os_str::Buf;
|
||||
use crate::sys_common::{AsInner, FromInner, IntoInner};
|
||||
|
||||
pub trait OsStringExt {
|
||||
fn from_vec(vec: Vec<u8>) -> Self;
|
||||
fn into_vec(self) -> Vec<u8>;
|
||||
}
|
||||
|
||||
impl OsStringExt for OsString {
|
||||
fn from_vec(vec: Vec<u8>) -> OsString {
|
||||
FromInner::from_inner(Buf { inner: vec })
|
||||
}
|
||||
fn into_vec(self) -> Vec<u8> {
|
||||
self.into_inner().inner
|
||||
}
|
||||
}
|
||||
|
||||
pub trait OsStrExt {
|
||||
fn from_bytes(slice: &[u8]) -> &Self;
|
||||
fn as_bytes(&self) -> &[u8];
|
||||
}
|
||||
|
||||
impl OsStrExt for OsStr {
|
||||
fn from_bytes(slice: &[u8]) -> &OsStr {
|
||||
unsafe { mem::transmute(slice) }
|
||||
}
|
||||
fn as_bytes(&self) -> &[u8] {
|
||||
&self.as_inner().inner
|
||||
}
|
||||
}
|
||||
|
||||
pub fn errno() -> i32 {
|
||||
unsafe { libc::errnoGet() }
|
||||
}
|
||||
|
||||
pub fn set_errno(e: i32) {
|
||||
unsafe {
|
||||
libc::errnoSet(e as c_int);
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets a detailed string description for the given error number.
|
||||
pub fn error_string(errno: i32) -> String {
|
||||
let mut buf = [0 as c_char; TMPBUF_SZ];
|
||||
extern "C" {
|
||||
fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: libc::size_t) -> c_int;
|
||||
}
|
||||
|
||||
let p = buf.as_mut_ptr();
|
||||
unsafe {
|
||||
if strerror_r(errno as c_int, p, buf.len()) < 0 {
|
||||
panic!("strerror_r failure");
|
||||
}
|
||||
let p = p as *const _;
|
||||
str::from_utf8(CStr::from_ptr(p).to_bytes()).unwrap().to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getcwd() -> io::Result<PathBuf> {
|
||||
let mut buf = Vec::with_capacity(512);
|
||||
loop {
|
||||
unsafe {
|
||||
let ptr = buf.as_mut_ptr() as *mut libc::c_char;
|
||||
if !libc::getcwd(ptr, buf.capacity() as libc::size_t).is_null() {
|
||||
let len = CStr::from_ptr(buf.as_ptr() as *const libc::c_char).to_bytes().len();
|
||||
buf.set_len(len);
|
||||
buf.shrink_to_fit();
|
||||
return Ok(PathBuf::from(OsString::from_vec(buf)));
|
||||
} else {
|
||||
let error = io::Error::last_os_error();
|
||||
if error.raw_os_error() != Some(libc::ERANGE) {
|
||||
return Err(error);
|
||||
}
|
||||
}
|
||||
// Trigger the internal buffer resizing logic of `Vec` by requiring
|
||||
// more space than the current capacity.
|
||||
let cap = buf.capacity();
|
||||
buf.set_len(cap);
|
||||
buf.reserve(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn chdir(p: &path::Path) -> io::Result<()> {
|
||||
let p: &OsStr = p.as_ref();
|
||||
let p = CString::new(p.as_bytes())?;
|
||||
unsafe {
|
||||
match libc::chdir(p.as_ptr()) == (0 as c_int) {
|
||||
true => Ok(()),
|
||||
false => Err(io::Error::last_os_error()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SplitPaths<'a> {
|
||||
iter: iter::Map<slice::Split<'a, u8, fn(&u8) -> bool>, fn(&'a [u8]) -> PathBuf>,
|
||||
}
|
||||
|
||||
pub fn split_paths(unparsed: &OsStr) -> SplitPaths<'_> {
|
||||
fn bytes_to_path(b: &[u8]) -> PathBuf {
|
||||
PathBuf::from(<OsStr as OsStrExt>::from_bytes(b))
|
||||
}
|
||||
fn is_colon(b: &u8) -> bool {
|
||||
*b == b':'
|
||||
}
|
||||
let unparsed = unparsed.as_bytes();
|
||||
SplitPaths {
|
||||
iter: unparsed
|
||||
.split(is_colon as fn(&u8) -> bool)
|
||||
.map(bytes_to_path as fn(&[u8]) -> PathBuf),
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for SplitPaths<'a> {
|
||||
type Item = PathBuf;
|
||||
fn next(&mut self) -> Option<PathBuf> {
|
||||
self.iter.next()
|
||||
}
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct JoinPathsError;
|
||||
|
||||
pub fn join_paths<I, T>(paths: I) -> Result<OsString, JoinPathsError>
|
||||
where
|
||||
I: Iterator<Item = T>,
|
||||
T: AsRef<OsStr>,
|
||||
{
|
||||
let mut joined = Vec::new();
|
||||
let sep = b':';
|
||||
|
||||
for (i, path) in paths.enumerate() {
|
||||
let path = path.as_ref().as_bytes();
|
||||
if i > 0 {
|
||||
joined.push(sep)
|
||||
}
|
||||
if path.contains(&sep) {
|
||||
return Err(JoinPathsError);
|
||||
}
|
||||
joined.extend_from_slice(path);
|
||||
}
|
||||
Ok(OsStringExt::from_vec(joined))
|
||||
}
|
||||
|
||||
impl fmt::Display for JoinPathsError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
"path segment contains separator `:`".fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl StdError for JoinPathsError {
|
||||
#[allow(deprecated)]
|
||||
fn description(&self) -> &str {
|
||||
"failed to join paths"
|
||||
}
|
||||
}
|
||||
|
||||
pub fn current_exe() -> io::Result<PathBuf> {
|
||||
#[cfg(test)]
|
||||
use realstd::env;
|
||||
|
||||
#[cfg(not(test))]
|
||||
use crate::env;
|
||||
|
||||
let exe_path = env::args().next().unwrap();
|
||||
let path = Path::new(&exe_path);
|
||||
path.canonicalize()
|
||||
}
|
||||
|
||||
pub struct Env {
|
||||
iter: vec::IntoIter<(OsString, OsString)>,
|
||||
_dont_send_or_sync_me: PhantomData<*mut ()>,
|
||||
}
|
||||
|
||||
impl Iterator for Env {
|
||||
type Item = (OsString, OsString);
|
||||
fn next(&mut self) -> Option<(OsString, OsString)> {
|
||||
self.iter.next()
|
||||
}
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn environ() -> *mut *const *const c_char {
|
||||
extern "C" {
|
||||
static mut environ: *const *const c_char;
|
||||
}
|
||||
&mut environ
|
||||
}
|
||||
|
||||
pub unsafe fn env_lock() -> StaticMutexGuard {
|
||||
// It is UB to attempt to acquire this mutex reentrantly!
|
||||
static ENV_LOCK: StaticMutex = StaticMutex::new();
|
||||
ENV_LOCK.lock()
|
||||
}
|
||||
|
||||
/// Returns a vector of (variable, value) byte-vector pairs for all the
|
||||
/// environment variables of the current process.
|
||||
pub fn env() -> Env {
|
||||
unsafe {
|
||||
let _guard = env_lock();
|
||||
let mut environ = *environ();
|
||||
if environ.is_null() {
|
||||
panic!("os::env() failure getting env string from OS: {}", io::Error::last_os_error());
|
||||
}
|
||||
let mut result = Vec::new();
|
||||
while !(*environ).is_null() {
|
||||
if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) {
|
||||
result.push(key_value);
|
||||
}
|
||||
environ = environ.add(1);
|
||||
}
|
||||
return Env { iter: result.into_iter(), _dont_send_or_sync_me: PhantomData };
|
||||
}
|
||||
|
||||
fn parse(input: &[u8]) -> Option<(OsString, OsString)> {
|
||||
// Strategy (copied from glibc): Variable name and value are separated
|
||||
// by an ASCII equals sign '='. Since a variable name must not be
|
||||
// empty, allow variable names starting with an equals sign. Skip all
|
||||
// malformed lines.
|
||||
if input.is_empty() {
|
||||
return None;
|
||||
}
|
||||
let pos = memchr::memchr(b'=', &input[1..]).map(|p| p + 1);
|
||||
pos.map(|p| {
|
||||
(
|
||||
OsStringExt::from_vec(input[..p].to_vec()),
|
||||
OsStringExt::from_vec(input[p + 1..].to_vec()),
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getenv(k: &OsStr) -> io::Result<Option<OsString>> {
|
||||
// environment variables with a nul byte can't be set, so their value is
|
||||
// always None as well
|
||||
let k = CString::new(k.as_bytes())?;
|
||||
unsafe {
|
||||
let _guard = env_lock();
|
||||
let s = libc::getenv(k.as_ptr()) as *const libc::c_char;
|
||||
let ret = if s.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(OsStringExt::from_vec(CStr::from_ptr(s).to_bytes().to_vec()))
|
||||
};
|
||||
Ok(ret)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
|
||||
let k = CString::new(k.as_bytes())?;
|
||||
let v = CString::new(v.as_bytes())?;
|
||||
|
||||
unsafe {
|
||||
let _guard = env_lock();
|
||||
cvt(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(drop)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unsetenv(n: &OsStr) -> io::Result<()> {
|
||||
let nbuf = CString::new(n.as_bytes())?;
|
||||
|
||||
unsafe {
|
||||
let _guard = env_lock();
|
||||
cvt(libc::unsetenv(nbuf.as_ptr())).map(drop)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn page_size() -> usize {
|
||||
unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize }
|
||||
}
|
||||
|
||||
pub fn temp_dir() -> PathBuf {
|
||||
crate::env::var_os("TMPDIR").map(PathBuf::from).unwrap_or_else(|| PathBuf::from("/tmp"))
|
||||
}
|
||||
|
||||
pub fn home_dir() -> Option<PathBuf> {
|
||||
crate::env::var_os("HOME").or_else(|| None).map(PathBuf::from)
|
||||
}
|
||||
|
||||
pub fn exit(code: i32) -> ! {
|
||||
unsafe { libc::exit(code as c_int) }
|
||||
}
|
||||
|
||||
pub fn getpid() -> u32 {
|
||||
unsafe { libc::getpid() as u32 }
|
||||
}
|
||||
|
||||
pub fn getppid() -> u32 {
|
||||
unsafe { libc::getppid() as u32 }
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
use crate::ffi::OsStr;
|
||||
use crate::path::Prefix;
|
||||
|
||||
#[inline]
|
||||
pub fn is_sep_byte(b: u8) -> bool {
|
||||
b == b'/'
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_verbatim_sep(b: u8) -> bool {
|
||||
b == b'/'
|
||||
}
|
||||
|
||||
pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> {
|
||||
None
|
||||
}
|
||||
|
||||
pub const MAIN_SEP_STR: &str = "/";
|
||||
pub const MAIN_SEP: char = '/';
|
@ -1,107 +0,0 @@
|
||||
use crate::io::{self, IoSlice, IoSliceMut};
|
||||
use crate::mem;
|
||||
use crate::sync::atomic::AtomicBool;
|
||||
use crate::sys::fd::FileDesc;
|
||||
use crate::sys::{cvt, cvt_r};
|
||||
use libc::{self /*, c_int apparently not used? */};
|
||||
|
||||
pub struct AnonPipe(FileDesc);
|
||||
|
||||
pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
|
||||
static INVALID: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
let mut fds = [0; 2];
|
||||
cvt(unsafe { libc::pipe(fds.as_mut_ptr()) })?;
|
||||
|
||||
let fd0 = FileDesc::new(fds[0]);
|
||||
let fd1 = FileDesc::new(fds[1]);
|
||||
fd0.set_cloexec()?;
|
||||
fd1.set_cloexec()?;
|
||||
Ok((AnonPipe(fd0), AnonPipe(fd1)))
|
||||
}
|
||||
|
||||
impl AnonPipe {
|
||||
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.0.read(buf)
|
||||
}
|
||||
|
||||
pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
self.0.read_vectored(bufs)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_read_vectored(&self) -> bool {
|
||||
self.0.is_read_vectored()
|
||||
}
|
||||
|
||||
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.0.write(buf)
|
||||
}
|
||||
|
||||
pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
self.0.write_vectored(bufs)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_write_vectored(&self) -> bool {
|
||||
self.0.is_write_vectored()
|
||||
}
|
||||
|
||||
pub fn fd(&self) -> &FileDesc {
|
||||
&self.0
|
||||
}
|
||||
pub fn into_fd(self) -> FileDesc {
|
||||
self.0
|
||||
}
|
||||
pub fn diverge(&self) -> ! {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read2(p1: AnonPipe, v1: &mut Vec<u8>, p2: AnonPipe, v2: &mut Vec<u8>) -> io::Result<()> {
|
||||
// Set both pipes into nonblocking mode as we're gonna be reading from both
|
||||
// in the `select` loop below, and we wouldn't want one to block the other!
|
||||
let p1 = p1.into_fd();
|
||||
let p2 = p2.into_fd();
|
||||
p1.set_nonblocking_pipe(true)?;
|
||||
p2.set_nonblocking_pipe(true)?;
|
||||
|
||||
let mut fds: [libc::pollfd; 2] = unsafe { mem::zeroed() };
|
||||
fds[0].fd = p1.raw();
|
||||
fds[0].events = libc::POLLIN;
|
||||
fds[1].fd = p2.raw();
|
||||
fds[1].events = libc::POLLIN;
|
||||
loop {
|
||||
// wait for either pipe to become readable using `poll`
|
||||
cvt_r(|| unsafe { libc::poll(fds.as_mut_ptr(), 2, -1) })?;
|
||||
|
||||
if fds[0].revents != 0 && read(&p1, v1)? {
|
||||
p2.set_nonblocking_pipe(false)?;
|
||||
return p2.read_to_end(v2).map(drop);
|
||||
}
|
||||
if fds[1].revents != 0 && read(&p2, v2)? {
|
||||
p1.set_nonblocking_pipe(false)?;
|
||||
return p1.read_to_end(v1).map(drop);
|
||||
}
|
||||
}
|
||||
|
||||
// Read as much as we can from each pipe, ignoring EWOULDBLOCK or
|
||||
// EAGAIN. If we hit EOF, then this will happen because the underlying
|
||||
// reader will return Ok(0), in which case we'll see `Ok` ourselves. In
|
||||
// this case we flip the other fd back into blocking mode and read
|
||||
// whatever's leftover on that file descriptor.
|
||||
fn read(fd: &FileDesc, dst: &mut Vec<u8>) -> Result<bool, io::Error> {
|
||||
match fd.read_to_end(dst) {
|
||||
Ok(_) => Ok(true),
|
||||
Err(e) => {
|
||||
if e.raw_os_error() == Some(libc::EWOULDBLOCK)
|
||||
|| e.raw_os_error() == Some(libc::EAGAIN)
|
||||
{
|
||||
Ok(false)
|
||||
} else {
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user