Skip to content

Commit

Permalink
printf: support for invalid utf-8 page
Browse files Browse the repository at this point in the history
  • Loading branch information
sylvestre committed Jan 1, 2025
1 parent 5985dd7 commit f763ff7
Showing 1 changed file with 46 additions and 7 deletions.
53 changes: 46 additions & 7 deletions src/uu/printf/src/printf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
use clap::{crate_version, Arg, ArgAction, Command};
use std::io::stdout;
use std::ops::ControlFlow;
#[cfg(unix)]
use std::os::unix::ffi::{OsStrExt, OsStringExt};
#[cfg(windows)]
use std::os::windows::ffi::OsStrExt;
use uucore::error::{UResult, UUsageError};
use uucore::format::{parse_spec_and_escape, FormatArgument, FormatItem};
use uucore::{format_usage, help_about, help_section, help_usage};
Expand All @@ -20,23 +24,54 @@ mod options {
pub const FORMAT: &str = "FORMAT";
pub const ARGUMENT: &str = "ARGUMENT";
}

#[uucore::main]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let matches = uu_app().get_matches_from(args);

let format = matches
.get_one::<String>(options::FORMAT)
.get_one::<std::ffi::OsString>(options::FORMAT)
.ok_or_else(|| UUsageError::new(1, "missing operand"))?;

#[cfg(unix)]
let format = format.as_bytes();

#[cfg(windows)]
let format_vec: Vec<u8> = format
.encode_wide()
.flat_map(|wchar| wchar.to_le_bytes())
.collect();
#[cfg(windows)]
let format = format_vec.as_slice();

let values: Vec<_> = match matches.get_many::<std::ffi::OsString>(options::ARGUMENT) {
Some(s) => s
.map(|os_str| {
#[cfg(unix)]
let raw_bytes: Vec<u8> = os_str.clone().into_vec();

#[cfg(windows)]
let raw_bytes: Vec<u8> = os_str
.encode_wide()
.flat_map(|wchar| wchar.to_le_bytes())
.collect();
FormatArgument::Unparsed(
String::from_utf8(raw_bytes.clone())
.unwrap_or_else(|_| raw_bytes.iter().map(|&b| b as char).collect()),
)
})
.collect(),
None => vec![],
};
#[cfg(windows)]
let values: Vec<_> = match matches.get_many::<String>(options::ARGUMENT) {
Some(s) => s.map(|s| FormatArgument::Unparsed(s.to_string())).collect(),
None => vec![],
};

let mut format_seen = false;
let mut args = values.iter().peekable();
for item in parse_spec_and_escape(format.as_ref()) {

// Parse and process the format string
for item in parse_spec_and_escape(format) {
if let Ok(FormatItem::Spec(_)) = item {
format_seen = true;
}
Expand All @@ -53,7 +88,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
}

while args.peek().is_some() {
for item in parse_spec_and_escape(format.as_ref()) {
for item in parse_spec_and_escape(format) {
match item?.write(stdout(), &mut args)? {
ControlFlow::Continue(()) => {}
ControlFlow::Break(()) => return Ok(()),
Expand Down Expand Up @@ -84,6 +119,10 @@ pub fn uu_app() -> Command {
.help("Print version information")
.action(ArgAction::Version),
)
.arg(Arg::new(options::FORMAT))
.arg(Arg::new(options::ARGUMENT).action(ArgAction::Append))
.arg(Arg::new(options::FORMAT).value_parser(clap::value_parser!(std::ffi::OsString)))
.arg(
Arg::new(options::ARGUMENT)
.action(ArgAction::Append)
.value_parser(clap::value_parser!(std::ffi::OsString)),
)
}

0 comments on commit f763ff7

Please sign in to comment.