about summary refs log tree commit diff
path: root/library/std/src
diff options
context:
space:
mode:
authorYuki Okushi <huyuumi.dev@gmail.com>2025-04-27 18:53:00 +0900
committerGitHub <noreply@github.com>2025-04-27 18:53:00 +0900
commitd91ffb6da5c306150e53f73a361f69837bc39851 (patch)
treeee6518c803de044596ce0e095d38bd7cab0f4a57 /library/std/src
parent89bb181106817c7828c16dc75ce5b2a367664471 (diff)
parent1b315ad92df192895fb2d1f0532270c54f6f8436 (diff)
downloadrust-d91ffb6da5c306150e53f73a361f69837bc39851.tar.gz
rust-d91ffb6da5c306150e53f73a361f69837bc39851.zip
Merge pull request #2351 from rust-lang/rustc-pull
Diffstat (limited to 'library/std/src')
-rw-r--r--library/std/src/collections/hash/map.rs3
-rw-r--r--library/std/src/os/unix/fs.rs36
-rw-r--r--library/std/src/os/unix/fs/tests.rs20
-rw-r--r--library/std/src/path.rs26
-rw-r--r--library/std/src/rt.rs2
-rw-r--r--library/std/src/sys/alloc/sgx.rs4
-rw-r--r--library/std/src/sys/args/hermit.rs35
-rw-r--r--library/std/src/sys/args/mod.rs8
-rw-r--r--library/std/src/sys/args/sgx.rs1
-rw-r--r--library/std/src/sys/args/unix.rs6
-rw-r--r--library/std/src/sys/fs/mod.rs2
-rw-r--r--library/std/src/sys/fs/unix.rs6
-rw-r--r--library/std/src/sys/pal/sgx/abi/tls/mod.rs6
-rw-r--r--library/std/src/sys/pal/sgx/os.rs6
-rw-r--r--library/std/src/sys/pal/sgx/thread.rs3
-rw-r--r--library/std/src/sys/process/unix/unix.rs8
-rw-r--r--library/std/src/thread/local.rs6
-rw-r--r--library/std/src/time.rs5
18 files changed, 122 insertions, 61 deletions
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index 0eef2bd225c..9ad26e5d28e 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -973,6 +973,9 @@ where
     /// Returns an array of length `N` with the results of each query. For soundness, at most one
     /// mutable reference will be returned to any value. `None` will be used if the key is missing.
     ///
+    /// This method performs a check to ensure there are no duplicate keys, which currently has a time-complexity of O(n^2),
+    /// so be careful when passing many keys.
+    ///
     /// # Panics
     ///
     /// Panics if any keys are overlapping.
diff --git a/library/std/src/os/unix/fs.rs b/library/std/src/os/unix/fs.rs
index 0427feb2955..4f9259f39c1 100644
--- a/library/std/src/os/unix/fs.rs
+++ b/library/std/src/os/unix/fs.rs
@@ -1100,3 +1100,39 @@ pub fn lchown<P: AsRef<Path>>(dir: P, uid: Option<u32>, gid: Option<u32>) -> io:
 pub fn chroot<P: AsRef<Path>>(dir: P) -> io::Result<()> {
     sys::fs::chroot(dir.as_ref())
 }
+
+/// Create a FIFO special file at the specified path with the specified mode.
+///
+/// # Examples
+///
+/// ```no_run
+/// # #![feature(unix_mkfifo)]
+/// # #[cfg(not(unix))]
+/// # fn main() {}
+/// # #[cfg(unix)]
+/// # fn main() -> std::io::Result<()> {
+/// # use std::{
+/// #     os::unix::fs::{mkfifo, PermissionsExt},
+/// #     fs::{File, Permissions, remove_file},
+/// #     io::{Write, Read},
+/// # };
+/// # let _ = remove_file("/tmp/fifo");
+/// mkfifo("/tmp/fifo", Permissions::from_mode(0o774))?;
+///
+/// let mut wx = File::options().read(true).write(true).open("/tmp/fifo")?;
+/// let mut rx = File::open("/tmp/fifo")?;
+///
+/// wx.write_all(b"hello, world!")?;
+/// drop(wx);
+///
+/// let mut s = String::new();
+/// rx.read_to_string(&mut s)?;
+///
+/// assert_eq!(s, "hello, world!");
+/// # Ok(())
+/// # }
+/// ```
+#[unstable(feature = "unix_mkfifo", issue = "139324")]
+pub fn mkfifo<P: AsRef<Path>>(path: P, permissions: Permissions) -> io::Result<()> {
+    sys::fs::mkfifo(path.as_ref(), permissions.mode())
+}
diff --git a/library/std/src/os/unix/fs/tests.rs b/library/std/src/os/unix/fs/tests.rs
index db9621c8c20..1840bb38c17 100644
--- a/library/std/src/os/unix/fs/tests.rs
+++ b/library/std/src/os/unix/fs/tests.rs
@@ -55,3 +55,23 @@ fn write_vectored_at() {
     let content = fs::read(&filename).unwrap();
     assert_eq!(&content, expected);
 }
+
+#[test]
+fn test_mkfifo() {
+    let tmp_dir = crate::test_helpers::tmpdir();
+
+    let fifo = tmp_dir.path().join("fifo");
+
+    mkfifo(&fifo, Permissions::from_mode(0o774)).unwrap();
+
+    let mut wx = fs::File::options().read(true).write(true).open(&fifo).unwrap();
+    let mut rx = fs::File::open(fifo).unwrap();
+
+    wx.write_all(b"hello, world!").unwrap();
+    drop(wx);
+
+    let mut s = String::new();
+    rx.read_to_string(&mut s).unwrap();
+
+    assert_eq!(s, "hello, world!");
+}
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 980213be7ea..7cd20c48d89 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -353,6 +353,15 @@ fn split_file_at_dot(file: &OsStr) -> (&OsStr, Option<&OsStr>) {
     }
 }
 
+/// Checks whether the string is valid as a file extension, or panics otherwise.
+fn validate_extension(extension: &OsStr) {
+    for &b in extension.as_encoded_bytes() {
+        if is_sep_byte(b) {
+            panic!("extension cannot contain path separators: {extension:?}");
+        }
+    }
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // The core iterators
 ////////////////////////////////////////////////////////////////////////////////
@@ -1507,13 +1516,7 @@ impl PathBuf {
     }
 
     fn _set_extension(&mut self, extension: &OsStr) -> bool {
-        for &b in extension.as_encoded_bytes() {
-            if b < 128 {
-                if is_separator(b as char) {
-                    panic!("extension cannot contain path separators: {:?}", extension);
-                }
-            }
-        }
+        validate_extension(extension);
 
         let file_stem = match self.file_stem() {
             None => return false,
@@ -1541,6 +1544,11 @@ impl PathBuf {
     /// Returns `false` and does nothing if [`self.file_name`] is [`None`],
     /// returns `true` and updates the extension otherwise.
     ///
+    /// # Panics
+    ///
+    /// Panics if the passed extension contains a path separator (see
+    /// [`is_separator`]).
+    ///
     /// # Caveats
     ///
     /// The appended `extension` may contain dots and will be used in its entirety,
@@ -1582,6 +1590,8 @@ impl PathBuf {
     }
 
     fn _add_extension(&mut self, extension: &OsStr) -> bool {
+        validate_extension(extension);
+
         let file_name = match self.file_name() {
             None => return false,
             Some(f) => f.as_encoded_bytes(),
@@ -3265,7 +3275,7 @@ impl Hash for Path {
                 if !verbatim {
                     component_start += match tail {
                         [b'.'] => 1,
-                        [b'.', sep @ _, ..] if is_sep_byte(*sep) => 1,
+                        [b'.', sep, ..] if is_sep_byte(*sep) => 1,
                         _ => 0,
                     };
                 }
diff --git a/library/std/src/rt.rs b/library/std/src/rt.rs
index 3a22a16cb16..9737b2f5bfe 100644
--- a/library/std/src/rt.rs
+++ b/library/std/src/rt.rs
@@ -46,7 +46,7 @@ macro_rules! rtprintpanic {
 macro_rules! rtabort {
     ($($t:tt)*) => {
         {
-            rtprintpanic!("fatal runtime error: {}\n", format_args!($($t)*));
+            rtprintpanic!("fatal runtime error: {}, aborting\n", format_args!($($t)*));
             crate::sys::abort_internal();
         }
     }
diff --git a/library/std/src/sys/alloc/sgx.rs b/library/std/src/sys/alloc/sgx.rs
index f5c27688fbc..7a846e2376b 100644
--- a/library/std/src/sys/alloc/sgx.rs
+++ b/library/std/src/sys/alloc/sgx.rs
@@ -10,8 +10,10 @@ use crate::sys::pal::waitqueue::SpinMutex;
 // The current allocator here is the `dlmalloc` crate which we've got included
 // in the rust-lang/rust repository as a submodule. The crate is a port of
 // dlmalloc.c from C to Rust.
+//
+// Specifying linkage/symbol name is solely to ensure a single instance between this crate and its unit tests
 #[cfg_attr(test, linkage = "available_externally")]
-#[unsafe(export_name = "_ZN16__rust_internals3std3sys3sgx5alloc8DLMALLOCE")]
+#[unsafe(export_name = "_ZN16__rust_internals3std3sys5alloc3sgx8DLMALLOCE")]
 static DLMALLOC: SpinMutex<dlmalloc::Dlmalloc<Sgx>> =
     SpinMutex::new(dlmalloc::Dlmalloc::new_with_allocator(Sgx {}));
 
diff --git a/library/std/src/sys/args/hermit.rs b/library/std/src/sys/args/hermit.rs
deleted file mode 100644
index ddd644a5540..00000000000
--- a/library/std/src/sys/args/hermit.rs
+++ /dev/null
@@ -1,35 +0,0 @@
-use crate::ffi::{CStr, OsString, c_char};
-use crate::os::hermit::ffi::OsStringExt;
-use crate::ptr;
-use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release};
-use crate::sync::atomic::{AtomicIsize, AtomicPtr};
-
-#[path = "common.rs"]
-mod common;
-pub use common::Args;
-
-static ARGC: AtomicIsize = AtomicIsize::new(0);
-static ARGV: AtomicPtr<*const u8> = AtomicPtr::new(ptr::null_mut());
-
-/// One-time global initialization.
-pub unsafe fn init(argc: isize, argv: *const *const u8) {
-    ARGC.store(argc, Relaxed);
-    // Use release ordering here to broadcast writes by the OS.
-    ARGV.store(argv as *mut *const u8, Release);
-}
-
-/// Returns the command line arguments
-pub fn args() -> Args {
-    // Synchronize with the store above.
-    let argv = ARGV.load(Acquire);
-    // If argv has not been initialized yet, do not return any arguments.
-    let argc = if argv.is_null() { 0 } else { ARGC.load(Relaxed) };
-    let args: Vec<OsString> = (0..argc)
-        .map(|i| unsafe {
-            let cstr = CStr::from_ptr(*argv.offset(i) as *const c_char);
-            OsStringExt::from_vec(cstr.to_bytes().to_vec())
-        })
-        .collect();
-
-    Args::new(args)
-}
diff --git a/library/std/src/sys/args/mod.rs b/library/std/src/sys/args/mod.rs
index f24d6eb123e..6a37b32d229 100644
--- a/library/std/src/sys/args/mod.rs
+++ b/library/std/src/sys/args/mod.rs
@@ -3,15 +3,15 @@
 #![forbid(unsafe_op_in_unsafe_fn)]
 
 cfg_if::cfg_if! {
-    if #[cfg(all(target_family = "unix", not(any(target_os = "espidf", target_os = "vita"))))] {
+    if #[cfg(any(
+        all(target_family = "unix", not(any(target_os = "espidf", target_os = "vita"))),
+        target_os = "hermit",
+    ))] {
         mod unix;
         pub use unix::*;
     } else if #[cfg(target_family = "windows")] {
         mod windows;
         pub use windows::*;
-    } else if #[cfg(target_os = "hermit")] {
-        mod hermit;
-        pub use hermit::*;
     } else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] {
         mod sgx;
         pub use sgx::*;
diff --git a/library/std/src/sys/args/sgx.rs b/library/std/src/sys/args/sgx.rs
index efc4b791852..0185a8a6000 100644
--- a/library/std/src/sys/args/sgx.rs
+++ b/library/std/src/sys/args/sgx.rs
@@ -8,6 +8,7 @@ use crate::sys::pal::abi::usercalls::raw::ByteBuffer;
 use crate::sys_common::FromInner;
 use crate::{fmt, slice};
 
+// Specifying linkage/symbol name is solely to ensure a single instance between this crate and its unit tests
 #[cfg_attr(test, linkage = "available_externally")]
 #[unsafe(export_name = "_ZN16__rust_internals3std3sys3sgx4args4ARGSE")]
 static ARGS: AtomicUsize = AtomicUsize::new(0);
diff --git a/library/std/src/sys/args/unix.rs b/library/std/src/sys/args/unix.rs
index 7d7815c6dff..c087fd62965 100644
--- a/library/std/src/sys/args/unix.rs
+++ b/library/std/src/sys/args/unix.rs
@@ -6,6 +6,9 @@
 #![allow(dead_code)] // runtime init functions not used during testing
 
 use crate::ffi::CStr;
+#[cfg(target_os = "hermit")]
+use crate::os::hermit::ffi::OsStringExt;
+#[cfg(not(target_os = "hermit"))]
 use crate::os::unix::ffi::OsStringExt;
 
 #[path = "common.rs"]
@@ -73,6 +76,7 @@ pub fn args() -> Args {
     target_os = "illumos",
     target_os = "emscripten",
     target_os = "haiku",
+    target_os = "hermit",
     target_os = "l4re",
     target_os = "fuchsia",
     target_os = "redox",
@@ -100,7 +104,7 @@ mod imp {
 
     unsafe fn really_init(argc: isize, argv: *const *const u8) {
         // These don't need to be ordered with each other or other stores,
-        // because they only hold the unmodified system-provide argv/argc.
+        // because they only hold the unmodified system-provided argv/argc.
         ARGC.store(argc, Ordering::Relaxed);
         ARGV.store(argv as *mut _, Ordering::Relaxed);
     }
diff --git a/library/std/src/sys/fs/mod.rs b/library/std/src/sys/fs/mod.rs
index 4c5e36ce67a..d55e28074fe 100644
--- a/library/std/src/sys/fs/mod.rs
+++ b/library/std/src/sys/fs/mod.rs
@@ -9,7 +9,7 @@ cfg_if::cfg_if! {
     if #[cfg(target_family = "unix")] {
         mod unix;
         use unix as imp;
-        pub use unix::{chown, fchown, lchown};
+        pub use unix::{chown, fchown, lchown, mkfifo};
         #[cfg(not(target_os = "fuchsia"))]
         pub use unix::chroot;
         pub(crate) use unix::debug_assert_fd_is_open;
diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs
index bc8817bac70..351a9f9413f 100644
--- a/library/std/src/sys/fs/unix.rs
+++ b/library/std/src/sys/fs/unix.rs
@@ -2137,6 +2137,12 @@ pub fn chroot(dir: &Path) -> io::Result<()> {
     Err(io::const_error!(io::ErrorKind::Unsupported, "chroot not supported by vxworks"))
 }
 
+pub fn mkfifo(path: &Path, mode: u32) -> io::Result<()> {
+    run_path_with_cstr(path, &|path| {
+        cvt(unsafe { libc::mkfifo(path.as_ptr(), mode.try_into().unwrap()) }).map(|_| ())
+    })
+}
+
 pub use remove_dir_impl::remove_dir_all;
 
 // Fallback for REDOX, ESP-ID, Horizon, Vita, Vxworks and Miri
diff --git a/library/std/src/sys/pal/sgx/abi/tls/mod.rs b/library/std/src/sys/pal/sgx/abi/tls/mod.rs
index 8e2b271f1c9..f082d94614b 100644
--- a/library/std/src/sys/pal/sgx/abi/tls/mod.rs
+++ b/library/std/src/sys/pal/sgx/abi/tls/mod.rs
@@ -11,15 +11,17 @@ const USIZE_BITS: usize = 64;
 const TLS_KEYS: usize = 128; // Same as POSIX minimum
 const TLS_KEYS_BITSET_SIZE: usize = (TLS_KEYS + (USIZE_BITS - 1)) / USIZE_BITS;
 
+// Specifying linkage/symbol name is solely to ensure a single instance between this crate and its unit tests
 #[cfg_attr(test, linkage = "available_externally")]
-#[unsafe(export_name = "_ZN16__rust_internals3std3sys3sgx3abi3tls14TLS_KEY_IN_USEE")]
+#[unsafe(export_name = "_ZN16__rust_internals3std3sys3pal3sgx3abi3tls14TLS_KEY_IN_USEE")]
 static TLS_KEY_IN_USE: SyncBitset = SYNC_BITSET_INIT;
 macro_rules! dup {
     ((* $($exp:tt)*) $($val:tt)*) => (dup!( ($($exp)*) $($val)* $($val)* ));
     (() $($val:tt)*) => ([$($val),*])
 }
+// Specifying linkage/symbol name is solely to ensure a single instance between this crate and its unit tests
 #[cfg_attr(test, linkage = "available_externally")]
-#[unsafe(export_name = "_ZN16__rust_internals3std3sys3sgx3abi3tls14TLS_DESTRUCTORE")]
+#[unsafe(export_name = "_ZN16__rust_internals3std3sys3pal3sgx3abi3tls14TLS_DESTRUCTORE")]
 static TLS_DESTRUCTOR: [AtomicUsize; TLS_KEYS] = dup!((* * * * * * *) (AtomicUsize::new(0)));
 
 unsafe extern "C" {
diff --git a/library/std/src/sys/pal/sgx/os.rs b/library/std/src/sys/pal/sgx/os.rs
index b1ec2afd764..010634cf310 100644
--- a/library/std/src/sys/pal/sgx/os.rs
+++ b/library/std/src/sys/pal/sgx/os.rs
@@ -73,11 +73,13 @@ pub fn current_exe() -> io::Result<PathBuf> {
     unsupported()
 }
 
+// Specifying linkage/symbol name is solely to ensure a single instance between this crate and its unit tests
 #[cfg_attr(test, linkage = "available_externally")]
-#[unsafe(export_name = "_ZN16__rust_internals3std3sys3sgx2os3ENVE")]
+#[unsafe(export_name = "_ZN16__rust_internals3std3sys3pal3sgx2os3ENVE")]
 static ENV: AtomicUsize = AtomicUsize::new(0);
+// Specifying linkage/symbol name is solely to ensure a single instance between this crate and its unit tests
 #[cfg_attr(test, linkage = "available_externally")]
-#[unsafe(export_name = "_ZN16__rust_internals3std3sys3sgx2os8ENV_INITE")]
+#[unsafe(export_name = "_ZN16__rust_internals3std3sys3pal3sgx2os8ENV_INITE")]
 static ENV_INIT: Once = Once::new();
 type EnvStore = Mutex<HashMap<OsString, OsString>>;
 
diff --git a/library/std/src/sys/pal/sgx/thread.rs b/library/std/src/sys/pal/sgx/thread.rs
index b6932df431f..219ef1b7a98 100644
--- a/library/std/src/sys/pal/sgx/thread.rs
+++ b/library/std/src/sys/pal/sgx/thread.rs
@@ -45,8 +45,9 @@ mod task_queue {
         }
     }
 
+    // Specifying linkage/symbol name is solely to ensure a single instance between this crate and its unit tests
     #[cfg_attr(test, linkage = "available_externally")]
-    #[unsafe(export_name = "_ZN16__rust_internals3std3sys3sgx6thread10TASK_QUEUEE")]
+    #[unsafe(export_name = "_ZN16__rust_internals3std3sys3pal3sgx6thread10TASK_QUEUEE")]
     static TASK_QUEUE: Mutex<Vec<Task>> = Mutex::new(Vec::new());
 
     pub(super) fn lock() -> MutexGuard<'static, Vec<Task>> {
diff --git a/library/std/src/sys/process/unix/unix.rs b/library/std/src/sys/process/unix/unix.rs
index 3b04ec50db3..92bb809d90c 100644
--- a/library/std/src/sys/process/unix/unix.rs
+++ b/library/std/src/sys/process/unix/unix.rs
@@ -415,6 +415,7 @@ impl Command {
         all(target_os = "linux", target_env = "musl"),
         target_os = "nto",
         target_vendor = "apple",
+        target_os = "cygwin",
     )))]
     fn posix_spawn(
         &mut self,
@@ -433,6 +434,7 @@ impl Command {
         all(target_os = "linux", target_env = "musl"),
         target_os = "nto",
         target_vendor = "apple",
+        target_os = "cygwin",
     ))]
     fn posix_spawn(
         &mut self,
@@ -584,7 +586,7 @@ impl Command {
         /// Some platforms can set a new working directory for a spawned process in the
         /// `posix_spawn` path. This function looks up the function pointer for adding
         /// such an action to a `posix_spawn_file_actions_t` struct.
-        #[cfg(not(all(target_os = "linux", target_env = "musl")))]
+        #[cfg(not(any(all(target_os = "linux", target_env = "musl"), target_os = "cygwin")))]
         fn get_posix_spawn_addchdir() -> Option<PosixSpawnAddChdirFn> {
             use crate::sys::weak::weak;
 
@@ -618,7 +620,9 @@ impl Command {
         /// Weak symbol lookup doesn't work with statically linked libcs, so in cases
         /// where static linking is possible we need to either check for the presence
         /// of the symbol at compile time or know about it upfront.
-        #[cfg(all(target_os = "linux", target_env = "musl"))]
+        ///
+        /// Cygwin doesn't support weak symbol, so just link it.
+        #[cfg(any(all(target_os = "linux", target_env = "musl"), target_os = "cygwin"))]
         fn get_posix_spawn_addchdir() -> Option<PosixSpawnAddChdirFn> {
             // Our minimum required musl supports this function, so we can just use it.
             Some(libc::posix_spawn_file_actions_addchdir_np)
diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs
index d5a5d10205d..7cd44873313 100644
--- a/library/std/src/thread/local.rs
+++ b/library/std/src/thread/local.rs
@@ -22,12 +22,16 @@ use crate::fmt;
 ///
 /// Initialization is dynamically performed on the first call to a setter (e.g.
 /// [`with`]) within a thread, and values that implement [`Drop`] get
-/// destructed when a thread exits. Some caveats apply, which are explained below.
+/// destructed when a thread exits. Some platform-specific caveats apply, which
+/// are explained below.
+/// Note that, should the destructor panics, the whole process will be [aborted].
 ///
 /// A `LocalKey`'s initializer cannot recursively depend on itself. Using a
 /// `LocalKey` in this way may cause panics, aborts or infinite recursion on
 /// the first call to `with`.
 ///
+/// [aborted]: crate::process::abort
+///
 /// # Single-thread Synchronization
 ///
 /// Though there is no potential race with other threads, it is still possible to
diff --git a/library/std/src/time.rs b/library/std/src/time.rs
index 5ab71413586..03af35e809c 100644
--- a/library/std/src/time.rs
+++ b/library/std/src/time.rs
@@ -205,8 +205,8 @@ pub struct Instant(time::Instant);
 ///            println!("{}", elapsed.as_secs());
 ///        }
 ///        Err(e) => {
-///            // an error occurred!
-///            println!("Error: {e:?}");
+///            // the system clock went backwards!
+///            println!("Great Scott! {e:?}");
 ///        }
 ///    }
 /// }
@@ -245,6 +245,7 @@ pub struct Instant(time::Instant);
 /// > structure cannot represent the new point in time.
 ///
 /// [`add`]: SystemTime::add
+/// [`UNIX_EPOCH`]: SystemTime::UNIX_EPOCH
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
 #[stable(feature = "time2", since = "1.8.0")]
 pub struct SystemTime(time::SystemTime);