diff --git a/libc-test/build.rs b/libc-test/build.rs index a8e0c015..5222192a 100644 --- a/libc-test/build.rs +++ b/libc-test/build.rs @@ -7,8 +7,11 @@ use std::env; fn do_cc() { let target = env::var("TARGET").unwrap(); - if cfg!(unix) && !target.contains("wasi") { - cc::Build::new().file("src/cmsg.c").compile("cmsg"); + if cfg!(unix) { + let exclude = ["wasi", "solaris", "illumos"]; + if !exclude.iter().any(|x| target.contains(x)) { + cc::Build::new().file("src/cmsg.c").compile("cmsg"); + } } if target.contains("android") || target.contains("linux") { cc::Build::new().file("src/errqueue.c").compile("errqueue"); @@ -27,7 +30,8 @@ fn do_ctest() { t if t.contains("netbsd") => return test_netbsd(t), t if t.contains("openbsd") => return test_openbsd(t), t if t.contains("redox") => return test_redox(t), - t if t.contains("solaris") => return test_solaris(t), + t if t.contains("solaris") => return test_solarish(t), + t if t.contains("illumos") => return test_solarish(t), t if t.contains("wasi") => return test_wasi(t), t if t.contains("windows") => return test_windows(t), t if t.contains("vxworks") => return test_vxworks(t), @@ -649,9 +653,13 @@ fn test_cloudabi(target: &str) { cfg.generate("../src/lib.rs", "main.rs"); } -fn test_solaris(target: &str) { - assert!(target.contains("solaris")); +fn test_solarish(target: &str) { + let is_solaris = target.contains("solaris"); + let is_illumos = target.contains("illumos"); + assert!(is_solaris || is_illumos); + // ctest generates arguments supported only by clang, so make sure to run with CC=clang. + // While debugging, "CFLAGS=-ferror-limit=" is useful to get more error output. let mut cfg = ctest_cfg(); cfg.flag("-Wno-deprecated-declarations"); @@ -664,6 +672,7 @@ fn test_solaris(target: &str) { "ctype.h", "dirent.h", "dlfcn.h", + "door.h", "errno.h", "execinfo.h", "fcntl.h", @@ -673,6 +682,7 @@ fn test_solaris(target: &str) { "langinfo.h", "limits.h", "locale.h", + "mqueue.h", "net/if.h", "net/if_arp.h", "net/route.h", @@ -705,6 +715,7 @@ fn test_solaris(target: &str) { "sys/socket.h", "sys/stat.h", "sys/statvfs.h", + "sys/shm.h", "sys/time.h", "sys/times.h", "sys/timex.h", @@ -723,15 +734,100 @@ fn test_solaris(target: &str) { "wchar.h", } + cfg.skip_type(move |ty| { + match ty { + // sighandler_t is not present here + "sighandler_t" => true, + _ => false, + } + }); + + cfg.type_name(move |ty, is_struct, is_union| { + match ty { + "FILE" => "__FILE".to_string(), + "DIR" | "Dl_info" => ty.to_string(), + t if t.ends_with("_t") => t.to_string(), + t if is_struct => format!("struct {}", t), + t if is_union => format!("union {}", t), + t => t.to_string(), + } + }); + + cfg.field_name(move |struct_, field| { + match struct_ { + // rust struct uses raw u64, rather than union + "epoll_event" if field == "u64" => "data.u64".to_string(), + // rust struct was committed with typo for Solaris + "door_arg_t" if field == "dec_num" => "desc_num".to_string(), + "stat" if field.ends_with("_nsec") => { + // expose stat.Xtim.tv_nsec fields + field.trim_end_matches("e_nsec").to_string() + ".tv_nsec" + }, + _ => field.to_string() + } + }); + cfg.skip_const(move |name| match name { "DT_FIFO" | "DT_CHR" | "DT_DIR" | "DT_BLK" | "DT_REG" | "DT_LNK" | "DT_SOCK" | "USRQUOTA" | "GRPQUOTA" | "PRIO_MIN" | "PRIO_MAX" => { true } + // skip sighandler_t assignments + "SIG_DFL" | "SIG_ERR" | "SIG_IGN" => true, + + "DT_UNKNOWN" => true, + + "_UTX_LINESIZE" | "_UTX_USERSIZE" | + "_UTX_PADSIZE" | "_UTX_IDSIZE" | "_UTX_HOSTSIZE" => true, + + "EADI" | "EXTPROC" | "IPC_SEAT" => true, + + // This evaluates to a sysconf() call rather than a constant + "PTHREAD_STACK_MIN" => true, + _ => false, }); + + + cfg.skip_struct(move |ty| { + // the union handling is a mess + if ty.contains("door_desc_t_") { + return true + } + match ty { + // union, not a struct + "sigval" => true, + // a bunch of solaris-only fields + "utmpx" if is_illumos => true, + _ => false, + } + }); + + cfg.skip_field(move |s, field| { + match s { + // C99 sizing on this is tough + "dirent" if field == "d_name" => true, + // the union/macro makes this rough + "sigaction" if field == "sa_sigaction" => true, + // Missing in illumos + "sigevent" if field == "ss_sp" => true, + // Avoid sigval union issues + "sigevent" if field == "sigev_value" => true, + // const issues + "sigevent" if field == "sigev_notify_attributes" => true, + + // Avoid const and union issues + "door_arg" if field == "desc_ptr" => true, + "door_desc_t" if field == "d_data" => true, + "door_arg_t" if field.ends_with("_ptr") => true, + "door_arg_t" if field.ends_with("rbuf") => true, + + _ => false + } + }); + cfg.skip_fn(move |name| { // skip those that are manually verified match name { @@ -746,13 +842,19 @@ fn test_solaris(target: &str) { // FIXME: unskip these for next major release "setpriority" | "personality" => true, - // signal is defined with sighandler_t, so ignore + // signal is defined in terms of sighandler_t, so ignore "signal" => true, + // Currently missing "cfmakeraw" | "cfsetspeed" => true, - // FIXME: mincore is defined with caddr_t on Solaris. - "mincore" => true, + // const-ness issues + "execv" | "execve" | "execvp" | "settimeofday" | "sethostname" => true, + + // Solaris-different + "getpwent_r" | "getgrent_r" | "updwtmpx" if is_illumos => true, + "madvise" | "mprotect" if is_illumos => true, + "door_call" | "door_return" | "door_create" if is_illumos => true, _ => false, } diff --git a/libc-test/test/cmsg.rs b/libc-test/test/cmsg.rs index 38a8ce15..c95899ce 100644 --- a/libc-test/test/cmsg.rs +++ b/libc-test/test/cmsg.rs @@ -4,6 +4,7 @@ extern crate libc; #[cfg(unix)] +#[cfg(not(any(target_os = "solaris", target_os = "illumos")))] mod t { use libc::{self, c_uchar, c_uint, c_void, cmsghdr, msghdr}; diff --git a/src/unix/mod.rs b/src/unix/mod.rs index 9c2cafcb..364ff559 100644 --- a/src/unix/mod.rs +++ b/src/unix/mod.rs @@ -226,8 +226,12 @@ pub const S_ISUID: ::mode_t = 0x800; pub const S_ISGID: ::mode_t = 0x400; pub const S_ISVTX: ::mode_t = 0x200; -pub const IF_NAMESIZE: ::size_t = 16; -pub const IFNAMSIZ: ::size_t = IF_NAMESIZE; +cfg_if! { + if #[cfg(not(any(target_os = "illumos", target_os = "solaris")))] { + pub const IF_NAMESIZE: ::size_t = 16; + pub const IFNAMSIZ: ::size_t = IF_NAMESIZE; + } +} pub const LOG_EMERG: ::c_int = 0; pub const LOG_ALERT: ::c_int = 1; @@ -612,7 +616,6 @@ extern "C" { all(target_os = "macos", target_arch = "x86"), link_name = "listen$UNIX2003" )] - #[cfg_attr(target_os = "illumos", link_name = "__xnet_listen")] pub fn listen(socket: ::c_int, backlog: ::c_int) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), @@ -855,6 +858,7 @@ extern "C" { pub fn geteuid() -> uid_t; pub fn getgid() -> gid_t; pub fn getgroups(ngroups_max: ::c_int, groups: *mut gid_t) -> ::c_int; + #[cfg_attr(target_os = "illumos", link_name = "getloginx")] pub fn getlogin() -> *mut c_char; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), @@ -911,6 +915,7 @@ extern "C" { all(target_os = "macos", target_arch = "x86"), link_name = "ttyname_r$UNIX2003" )] + #[cfg_attr(target_os = "illumos", link_name = "__posix_ttyname_r")] pub fn ttyname_r( fd: ::c_int, buf: *mut c_char, @@ -1217,6 +1222,7 @@ extern "C" { pub fn dlclose(handle: *mut ::c_void) -> ::c_int; pub fn dladdr(addr: *const ::c_void, info: *mut Dl_info) -> ::c_int; + #[cfg_attr(target_os = "illumos", link_name = "__xnet_getaddrinfo")] pub fn getaddrinfo( node: *const c_char, service: *const c_char, diff --git a/src/unix/solarish/illumos.rs b/src/unix/solarish/illumos.rs new file mode 100644 index 00000000..42b4af39 --- /dev/null +++ b/src/unix/solarish/illumos.rs @@ -0,0 +1,27 @@ +s! { + pub struct shmid_ds { + pub shm_perm: ::ipc_perm, + pub shm_segsz: ::size_t, + pub shm_amp: *mut ::c_void, + pub shm_lkcnt: ::c_ushort, + pub shm_lpid: ::pid_t, + pub shm_cpid: ::pid_t, + pub shm_nattch: ::shmatt_t, + pub shm_cnattch: ::c_ulong, + pub shm_atime: ::time_t, + pub shm_dtime: ::time_t, + pub shm_ctime: ::time_t, + pub shm_pad4: [i64; 4], + } +} + +pub const AF_LOCAL: ::c_int = 1; // AF_UNIX +pub const AF_FILE: ::c_int = 1; // AF_UNIX + +extern "C" { + pub fn mincore( + addr: ::caddr_t, + len: ::size_t, + vec: *mut ::c_char, + ) -> ::c_int; +} diff --git a/src/unix/solarish/mod.rs b/src/unix/solarish/mod.rs index f893374f..ba959a79 100644 --- a/src/unix/solarish/mod.rs +++ b/src/unix/solarish/mod.rs @@ -1,6 +1,7 @@ pub type c_char = i8; pub type c_long = i64; pub type c_ulong = u64; +pub type caddr_t = *mut ::c_char; pub type clockid_t = ::c_int; pub type blkcnt_t = ::c_long; @@ -36,9 +37,6 @@ pub type id_t = ::c_int; pub type idtype_t = ::c_uint; pub type shmatt_t = ::c_ulong; -pub type door_attr_t = ::c_uint; -pub type door_id_t = ::c_ulonglong; - #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum timezone {} impl ::Copy for timezone {} @@ -217,33 +215,6 @@ s! { pub ai_next: *mut addrinfo, } - pub struct shmid_ds { - pub shm_perm: ipc_perm, - pub shm_segsz: ::size_t, - #[cfg(target_os = "illumos")] - pub shm_amp: *mut ::c_void, - #[cfg(target_os = "solaris")] - pub shm_flags: ::uintptr_t, - pub shm_lkcnt: ::c_ushort, - pub shm_lpid: ::pid_t, - pub shm_cpid: ::pid_t, - pub shm_nattch: ::shmatt_t, - pub shm_cnattch: ::c_ulong, - pub shm_atime: ::time_t, - pub shm_dtime: ::time_t, - pub shm_ctime: ::time_t, - #[cfg(target_os = "illumos")] - pub shm_pad4: [i64; 4], - #[cfg(target_os = "solaris")] - pub shm_amp: *mut ::c_void, - #[cfg(target_os = "solaris")] - pub shm_gransize: u64, - #[cfg(target_os = "solaris")] - pub shm_allocated: u64, - #[cfg(target_os = "solaris")] - pub shm_pad4: [i64; 1], - } - pub struct sigset_t { bits: [u32; 4], } @@ -371,7 +342,7 @@ s! { pub mq_maxmsg: ::c_long, pub mq_msgsize: ::c_long, pub mq_curmsgs: ::c_long, - _pad: [::c_int; 4] + _pad: [::c_int; 12] } pub struct port_event { @@ -382,11 +353,6 @@ s! { pub portev_user: *mut ::c_void, } - pub struct door_desc_t__d_data__d_desc { - pub d_descriptor: ::c_int, - pub d_id: ::door_id_t - } - pub struct exit_status { e_termination: ::c_short, e_exit: ::c_short, @@ -431,7 +397,14 @@ s! { } s_no_extra_traits! { - #[cfg_attr(any(target_arch = "x86", target_arch = "x86_64"), repr(packed))] + #[cfg_attr(all( + any(target_arch = "x86", target_arch = "x86_64"), + libc_packedN + ), repr(packed(4)))] + #[cfg_attr(all( + any(target_arch = "x86", target_arch = "x86_64"), + not(libc_packedN) + ), repr(packed))] pub struct epoll_event { pub events: u32, pub u64: u64, @@ -505,28 +478,6 @@ s_no_extra_traits! { pub sigev_notify_attributes: *const ::pthread_attr_t, __sigev_pad2: ::c_int, } - - #[cfg_attr(feature = "extra_traits", allow(missing_debug_implementations))] - pub union door_desc_t__d_data { - pub d_desc: door_desc_t__d_data__d_desc, - d_resv: [::c_int; 5], /* Check out /usr/include/sys/door.h */ - } - - #[cfg_attr(feature = "extra_traits", allow(missing_debug_implementations))] - pub struct door_desc_t { - pub d_attributes: door_attr_t, - pub d_data: door_desc_t__d_data, - } - - #[cfg_attr(feature = "extra_traits", allow(missing_debug_implementations))] - pub struct door_arg_t { - pub data_ptr: *const ::c_char, - pub data_size: ::size_t, - pub desc_ptr: *const door_desc_t, - pub dec_num: ::c_uint, - pub rbuf: *const ::c_char, - pub rsize: ::size_t, - } } cfg_if! { @@ -1018,7 +969,7 @@ pub const O_CREAT: ::c_int = 256; pub const O_EXCL: ::c_int = 1024; pub const O_NOCTTY: ::c_int = 2048; pub const O_TRUNC: ::c_int = 512; -pub const O_NOFOLLOW: ::c_int = 0x200000; +pub const O_NOFOLLOW: ::c_int = 0x20000; pub const O_SEARCH: ::c_int = 0x200000; pub const O_EXEC: ::c_int = 0x400000; pub const O_CLOEXEC: ::c_int = 0x800000; @@ -1361,7 +1312,7 @@ pub const RLIMIT_AS: ::c_int = RLIMIT_VMEM; #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: rlim_t = 7; -pub const RLIM_INFINITY: rlim_t = 0x7fffffff; +pub const RLIM_INFINITY: rlim_t = 0xfffffffffffffffd; pub const RUSAGE_SELF: ::c_int = 0; pub const RUSAGE_CHILDREN: ::c_int = -1; @@ -1375,8 +1326,6 @@ pub const MADV_FREE: ::c_int = 5; pub const AF_UNSPEC: ::c_int = 0; pub const AF_UNIX: ::c_int = 1; -pub const AF_LOCAL: ::c_int = 0; -pub const AF_FILE: ::c_int = 0; pub const AF_INET: ::c_int = 2; pub const AF_IMPLINK: ::c_int = 3; pub const AF_PUP: ::c_int = 4; @@ -1465,6 +1414,9 @@ pub const MSG_DUPCTRL: ::c_int = 0x800; pub const MSG_XPG4_2: ::c_int = 0x8000; pub const MSG_MAXIOVLEN: ::c_int = 16; +pub const IF_NAMESIZE: ::size_t = 32; +pub const IFNAMSIZ: ::size_t = 16; + // https://docs.oracle.com/cd/E23824_01/html/821-1475/if-7p.html pub const IFF_UP: ::c_int = 0x0000000001; // Address is up pub const IFF_BROADCAST: ::c_int = 0x0000000002; // Broadcast address valid @@ -1780,8 +1732,6 @@ pub const PORT_SOURCE_FD: ::c_int = 4; pub const PORT_SOURCE_ALERT: ::c_int = 5; pub const PORT_SOURCE_MQ: ::c_int = 6; pub const PORT_SOURCE_FILE: ::c_int = 7; -pub const PORT_SOURCE_POSTWAIT: ::c_int = 8; -pub const PORT_SOURCE_SIGNAL: ::c_int = 9; pub const NONROOT_USR: ::c_short = 2; pub const _UTX_USERSIZE: usize = 32; @@ -1888,7 +1838,6 @@ pub const EPOLLERR: ::c_int = 0x8; pub const EPOLLHUP: ::c_int = 0x10; pub const EPOLLET: ::c_int = 0x80000000; pub const EPOLLRDHUP: ::c_int = 0x2000; -pub const EPOLLEXCLUSIVE: ::c_int = 0x10000000; pub const EPOLLONESHOT: ::c_int = 0x40000000; pub const EPOLL_CLOEXEC: ::c_int = 0x80000; pub const EPOLL_CTL_ADD: ::c_int = 1; @@ -1920,9 +1869,9 @@ pub const B230400: speed_t = 20; pub const B307200: speed_t = 21; pub const B460800: speed_t = 22; pub const B921600: speed_t = 23; -pub const CSTART: ::tcflag_t = 021; -pub const CSTOP: ::tcflag_t = 023; -pub const CSWTCH: ::tcflag_t = 032; +pub const CSTART: ::tcflag_t = 0o21; +pub const CSTOP: ::tcflag_t = 0o23; +pub const CSWTCH: ::tcflag_t = 0o32; pub const CSIZE: ::tcflag_t = 0o000060; pub const CS5: ::tcflag_t = 0; pub const CS6: ::tcflag_t = 0o000020; @@ -2137,11 +2086,6 @@ extern "C" { pub fn freeifaddrs(ifa: *mut ::ifaddrs); pub fn stack_getbounds(sp: *mut ::stack_t) -> ::c_int; - pub fn mincore( - addr: *const ::c_void, - len: ::size_t, - vec: *mut c_char, - ) -> ::c_int; pub fn initgroups(name: *const ::c_char, basegid: ::gid_t) -> ::c_int; pub fn setgroups(ngroups: ::c_int, ptr: *const ::gid_t) -> ::c_int; pub fn ioctl(fildes: ::c_int, request: ::c_int, ...) -> ::c_int; @@ -2237,6 +2181,7 @@ extern "C" { options: ::c_int, ) -> ::c_int; + #[cfg_attr(target_os = "illumos", link_name = "_glob_ext")] pub fn glob( pattern: *const ::c_char, flags: ::c_int, @@ -2246,6 +2191,7 @@ extern "C" { pglob: *mut ::glob_t, ) -> ::c_int; + #[cfg_attr(target_os = "illumos", link_name = "_globfree_ext")] pub fn globfree(pglob: *mut ::glob_t); pub fn posix_madvise( @@ -2426,11 +2372,6 @@ extern "C" { events: ::c_int, user: *mut ::c_void, ) -> ::c_int; - pub fn fexecve( - fd: ::c_int, - argv: *const *const ::c_char, - envp: *const *const ::c_char, - ) -> ::c_int; #[cfg_attr( any(target_os = "solaris", target_os = "illumos"), link_name = "__posix_getgrgid_r" @@ -2555,25 +2496,6 @@ extern "C" { pub fn dup3(src: ::c_int, dst: ::c_int, flags: ::c_int) -> ::c_int; pub fn uname(buf: *mut ::utsname) -> ::c_int; pub fn pipe2(fds: *mut ::c_int, flags: ::c_int) -> ::c_int; - pub fn door_call(d: ::c_int, params: *const door_arg_t) -> ::c_int; - pub fn door_return( - data_ptr: *const ::c_char, - data_size: ::size_t, - desc_ptr: *const door_desc_t, - num_desc: ::c_uint, - ); - pub fn door_create( - server_procedure: extern "C" fn( - cookie: *const ::c_void, - argp: *const ::c_char, - arg_size: ::size_t, - dp: *const door_desc_t, - n_desc: ::c_uint, - ), - cookie: *const ::c_void, - attributes: door_attr_t, - ) -> ::c_int; - pub fn fattach(fildes: ::c_int, path: *const ::c_char) -> ::c_int; pub fn makeutx(ux: *const utmpx) -> *mut utmpx; pub fn modutx(ux: *const utmpx) -> *mut utmpx; @@ -2604,3 +2526,15 @@ extern "C" { mod compat; pub use self::compat::*; + +cfg_if! { + if #[cfg(target_os = "illumos")] { + mod illumos; + pub use self::illumos::*; + } else if #[cfg(target_os = "solaris")] { + mod solaris; + pub use self::solaris::*; + } else { + // Unknown target_os + } +} diff --git a/src/unix/solarish/solaris.rs b/src/unix/solarish/solaris.rs new file mode 100644 index 00000000..798622e3 --- /dev/null +++ b/src/unix/solarish/solaris.rs @@ -0,0 +1,94 @@ +pub type door_attr_t = ::c_uint; +pub type door_id_t = ::c_ulonglong; + +s! { + pub struct shmid_ds { + pub shm_perm: ::ipc_perm, + pub shm_segsz: ::size_t, + pub shm_flags: ::uintptr_t, + pub shm_lkcnt: ::c_ushort, + pub shm_lpid: ::pid_t, + pub shm_cpid: ::pid_t, + pub shm_nattch: ::shmatt_t, + pub shm_cnattch: ::c_ulong, + pub shm_atime: ::time_t, + pub shm_dtime: ::time_t, + pub shm_ctime: ::time_t, + pub shm_amp: *mut ::c_void, + pub shm_gransize: u64, + pub shm_allocated: u64, + pub shm_pad4: [i64; 1], + } + + pub struct door_desc_t__d_data__d_desc { + pub d_descriptor: ::c_int, + pub d_id: ::door_id_t + } +} + +pub const PORT_SOURCE_POSTWAIT: ::c_int = 8; +pub const PORT_SOURCE_SIGNAL: ::c_int = 9; + +pub const EPOLLEXCLUSIVE: ::c_int = 0x10000000; + +pub const AF_LOCAL: ::c_int = 0; +pub const AF_FILE: ::c_int = 0; + +extern "C" { + pub fn fexecve( + fd: ::c_int, + argv: *const *const ::c_char, + envp: *const *const ::c_char, + ) -> ::c_int; + + pub fn mincore( + addr: *const ::c_void, + len: ::size_t, + vec: *mut ::c_char, + ) -> ::c_int; + + pub fn door_call(d: ::c_int, params: *const door_arg_t) -> ::c_int; + pub fn door_return( + data_ptr: *const ::c_char, + data_size: ::size_t, + desc_ptr: *const door_desc_t, + num_desc: ::c_uint, + ); + pub fn door_create( + server_procedure: extern "C" fn( + cookie: *const ::c_void, + argp: *const ::c_char, + arg_size: ::size_t, + dp: *const door_desc_t, + n_desc: ::c_uint, + ), + cookie: *const ::c_void, + attributes: door_attr_t, + ) -> ::c_int; + + pub fn fattach(fildes: ::c_int, path: *const ::c_char) -> ::c_int; +} + +s_no_extra_traits! { + #[cfg_attr(feature = "extra_traits", allow(missing_debug_implementations))] + pub union door_desc_t__d_data { + pub d_desc: door_desc_t__d_data__d_desc, + d_resv: [::c_int; 5], /* Check out /usr/include/sys/door.h */ + } + + #[cfg_attr(feature = "extra_traits", allow(missing_debug_implementations))] + pub struct door_desc_t { + pub d_attributes: door_attr_t, + pub d_data: door_desc_t__d_data, + } + + #[cfg_attr(feature = "extra_traits", allow(missing_debug_implementations))] + pub struct door_arg_t { + pub data_ptr: *const ::c_char, + pub data_size: ::size_t, + pub desc_ptr: *const door_desc_t, + pub dec_num: ::c_uint, + pub rbuf: *const ::c_char, + pub rsize: ::size_t, + } +}