Rollup merge of #139710 - thaliaarchi:move-args-pal, r=joboet

Move `args` into `std::sys`

Move platform definitions of `args` into `std::sys`, as part of https://github.com/rust-lang/rust/issues/117276.

cc ``@joboet``
This commit is contained in:
Chris Denton 2025-04-13 11:48:19 +00:00 committed by GitHub
commit daed9e2d9f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
29 changed files with 171 additions and 315 deletions

View File

@ -0,0 +1,43 @@
use crate::ffi::OsString;
use crate::{fmt, vec};
pub struct Args {
iter: vec::IntoIter<OsString>,
}
impl !Send for Args {}
impl !Sync for Args {}
impl Args {
pub(super) fn new(args: Vec<OsString>) -> Self {
Args { iter: args.into_iter() }
}
}
impl fmt::Debug for Args {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.iter.as_slice().fmt(f)
}
}
impl Iterator for Args {
type Item = OsString;
fn next(&mut self) -> Option<OsString> {
self.iter.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl ExactSizeIterator for Args {
fn len(&self) -> usize {
self.iter.len()
}
}
impl DoubleEndedIterator for Args {
fn next_back(&mut self) -> Option<OsString> {
self.iter.next_back()
}
}

View File

@ -1,8 +1,12 @@
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};
use crate::{fmt, ptr, vec};
#[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());
@ -27,40 +31,5 @@ pub fn args() -> Args {
})
.collect();
Args { iter: args.into_iter() }
}
pub struct Args {
iter: vec::IntoIter<OsString>,
}
impl fmt::Debug for Args {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.iter.as_slice().fmt(f)
}
}
impl !Send for Args {}
impl !Sync for Args {}
impl Iterator for Args {
type Item = OsString;
fn next(&mut self) -> Option<OsString> {
self.iter.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl ExactSizeIterator for Args {
fn len(&self) -> usize {
self.iter.len()
}
}
impl DoubleEndedIterator for Args {
fn next_back(&mut self) -> Option<OsString> {
self.iter.next_back()
}
Args::new(args)
}

View File

@ -0,0 +1,34 @@
//! Platform-dependent command line arguments abstraction.
#![forbid(unsafe_op_in_unsafe_fn)]
cfg_if::cfg_if! {
if #[cfg(all(target_family = "unix", not(any(target_os = "espidf", target_os = "vita"))))] {
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::*;
} else if #[cfg(target_os = "uefi")] {
mod uefi;
pub use uefi::*;
} else if #[cfg(target_os = "wasi")] {
mod wasi;
pub use wasi::*;
} else if #[cfg(target_os = "xous")] {
mod xous;
pub use xous::*;
} else if #[cfg(target_os = "zkvm")] {
mod zkvm;
pub use zkvm::*;
} else {
mod unsupported;
pub use unsupported::*;
}
}

View File

@ -1,8 +1,10 @@
use super::abi::usercalls::alloc;
use super::abi::usercalls::raw::ByteBuffer;
#![allow(fuzzy_provenance_casts)] // FIXME: this module systematically confuses pointers and integers
use crate::ffi::OsString;
use crate::sync::atomic::{AtomicUsize, Ordering};
use crate::sys::os_str::Buf;
use crate::sys::pal::abi::usercalls::alloc;
use crate::sys::pal::abi::usercalls::raw::ByteBuffer;
use crate::sys_common::FromInner;
use crate::{fmt, slice};

View File

@ -1,14 +1,13 @@
use r_efi::protocols::loaded_image;
use super::helpers;
use crate::env::current_exe;
use crate::ffi::OsString;
use crate::iter::Iterator;
use crate::{fmt, vec};
use crate::sys::pal::helpers;
pub struct Args {
parsed_args_list: vec::IntoIter<OsString>,
}
#[path = "common.rs"]
mod common;
pub use common::Args;
pub fn args() -> Args {
let lazy_current_exe = || Vec::from([current_exe().map(Into::into).unwrap_or_default()]);
@ -22,51 +21,17 @@ pub fn args() -> Args {
let lp_size = unsafe { (*protocol.as_ptr()).load_options_size } as usize;
// Break if we are sure that it cannot be UTF-16
if lp_size < size_of::<u16>() || lp_size % size_of::<u16>() != 0 {
return Args { parsed_args_list: lazy_current_exe().into_iter() };
return Args::new(lazy_current_exe());
}
let lp_size = lp_size / size_of::<u16>();
let lp_cmd_line = unsafe { (*protocol.as_ptr()).load_options as *const u16 };
if !lp_cmd_line.is_aligned() {
return Args { parsed_args_list: lazy_current_exe().into_iter() };
return Args::new(lazy_current_exe());
}
let lp_cmd_line = unsafe { crate::slice::from_raw_parts(lp_cmd_line, lp_size) };
Args {
parsed_args_list: parse_lp_cmd_line(lp_cmd_line)
.unwrap_or_else(lazy_current_exe)
.into_iter(),
}
}
impl fmt::Debug for Args {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.parsed_args_list.as_slice().fmt(f)
}
}
impl Iterator for Args {
type Item = OsString;
fn next(&mut self) -> Option<OsString> {
self.parsed_args_list.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.parsed_args_list.size_hint()
}
}
impl ExactSizeIterator for Args {
fn len(&self) -> usize {
self.parsed_args_list.len()
}
}
impl DoubleEndedIterator for Args {
fn next_back(&mut self) -> Option<OsString> {
self.parsed_args_list.next_back()
}
Args::new(parse_lp_cmd_line(lp_cmd_line).unwrap_or_else(lazy_current_exe))
}
/// Implements the UEFI command-line argument parsing algorithm.

View File

@ -5,13 +5,16 @@
#![allow(dead_code)] // runtime init functions not used during testing
use crate::ffi::{CStr, OsString};
use crate::ffi::CStr;
use crate::os::unix::ffi::OsStringExt;
use crate::{fmt, vec};
#[path = "common.rs"]
mod common;
pub use common::Args;
/// One-time global initialization.
pub unsafe fn init(argc: isize, argv: *const *const u8) {
imp::init(argc, argv)
unsafe { imp::init(argc, argv) }
}
/// Returns the command line arguments
@ -55,42 +58,7 @@ pub fn args() -> Args {
vec.push(OsStringExt::from_vec(cstr.to_bytes().to_vec()));
}
Args { iter: vec.into_iter() }
}
pub struct Args {
iter: vec::IntoIter<OsString>,
}
impl !Send for Args {}
impl !Sync for Args {}
impl fmt::Debug for Args {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.iter.as_slice().fmt(f)
}
}
impl Iterator for Args {
type Item = OsString;
fn next(&mut self) -> Option<OsString> {
self.iter.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl ExactSizeIterator for Args {
fn len(&self) -> usize {
self.iter.len()
}
}
impl DoubleEndedIterator for Args {
fn next_back(&mut self) -> Option<OsString> {
self.iter.next_back()
}
Args::new(vec)
}
#[cfg(any(
@ -141,7 +109,7 @@ mod imp {
pub unsafe fn init(argc: isize, argv: *const *const u8) {
// on GNU/Linux if we are main then we will init argv and argc twice, it "duplicates work"
// BUT edge-cases are real: only using .init_array can break most emulators, dlopen, etc.
really_init(argc, argv);
unsafe { really_init(argc, argv) };
}
/// glibc passes argc, argv, and envp to functions in .init_array, as a non-standard extension.
@ -159,9 +127,7 @@ mod imp {
argv: *const *const u8,
_envp: *const *const u8,
) {
unsafe {
really_init(argc as isize, argv);
}
unsafe { really_init(argc as isize, argv) };
}
init_wrapper
};
@ -228,16 +194,3 @@ mod imp {
(argc as isize, argv.cast())
}
}
#[cfg(any(target_os = "espidf", target_os = "vita"))]
mod imp {
use crate::ffi::c_char;
use crate::ptr;
#[inline(always)]
pub unsafe fn init(_argc: isize, _argv: *const *const u8) {}
pub fn argc_argv() -> (isize, *const *const c_char) {
(0, ptr::null())
}
}

View File

@ -0,0 +1,29 @@
#![forbid(unsafe_op_in_unsafe_fn)]
use crate::ffi::{CStr, OsStr, OsString};
use crate::os::wasi::ffi::OsStrExt;
#[path = "common.rs"]
mod common;
pub use common::Args;
/// Returns the command line arguments
pub fn args() -> Args {
Args::new(maybe_args().unwrap_or(Vec::new()))
}
fn maybe_args() -> Option<Vec<OsString>> {
unsafe {
let (argc, buf_size) = wasi::args_sizes_get().ok()?;
let mut argv = Vec::with_capacity(argc);
let mut buf = Vec::with_capacity(buf_size);
wasi::args_get(argv.as_mut_ptr(), buf.as_mut_ptr()).ok()?;
argv.set_len(argc);
let mut ret = Vec::with_capacity(argc);
for ptr in argv {
let s = CStr::from_ptr(ptr.cast());
ret.push(OsStr::from_bytes(s.to_bytes()).to_owned());
}
Some(ret)
}
}

View File

@ -6,17 +6,21 @@
#[cfg(test)]
mod tests;
use super::ensure_no_nuls;
use super::os::current_exe;
use crate::ffi::{OsStr, OsString};
use crate::num::NonZero;
use crate::os::windows::prelude::*;
use crate::path::{Path, PathBuf};
use crate::sys::pal::os::current_exe;
use crate::sys::pal::{ensure_no_nuls, fill_utf16_buf};
use crate::sys::path::get_long_path;
use crate::sys::{c, to_u16s};
use crate::sys_common::AsInner;
use crate::sys_common::wstr::WStrUnits;
use crate::{fmt, io, iter, vec};
use crate::{io, iter, ptr};
#[path = "common.rs"]
mod common;
pub use common::Args;
pub fn args() -> Args {
// SAFETY: `GetCommandLineW` returns a pointer to a null terminated UTF-16
@ -27,7 +31,7 @@ pub fn args() -> Args {
current_exe().map(PathBuf::into_os_string).unwrap_or_else(|_| OsString::new())
});
Args { parsed_args_list: parsed_args_list.into_iter() }
Args::new(parsed_args_list)
}
}
@ -153,38 +157,6 @@ fn parse_lp_cmd_line<'a, F: Fn() -> OsString>(
ret_val
}
pub struct Args {
parsed_args_list: vec::IntoIter<OsString>,
}
impl fmt::Debug for Args {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.parsed_args_list.as_slice().fmt(f)
}
}
impl Iterator for Args {
type Item = OsString;
fn next(&mut self) -> Option<OsString> {
self.parsed_args_list.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.parsed_args_list.size_hint()
}
}
impl DoubleEndedIterator for Args {
fn next_back(&mut self) -> Option<OsString> {
self.parsed_args_list.next_back()
}
}
impl ExactSizeIterator for Args {
fn len(&self) -> usize {
self.parsed_args_list.len()
}
}
#[derive(Debug)]
pub(crate) enum Arg {
/// Add quotes (if needed)
@ -384,9 +356,6 @@ pub(crate) fn to_user_path(path: &Path) -> io::Result<Vec<u16>> {
from_wide_to_user_path(to_u16s(path)?)
}
pub(crate) fn from_wide_to_user_path(mut path: Vec<u16>) -> io::Result<Vec<u16>> {
use super::fill_utf16_buf;
use crate::ptr;
// UTF-16 encoded code points, used in parsing and building UTF-16 paths.
// All of these are in the ASCII range so they can be cast directly to `u16`.
const SEP: u16 = b'\\' as _;

View File

@ -0,0 +1,23 @@
use crate::sys::pal::os::get_application_parameters;
use crate::sys::pal::os::params::ArgumentList;
#[path = "common.rs"]
mod common;
pub use common::Args;
pub fn args() -> Args {
let Some(params) = get_application_parameters() else {
return Args::new(vec![]);
};
for param in params {
if let Ok(args) = ArgumentList::try_from(&param) {
let mut parsed_args = vec![];
for arg in args {
parsed_args.push(arg.into());
}
return Args::new(parsed_args);
}
}
Args::new(vec![])
}

View File

@ -1,7 +1,7 @@
use super::{WORD_SIZE, abi};
use crate::ffi::OsString;
use crate::fmt;
use crate::sys::os_str;
use crate::sys::pal::{WORD_SIZE, abi};
use crate::sys_common::FromInner;
pub struct Args {

View File

@ -9,6 +9,7 @@ mod alloc;
mod personality;
pub mod anonymous_pipe;
pub mod args;
pub mod backtrace;
pub mod cmath;
pub mod exit_guard;

View File

@ -18,7 +18,6 @@
use crate::os::raw::c_char;
pub mod args;
pub mod env;
pub mod futex;
pub mod os;
@ -58,7 +57,7 @@ pub extern "C" fn __rust_abort() {
// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
pub unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) {
unsafe {
args::init(argc, argv);
crate::sys::args::init(argc, argv);
}
}

View File

@ -9,7 +9,6 @@ use crate::io::ErrorKind;
use crate::sync::atomic::{AtomicBool, Ordering};
pub mod abi;
pub mod args;
pub mod env;
mod libunwind_integration;
pub mod os;
@ -24,7 +23,7 @@ pub mod waitqueue;
// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
pub unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) {
unsafe {
args::init(argc, argv);
crate::sys::args::init(argc, argv);
}
}

View File

@ -16,8 +16,6 @@ pub mod itron {
use super::unsupported;
}
#[path = "../unsupported/args.rs"]
pub mod args;
pub mod env;
// `error` is `pub(crate)` so that it can be accessed by `itron/error.rs` as
// `crate::sys::error`

View File

@ -6,8 +6,6 @@
#![allow(unused_variables)]
#![allow(dead_code)]
#[path = "../unsupported/args.rs"]
pub mod args;
#[path = "../unsupported/env.rs"]
pub mod env;
//pub mod fd;

View File

@ -1,7 +1,5 @@
//! System bindings for the Trusty OS.
#[path = "../unsupported/args.rs"]
pub mod args;
#[path = "../unsupported/common.rs"]
#[deny(unsafe_op_in_unsafe_fn)]
mod common;

View File

@ -13,7 +13,6 @@
//! [`OsString`]: crate::ffi::OsString
#![forbid(unsafe_op_in_unsafe_fn)]
pub mod args;
pub mod env;
pub mod helpers;
pub mod os;

View File

@ -6,7 +6,6 @@ use crate::io::ErrorKind;
#[macro_use]
pub mod weak;
pub mod args;
pub mod env;
#[cfg(target_os = "fuchsia")]
pub mod fuchsia;
@ -27,6 +26,7 @@ pub mod time;
pub fn init(_argc: isize, _argv: *const *const u8, _sigpipe: u8) {}
#[cfg(not(target_os = "espidf"))]
#[cfg_attr(target_os = "vita", allow(unused_variables))]
// SAFETY: must be called only once during runtime initialization.
// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
// See `fn init()` in `library/std/src/rt.rs` for docs on `sigpipe`.
@ -47,7 +47,8 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
reset_sigpipe(sigpipe);
stack_overflow::init();
args::init(argc, argv);
#[cfg(not(target_os = "vita"))]
crate::sys::args::init(argc, argv);
// Normally, `thread::spawn` will call `Thread::set_name` but since this thread
// already exists, we have to call it ourselves. We only do this on Apple targets

View File

@ -1,6 +1,5 @@
#![deny(unsafe_op_in_unsafe_fn)]
pub mod args;
pub mod env;
pub mod os;
pub mod pipe;

View File

@ -1,61 +0,0 @@
#![forbid(unsafe_op_in_unsafe_fn)]
use crate::ffi::{CStr, OsStr, OsString};
use crate::os::wasi::ffi::OsStrExt;
use crate::{fmt, vec};
pub struct Args {
iter: vec::IntoIter<OsString>,
}
impl !Send for Args {}
impl !Sync for Args {}
/// Returns the command line arguments
pub fn args() -> Args {
Args { iter: maybe_args().unwrap_or(Vec::new()).into_iter() }
}
fn maybe_args() -> Option<Vec<OsString>> {
unsafe {
let (argc, buf_size) = wasi::args_sizes_get().ok()?;
let mut argv = Vec::with_capacity(argc);
let mut buf = Vec::with_capacity(buf_size);
wasi::args_get(argv.as_mut_ptr(), buf.as_mut_ptr()).ok()?;
argv.set_len(argc);
let mut ret = Vec::with_capacity(argc);
for ptr in argv {
let s = CStr::from_ptr(ptr.cast());
ret.push(OsStr::from_bytes(s.to_bytes()).to_owned());
}
Some(ret)
}
}
impl fmt::Debug for Args {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.iter.as_slice().fmt(f)
}
}
impl Iterator for Args {
type Item = OsString;
fn next(&mut self) -> Option<OsString> {
self.iter.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl ExactSizeIterator for Args {
fn len(&self) -> usize {
self.iter.len()
}
}
impl DoubleEndedIterator for Args {
fn next_back(&mut self) -> Option<OsString> {
self.iter.next_back()
}
}

View File

@ -13,7 +13,6 @@
//! compiling for wasm. That way it's a compile time error for something that's
//! guaranteed to be a runtime error!
pub mod args;
pub mod env;
#[allow(unused)]
#[path = "../wasm/atomics/futex.rs"]

View File

@ -6,8 +6,6 @@
//! To begin with, this target mirrors the wasi target 1 to 1, but over
//! time this will change significantly.
#[path = "../wasi/args.rs"]
pub mod args;
#[path = "../wasi/env.rs"]
pub mod env;
#[allow(unused)]

View File

@ -16,8 +16,6 @@
#![deny(unsafe_op_in_unsafe_fn)]
#[path = "../unsupported/args.rs"]
pub mod args;
pub mod env;
#[path = "../unsupported/os.rs"]
pub mod os;

View File

@ -14,7 +14,6 @@ pub mod compat;
pub mod api;
pub mod args;
pub mod c;
pub mod env;
#[cfg(not(target_vendor = "win7"))]

View File

@ -1,53 +0,0 @@
use crate::ffi::OsString;
use crate::sys::pal::xous::os::get_application_parameters;
use crate::sys::pal::xous::os::params::ArgumentList;
use crate::{fmt, vec};
pub struct Args {
parsed_args_list: vec::IntoIter<OsString>,
}
pub fn args() -> Args {
let Some(params) = get_application_parameters() else {
return Args { parsed_args_list: vec![].into_iter() };
};
for param in params {
if let Ok(args) = ArgumentList::try_from(&param) {
let mut parsed_args = vec![];
for arg in args {
parsed_args.push(arg.into());
}
return Args { parsed_args_list: parsed_args.into_iter() };
}
}
Args { parsed_args_list: vec![].into_iter() }
}
impl fmt::Debug for Args {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.parsed_args_list.as_slice().fmt(f)
}
}
impl Iterator for Args {
type Item = OsString;
fn next(&mut self) -> Option<OsString> {
self.parsed_args_list.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.parsed_args_list.size_hint()
}
}
impl DoubleEndedIterator for Args {
fn next_back(&mut self) -> Option<OsString> {
self.parsed_args_list.next_back()
}
}
impl ExactSizeIterator for Args {
fn len(&self) -> usize {
self.parsed_args_list.len()
}
}

View File

@ -1,6 +1,5 @@
#![forbid(unsafe_op_in_unsafe_fn)]
pub mod args;
#[path = "../unsupported/env.rs"]
pub mod env;
pub mod os;

View File

@ -8,11 +8,9 @@
//! will likely change over time.
#![forbid(unsafe_op_in_unsafe_fn)]
const WORD_SIZE: usize = size_of::<u32>();
pub const WORD_SIZE: usize = size_of::<u32>();
pub mod abi;
#[path = "../zkvm/args.rs"]
pub mod args;
pub mod env;
pub mod os;
#[path = "../unsupported/pipe.rs"]