about summary refs log tree commit diff
path: root/library/std/src
diff options
context:
space:
mode:
Diffstat (limited to 'library/std/src')
-rw-r--r--library/std/src/f128.rs24
-rw-r--r--library/std/src/f16.rs24
-rw-r--r--library/std/src/io/mod.rs9
-rw-r--r--library/std/src/io/stdio.rs34
-rw-r--r--library/std/src/os/hermit/mod.rs2
-rw-r--r--library/std/src/os/windows/process.rs49
-rw-r--r--library/std/src/process.rs48
-rw-r--r--library/std/src/sys/pal/hermit/alloc.rs10
-rw-r--r--library/std/src/sys/pal/hermit/fd.rs12
-rw-r--r--library/std/src/sys/pal/hermit/fs.rs51
-rw-r--r--library/std/src/sys/pal/hermit/futex.rs16
-rw-r--r--library/std/src/sys/pal/hermit/mod.rs40
-rw-r--r--library/std/src/sys/pal/hermit/os.rs10
-rw-r--r--library/std/src/sys/pal/hermit/stdio.rs10
-rw-r--r--library/std/src/sys/pal/hermit/thread.rs16
-rw-r--r--library/std/src/sys/pal/hermit/time.rs10
-rw-r--r--library/std/src/sys/pal/unix/alloc.rs40
-rw-r--r--library/std/src/sys/pal/unix/rand.rs13
18 files changed, 255 insertions, 163 deletions
diff --git a/library/std/src/f128.rs b/library/std/src/f128.rs
index 4710d7c50b4..491235a872e 100644
--- a/library/std/src/f128.rs
+++ b/library/std/src/f128.rs
@@ -7,5 +7,29 @@
 #[cfg(test)]
 mod tests;
 
+#[cfg(not(test))]
+use crate::intrinsics;
+
 #[unstable(feature = "f128", issue = "116909")]
 pub use core::f128::consts;
+
+#[cfg(not(test))]
+impl f128 {
+    /// Raises a number to an integer power.
+    ///
+    /// Using this function is generally faster than using `powf`.
+    /// It might have a different sequence of rounding operations than `powf`,
+    /// so the results are not guaranteed to agree.
+    ///
+    /// # Unspecified precision
+    ///
+    /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and
+    /// can even differ within the same execution from one invocation to the next.
+    #[inline]
+    #[rustc_allow_incoherent_impl]
+    #[unstable(feature = "f128", issue = "116909")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn powi(self, n: i32) -> f128 {
+        unsafe { intrinsics::powif128(self, n) }
+    }
+}
diff --git a/library/std/src/f16.rs b/library/std/src/f16.rs
index c36f9f5d4c6..1cb655ffabd 100644
--- a/library/std/src/f16.rs
+++ b/library/std/src/f16.rs
@@ -7,5 +7,29 @@
 #[cfg(test)]
 mod tests;
 
+#[cfg(not(test))]
+use crate::intrinsics;
+
 #[unstable(feature = "f16", issue = "116909")]
 pub use core::f16::consts;
+
+#[cfg(not(test))]
+impl f16 {
+    /// Raises a number to an integer power.
+    ///
+    /// Using this function is generally faster than using `powf`.
+    /// It might have a different sequence of rounding operations than `powf`,
+    /// so the results are not guaranteed to agree.
+    ///
+    /// # Unspecified precision
+    ///
+    /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and
+    /// can even differ within the same execution from one invocation to the next.
+    #[inline]
+    #[rustc_allow_incoherent_impl]
+    #[unstable(feature = "f16", issue = "116909")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn powi(self, n: i32) -> f16 {
+        unsafe { intrinsics::powif16(self, n) }
+    }
+}
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index af055152cbe..f55ec1588f9 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -1839,7 +1839,11 @@ pub trait Write {
                 if output.error.is_err() {
                     output.error
                 } else {
-                    Err(error::const_io_error!(ErrorKind::Uncategorized, "formatter error"))
+                    // This shouldn't happen: the underlying stream did not error, but somehow
+                    // the formatter still errored?
+                    panic!(
+                        "a formatting trait implementation returned an error when the underlying stream did not"
+                    );
                 }
             }
         }
@@ -2040,7 +2044,6 @@ pub trait Seek {
     /// # Example
     ///
     /// ```no_run
-    /// #![feature(seek_seek_relative)]
     /// use std::{
     ///     io::{self, Seek},
     ///     fs::File,
@@ -2055,7 +2058,7 @@ pub trait Seek {
     /// ```
     ///
     /// [`BufReader`]: crate::io::BufReader
-    #[unstable(feature = "seek_seek_relative", issue = "117374")]
+    #[stable(feature = "seek_seek_relative", since = "CURRENT_RUSTC_VERSION")]
     fn seek_relative(&mut self, offset: i64) -> Result<()> {
         self.seek(SeekFrom::Current(offset))?;
         Ok(())
diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs
index 07fa9259e0b..c8968b74b12 100644
--- a/library/std/src/io/stdio.rs
+++ b/library/std/src/io/stdio.rs
@@ -1161,7 +1161,41 @@ pub trait IsTerminal: crate::sealed::Sealed {
     /// starting with `msys-` or `cygwin-` and ending in `-pty` will be considered terminals.
     /// Note that this [may change in the future][changes].
     ///
+    /// # Examples
+    ///
+    /// An example of a type for which `IsTerminal` is implemented is [`Stdin`]:
+    ///
+    /// ```no_run
+    /// use std::io::{self, IsTerminal, Write};
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let stdin = io::stdin();
+    ///
+    ///     // Indicate that the user is prompted for input, if this is a terminal.
+    ///     if stdin.is_terminal() {
+    ///         print!("> ");
+    ///         io::stdout().flush()?;
+    ///     }
+    ///
+    ///     let mut name = String::new();
+    ///     let _ = stdin.read_line(&mut name)?;
+    ///
+    ///     println!("Hello {}", name.trim_end());
+    ///
+    ///     Ok(())
+    /// }
+    /// ```
+    ///
+    /// The example can be run in two ways:
+    ///
+    /// - If you run this example by piping some text to it, e.g. `echo "foo" | path/to/executable`
+    ///   it will print: `Hello foo`.
+    /// - If you instead run the example interactively by running the executable directly, it will
+    ///   panic with the message "Expected input to be piped to the process".
+    ///
+    ///
     /// [changes]: io#platform-specific-behavior
+    /// [`Stdin`]: crate::io::Stdin
     #[stable(feature = "is_terminal", since = "1.70.0")]
     fn is_terminal(&self) -> bool;
 }
diff --git a/library/std/src/os/hermit/mod.rs b/library/std/src/os/hermit/mod.rs
index 89b1b831912..02a4b2c3ab5 100644
--- a/library/std/src/os/hermit/mod.rs
+++ b/library/std/src/os/hermit/mod.rs
@@ -2,7 +2,7 @@
 
 #[allow(unused_extern_crates)]
 #[stable(feature = "rust1", since = "1.0.0")]
-pub extern crate hermit_abi as abi;
+pub extern crate hermit_abi;
 
 pub mod ffi;
 pub mod io;
diff --git a/library/std/src/os/windows/process.rs b/library/std/src/os/windows/process.rs
index 15ab2250122..9cca27fa5dd 100644
--- a/library/std/src/os/windows/process.rs
+++ b/library/std/src/os/windows/process.rs
@@ -199,14 +199,14 @@ pub trait CommandExt: Sealed {
 
     /// Append literal text to the command line without any quoting or escaping.
     ///
-    /// This is useful for passing arguments to applications which doesn't follow
+    /// This is useful for passing arguments to applications that don't follow
     /// the standard C run-time escaping rules, such as `cmd.exe /c`.
     ///
-    /// # Bat files
+    /// # Batch files
     ///
-    /// Note the `cmd /c` command line has slightly different escaping rules then bat files
+    /// Note the `cmd /c` command line has slightly different escaping rules than batch files
     /// themselves. If possible, it may be better to write complex arguments to a temporary
-    /// .bat file, with appropriate escaping, and simply run that using:
+    /// `.bat` file, with appropriate escaping, and simply run that using:
     ///
     /// ```no_run
     /// # use std::process::Command;
@@ -217,7 +217,7 @@ pub trait CommandExt: Sealed {
     ///
     /// # Example
     ///
-    /// Run a bat script using both trusted and untrusted arguments.
+    /// Run a batch script using both trusted and untrusted arguments.
     ///
     /// ```no_run
     /// #[cfg(windows)]
@@ -241,9 +241,10 @@ pub trait CommandExt: Sealed {
     ///     if !user_name.chars().all(|c| c.is_alphanumeric()) {
     ///         return Err(Error::new(ErrorKind::InvalidInput, "invalid user name"));
     ///     }
-    ///     // now we've checked the user name, let's add that too.
-    ///     cmd_args.push(' ');
-    ///     cmd_args.push_str(&format!("--user {user_name}"));
+    ///
+    ///     // now we have validated the user name, let's add that too.
+    ///     cmd_args.push_str(" --user ");
+    ///     cmd_args.push_str(user_name);
     ///
     ///     // call cmd.exe and return the output
     ///     Command::new("cmd.exe")
@@ -287,25 +288,37 @@ pub trait CommandExt: Sealed {
     #[unstable(feature = "windows_process_extensions_async_pipes", issue = "98289")]
     fn async_pipes(&mut self, always_async: bool) -> &mut process::Command;
 
-    /// Sets a raw attribute on the command, providing extended configuration options for Windows processes.
+    /// Set a raw attribute on the command, providing extended configuration options for Windows
+    /// processes.
+    ///
+    /// This method allows you to specify custom attributes for a child process on Windows systems
+    /// using raw attribute values. Raw attributes provide extended configurability for process
+    /// creation, but their usage can be complex and potentially unsafe.
     ///
-    /// This method allows you to specify custom attributes for a child process on Windows systems using raw attribute values.
-    /// Raw attributes provide extended configurability for process creation, but their usage can be complex and potentially unsafe.
+    /// The `attribute` parameter specifies the raw attribute to be set, while the `value`
+    /// parameter holds the value associated with that attribute. Please refer to the
+    /// [`windows-rs` documentation] or the [Win32 API documentation] for detailed information
+    /// about available attributes and their meanings.
     ///
-    /// The `attribute` parameter specifies the raw attribute to be set, while the `value` parameter holds the value associated with that attribute.
-    /// Please refer to the [`windows-rs`](https://microsoft.github.io/windows-docs-rs/doc/windows/) documentation or the [`Win32 API documentation`](https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-updateprocthreadattribute) for detailed information about available attributes and their meanings.
+    /// [`windows-rs` documentation]: https://microsoft.github.io/windows-docs-rs/doc/windows/
+    /// [Win32 API documentation]: https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-updateprocthreadattribute
     ///
     /// # Note
     ///
     /// The maximum number of raw attributes is the value of [`u32::MAX`].
-    /// If this limit is exceeded, the call to [`process::Command::spawn`] will return an `Error` indicating that the maximum number of attributes has been exceeded.
+    /// If this limit is exceeded, the call to [`process::Command::spawn`] will return an `Error`
+    /// indicating that the maximum number of attributes has been exceeded.
+    ///
     /// # Safety
     ///
-    /// The usage of raw attributes is potentially unsafe and should be done with caution. Incorrect attribute values or improper configuration can lead to unexpected behavior or errors.
+    /// The usage of raw attributes is potentially unsafe and should be done with caution.
+    /// Incorrect attribute values or improper configuration can lead to unexpected behavior or
+    /// errors.
     ///
     /// # Example
     ///
-    /// The following example demonstrates how to create a child process with a specific parent process ID using a raw attribute.
+    /// The following example demonstrates how to create a child process with a specific parent
+    /// process ID using a raw attribute.
     ///
     /// ```rust
     /// #![feature(windows_process_extensions_raw_attribute)]
@@ -339,7 +352,9 @@ pub trait CommandExt: Sealed {
     ///
     /// # Safety Note
     ///
-    /// Remember that improper use of raw attributes can lead to undefined behavior or security vulnerabilities. Always consult the documentation and ensure proper attribute values are used.
+    /// Remember that improper use of raw attributes can lead to undefined behavior or security
+    /// vulnerabilities. Always consult the documentation and ensure proper attribute values are
+    /// used.
     #[unstable(feature = "windows_process_extensions_raw_attribute", issue = "114854")]
     unsafe fn raw_attribute<T: Copy + Send + Sync + 'static>(
         &mut self,
diff --git a/library/std/src/process.rs b/library/std/src/process.rs
index d1848224251..c926c89f7a9 100644
--- a/library/std/src/process.rs
+++ b/library/std/src/process.rs
@@ -90,8 +90,8 @@
 //!
 //! # Windows argument splitting
 //!
-//! On Unix systems arguments are passed to a new process as an array of strings
-//! but on Windows arguments are passed as a single commandline string and it's
+//! On Unix systems arguments are passed to a new process as an array of strings,
+//! but on Windows arguments are passed as a single commandline string and it is
 //! up to the child process to parse it into an array. Therefore the parent and
 //! child processes must agree on how the commandline string is encoded.
 //!
@@ -107,26 +107,26 @@
 //! * Use [`raw_arg`] to build a custom commandline. This bypasses the escaping
 //!   rules used by [`arg`] so should be used with due caution.
 //!
-//! `cmd.exe` and `.bat` use non-standard argument parsing and are especially
+//! `cmd.exe` and `.bat` files use non-standard argument parsing and are especially
 //! vulnerable to malicious input as they may be used to run arbitrary shell
 //! commands. Untrusted arguments should be restricted as much as possible.
 //! For examples on handling this see [`raw_arg`].
 //!
-//! ### Bat file special handling
+//! ### Batch file special handling
 //!
 //! On Windows, `Command` uses the Windows API function [`CreateProcessW`] to
-//! spawn new processes. An undocumented feature of this function is that,
+//! spawn new processes. An undocumented feature of this function is that
 //! when given a `.bat` file as the application to run, it will automatically
-//! convert that into running `cmd.exe /c` with the bat file as the next argument.
+//! convert that into running `cmd.exe /c` with the batch file as the next argument.
 //!
 //! For historical reasons Rust currently preserves this behaviour when using
 //! [`Command::new`], and escapes the arguments according to `cmd.exe` rules.
 //! Due to the complexity of `cmd.exe` argument handling, it might not be
-//! possible to safely escape some special chars, and using them will result
+//! possible to safely escape some special characters, and using them will result
 //! in an error being returned at process spawn. The set of unescapeable
-//! special chars might change between releases.
+//! special characters might change between releases.
 //!
-//! Also note that running `.bat` scripts in this way may be removed in the
+//! Also note that running batch scripts in this way may be removed in the
 //! future and so should not be relied upon.
 //!
 //! [`spawn`]: Command::spawn
@@ -659,16 +659,19 @@ impl Command {
     ///
     /// Note that the argument is not passed through a shell, but given
     /// literally to the program. This means that shell syntax like quotes,
-    /// escaped characters, word splitting, glob patterns, variable substitution, etc.
-    /// have no effect.
+    /// escaped characters, word splitting, glob patterns, variable substitution,
+    /// etc. have no effect.
     ///
     /// <div class="warning">
     ///
-    /// On Windows use caution with untrusted inputs. Most applications use the
-    /// standard convention for decoding arguments passed to them. These are safe to use with `arg`.
-    /// However some applications, such as `cmd.exe` and `.bat` files, use a non-standard way of decoding arguments
-    /// and are therefore vulnerable to malicious input.
-    /// In the case of `cmd.exe` this is especially important because a malicious argument can potentially run arbitrary shell commands.
+    /// On Windows, use caution with untrusted inputs. Most applications use the
+    /// standard convention for decoding arguments passed to them. These are safe to
+    /// use with `arg`. However, some applications such as `cmd.exe` and `.bat` files
+    /// use a non-standard way of decoding arguments. They are therefore vulnerable
+    /// to malicious input.
+    ///
+    /// In the case of `cmd.exe` this is especially important because a malicious
+    /// argument can potentially run arbitrary shell commands.
     ///
     /// See [Windows argument splitting][windows-args] for more details
     /// or [`raw_arg`] for manually implementing non-standard argument encoding.
@@ -710,11 +713,14 @@ impl Command {
     ///
     /// <div class="warning">
     ///
-    /// On Windows use caution with untrusted inputs. Most applications use the
-    /// standard convention for decoding arguments passed to them. These are safe to use with `args`.
-    /// However some applications, such as `cmd.exe` and `.bat` files, use a non-standard way of decoding arguments
-    /// and are therefore vulnerable to malicious input.
-    /// In the case of `cmd.exe` this is especially important because a malicious argument can potentially run arbitrary shell commands.
+    /// On Windows, use caution with untrusted inputs. Most applications use the
+    /// standard convention for decoding arguments passed to them. These are safe to
+    /// use with `arg`. However, some applications such as `cmd.exe` and `.bat` files
+    /// use a non-standard way of decoding arguments. They are therefore vulnerable
+    /// to malicious input.
+    ///
+    /// In the case of `cmd.exe` this is especially important because a malicious
+    /// argument can potentially run arbitrary shell commands.
     ///
     /// See [Windows argument splitting][windows-args] for more details
     /// or [`raw_arg`] for manually implementing non-standard argument encoding.
diff --git a/library/std/src/sys/pal/hermit/alloc.rs b/library/std/src/sys/pal/hermit/alloc.rs
index de550987a43..2cd0db90940 100644
--- a/library/std/src/sys/pal/hermit/alloc.rs
+++ b/library/std/src/sys/pal/hermit/alloc.rs
@@ -1,4 +1,4 @@
-use super::abi;
+use super::hermit_abi;
 use crate::alloc::{GlobalAlloc, Layout, System};
 use crate::ptr;
 
@@ -6,11 +6,11 @@ use crate::ptr;
 unsafe impl GlobalAlloc for System {
     #[inline]
     unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
-        abi::malloc(layout.size(), layout.align())
+        hermit_abi::malloc(layout.size(), layout.align())
     }
 
     unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
-        let addr = abi::malloc(layout.size(), layout.align());
+        let addr = hermit_abi::malloc(layout.size(), layout.align());
 
         if !addr.is_null() {
             ptr::write_bytes(addr, 0x00, layout.size());
@@ -21,11 +21,11 @@ unsafe impl GlobalAlloc for System {
 
     #[inline]
     unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
-        abi::free(ptr, layout.size(), layout.align())
+        hermit_abi::free(ptr, layout.size(), layout.align())
     }
 
     #[inline]
     unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
-        abi::realloc(ptr, layout.size(), layout.align(), new_size)
+        hermit_abi::realloc(ptr, layout.size(), layout.align(), new_size)
     }
 }
diff --git a/library/std/src/sys/pal/hermit/fd.rs b/library/std/src/sys/pal/hermit/fd.rs
index 962577bb1ed..d7dab08cfbd 100644
--- a/library/std/src/sys/pal/hermit/fd.rs
+++ b/library/std/src/sys/pal/hermit/fd.rs
@@ -1,6 +1,6 @@
 #![unstable(reason = "not public", issue = "none", feature = "fd")]
 
-use super::abi;
+use super::hermit_abi;
 use crate::io::{self, Read};
 use crate::os::hermit::io::{FromRawFd, OwnedFd, RawFd};
 use crate::sys::cvt;
@@ -16,7 +16,8 @@ pub struct FileDesc {
 
 impl FileDesc {
     pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
-        let result = cvt(unsafe { abi::read(self.fd.as_raw_fd(), buf.as_mut_ptr(), buf.len()) })?;
+        let result =
+            cvt(unsafe { hermit_abi::read(self.fd.as_raw_fd(), buf.as_mut_ptr(), buf.len()) })?;
         Ok(result as usize)
     }
 
@@ -26,7 +27,8 @@ impl FileDesc {
     }
 
     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
-        let result = cvt(unsafe { abi::write(self.fd.as_raw_fd(), buf.as_ptr(), buf.len()) })?;
+        let result =
+            cvt(unsafe { hermit_abi::write(self.fd.as_raw_fd(), buf.as_ptr(), buf.len()) })?;
         Ok(result as usize)
     }
 
@@ -49,8 +51,8 @@ impl FileDesc {
         unsupported()
     }
 
-    pub fn fstat(&self, stat: *mut abi::stat) -> io::Result<()> {
-        cvt(unsafe { abi::fstat(self.fd.as_raw_fd(), stat) })?;
+    pub fn fstat(&self, stat: *mut hermit_abi::stat) -> io::Result<()> {
+        cvt(unsafe { hermit_abi::fstat(self.fd.as_raw_fd(), stat) })?;
         Ok(())
     }
 }
diff --git a/library/std/src/sys/pal/hermit/fs.rs b/library/std/src/sys/pal/hermit/fs.rs
index 6519cc22f1f..a4a16e6e86b 100644
--- a/library/std/src/sys/pal/hermit/fs.rs
+++ b/library/std/src/sys/pal/hermit/fs.rs
@@ -1,8 +1,8 @@
-use super::abi::{
+use super::fd::FileDesc;
+use super::hermit_abi::{
     self, dirent64, stat as stat_struct, DT_DIR, DT_LNK, DT_REG, DT_UNKNOWN, O_APPEND, O_CREAT,
     O_EXCL, O_RDONLY, O_RDWR, O_TRUNC, O_WRONLY, S_IFDIR, S_IFLNK, S_IFMT, S_IFREG,
 };
-use super::fd::FileDesc;
 use crate::ffi::{CStr, OsStr, OsString};
 use crate::fmt;
 use crate::io::{self, Error, ErrorKind};
@@ -47,7 +47,7 @@ impl InnerReadDir {
 
 pub struct ReadDir {
     inner: Arc<InnerReadDir>,
-    pos: i64,
+    pos: usize,
 }
 
 impl ReadDir {
@@ -197,38 +197,31 @@ impl Iterator for ReadDir {
 
     fn next(&mut self) -> Option<io::Result<DirEntry>> {
         let mut counter: usize = 0;
-        let mut offset: i64 = 0;
+        let mut offset: usize = 0;
 
         // loop over all directory entries and search the entry for the current position
         loop {
             // leave function, if the loop reaches the of the buffer (with all entries)
-            if offset >= self.inner.dir.len().try_into().unwrap() {
+            if offset >= self.inner.dir.len() {
                 return None;
             }
 
-            let dir = unsafe {
-                &*(self.inner.dir.as_ptr().offset(offset.try_into().unwrap()) as *const dirent64)
-            };
+            let dir = unsafe { &*(self.inner.dir.as_ptr().add(offset) as *const dirent64) };
 
-            if counter == self.pos.try_into().unwrap() {
+            if counter == self.pos {
                 self.pos += 1;
 
                 // After dirent64, the file name is stored. d_reclen represents the length of the dirent64
                 // plus the length of the file name. Consequently, file name has a size of d_reclen minus
                 // the size of dirent64. The file name is always a C string and terminated by `\0`.
                 // Consequently, we are able to ignore the last byte.
-                let name_bytes = unsafe {
-                    core::slice::from_raw_parts(
-                        &dir.d_name as *const _ as *const u8,
-                        dir.d_reclen as usize - core::mem::size_of::<dirent64>() - 1,
-                    )
-                    .to_vec()
-                };
+                let name_bytes =
+                    unsafe { CStr::from_ptr(&dir.d_name as *const _ as *const i8).to_bytes() };
                 let entry = DirEntry {
                     root: self.inner.root.clone(),
                     ino: dir.d_ino,
                     type_: dir.d_type as u32,
-                    name: OsString::from_vec(name_bytes),
+                    name: OsString::from_vec(name_bytes.to_vec()),
                 };
 
                 return Some(Ok(entry));
@@ -237,7 +230,7 @@ impl Iterator for ReadDir {
             counter += 1;
 
             // move to the next dirent64, which is directly stored after the previous one
-            offset = offset + dir.d_off;
+            offset = offset + usize::from(dir.d_reclen);
         }
     }
 }
@@ -365,7 +358,7 @@ impl File {
             mode = 0;
         }
 
-        let fd = unsafe { cvt(abi::open(path.as_ptr(), flags, mode))? };
+        let fd = unsafe { cvt(hermit_abi::open(path.as_ptr(), flags, mode))? };
         Ok(File(unsafe { FileDesc::from_raw_fd(fd as i32) }))
     }
 
@@ -446,7 +439,7 @@ impl DirBuilder {
 
     pub fn mkdir(&self, path: &Path) -> io::Result<()> {
         run_path_with_cstr(path, &|path| {
-            cvt(unsafe { abi::mkdir(path.as_ptr(), self.mode) }).map(|_| ())
+            cvt(unsafe { hermit_abi::mkdir(path.as_ptr(), self.mode) }).map(|_| ())
         })
     }
 
@@ -508,7 +501,8 @@ impl FromRawFd for File {
 }
 
 pub fn readdir(path: &Path) -> io::Result<ReadDir> {
-    let fd_raw = run_path_with_cstr(path, &|path| cvt(unsafe { abi::opendir(path.as_ptr()) }))?;
+    let fd_raw =
+        run_path_with_cstr(path, &|path| cvt(unsafe { hermit_abi::opendir(path.as_ptr()) }))?;
     let fd = unsafe { FileDesc::from_raw_fd(fd_raw as i32) };
     let root = path.to_path_buf();
 
@@ -519,8 +513,9 @@ pub fn readdir(path: &Path) -> io::Result<ReadDir> {
         // reserve memory to receive all directory entries
         vec.resize(sz, 0);
 
-        let readlen =
-            unsafe { abi::getdents64(fd.as_raw_fd(), vec.as_mut_ptr() as *mut dirent64, sz) };
+        let readlen = unsafe {
+            hermit_abi::getdents64(fd.as_raw_fd(), vec.as_mut_ptr() as *mut dirent64, sz)
+        };
         if readlen > 0 {
             // shrink down to the minimal size
             vec.resize(readlen.try_into().unwrap(), 0);
@@ -529,7 +524,7 @@ pub fn readdir(path: &Path) -> io::Result<ReadDir> {
 
         // if the buffer is too small, getdents64 returns EINVAL
         // otherwise, getdents64 returns an error number
-        if readlen != (-abi::errno::EINVAL).into() {
+        if readlen != (-hermit_abi::errno::EINVAL).into() {
             return Err(Error::from_raw_os_error(readlen.try_into().unwrap()));
         }
 
@@ -547,7 +542,7 @@ pub fn readdir(path: &Path) -> io::Result<ReadDir> {
 }
 
 pub fn unlink(path: &Path) -> io::Result<()> {
-    run_path_with_cstr(path, &|path| cvt(unsafe { abi::unlink(path.as_ptr()) }).map(|_| ()))
+    run_path_with_cstr(path, &|path| cvt(unsafe { hermit_abi::unlink(path.as_ptr()) }).map(|_| ()))
 }
 
 pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> {
@@ -559,7 +554,7 @@ pub fn set_perm(_p: &Path, _perm: FilePermissions) -> io::Result<()> {
 }
 
 pub fn rmdir(path: &Path) -> io::Result<()> {
-    run_path_with_cstr(path, &|path| cvt(unsafe { abi::rmdir(path.as_ptr()) }).map(|_| ()))
+    run_path_with_cstr(path, &|path| cvt(unsafe { hermit_abi::rmdir(path.as_ptr()) }).map(|_| ()))
 }
 
 pub fn remove_dir_all(_path: &Path) -> io::Result<()> {
@@ -581,7 +576,7 @@ pub fn link(_original: &Path, _link: &Path) -> io::Result<()> {
 pub fn stat(path: &Path) -> io::Result<FileAttr> {
     run_path_with_cstr(path, &|path| {
         let mut stat_val: stat_struct = unsafe { mem::zeroed() };
-        cvt(unsafe { abi::stat(path.as_ptr(), &mut stat_val) })?;
+        cvt(unsafe { hermit_abi::stat(path.as_ptr(), &mut stat_val) })?;
         Ok(FileAttr::from_stat(stat_val))
     })
 }
@@ -589,7 +584,7 @@ pub fn stat(path: &Path) -> io::Result<FileAttr> {
 pub fn lstat(path: &Path) -> io::Result<FileAttr> {
     run_path_with_cstr(path, &|path| {
         let mut stat_val: stat_struct = unsafe { mem::zeroed() };
-        cvt(unsafe { abi::lstat(path.as_ptr(), &mut stat_val) })?;
+        cvt(unsafe { hermit_abi::lstat(path.as_ptr(), &mut stat_val) })?;
         Ok(FileAttr::from_stat(stat_val))
     })
 }
diff --git a/library/std/src/sys/pal/hermit/futex.rs b/library/std/src/sys/pal/hermit/futex.rs
index 427d8ff6f2e..571b2885658 100644
--- a/library/std/src/sys/pal/hermit/futex.rs
+++ b/library/std/src/sys/pal/hermit/futex.rs
@@ -1,4 +1,4 @@
-use super::abi;
+use super::hermit_abi;
 use crate::ptr::null;
 use crate::sync::atomic::AtomicU32;
 use crate::time::Duration;
@@ -8,32 +8,32 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -
     //
     // Overflows are rounded up to an infinite timeout (None).
     let timespec = timeout.and_then(|dur| {
-        Some(abi::timespec {
+        Some(hermit_abi::timespec {
             tv_sec: dur.as_secs().try_into().ok()?,
             tv_nsec: dur.subsec_nanos().into(),
         })
     });
 
     let r = unsafe {
-        abi::futex_wait(
+        hermit_abi::futex_wait(
             futex.as_ptr(),
             expected,
-            timespec.as_ref().map_or(null(), |t| t as *const abi::timespec),
-            abi::FUTEX_RELATIVE_TIMEOUT,
+            timespec.as_ref().map_or(null(), |t| t as *const hermit_abi::timespec),
+            hermit_abi::FUTEX_RELATIVE_TIMEOUT,
         )
     };
 
-    r != -abi::errno::ETIMEDOUT
+    r != -hermit_abi::errno::ETIMEDOUT
 }
 
 #[inline]
 pub fn futex_wake(futex: &AtomicU32) -> bool {
-    unsafe { abi::futex_wake(futex.as_ptr(), 1) > 0 }
+    unsafe { hermit_abi::futex_wake(futex.as_ptr(), 1) > 0 }
 }
 
 #[inline]
 pub fn futex_wake_all(futex: &AtomicU32) {
     unsafe {
-        abi::futex_wake(futex.as_ptr(), i32::MAX);
+        hermit_abi::futex_wake(futex.as_ptr(), i32::MAX);
     }
 }
diff --git a/library/std/src/sys/pal/hermit/mod.rs b/library/std/src/sys/pal/hermit/mod.rs
index 910935541bd..a64323a3a29 100644
--- a/library/std/src/sys/pal/hermit/mod.rs
+++ b/library/std/src/sys/pal/hermit/mod.rs
@@ -39,7 +39,7 @@ pub mod thread_local_key;
 pub mod time;
 
 use crate::io::ErrorKind;
-use crate::os::hermit::abi;
+use crate::os::hermit::hermit_abi;
 
 pub fn unsupported<T>() -> crate::io::Result<T> {
     Err(unsupported_err())
@@ -54,7 +54,7 @@ pub fn unsupported_err() -> crate::io::Error {
 
 pub fn abort_internal() -> ! {
     unsafe {
-        abi::abort();
+        hermit_abi::abort();
     }
 }
 
@@ -62,7 +62,7 @@ pub fn hashmap_random_keys() -> (u64, u64) {
     let mut buf = [0; 16];
     let mut slice = &mut buf[..];
     while !slice.is_empty() {
-        let res = cvt(unsafe { abi::read_entropy(slice.as_mut_ptr(), slice.len(), 0) })
+        let res = cvt(unsafe { hermit_abi::read_entropy(slice.as_mut_ptr(), slice.len(), 0) })
             .expect("failed to generate random hashmap keys");
         slice = &mut slice[res as usize..];
     }
@@ -109,31 +109,31 @@ pub unsafe extern "C" fn runtime_entry(
     let result = main(argc as isize, argv);
 
     run_dtors();
-    abi::exit(result);
+    hermit_abi::exit(result);
 }
 
 #[inline]
 pub(crate) fn is_interrupted(errno: i32) -> bool {
-    errno == abi::errno::EINTR
+    errno == hermit_abi::errno::EINTR
 }
 
 pub fn decode_error_kind(errno: i32) -> ErrorKind {
     match errno {
-        abi::errno::EACCES => ErrorKind::PermissionDenied,
-        abi::errno::EADDRINUSE => ErrorKind::AddrInUse,
-        abi::errno::EADDRNOTAVAIL => ErrorKind::AddrNotAvailable,
-        abi::errno::EAGAIN => ErrorKind::WouldBlock,
-        abi::errno::ECONNABORTED => ErrorKind::ConnectionAborted,
-        abi::errno::ECONNREFUSED => ErrorKind::ConnectionRefused,
-        abi::errno::ECONNRESET => ErrorKind::ConnectionReset,
-        abi::errno::EEXIST => ErrorKind::AlreadyExists,
-        abi::errno::EINTR => ErrorKind::Interrupted,
-        abi::errno::EINVAL => ErrorKind::InvalidInput,
-        abi::errno::ENOENT => ErrorKind::NotFound,
-        abi::errno::ENOTCONN => ErrorKind::NotConnected,
-        abi::errno::EPERM => ErrorKind::PermissionDenied,
-        abi::errno::EPIPE => ErrorKind::BrokenPipe,
-        abi::errno::ETIMEDOUT => ErrorKind::TimedOut,
+        hermit_abi::errno::EACCES => ErrorKind::PermissionDenied,
+        hermit_abi::errno::EADDRINUSE => ErrorKind::AddrInUse,
+        hermit_abi::errno::EADDRNOTAVAIL => ErrorKind::AddrNotAvailable,
+        hermit_abi::errno::EAGAIN => ErrorKind::WouldBlock,
+        hermit_abi::errno::ECONNABORTED => ErrorKind::ConnectionAborted,
+        hermit_abi::errno::ECONNREFUSED => ErrorKind::ConnectionRefused,
+        hermit_abi::errno::ECONNRESET => ErrorKind::ConnectionReset,
+        hermit_abi::errno::EEXIST => ErrorKind::AlreadyExists,
+        hermit_abi::errno::EINTR => ErrorKind::Interrupted,
+        hermit_abi::errno::EINVAL => ErrorKind::InvalidInput,
+        hermit_abi::errno::ENOENT => ErrorKind::NotFound,
+        hermit_abi::errno::ENOTCONN => ErrorKind::NotConnected,
+        hermit_abi::errno::EPERM => ErrorKind::PermissionDenied,
+        hermit_abi::errno::EPIPE => ErrorKind::BrokenPipe,
+        hermit_abi::errno::ETIMEDOUT => ErrorKind::TimedOut,
         _ => ErrorKind::Uncategorized,
     }
 }
diff --git a/library/std/src/sys/pal/hermit/os.rs b/library/std/src/sys/pal/hermit/os.rs
index 1f9affbf773..cc678123831 100644
--- a/library/std/src/sys/pal/hermit/os.rs
+++ b/library/std/src/sys/pal/hermit/os.rs
@@ -1,4 +1,4 @@
-use super::abi;
+use super::hermit_abi;
 use crate::collections::HashMap;
 use crate::error::Error as StdError;
 use crate::ffi::{CStr, OsStr, OsString};
@@ -14,11 +14,11 @@ use crate::vec;
 use core::slice::memchr;
 
 pub fn errno() -> i32 {
-    unsafe { abi::get_errno() }
+    unsafe { hermit_abi::get_errno() }
 }
 
 pub fn error_string(errno: i32) -> String {
-    abi::error_string(errno).to_string()
+    hermit_abi::error_string(errno).to_string()
 }
 
 pub fn getcwd() -> io::Result<PathBuf> {
@@ -197,10 +197,10 @@ pub fn home_dir() -> Option<PathBuf> {
 
 pub fn exit(code: i32) -> ! {
     unsafe {
-        abi::exit(code);
+        hermit_abi::exit(code);
     }
 }
 
 pub fn getpid() -> u32 {
-    unsafe { abi::getpid() }
+    unsafe { hermit_abi::getpid() }
 }
diff --git a/library/std/src/sys/pal/hermit/stdio.rs b/library/std/src/sys/pal/hermit/stdio.rs
index ac54385e8ce..777c57b391c 100644
--- a/library/std/src/sys/pal/hermit/stdio.rs
+++ b/library/std/src/sys/pal/hermit/stdio.rs
@@ -1,4 +1,4 @@
-use super::abi;
+use super::hermit_abi;
 use crate::io;
 use crate::io::{IoSlice, IoSliceMut};
 
@@ -37,7 +37,7 @@ impl io::Write for Stdout {
     fn write(&mut self, data: &[u8]) -> io::Result<usize> {
         let len;
 
-        unsafe { len = abi::write(1, data.as_ptr() as *const u8, data.len()) }
+        unsafe { len = hermit_abi::write(1, data.as_ptr() as *const u8, data.len()) }
 
         if len < 0 {
             Err(io::const_io_error!(io::ErrorKind::Uncategorized, "Stdout is not able to print"))
@@ -49,7 +49,7 @@ impl io::Write for Stdout {
     fn write_vectored(&mut self, data: &[IoSlice<'_>]) -> io::Result<usize> {
         let len;
 
-        unsafe { len = abi::write(1, data.as_ptr() as *const u8, data.len()) }
+        unsafe { len = hermit_abi::write(1, data.as_ptr() as *const u8, data.len()) }
 
         if len < 0 {
             Err(io::const_io_error!(io::ErrorKind::Uncategorized, "Stdout is not able to print"))
@@ -78,7 +78,7 @@ impl io::Write for Stderr {
     fn write(&mut self, data: &[u8]) -> io::Result<usize> {
         let len;
 
-        unsafe { len = abi::write(2, data.as_ptr() as *const u8, data.len()) }
+        unsafe { len = hermit_abi::write(2, data.as_ptr() as *const u8, data.len()) }
 
         if len < 0 {
             Err(io::const_io_error!(io::ErrorKind::Uncategorized, "Stderr is not able to print"))
@@ -90,7 +90,7 @@ impl io::Write for Stderr {
     fn write_vectored(&mut self, data: &[IoSlice<'_>]) -> io::Result<usize> {
         let len;
 
-        unsafe { len = abi::write(2, data.as_ptr() as *const u8, data.len()) }
+        unsafe { len = hermit_abi::write(2, data.as_ptr() as *const u8, data.len()) }
 
         if len < 0 {
             Err(io::const_io_error!(io::ErrorKind::Uncategorized, "Stderr is not able to print"))
diff --git a/library/std/src/sys/pal/hermit/thread.rs b/library/std/src/sys/pal/hermit/thread.rs
index 4fe6b12a95b..b336dcd6860 100644
--- a/library/std/src/sys/pal/hermit/thread.rs
+++ b/library/std/src/sys/pal/hermit/thread.rs
@@ -1,6 +1,6 @@
 #![allow(dead_code)]
 
-use super::abi;
+use super::hermit_abi;
 use super::thread_local_dtor::run_dtors;
 use crate::ffi::CStr;
 use crate::io;
@@ -9,7 +9,7 @@ use crate::num::NonZero;
 use crate::ptr;
 use crate::time::Duration;
 
-pub type Tid = abi::Tid;
+pub type Tid = hermit_abi::Tid;
 
 pub struct Thread {
     tid: Tid,
@@ -27,10 +27,10 @@ impl Thread {
         core_id: isize,
     ) -> io::Result<Thread> {
         let p = Box::into_raw(Box::new(p));
-        let tid = abi::spawn2(
+        let tid = hermit_abi::spawn2(
             thread_start,
             p.expose_provenance(),
-            abi::Priority::into(abi::NORMAL_PRIO),
+            hermit_abi::Priority::into(hermit_abi::NORMAL_PRIO),
             stack,
             core_id,
         );
@@ -62,7 +62,7 @@ impl Thread {
     #[inline]
     pub fn yield_now() {
         unsafe {
-            abi::yield_now();
+            hermit_abi::yield_now();
         }
     }
 
@@ -74,13 +74,13 @@ impl Thread {
     #[inline]
     pub fn sleep(dur: Duration) {
         unsafe {
-            abi::usleep(dur.as_micros() as u64);
+            hermit_abi::usleep(dur.as_micros() as u64);
         }
     }
 
     pub fn join(self) {
         unsafe {
-            let _ = abi::join(self.tid);
+            let _ = hermit_abi::join(self.tid);
         }
     }
 
@@ -98,5 +98,5 @@ impl Thread {
 }
 
 pub fn available_parallelism() -> io::Result<NonZero<usize>> {
-    unsafe { Ok(NonZero::new_unchecked(abi::get_processor_count())) }
+    unsafe { Ok(NonZero::new_unchecked(hermit_abi::get_processor_count())) }
 }
diff --git a/library/std/src/sys/pal/hermit/time.rs b/library/std/src/sys/pal/hermit/time.rs
index d6f9e4c1476..2bf24462fa8 100644
--- a/library/std/src/sys/pal/hermit/time.rs
+++ b/library/std/src/sys/pal/hermit/time.rs
@@ -1,8 +1,6 @@
 #![allow(dead_code)]
 
-use super::abi;
-use super::abi::timespec;
-use super::abi::{CLOCK_MONOTONIC, CLOCK_REALTIME, NSEC_PER_SEC};
+use super::hermit_abi::{self, timespec, CLOCK_MONOTONIC, CLOCK_REALTIME, NSEC_PER_SEC};
 use crate::cmp::Ordering;
 use crate::ops::{Add, AddAssign, Sub, SubAssign};
 use crate::time::Duration;
@@ -106,7 +104,8 @@ pub struct Instant(Timespec);
 impl Instant {
     pub fn now() -> Instant {
         let mut time: Timespec = Timespec::zero();
-        let _ = unsafe { abi::clock_gettime(CLOCK_MONOTONIC, core::ptr::addr_of_mut!(time.t)) };
+        let _ =
+            unsafe { hermit_abi::clock_gettime(CLOCK_MONOTONIC, core::ptr::addr_of_mut!(time.t)) };
 
         Instant(time)
     }
@@ -207,7 +206,8 @@ impl SystemTime {
 
     pub fn now() -> SystemTime {
         let mut time: Timespec = Timespec::zero();
-        let _ = unsafe { abi::clock_gettime(CLOCK_REALTIME, core::ptr::addr_of_mut!(time.t)) };
+        let _ =
+            unsafe { hermit_abi::clock_gettime(CLOCK_REALTIME, core::ptr::addr_of_mut!(time.t)) };
 
         SystemTime(time)
     }
diff --git a/library/std/src/sys/pal/unix/alloc.rs b/library/std/src/sys/pal/unix/alloc.rs
index 9938c0bac25..2f908e3d0e9 100644
--- a/library/std/src/sys/pal/unix/alloc.rs
+++ b/library/std/src/sys/pal/unix/alloc.rs
@@ -59,51 +59,29 @@ unsafe impl GlobalAlloc for System {
 }
 
 cfg_if::cfg_if! {
+    // We use posix_memalign wherever possible, but not all targets have that function.
     if #[cfg(any(
-        target_os = "android",
-        target_os = "illumos",
         target_os = "redox",
-        target_os = "solaris",
         target_os = "espidf",
         target_os = "horizon",
         target_os = "vita",
     ))] {
         #[inline]
         unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
-            // On android we currently target API level 9 which unfortunately
-            // doesn't have the `posix_memalign` API used below. Instead we use
-            // `memalign`, but this unfortunately has the property on some systems
-            // where the memory returned cannot be deallocated by `free`!
-            //
-            // Upon closer inspection, however, this appears to work just fine with
-            // Android, so for this platform we should be fine to call `memalign`
-            // (which is present in API level 9). Some helpful references could
-            // possibly be chromium using memalign [1], attempts at documenting that
-            // memalign + free is ok [2] [3], or the current source of chromium
-            // which still uses memalign on android [4].
-            //
-            // [1]: https://codereview.chromium.org/10796020/
-            // [2]: https://code.google.com/p/android/issues/detail?id=35391
-            // [3]: https://bugs.chromium.org/p/chromium/issues/detail?id=138579
-            // [4]: https://chromium.googlesource.com/chromium/src/base/+/master/
-            //                                       /memory/aligned_memory.cc
             libc::memalign(layout.align(), layout.size()) as *mut u8
         }
-    } else if #[cfg(target_os = "wasi")] {
-        #[inline]
-        unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
-            // C11 aligned_alloc requires that the size be a multiple of the alignment.
-            // Layout already checks that the size rounded up doesn't overflow isize::MAX.
-            let align = layout.align();
-            let size = layout.size().next_multiple_of(align);
-            libc::aligned_alloc(align, size) as *mut u8
-        }
     } else {
         #[inline]
         unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
             let mut out = ptr::null_mut();
-            // posix_memalign requires that the alignment be a multiple of `sizeof(void*)`.
-            // Since these are all powers of 2, we can just use max.
+            // We prefer posix_memalign over aligned_malloc since with aligned_malloc,
+            // implementations are making almost arbitrary choices for which alignments are
+            // "supported", making it hard to use. For instance, some implementations require the
+            // size to be a multiple of the alignment (wasi emmalloc), while others require the
+            // alignment to be at least the pointer size (Illumos, macOS) -- which may or may not be
+            // standards-compliant, but that does not help us.
+            // posix_memalign only has one, clear requirement: that the alignment be a multiple of
+            // `sizeof(void*)`. Since these are all powers of 2, we can just use max.
             let align = layout.align().max(crate::mem::size_of::<usize>());
             let ret = libc::posix_memalign(&mut out, align, layout.size());
             if ret != 0 { ptr::null_mut() } else { out as *mut u8 }
diff --git a/library/std/src/sys/pal/unix/rand.rs b/library/std/src/sys/pal/unix/rand.rs
index d8f227b4ef4..e6df109a6b8 100644
--- a/library/std/src/sys/pal/unix/rand.rs
+++ b/library/std/src/sys/pal/unix/rand.rs
@@ -59,7 +59,14 @@ mod imp {
         unsafe { getrandom(buf.as_mut_ptr().cast(), buf.len(), libc::GRND_NONBLOCK) }
     }
 
-    #[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "freebsd", netbsd10))]
+    #[cfg(any(
+        target_os = "espidf",
+        target_os = "horizon",
+        target_os = "freebsd",
+        netbsd10,
+        target_os = "illumos",
+        target_os = "solaris"
+    ))]
     fn getrandom(buf: &mut [u8]) -> libc::ssize_t {
         unsafe { libc::getrandom(buf.as_mut_ptr().cast(), buf.len(), 0) }
     }
@@ -83,6 +90,8 @@ mod imp {
         target_os = "horizon",
         target_os = "freebsd",
         target_os = "dragonfly",
+        target_os = "solaris",
+        target_os = "illumos",
         netbsd10
     )))]
     fn getrandom_fill_bytes(_buf: &mut [u8]) -> bool {
@@ -96,6 +105,8 @@ mod imp {
         target_os = "horizon",
         target_os = "freebsd",
         target_os = "dragonfly",
+        target_os = "solaris",
+        target_os = "illumos",
         netbsd10
     ))]
     fn getrandom_fill_bytes(v: &mut [u8]) -> bool {