diff options
| author | Yuki Okushi <huyuumi.dev@gmail.com> | 2025-04-27 18:53:00 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-04-27 18:53:00 +0900 |
| commit | d91ffb6da5c306150e53f73a361f69837bc39851 (patch) | |
| tree | ee6518c803de044596ce0e095d38bd7cab0f4a57 /library/std/src | |
| parent | 89bb181106817c7828c16dc75ce5b2a367664471 (diff) | |
| parent | 1b315ad92df192895fb2d1f0532270c54f6f8436 (diff) | |
| download | rust-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.rs | 3 | ||||
| -rw-r--r-- | library/std/src/os/unix/fs.rs | 36 | ||||
| -rw-r--r-- | library/std/src/os/unix/fs/tests.rs | 20 | ||||
| -rw-r--r-- | library/std/src/path.rs | 26 | ||||
| -rw-r--r-- | library/std/src/rt.rs | 2 | ||||
| -rw-r--r-- | library/std/src/sys/alloc/sgx.rs | 4 | ||||
| -rw-r--r-- | library/std/src/sys/args/hermit.rs | 35 | ||||
| -rw-r--r-- | library/std/src/sys/args/mod.rs | 8 | ||||
| -rw-r--r-- | library/std/src/sys/args/sgx.rs | 1 | ||||
| -rw-r--r-- | library/std/src/sys/args/unix.rs | 6 | ||||
| -rw-r--r-- | library/std/src/sys/fs/mod.rs | 2 | ||||
| -rw-r--r-- | library/std/src/sys/fs/unix.rs | 6 | ||||
| -rw-r--r-- | library/std/src/sys/pal/sgx/abi/tls/mod.rs | 6 | ||||
| -rw-r--r-- | library/std/src/sys/pal/sgx/os.rs | 6 | ||||
| -rw-r--r-- | library/std/src/sys/pal/sgx/thread.rs | 3 | ||||
| -rw-r--r-- | library/std/src/sys/process/unix/unix.rs | 8 | ||||
| -rw-r--r-- | library/std/src/thread/local.rs | 6 | ||||
| -rw-r--r-- | library/std/src/time.rs | 5 |
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); |
