1
Fork 0

Auto merge of #31078 - nbaksalyar:illumos, r=alexcrichton

This pull request adds support for [Illumos](http://illumos.org/)-based operating systems: SmartOS, OpenIndiana, and others. For now it's x86-64 only, as I'm not sure if 32-bit installations are widespread. This PR is based on #28589 by @potatosalad, and also closes #21000, #25845, and #25846.

Required changes in libc are already merged: https://github.com/rust-lang-nursery/libc/pull/138

Here's a snapshot required to build a stage0 compiler:
https://s3-eu-west-1.amazonaws.com/nbaksalyar/rustc-sunos-snapshot.tar.gz
It passes all checks from `make check`.

There are some changes I'm not quite sure about, e.g. macro usage in `src/libstd/num/f64.rs` and `DirEntry` structure in `src/libstd/sys/unix/fs.rs`, so any comments on how to rewrite it better would be greatly appreciated.

Also, LLVM configure script might need to be patched to build it successfully, or a pre-built libLLVM should be used. Some details can be found here: https://llvm.org/bugs/show_bug.cgi?id=25409

Thanks!

r? @brson
This commit is contained in:
bors 2016-02-03 22:40:32 +00:00
commit e3bcddb44b
36 changed files with 412 additions and 38 deletions

View file

@ -8,14 +8,14 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use prelude::v1::*;
use io::prelude::*;
use os::unix::prelude::*;
use ffi::{CString, CStr, OsString, OsStr};
use fmt;
use io::{self, Error, ErrorKind, SeekFrom};
use libc::{dirent, readdir_r};
use libc::{self, c_int, off_t, mode_t};
use libc::{self, dirent, c_int, off_t, mode_t};
use mem;
use path::{Path, PathBuf};
use ptr;
@ -24,7 +24,6 @@ use sys::fd::FileDesc;
use sys::platform::raw;
use sys::{cvt, cvt_r};
use sys_common::{AsInner, FromInner};
use vec::Vec;
pub struct File(FileDesc);
@ -46,6 +45,12 @@ unsafe impl Sync for Dir {}
pub struct DirEntry {
entry: dirent,
root: Arc<PathBuf>,
// We need to store an owned copy of the directory name
// on Solaris because a) it uses a zero-length array to
// store the name, b) its lifetime between readdir calls
// is not guaranteed.
#[cfg(target_os = "solaris")]
name: Box<[u8]>
}
#[derive(Clone)]
@ -132,6 +137,36 @@ impl FromInner<raw::mode_t> for FilePermissions {
impl Iterator for ReadDir {
type Item = io::Result<DirEntry>;
#[cfg(target_os = "solaris")]
fn next(&mut self) -> Option<io::Result<DirEntry>> {
unsafe {
loop {
// Although readdir_r(3) would be a correct function to use here because
// of the thread safety, on Illumos the readdir(3C) function is safe to use
// in threaded applications and it is generally preferred over the
// readdir_r(3C) function.
let entry_ptr = libc::readdir(self.dirp.0);
if entry_ptr.is_null() {
return None
}
let name = (*entry_ptr).d_name.as_ptr();
let namelen = libc::strlen(name) as usize;
let ret = DirEntry {
entry: *entry_ptr,
name: ::slice::from_raw_parts(name as *const u8,
namelen as usize).to_owned().into_boxed_slice(),
root: self.root.clone()
};
if ret.name_bytes() != b"." && ret.name_bytes() != b".." {
return Some(Ok(ret))
}
}
}
}
#[cfg(not(target_os = "solaris"))]
fn next(&mut self) -> Option<io::Result<DirEntry>> {
unsafe {
let mut ret = DirEntry {
@ -140,7 +175,7 @@ impl Iterator for ReadDir {
};
let mut entry_ptr = ptr::null_mut();
loop {
if readdir_r(self.dirp.0, &mut ret.entry, &mut entry_ptr) != 0 {
if libc::readdir_r(self.dirp.0, &mut ret.entry, &mut entry_ptr) != 0 {
return Some(Err(Error::last_os_error()))
}
if entry_ptr.is_null() {
@ -174,6 +209,12 @@ impl DirEntry {
lstat(&self.path())
}
#[cfg(target_os = "solaris")]
pub fn file_type(&self) -> io::Result<FileType> {
stat(&self.path()).map(|m| m.file_type())
}
#[cfg(not(target_os = "solaris"))]
pub fn file_type(&self) -> io::Result<FileType> {
match self.entry.d_type {
libc::DT_CHR => Ok(FileType { mode: libc::S_IFCHR }),
@ -189,7 +230,8 @@ impl DirEntry {
#[cfg(any(target_os = "macos",
target_os = "ios",
target_os = "linux"))]
target_os = "linux",
target_os = "solaris"))]
pub fn ino(&self) -> raw::ino_t {
self.entry.d_ino
}
@ -228,6 +270,10 @@ impl DirEntry {
CStr::from_ptr(self.entry.d_name.as_ptr()).to_bytes()
}
}
#[cfg(target_os = "solaris")]
fn name_bytes(&self) -> &[u8] {
&*self.name
}
}
impl OpenOptions {