Skip to content

Commit e8c1533

Browse files
authored
Merge branch 'uutils:main' into sort/sort-merge-fdlimit.sh
2 parents 0df862e + 6c5fae7 commit e8c1533

File tree

13 files changed

+165
-75
lines changed

13 files changed

+165
-75
lines changed

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -667,7 +667,6 @@ should_panic_without_expect = "allow" # 2
667667
doc_markdown = "allow"
668668
unused_self = "allow"
669669
enum_glob_use = "allow"
670-
needless_raw_string_hashes = "allow"
671670
unreadable_literal = "allow"
672671
unnested_or_patterns = "allow"
673672
implicit_hasher = "allow"

src/uu/env/src/env.rs

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,13 @@ use nix::sys::signal::{SigHandler::SigIgn, Signal, signal};
2424
use std::borrow::Cow;
2525
use std::env;
2626
use std::ffi::{OsStr, OsString};
27-
use std::io::{self, Write};
27+
use std::io;
2828
#[cfg(unix)]
2929
use std::os::unix::ffi::OsStrExt;
3030
#[cfg(unix)]
3131
use std::os::unix::process::CommandExt;
3232

33-
use uucore::display::{OsWrite, Quotable};
33+
use uucore::display::{Quotable, print_all_env_vars};
3434
use uucore::error::{ExitCode, UError, UResult, USimpleError, UUsageError};
3535
use uucore::line_ending::LineEnding;
3636
#[cfg(unix)]
@@ -99,19 +99,6 @@ struct Options<'a> {
9999
ignore_signal: Vec<usize>,
100100
}
101101

102-
/// print `name=value` env pairs on screen
103-
fn print_env(line_ending: LineEnding) -> io::Result<()> {
104-
let stdout_raw = io::stdout();
105-
let mut stdout = stdout_raw.lock();
106-
for (n, v) in env::vars_os() {
107-
stdout.write_all_os(&n)?;
108-
stdout.write_all(b"=")?;
109-
stdout.write_all_os(&v)?;
110-
write!(stdout, "{line_ending}")?;
111-
}
112-
Ok(())
113-
}
114-
115102
fn parse_name_value_opt<'a>(opts: &mut Options<'a>, opt: &'a OsStr) -> UResult<bool> {
116103
// is it a NAME=VALUE like opt ?
117104
let wrap = NativeStr::<'a>::new(opt);
@@ -552,7 +539,7 @@ impl EnvAppData {
552539

553540
if opts.program.is_empty() {
554541
// no program provided, so just dump all env vars to stdout
555-
print_env(opts.line_ending)?;
542+
print_all_env_vars(opts.line_ending)?;
556543
} else {
557544
return self.run_program(&opts, self.do_debug_printing);
558545
}

src/uu/printenv/src/printenv.rs

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ use std::io::Write;
88

99
use clap::{Arg, ArgAction, Command};
1010

11+
use uucore::display::{OsWrite, print_all_env_vars};
1112
use uucore::error::UResult;
1213
use uucore::line_ending::LineEnding;
13-
use uucore::{format_usage, os_str_as_bytes, translate};
14+
use uucore::{format_usage, translate};
1415

1516
static OPT_NULL: &str = "null";
1617

@@ -28,14 +29,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
2829
let separator = LineEnding::from_zero_flag(matches.get_flag(OPT_NULL));
2930

3031
if variables.is_empty() {
31-
for (env_var, value) in env::vars_os() {
32-
let env_bytes = os_str_as_bytes(&env_var)?;
33-
let val_bytes = os_str_as_bytes(&value)?;
34-
std::io::stdout().lock().write_all(env_bytes)?;
35-
print!("=");
36-
std::io::stdout().lock().write_all(val_bytes)?;
37-
print!("{separator}");
38-
}
32+
print_all_env_vars(separator)?;
3933
return Ok(());
4034
}
4135

@@ -47,9 +41,9 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
4741
continue;
4842
}
4943
if let Some(var) = env::var_os(env_var) {
50-
let val_bytes = os_str_as_bytes(&var)?;
51-
std::io::stdout().lock().write_all(val_bytes)?;
52-
print!("{separator}");
44+
let mut stdout = std::io::stdout().lock();
45+
stdout.write_all_os(&var)?;
46+
write!(stdout, "{separator}")?;
5347
} else {
5448
error_found = true;
5549
}

src/uu/runcon/src/runcon.rs

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@ use uucore::format_usage;
1515

1616
use std::borrow::Cow;
1717
use std::ffi::{CStr, CString, OsStr, OsString};
18-
use std::os::raw::c_char;
18+
use std::io;
1919
use std::os::unix::ffi::OsStrExt;
20-
use std::{io, ptr};
20+
use std::os::unix::process::CommandExt;
21+
use std::process;
2122

2223
mod errors;
2324

@@ -367,23 +368,8 @@ fn get_custom_context(
367368
/// compiler the only valid return type is to say "if this returns, it will
368369
/// always return an error".
369370
fn execute_command(command: &OsStr, arguments: &[OsString]) -> UResult<()> {
370-
let c_command = os_str_to_c_string(command).map_err(RunconError::new)?;
371+
let err = process::Command::new(command).args(arguments).exec();
371372

372-
let argv_storage: Vec<CString> = arguments
373-
.iter()
374-
.map(AsRef::as_ref)
375-
.map(os_str_to_c_string)
376-
.collect::<Result<_>>()
377-
.map_err(RunconError::new)?;
378-
379-
let mut argv: Vec<*const c_char> = Vec::with_capacity(arguments.len().saturating_add(2));
380-
argv.push(c_command.as_ptr());
381-
argv.extend(argv_storage.iter().map(AsRef::as_ref).map(CStr::as_ptr));
382-
argv.push(ptr::null());
383-
384-
unsafe { libc::execvp(c_command.as_ptr(), argv.as_ptr()) };
385-
386-
let err = io::Error::last_os_error();
387373
let exit_status = if err.kind() == io::ErrorKind::NotFound {
388374
error_exit_status::NOT_FOUND
389375
} else {

src/uucore/build.rs

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
5858
}
5959

6060
/// Get the project root directory
61+
///
62+
/// # Errors
63+
///
64+
/// Returns an error if the `CARGO_MANIFEST_DIR` environment variable is not set
65+
/// or if the current directory structure does not allow determining the project root.
6166
fn project_root() -> Result<std::path::PathBuf, Box<dyn std::error::Error>> {
6267
let manifest_dir = env::var("CARGO_MANIFEST_DIR")?;
6368
let uucore_path = std::path::Path::new(&manifest_dir);
@@ -120,6 +125,11 @@ fn detect_target_utility() -> Option<String> {
120125
}
121126

122127
/// Embed locale for a single specific utility
128+
///
129+
/// # Errors
130+
///
131+
/// Returns an error if the locales for `util_name` or `uucore` cannot be found
132+
/// or if writing to the `embedded_file` fails.
123133
fn embed_single_utility_locale(
124134
embedded_file: &mut std::fs::File,
125135
project_root: &Path,
@@ -142,7 +152,12 @@ fn embed_single_utility_locale(
142152
Ok(())
143153
}
144154

145-
/// Embed locale files for all utilities (multicall binary)
155+
/// Embed locale files for all utilities (multicall binary).
156+
///
157+
/// # Errors
158+
///
159+
/// Returns an error if the `src/uu` directory cannot be read, if any utility
160+
/// locales cannot be embedded, or if flushing the `embedded_file` fails.
146161
fn embed_all_utility_locales(
147162
embedded_file: &mut std::fs::File,
148163
project_root: &Path,
@@ -188,6 +203,12 @@ fn embed_all_utility_locales(
188203
Ok(())
189204
}
190205

206+
/// Embed static utility locales for crates.io builds.
207+
///
208+
/// # Errors
209+
///
210+
/// Returns an error if the directory containing the crate cannot be read or
211+
/// if writing to the `embedded_file` fails.
191212
fn embed_static_utility_locales(
192213
embedded_file: &mut std::fs::File,
193214
locales_to_embed: &(String, Option<String>),
@@ -213,7 +234,7 @@ fn embed_static_utility_locales(
213234
let mut entries: Vec<_> = std::fs::read_dir(registry_dir)?
214235
.filter_map(Result::ok)
215236
.collect();
216-
entries.sort_by_key(|e| e.file_name());
237+
entries.sort_by_key(std::fs::DirEntry::file_name);
217238

218239
for entry in entries {
219240
let file_name = entry.file_name();
@@ -256,6 +277,11 @@ fn get_locales_to_embed() -> (String, Option<String>) {
256277
}
257278

258279
/// Helper function to iterate over the locales to embed.
280+
///
281+
/// # Errors
282+
///
283+
/// Returns an error if the provided closure `f` returns an error when called
284+
/// on either the primary or system locale.
259285
fn for_each_locale<F>(
260286
locales: &(String, Option<String>),
261287
mut f: F,
@@ -271,6 +297,11 @@ where
271297
}
272298

273299
/// Helper function to embed a single locale file.
300+
///
301+
/// # Errors
302+
///
303+
/// Returns an error if the file at `locale_path` cannot be read or if
304+
/// writing to `embedded_file` fails.
274305
fn embed_locale_file(
275306
embedded_file: &mut std::fs::File,
276307
locale_path: &Path,
@@ -286,9 +317,11 @@ fn embed_locale_file(
286317
embedded_file,
287318
" // Locale for {component} ({locale})"
288319
)?;
320+
// Determine if we need a hash. If content contains ", we need r#""#
321+
let delimiter = if content.contains('"') { "#" } else { "" };
289322
writeln!(
290323
embedded_file,
291-
" \"{locale_key}\" => Some(r###\"{content}\"###),"
324+
" \"{locale_key}\" => Some(r{delimiter}\"{content}\"{delimiter}),"
292325
)?;
293326

294327
// Tell Cargo to rerun if this file changes
@@ -298,7 +331,13 @@ fn embed_locale_file(
298331
}
299332

300333
/// Higher-level helper to embed locale files for a component with a path pattern.
301-
/// This eliminates the repetitive for_each_locale + embed_locale_file pattern.
334+
///
335+
/// This eliminates the repetitive `for_each_locale` + `embed_locale_file` pattern.
336+
///
337+
/// # Errors
338+
///
339+
/// Returns an error if `for_each_locale` fails, which typically happens if
340+
/// reading a locale file or writing to the `embedded_file` fails.
302341
fn embed_component_locales<F>(
303342
embedded_file: &mut std::fs::File,
304343
locales: &(String, Option<String>),

src/uucore/src/lib/features/fsext.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -201,9 +201,9 @@ fn replace_special_chars(s: &[u8]) -> Vec<u8> {
201201
// * \011 ASCII horizontal tab with a tab character,
202202
// * ASCII backslash with an actual backslash character.
203203
//
204-
s.replace(r#"\040"#, " ")
205-
.replace(r#"\011"#, " ")
206-
.replace(r#"\134"#, r#"\"#)
204+
s.replace(r"\040", " ")
205+
.replace(r"\011", " ")
206+
.replace(r"\134", r"\")
207207
}
208208

209209
impl MountInfo {
@@ -1171,23 +1171,23 @@ mod tests {
11711171
fn test_mountinfo_dir_special_chars() {
11721172
let info = MountInfo::new(
11731173
LINUX_MOUNTINFO,
1174-
&br#"317 61 7:0 / /mnt/f\134\040\011oo rw,relatime shared:641 - ext4 /dev/loop0 rw"#
1174+
&br"317 61 7:0 / /mnt/f\134\040\011oo rw,relatime shared:641 - ext4 /dev/loop0 rw"
11751175
.split(|c| *c == b' ')
11761176
.collect::<Vec<_>>(),
11771177
)
11781178
.unwrap();
11791179

1180-
assert_eq!(info.mount_dir, r#"/mnt/f\ oo"#);
1180+
assert_eq!(info.mount_dir, r"/mnt/f\ oo");
11811181

11821182
let info = MountInfo::new(
11831183
LINUX_MTAB,
1184-
&br#"/dev/loop0 /mnt/f\134\040\011oo ext4 rw,relatime 0 0"#
1184+
&br"/dev/loop0 /mnt/f\134\040\011oo ext4 rw,relatime 0 0"
11851185
.split(|c| *c == b' ')
11861186
.collect::<Vec<_>>(),
11871187
)
11881188
.unwrap();
11891189

1190-
assert_eq!(info.mount_dir, r#"/mnt/f\ oo"#);
1190+
assert_eq!(info.mount_dir, r"/mnt/f\ oo");
11911191
}
11921192

11931193
#[test]

src/uucore/src/lib/mods/display.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@
2424
//! # Ok::<(), std::io::Error>(())
2525
//! ```
2626
27+
use std::env;
2728
use std::ffi::OsStr;
29+
use std::fmt;
2830
use std::fs::File;
2931
use std::io::{self, BufWriter, Stdout, StdoutLock, Write as IoWrite};
3032

@@ -117,3 +119,18 @@ impl OsWrite for Box<dyn OsWrite> {
117119
this.write_all_os(buf)
118120
}
119121
}
122+
123+
/// Print all environment variables in the format `name=value` with the specified line ending.
124+
///
125+
/// This function handles non-UTF-8 environment variable names and values correctly by using
126+
/// raw bytes on Unix systems.
127+
pub fn print_all_env_vars<T: fmt::Display>(line_ending: T) -> io::Result<()> {
128+
let mut stdout = io::stdout().lock();
129+
for (name, value) in env::vars_os() {
130+
stdout.write_all_os(&name)?;
131+
stdout.write_all(b"=")?;
132+
stdout.write_all_os(&value)?;
133+
write!(stdout, "{line_ending}")?;
134+
}
135+
Ok(())
136+
}

src/uucore/src/lib/mods/locale.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -617,35 +617,35 @@ mod tests {
617617
let temp_dir = TempDir::new().expect("Failed to create temp directory");
618618

619619
// Create en-US.ftl
620-
let en_content = r#"
620+
let en_content = r"
621621
greeting = Hello, world!
622622
welcome = Welcome, { $name }!
623623
count-items = You have { $count ->
624624
[one] { $count } item
625625
*[other] { $count } items
626626
}
627627
missing-in-other = This message only exists in English
628-
"#;
628+
";
629629

630630
// Create fr-FR.ftl
631-
let fr_content = r#"
631+
let fr_content = r"
632632
greeting = Bonjour, le monde!
633633
welcome = Bienvenue, { $name }!
634634
count-items = Vous avez { $count ->
635635
[one] { $count } élément
636636
*[other] { $count } éléments
637637
}
638-
"#;
638+
";
639639

640640
// Create ja-JP.ftl (Japanese)
641-
let ja_content = r#"
641+
let ja_content = r"
642642
greeting = こんにちは、世界!
643643
welcome = ようこそ、{ $name }さん!
644644
count-items = { $count }個のアイテムがあります
645-
"#;
645+
";
646646

647647
// Create ar-SA.ftl (Arabic - Right-to-Left)
648-
let ar_content = r#"
648+
let ar_content = r"
649649
greeting = أهلاً بالعالم!
650650
welcome = أهلاً وسهلاً، { $name }!
651651
count-items = لديك { $count ->
@@ -655,13 +655,13 @@ count-items = لديك { $count ->
655655
[few] { $count } عناصر
656656
*[other] { $count } عنصر
657657
}
658-
"#;
658+
";
659659

660660
// Create es-ES.ftl with invalid syntax
661-
let es_invalid_content = r#"
661+
let es_invalid_content = r"
662662
greeting = Hola, mundo!
663663
invalid-syntax = This is { $missing
664-
"#;
664+
";
665665

666666
fs::write(temp_dir.path().join("en-US.ftl"), en_content)
667667
.expect("Failed to write en-US.ftl");

0 commit comments

Comments
 (0)