about summary refs log tree commit diff
path: root/src/libstd/sys/unix
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstd/sys/unix')
-rw-r--r--src/libstd/sys/unix/backtrace.rs6
-rw-r--r--src/libstd/sys/unix/ext.rs12
-rw-r--r--src/libstd/sys/unix/fs.rs42
-rw-r--r--src/libstd/sys/unix/fs2.rs44
-rw-r--r--src/libstd/sys/unix/mod.rs5
-rw-r--r--src/libstd/sys/unix/net.rs4
-rw-r--r--src/libstd/sys/unix/os.rs28
-rw-r--r--src/libstd/sys/unix/pipe.rs6
-rw-r--r--src/libstd/sys/unix/process.rs249
-rw-r--r--src/libstd/sys/unix/process2.rs9
-rw-r--r--src/libstd/sys/unix/thread.rs6
11 files changed, 331 insertions, 80 deletions
diff --git a/src/libstd/sys/unix/backtrace.rs b/src/libstd/sys/unix/backtrace.rs
index 5e512e9261b..8b560339f30 100644
--- a/src/libstd/sys/unix/backtrace.rs
+++ b/src/libstd/sys/unix/backtrace.rs
@@ -85,7 +85,7 @@
 
 use prelude::v1::*;
 
-use ffi;
+use ffi::CStr;
 use old_io::IoResult;
 use libc;
 use mem;
@@ -233,7 +233,7 @@ fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> {
         output(w, idx,addr, None)
     } else {
         output(w, idx, addr, Some(unsafe {
-            ffi::c_str_to_bytes(&info.dli_sname)
+            CStr::from_ptr(info.dli_sname).to_bytes()
         }))
     }
 }
@@ -364,7 +364,7 @@ fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> {
     if ret == 0 || data.is_null() {
         output(w, idx, addr, None)
     } else {
-        output(w, idx, addr, Some(unsafe { ffi::c_str_to_bytes(&data) }))
+        output(w, idx, addr, Some(unsafe { CStr::from_ptr(data).to_bytes() }))
     }
 }
 
diff --git a/src/libstd/sys/unix/ext.rs b/src/libstd/sys/unix/ext.rs
index bbbe022fbaf..b8b9dcfb3c6 100644
--- a/src/libstd/sys/unix/ext.rs
+++ b/src/libstd/sys/unix/ext.rs
@@ -33,7 +33,7 @@
 
 use prelude::v1::*;
 
-use ffi::{CString, OsStr, OsString};
+use ffi::{CString, NulError, OsStr, OsString};
 use fs::{self, Permissions, OpenOptions};
 use net;
 use mem;
@@ -155,7 +155,7 @@ pub trait OsStrExt {
     fn as_bytes(&self) -> &[u8];
 
     /// Convert the `OsStr` slice into a `CString`.
-    fn to_cstring(&self) -> CString;
+    fn to_cstring(&self) -> Result<CString, NulError>;
 }
 
 impl OsStrExt for OsStr {
@@ -166,8 +166,8 @@ impl OsStrExt for OsStr {
         &self.as_inner().inner
     }
 
-    fn to_cstring(&self) -> CString {
-        CString::from_slice(self.as_bytes())
+    fn to_cstring(&self) -> Result<CString, NulError> {
+        CString::new(self.as_bytes())
     }
 }
 
@@ -249,5 +249,7 @@ impl ExitStatusExt for process::ExitStatus {
 /// Includes all extension traits, and some important type definitions.
 pub mod prelude {
     #[doc(no_inline)]
-    pub use super::{Fd, AsRawFd, OsStrExt, OsStringExt, PermissionsExt, CommandExt, ExitStatusExt};
+    pub use super::{Fd, AsRawFd, OsStrExt, OsStringExt, PermissionsExt};
+    #[doc(no_inline)]
+    pub use super::{CommandExt, ExitStatusExt};
 }
diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs
index 0ee2b5b6809..5c847002d23 100644
--- a/src/libstd/sys/unix/fs.rs
+++ b/src/libstd/sys/unix/fs.rs
@@ -12,7 +12,7 @@
 
 use prelude::v1::*;
 
-use ffi::{self, CString};
+use ffi::{CString, CStr};
 use old_io::{FilePermission, Write, UnstableFileStat, Open, FileAccess, FileMode};
 use old_io::{IoResult, FileStat, SeekStyle};
 use old_io::{Read, Truncate, SeekCur, SeekSet, ReadWrite, SeekEnd, Append};
@@ -151,8 +151,8 @@ impl Drop for FileDesc {
     }
 }
 
-fn cstr(path: &Path) -> CString {
-    CString::from_slice(path.as_vec())
+fn cstr(path: &Path) -> IoResult<CString> {
+    Ok(try!(CString::new(path.as_vec())))
 }
 
 pub fn open(path: &Path, fm: FileMode, fa: FileAccess) -> IoResult<FileDesc> {
@@ -170,7 +170,7 @@ pub fn open(path: &Path, fm: FileMode, fa: FileAccess) -> IoResult<FileDesc> {
                             libc::S_IRUSR | libc::S_IWUSR),
     };
 
-    let path = cstr(path);
+    let path = try!(cstr(path));
     match retry(|| unsafe { libc::open(path.as_ptr(), flags, mode) }) {
         -1 => Err(super::last_error()),
         fd => Ok(FileDesc::new(fd, true)),
@@ -178,7 +178,7 @@ pub fn open(path: &Path, fm: FileMode, fa: FileAccess) -> IoResult<FileDesc> {
 }
 
 pub fn mkdir(p: &Path, mode: uint) -> IoResult<()> {
-    let p = cstr(p);
+    let p = try!(cstr(p));
     mkerr_libc(unsafe { libc::mkdir(p.as_ptr(), mode as libc::mode_t) })
 }
 
@@ -203,7 +203,7 @@ pub fn readdir(p: &Path) -> IoResult<Vec<Path>> {
     let mut buf = Vec::<u8>::with_capacity(size as uint);
     let ptr = buf.as_mut_ptr() as *mut dirent_t;
 
-    let p = CString::from_slice(p.as_vec());
+    let p = try!(CString::new(p.as_vec()));
     let dir_ptr = unsafe {opendir(p.as_ptr())};
 
     if dir_ptr as uint != 0 {
@@ -212,7 +212,7 @@ pub fn readdir(p: &Path) -> IoResult<Vec<Path>> {
         while unsafe { readdir_r(dir_ptr, ptr, &mut entry_ptr) == 0 } {
             if entry_ptr.is_null() { break }
             paths.push(unsafe {
-                Path::new(ffi::c_str_to_bytes(&rust_list_dir_val(entry_ptr)))
+                Path::new(CStr::from_ptr(rust_list_dir_val(entry_ptr)).to_bytes())
             });
         }
         assert_eq!(unsafe { closedir(dir_ptr) }, 0);
@@ -223,39 +223,39 @@ pub fn readdir(p: &Path) -> IoResult<Vec<Path>> {
 }
 
 pub fn unlink(p: &Path) -> IoResult<()> {
-    let p = cstr(p);
+    let p = try!(cstr(p));
     mkerr_libc(unsafe { libc::unlink(p.as_ptr()) })
 }
 
 pub fn rename(old: &Path, new: &Path) -> IoResult<()> {
-    let old = cstr(old);
-    let new = cstr(new);
+    let old = try!(cstr(old));
+    let new = try!(cstr(new));
     mkerr_libc(unsafe {
         libc::rename(old.as_ptr(), new.as_ptr())
     })
 }
 
 pub fn chmod(p: &Path, mode: uint) -> IoResult<()> {
-    let p = cstr(p);
+    let p = try!(cstr(p));
     mkerr_libc(retry(|| unsafe {
         libc::chmod(p.as_ptr(), mode as libc::mode_t)
     }))
 }
 
 pub fn rmdir(p: &Path) -> IoResult<()> {
-    let p = cstr(p);
+    let p = try!(cstr(p));
     mkerr_libc(unsafe { libc::rmdir(p.as_ptr()) })
 }
 
 pub fn chown(p: &Path, uid: int, gid: int) -> IoResult<()> {
-    let p = cstr(p);
+    let p = try!(cstr(p));
     mkerr_libc(retry(|| unsafe {
         libc::chown(p.as_ptr(), uid as libc::uid_t, gid as libc::gid_t)
     }))
 }
 
 pub fn readlink(p: &Path) -> IoResult<Path> {
-    let c_path = cstr(p);
+    let c_path = try!(cstr(p));
     let p = c_path.as_ptr();
     let mut len = unsafe { libc::pathconf(p as *mut _, libc::_PC_NAME_MAX) };
     if len == -1 {
@@ -276,14 +276,14 @@ pub fn readlink(p: &Path) -> IoResult<Path> {
 }
 
 pub fn symlink(src: &Path, dst: &Path) -> IoResult<()> {
-    let src = cstr(src);
-    let dst = cstr(dst);
+    let src = try!(cstr(src));
+    let dst = try!(cstr(dst));
     mkerr_libc(unsafe { libc::symlink(src.as_ptr(), dst.as_ptr()) })
 }
 
 pub fn link(src: &Path, dst: &Path) -> IoResult<()> {
-    let src = cstr(src);
-    let dst = cstr(dst);
+    let src = try!(cstr(src));
+    let dst = try!(cstr(dst));
     mkerr_libc(unsafe { libc::link(src.as_ptr(), dst.as_ptr()) })
 }
 
@@ -331,7 +331,7 @@ fn mkstat(stat: &libc::stat) -> FileStat {
 }
 
 pub fn stat(p: &Path) -> IoResult<FileStat> {
-    let p = cstr(p);
+    let p = try!(cstr(p));
     let mut stat: libc::stat = unsafe { mem::zeroed() };
     match unsafe { libc::stat(p.as_ptr(), &mut stat) } {
         0 => Ok(mkstat(&stat)),
@@ -340,7 +340,7 @@ pub fn stat(p: &Path) -> IoResult<FileStat> {
 }
 
 pub fn lstat(p: &Path) -> IoResult<FileStat> {
-    let p = cstr(p);
+    let p = try!(cstr(p));
     let mut stat: libc::stat = unsafe { mem::zeroed() };
     match unsafe { libc::lstat(p.as_ptr(), &mut stat) } {
         0 => Ok(mkstat(&stat)),
@@ -349,7 +349,7 @@ pub fn lstat(p: &Path) -> IoResult<FileStat> {
 }
 
 pub fn utime(p: &Path, atime: u64, mtime: u64) -> IoResult<()> {
-    let p = cstr(p);
+    let p = try!(cstr(p));
     let buf = libc::utimbuf {
         actime: (atime / 1000) as libc::time_t,
         modtime: (mtime / 1000) as libc::time_t,
diff --git a/src/libstd/sys/unix/fs2.rs b/src/libstd/sys/unix/fs2.rs
index e5904b074bc..92a47c6c385 100644
--- a/src/libstd/sys/unix/fs2.rs
+++ b/src/libstd/sys/unix/fs2.rs
@@ -12,7 +12,7 @@ use core::prelude::*;
 use io::prelude::*;
 use os::unix::prelude::*;
 
-use ffi::{self, CString, OsString, AsOsStr, OsStr};
+use ffi::{CString, CStr, OsString, AsOsStr, OsStr};
 use io::{self, Error, Seek, SeekFrom};
 use libc::{self, c_int, c_void, size_t, off_t, c_char, mode_t};
 use mem;
@@ -147,8 +147,7 @@ impl DirEntry {
             fn rust_list_dir_val(ptr: *mut libc::dirent_t) -> *const c_char;
         }
         unsafe {
-            let ptr = rust_list_dir_val(self.dirent);
-            ffi::c_str_to_bytes(mem::copy_lifetime(self, &ptr))
+            CStr::from_ptr(rust_list_dir_val(self.dirent)).to_bytes()
         }
     }
 }
@@ -204,7 +203,7 @@ impl File {
             (true, false) |
             (false, false) => libc::O_RDONLY,
         };
-        let path = cstr(path);
+        let path = try!(cstr(path));
         let fd = try!(cvt_r(|| unsafe {
             libc::open(path.as_ptr(), flags, opts.mode)
         }));
@@ -268,19 +267,20 @@ impl File {
     pub fn fd(&self) -> &FileDesc { &self.0 }
 }
 
-fn cstr(path: &Path) -> CString {
-    CString::from_slice(path.as_os_str().as_bytes())
+fn cstr(path: &Path) -> io::Result<CString> {
+    let cstring = try!(path.as_os_str().to_cstring());
+    Ok(cstring)
 }
 
 pub fn mkdir(p: &Path) -> io::Result<()> {
-    let p = cstr(p);
+    let p = try!(cstr(p));
     try!(cvt(unsafe { libc::mkdir(p.as_ptr(), 0o777) }));
     Ok(())
 }
 
 pub fn readdir(p: &Path) -> io::Result<ReadDir> {
     let root = Rc::new(p.to_path_buf());
-    let p = cstr(p);
+    let p = try!(cstr(p));
     unsafe {
         let ptr = libc::opendir(p.as_ptr());
         if ptr.is_null() {
@@ -292,32 +292,32 @@ pub fn readdir(p: &Path) -> io::Result<ReadDir> {
 }
 
 pub fn unlink(p: &Path) -> io::Result<()> {
-    let p = cstr(p);
+    let p = try!(cstr(p));
     try!(cvt(unsafe { libc::unlink(p.as_ptr()) }));
     Ok(())
 }
 
 pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
-    let old = cstr(old);
-    let new = cstr(new);
+    let old = try!(cstr(old));
+    let new = try!(cstr(new));
     try!(cvt(unsafe { libc::rename(old.as_ptr(), new.as_ptr()) }));
     Ok(())
 }
 
 pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> {
-    let p = cstr(p);
+    let p = try!(cstr(p));
     try!(cvt_r(|| unsafe { libc::chmod(p.as_ptr(), perm.mode) }));
     Ok(())
 }
 
 pub fn rmdir(p: &Path) -> io::Result<()> {
-    let p = cstr(p);
+    let p = try!(cstr(p));
     try!(cvt(unsafe { libc::rmdir(p.as_ptr()) }));
     Ok(())
 }
 
 pub fn chown(p: &Path, uid: isize, gid: isize) -> io::Result<()> {
-    let p = cstr(p);
+    let p = try!(cstr(p));
     try!(cvt_r(|| unsafe {
         libc::chown(p.as_ptr(), uid as libc::uid_t, gid as libc::gid_t)
     }));
@@ -325,7 +325,7 @@ pub fn chown(p: &Path, uid: isize, gid: isize) -> io::Result<()> {
 }
 
 pub fn readlink(p: &Path) -> io::Result<PathBuf> {
-    let c_path = cstr(p);
+    let c_path = try!(cstr(p));
     let p = c_path.as_ptr();
     let mut len = unsafe { libc::pathconf(p as *mut _, libc::_PC_NAME_MAX) };
     if len < 0 {
@@ -343,35 +343,35 @@ pub fn readlink(p: &Path) -> io::Result<PathBuf> {
 }
 
 pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> {
-    let src = cstr(src);
-    let dst = cstr(dst);
+    let src = try!(cstr(src));
+    let dst = try!(cstr(dst));
     try!(cvt(unsafe { libc::symlink(src.as_ptr(), dst.as_ptr()) }));
     Ok(())
 }
 
 pub fn link(src: &Path, dst: &Path) -> io::Result<()> {
-    let src = cstr(src);
-    let dst = cstr(dst);
+    let src = try!(cstr(src));
+    let dst = try!(cstr(dst));
     try!(cvt(unsafe { libc::link(src.as_ptr(), dst.as_ptr()) }));
     Ok(())
 }
 
 pub fn stat(p: &Path) -> io::Result<FileAttr> {
-    let p = cstr(p);
+    let p = try!(cstr(p));
     let mut stat: libc::stat = unsafe { mem::zeroed() };
     try!(cvt(unsafe { libc::stat(p.as_ptr(), &mut stat) }));
     Ok(FileAttr { stat: stat })
 }
 
 pub fn lstat(p: &Path) -> io::Result<FileAttr> {
-    let p = cstr(p);
+    let p = try!(cstr(p));
     let mut stat: libc::stat = unsafe { mem::zeroed() };
     try!(cvt(unsafe { libc::lstat(p.as_ptr(), &mut stat) }));
     Ok(FileAttr { stat: stat })
 }
 
 pub fn utimes(p: &Path, atime: u64, mtime: u64) -> io::Result<()> {
-    let p = cstr(p);
+    let p = try!(cstr(p));
     let buf = [super::ms_to_timeval(atime), super::ms_to_timeval(mtime)];
     try!(cvt(unsafe { c::utimes(p.as_ptr(), buf.as_ptr()) }));
     Ok(())
diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs
index 850189140d1..b79ad7031fa 100644
--- a/src/libstd/sys/unix/mod.rs
+++ b/src/libstd/sys/unix/mod.rs
@@ -17,7 +17,7 @@
 
 use prelude::v1::*;
 
-use ffi;
+use ffi::CStr;
 use io::{self, ErrorKind};
 use libc;
 use num::{Int, SignedInt};
@@ -91,7 +91,8 @@ pub fn last_gai_error(s: libc::c_int) -> IoError {
 
     let mut err = decode_error(s);
     err.detail = Some(unsafe {
-        str::from_utf8(ffi::c_str_to_bytes(&gai_strerror(s))).unwrap().to_string()
+        let data = CStr::from_ptr(gai_strerror(s));
+        str::from_utf8(data.to_bytes()).unwrap().to_string()
     });
     err
 }
diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs
index 54aec7cf4b1..83b6a14b78d 100644
--- a/src/libstd/sys/unix/net.rs
+++ b/src/libstd/sys/unix/net.rs
@@ -10,7 +10,7 @@
 
 use prelude::v1::*;
 
-use ffi;
+use ffi::CStr;
 use io;
 use libc::{self, c_int, size_t};
 use str;
@@ -31,7 +31,7 @@ pub fn cvt_gai(err: c_int) -> io::Result<()> {
     if err == 0 { return Ok(()) }
 
     let detail = unsafe {
-        str::from_utf8(ffi::c_str_to_bytes(&c::gai_strerror(err))).unwrap()
+        str::from_utf8(CStr::from_ptr(c::gai_strerror(err)).to_bytes()).unwrap()
             .to_string()
     };
     Err(io::Error::new(io::ErrorKind::Other,
diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs
index 5fe84cafb71..3d1ef3a2c37 100644
--- a/src/libstd/sys/unix/os.rs
+++ b/src/libstd/sys/unix/os.rs
@@ -14,7 +14,7 @@ use prelude::v1::*;
 use os::unix::*;
 
 use error::Error as StdError;
-use ffi::{self, CString, OsString, OsStr, AsOsStr};
+use ffi::{CString, CStr, OsString, OsStr, AsOsStr};
 use fmt;
 use iter;
 use libc::{self, c_int, c_char, c_void};
@@ -88,7 +88,7 @@ pub fn error_string(errno: i32) -> String {
         }
 
         let p = p as *const _;
-        str::from_utf8(ffi::c_str_to_bytes(&p)).unwrap().to_string()
+        str::from_utf8(CStr::from_ptr(p).to_bytes()).unwrap().to_string()
     }
 }
 
@@ -98,13 +98,13 @@ pub fn getcwd() -> IoResult<Path> {
         if libc::getcwd(buf.as_mut_ptr(), buf.len() as libc::size_t).is_null() {
             Err(IoError::last_error())
         } else {
-            Ok(Path::new(ffi::c_str_to_bytes(&buf.as_ptr())))
+            Ok(Path::new(CStr::from_ptr(buf.as_ptr()).to_bytes()))
         }
     }
 }
 
 pub fn chdir(p: &Path) -> IoResult<()> {
-    let p = CString::from_slice(p.as_vec());
+    let p = CString::new(p.as_vec()).unwrap();
     unsafe {
         match libc::chdir(p.as_ptr()) == (0 as c_int) {
             true => Ok(()),
@@ -211,7 +211,7 @@ pub fn current_exe() -> IoResult<Path> {
         if v.is_null() {
             Err(IoError::last_error())
         } else {
-            Ok(Path::new(ffi::c_str_to_bytes(&v).to_vec()))
+            Ok(Path::new(CStr::from_ptr(&v).to_bytes().to_vec()))
         }
     }
 }
@@ -266,7 +266,7 @@ pub fn args() -> Args {
         let (argc, argv) = (*_NSGetArgc() as isize,
                             *_NSGetArgv() as *const *const c_char);
         range(0, argc as isize).map(|i| {
-            let bytes = ffi::c_str_to_bytes(&*argv.offset(i)).to_vec();
+            let bytes = CStr::from_ptr(*argv.offset(i)).to_bytes().to_vec();
             OsStringExt::from_vec(bytes)
         }).collect::<Vec<_>>()
     };
@@ -324,7 +324,7 @@ pub fn args() -> Args {
             let tmp = objc_msgSend(args, object_at_sel, i);
             let utf_c_str: *const libc::c_char =
                 mem::transmute(objc_msgSend(tmp, utf8_sel));
-            let bytes = ffi::c_str_to_bytes(&utf_c_str);
+            let bytes = CStr::from_ptr(utf_c_str).to_bytes();
             res.push(OsString::from_str(str::from_utf8(bytes).unwrap()))
         }
     }
@@ -380,7 +380,7 @@ pub fn env() -> Env {
         }
         let mut result = Vec::new();
         while *environ != ptr::null() {
-            result.push(parse(ffi::c_str_to_bytes(&*environ)));
+            result.push(parse(CStr::from_ptr(*environ).to_bytes()));
             environ = environ.offset(1);
         }
         Env { iter: result.into_iter(), _dont_send_or_sync_me: 0 as *mut _ }
@@ -397,20 +397,20 @@ pub fn env() -> Env {
 
 pub fn getenv(k: &OsStr) -> Option<OsString> {
     unsafe {
-        let s = CString::from_slice(k.as_bytes());
+        let s = k.to_cstring().unwrap();
         let s = libc::getenv(s.as_ptr()) as *const _;
         if s.is_null() {
             None
         } else {
-            Some(OsStringExt::from_vec(ffi::c_str_to_bytes(&s).to_vec()))
+            Some(OsStringExt::from_vec(CStr::from_ptr(s).to_bytes().to_vec()))
         }
     }
 }
 
 pub fn setenv(k: &OsStr, v: &OsStr) {
     unsafe {
-        let k = CString::from_slice(k.as_bytes());
-        let v = CString::from_slice(v.as_bytes());
+        let k = k.to_cstring().unwrap();
+        let v = v.to_cstring().unwrap();
         if libc::funcs::posix01::unistd::setenv(k.as_ptr(), v.as_ptr(), 1) != 0 {
             panic!("failed setenv: {}", IoError::last_error());
         }
@@ -419,7 +419,7 @@ pub fn setenv(k: &OsStr, v: &OsStr) {
 
 pub fn unsetenv(n: &OsStr) {
     unsafe {
-        let nbuf = CString::from_slice(n.as_bytes());
+        let nbuf = n.to_cstring().unwrap();
         if libc::funcs::posix01::unistd::unsetenv(nbuf.as_ptr()) != 0 {
             panic!("failed unsetenv: {}", IoError::last_error());
         }
@@ -480,7 +480,7 @@ pub fn home_dir() -> Option<Path> {
                 _ => return None
             }
             let ptr = passwd.pw_dir as *const _;
-            let bytes = ffi::c_str_to_bytes(&ptr).to_vec();
+            let bytes = CStr::from_ptr(ptr).to_bytes().to_vec();
             return Some(OsStringExt::from_vec(bytes))
         }
     }
diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs
index 45d5b1506c3..3c9cdc65975 100644
--- a/src/libstd/sys/unix/pipe.rs
+++ b/src/libstd/sys/unix/pipe.rs
@@ -38,7 +38,7 @@ fn addr_to_sockaddr_un(addr: &CString,
             mem::size_of::<libc::sockaddr_un>());
     let s = unsafe { &mut *(storage as *mut _ as *mut libc::sockaddr_un) };
 
-    let len = addr.len();
+    let len = addr.as_bytes().len();
     if len > s.sun_path.len() - 1 {
         return Err(IoError {
             kind: old_io::InvalidInput,
@@ -47,8 +47,8 @@ fn addr_to_sockaddr_un(addr: &CString,
         })
     }
     s.sun_family = libc::AF_UNIX as libc::sa_family_t;
-    for (slot, value) in s.sun_path.iter_mut().zip(addr.iter()) {
-        *slot = *value;
+    for (slot, value) in s.sun_path.iter_mut().zip(addr.as_bytes().iter()) {
+        *slot = *value as libc::c_char;
     }
 
     // count the null terminator
diff --git a/src/libstd/sys/unix/process.rs b/src/libstd/sys/unix/process.rs
index f954024b0e9..b30ac889120 100644
--- a/src/libstd/sys/unix/process.rs
+++ b/src/libstd/sys/unix/process.rs
@@ -12,6 +12,7 @@ use prelude::v1::*;
 use self::Req::*;
 
 use collections::HashMap;
+#[cfg(stage0)]
 use collections::hash_map::Hasher;
 use ffi::CString;
 use hash::Hash;
@@ -63,6 +64,7 @@ impl Process {
         mkerr_libc(r)
     }
 
+    #[cfg(stage0)]
     pub fn spawn<K, V, C, P>(cfg: &C, in_fd: Option<P>,
                               out_fd: Option<P>, err_fd: Option<P>)
                               -> IoResult<Process>
@@ -278,6 +280,214 @@ impl Process {
             })
         })
     }
+    #[cfg(not(stage0))]
+    pub fn spawn<K, V, C, P>(cfg: &C, in_fd: Option<P>,
+                              out_fd: Option<P>, err_fd: Option<P>)
+                              -> IoResult<Process>
+        where C: ProcessConfig<K, V>, P: AsInner<FileDesc>,
+              K: BytesContainer + Eq + Hash, V: BytesContainer
+    {
+        use libc::funcs::posix88::unistd::{fork, dup2, close, chdir, execvp};
+        use libc::funcs::bsd44::getdtablesize;
+
+        mod rustrt {
+            extern {
+                pub fn rust_unset_sigprocmask();
+            }
+        }
+
+        unsafe fn set_cloexec(fd: c_int) {
+            let ret = c::ioctl(fd, c::FIOCLEX);
+            assert_eq!(ret, 0);
+        }
+
+        let dirp = cfg.cwd().map(|c| c.as_ptr()).unwrap_or(ptr::null());
+
+        // temporary until unboxed closures land
+        let cfg = unsafe {
+            mem::transmute::<&ProcessConfig<K,V>,&'static ProcessConfig<K,V>>(cfg)
+        };
+
+        with_envp(cfg.env(), move|envp: *const c_void| {
+            with_argv(cfg.program(), cfg.args(), move|argv: *const *const libc::c_char| unsafe {
+                let (input, mut output) = try!(sys::os::pipe());
+
+                // We may use this in the child, so perform allocations before the
+                // fork
+                let devnull = b"/dev/null\0";
+
+                set_cloexec(output.fd());
+
+                let pid = fork();
+                if pid < 0 {
+                    return Err(super::last_error())
+                } else if pid > 0 {
+                    #[inline]
+                    fn combine(arr: &[u8]) -> i32 {
+                        let a = arr[0] as u32;
+                        let b = arr[1] as u32;
+                        let c = arr[2] as u32;
+                        let d = arr[3] as u32;
+
+                        ((a << 24) | (b << 16) | (c << 8) | (d << 0)) as i32
+                    }
+
+                    let p = Process{ pid: pid };
+                    drop(output);
+                    let mut bytes = [0; 8];
+                    return match input.read(&mut bytes) {
+                        Ok(8) => {
+                            assert!(combine(CLOEXEC_MSG_FOOTER) == combine(&bytes[4.. 8]),
+                                "Validation on the CLOEXEC pipe failed: {:?}", bytes);
+                            let errno = combine(&bytes[0.. 4]);
+                            assert!(p.wait(0).is_ok(), "wait(0) should either return Ok or panic");
+                            Err(super::decode_error(errno))
+                        }
+                        Err(ref e) if e.kind == EndOfFile => Ok(p),
+                        Err(e) => {
+                            assert!(p.wait(0).is_ok(), "wait(0) should either return Ok or panic");
+                            panic!("the CLOEXEC pipe failed: {:?}", e)
+                        },
+                        Ok(..) => { // pipe I/O up to PIPE_BUF bytes should be atomic
+                            assert!(p.wait(0).is_ok(), "wait(0) should either return Ok or panic");
+                            panic!("short read on the CLOEXEC pipe")
+                        }
+                    };
+                }
+
+                // And at this point we've reached a special time in the life of the
+                // child. The child must now be considered hamstrung and unable to
+                // do anything other than syscalls really. Consider the following
+                // scenario:
+                //
+                //      1. Thread A of process 1 grabs the malloc() mutex
+                //      2. Thread B of process 1 forks(), creating thread C
+                //      3. Thread C of process 2 then attempts to malloc()
+                //      4. The memory of process 2 is the same as the memory of
+                //         process 1, so the mutex is locked.
+                //
+                // This situation looks a lot like deadlock, right? It turns out
+                // that this is what pthread_atfork() takes care of, which is
+                // presumably implemented across platforms. The first thing that
+                // threads to *before* forking is to do things like grab the malloc
+                // mutex, and then after the fork they unlock it.
+                //
+                // Despite this information, libnative's spawn has been witnessed to
+                // deadlock on both OSX and FreeBSD. I'm not entirely sure why, but
+                // all collected backtraces point at malloc/free traffic in the
+                // child spawned process.
+                //
+                // For this reason, the block of code below should contain 0
+                // invocations of either malloc of free (or their related friends).
+                //
+                // As an example of not having malloc/free traffic, we don't close
+                // this file descriptor by dropping the FileDesc (which contains an
+                // allocation). Instead we just close it manually. This will never
+                // have the drop glue anyway because this code never returns (the
+                // child will either exec() or invoke libc::exit)
+                let _ = libc::close(input.fd());
+
+                fn fail(output: &mut FileDesc) -> ! {
+                    let errno = sys::os::errno() as u32;
+                    let bytes = [
+                        (errno >> 24) as u8,
+                        (errno >> 16) as u8,
+                        (errno >>  8) as u8,
+                        (errno >>  0) as u8,
+                        CLOEXEC_MSG_FOOTER[0], CLOEXEC_MSG_FOOTER[1],
+                        CLOEXEC_MSG_FOOTER[2], CLOEXEC_MSG_FOOTER[3]
+                    ];
+                    // pipe I/O up to PIPE_BUF bytes should be atomic
+                    assert!(output.write(&bytes).is_ok());
+                    unsafe { libc::_exit(1) }
+                }
+
+                rustrt::rust_unset_sigprocmask();
+
+                // If a stdio file descriptor is set to be ignored (via a -1 file
+                // descriptor), then we don't actually close it, but rather open
+                // up /dev/null into that file descriptor. Otherwise, the first file
+                // descriptor opened up in the child would be numbered as one of the
+                // stdio file descriptors, which is likely to wreak havoc.
+                let setup = |src: Option<P>, dst: c_int| {
+                    let src = match src {
+                        None => {
+                            let flags = if dst == libc::STDIN_FILENO {
+                                libc::O_RDONLY
+                            } else {
+                                libc::O_RDWR
+                            };
+                            libc::open(devnull.as_ptr() as *const _, flags, 0)
+                        }
+                        Some(obj) => {
+                            let fd = obj.as_inner().fd();
+                            // Leak the memory and the file descriptor. We're in the
+                            // child now an all our resources are going to be
+                            // cleaned up very soon
+                            mem::forget(obj);
+                            fd
+                        }
+                    };
+                    src != -1 && retry(|| dup2(src, dst)) != -1
+                };
+
+                if !setup(in_fd, libc::STDIN_FILENO) { fail(&mut output) }
+                if !setup(out_fd, libc::STDOUT_FILENO) { fail(&mut output) }
+                if !setup(err_fd, libc::STDERR_FILENO) { fail(&mut output) }
+
+                // close all other fds
+                for fd in (3..getdtablesize()).rev() {
+                    if fd != output.fd() {
+                        let _ = close(fd as c_int);
+                    }
+                }
+
+                match cfg.gid() {
+                    Some(u) => {
+                        if libc::setgid(u as libc::gid_t) != 0 {
+                            fail(&mut output);
+                        }
+                    }
+                    None => {}
+                }
+                match cfg.uid() {
+                    Some(u) => {
+                        // When dropping privileges from root, the `setgroups` call
+                        // will remove any extraneous groups. If we don't call this,
+                        // then even though our uid has dropped, we may still have
+                        // groups that enable us to do super-user things. This will
+                        // fail if we aren't root, so don't bother checking the
+                        // return value, this is just done as an optimistic
+                        // privilege dropping function.
+                        extern {
+                            fn setgroups(ngroups: libc::c_int,
+                                         ptr: *const libc::c_void) -> libc::c_int;
+                        }
+                        let _ = setgroups(0, ptr::null());
+
+                        if libc::setuid(u as libc::uid_t) != 0 {
+                            fail(&mut output);
+                        }
+                    }
+                    None => {}
+                }
+                if cfg.detach() {
+                    // Don't check the error of setsid because it fails if we're the
+                    // process leader already. We just forked so it shouldn't return
+                    // error, but ignore it anyway.
+                    let _ = libc::setsid();
+                }
+                if !dirp.is_null() && chdir(dirp) == -1 {
+                    fail(&mut output);
+                }
+                if !envp.is_null() {
+                    *sys::os::environ() = envp as *const _;
+                }
+                let _ = execvp(*argv, argv as *mut _);
+                fail(&mut output);
+            })
+        })
+    }
 
     pub fn wait(&self, deadline: u64) -> IoResult<ProcessExit> {
         use cmp;
@@ -556,6 +766,7 @@ fn with_argv<T,F>(prog: &CString, args: &[CString],
     cb(ptrs.as_ptr())
 }
 
+#[cfg(stage0)]
 fn with_envp<K,V,T,F>(env: Option<&HashMap<K, V>>,
                       cb: F)
                       -> T
@@ -593,6 +804,44 @@ fn with_envp<K,V,T,F>(env: Option<&HashMap<K, V>>,
         _ => cb(ptr::null())
     }
 }
+#[cfg(not(stage0))]
+fn with_envp<K,V,T,F>(env: Option<&HashMap<K, V>>,
+                      cb: F)
+                      -> T
+    where F : FnOnce(*const c_void) -> T,
+          K : BytesContainer + Eq + Hash,
+          V : BytesContainer
+{
+    // On posixy systems we can pass a char** for envp, which is a
+    // null-terminated array of "k=v\0" strings. Since we must create
+    // these strings locally, yet expose a raw pointer to them, we
+    // create a temporary vector to own the CStrings that outlives the
+    // call to cb.
+    match env {
+        Some(env) => {
+            let mut tmps = Vec::with_capacity(env.len());
+
+            for pair in env {
+                let mut kv = Vec::new();
+                kv.push_all(pair.0.container_as_bytes());
+                kv.push('=' as u8);
+                kv.push_all(pair.1.container_as_bytes());
+                kv.push(0); // terminating null
+                tmps.push(kv);
+            }
+
+            // As with `with_argv`, this is unsafe, since cb could leak the pointers.
+            let mut ptrs: Vec<*const libc::c_char> =
+                tmps.iter()
+                    .map(|tmp| tmp.as_ptr() as *const libc::c_char)
+                    .collect();
+            ptrs.push(ptr::null());
+
+            cb(ptrs.as_ptr() as *const c_void)
+        }
+        _ => cb(ptr::null())
+    }
+}
 
 fn translate_status(status: c_int) -> ProcessExit {
     #![allow(non_snake_case)]
diff --git a/src/libstd/sys/unix/process2.rs b/src/libstd/sys/unix/process2.rs
index 5e2c207f375..06fa5c4bba7 100644
--- a/src/libstd/sys/unix/process2.rs
+++ b/src/libstd/sys/unix/process2.rs
@@ -11,7 +11,6 @@
 use prelude::v1::*;
 
 use collections::HashMap;
-use collections::hash_map::Hasher;
 use env;
 use ffi::{OsString, OsStr, CString};
 use fmt;
@@ -46,7 +45,7 @@ pub struct Command {
 impl Command {
     pub fn new(program: &OsStr) -> Command {
         Command {
-            program: program.to_cstring(),
+            program: program.to_cstring().unwrap(),
             args: Vec::new(),
             env: None,
             cwd: None,
@@ -57,10 +56,10 @@ impl Command {
     }
 
     pub fn arg(&mut self, arg: &OsStr) {
-        self.args.push(arg.to_cstring())
+        self.args.push(arg.to_cstring().unwrap())
     }
     pub fn args<'a, I: Iterator<Item = &'a OsStr>>(&mut self, args: I) {
-        self.args.extend(args.map(OsStrExt::to_cstring))
+        self.args.extend(args.map(|s| OsStrExt::to_cstring(s).unwrap()))
     }
     fn init_env_map(&mut self) {
         if self.env.is_none() {
@@ -79,7 +78,7 @@ impl Command {
         self.env = Some(HashMap::new())
     }
     pub fn cwd(&mut self, dir: &OsStr) {
-        self.cwd = Some(dir.to_cstring())
+        self.cwd = Some(dir.to_cstring().unwrap())
     }
 }
 
diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs
index 82c52471d10..c90ba7645fe 100644
--- a/src/libstd/sys/unix/thread.rs
+++ b/src/libstd/sys/unix/thread.rs
@@ -237,7 +237,7 @@ pub unsafe fn create(stack: uint, p: Thunk) -> io::Result<rust_thread> {
 pub unsafe fn set_name(name: &str) {
     // pthread_setname_np() since glibc 2.12
     // availability autodetected via weak linkage
-    let cname = CString::from_slice(name.as_bytes());
+    let cname = CString::new(name).unwrap();
     type F = unsafe extern "C" fn(libc::pthread_t, *const libc::c_char) -> libc::c_int;
     extern {
         #[linkage = "extern_weak"]
@@ -255,14 +255,14 @@ pub unsafe fn set_name(name: &str) {
           target_os = "openbsd"))]
 pub unsafe fn set_name(name: &str) {
     // pthread_set_name_np() since almost forever on all BSDs
-    let cname = CString::from_slice(name.as_bytes());
+    let cname = CString::new(name).unwrap();
     pthread_set_name_np(pthread_self(), cname.as_ptr());
 }
 
 #[cfg(any(target_os = "macos", target_os = "ios"))]
 pub unsafe fn set_name(name: &str) {
     // pthread_setname_np() since OS X 10.6 and iOS 3.2
-    let cname = CString::from_slice(name.as_bytes());
+    let cname = CString::new(name).unwrap();
     pthread_setname_np(cname.as_ptr());
 }