diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9338285e94..5b84767897 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -271,6 +271,7 @@ jobs: # https://github.com/nix-rust/nix/issues/2200 #- target: armv7-unknown-linux-uclibceabihf - target: x86_64-unknown-haiku + - target: i686-unknown-hurd-gnu steps: - name: checkout uses: actions/checkout@v4 diff --git a/src/dir.rs b/src/dir.rs index 1579b65683..ab70f064cc 100644 --- a/src/dir.rs +++ b/src/dir.rs @@ -228,6 +228,7 @@ impl Entry { target_os = "emscripten", target_os = "fuchsia", target_os = "haiku", + target_os = "hurd", solarish, linux_android, apple_targets))] { diff --git a/src/errno.rs b/src/errno.rs index c7a182b6c0..cde462d958 100644 --- a/src/errno.rs +++ b/src/errno.rs @@ -19,7 +19,8 @@ cfg_if! { } else if #[cfg(any(target_os = "linux", target_os = "redox", target_os = "dragonfly", - target_os = "fuchsia"))] { + target_os = "fuchsia", + target_os = "hurd"))] { unsafe fn errno_location() -> *mut c_int { unsafe { libc::__errno_location() } } @@ -306,16 +307,36 @@ fn desc(errno: Errno) -> &'static str { #[cfg(any(linux_android, solarish, target_os = "fuchsia"))] EBFONT => "Bad font file format", - #[cfg(any(linux_android, solarish, target_os = "fuchsia"))] + #[cfg(any( + linux_android, + solarish, + target_os = "fuchsia", + target_os = "hurd" + ))] ENOSTR => "Device not a stream", - #[cfg(any(linux_android, solarish, target_os = "fuchsia"))] + #[cfg(any( + linux_android, + solarish, + target_os = "fuchsia", + target_os = "hurd" + ))] ENODATA => "No data available", - #[cfg(any(linux_android, solarish, target_os = "fuchsia"))] + #[cfg(any( + linux_android, + solarish, + target_os = "fuchsia", + target_os = "hurd" + ))] ETIME => "Timer expired", - #[cfg(any(linux_android, solarish, target_os = "fuchsia"))] + #[cfg(any( + linux_android, + solarish, + target_os = "fuchsia", + target_os = "hurd" + ))] ENOSR => "Out of streams resources", #[cfg(any(linux_android, solarish, target_os = "fuchsia"))] @@ -324,7 +345,12 @@ fn desc(errno: Errno) -> &'static str { #[cfg(any(linux_android, solarish, target_os = "fuchsia"))] ENOPKG => "Package not installed", - #[cfg(any(linux_android, solarish, target_os = "fuchsia"))] + #[cfg(any( + linux_android, + solarish, + target_os = "fuchsia", + target_os = "hurd" + ))] EREMOTE => "Object is remote", #[cfg(any( @@ -348,7 +374,7 @@ fn desc(errno: Errno) -> &'static str { linux_android, solarish, target_os = "aix", - target_os = "fuchsia" + target_os = "fuchsia", ))] EPROTO => "Protocol error", @@ -373,7 +399,8 @@ fn desc(errno: Errno) -> &'static str { linux_android, target_os = "aix", target_os = "fuchsia", - target_os = "haiku" + target_os = "haiku", + target_os = "hurd" ))] EOVERFLOW => "Value too large for defined data type", @@ -398,7 +425,12 @@ fn desc(errno: Errno) -> &'static str { #[cfg(any(linux_android, solarish, target_os = "fuchsia"))] ELIBMAX => "Attempting to link in too many shared libraries", - #[cfg(any(linux_android, solarish, target_os = "fuchsia"))] + #[cfg(any( + linux_android, + solarish, + target_os = "fuchsia", + target_os = "hurd" + ))] ELIBEXEC => "Cannot exec a shared library directly", #[cfg(any( @@ -432,7 +464,7 @@ fn desc(errno: Errno) -> &'static str { ))] EOPNOTSUPP => "Operation not supported on transport endpoint", - #[cfg(any(linux_android, target_os = "fuchsia"))] + #[cfg(any(linux_android, target_os = "fuchsia", target_os = "hurd"))] ESTALE => "Stale file handle", #[cfg(any(linux_android, target_os = "fuchsia"))] @@ -488,7 +520,12 @@ fn desc(errno: Errno) -> &'static str { #[cfg(any(linux_android, target_os = "fuchsia"))] EKEYREJECTED => "Key was rejected by service", - #[cfg(any(linux_android, target_os = "aix", target_os = "fuchsia"))] + #[cfg(any( + linux_android, + target_os = "aix", + target_os = "fuchsia", + target_os = "hurd" + ))] EOWNERDEAD => "Owner died", #[cfg(solarish)] @@ -515,10 +552,10 @@ fn desc(errno: Errno) -> &'static str { #[cfg(freebsdlike)] EDOOFUS => "Programming error", - #[cfg(any(freebsdlike, target_os = "redox"))] + #[cfg(any(freebsdlike, target_os = "hurd", target_os = "redox"))] EMULTIHOP => "Multihop attempted", - #[cfg(any(freebsdlike, target_os = "redox"))] + #[cfg(any(freebsdlike, target_os = "hurd", target_os = "redox"))] ENOLINK => "Link has been severed", #[cfg(target_os = "freebsd")] @@ -527,7 +564,7 @@ fn desc(errno: Errno) -> &'static str { #[cfg(target_os = "freebsd")] ECAPMODE => "Not permitted in capability mode", - #[cfg(bsd)] + #[cfg(any(bsd, target_os = "hurd"))] ENEEDAUTH => "Need authenticator", #[cfg(any(bsd, target_os = "redox", solarish))] @@ -538,32 +575,59 @@ fn desc(errno: Errno) -> &'static str { apple_targets, target_os = "netbsd", target_os = "redox", - target_os = "haiku" + target_os = "haiku", + target_os = "hurd" ))] EILSEQ => "Illegal byte sequence", #[cfg(any(bsd, target_os = "haiku"))] ENOATTR => "Attribute not found", - #[cfg(any(bsd, target_os = "redox", target_os = "haiku"))] + #[cfg(any( + bsd, + target_os = "redox", + target_os = "haiku", + target_os = "hurd" + ))] EBADMSG => "Bad message", - #[cfg(any(bsd, target_os = "redox", target_os = "haiku"))] + #[cfg(any( + bsd, + target_os = "haiku", + target_os = "hurd", + target_os = "redox" + ))] EPROTO => "Protocol error", - #[cfg(any(freebsdlike, apple_targets, target_os = "openbsd"))] + #[cfg(any( + freebsdlike, + apple_targets, + target_os = "openbsd", + target_os = "hurd" + ))] ENOTRECOVERABLE => "State not recoverable", #[cfg(any(freebsdlike, apple_targets, target_os = "openbsd"))] EOWNERDEAD => "Previous owner died", - #[cfg(any(bsd, target_os = "aix", solarish, target_os = "haiku"))] + #[cfg(any( + bsd, + target_os = "aix", + solarish, + target_os = "haiku", + target_os = "hurd" + ))] ENOTSUP => "Operation not supported", - #[cfg(any(bsd, target_os = "aix"))] + #[cfg(any(bsd, target_os = "aix", target_os = "hurd"))] EPROCLIM => "Too many processes", - #[cfg(any(bsd, target_os = "aix", target_os = "redox"))] + #[cfg(any( + bsd, + target_os = "aix", + target_os = "hurd", + target_os = "redox" + ))] EUSERS => "Too many users", #[cfg(any( @@ -571,7 +635,8 @@ fn desc(errno: Errno) -> &'static str { solarish, target_os = "redox", target_os = "aix", - target_os = "haiku" + target_os = "haiku", + target_os = "hurd" ))] EDQUOT => "Disc quota exceeded", @@ -587,28 +652,33 @@ fn desc(errno: Errno) -> &'static str { #[cfg(any(bsd, target_os = "aix", target_os = "redox"))] EREMOTE => "Too many levels of remote in path", - #[cfg(bsd)] + #[cfg(any(bsd, target_os = "hurd"))] EBADRPC => "RPC struct is bad", - #[cfg(bsd)] + #[cfg(any(bsd, target_os = "hurd"))] ERPCMISMATCH => "RPC version wrong", - #[cfg(bsd)] + #[cfg(any(bsd, target_os = "hurd"))] EPROGUNAVAIL => "RPC prog. not avail", - #[cfg(bsd)] + #[cfg(any(bsd, target_os = "hurd"))] EPROGMISMATCH => "Program version wrong", - #[cfg(bsd)] + #[cfg(any(bsd, target_os = "hurd"))] EPROCUNAVAIL => "Bad procedure for program", - #[cfg(bsd)] + #[cfg(any(bsd, target_os = "hurd"))] EFTYPE => "Inappropriate file type or format", - #[cfg(bsd)] + #[cfg(any(bsd, target_os = "hurd"))] EAUTH => "Authentication error", - #[cfg(any(bsd, target_os = "aix", target_os = "redox"))] + #[cfg(any( + bsd, + target_os = "aix", + target_os = "hurd", + target_os = "redox" + ))] ECANCELED => "Operation canceled", #[cfg(apple_targets)] @@ -676,7 +746,7 @@ fn desc(errno: Errno) -> &'static str { #[cfg(apple_targets)] EQFULL => "Interface output queue is full", - #[cfg(target_os = "openbsd")] + #[cfg(any(target_os = "openbsd", target_os = "hurd"))] EOPNOTSUPP => "Operation not supported", #[cfg(target_os = "openbsd")] @@ -693,6 +763,21 @@ fn desc(errno: Errno) -> &'static str { #[cfg(solarish)] ENOTACTIVE => "Facility is not active", + + #[cfg(target_os = "hurd")] + EBACKGROUND => "Inappropriate operation for background process", + + #[cfg(target_os = "hurd")] + EDIED => "Translator died", + + #[cfg(target_os = "hurd")] + EGREGIOUS => "You really blew it this time", + + #[cfg(target_os = "hurd")] + EIEIO => "Computer bought the farm", + + #[cfg(target_os = "hurd")] + EGRATUITOUS => "Gratuitous error", } } @@ -2926,3 +3011,231 @@ mod consts { } } } + +#[cfg(target_os = "hurd")] +mod consts { + #[derive(Clone, Copy, Debug, Eq, PartialEq)] + #[repr(i32)] + #[non_exhaustive] + pub enum Errno { + UnknownErrno = 0, + EPERM = libc::EPERM, + ENOENT = libc::ENOENT, + ESRCH = libc::ESRCH, + EINTR = libc::EINTR, + EIO = libc::EIO, + ENXIO = libc::ENXIO, + E2BIG = libc::E2BIG, + ENOEXEC = libc::ENOEXEC, + EBADF = libc::EBADF, + ECHILD = libc::ECHILD, + EDEADLK = libc::EDEADLK, + ENOMEM = libc::ENOMEM, + EACCES = libc::EACCES, + EFAULT = libc::EFAULT, + ENOTBLK = libc::ENOTBLK, + EBUSY = libc::EBUSY, + EEXIST = libc::EEXIST, + EXDEV = libc::EXDEV, + ENODEV = libc::ENODEV, + ENOTDIR = libc::ENOTDIR, + EISDIR = libc::EISDIR, + EINVAL = libc::EINVAL, + EMFILE = libc::EMFILE, + ENFILE = libc::ENFILE, + ENOTTY = libc::ENOTTY, + ETXTBSY = libc::ETXTBSY, + EFBIG = libc::EFBIG, + ENOSPC = libc::ENOSPC, + ESPIPE = libc::ESPIPE, + EROFS = libc::EROFS, + EMLINK = libc::EMLINK, + EPIPE = libc::EPIPE, + EDOM = libc::EDOM, + ERANGE = libc::ERANGE, + EAGAIN = libc::EAGAIN, + EINPROGRESS = libc::EINPROGRESS, + EALREADY = libc::EALREADY, + ENOTSOCK = libc::ENOTSOCK, + EMSGSIZE = libc::EMSGSIZE, + EPROTOTYPE = libc::EPROTOTYPE, + ENOPROTOOPT = libc::ENOPROTOOPT, + EPROTONOSUPPORT = libc::EPROTONOSUPPORT, + ESOCKTNOSUPPORT = libc::ESOCKTNOSUPPORT, + EOPNOTSUPP = libc::EOPNOTSUPP, + EPFNOSUPPORT = libc::EPFNOSUPPORT, + EAFNOSUPPORT = libc::EAFNOSUPPORT, + EADDRINUSE = libc::EADDRINUSE, + EADDRNOTAVAIL = libc::EADDRNOTAVAIL, + ENETDOWN = libc::ENETDOWN, + ENETUNREACH = libc::ENETUNREACH, + ENETRESET = libc::ENETRESET, + ECONNABORTED = libc::ECONNABORTED, + ECONNRESET = libc::ECONNRESET, + ENOBUFS = libc::ENOBUFS, + EISCONN = libc::EISCONN, + ENOTCONN = libc::ENOTCONN, + EDESTADDRREQ = libc::EDESTADDRREQ, + ESHUTDOWN = libc::ESHUTDOWN, + ETOOMANYREFS = libc::ETOOMANYREFS, + ETIMEDOUT = libc::ETIMEDOUT, + ECONNREFUSED = libc::ECONNREFUSED, + ELOOP = libc::ELOOP, + ENAMETOOLONG = libc::ENAMETOOLONG, + EHOSTDOWN = libc::EHOSTDOWN, + EHOSTUNREACH = libc::EHOSTUNREACH, + ENOTEMPTY = libc::ENOTEMPTY, + EPROCLIM = libc::EPROCLIM, + EUSERS = libc::EUSERS, + EDQUOT = libc::EDQUOT, + ESTALE = libc::ESTALE, + EREMOTE = libc::EREMOTE, + EBADRPC = libc::EBADRPC, + ERPCMISMATCH = libc::ERPCMISMATCH, + EPROGUNAVAIL = libc::EPROGUNAVAIL, + EPROGMISMATCH = libc::EPROGMISMATCH, + EPROCUNAVAIL = libc::EPROCUNAVAIL, + ENOLCK = libc::ENOLCK, + EFTYPE = libc::EFTYPE, + EAUTH = libc::EAUTH, + ENEEDAUTH = libc::ENEEDAUTH, + ENOSYS = libc::ENOSYS, + ELIBEXEC = libc::ELIBEXEC, + ENOTSUP = libc::ENOTSUP, + EILSEQ = libc::EILSEQ, + EBACKGROUND = libc::EBACKGROUND, + EDIED = libc::EDIED, + EGREGIOUS = libc::EGREGIOUS, + EIEIO = libc::EIEIO, + EGRATUITOUS = libc::EGRATUITOUS, + EBADMSG = libc::EBADMSG, + EIDRM = libc::EIDRM, + EMULTIHOP = libc::EMULTIHOP, + ENODATA = libc::ENODATA, + ENOLINK = libc::ENOLINK, + ENOMSG = libc::ENOMSG, + ENOSR = libc::ENOSR, + ENOSTR = libc::ENOSTR, + EOVERFLOW = libc::EOVERFLOW, + EPROTO = libc::EPROTO, + ETIME = libc::ETIME, + ECANCELED = libc::ECANCELED, + EOWNERDEAD = libc::EOWNERDEAD, + ENOTRECOVERABLE = libc::ENOTRECOVERABLE, + } + + impl Errno { + pub const EWOULDBLOCK: Errno = Errno::EAGAIN; + } + + pub const fn from_i32(e: i32) -> Errno { + use self::Errno::*; + + match e { + libc::EPERM => EPERM, + libc::ENOENT => ENOENT, + libc::ESRCH => ESRCH, + libc::EINTR => EINTR, + libc::EIO => EIO, + libc::ENXIO => ENXIO, + libc::E2BIG => E2BIG, + libc::ENOEXEC => ENOEXEC, + libc::EBADF => EBADF, + libc::ECHILD => ECHILD, + libc::EDEADLK => EDEADLK, + libc::ENOMEM => ENOMEM, + libc::EACCES => EACCES, + libc::EFAULT => EFAULT, + libc::ENOTBLK => ENOTBLK, + libc::EBUSY => EBUSY, + libc::EEXIST => EEXIST, + libc::EXDEV => EXDEV, + libc::ENODEV => ENODEV, + libc::ENOTDIR => ENOTDIR, + libc::EISDIR => EISDIR, + libc::EINVAL => EINVAL, + libc::EMFILE => EMFILE, + libc::ENFILE => ENFILE, + libc::ENOTTY => ENOTTY, + libc::ETXTBSY => ETXTBSY, + libc::EFBIG => EFBIG, + libc::ENOSPC => ENOSPC, + libc::ESPIPE => ESPIPE, + libc::EROFS => EROFS, + libc::EMLINK => EMLINK, + libc::EPIPE => EPIPE, + libc::EDOM => EDOM, + libc::ERANGE => ERANGE, + libc::EAGAIN => EAGAIN, + libc::EINPROGRESS => EINPROGRESS, + libc::EALREADY => EALREADY, + libc::ENOTSOCK => ENOTSOCK, + libc::EMSGSIZE => EMSGSIZE, + libc::EPROTOTYPE => EPROTOTYPE, + libc::ENOPROTOOPT => ENOPROTOOPT, + libc::EPROTONOSUPPORT => EPROTONOSUPPORT, + libc::ESOCKTNOSUPPORT => ESOCKTNOSUPPORT, + libc::EOPNOTSUPP => EOPNOTSUPP, + libc::EPFNOSUPPORT => EPFNOSUPPORT, + libc::EAFNOSUPPORT => EAFNOSUPPORT, + libc::EADDRINUSE => EADDRINUSE, + libc::EADDRNOTAVAIL => EADDRNOTAVAIL, + libc::ENETDOWN => ENETDOWN, + libc::ENETUNREACH => ENETUNREACH, + libc::ENETRESET => ENETRESET, + libc::ECONNABORTED => ECONNABORTED, + libc::ECONNRESET => ECONNRESET, + libc::ENOBUFS => ENOBUFS, + libc::EISCONN => EISCONN, + libc::ENOTCONN => ENOTCONN, + libc::EDESTADDRREQ => EDESTADDRREQ, + libc::ESHUTDOWN => ESHUTDOWN, + libc::ETOOMANYREFS => ETOOMANYREFS, + libc::ETIMEDOUT => ETIMEDOUT, + libc::ECONNREFUSED => ECONNREFUSED, + libc::ELOOP => ELOOP, + libc::ENAMETOOLONG => ENAMETOOLONG, + libc::EHOSTDOWN => EHOSTDOWN, + libc::EHOSTUNREACH => EHOSTUNREACH, + libc::ENOTEMPTY => ENOTEMPTY, + libc::EPROCLIM => EPROCLIM, + libc::EUSERS => EUSERS, + libc::EDQUOT => EDQUOT, + libc::ESTALE => ESTALE, + libc::EREMOTE => EREMOTE, + libc::EBADRPC => EBADRPC, + libc::ERPCMISMATCH => ERPCMISMATCH, + libc::EPROGUNAVAIL => EPROGUNAVAIL, + libc::EPROGMISMATCH => EPROGMISMATCH, + libc::EPROCUNAVAIL => EPROCUNAVAIL, + libc::ENOLCK => ENOLCK, + libc::EFTYPE => EFTYPE, + libc::EAUTH => EAUTH, + libc::ENEEDAUTH => ENEEDAUTH, + libc::ENOSYS => ENOSYS, + libc::ELIBEXEC => ELIBEXEC, + libc::ENOTSUP => ENOTSUP, + libc::EILSEQ => EILSEQ, + libc::EBACKGROUND => EBACKGROUND, + libc::EDIED => EDIED, + libc::EGREGIOUS => EGREGIOUS, + libc::EIEIO => EIEIO, + libc::EGRATUITOUS => EGRATUITOUS, + libc::EBADMSG => EBADMSG, + libc::EIDRM => EIDRM, + libc::EMULTIHOP => EMULTIHOP, + libc::ENODATA => ENODATA, + libc::ENOLINK => ENOLINK, + libc::ENOMSG => ENOMSG, + libc::ENOSR => ENOSR, + libc::ENOSTR => ENOSTR, + libc::EOVERFLOW => EOVERFLOW, + libc::EPROTO => EPROTO, + libc::ETIME => ETIME, + libc::ECANCELED => ECANCELED, + libc::EOWNERDEAD => EOWNERDEAD, + libc::ENOTRECOVERABLE => ENOTRECOVERABLE, + _ => UnknownErrno, + } + } +} diff --git a/src/fcntl.rs b/src/fcntl.rs index 8f68b498e7..5a50700d1f 100644 --- a/src/fcntl.rs +++ b/src/fcntl.rs @@ -306,7 +306,11 @@ fn inner_readlink( dirfd: Option, path: &P, ) -> Result { - let mut v = Vec::with_capacity(libc::PATH_MAX as usize); + #[cfg(not(target_os = "hurd"))] + const PATH_MAX: usize = libc::PATH_MAX as usize; + #[cfg(target_os = "hurd")] + const PATH_MAX: usize = 1024; + let mut v = Vec::with_capacity(PATH_MAX); { // simple case: result is strictly less than `PATH_MAX` @@ -358,7 +362,7 @@ fn inner_readlink( } else { // If lstat doesn't cooperate, or reports an error, be a little less // precise. - (libc::PATH_MAX as usize).max(128) << 1 + PATH_MAX.max(128) << 1 } }; diff --git a/src/features.rs b/src/features.rs index d75f6a408a..0a0c618096 100644 --- a/src/features.rs +++ b/src/features.rs @@ -100,6 +100,7 @@ mod os { #[cfg(any( freebsdlike, // FreeBSD since 10.0 DragonFlyBSD since ??? netbsdlike, // NetBSD since 6.0 OpenBSD since 5.7 + target_os = "hurd", // Since glibc 2.28 target_os = "illumos", // Since ??? target_os = "redox", // Since 1-july-2020 ))] diff --git a/src/sys/mman.rs b/src/sys/mman.rs index 9f4c40acaf..982f6924c2 100644 --- a/src/sys/mman.rs +++ b/src/sys/mman.rs @@ -77,7 +77,7 @@ libc_bitflags! { /// Do not reserve swap space for this mapping. /// /// This was removed in FreeBSD 11 and is unused in DragonFlyBSD. - #[cfg(not(any(freebsdlike, target_os = "aix")))] + #[cfg(not(any(freebsdlike, target_os = "aix", target_os = "hurd")))] MAP_NORESERVE; /// Populate page tables for a mapping. #[cfg(linux_android)] @@ -264,7 +264,7 @@ libc_enum! { #[cfg(linux_android)] MADV_DODUMP, /// Specify that the application no longer needs the pages in the given range. - #[cfg(not(target_os = "aix"))] + #[cfg(not(any(target_os = "aix", target_os = "hurd")))] MADV_FREE, /// Request that the system not flush the current range to disk unless it needs to. #[cfg(freebsdlike)] @@ -513,6 +513,7 @@ pub unsafe fn munmap(addr: NonNull, len: size_t) -> Result<()> { /// [`MmapAdvise::MADV_FREE`]. /// /// [`madvise(2)`]: https://man7.org/linux/man-pages/man2/madvise.2.html +#[allow(rustdoc::broken_intra_doc_links)] pub unsafe fn madvise( addr: NonNull, length: size_t, diff --git a/src/sys/resource.rs b/src/sys/resource.rs index c0116f080b..c7f1491fed 100644 --- a/src/sys/resource.rs +++ b/src/sys/resource.rs @@ -10,12 +10,16 @@ pub use libc::RLIM_INFINITY; use std::mem; cfg_if! { - if #[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))]{ + if #[cfg(any( + all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")), + target_os = "hurd" + ))]{ use libc::{__rlimit_resource_t, rlimit}; } else if #[cfg(any( bsd, target_os = "android", target_os = "aix", + target_os = "hurd", all(target_os = "linux", not(target_env = "gnu")) ))]{ use libc::rlimit; @@ -38,7 +42,10 @@ libc_enum! { // // https://gcc.gnu.org/legacy-ml/gcc/2015-08/msg00441.html // https://github.com/rust-lang/libc/blob/master/src/unix/linux_like/linux/gnu/mod.rs - #[cfg_attr(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")), repr(u32))] + #[cfg_attr(any( + all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")), + target_os = "hurd" + ), repr(u32))] #[cfg_attr(any( bsd, target_os = "android", @@ -171,7 +178,10 @@ pub fn getrlimit(resource: Resource) -> Result<(rlim_t, rlim_t)> { let mut old_rlim = mem::MaybeUninit::::uninit(); cfg_if! { - if #[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))]{ + if #[cfg(any( + all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")), + target_os = "hurd" + ))] { let res = unsafe { libc::getrlimit(resource as __rlimit_resource_t, old_rlim.as_mut_ptr()) }; } else { let res = unsafe { libc::getrlimit(resource as c_int, old_rlim.as_mut_ptr()) }; @@ -224,7 +234,10 @@ pub fn setrlimit( rlim_max: hard_limit, }; cfg_if! { - if #[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))]{ + if #[cfg(any( + all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")), + target_os = "hurd", + ))]{ let res = unsafe { libc::setrlimit(resource as __rlimit_resource_t, &new_rlim as *const rlimit) }; }else{ let res = unsafe { libc::setrlimit(resource as c_int, &new_rlim as *const rlimit) }; diff --git a/src/sys/signal.rs b/src/sys/signal.rs index 3156848c48..02c9266869 100644 --- a/src/sys/signal.rs +++ b/src/sys/signal.rs @@ -17,6 +17,7 @@ use std::str::FromStr; #[cfg(not(any( target_os = "fuchsia", + target_os = "hurd", target_os = "openbsd", target_os = "redox" )))] @@ -431,6 +432,7 @@ libc_bitflags! { SA_NOCLDSTOP; /// When catching a [`Signal::SIGCHLD`] signal, the system will not /// create zombie processes when children of the calling process exit. + #[cfg(not(target_os = "hurd"))] SA_NOCLDWAIT; /// Further occurrences of the delivered signal are not masked during /// the execution of the handler. @@ -1075,7 +1077,7 @@ pub type type_of_thread_id = libc::pid_t; // sigval is actually a union of a int and a void*. But it's never really used // as a pointer, because neither libc nor the kernel ever dereference it. nix // therefore presents it as an intptr_t, which is how kevent uses it. -#[cfg(not(any(target_os = "fuchsia", target_os = "openbsd", target_os = "redox")))] +#[cfg(not(any(target_os = "fuchsia", target_os = "hurd", target_os = "openbsd", target_os = "redox")))] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub enum SigevNotify { /// No notification will be delivered @@ -1128,6 +1130,7 @@ pub enum SigevNotify { #[cfg(not(any( target_os = "fuchsia", + target_os = "hurd", target_os = "openbsd", target_os = "redox" )))] diff --git a/src/sys/socket/addr.rs b/src/sys/socket/addr.rs index eb1944bb99..b8413b6c44 100644 --- a/src/sys/socket/addr.rs +++ b/src/sys/socket/addr.rs @@ -162,6 +162,7 @@ pub enum AddressFamily { target_os = "aix", solarish, apple_targets, + target_os = "hurd", target_os = "redox", )))] Bluetooth = libc::AF_BLUETOOTH, @@ -177,6 +178,7 @@ pub enum AddressFamily { target_os = "aix", solarish, target_os = "haiku", + target_os = "hurd", target_os = "redox", )))] Isdn = libc::AF_ISDN, @@ -283,7 +285,7 @@ pub struct UnixAddr { /// The length of the valid part of `sun`, including the sun_family field /// but excluding any trailing nul. // On the BSDs, this field is built into sun - #[cfg(not(any(bsd, target_os = "haiku")))] + #[cfg(not(any(bsd, target_os = "haiku", target_os = "hurd")))] sun_len: u8, } @@ -361,7 +363,7 @@ impl UnixAddr { .try_into() .unwrap(); - #[cfg(any(bsd, target_os = "haiku"))] + #[cfg(any(bsd, target_os = "haiku", target_os = "hurd"))] { ret.sun_len = sun_len; } @@ -520,7 +522,12 @@ impl UnixAddr { impl private::SockaddrLikePriv for UnixAddr {} impl SockaddrLike for UnixAddr { - #[cfg(any(linux_android, target_os = "fuchsia", solarish, target_os = "redox"))] + #[cfg(any( + linux_android, + target_os = "fuchsia", + solarish, + target_os = "redox" + ))] fn len(&self) -> libc::socklen_t { self.sun_len.into() } @@ -813,7 +820,12 @@ impl SockaddrIn { /// Creates a new socket address from IPv4 octets and a port number. pub fn new(a: u8, b: u8, c: u8, d: u8, port: u16) -> Self { Self(libc::sockaddr_in { - #[cfg(any(bsd, target_os = "aix", target_os = "haiku"))] + #[cfg(any( + bsd, + target_os = "aix", + target_os = "haiku", + target_os = "hurd" + ))] sin_len: Self::size() as u8, sin_family: AddressFamily::Inet as sa_family_t, sin_port: u16::to_be(port), @@ -882,7 +894,12 @@ impl fmt::Display for SockaddrIn { impl From for SockaddrIn { fn from(addr: net::SocketAddrV4) -> Self { Self(libc::sockaddr_in { - #[cfg(any(bsd, target_os = "haiku", target_os = "hermit"))] + #[cfg(any( + bsd, + target_os = "haiku", + target_os = "hermit", + target_os = "hurd" + ))] sin_len: mem::size_of::() as u8, sin_family: AddressFamily::Inet as sa_family_t, sin_port: addr.port().to_be(), // network byte order @@ -1002,7 +1019,12 @@ impl From for SockaddrIn6 { fn from(addr: net::SocketAddrV6) -> Self { #[allow(clippy::needless_update)] // It isn't needless on Illumos Self(libc::sockaddr_in6 { - #[cfg(any(bsd, target_os = "haiku", target_os = "hermit"))] + #[cfg(any( + bsd, + target_os = "haiku", + target_os = "hermit", + target_os = "hurd" + ))] sin6_len: mem::size_of::() as u8, sin6_family: AddressFamily::Inet6 as sa_family_t, sin6_port: addr.port().to_be(), // network byte order @@ -1059,7 +1081,10 @@ impl std::str::FromStr for SockaddrIn6 { pub union SockaddrStorage { #[cfg(linux_android)] alg: AlgAddr, - #[cfg(all(feature = "net", not(target_os = "redox")))] + #[cfg(all( + feature = "net", + not(any(target_os = "hurd", target_os = "redox")) + ))] #[cfg_attr(docsrs, doc(cfg(feature = "net")))] dl: LinkAddr, #[cfg(linux_android)] @@ -2124,7 +2149,7 @@ mod tests { } } - #[cfg(not(target_os = "redox"))] + #[cfg(not(any(target_os = "hurd", target_os = "redox")))] mod link { #![allow(clippy::cast_ptr_alignment)] @@ -2238,12 +2263,7 @@ mod tests { #[test] fn size() { - #[cfg(any( - bsd, - target_os = "aix", - solarish, - target_os = "haiku" - ))] + #[cfg(any(bsd, target_os = "aix", solarish, target_os = "haiku"))] let l = mem::size_of::(); #[cfg(any(linux_android, target_os = "fuchsia"))] let l = mem::size_of::(); diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs index a37e123616..96d20035e5 100644 --- a/src/sys/socket/mod.rs +++ b/src/sys/socket/mod.rs @@ -38,10 +38,10 @@ pub use self::addr::{SockaddrLike, SockaddrStorage}; pub use self::addr::{AddressFamily, UnixAddr}; #[cfg(not(solarish))] pub use self::addr::{AddressFamily, UnixAddr}; -#[cfg(not(any(solarish, target_os = "haiku", target_os = "redox")))] +#[cfg(not(any(solarish, target_os = "haiku", target_os = "hurd", target_os = "redox")))] #[cfg(feature = "net")] pub use self::addr::{LinkAddr, SockaddrIn, SockaddrIn6}; -#[cfg(any(solarish, target_os = "haiku", target_os = "redox"))] +#[cfg(any(solarish, target_os = "haiku", target_os = "hurd", target_os = "redox"))] #[cfg(feature = "net")] pub use self::addr::{SockaddrIn, SockaddrIn6}; diff --git a/src/sys/socket/sockopt.rs b/src/sys/socket/sockopt.rs index f5fef2e9f0..63db9b9e21 100644 --- a/src/sys/socket/sockopt.rs +++ b/src/sys/socket/sockopt.rs @@ -728,7 +728,7 @@ sockopt_impl!( libc::SO_TIMESTAMPING, super::TimestampingFlag ); -#[cfg(not(any(target_os = "aix", target_os = "haiku", target_os = "redox")))] +#[cfg(not(any(target_os = "aix", target_os = "haiku", target_os = "hurd", target_os = "redox")))] sockopt_impl!( /// Enable or disable the receiving of the `SO_TIMESTAMP` control message. ReceiveTimestamp, diff --git a/src/sys/statvfs.rs b/src/sys/statvfs.rs index 1b2cb5ea50..72f38ab7ab 100644 --- a/src/sys/statvfs.rs +++ b/src/sys/statvfs.rs @@ -104,9 +104,15 @@ impl Statvfs { } /// Get the file system id + #[cfg(not(target_os = "hurd"))] pub fn filesystem_id(&self) -> c_ulong { self.0.f_fsid } + /// Get the file system id + #[cfg(target_os = "hurd")] + pub fn filesystem_id(&self) -> u64 { + self.0.f_fsid + } /// Get the mount flags #[cfg(not(target_os = "redox"))] diff --git a/src/sys/termios.rs b/src/sys/termios.rs index bdddc0c735..57b42254ea 100644 --- a/src/sys/termios.rs +++ b/src/sys/termios.rs @@ -260,8 +260,13 @@ libc_enum! { /// /// B0 is special and will disable the port. #[cfg_attr(target_os = "haiku", repr(u8))] + #[cfg_attr(target_os = "hurd", repr(i32))] #[cfg_attr(all(apple_targets, target_pointer_width = "64"), repr(u64))] - #[cfg_attr(all(not(all(apple_targets, target_pointer_width = "64")), not(target_os = "haiku")), repr(u32))] + #[cfg_attr(all( + not(all(apple_targets, target_pointer_width = "64")), + not(target_os = "haiku"), + not(target_os = "hurd") + ), repr(u32))] #[non_exhaustive] pub enum BaudRate { B0, diff --git a/src/unistd.rs b/src/unistd.rs index a9d8b0aaf2..9c8d47946a 100644 --- a/src/unistd.rs +++ b/src/unistd.rs @@ -22,7 +22,7 @@ use crate::{Error, NixPath, Result}; use cfg_if::cfg_if; use libc::{ self, c_char, c_int, c_long, c_uint, gid_t, mode_t, off_t, pid_t, size_t, - uid_t, PATH_MAX, + uid_t, }; use std::convert::Infallible; #[cfg(not(target_os = "redox"))] @@ -669,8 +669,13 @@ pub fn getcwd() -> Result { } } + #[cfg(not(target_os = "hurd"))] + const PATH_MAX: usize = libc::PATH_MAX as usize; + #[cfg(target_os = "hurd")] + const PATH_MAX: usize = 1024; + // Trigger the internal buffer resizing logic. - reserve_double_buffer_size(&mut buf, PATH_MAX as usize)?; + reserve_double_buffer_size(&mut buf, PATH_MAX)?; } } } @@ -864,7 +869,7 @@ pub fn execvp>( /// This functions like a combination of `execvp(2)` and `execve(2)` to pass an /// environment and have a search path. See these two for additional /// information. -#[cfg(any(target_os = "haiku", target_os = "linux", target_os = "openbsd"))] +#[cfg(any(target_os = "haiku", target_os = "hurd", target_os = "linux", target_os = "openbsd"))] pub fn execvpe, SE: AsRef>( filename: &CStr, args: &[SA], @@ -890,7 +895,7 @@ pub fn execvpe, SE: AsRef>( /// /// This function is similar to `execve`, except that the program to be executed /// is referenced as a file descriptor instead of a path. -#[cfg(any(linux_android, freebsdlike))] +#[cfg(any(linux_android, freebsdlike, target_os = "hurd"))] #[inline] pub fn fexecve, SE: AsRef>( fd: RawFd, @@ -1193,6 +1198,7 @@ feature! { freebsdlike, solarish, target_os = "emscripten", + target_os = "hurd", target_os = "redox", netbsdlike, ))] @@ -3055,6 +3061,7 @@ pub struct User { target_os = "aix", target_os = "fuchsia", target_os = "haiku", + target_os = "hurd", )))] pub class: CString, /// Last password change @@ -3064,6 +3071,7 @@ pub struct User { target_os = "aix", target_os = "fuchsia", target_os = "haiku", + target_os = "hurd", )))] pub change: libc::time_t, /// Expiration time of account @@ -3073,6 +3081,7 @@ pub struct User { target_os = "aix", target_os = "fuchsia", target_os = "haiku", + target_os = "hurd", )))] pub expire: libc::time_t, } @@ -3125,6 +3134,7 @@ impl From<&libc::passwd> for User { target_os = "aix", target_os = "fuchsia", target_os = "haiku", + target_os = "hurd", )))] class: CString::new(CStr::from_ptr(pw.pw_class).to_bytes()) .unwrap(), @@ -3134,6 +3144,7 @@ impl From<&libc::passwd> for User { target_os = "aix", target_os = "fuchsia", target_os = "haiku", + target_os = "hurd", )))] change: pw.pw_change, #[cfg(not(any( @@ -3142,6 +3153,7 @@ impl From<&libc::passwd> for User { target_os = "aix", target_os = "fuchsia", target_os = "haiku", + target_os = "hurd", )))] expire: pw.pw_expire, } @@ -3182,6 +3194,7 @@ impl From for libc::passwd { target_os = "aix", target_os = "fuchsia", target_os = "haiku", + target_os = "hurd", )))] pw_class: u.class.into_raw(), #[cfg(not(any( @@ -3190,6 +3203,7 @@ impl From for libc::passwd { target_os = "aix", target_os = "fuchsia", target_os = "haiku", + target_os = "hurd", )))] pw_change: u.change, #[cfg(not(any( @@ -3198,6 +3212,7 @@ impl From for libc::passwd { target_os = "aix", target_os = "fuchsia", target_os = "haiku", + target_os = "hurd", )))] pw_expire: u.expire, #[cfg(target_os = "illumos")] @@ -3483,7 +3498,10 @@ feature! { /// (see [`ttyname(3)`](https://man7.org/linux/man-pages/man3/ttyname.3.html)). #[cfg(not(target_os = "fuchsia"))] pub fn ttyname(fd: F) -> Result { + #[cfg(not(target_os = "hurd"))] const PATH_MAX: usize = libc::PATH_MAX as usize; + #[cfg(target_os = "hurd")] + const PATH_MAX: usize = 1024; let mut buf = vec![0_u8; PATH_MAX]; let c_buf = buf.as_mut_ptr().cast(); diff --git a/test/sys/mod.rs b/test/sys/mod.rs index a62e6cb376..8812cdd6cd 100644 --- a/test/sys/mod.rs +++ b/test/sys/mod.rs @@ -15,7 +15,8 @@ mod test_aio; #[cfg(not(any( target_os = "redox", target_os = "fuchsia", - target_os = "haiku" + target_os = "haiku", + target_os = "hurd" )))] mod test_ioctl; #[cfg(not(target_os = "redox"))] diff --git a/test/test_unistd.rs b/test/test_unistd.rs index 0a841df060..c93562310d 100644 --- a/test/test_unistd.rs +++ b/test/test_unistd.rs @@ -432,6 +432,7 @@ cfg_if! { execve_test_factory!(test_fexecve, fexecve, File::open("/system/bin/sh").unwrap().into_raw_fd()); } else if #[cfg(any(target_os = "dragonfly", target_os = "freebsd", + target_os = "hurd", target_os = "linux"))] { // These tests frequently fail on musl, probably due to // https://github.com/nix-rust/nix/issues/555 @@ -447,7 +448,12 @@ cfg_if! { } } -#[cfg(any(target_os = "haiku", target_os = "linux", target_os = "openbsd"))] +#[cfg(any( + target_os = "haiku", + target_os = "hurd", + target_os = "linux", + target_os = "openbsd" +))] execve_test_factory!(test_execvpe, execvpe, &CString::new("sh").unwrap()); cfg_if! { @@ -656,10 +662,11 @@ fn test_acct() { acct::disable().unwrap(); } +#[cfg(not(target_os = "hurd"))] #[test] fn test_fpathconf_limited() { let f = tempfile().unwrap(); - // AFAIK, PATH_MAX is limited on all platforms, so it makes a good test + // PATH_MAX is limited on most platforms, so it makes a good test let path_max = fpathconf(f, PathconfVar::PATH_MAX); assert!( path_max @@ -669,9 +676,10 @@ fn test_fpathconf_limited() { ); } +#[cfg(not(target_os = "hurd"))] #[test] fn test_pathconf_limited() { - // AFAIK, PATH_MAX is limited on all platforms, so it makes a good test + // PATH_MAX is limited on most platforms, so it makes a good test let path_max = pathconf("/", PathconfVar::PATH_MAX); assert!( path_max @@ -681,9 +689,10 @@ fn test_pathconf_limited() { ); } +#[cfg(not(target_os = "hurd"))] #[test] fn test_sysconf_limited() { - // AFAIK, OPEN_MAX is limited on all platforms, so it makes a good test + // OPEN_MAX is limited on most platforms, so it makes a good test let open_max = sysconf(SysconfVar::OPEN_MAX); assert!( open_max