Skip to content

Move args into std::sys #139710

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions library/std/src/sys/args/common.rs
Original file line number Diff line number Diff line change
@@ -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()
}
}
Original file line number Diff line number Diff line change
@@ -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());
Expand All @@ -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)
}
34 changes: 34 additions & 0 deletions library/std/src/sys/args/mod.rs
Original file line number Diff line number Diff line change
@@ -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::*;
}
}
Original file line number Diff line number Diff line change
@@ -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};

Expand Down
Original file line number Diff line number Diff line change
@@ -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()]);
Expand All @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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.
Expand All @@ -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
};
Expand Down Expand Up @@ -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())
}
}
29 changes: 29 additions & 0 deletions library/std/src/sys/args/wasi.rs
Original file line number Diff line number Diff line change
@@ -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)
}
}
Loading
Loading