diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 45078bab82..cea028daca 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -634,3 +634,55 @@ jobs: - name: before_cache_script run: rm -rf $CARGO_HOME/registry/index + # Runs the test suite against wasm32-unknown-emscripten under Node. + emscripten: + runs-on: ubuntu-latest + timeout-minutes: 20 + # TEMPORARY: builds against the guybedford/emscripten `cf` fork, which + # carries the NODEFS/socket/blocking patches this target depends on. Once + # those land upstream the fork checkout can be dropped for a released emsdk. + steps: + - name: checkout + uses: actions/checkout@v4 + + - name: setup Rust + uses: dtolnay/rust-toolchain@nightly + with: + components: rust-src + + # JSPI is the return-to-host bridge for blocking reads/writes; it needs a + # Node with JSPI on by default (V8 13.x+), not the one bundled with emsdk. + - name: setup Node + uses: actions/setup-node@v4 + with: + node-version: 26 + + - name: record JSPI-capable node + run: echo "JSPI_NODE=$(which node)" >> "$GITHUB_ENV" + + - name: install emsdk + run: | + git clone --depth 1 https://github.com/emscripten-core/emsdk.git + ./emsdk/emsdk install latest + ./emsdk/emsdk activate latest + + - name: overlay guybedford/emscripten (cf) fork + run: | + git clone --branch cf https://github.com/guybedford/emscripten.git em-fork + python3 em-fork/bootstrap.py + rm -rf ./emsdk/upstream/emscripten + ln -s "$(pwd)/em-fork" ./emsdk/upstream/emscripten + + - name: test + run: | + source ./emsdk/emsdk_env.sh + export EM_CONFIG="$EMSDK/.emscripten" + CARGO_TARGET_WASM32_UNKNOWN_EMSCRIPTEN_RUNNER="$JSPI_NODE" \ + RUSTFLAGS="-A linker_messages -C target-feature=+atomics,+bulk-memory,+mutable-globals -C link-arg=-pthread -C link-arg=-sPROXY_TO_PTHREAD -C link-arg=-sNODERAWSOCKETS -C link-arg=-sNODERAWFS -C link-arg=-sALLOW_MEMORY_GROWTH=1 -C link-arg=-sEXIT_RUNTIME=1 -C link-arg=-sJSPI" \ + cargo +nightly test --target wasm32-unknown-emscripten -Zbuild-std=std,panic_abort --test test \ + --config 'patch.crates-io.libc.git="https://github.com/guybedford/libc"' \ + --config 'patch.crates-io.libc.branch="libc-0.2-emscripten"' + + - name: before_cache_script + run: rm -rf $CARGO_HOME/registry/index + diff --git a/README.md b/README.md index b5e51333bf..b4a3c9d0b8 100644 --- a/README.md +++ b/README.md @@ -103,6 +103,7 @@ The following targets are supported by `nix`:
  • x86_64-unknown-openbsd
  • x86_64-unknown-redox
  • i686-unknown-hurd-gnu
  • +
  • wasm32-unknown-emscripten
  • diff --git a/src/sys/ioctl/linux.rs b/src/sys/ioctl/linux.rs index 067996d6d4..a415d38f37 100644 --- a/src/sys/ioctl/linux.rs +++ b/src/sys/ioctl/linux.rs @@ -5,6 +5,7 @@ use cfg_if::cfg_if; target_os = "android", target_os = "fuchsia", target_os = "cygwin", + target_os = "emscripten", target_env = "musl", target_env = "ohos" ))] @@ -14,6 +15,7 @@ pub type ioctl_num_type = ::libc::c_int; target_os = "android", target_os = "fuchsia", target_os = "cygwin", + target_os = "emscripten", target_env = "musl", target_env = "ohos" )))] diff --git a/src/sys/ioctl/mod.rs b/src/sys/ioctl/mod.rs index f8bf61652b..bac4bccb39 100644 --- a/src/sys/ioctl/mod.rs +++ b/src/sys/ioctl/mod.rs @@ -231,7 +231,8 @@ use cfg_if::cfg_if; linux_android, target_os = "fuchsia", target_os = "redox", - target_os = "cygwin" + target_os = "cygwin", + target_os = "emscripten" ))] #[macro_use] mod linux; @@ -240,7 +241,8 @@ mod linux; linux_android, target_os = "fuchsia", target_os = "redox", - target_os = "cygwin" + target_os = "cygwin", + target_os = "emscripten" ))] pub use self::linux::*; diff --git a/src/sys/mod.rs b/src/sys/mod.rs index d07ddb78f7..f1d4441ea3 100644 --- a/src/sys/mod.rs +++ b/src/sys/mod.rs @@ -42,6 +42,7 @@ feature! { target_os = "haiku", target_os = "redox", target_os = "cygwin", + target_os = "emscripten", ))] #[cfg(feature = "ioctl")] #[cfg_attr(docsrs, doc(cfg(feature = "ioctl")))] diff --git a/src/sys/resource.rs b/src/sys/resource.rs index 4868eac643..edb50079e6 100644 --- a/src/sys/resource.rs +++ b/src/sys/resource.rs @@ -21,6 +21,7 @@ cfg_if! { target_os = "aix", target_os = "illumos", all(target_os = "linux", not(target_env = "gnu")), + target_os = "emscripten", target_os = "cygwin" ))]{ use libc::rlimit; @@ -53,6 +54,7 @@ libc_enum! { target_os = "aix", target_os = "illumos", all(target_os = "linux", not(any(target_env = "gnu", target_env = "uclibc"))), + target_os = "emscripten", target_os = "cygwin" ), repr(i32))] #[non_exhaustive] diff --git a/src/sys/socket/addr.rs b/src/sys/socket/addr.rs index 09be1d68b5..848b8e4c90 100644 --- a/src/sys/socket/addr.rs +++ b/src/sys/socket/addr.rs @@ -4,6 +4,7 @@ solarish, target_os = "haiku", target_os = "fuchsia", + target_os = "emscripten", target_os = "aix", ))] #[cfg(feature = "net")] @@ -448,6 +449,7 @@ impl UnixAddr { target_os = "fuchsia", solarish, target_os = "redox", + target_os = "emscripten", target_os = "cygwin", ))] { @@ -513,6 +515,7 @@ impl UnixAddr { target_os = "fuchsia", solarish, target_os = "redox", + target_os = "emscripten", target_os = "cygwin", ))] { @@ -531,6 +534,7 @@ impl SockaddrLike for UnixAddr { target_os = "fuchsia", solarish, target_os = "redox", + target_os = "emscripten", target_os = "cygwin", ))] fn len(&self) -> libc::socklen_t { @@ -561,6 +565,7 @@ impl SockaddrLike for UnixAddr { target_os = "fuchsia", solarish, target_os = "redox", + target_os = "emscripten", target_os = "cygwin", ))] { let su_len = len.unwrap_or( @@ -1172,6 +1177,7 @@ impl SockaddrLike for SockaddrStorage { linux_android, target_os = "fuchsia", solarish, + target_os = "emscripten", target_os = "cygwin", ))] if i32::from(ss.ss_family) == libc::AF_UNIX { @@ -1229,7 +1235,7 @@ impl SockaddrLike for SockaddrStorage { } } - #[cfg(any(linux_android, target_os = "fuchsia", solarish, target_os = "cygwin"))] + #[cfg(any(linux_android, target_os = "fuchsia", solarish, target_os = "emscripten", target_os = "cygwin"))] fn len(&self) -> libc::socklen_t { match self.as_unix_addr() { // The UnixAddr type knows its own length @@ -1291,6 +1297,7 @@ impl SockaddrStorage { if #[cfg(any(linux_android, target_os = "fuchsia", solarish, + target_os = "emscripten", target_os = "cygwin", ))] { @@ -1321,6 +1328,7 @@ impl SockaddrStorage { if #[cfg(any(linux_android, target_os = "fuchsia", solarish, + target_os = "emscripten", target_os = "cygwin", ))] { @@ -1834,7 +1842,7 @@ pub mod sys_control { } } -#[cfg(any(linux_android, target_os = "fuchsia"))] +#[cfg(any(linux_android, target_os = "fuchsia", target_os = "emscripten"))] mod datalink { feature! { #![feature = "net"] @@ -2312,7 +2320,7 @@ mod tests { fn size() { #[cfg(any(bsd, target_os = "aix", solarish, target_os = "haiku"))] let l = mem::size_of::(); - #[cfg(any(linux_android, target_os = "fuchsia"))] + #[cfg(any(linux_android, target_os = "fuchsia", target_os = "emscripten"))] let l = mem::size_of::(); assert_eq!(LinkAddr::size() as usize, l); } diff --git a/src/unistd.rs b/src/unistd.rs index 4b313987ea..279227a45b 100644 --- a/src/unistd.rs +++ b/src/unistd.rs @@ -1301,7 +1301,7 @@ feature! { /// On some systems, the host name is limited to as few as 64 bytes. An error /// will be returned if the name is not valid or the current process does not /// have permissions to update the host name. -#[cfg(not(target_os = "redox"))] +#[cfg(not(any(target_os = "redox", target_os = "emscripten")))] pub fn sethostname>(name: S) -> Result<()> { // Handle some differences in type of the len arg across platforms. cfg_if! { diff --git a/test/sys/test_resource.rs b/test/sys/test_resource.rs index 102b1b57d8..9101d8fafc 100644 --- a/test/sys/test_resource.rs +++ b/test/sys/test_resource.rs @@ -11,6 +11,7 @@ use nix::sys::resource::{getrusage, UsageWho}; /// been updated. #[test] #[cfg_attr(target_os = "cygwin", ignore)] +#[cfg_attr(target_os = "emscripten", ignore)] pub fn test_resource_limits_nofile() { let (mut soft_limit, hard_limit) = getrlimit(Resource::RLIMIT_NOFILE).unwrap(); diff --git a/test/sys/test_signal.rs b/test/sys/test_signal.rs index 49e5089cb2..66f67639a4 100644 --- a/test/sys/test_signal.rs +++ b/test/sys/test_signal.rs @@ -2,6 +2,7 @@ use nix::errno::Errno; use nix::sys::signal::*; use nix::unistd::*; use std::hash::{Hash, Hasher}; +#[cfg_attr(target_os = "emscripten", allow(unused_imports))] use std::sync::atomic::{AtomicBool, Ordering}; #[cfg(not(target_os = "redox"))] use std::thread; @@ -12,7 +13,7 @@ fn test_kill_none() { } #[test] -#[cfg(not(target_os = "fuchsia"))] +#[cfg(not(any(target_os = "fuchsia", target_os = "emscripten")))] fn test_killpg_none() { killpg(getpgrp(), None) .expect("Should be able to send signal to my process group."); @@ -79,8 +80,10 @@ fn test_sigprocmask() { .expect("expect to be able to block signals"); } +#[cfg(not(target_os = "emscripten"))] static SIGNALED: AtomicBool = AtomicBool::new(false); +#[cfg(not(target_os = "emscripten"))] extern "C" fn test_sigaction_handler(signal: libc::c_int) { let signal = Signal::try_from(signal).unwrap(); SIGNALED.store(signal == Signal::SIGINT, Ordering::Relaxed); @@ -107,6 +110,7 @@ fn test_signal_sigaction() { } #[test] +#[cfg(not(target_os = "emscripten"))] fn test_signal() { let _m = crate::SIGNAL_MTX.lock(); @@ -186,7 +190,7 @@ fn test_extend() { } #[test] -#[cfg(not(target_os = "redox"))] +#[cfg(not(any(target_os = "redox", target_os = "emscripten")))] fn test_thread_signal_set_mask() { thread::spawn(|| { let prev_mask = SigSet::thread_get_mask() @@ -211,7 +215,7 @@ fn test_thread_signal_set_mask() { } #[test] -#[cfg(not(target_os = "redox"))] +#[cfg(not(any(target_os = "redox", target_os = "emscripten")))] fn test_thread_signal_block() { thread::spawn(|| { let mut mask = SigSet::empty(); @@ -242,6 +246,7 @@ fn test_thread_signal_unblock() { #[test] #[cfg(not(target_os = "redox"))] +#[cfg_attr(target_os = "emscripten", ignore)] fn test_thread_signal_swap() { thread::spawn(|| { let mut mask = SigSet::empty(); diff --git a/test/sys/test_socket.rs b/test/sys/test_socket.rs index 9f309b42db..922cbfe63a 100644 --- a/test/sys/test_socket.rs +++ b/test/sys/test_socket.rs @@ -286,6 +286,7 @@ pub fn test_unnamed_uds_addr() { } #[test] +#[cfg_attr(target_os = "emscripten", ignore)] pub fn test_getsockname() { use nix::sys::socket::bind; use nix::sys::socket::{socket, AddressFamily, SockFlag, SockType}; @@ -308,6 +309,7 @@ pub fn test_getsockname() { } #[test] +#[cfg_attr(target_os = "emscripten", ignore)] pub fn test_socketpair() { use nix::sys::socket::{socketpair, AddressFamily, SockFlag, SockType}; use nix::unistd::{read, write}; @@ -328,6 +330,7 @@ pub fn test_socketpair() { #[test] #[cfg_attr(target_os = "cygwin", ignore)] +#[cfg_attr(target_os = "emscripten", ignore)] pub fn test_recvmsg_sockaddr_un() { use nix::sys::socket::{ self, bind, socket, AddressFamily, MsgFlags, SockFlag, SockType, @@ -421,6 +424,7 @@ mod recvfrom { } #[test] + #[cfg_attr(target_os = "emscripten", ignore)] pub fn stream() { let (fd2, fd1) = socketpair( AddressFamily::Unix, @@ -843,6 +847,7 @@ pub fn test_recvmsg_ebadf() { #[cfg_attr(qemu, ignore)] #[test] #[cfg_attr(target_os = "cygwin", ignore)] +#[cfg_attr(target_os = "emscripten", ignore)] pub fn test_scm_rights() { use nix::sys::socket::{ recvmsg, sendmsg, socketpair, AddressFamily, ControlMessage, @@ -1346,6 +1351,7 @@ pub fn test_sendmsg_ipv4sendsrcaddr() { #[cfg_attr(qemu, ignore)] #[test] #[cfg_attr(target_os = "cygwin", ignore)] +#[cfg_attr(target_os = "emscripten", ignore)] fn test_scm_rights_single_cmsg_multiple_fds() { use nix::sys::socket::{ recvmsg, sendmsg, ControlMessage, ControlMessageOwned, MsgFlags, @@ -1404,6 +1410,7 @@ fn test_scm_rights_single_cmsg_multiple_fds() { // msg_control field and a msg_controllen of 0 when calling into the // raw `sendmsg`. #[test] +#[cfg_attr(target_os = "emscripten", ignore)] pub fn test_sendmsg_empty_cmsgs() { use nix::sys::socket::{ recvmsg, sendmsg, socketpair, AddressFamily, MsgFlags, SockFlag, @@ -3265,7 +3272,8 @@ fn can_use_cmsg_space() { linux_android, target_os = "redox", target_os = "haiku", - target_os = "cygwin" + target_os = "cygwin", + target_os = "emscripten" )))] #[test] fn can_open_routing_socket() { diff --git a/test/sys/test_sockopt.rs b/test/sys/test_sockopt.rs index c3e1d5ed07..7150432ca5 100644 --- a/test/sys/test_sockopt.rs +++ b/test/sys/test_sockopt.rs @@ -806,6 +806,7 @@ fn can_get_peerpidfd_on_unix_socket() { } #[test] +#[cfg_attr(target_os = "emscripten", ignore)] fn is_socket_type_unix() { use nix::sys::socket::{socketpair, sockopt, SockFlag, SockType}; diff --git a/test/sys/test_termios.rs b/test/sys/test_termios.rs index 98de86bc74..d483d7f17f 100644 --- a/test/sys/test_termios.rs +++ b/test/sys/test_termios.rs @@ -26,6 +26,7 @@ fn test_baudrate_try_from() { // Test tcgetattr on a terminal #[test] +#[cfg_attr(target_os = "emscripten", ignore)] fn test_tcgetattr_pty() { // openpty uses ptname(3) internally let _m = crate::PTSNAME_MTX.lock(); @@ -43,6 +44,7 @@ fn test_tcgetattr_enotty() { // Test modifying output flags #[test] +#[cfg_attr(target_os = "emscripten", ignore)] fn test_output_flags() { // openpty uses ptname(3) internally let _m = crate::PTSNAME_MTX.lock(); @@ -81,6 +83,7 @@ fn test_output_flags() { // Test modifying local flags #[test] #[cfg(not(target_os = "solaris"))] +#[cfg_attr(target_os = "emscripten", ignore)] fn test_local_flags() { // openpty uses ptname(3) internally let _m = crate::PTSNAME_MTX.lock(); diff --git a/test/sys/test_wait.rs b/test/sys/test_wait.rs index 365b0165f8..77e2e2d69c 100644 --- a/test/sys/test_wait.rs +++ b/test/sys/test_wait.rs @@ -7,6 +7,7 @@ use nix::unistd::*; #[test] #[cfg(not(any(target_os = "redox", target_os = "haiku")))] +#[cfg_attr(target_os = "emscripten", ignore)] fn test_wait_signal() { let _m = crate::FORK_MTX.lock(); @@ -59,6 +60,7 @@ fn test_waitid_signal() { } #[test] +#[cfg_attr(target_os = "emscripten", ignore)] fn test_wait_exit() { let _m = crate::FORK_MTX.lock(); @@ -119,6 +121,7 @@ fn test_waitstatus_from_raw() { } #[test] +#[cfg_attr(target_os = "emscripten", ignore)] fn test_waitstatus_pid() { let _m = crate::FORK_MTX.lock(); diff --git a/test/test_fcntl.rs b/test/test_fcntl.rs index 4894dad340..40aa644ae6 100644 --- a/test/test_fcntl.rs +++ b/test/test_fcntl.rs @@ -660,6 +660,7 @@ mod test_flock { /// Verify that `Flock::lock()` correctly obtains a lock, and subsequently unlocks upon drop. #[test] + #[cfg_attr(target_os = "emscripten", ignore)] fn lock_and_drop() { // Get 2 `File` handles to same underlying file. let file1 = NamedTempFile::new().unwrap(); @@ -686,6 +687,7 @@ mod test_flock { /// An exclusive lock can be downgraded #[test] + #[cfg_attr(target_os = "emscripten", ignore)] fn downgrade() { let file1 = NamedTempFile::new().unwrap(); let file2 = file1.reopen().unwrap(); @@ -729,6 +731,7 @@ mod test_flock { /// A shared lock can be upgraded #[test] + #[cfg_attr(target_os = "emscripten", ignore)] fn upgrade() { let file1 = NamedTempFile::new().unwrap(); let file2 = file1.reopen().unwrap(); diff --git a/test/test_net.rs b/test/test_net.rs index be86b65d30..be16b88e87 100644 --- a/test/test_net.rs +++ b/test/test_net.rs @@ -11,12 +11,14 @@ const LOOPBACK: &[u8] = b"loop"; #[test] #[cfg_attr(target_os = "cygwin", ignore)] +#[cfg_attr(target_os = "emscripten", ignore)] fn test_if_nametoindex() { if_nametoindex(LOOPBACK).expect("assertion failed"); } #[test] #[cfg_attr(target_os = "cygwin", ignore)] +#[cfg_attr(target_os = "emscripten", ignore)] fn test_if_indextoname() { let loopback_index = if_nametoindex(LOOPBACK).expect("assertion failed"); assert_eq!( diff --git a/test/test_pty.rs b/test/test_pty.rs index a580832705..6769e95963 100644 --- a/test/test_pty.rs +++ b/test/test_pty.rs @@ -135,6 +135,7 @@ fn open_ptty_pair() -> (PtyMaster, File) { /// themselves. So for this test we perform the basic act of getting a file handle for a /// master/slave PTTY pair. #[test] +#[cfg_attr(target_os = "emscripten", ignore)] fn test_open_ptty_pair() { let (_, _) = open_ptty_pair(); } @@ -149,6 +150,7 @@ fn make_raw(fd: Fd) { /// Test `io::Read` on the PTTY master #[test] #[cfg(not(target_os = "solaris"))] +#[cfg_attr(target_os = "emscripten", ignore)] fn test_read_ptty_pair() { let (mut master, mut slave) = open_ptty_pair(); make_raw(&slave); @@ -166,6 +168,7 @@ fn test_read_ptty_pair() { /// Test `io::Write` on the PTTY master #[test] +#[cfg_attr(target_os = "emscripten", ignore)] fn test_write_ptty_pair() { let (mut master, mut slave) = open_ptty_pair(); make_raw(&slave); @@ -182,6 +185,7 @@ fn test_write_ptty_pair() { } #[test] +#[cfg_attr(target_os = "emscripten", ignore)] fn test_openpty() { // openpty uses ptname(3) internally let _m = crate::PTSNAME_MTX.lock(); @@ -212,6 +216,7 @@ fn test_openpty() { } #[test] +#[cfg_attr(target_os = "emscripten", ignore)] fn test_openpty_with_termios() { // openpty uses ptname(3) internally let _m = crate::PTSNAME_MTX.lock(); @@ -250,6 +255,7 @@ fn test_openpty_with_termios() { } #[test] +#[cfg_attr(target_os = "emscripten", ignore)] fn test_forkpty() { use nix::sys::signal::*; use nix::sys::wait::wait; diff --git a/test/test_unistd.rs b/test/test_unistd.rs index 7641752a21..55a079e05f 100644 --- a/test/test_unistd.rs +++ b/test/test_unistd.rs @@ -21,6 +21,7 @@ use nix::unistd::ForkResult::*; use nix::unistd::*; use std::env; #[cfg(not(any(target_os = "fuchsia", target_os = "redox")))] +#[cfg_attr(target_os = "emscripten", allow(unused_imports))] use std::ffi::CString; #[cfg(not(target_os = "redox"))] use std::fs::DirBuilder; @@ -38,6 +39,7 @@ use crate::*; #[test] #[cfg(not(any(target_os = "netbsd")))] +#[cfg_attr(target_os = "emscripten", ignore)] fn test_fork_and_waitpid() { let _m = crate::FORK_MTX.lock(); @@ -97,6 +99,7 @@ fn test_rfork_and_waitpid() { } #[test] +#[cfg_attr(target_os = "emscripten", ignore)] fn test_wait() { // Grab FORK_MTX so wait doesn't reap a different test's child process let _m = crate::FORK_MTX.lock(); @@ -135,6 +138,7 @@ fn test_mkstemp_directory() { #[test] #[cfg(not(target_os = "redox"))] +#[cfg_attr(target_os = "emscripten", ignore)] fn test_mkfifo() { let tempdir = tempdir().unwrap(); let mkfifo_fifo = tempdir.path().join("mkfifo_fifo"); @@ -160,6 +164,7 @@ fn test_mkfifo_directory() { target_os = "redox", target_os = "haiku" )))] +#[cfg_attr(target_os = "emscripten", ignore)] fn test_mkfifoat_none() { use nix::fcntl::AT_FDCWD; @@ -182,6 +187,7 @@ fn test_mkfifoat_none() { target_os = "redox", target_os = "haiku" )))] +#[cfg_attr(target_os = "emscripten", ignore)] fn test_mkfifoat() { use nix::fcntl; @@ -281,6 +287,7 @@ mod freebsd { target_os = "fuchsia", target_os = "haiku" )))] +#[cfg_attr(target_os = "emscripten", ignore)] fn test_setgroups() { // Skip this test when not run as root as `setgroups()` requires root. skip_if_not_root!("test_setgroups"); @@ -308,6 +315,7 @@ fn test_setgroups() { target_os = "redox", target_os = "fuchsia", target_os = "haiku", + target_os = "emscripten", solarish )))] fn test_initgroups() { @@ -343,6 +351,7 @@ fn test_initgroups() { } #[cfg(not(any(target_os = "fuchsia", target_os = "redox")))] +#[cfg_attr(target_os = "emscripten", allow(unused_macros))] macro_rules! execve_test_factory ( ($test_name:ident, $syscall:ident, $exe: expr $(, $pathname:expr, $flags:expr)*) => ( @@ -647,6 +656,7 @@ cfg_if! { target_os = "haiku", target_os = "cygwin" )))] +#[cfg_attr(target_os = "emscripten", ignore)] fn test_acct() { use std::process::Command; use std::{thread, time}; @@ -776,6 +786,7 @@ fn test_pipe() { target_os = "redox", ))] #[test] +#[cfg_attr(target_os = "emscripten", ignore)] fn test_pipe2() { use nix::fcntl::{fcntl, FcntlArg, FdFlag}; @@ -1067,6 +1078,7 @@ fn test_linkat_newdirfd_none() { #[test] #[cfg(not(any(apple_targets, target_os = "redox", target_os = "haiku")))] +#[cfg_attr(target_os = "emscripten", ignore)] fn test_linkat_no_follow_symlink() { use nix::fcntl::AtFlags; use nix::fcntl::AT_FDCWD; @@ -1245,6 +1257,7 @@ fn test_access_file_exists() { #[cfg(not(target_os = "redox"))] #[test] +#[cfg_attr(target_os = "emscripten", ignore)] fn test_user_into_passwd() { let test_username = if cfg!(target_os = "haiku") { // "nobody" unavailable on haiku @@ -1306,6 +1319,7 @@ fn test_setfsuid() { target_os = "fuchsia", target_os = "haiku" )))] +#[cfg_attr(target_os = "emscripten", ignore)] fn test_ttyname() { use std::os::fd::AsRawFd;