Files
rust/src/libstd/sys/unix/os.rs
Alex Crichton 56290a0044 std: Stabilize the prelude module
This commit is an implementation of [RFC 503][rfc] which is a stabilization
story for the prelude. Most of the RFC was directly applied, removing reexports.
Some reexports are kept around, however:

* `range` remains until range syntax has landed to reduce churn.
* `Path` and `GenericPath` remain until path reform lands. This is done to
  prevent many imports of `GenericPath` which will soon be removed.
* All `io` traits remain until I/O reform lands so imports can be rewritten all
  at once to `std::io::prelude::*`.

This is a breaking change because many prelude reexports have been removed, and
the RFC can be consulted for the exact list of removed reexports, as well as to
find the locations of where to import them.

[rfc]: https://github.com/rust-lang/rfcs/blob/master/text/0503-prelude-stabilization.md
[breaking-change]

Closes #20068
2015-01-02 08:54:06 -08:00

253 lines
7.2 KiB
Rust

// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Implementation of `std::os` functionality for unix systems
use prelude::v1::*;
use c_str::ToCStr;
use error::{FromError, Error};
use fmt;
use io::{IoError, IoResult};
use libc::{mod, c_int, c_char, c_void};
use os;
use path::{BytesContainer};
use ptr;
use sync::atomic::{AtomicInt, INIT_ATOMIC_INT, SeqCst};
use sys::fs::FileDesc;
use os::TMPBUF_SZ;
const BUF_BYTES : uint = 2048u;
/// Returns the platform-specific value of errno
pub fn errno() -> int {
#[cfg(any(target_os = "macos",
target_os = "ios",
target_os = "freebsd"))]
fn errno_location() -> *const c_int {
extern {
fn __error() -> *const c_int;
}
unsafe {
__error()
}
}
#[cfg(target_os = "dragonfly")]
fn errno_location() -> *const c_int {
extern {
fn __dfly_error() -> *const c_int;
}
unsafe {
__dfly_error()
}
}
#[cfg(any(target_os = "linux", target_os = "android"))]
fn errno_location() -> *const c_int {
extern {
fn __errno_location() -> *const c_int;
}
unsafe {
__errno_location()
}
}
unsafe {
(*errno_location()) as int
}
}
/// Get a detailed string description for the given error number
pub fn error_string(errno: i32) -> String {
#[cfg(any(target_os = "macos",
target_os = "ios",
target_os = "android",
target_os = "freebsd",
target_os = "dragonfly"))]
fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: libc::size_t)
-> c_int {
extern {
fn strerror_r(errnum: c_int, buf: *mut c_char,
buflen: libc::size_t) -> c_int;
}
unsafe {
strerror_r(errnum, buf, buflen)
}
}
// GNU libc provides a non-compliant version of strerror_r by default
// and requires macros to instead use the POSIX compliant variant.
// So we just use __xpg_strerror_r which is always POSIX compliant
#[cfg(target_os = "linux")]
fn strerror_r(errnum: c_int, buf: *mut c_char,
buflen: libc::size_t) -> c_int {
extern {
fn __xpg_strerror_r(errnum: c_int,
buf: *mut c_char,
buflen: libc::size_t)
-> c_int;
}
unsafe {
__xpg_strerror_r(errnum, buf, buflen)
}
}
let mut buf = [0 as c_char; TMPBUF_SZ];
let p = buf.as_mut_ptr();
unsafe {
if strerror_r(errno as c_int, p, buf.len() as libc::size_t) < 0 {
panic!("strerror_r failure");
}
String::from_raw_buf(p as *const u8)
}
}
pub unsafe fn pipe() -> IoResult<(FileDesc, FileDesc)> {
let mut fds = [0; 2];
if libc::pipe(fds.as_mut_ptr()) == 0 {
Ok((FileDesc::new(fds[0], true), FileDesc::new(fds[1], true)))
} else {
Err(super::last_error())
}
}
pub fn getcwd() -> IoResult<Path> {
use c_str::CString;
let mut buf = [0 as c_char; BUF_BYTES];
unsafe {
if libc::getcwd(buf.as_mut_ptr(), buf.len() as libc::size_t).is_null() {
Err(IoError::last_error())
} else {
Ok(Path::new(CString::new(buf.as_ptr(), false)))
}
}
}
pub unsafe fn get_env_pairs() -> Vec<Vec<u8>> {
use c_str::CString;
extern {
fn rust_env_pairs() -> *const *const c_char;
}
let mut environ = rust_env_pairs();
if environ as uint == 0 {
panic!("os::env() failure getting env string from OS: {}",
os::last_os_error());
}
let mut result = Vec::new();
while *environ != 0 as *const _ {
let env_pair =
CString::new(*environ, false).as_bytes_no_nul().to_vec();
result.push(env_pair);
environ = environ.offset(1);
}
result
}
pub fn split_paths(unparsed: &[u8]) -> Vec<Path> {
unparsed.split(|b| *b == b':').map(Path::new).collect()
}
pub fn join_paths<T: BytesContainer>(paths: &[T]) -> Result<Vec<u8>, &'static str> {
let mut joined = Vec::new();
let sep = b':';
for (i, path) in paths.iter().map(|p| p.container_as_bytes()).enumerate() {
if i > 0 { joined.push(sep) }
if path.contains(&sep) { return Err("path segment contains separator `:`") }
joined.push_all(path);
}
Ok(joined)
}
#[cfg(target_os = "freebsd")]
pub fn load_self() -> Option<Vec<u8>> {
unsafe {
use libc::funcs::bsd44::*;
use libc::consts::os::extra::*;
let mut mib = vec![CTL_KERN as c_int,
KERN_PROC as c_int,
KERN_PROC_PATHNAME as c_int,
-1 as c_int];
let mut sz: libc::size_t = 0;
let err = sysctl(mib.as_mut_ptr(), mib.len() as ::libc::c_uint,
ptr::null_mut(), &mut sz, ptr::null_mut(),
0u as libc::size_t);
if err != 0 { return None; }
if sz == 0 { return None; }
let mut v: Vec<u8> = Vec::with_capacity(sz as uint);
let err = sysctl(mib.as_mut_ptr(), mib.len() as ::libc::c_uint,
v.as_mut_ptr() as *mut libc::c_void, &mut sz,
ptr::null_mut(), 0u as libc::size_t);
if err != 0 { return None; }
if sz == 0 { return None; }
v.set_len(sz as uint - 1); // chop off trailing NUL
Some(v)
}
}
#[cfg(target_os = "dragonfly")]
pub fn load_self() -> Option<Vec<u8>> {
use std::io;
match io::fs::readlink(&Path::new("/proc/curproc/file")) {
Ok(path) => Some(path.into_vec()),
Err(..) => None
}
}
#[cfg(any(target_os = "linux", target_os = "android"))]
pub fn load_self() -> Option<Vec<u8>> {
use std::io;
match io::fs::readlink(&Path::new("/proc/self/exe")) {
Ok(path) => Some(path.into_vec()),
Err(..) => None
}
}
#[cfg(any(target_os = "macos", target_os = "ios"))]
pub fn load_self() -> Option<Vec<u8>> {
unsafe {
use libc::funcs::extra::_NSGetExecutablePath;
let mut sz: u32 = 0;
_NSGetExecutablePath(ptr::null_mut(), &mut sz);
if sz == 0 { return None; }
let mut v: Vec<u8> = Vec::with_capacity(sz as uint);
let err = _NSGetExecutablePath(v.as_mut_ptr() as *mut i8, &mut sz);
if err != 0 { return None; }
v.set_len(sz as uint - 1); // chop off trailing NUL
Some(v)
}
}
pub fn chdir(p: &Path) -> IoResult<()> {
p.with_c_str(|buf| {
unsafe {
match libc::chdir(buf) == (0 as c_int) {
true => Ok(()),
false => Err(IoError::last_error()),
}
}
})
}
pub fn page_size() -> uint {
unsafe {
libc::sysconf(libc::_SC_PAGESIZE) as uint
}
}