mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 03:27:44 +00:00
Merge pull request #7715 from nyurik/unused_qualifications
Enable and fix `unused_qualifications` lint
This commit is contained in:
commit
5bfbc30fba
45 changed files with 218 additions and 242 deletions
|
@ -594,7 +594,7 @@ pedantic = { level = "deny", priority = -1 }
|
||||||
# Eventually the clippy settings from the `[lints]` section should be moved here.
|
# Eventually the clippy settings from the `[lints]` section should be moved here.
|
||||||
# In order to use these, all crates have `[lints] workspace = true` section.
|
# In order to use these, all crates have `[lints] workspace = true` section.
|
||||||
[workspace.lints.rust]
|
[workspace.lints.rust]
|
||||||
# unused_qualifications = "warn"
|
unused_qualifications = "warn"
|
||||||
|
|
||||||
[workspace.lints.clippy]
|
[workspace.lints.clippy]
|
||||||
all = { level = "deny", priority = -1 }
|
all = { level = "deny", priority = -1 }
|
||||||
|
|
|
@ -139,7 +139,7 @@ pub fn base_app(about: &'static str, usage: &str) -> Command {
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new(options::FILE)
|
Arg::new(options::FILE)
|
||||||
.index(1)
|
.index(1)
|
||||||
.action(clap::ArgAction::Append)
|
.action(ArgAction::Append)
|
||||||
.value_hint(clap::ValueHint::FilePath),
|
.value_hint(clap::ValueHint::FilePath),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,7 +90,7 @@ pub fn uu_app() -> Command {
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new(options::NAME)
|
Arg::new(options::NAME)
|
||||||
.action(clap::ArgAction::Append)
|
.action(ArgAction::Append)
|
||||||
.value_hint(clap::ValueHint::AnyPath)
|
.value_hint(clap::ValueHint::AnyPath)
|
||||||
.hide(true)
|
.hide(true)
|
||||||
.trailing_var_arg(true),
|
.trailing_var_arg(true),
|
||||||
|
|
|
@ -86,7 +86,7 @@ impl LineNumber {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write(&self, writer: &mut impl Write) -> std::io::Result<()> {
|
fn write(&self, writer: &mut impl Write) -> io::Result<()> {
|
||||||
writer.write_all(&self.buf)
|
writer.write_all(&self.buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -288,7 +288,7 @@ pub fn uu_app() -> Command {
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new(options::FILE)
|
Arg::new(options::FILE)
|
||||||
.hide(true)
|
.hide(true)
|
||||||
.action(clap::ArgAction::Append)
|
.action(ArgAction::Append)
|
||||||
.value_hint(clap::ValueHint::FilePath),
|
.value_hint(clap::ValueHint::FilePath),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
|
@ -377,7 +377,7 @@ fn cat_handle<R: FdReadable>(
|
||||||
/// Whether this process is appending to stdout.
|
/// Whether this process is appending to stdout.
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
fn is_appending() -> bool {
|
fn is_appending() -> bool {
|
||||||
let stdout = std::io::stdout();
|
let stdout = io::stdout();
|
||||||
let flags = match fcntl(stdout.as_raw_fd(), FcntlArg::F_GETFL) {
|
let flags = match fcntl(stdout.as_raw_fd(), FcntlArg::F_GETFL) {
|
||||||
Ok(flags) => flags,
|
Ok(flags) => flags,
|
||||||
Err(_) => return false,
|
Err(_) => return false,
|
||||||
|
@ -404,7 +404,7 @@ fn cat_path(
|
||||||
let in_info = FileInformation::from_file(&stdin)?;
|
let in_info = FileInformation::from_file(&stdin)?;
|
||||||
let mut handle = InputHandle {
|
let mut handle = InputHandle {
|
||||||
reader: stdin,
|
reader: stdin,
|
||||||
is_interactive: std::io::stdin().is_terminal(),
|
is_interactive: io::stdin().is_terminal(),
|
||||||
};
|
};
|
||||||
if let Some(out_info) = out_info {
|
if let Some(out_info) = out_info {
|
||||||
if in_info == *out_info && is_appending() {
|
if in_info == *out_info && is_appending() {
|
||||||
|
@ -445,7 +445,7 @@ fn cat_path(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cat_files(files: &[String], options: &OutputOptions) -> UResult<()> {
|
fn cat_files(files: &[String], options: &OutputOptions) -> UResult<()> {
|
||||||
let out_info = FileInformation::from_file(&std::io::stdout()).ok();
|
let out_info = FileInformation::from_file(&io::stdout()).ok();
|
||||||
|
|
||||||
let mut state = OutputState {
|
let mut state = OutputState {
|
||||||
line_number: LineNumber::new(),
|
line_number: LineNumber::new(),
|
||||||
|
|
|
@ -312,7 +312,7 @@ struct Options {
|
||||||
files: Vec<PathBuf>,
|
files: Vec<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_command_line(config: clap::Command, args: impl uucore::Args) -> Result<Options> {
|
fn parse_command_line(config: Command, args: impl uucore::Args) -> Result<Options> {
|
||||||
let matches = config.try_get_matches_from(args)?;
|
let matches = config.try_get_matches_from(args)?;
|
||||||
|
|
||||||
let verbose = matches.get_flag(options::VERBOSE);
|
let verbose = matches.get_flag(options::VERBOSE);
|
||||||
|
|
|
@ -8,7 +8,6 @@ use std::ffi::{CStr, CString, OsStr};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::os::raw::{c_int, c_long, c_short};
|
use std::os::raw::{c_int, c_long, c_short};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::ptr::NonNull;
|
|
||||||
use std::{io, iter, ptr, slice};
|
use std::{io, iter, ptr, slice};
|
||||||
|
|
||||||
use crate::errors::{Error, Result};
|
use crate::errors::{Error, Result};
|
||||||
|
@ -71,7 +70,7 @@ impl FTS {
|
||||||
// pointer assumed to be valid.
|
// pointer assumed to be valid.
|
||||||
let new_entry = unsafe { fts_sys::fts_read(self.fts.as_ptr()) };
|
let new_entry = unsafe { fts_sys::fts_read(self.fts.as_ptr()) };
|
||||||
|
|
||||||
self.entry = NonNull::new(new_entry);
|
self.entry = ptr::NonNull::new(new_entry);
|
||||||
if self.entry.is_none() {
|
if self.entry.is_none() {
|
||||||
let r = io::Error::last_os_error();
|
let r = io::Error::last_os_error();
|
||||||
if let Some(0) = r.raw_os_error() {
|
if let Some(0) = r.raw_os_error() {
|
||||||
|
@ -161,7 +160,7 @@ impl<'fts> EntryRef<'fts> {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
NonNull::new(entry.fts_path)
|
ptr::NonNull::new(entry.fts_path)
|
||||||
.map(|path_ptr| {
|
.map(|path_ptr| {
|
||||||
let path_size = usize::from(entry.fts_pathlen).saturating_add(1);
|
let path_size = usize::from(entry.fts_pathlen).saturating_add(1);
|
||||||
|
|
||||||
|
|
|
@ -350,7 +350,7 @@ pub fn uu_app() -> Command {
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new(options::FILE)
|
Arg::new(options::FILE)
|
||||||
.hide(true)
|
.hide(true)
|
||||||
.action(clap::ArgAction::Append)
|
.action(ArgAction::Append)
|
||||||
.value_parser(ValueParser::os_string())
|
.value_parser(ValueParser::os_string())
|
||||||
.value_hint(clap::ValueHint::FilePath),
|
.value_hint(clap::ValueHint::FilePath),
|
||||||
)
|
)
|
||||||
|
|
|
@ -118,8 +118,8 @@ impl OrderChecker {
|
||||||
// Check if two files are identical by comparing their contents
|
// Check if two files are identical by comparing their contents
|
||||||
pub fn are_files_identical(path1: &str, path2: &str) -> io::Result<bool> {
|
pub fn are_files_identical(path1: &str, path2: &str) -> io::Result<bool> {
|
||||||
// First compare file sizes
|
// First compare file sizes
|
||||||
let metadata1 = std::fs::metadata(path1)?;
|
let metadata1 = metadata(path1)?;
|
||||||
let metadata2 = std::fs::metadata(path2)?;
|
let metadata2 = metadata(path2)?;
|
||||||
|
|
||||||
if metadata1.len() != metadata2.len() {
|
if metadata1.len() != metadata2.len() {
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
|
|
|
@ -101,7 +101,7 @@ struct Context<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Context<'a> {
|
impl<'a> Context<'a> {
|
||||||
fn new(root: &'a Path, target: &'a Path) -> std::io::Result<Self> {
|
fn new(root: &'a Path, target: &'a Path) -> io::Result<Self> {
|
||||||
let current_dir = env::current_dir()?;
|
let current_dir = env::current_dir()?;
|
||||||
let root_path = current_dir.join(root);
|
let root_path = current_dir.join(root);
|
||||||
let root_parent = if target.exists() && !root.to_str().unwrap().ends_with("/.") {
|
let root_parent = if target.exists() && !root.to_str().unwrap().ends_with("/.") {
|
||||||
|
@ -181,7 +181,7 @@ impl Entry {
|
||||||
if no_target_dir {
|
if no_target_dir {
|
||||||
let source_is_dir = source.is_dir();
|
let source_is_dir = source.is_dir();
|
||||||
if path_ends_with_terminator(context.target) && source_is_dir {
|
if path_ends_with_terminator(context.target) && source_is_dir {
|
||||||
if let Err(e) = std::fs::create_dir_all(context.target) {
|
if let Err(e) = fs::create_dir_all(context.target) {
|
||||||
eprintln!("Failed to create directory: {e}");
|
eprintln!("Failed to create directory: {e}");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -305,9 +305,7 @@ fn copy_direntry(
|
||||||
false,
|
false,
|
||||||
) {
|
) {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(Error::IoErrContext(e, _))
|
Err(Error::IoErrContext(e, _)) if e.kind() == io::ErrorKind::PermissionDenied => {
|
||||||
if e.kind() == std::io::ErrorKind::PermissionDenied =>
|
|
||||||
{
|
|
||||||
show!(uio_error!(
|
show!(uio_error!(
|
||||||
e,
|
e,
|
||||||
"cannot open {} for reading",
|
"cannot open {} for reading",
|
||||||
|
@ -580,14 +578,13 @@ fn build_dir(
|
||||||
// we need to allow trivial casts here because some systems like linux have u32 constants in
|
// we need to allow trivial casts here because some systems like linux have u32 constants in
|
||||||
// in libc while others don't.
|
// in libc while others don't.
|
||||||
#[allow(clippy::unnecessary_cast)]
|
#[allow(clippy::unnecessary_cast)]
|
||||||
let mut excluded_perms =
|
let mut excluded_perms = if matches!(options.attributes.ownership, Preserve::Yes { .. }) {
|
||||||
if matches!(options.attributes.ownership, crate::Preserve::Yes { .. }) {
|
libc::S_IRWXG | libc::S_IRWXO // exclude rwx for group and other
|
||||||
libc::S_IRWXG | libc::S_IRWXO // exclude rwx for group and other
|
} else if matches!(options.attributes.mode, Preserve::Yes { .. }) {
|
||||||
} else if matches!(options.attributes.mode, crate::Preserve::Yes { .. }) {
|
libc::S_IWGRP | libc::S_IWOTH //exclude w for group and other
|
||||||
libc::S_IWGRP | libc::S_IWOTH //exclude w for group and other
|
} else {
|
||||||
} else {
|
0
|
||||||
0
|
} as u32;
|
||||||
} as u32;
|
|
||||||
|
|
||||||
let umask = if copy_attributes_from.is_some()
|
let umask = if copy_attributes_from.is_some()
|
||||||
&& matches!(options.attributes.mode, Preserve::Yes { .. })
|
&& matches!(options.attributes.mode, Preserve::Yes { .. })
|
||||||
|
|
|
@ -737,7 +737,7 @@ pub fn uu_app() -> Command {
|
||||||
Arg::new(options::PROGRESS_BAR)
|
Arg::new(options::PROGRESS_BAR)
|
||||||
.long(options::PROGRESS_BAR)
|
.long(options::PROGRESS_BAR)
|
||||||
.short('g')
|
.short('g')
|
||||||
.action(clap::ArgAction::SetTrue)
|
.action(ArgAction::SetTrue)
|
||||||
.help(
|
.help(
|
||||||
"Display a progress bar. \n\
|
"Display a progress bar. \n\
|
||||||
Note: this feature is not supported by GNU coreutils.",
|
Note: this feature is not supported by GNU coreutils.",
|
||||||
|
@ -2081,7 +2081,7 @@ fn handle_copy_mode(
|
||||||
CopyMode::Update => {
|
CopyMode::Update => {
|
||||||
if dest.exists() {
|
if dest.exists() {
|
||||||
match options.update {
|
match options.update {
|
||||||
update_control::UpdateMode::ReplaceAll => {
|
UpdateMode::ReplaceAll => {
|
||||||
copy_helper(
|
copy_helper(
|
||||||
source,
|
source,
|
||||||
dest,
|
dest,
|
||||||
|
@ -2094,17 +2094,17 @@ fn handle_copy_mode(
|
||||||
source_is_stream,
|
source_is_stream,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
update_control::UpdateMode::ReplaceNone => {
|
UpdateMode::ReplaceNone => {
|
||||||
if options.debug {
|
if options.debug {
|
||||||
println!("skipped {}", dest.quote());
|
println!("skipped {}", dest.quote());
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(PerformedAction::Skipped);
|
return Ok(PerformedAction::Skipped);
|
||||||
}
|
}
|
||||||
update_control::UpdateMode::ReplaceNoneFail => {
|
UpdateMode::ReplaceNoneFail => {
|
||||||
return Err(Error::Error(format!("not replacing '{}'", dest.display())));
|
return Err(Error::Error(format!("not replacing '{}'", dest.display())));
|
||||||
}
|
}
|
||||||
update_control::UpdateMode::ReplaceIfOlder => {
|
UpdateMode::ReplaceIfOlder => {
|
||||||
let dest_metadata = fs::symlink_metadata(dest)?;
|
let dest_metadata = fs::symlink_metadata(dest)?;
|
||||||
|
|
||||||
let src_time = source_metadata.modified()?;
|
let src_time = source_metadata.modified()?;
|
||||||
|
@ -2335,7 +2335,7 @@ fn copy_file(
|
||||||
&FileInformation::from_path(source, options.dereference(source_in_command_line))
|
&FileInformation::from_path(source, options.dereference(source_in_command_line))
|
||||||
.context(format!("cannot stat {}", source.quote()))?,
|
.context(format!("cannot stat {}", source.quote()))?,
|
||||||
) {
|
) {
|
||||||
std::fs::hard_link(new_source, dest)?;
|
fs::hard_link(new_source, dest)?;
|
||||||
|
|
||||||
if options.verbose {
|
if options.verbose {
|
||||||
print_verbose_output(options.parents, progress_bar, source, dest);
|
print_verbose_output(options.parents, progress_bar, source, dest);
|
||||||
|
|
|
@ -43,7 +43,7 @@ mod options {
|
||||||
|
|
||||||
/// Command line options for csplit.
|
/// Command line options for csplit.
|
||||||
pub struct CsplitOptions {
|
pub struct CsplitOptions {
|
||||||
split_name: crate::SplitName,
|
split_name: SplitName,
|
||||||
keep_files: bool,
|
keep_files: bool,
|
||||||
quiet: bool,
|
quiet: bool,
|
||||||
elide_empty_files: bool,
|
elide_empty_files: bool,
|
||||||
|
@ -661,7 +661,7 @@ pub fn uu_app() -> Command {
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new(options::PATTERN)
|
Arg::new(options::PATTERN)
|
||||||
.hide(true)
|
.hide(true)
|
||||||
.action(clap::ArgAction::Append)
|
.action(ArgAction::Append)
|
||||||
.required(true),
|
.required(true),
|
||||||
)
|
)
|
||||||
.after_help(AFTER_HELP)
|
.after_help(AFTER_HELP)
|
||||||
|
|
|
@ -352,7 +352,7 @@ fn cut_files(mut filenames: Vec<String>, mode: &Mode) {
|
||||||
filenames.push("-".to_owned());
|
filenames.push("-".to_owned());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut out: Box<dyn Write> = if std::io::stdout().is_terminal() {
|
let mut out: Box<dyn Write> = if stdout().is_terminal() {
|
||||||
Box::new(stdout())
|
Box::new(stdout())
|
||||||
} else {
|
} else {
|
||||||
Box::new(BufWriter::new(stdout())) as Box<dyn Write>
|
Box::new(BufWriter::new(stdout())) as Box<dyn Write>
|
||||||
|
|
|
@ -222,7 +222,7 @@ impl Source {
|
||||||
/// The length of the data source in number of bytes.
|
/// The length of the data source in number of bytes.
|
||||||
///
|
///
|
||||||
/// If it cannot be determined, then this function returns 0.
|
/// If it cannot be determined, then this function returns 0.
|
||||||
fn len(&self) -> std::io::Result<i64> {
|
fn len(&self) -> io::Result<i64> {
|
||||||
match self {
|
match self {
|
||||||
Self::File(f) => Ok(f.metadata()?.len().try_into().unwrap_or(i64::MAX)),
|
Self::File(f) => Ok(f.metadata()?.len().try_into().unwrap_or(i64::MAX)),
|
||||||
_ => Ok(0),
|
_ => Ok(0),
|
||||||
|
@ -260,7 +260,7 @@ impl Source {
|
||||||
Err(e) => Err(e),
|
Err(e) => Err(e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Self::File(f) => f.seek(io::SeekFrom::Current(n.try_into().unwrap())),
|
Self::File(f) => f.seek(SeekFrom::Current(n.try_into().unwrap())),
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
Self::Fifo(f) => io::copy(&mut f.take(n), &mut io::sink()),
|
Self::Fifo(f) => io::copy(&mut f.take(n), &mut io::sink()),
|
||||||
}
|
}
|
||||||
|
@ -470,7 +470,7 @@ impl Input<'_> {
|
||||||
/// Fills a given buffer.
|
/// Fills a given buffer.
|
||||||
/// Reads in increments of 'self.ibs'.
|
/// Reads in increments of 'self.ibs'.
|
||||||
/// The start of each ibs-sized read follows the previous one.
|
/// The start of each ibs-sized read follows the previous one.
|
||||||
fn fill_consecutive(&mut self, buf: &mut Vec<u8>) -> std::io::Result<ReadStat> {
|
fn fill_consecutive(&mut self, buf: &mut Vec<u8>) -> io::Result<ReadStat> {
|
||||||
let mut reads_complete = 0;
|
let mut reads_complete = 0;
|
||||||
let mut reads_partial = 0;
|
let mut reads_partial = 0;
|
||||||
let mut bytes_total = 0;
|
let mut bytes_total = 0;
|
||||||
|
@ -501,7 +501,7 @@ impl Input<'_> {
|
||||||
/// Fills a given buffer.
|
/// Fills a given buffer.
|
||||||
/// Reads in increments of 'self.ibs'.
|
/// Reads in increments of 'self.ibs'.
|
||||||
/// The start of each ibs-sized read is aligned to multiples of ibs; remaining space is filled with the 'pad' byte.
|
/// The start of each ibs-sized read is aligned to multiples of ibs; remaining space is filled with the 'pad' byte.
|
||||||
fn fill_blocks(&mut self, buf: &mut Vec<u8>, pad: u8) -> std::io::Result<ReadStat> {
|
fn fill_blocks(&mut self, buf: &mut Vec<u8>, pad: u8) -> io::Result<ReadStat> {
|
||||||
let mut reads_complete = 0;
|
let mut reads_complete = 0;
|
||||||
let mut reads_partial = 0;
|
let mut reads_partial = 0;
|
||||||
let mut base_idx = 0;
|
let mut base_idx = 0;
|
||||||
|
@ -612,7 +612,7 @@ impl Dest {
|
||||||
return Ok(len);
|
return Ok(len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
f.seek(io::SeekFrom::Current(n.try_into().unwrap()))
|
f.seek(SeekFrom::Current(n.try_into().unwrap()))
|
||||||
}
|
}
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
Self::Fifo(f) => {
|
Self::Fifo(f) => {
|
||||||
|
@ -655,7 +655,7 @@ impl Dest {
|
||||||
/// The length of the data destination in number of bytes.
|
/// The length of the data destination in number of bytes.
|
||||||
///
|
///
|
||||||
/// If it cannot be determined, then this function returns 0.
|
/// If it cannot be determined, then this function returns 0.
|
||||||
fn len(&self) -> std::io::Result<i64> {
|
fn len(&self) -> io::Result<i64> {
|
||||||
match self {
|
match self {
|
||||||
Self::File(f, _) => Ok(f.metadata()?.len().try_into().unwrap_or(i64::MAX)),
|
Self::File(f, _) => Ok(f.metadata()?.len().try_into().unwrap_or(i64::MAX)),
|
||||||
_ => Ok(0),
|
_ => Ok(0),
|
||||||
|
@ -676,7 +676,7 @@ impl Write for Dest {
|
||||||
.len()
|
.len()
|
||||||
.try_into()
|
.try_into()
|
||||||
.expect("Internal dd Error: Seek amount greater than signed 64-bit integer");
|
.expect("Internal dd Error: Seek amount greater than signed 64-bit integer");
|
||||||
f.seek(io::SeekFrom::Current(seek_amt))?;
|
f.seek(SeekFrom::Current(seek_amt))?;
|
||||||
Ok(buf.len())
|
Ok(buf.len())
|
||||||
}
|
}
|
||||||
Self::File(f, _) => f.write(buf),
|
Self::File(f, _) => f.write(buf),
|
||||||
|
@ -893,7 +893,7 @@ impl<'a> Output<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Flush the output to disk, if configured to do so.
|
/// Flush the output to disk, if configured to do so.
|
||||||
fn sync(&mut self) -> std::io::Result<()> {
|
fn sync(&mut self) -> io::Result<()> {
|
||||||
if self.settings.oconv.fsync {
|
if self.settings.oconv.fsync {
|
||||||
self.dst.fsync()
|
self.dst.fsync()
|
||||||
} else if self.settings.oconv.fdatasync {
|
} else if self.settings.oconv.fdatasync {
|
||||||
|
@ -905,7 +905,7 @@ impl<'a> Output<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Truncate the underlying file to the current stream position, if possible.
|
/// Truncate the underlying file to the current stream position, if possible.
|
||||||
fn truncate(&mut self) -> std::io::Result<()> {
|
fn truncate(&mut self) -> io::Result<()> {
|
||||||
self.dst.truncate()
|
self.dst.truncate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -959,7 +959,7 @@ impl BlockWriter<'_> {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_blocks(&mut self, buf: &[u8]) -> std::io::Result<WriteStat> {
|
fn write_blocks(&mut self, buf: &[u8]) -> io::Result<WriteStat> {
|
||||||
match self {
|
match self {
|
||||||
Self::Unbuffered(o) => o.write_blocks(buf),
|
Self::Unbuffered(o) => o.write_blocks(buf),
|
||||||
Self::Buffered(o) => o.write_blocks(buf),
|
Self::Buffered(o) => o.write_blocks(buf),
|
||||||
|
@ -969,7 +969,7 @@ impl BlockWriter<'_> {
|
||||||
|
|
||||||
/// depending on the command line arguments, this function
|
/// depending on the command line arguments, this function
|
||||||
/// informs the OS to flush/discard the caches for input and/or output file.
|
/// informs the OS to flush/discard the caches for input and/or output file.
|
||||||
fn flush_caches_full_length(i: &Input, o: &Output) -> std::io::Result<()> {
|
fn flush_caches_full_length(i: &Input, o: &Output) -> io::Result<()> {
|
||||||
// TODO Better error handling for overflowing `len`.
|
// TODO Better error handling for overflowing `len`.
|
||||||
if i.settings.iflags.nocache {
|
if i.settings.iflags.nocache {
|
||||||
let offset = 0;
|
let offset = 0;
|
||||||
|
@ -1001,7 +1001,7 @@ fn flush_caches_full_length(i: &Input, o: &Output) -> std::io::Result<()> {
|
||||||
///
|
///
|
||||||
/// If there is a problem reading from the input or writing to
|
/// If there is a problem reading from the input or writing to
|
||||||
/// this output.
|
/// this output.
|
||||||
fn dd_copy(mut i: Input, o: Output) -> std::io::Result<()> {
|
fn dd_copy(mut i: Input, o: Output) -> io::Result<()> {
|
||||||
// The read and write statistics.
|
// The read and write statistics.
|
||||||
//
|
//
|
||||||
// These objects are counters, initialized to zero. After each
|
// These objects are counters, initialized to zero. After each
|
||||||
|
@ -1177,7 +1177,7 @@ fn finalize<T>(
|
||||||
prog_tx: &mpsc::Sender<ProgUpdate>,
|
prog_tx: &mpsc::Sender<ProgUpdate>,
|
||||||
output_thread: thread::JoinHandle<T>,
|
output_thread: thread::JoinHandle<T>,
|
||||||
truncate: bool,
|
truncate: bool,
|
||||||
) -> std::io::Result<()> {
|
) -> io::Result<()> {
|
||||||
// Flush the output in case a partial write has been buffered but
|
// Flush the output in case a partial write has been buffered but
|
||||||
// not yet written.
|
// not yet written.
|
||||||
let wstat_update = output.flush()?;
|
let wstat_update = output.flush()?;
|
||||||
|
@ -1245,7 +1245,7 @@ fn make_linux_oflags(oflags: &OFlags) -> Option<libc::c_int> {
|
||||||
/// `conv=swab` or `conv=block` command-line arguments. This function
|
/// `conv=swab` or `conv=block` command-line arguments. This function
|
||||||
/// mutates the `buf` argument in-place. The returned [`ReadStat`]
|
/// mutates the `buf` argument in-place. The returned [`ReadStat`]
|
||||||
/// indicates how many blocks were read.
|
/// indicates how many blocks were read.
|
||||||
fn read_helper(i: &mut Input, buf: &mut Vec<u8>, bsize: usize) -> std::io::Result<ReadStat> {
|
fn read_helper(i: &mut Input, buf: &mut Vec<u8>, bsize: usize) -> io::Result<ReadStat> {
|
||||||
// Local Helper Fns -------------------------------------------------
|
// Local Helper Fns -------------------------------------------------
|
||||||
fn perform_swab(buf: &mut [u8]) {
|
fn perform_swab(buf: &mut [u8]) {
|
||||||
for base in (1..buf.len()).step_by(2) {
|
for base in (1..buf.len()).step_by(2) {
|
||||||
|
|
|
@ -227,7 +227,7 @@ fn get_size_on_disk(path: &Path) -> u64 {
|
||||||
|
|
||||||
// bind file so it stays in scope until end of function
|
// bind file so it stays in scope until end of function
|
||||||
// if it goes out of scope the handle below becomes invalid
|
// if it goes out of scope the handle below becomes invalid
|
||||||
let file = match fs::File::open(path) {
|
let file = match File::open(path) {
|
||||||
Ok(file) => file,
|
Ok(file) => file,
|
||||||
Err(_) => return size_on_disk, // opening directories will fail
|
Err(_) => return size_on_disk, // opening directories will fail
|
||||||
};
|
};
|
||||||
|
@ -240,7 +240,7 @@ fn get_size_on_disk(path: &Path) -> u64 {
|
||||||
file.as_raw_handle() as HANDLE,
|
file.as_raw_handle() as HANDLE,
|
||||||
FileStandardInfo,
|
FileStandardInfo,
|
||||||
file_info_ptr as _,
|
file_info_ptr as _,
|
||||||
std::mem::size_of::<FILE_STANDARD_INFO>() as u32,
|
size_of::<FILE_STANDARD_INFO>() as u32,
|
||||||
);
|
);
|
||||||
|
|
||||||
if success != 0 {
|
if success != 0 {
|
||||||
|
@ -255,7 +255,7 @@ fn get_size_on_disk(path: &Path) -> u64 {
|
||||||
fn get_file_info(path: &Path) -> Option<FileInfo> {
|
fn get_file_info(path: &Path) -> Option<FileInfo> {
|
||||||
let mut result = None;
|
let mut result = None;
|
||||||
|
|
||||||
let file = match fs::File::open(path) {
|
let file = match File::open(path) {
|
||||||
Ok(file) => file,
|
Ok(file) => file,
|
||||||
Err(_) => return result,
|
Err(_) => return result,
|
||||||
};
|
};
|
||||||
|
@ -268,7 +268,7 @@ fn get_file_info(path: &Path) -> Option<FileInfo> {
|
||||||
file.as_raw_handle() as HANDLE,
|
file.as_raw_handle() as HANDLE,
|
||||||
FileIdInfo,
|
FileIdInfo,
|
||||||
file_info_ptr as _,
|
file_info_ptr as _,
|
||||||
std::mem::size_of::<FILE_ID_INFO>() as u32,
|
size_of::<FILE_ID_INFO>() as u32,
|
||||||
);
|
);
|
||||||
|
|
||||||
if success != 0 {
|
if success != 0 {
|
||||||
|
@ -654,7 +654,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
files.collect()
|
files.collect()
|
||||||
} else {
|
} else {
|
||||||
// Deduplicate while preserving order
|
// Deduplicate while preserving order
|
||||||
let mut seen = std::collections::HashSet::new();
|
let mut seen = HashSet::new();
|
||||||
files
|
files
|
||||||
.filter(|path| seen.insert(path.clone()))
|
.filter(|path| seen.insert(path.clone()))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
|
|
12
src/uu/env/src/env.rs
vendored
12
src/uu/env/src/env.rs
vendored
|
@ -345,7 +345,7 @@ fn debug_print_args(args: &[OsString]) {
|
||||||
fn check_and_handle_string_args(
|
fn check_and_handle_string_args(
|
||||||
arg: &OsString,
|
arg: &OsString,
|
||||||
prefix_to_test: &str,
|
prefix_to_test: &str,
|
||||||
all_args: &mut Vec<std::ffi::OsString>,
|
all_args: &mut Vec<OsString>,
|
||||||
do_debug_print_args: Option<&Vec<OsString>>,
|
do_debug_print_args: Option<&Vec<OsString>>,
|
||||||
) -> UResult<bool> {
|
) -> UResult<bool> {
|
||||||
let native_arg = NCvt::convert(arg);
|
let native_arg = NCvt::convert(arg);
|
||||||
|
@ -386,8 +386,8 @@ impl EnvAppData {
|
||||||
fn process_all_string_arguments(
|
fn process_all_string_arguments(
|
||||||
&mut self,
|
&mut self,
|
||||||
original_args: &Vec<OsString>,
|
original_args: &Vec<OsString>,
|
||||||
) -> UResult<Vec<std::ffi::OsString>> {
|
) -> UResult<Vec<OsString>> {
|
||||||
let mut all_args: Vec<std::ffi::OsString> = Vec::new();
|
let mut all_args: Vec<OsString> = Vec::new();
|
||||||
for arg in original_args {
|
for arg in original_args {
|
||||||
match arg {
|
match arg {
|
||||||
b if check_and_handle_string_args(b, "--split-string", &mut all_args, None)? => {
|
b if check_and_handle_string_args(b, "--split-string", &mut all_args, None)? => {
|
||||||
|
@ -454,7 +454,7 @@ impl EnvAppData {
|
||||||
uucore::show_error!("{s}");
|
uucore::show_error!("{s}");
|
||||||
}
|
}
|
||||||
uucore::show_error!("{ERROR_MSG_S_SHEBANG}");
|
uucore::show_error!("{ERROR_MSG_S_SHEBANG}");
|
||||||
uucore::error::ExitCode::new(125)
|
ExitCode::new(125)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})?;
|
})?;
|
||||||
|
@ -751,7 +751,7 @@ fn apply_ignore_signal(opts: &Options<'_>) -> UResult<()> {
|
||||||
for &sig_value in &opts.ignore_signal {
|
for &sig_value in &opts.ignore_signal {
|
||||||
let sig: Signal = (sig_value as i32)
|
let sig: Signal = (sig_value as i32)
|
||||||
.try_into()
|
.try_into()
|
||||||
.map_err(|e| std::io::Error::from_raw_os_error(e as i32))?;
|
.map_err(|e| io::Error::from_raw_os_error(e as i32))?;
|
||||||
|
|
||||||
ignore_signal(sig)?;
|
ignore_signal(sig)?;
|
||||||
}
|
}
|
||||||
|
@ -786,7 +786,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_split_string_environment_vars_test() {
|
fn test_split_string_environment_vars_test() {
|
||||||
unsafe { std::env::set_var("FOO", "BAR") };
|
unsafe { env::set_var("FOO", "BAR") };
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
NCvt::convert(vec!["FOO=bar", "sh", "-c", "echo xBARx =$FOO="]),
|
NCvt::convert(vec!["FOO=bar", "sh", "-c", "echo xBARx =$FOO="]),
|
||||||
parse_args_from_str(&NCvt::convert(r#"FOO=bar sh -c "echo x${FOO}x =\$FOO=""#))
|
parse_args_from_str(&NCvt::convert(r#"FOO=bar sh -c "echo x${FOO}x =\$FOO=""#))
|
||||||
|
|
|
@ -27,10 +27,10 @@ mod options {
|
||||||
|
|
||||||
fn print_factors_str(
|
fn print_factors_str(
|
||||||
num_str: &str,
|
num_str: &str,
|
||||||
w: &mut io::BufWriter<impl io::Write>,
|
w: &mut io::BufWriter<impl Write>,
|
||||||
print_exponents: bool,
|
print_exponents: bool,
|
||||||
) -> UResult<()> {
|
) -> UResult<()> {
|
||||||
let rx = num_str.trim().parse::<num_bigint::BigUint>();
|
let rx = num_str.trim().parse::<BigUint>();
|
||||||
let Ok(x) = rx else {
|
let Ok(x) = rx else {
|
||||||
// return Ok(). it's non-fatal and we should try the next number.
|
// return Ok(). it's non-fatal and we should try the next number.
|
||||||
show_warning!("{}: {}", num_str.maybe_quote(), rx.unwrap_err());
|
show_warning!("{}: {}", num_str.maybe_quote(), rx.unwrap_err());
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
|
|
||||||
use clap::{Arg, ArgAction, ArgMatches, Command};
|
use clap::{Arg, ArgAction, ArgMatches, Command};
|
||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
#[cfg(unix)]
|
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{self, BufWriter, Read, Seek, SeekFrom, Write};
|
use std::io::{self, BufWriter, Read, Seek, SeekFrom, Write};
|
||||||
use std::num::TryFromIntError;
|
use std::num::TryFromIntError;
|
||||||
|
@ -224,7 +223,7 @@ struct HeadOptions {
|
||||||
|
|
||||||
impl HeadOptions {
|
impl HeadOptions {
|
||||||
///Construct options from matches
|
///Construct options from matches
|
||||||
pub fn get_from(matches: &clap::ArgMatches) -> Result<Self, String> {
|
pub fn get_from(matches: &ArgMatches) -> Result<Self, String> {
|
||||||
let mut options = Self::default();
|
let mut options = Self::default();
|
||||||
|
|
||||||
options.quiet = matches.get_flag(options::QUIET_NAME);
|
options.quiet = matches.get_flag(options::QUIET_NAME);
|
||||||
|
@ -251,12 +250,12 @@ fn wrap_in_stdout_error(err: io::Error) -> io::Error {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_n_bytes(input: impl Read, n: u64) -> std::io::Result<u64> {
|
fn read_n_bytes(input: impl Read, n: u64) -> io::Result<u64> {
|
||||||
// Read the first `n` bytes from the `input` reader.
|
// Read the first `n` bytes from the `input` reader.
|
||||||
let mut reader = input.take(n);
|
let mut reader = input.take(n);
|
||||||
|
|
||||||
// Write those bytes to `stdout`.
|
// Write those bytes to `stdout`.
|
||||||
let stdout = std::io::stdout();
|
let stdout = io::stdout();
|
||||||
let mut stdout = stdout.lock();
|
let mut stdout = stdout.lock();
|
||||||
|
|
||||||
let bytes_written = io::copy(&mut reader, &mut stdout).map_err(wrap_in_stdout_error)?;
|
let bytes_written = io::copy(&mut reader, &mut stdout).map_err(wrap_in_stdout_error)?;
|
||||||
|
@ -269,12 +268,12 @@ fn read_n_bytes(input: impl Read, n: u64) -> std::io::Result<u64> {
|
||||||
Ok(bytes_written)
|
Ok(bytes_written)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_n_lines(input: &mut impl std::io::BufRead, n: u64, separator: u8) -> std::io::Result<u64> {
|
fn read_n_lines(input: &mut impl io::BufRead, n: u64, separator: u8) -> io::Result<u64> {
|
||||||
// Read the first `n` lines from the `input` reader.
|
// Read the first `n` lines from the `input` reader.
|
||||||
let mut reader = take_lines(input, n, separator);
|
let mut reader = take_lines(input, n, separator);
|
||||||
|
|
||||||
// Write those bytes to `stdout`.
|
// Write those bytes to `stdout`.
|
||||||
let stdout = std::io::stdout();
|
let stdout = io::stdout();
|
||||||
let stdout = stdout.lock();
|
let stdout = stdout.lock();
|
||||||
let mut writer = BufWriter::with_capacity(BUF_SIZE, stdout);
|
let mut writer = BufWriter::with_capacity(BUF_SIZE, stdout);
|
||||||
|
|
||||||
|
@ -298,10 +297,10 @@ fn catch_too_large_numbers_in_backwards_bytes_or_lines(n: u64) -> Option<usize>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_but_last_n_bytes(mut input: impl Read, n: u64) -> std::io::Result<u64> {
|
fn read_but_last_n_bytes(mut input: impl Read, n: u64) -> io::Result<u64> {
|
||||||
let mut bytes_written: u64 = 0;
|
let mut bytes_written: u64 = 0;
|
||||||
if let Some(n) = catch_too_large_numbers_in_backwards_bytes_or_lines(n) {
|
if let Some(n) = catch_too_large_numbers_in_backwards_bytes_or_lines(n) {
|
||||||
let stdout = std::io::stdout();
|
let stdout = io::stdout();
|
||||||
let mut stdout = stdout.lock();
|
let mut stdout = stdout.lock();
|
||||||
|
|
||||||
bytes_written = copy_all_but_n_bytes(&mut input, &mut stdout, n)
|
bytes_written = copy_all_but_n_bytes(&mut input, &mut stdout, n)
|
||||||
|
@ -317,8 +316,8 @@ fn read_but_last_n_bytes(mut input: impl Read, n: u64) -> std::io::Result<u64> {
|
||||||
Ok(bytes_written)
|
Ok(bytes_written)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_but_last_n_lines(mut input: impl Read, n: u64, separator: u8) -> std::io::Result<u64> {
|
fn read_but_last_n_lines(mut input: impl Read, n: u64, separator: u8) -> io::Result<u64> {
|
||||||
let stdout = std::io::stdout();
|
let stdout = io::stdout();
|
||||||
let mut stdout = stdout.lock();
|
let mut stdout = stdout.lock();
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
return io::copy(&mut input, &mut stdout).map_err(wrap_in_stdout_error);
|
return io::copy(&mut input, &mut stdout).map_err(wrap_in_stdout_error);
|
||||||
|
@ -370,7 +369,7 @@ fn read_but_last_n_lines(mut input: impl Read, n: u64, separator: u8) -> std::io
|
||||||
/// assert_eq!(find_nth_line_from_end(&mut input, 4, false).unwrap(), 0);
|
/// assert_eq!(find_nth_line_from_end(&mut input, 4, false).unwrap(), 0);
|
||||||
/// assert_eq!(find_nth_line_from_end(&mut input, 1000, false).unwrap(), 0);
|
/// assert_eq!(find_nth_line_from_end(&mut input, 1000, false).unwrap(), 0);
|
||||||
/// ```
|
/// ```
|
||||||
fn find_nth_line_from_end<R>(input: &mut R, n: u64, separator: u8) -> std::io::Result<u64>
|
fn find_nth_line_from_end<R>(input: &mut R, n: u64, separator: u8) -> io::Result<u64>
|
||||||
where
|
where
|
||||||
R: Read + Seek,
|
R: Read + Seek,
|
||||||
{
|
{
|
||||||
|
@ -408,14 +407,14 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_seekable(input: &mut std::fs::File) -> bool {
|
fn is_seekable(input: &mut File) -> bool {
|
||||||
let current_pos = input.stream_position();
|
let current_pos = input.stream_position();
|
||||||
current_pos.is_ok()
|
current_pos.is_ok()
|
||||||
&& input.seek(SeekFrom::End(0)).is_ok()
|
&& input.seek(SeekFrom::End(0)).is_ok()
|
||||||
&& input.seek(SeekFrom::Start(current_pos.unwrap())).is_ok()
|
&& input.seek(SeekFrom::Start(current_pos.unwrap())).is_ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn head_backwards_file(input: &mut std::fs::File, options: &HeadOptions) -> std::io::Result<u64> {
|
fn head_backwards_file(input: &mut File, options: &HeadOptions) -> io::Result<u64> {
|
||||||
let st = input.metadata()?;
|
let st = input.metadata()?;
|
||||||
let seekable = is_seekable(input);
|
let seekable = is_seekable(input);
|
||||||
let blksize_limit = uucore::fs::sane_blksize::sane_blksize_from_metadata(&st);
|
let blksize_limit = uucore::fs::sane_blksize::sane_blksize_from_metadata(&st);
|
||||||
|
@ -426,10 +425,7 @@ fn head_backwards_file(input: &mut std::fs::File, options: &HeadOptions) -> std:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn head_backwards_without_seek_file(
|
fn head_backwards_without_seek_file(input: &mut File, options: &HeadOptions) -> io::Result<u64> {
|
||||||
input: &mut std::fs::File,
|
|
||||||
options: &HeadOptions,
|
|
||||||
) -> std::io::Result<u64> {
|
|
||||||
match options.mode {
|
match options.mode {
|
||||||
Mode::AllButLastBytes(n) => read_but_last_n_bytes(input, n),
|
Mode::AllButLastBytes(n) => read_but_last_n_bytes(input, n),
|
||||||
Mode::AllButLastLines(n) => read_but_last_n_lines(input, n, options.line_ending.into()),
|
Mode::AllButLastLines(n) => read_but_last_n_lines(input, n, options.line_ending.into()),
|
||||||
|
@ -437,10 +433,7 @@ fn head_backwards_without_seek_file(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn head_backwards_on_seekable_file(
|
fn head_backwards_on_seekable_file(input: &mut File, options: &HeadOptions) -> io::Result<u64> {
|
||||||
input: &mut std::fs::File,
|
|
||||||
options: &HeadOptions,
|
|
||||||
) -> std::io::Result<u64> {
|
|
||||||
match options.mode {
|
match options.mode {
|
||||||
Mode::AllButLastBytes(n) => {
|
Mode::AllButLastBytes(n) => {
|
||||||
let size = input.metadata()?.len();
|
let size = input.metadata()?.len();
|
||||||
|
@ -458,11 +451,11 @@ fn head_backwards_on_seekable_file(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn head_file(input: &mut std::fs::File, options: &HeadOptions) -> std::io::Result<u64> {
|
fn head_file(input: &mut File, options: &HeadOptions) -> io::Result<u64> {
|
||||||
match options.mode {
|
match options.mode {
|
||||||
Mode::FirstBytes(n) => read_n_bytes(input, n),
|
Mode::FirstBytes(n) => read_n_bytes(input, n),
|
||||||
Mode::FirstLines(n) => read_n_lines(
|
Mode::FirstLines(n) => read_n_lines(
|
||||||
&mut std::io::BufReader::with_capacity(BUF_SIZE, input),
|
&mut io::BufReader::with_capacity(BUF_SIZE, input),
|
||||||
n,
|
n,
|
||||||
options.line_ending.into(),
|
options.line_ending.into(),
|
||||||
),
|
),
|
||||||
|
@ -482,7 +475,7 @@ fn uu_head(options: &HeadOptions) -> UResult<()> {
|
||||||
}
|
}
|
||||||
println!("==> standard input <==");
|
println!("==> standard input <==");
|
||||||
}
|
}
|
||||||
let stdin = std::io::stdin();
|
let stdin = io::stdin();
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
{
|
{
|
||||||
|
@ -520,7 +513,7 @@ fn uu_head(options: &HeadOptions) -> UResult<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
(name, false) => {
|
(name, false) => {
|
||||||
let mut file = match std::fs::File::open(name) {
|
let mut file = match File::open(name) {
|
||||||
Ok(f) => f,
|
Ok(f) => f,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
show!(err.map_err_context(|| format!(
|
show!(err.map_err_context(|| format!(
|
||||||
|
@ -575,8 +568,8 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use io::Cursor;
|
||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
use std::io::Cursor;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
@ -691,7 +684,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn read_early_exit() {
|
fn read_early_exit() {
|
||||||
let mut empty = std::io::BufReader::new(std::io::Cursor::new(Vec::new()));
|
let mut empty = io::BufReader::new(Cursor::new(Vec::new()));
|
||||||
assert!(read_n_bytes(&mut empty, 0).is_ok());
|
assert!(read_n_bytes(&mut empty, 0).is_ok());
|
||||||
assert!(read_n_lines(&mut empty, 0, b'\n').is_ok());
|
assert!(read_n_lines(&mut empty, 0, b'\n').is_ok());
|
||||||
}
|
}
|
||||||
|
|
|
@ -675,7 +675,7 @@ fn chown_optional_user_group(path: &Path, b: &Behavior) -> UResult<()> {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
|
|
||||||
let meta = match fs::metadata(path) {
|
let meta = match metadata(path) {
|
||||||
Ok(meta) => meta,
|
Ok(meta) => meta,
|
||||||
Err(e) => return Err(InstallError::MetadataFailed(e).into()),
|
Err(e) => return Err(InstallError::MetadataFailed(e).into()),
|
||||||
};
|
};
|
||||||
|
@ -859,7 +859,7 @@ fn set_ownership_and_permissions(to: &Path, b: &Behavior) -> UResult<()> {
|
||||||
/// Returns an empty Result or an error in case of failure.
|
/// Returns an empty Result or an error in case of failure.
|
||||||
///
|
///
|
||||||
fn preserve_timestamps(from: &Path, to: &Path) -> UResult<()> {
|
fn preserve_timestamps(from: &Path, to: &Path) -> UResult<()> {
|
||||||
let meta = match fs::metadata(from) {
|
let meta = match metadata(from) {
|
||||||
Ok(meta) => meta,
|
Ok(meta) => meta,
|
||||||
Err(e) => return Err(InstallError::MetadataFailed(e).into()),
|
Err(e) => return Err(InstallError::MetadataFailed(e).into()),
|
||||||
};
|
};
|
||||||
|
@ -940,14 +940,14 @@ fn copy(from: &Path, to: &Path, b: &Behavior) -> UResult<()> {
|
||||||
fn need_copy(from: &Path, to: &Path, b: &Behavior) -> UResult<bool> {
|
fn need_copy(from: &Path, to: &Path, b: &Behavior) -> UResult<bool> {
|
||||||
// Attempt to retrieve metadata for the source file.
|
// Attempt to retrieve metadata for the source file.
|
||||||
// If this fails, assume the file needs to be copied.
|
// If this fails, assume the file needs to be copied.
|
||||||
let from_meta = match fs::metadata(from) {
|
let from_meta = match metadata(from) {
|
||||||
Ok(meta) => meta,
|
Ok(meta) => meta,
|
||||||
Err(_) => return Ok(true),
|
Err(_) => return Ok(true),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Attempt to retrieve metadata for the destination file.
|
// Attempt to retrieve metadata for the destination file.
|
||||||
// If this fails, assume the file needs to be copied.
|
// If this fails, assume the file needs to be copied.
|
||||||
let to_meta = match fs::metadata(to) {
|
let to_meta = match metadata(to) {
|
||||||
Ok(meta) => meta,
|
Ok(meta) => meta,
|
||||||
Err(_) => return Ok(true),
|
Err(_) => return Ok(true),
|
||||||
};
|
};
|
||||||
|
|
|
@ -74,7 +74,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
} else {
|
} else {
|
||||||
let sig = (sig as i32)
|
let sig = (sig as i32)
|
||||||
.try_into()
|
.try_into()
|
||||||
.map_err(|e| std::io::Error::from_raw_os_error(e as i32))?;
|
.map_err(|e| Error::from_raw_os_error(e as i32))?;
|
||||||
Some(sig)
|
Some(sig)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -439,7 +439,7 @@ fn extract_format(options: &clap::ArgMatches) -> (Format, Option<&'static str>)
|
||||||
(Format::Commas, Some(options::format::COMMAS))
|
(Format::Commas, Some(options::format::COMMAS))
|
||||||
} else if options.get_flag(options::format::COLUMNS) {
|
} else if options.get_flag(options::format::COLUMNS) {
|
||||||
(Format::Columns, Some(options::format::COLUMNS))
|
(Format::Columns, Some(options::format::COLUMNS))
|
||||||
} else if std::io::stdout().is_terminal() {
|
} else if stdout().is_terminal() {
|
||||||
(Format::Columns, None)
|
(Format::Columns, None)
|
||||||
} else {
|
} else {
|
||||||
(Format::OneLine, None)
|
(Format::OneLine, None)
|
||||||
|
@ -559,7 +559,7 @@ fn extract_color(options: &clap::ArgMatches) -> bool {
|
||||||
None => options.contains_id(options::COLOR),
|
None => options.contains_id(options::COLOR),
|
||||||
Some(val) => match val.as_str() {
|
Some(val) => match val.as_str() {
|
||||||
"" | "always" | "yes" | "force" => true,
|
"" | "always" | "yes" | "force" => true,
|
||||||
"auto" | "tty" | "if-tty" => std::io::stdout().is_terminal(),
|
"auto" | "tty" | "if-tty" => stdout().is_terminal(),
|
||||||
/* "never" | "no" | "none" | */ _ => false,
|
/* "never" | "no" | "none" | */ _ => false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -578,7 +578,7 @@ fn extract_hyperlink(options: &clap::ArgMatches) -> bool {
|
||||||
|
|
||||||
match hyperlink {
|
match hyperlink {
|
||||||
"always" | "yes" | "force" => true,
|
"always" | "yes" | "force" => true,
|
||||||
"auto" | "tty" | "if-tty" => std::io::stdout().is_terminal(),
|
"auto" | "tty" | "if-tty" => stdout().is_terminal(),
|
||||||
"never" | "no" | "none" => false,
|
"never" | "no" | "none" => false,
|
||||||
_ => unreachable!("should be handled by clap"),
|
_ => unreachable!("should be handled by clap"),
|
||||||
}
|
}
|
||||||
|
@ -673,7 +673,7 @@ fn extract_quoting_style(options: &clap::ArgMatches, show_control: bool) -> Quot
|
||||||
|
|
||||||
// By default, `ls` uses Shell escape quoting style when writing to a terminal file
|
// By default, `ls` uses Shell escape quoting style when writing to a terminal file
|
||||||
// descriptor and Literal otherwise.
|
// descriptor and Literal otherwise.
|
||||||
if std::io::stdout().is_terminal() {
|
if stdout().is_terminal() {
|
||||||
QuotingStyle::Shell {
|
QuotingStyle::Shell {
|
||||||
escape: true,
|
escape: true,
|
||||||
always_quote: false,
|
always_quote: false,
|
||||||
|
@ -704,7 +704,7 @@ fn extract_indicator_style(options: &clap::ArgMatches) -> IndicatorStyle {
|
||||||
"never" | "no" | "none" => IndicatorStyle::None,
|
"never" | "no" | "none" => IndicatorStyle::None,
|
||||||
"always" | "yes" | "force" => IndicatorStyle::Classify,
|
"always" | "yes" | "force" => IndicatorStyle::Classify,
|
||||||
"auto" | "tty" | "if-tty" => {
|
"auto" | "tty" | "if-tty" => {
|
||||||
if std::io::stdout().is_terminal() {
|
if stdout().is_terminal() {
|
||||||
IndicatorStyle::Classify
|
IndicatorStyle::Classify
|
||||||
} else {
|
} else {
|
||||||
IndicatorStyle::None
|
IndicatorStyle::None
|
||||||
|
@ -933,7 +933,7 @@ impl Config {
|
||||||
} else if options.get_flag(options::SHOW_CONTROL_CHARS) {
|
} else if options.get_flag(options::SHOW_CONTROL_CHARS) {
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
!std::io::stdout().is_terminal()
|
!stdout().is_terminal()
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut quoting_style = extract_quoting_style(options, show_control);
|
let mut quoting_style = extract_quoting_style(options, show_control);
|
||||||
|
@ -2386,7 +2386,7 @@ fn get_metadata_with_deref_opt(p_buf: &Path, dereference: bool) -> std::io::Resu
|
||||||
fn display_dir_entry_size(
|
fn display_dir_entry_size(
|
||||||
entry: &PathData,
|
entry: &PathData,
|
||||||
config: &Config,
|
config: &Config,
|
||||||
out: &mut BufWriter<std::io::Stdout>,
|
out: &mut BufWriter<Stdout>,
|
||||||
) -> (usize, usize, usize, usize, usize, usize) {
|
) -> (usize, usize, usize, usize, usize, usize) {
|
||||||
// TODO: Cache/memorize the display_* results so we don't have to recalculate them.
|
// TODO: Cache/memorize the display_* results so we don't have to recalculate them.
|
||||||
if let Some(md) = entry.get_metadata(out) {
|
if let Some(md) = entry.get_metadata(out) {
|
||||||
|
@ -3070,7 +3070,7 @@ fn get_system_time(md: &Metadata, config: &Config) -> Option<SystemTime> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_time(md: &Metadata, config: &Config) -> Option<chrono::DateTime<chrono::Local>> {
|
fn get_time(md: &Metadata, config: &Config) -> Option<DateTime<Local>> {
|
||||||
let time = get_system_time(md, config)?;
|
let time = get_system_time(md, config)?;
|
||||||
Some(time.into())
|
Some(time.into())
|
||||||
}
|
}
|
||||||
|
|
|
@ -266,7 +266,7 @@ pub fn uu_app() -> Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_os = "fuchsia"))]
|
#[cfg(not(target_os = "fuchsia"))]
|
||||||
fn setup_term() -> std::io::Stdout {
|
fn setup_term() -> Stdout {
|
||||||
let stdout = stdout();
|
let stdout = stdout();
|
||||||
terminal::enable_raw_mode().unwrap();
|
terminal::enable_raw_mode().unwrap();
|
||||||
stdout
|
stdout
|
||||||
|
@ -279,10 +279,10 @@ fn setup_term() -> usize {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_os = "fuchsia"))]
|
#[cfg(not(target_os = "fuchsia"))]
|
||||||
fn reset_term(stdout: &mut std::io::Stdout) {
|
fn reset_term(stdout: &mut Stdout) {
|
||||||
terminal::disable_raw_mode().unwrap();
|
terminal::disable_raw_mode().unwrap();
|
||||||
// Clear the prompt
|
// Clear the prompt
|
||||||
queue!(stdout, terminal::Clear(ClearType::CurrentLine)).unwrap();
|
queue!(stdout, Clear(ClearType::CurrentLine)).unwrap();
|
||||||
// Move cursor to the beginning without printing new line
|
// Move cursor to the beginning without printing new line
|
||||||
print!("\r");
|
print!("\r");
|
||||||
stdout.flush().unwrap();
|
stdout.flush().unwrap();
|
||||||
|
@ -313,7 +313,7 @@ fn more(
|
||||||
match search_pattern_in_file(&pager.lines, pat) {
|
match search_pattern_in_file(&pager.lines, pat) {
|
||||||
Some(number) => pager.upper_mark = number,
|
Some(number) => pager.upper_mark = number,
|
||||||
None => {
|
None => {
|
||||||
execute!(stdout, terminal::Clear(terminal::ClearType::CurrentLine))?;
|
execute!(stdout, Clear(ClearType::CurrentLine))?;
|
||||||
stdout.write_all("\rPattern not found\n".as_bytes())?;
|
stdout.write_all("\rPattern not found\n".as_bytes())?;
|
||||||
pager.content_rows -= 1;
|
pager.content_rows -= 1;
|
||||||
}
|
}
|
||||||
|
@ -321,7 +321,7 @@ fn more(
|
||||||
}
|
}
|
||||||
|
|
||||||
if multiple_file {
|
if multiple_file {
|
||||||
execute!(stdout, terminal::Clear(terminal::ClearType::CurrentLine)).unwrap();
|
execute!(stdout, Clear(ClearType::CurrentLine)).unwrap();
|
||||||
stdout.write_all(
|
stdout.write_all(
|
||||||
MULTI_FILE_TOP_PROMPT
|
MULTI_FILE_TOP_PROMPT
|
||||||
.replace("{}", file.unwrap_or_default())
|
.replace("{}", file.unwrap_or_default())
|
||||||
|
@ -516,7 +516,7 @@ impl<'a> Pager<'a> {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw(&mut self, stdout: &mut std::io::Stdout, wrong_key: Option<char>) {
|
fn draw(&mut self, stdout: &mut Stdout, wrong_key: Option<char>) {
|
||||||
self.draw_lines(stdout);
|
self.draw_lines(stdout);
|
||||||
let lower_mark = self
|
let lower_mark = self
|
||||||
.line_count
|
.line_count
|
||||||
|
@ -525,8 +525,8 @@ impl<'a> Pager<'a> {
|
||||||
stdout.flush().unwrap();
|
stdout.flush().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_lines(&mut self, stdout: &mut std::io::Stdout) {
|
fn draw_lines(&mut self, stdout: &mut Stdout) {
|
||||||
execute!(stdout, terminal::Clear(terminal::ClearType::CurrentLine)).unwrap();
|
execute!(stdout, Clear(ClearType::CurrentLine)).unwrap();
|
||||||
|
|
||||||
self.line_squeezed = 0;
|
self.line_squeezed = 0;
|
||||||
let mut previous_line_blank = false;
|
let mut previous_line_blank = false;
|
||||||
|
@ -611,7 +611,7 @@ fn search_pattern_in_file(lines: &[&str], pattern: &str) -> Option<usize> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paging_add_back_message(options: &Options, stdout: &mut std::io::Stdout) -> UResult<()> {
|
fn paging_add_back_message(options: &Options, stdout: &mut Stdout) -> UResult<()> {
|
||||||
if options.lines.is_some() {
|
if options.lines.is_some() {
|
||||||
execute!(stdout, MoveUp(1))?;
|
execute!(stdout, MoveUp(1))?;
|
||||||
stdout.write_all("\n\r...back 1 page\n".as_bytes())?;
|
stdout.write_all("\n\r...back 1 page\n".as_bytes())?;
|
||||||
|
|
|
@ -131,7 +131,7 @@ fn replace_fds() -> UResult<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_stdout() -> UResult<File> {
|
fn find_stdout() -> UResult<File> {
|
||||||
let internal_failure_code = match std::env::var("POSIXLY_CORRECT") {
|
let internal_failure_code = match env::var("POSIXLY_CORRECT") {
|
||||||
Ok(_) => POSIX_NOHUP_FAILURE,
|
Ok(_) => POSIX_NOHUP_FAILURE,
|
||||||
Err(_) => EXIT_CANCELED,
|
Err(_) => EXIT_CANCELED,
|
||||||
};
|
};
|
||||||
|
|
|
@ -153,10 +153,10 @@ fn parse_unit_size_suffix(s: &str) -> Option<usize> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_options(args: &ArgMatches) -> Result<NumfmtOptions> {
|
fn parse_options(args: &ArgMatches) -> Result<NumfmtOptions> {
|
||||||
let from = parse_unit(args.get_one::<String>(options::FROM).unwrap())?;
|
let from = parse_unit(args.get_one::<String>(FROM).unwrap())?;
|
||||||
let to = parse_unit(args.get_one::<String>(options::TO).unwrap())?;
|
let to = parse_unit(args.get_one::<String>(TO).unwrap())?;
|
||||||
let from_unit = parse_unit_size(args.get_one::<String>(options::FROM_UNIT).unwrap())?;
|
let from_unit = parse_unit_size(args.get_one::<String>(FROM_UNIT).unwrap())?;
|
||||||
let to_unit = parse_unit_size(args.get_one::<String>(options::TO_UNIT).unwrap())?;
|
let to_unit = parse_unit_size(args.get_one::<String>(TO_UNIT).unwrap())?;
|
||||||
|
|
||||||
let transform = TransformOptions {
|
let transform = TransformOptions {
|
||||||
from,
|
from,
|
||||||
|
@ -165,7 +165,7 @@ fn parse_options(args: &ArgMatches) -> Result<NumfmtOptions> {
|
||||||
to_unit,
|
to_unit,
|
||||||
};
|
};
|
||||||
|
|
||||||
let padding = match args.get_one::<String>(options::PADDING) {
|
let padding = match args.get_one::<String>(PADDING) {
|
||||||
Some(s) => s
|
Some(s) => s
|
||||||
.parse::<isize>()
|
.parse::<isize>()
|
||||||
.map_err(|_| s)
|
.map_err(|_| s)
|
||||||
|
@ -177,8 +177,8 @@ fn parse_options(args: &ArgMatches) -> Result<NumfmtOptions> {
|
||||||
None => Ok(0),
|
None => Ok(0),
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
let header = if args.value_source(options::HEADER) == Some(ValueSource::CommandLine) {
|
let header = if args.value_source(HEADER) == Some(ValueSource::CommandLine) {
|
||||||
let value = args.get_one::<String>(options::HEADER).unwrap();
|
let value = args.get_one::<String>(HEADER).unwrap();
|
||||||
|
|
||||||
value
|
value
|
||||||
.parse::<usize>()
|
.parse::<usize>()
|
||||||
|
@ -192,7 +192,7 @@ fn parse_options(args: &ArgMatches) -> Result<NumfmtOptions> {
|
||||||
Ok(0)
|
Ok(0)
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
let fields = args.get_one::<String>(options::FIELD).unwrap().as_str();
|
let fields = args.get_one::<String>(FIELD).unwrap().as_str();
|
||||||
// a lone "-" means "all fields", even as part of a list of fields
|
// a lone "-" means "all fields", even as part of a list of fields
|
||||||
let fields = if fields.split(&[',', ' ']).any(|x| x == "-") {
|
let fields = if fields.split(&[',', ' ']).any(|x| x == "-") {
|
||||||
vec![Range {
|
vec![Range {
|
||||||
|
@ -203,7 +203,7 @@ fn parse_options(args: &ArgMatches) -> Result<NumfmtOptions> {
|
||||||
Range::from_list(fields)?
|
Range::from_list(fields)?
|
||||||
};
|
};
|
||||||
|
|
||||||
let format = match args.get_one::<String>(options::FORMAT) {
|
let format = match args.get_one::<String>(FORMAT) {
|
||||||
Some(s) => s.parse()?,
|
Some(s) => s.parse()?,
|
||||||
None => FormatOptions::default(),
|
None => FormatOptions::default(),
|
||||||
};
|
};
|
||||||
|
@ -212,18 +212,16 @@ fn parse_options(args: &ArgMatches) -> Result<NumfmtOptions> {
|
||||||
return Err("grouping cannot be combined with --to".to_string());
|
return Err("grouping cannot be combined with --to".to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
let delimiter = args
|
let delimiter = args.get_one::<String>(DELIMITER).map_or(Ok(None), |arg| {
|
||||||
.get_one::<String>(options::DELIMITER)
|
if arg.len() == 1 {
|
||||||
.map_or(Ok(None), |arg| {
|
Ok(Some(arg.to_string()))
|
||||||
if arg.len() == 1 {
|
} else {
|
||||||
Ok(Some(arg.to_string()))
|
Err("the delimiter must be a single character".to_string())
|
||||||
} else {
|
}
|
||||||
Err("the delimiter must be a single character".to_string())
|
})?;
|
||||||
}
|
|
||||||
})?;
|
|
||||||
|
|
||||||
// unwrap is fine because the argument has a default value
|
// unwrap is fine because the argument has a default value
|
||||||
let round = match args.get_one::<String>(options::ROUND).unwrap().as_str() {
|
let round = match args.get_one::<String>(ROUND).unwrap().as_str() {
|
||||||
"up" => RoundMethod::Up,
|
"up" => RoundMethod::Up,
|
||||||
"down" => RoundMethod::Down,
|
"down" => RoundMethod::Down,
|
||||||
"from-zero" => RoundMethod::FromZero,
|
"from-zero" => RoundMethod::FromZero,
|
||||||
|
@ -232,12 +230,11 @@ fn parse_options(args: &ArgMatches) -> Result<NumfmtOptions> {
|
||||||
_ => unreachable!("Should be restricted by clap"),
|
_ => unreachable!("Should be restricted by clap"),
|
||||||
};
|
};
|
||||||
|
|
||||||
let suffix = args.get_one::<String>(options::SUFFIX).cloned();
|
let suffix = args.get_one::<String>(SUFFIX).cloned();
|
||||||
|
|
||||||
let invalid =
|
let invalid = InvalidModes::from_str(args.get_one::<String>(INVALID).unwrap()).unwrap();
|
||||||
InvalidModes::from_str(args.get_one::<String>(options::INVALID).unwrap()).unwrap();
|
|
||||||
|
|
||||||
let zero_terminated = args.get_flag(options::ZERO_TERMINATED);
|
let zero_terminated = args.get_flag(ZERO_TERMINATED);
|
||||||
|
|
||||||
Ok(NumfmtOptions {
|
Ok(NumfmtOptions {
|
||||||
transform,
|
transform,
|
||||||
|
@ -259,7 +256,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
|
|
||||||
let options = parse_options(&matches).map_err(NumfmtError::IllegalArgument)?;
|
let options = parse_options(&matches).map_err(NumfmtError::IllegalArgument)?;
|
||||||
|
|
||||||
let result = match matches.get_many::<String>(options::NUMBER) {
|
let result = match matches.get_many::<String>(NUMBER) {
|
||||||
Some(values) => handle_args(values.map(|s| s.as_str()), &options),
|
Some(values) => handle_args(values.map(|s| s.as_str()), &options),
|
||||||
None => {
|
None => {
|
||||||
let stdin = std::io::stdin();
|
let stdin = std::io::stdin();
|
||||||
|
@ -286,58 +283,58 @@ pub fn uu_app() -> Command {
|
||||||
.allow_negative_numbers(true)
|
.allow_negative_numbers(true)
|
||||||
.infer_long_args(true)
|
.infer_long_args(true)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new(options::DELIMITER)
|
Arg::new(DELIMITER)
|
||||||
.short('d')
|
.short('d')
|
||||||
.long(options::DELIMITER)
|
.long(DELIMITER)
|
||||||
.value_name("X")
|
.value_name("X")
|
||||||
.help("use X instead of whitespace for field delimiter"),
|
.help("use X instead of whitespace for field delimiter"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new(options::FIELD)
|
Arg::new(FIELD)
|
||||||
.long(options::FIELD)
|
.long(FIELD)
|
||||||
.help("replace the numbers in these input fields; see FIELDS below")
|
.help("replace the numbers in these input fields; see FIELDS below")
|
||||||
.value_name("FIELDS")
|
.value_name("FIELDS")
|
||||||
.allow_hyphen_values(true)
|
.allow_hyphen_values(true)
|
||||||
.default_value(options::FIELD_DEFAULT),
|
.default_value(FIELD_DEFAULT),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new(options::FORMAT)
|
Arg::new(FORMAT)
|
||||||
.long(options::FORMAT)
|
.long(FORMAT)
|
||||||
.help("use printf style floating-point FORMAT; see FORMAT below for details")
|
.help("use printf style floating-point FORMAT; see FORMAT below for details")
|
||||||
.value_name("FORMAT")
|
.value_name("FORMAT")
|
||||||
.allow_hyphen_values(true),
|
.allow_hyphen_values(true),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new(options::FROM)
|
Arg::new(FROM)
|
||||||
.long(options::FROM)
|
.long(FROM)
|
||||||
.help("auto-scale input numbers to UNITs; see UNIT below")
|
.help("auto-scale input numbers to UNITs; see UNIT below")
|
||||||
.value_name("UNIT")
|
.value_name("UNIT")
|
||||||
.default_value(options::FROM_DEFAULT),
|
.default_value(FROM_DEFAULT),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new(options::FROM_UNIT)
|
Arg::new(FROM_UNIT)
|
||||||
.long(options::FROM_UNIT)
|
.long(FROM_UNIT)
|
||||||
.help("specify the input unit size")
|
.help("specify the input unit size")
|
||||||
.value_name("N")
|
.value_name("N")
|
||||||
.default_value(options::FROM_UNIT_DEFAULT),
|
.default_value(FROM_UNIT_DEFAULT),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new(options::TO)
|
Arg::new(TO)
|
||||||
.long(options::TO)
|
.long(TO)
|
||||||
.help("auto-scale output numbers to UNITs; see UNIT below")
|
.help("auto-scale output numbers to UNITs; see UNIT below")
|
||||||
.value_name("UNIT")
|
.value_name("UNIT")
|
||||||
.default_value(options::TO_DEFAULT),
|
.default_value(TO_DEFAULT),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new(options::TO_UNIT)
|
Arg::new(TO_UNIT)
|
||||||
.long(options::TO_UNIT)
|
.long(TO_UNIT)
|
||||||
.help("the output unit size")
|
.help("the output unit size")
|
||||||
.value_name("N")
|
.value_name("N")
|
||||||
.default_value(options::TO_UNIT_DEFAULT),
|
.default_value(TO_UNIT_DEFAULT),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new(options::PADDING)
|
Arg::new(PADDING)
|
||||||
.long(options::PADDING)
|
.long(PADDING)
|
||||||
.help(
|
.help(
|
||||||
"pad the output to N characters; positive N will \
|
"pad the output to N characters; positive N will \
|
||||||
right-align; negative N will left-align; padding is \
|
right-align; negative N will left-align; padding is \
|
||||||
|
@ -347,20 +344,20 @@ pub fn uu_app() -> Command {
|
||||||
.value_name("N"),
|
.value_name("N"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new(options::HEADER)
|
Arg::new(HEADER)
|
||||||
.long(options::HEADER)
|
.long(HEADER)
|
||||||
.help(
|
.help(
|
||||||
"print (without converting) the first N header lines; \
|
"print (without converting) the first N header lines; \
|
||||||
N defaults to 1 if not specified",
|
N defaults to 1 if not specified",
|
||||||
)
|
)
|
||||||
.num_args(..=1)
|
.num_args(..=1)
|
||||||
.value_name("N")
|
.value_name("N")
|
||||||
.default_missing_value(options::HEADER_DEFAULT)
|
.default_missing_value(HEADER_DEFAULT)
|
||||||
.hide_default_value(true),
|
.hide_default_value(true),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new(options::ROUND)
|
Arg::new(ROUND)
|
||||||
.long(options::ROUND)
|
.long(ROUND)
|
||||||
.help("use METHOD for rounding when scaling")
|
.help("use METHOD for rounding when scaling")
|
||||||
.value_name("METHOD")
|
.value_name("METHOD")
|
||||||
.default_value("from-zero")
|
.default_value("from-zero")
|
||||||
|
@ -373,8 +370,8 @@ pub fn uu_app() -> Command {
|
||||||
])),
|
])),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new(options::SUFFIX)
|
Arg::new(SUFFIX)
|
||||||
.long(options::SUFFIX)
|
.long(SUFFIX)
|
||||||
.help(
|
.help(
|
||||||
"print SUFFIX after each formatted number, and accept \
|
"print SUFFIX after each formatted number, and accept \
|
||||||
inputs optionally ending with SUFFIX",
|
inputs optionally ending with SUFFIX",
|
||||||
|
@ -382,25 +379,21 @@ pub fn uu_app() -> Command {
|
||||||
.value_name("SUFFIX"),
|
.value_name("SUFFIX"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new(options::INVALID)
|
Arg::new(INVALID)
|
||||||
.long(options::INVALID)
|
.long(INVALID)
|
||||||
.help("set the failure mode for invalid input")
|
.help("set the failure mode for invalid input")
|
||||||
.default_value("abort")
|
.default_value("abort")
|
||||||
.value_parser(["abort", "fail", "warn", "ignore"])
|
.value_parser(["abort", "fail", "warn", "ignore"])
|
||||||
.value_name("INVALID"),
|
.value_name("INVALID"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new(options::ZERO_TERMINATED)
|
Arg::new(ZERO_TERMINATED)
|
||||||
.long(options::ZERO_TERMINATED)
|
.long(ZERO_TERMINATED)
|
||||||
.short('z')
|
.short('z')
|
||||||
.help("line delimiter is NUL, not newline")
|
.help("line delimiter is NUL, not newline")
|
||||||
.action(ArgAction::SetTrue),
|
.action(ArgAction::SetTrue),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(Arg::new(NUMBER).hide(true).action(ArgAction::Append))
|
||||||
Arg::new(options::NUMBER)
|
|
||||||
.hide(true)
|
|
||||||
.action(ArgAction::Append),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -48,7 +48,7 @@ impl MultifileReader<'_> {
|
||||||
}
|
}
|
||||||
match self.ni.remove(0) {
|
match self.ni.remove(0) {
|
||||||
InputSource::Stdin => {
|
InputSource::Stdin => {
|
||||||
self.curr_file = Some(Box::new(BufReader::new(std::io::stdin())));
|
self.curr_file = Some(Box::new(BufReader::new(io::stdin())));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
InputSource::FileName(fname) => {
|
InputSource::FileName(fname) => {
|
||||||
|
|
|
@ -333,7 +333,7 @@ pub fn remove(files: &[&OsStr], options: &Options) -> bool {
|
||||||
/// `path` must be a directory. If there is an error reading the
|
/// `path` must be a directory. If there is an error reading the
|
||||||
/// contents of the directory, this returns `false`.
|
/// contents of the directory, this returns `false`.
|
||||||
fn is_dir_empty(path: &Path) -> bool {
|
fn is_dir_empty(path: &Path) -> bool {
|
||||||
match std::fs::read_dir(path) {
|
match fs::read_dir(path) {
|
||||||
Err(_) => false,
|
Err(_) => false,
|
||||||
Ok(iter) => iter.count() == 0,
|
Ok(iter) => iter.count() == 0,
|
||||||
}
|
}
|
||||||
|
@ -348,7 +348,7 @@ fn is_readable_metadata(metadata: &Metadata) -> bool {
|
||||||
/// Whether the given file or directory is readable.
|
/// Whether the given file or directory is readable.
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
fn is_readable(path: &Path) -> bool {
|
fn is_readable(path: &Path) -> bool {
|
||||||
match std::fs::metadata(path) {
|
match fs::metadata(path) {
|
||||||
Err(_) => false,
|
Err(_) => false,
|
||||||
Ok(metadata) => is_readable_metadata(&metadata),
|
Ok(metadata) => is_readable_metadata(&metadata),
|
||||||
}
|
}
|
||||||
|
@ -369,7 +369,7 @@ fn is_writable_metadata(metadata: &Metadata) -> bool {
|
||||||
/// Whether the given file or directory is writable.
|
/// Whether the given file or directory is writable.
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
fn is_writable(path: &Path) -> bool {
|
fn is_writable(path: &Path) -> bool {
|
||||||
match std::fs::metadata(path) {
|
match fs::metadata(path) {
|
||||||
Err(_) => false,
|
Err(_) => false,
|
||||||
Ok(metadata) => is_writable_metadata(&metadata),
|
Ok(metadata) => is_writable_metadata(&metadata),
|
||||||
}
|
}
|
||||||
|
@ -391,7 +391,7 @@ fn is_writable(_path: &Path) -> bool {
|
||||||
fn remove_dir_recursive(path: &Path, options: &Options) -> bool {
|
fn remove_dir_recursive(path: &Path, options: &Options) -> bool {
|
||||||
// Special case: if we cannot access the metadata because the
|
// Special case: if we cannot access the metadata because the
|
||||||
// filename is too long, fall back to try
|
// filename is too long, fall back to try
|
||||||
// `std::fs::remove_dir_all()`.
|
// `fs::remove_dir_all()`.
|
||||||
//
|
//
|
||||||
// TODO This is a temporary bandage; we shouldn't need to do this
|
// TODO This is a temporary bandage; we shouldn't need to do this
|
||||||
// at all. Instead of using the full path like "x/y/z", which
|
// at all. Instead of using the full path like "x/y/z", which
|
||||||
|
@ -400,7 +400,7 @@ fn remove_dir_recursive(path: &Path, options: &Options) -> bool {
|
||||||
// path, "z", and know that it is relative to the parent, "x/y".
|
// path, "z", and know that it is relative to the parent, "x/y".
|
||||||
if let Some(s) = path.to_str() {
|
if let Some(s) = path.to_str() {
|
||||||
if s.len() > 1000 {
|
if s.len() > 1000 {
|
||||||
match std::fs::remove_dir_all(path) {
|
match fs::remove_dir_all(path) {
|
||||||
Ok(_) => return false,
|
Ok(_) => return false,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let e = e.map_err_context(|| format!("cannot remove {}", path.quote()));
|
let e = e.map_err_context(|| format!("cannot remove {}", path.quote()));
|
||||||
|
@ -432,7 +432,7 @@ fn remove_dir_recursive(path: &Path, options: &Options) -> bool {
|
||||||
|
|
||||||
// Recursive case: this is a directory.
|
// Recursive case: this is a directory.
|
||||||
let mut error = false;
|
let mut error = false;
|
||||||
match std::fs::read_dir(path) {
|
match fs::read_dir(path) {
|
||||||
Err(e) if e.kind() == std::io::ErrorKind::PermissionDenied => {
|
Err(e) if e.kind() == std::io::ErrorKind::PermissionDenied => {
|
||||||
// This is not considered an error.
|
// This is not considered an error.
|
||||||
}
|
}
|
||||||
|
@ -456,7 +456,7 @@ fn remove_dir_recursive(path: &Path, options: &Options) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try removing the directory itself.
|
// Try removing the directory itself.
|
||||||
match std::fs::remove_dir(path) {
|
match fs::remove_dir(path) {
|
||||||
Err(_) if !error && !is_readable(path) => {
|
Err(_) if !error && !is_readable(path) => {
|
||||||
// For compatibility with GNU test case
|
// For compatibility with GNU test case
|
||||||
// `tests/rm/unread2.sh`, show "Permission denied" in this
|
// `tests/rm/unread2.sh`, show "Permission denied" in this
|
||||||
|
|
|
@ -163,7 +163,7 @@ struct Opts {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn uu_app() -> Command {
|
pub fn uu_app() -> Command {
|
||||||
Command::new(uucore::util_name())
|
Command::new(util_name())
|
||||||
.version(uucore::crate_version!())
|
.version(uucore::crate_version!())
|
||||||
.about(ABOUT)
|
.about(ABOUT)
|
||||||
.override_usage(format_usage(USAGE))
|
.override_usage(format_usage(USAGE))
|
||||||
|
|
|
@ -152,7 +152,7 @@ pub fn uu_app() -> Command {
|
||||||
.short('e')
|
.short('e')
|
||||||
.long(options::ECHO)
|
.long(options::ECHO)
|
||||||
.help("treat each ARG as an input line")
|
.help("treat each ARG as an input line")
|
||||||
.action(clap::ArgAction::SetTrue)
|
.action(ArgAction::SetTrue)
|
||||||
.overrides_with(options::ECHO)
|
.overrides_with(options::ECHO)
|
||||||
.conflicts_with(options::INPUT_RANGE),
|
.conflicts_with(options::INPUT_RANGE),
|
||||||
)
|
)
|
||||||
|
@ -170,7 +170,7 @@ pub fn uu_app() -> Command {
|
||||||
.short('n')
|
.short('n')
|
||||||
.long(options::HEAD_COUNT)
|
.long(options::HEAD_COUNT)
|
||||||
.value_name("COUNT")
|
.value_name("COUNT")
|
||||||
.action(clap::ArgAction::Append)
|
.action(ArgAction::Append)
|
||||||
.help("output at most COUNT lines")
|
.help("output at most COUNT lines")
|
||||||
.value_parser(usize::from_str),
|
.value_parser(usize::from_str),
|
||||||
)
|
)
|
||||||
|
@ -209,7 +209,7 @@ pub fn uu_app() -> Command {
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new(options::FILE_OR_ARGS)
|
Arg::new(options::FILE_OR_ARGS)
|
||||||
.action(clap::ArgAction::Append)
|
.action(ArgAction::Append)
|
||||||
.value_parser(ValueParser::os_string())
|
.value_parser(ValueParser::os_string())
|
||||||
.value_hint(clap::ValueHint::FilePath),
|
.value_hint(clap::ValueHint::FilePath),
|
||||||
)
|
)
|
||||||
|
|
|
@ -90,7 +90,7 @@ fn sleep(args: &[&str]) -> UResult<()> {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.fold(Duration::ZERO, |acc, n| {
|
.fold(Duration::ZERO, |acc, n| {
|
||||||
acc.saturating_add(SaturatingInto::<std::time::Duration>::saturating_into(n))
|
acc.saturating_add(SaturatingInto::<Duration>::saturating_into(n))
|
||||||
});
|
});
|
||||||
|
|
||||||
if arg_error {
|
if arg_error {
|
||||||
|
|
|
@ -50,7 +50,7 @@ fn replace_output_file_in_input_files(
|
||||||
*file = copy.clone().into_os_string();
|
*file = copy.clone().into_os_string();
|
||||||
} else {
|
} else {
|
||||||
let (_file, copy_path) = tmp_dir.next_file()?;
|
let (_file, copy_path) = tmp_dir.next_file()?;
|
||||||
std::fs::copy(file_path, ©_path)
|
fs::copy(file_path, ©_path)
|
||||||
.map_err(|error| SortError::OpenTmpFileFailed { error })?;
|
.map_err(|error| SortError::OpenTmpFileFailed { error })?;
|
||||||
*file = copy_path.clone().into_os_string();
|
*file = copy_path.clone().into_os_string();
|
||||||
copy = Some(copy_path);
|
copy = Some(copy_path);
|
||||||
|
|
|
@ -1152,7 +1152,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
settings.merge_batch_size = parsed_value;
|
settings.merge_batch_size = parsed_value;
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let error_message = if *e.kind() == std::num::IntErrorKind::PosOverflow {
|
let error_message = if *e.kind() == IntErrorKind::PosOverflow {
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
{
|
{
|
||||||
show_error!("--batch-size argument {} too large", n_merge.quote());
|
show_error!("--batch-size argument {} too large", n_merge.quote());
|
||||||
|
@ -1987,7 +1987,7 @@ mod tests {
|
||||||
fn test_line_size() {
|
fn test_line_size() {
|
||||||
// We should make sure to not regress the size of the Line struct because
|
// We should make sure to not regress the size of the Line struct because
|
||||||
// it is unconditional overhead for every line we sort.
|
// it is unconditional overhead for every line we sort.
|
||||||
assert_eq!(std::mem::size_of::<Line>(), 24);
|
assert_eq!(size_of::<Line>(), 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -21,8 +21,8 @@ use std::fmt::{self, Display, Formatter};
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Overflow;
|
pub struct Overflow;
|
||||||
|
|
||||||
impl fmt::Display for Overflow {
|
impl Display for Overflow {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
write!(f, "Overflow")
|
write!(f, "Overflow")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,7 +133,7 @@ pub fn instantiate_current_writer(
|
||||||
.write(true)
|
.write(true)
|
||||||
.create(true)
|
.create(true)
|
||||||
.truncate(true)
|
.truncate(true)
|
||||||
.open(std::path::Path::new(&filename))
|
.open(Path::new(&filename))
|
||||||
.map_err(|_| {
|
.map_err(|_| {
|
||||||
Error::new(
|
Error::new(
|
||||||
ErrorKind::Other,
|
ErrorKind::Other,
|
||||||
|
@ -144,7 +144,7 @@ pub fn instantiate_current_writer(
|
||||||
// re-open file that we previously created to append to it
|
// re-open file that we previously created to append to it
|
||||||
std::fs::OpenOptions::new()
|
std::fs::OpenOptions::new()
|
||||||
.append(true)
|
.append(true)
|
||||||
.open(std::path::Path::new(&filename))
|
.open(Path::new(&filename))
|
||||||
.map_err(|_| {
|
.map_err(|_| {
|
||||||
Error::new(
|
Error::new(
|
||||||
ErrorKind::Other,
|
ErrorKind::Other,
|
||||||
|
|
|
@ -22,7 +22,7 @@ pub fn instantiate_current_writer(
|
||||||
.write(true)
|
.write(true)
|
||||||
.create(true)
|
.create(true)
|
||||||
.truncate(true)
|
.truncate(true)
|
||||||
.open(std::path::Path::new(&filename))
|
.open(Path::new(&filename))
|
||||||
.map_err(|_| {
|
.map_err(|_| {
|
||||||
Error::new(
|
Error::new(
|
||||||
ErrorKind::Other,
|
ErrorKind::Other,
|
||||||
|
@ -33,7 +33,7 @@ pub fn instantiate_current_writer(
|
||||||
// re-open file that we previously created to append to it
|
// re-open file that we previously created to append to it
|
||||||
std::fs::OpenOptions::new()
|
std::fs::OpenOptions::new()
|
||||||
.append(true)
|
.append(true)
|
||||||
.open(std::path::Path::new(&filename))
|
.open(Path::new(&filename))
|
||||||
.map_err(|_| {
|
.map_err(|_| {
|
||||||
Error::new(
|
Error::new(
|
||||||
ErrorKind::Other,
|
ErrorKind::Other,
|
||||||
|
|
|
@ -546,7 +546,7 @@ impl Settings {
|
||||||
/// When using `--filter` option, writing to child command process stdin
|
/// When using `--filter` option, writing to child command process stdin
|
||||||
/// could fail with BrokenPipe error
|
/// could fail with BrokenPipe error
|
||||||
/// It can be safely ignored
|
/// It can be safely ignored
|
||||||
fn ignorable_io_error(error: &std::io::Error, settings: &Settings) -> bool {
|
fn ignorable_io_error(error: &io::Error, settings: &Settings) -> bool {
|
||||||
error.kind() == ErrorKind::BrokenPipe && settings.filter.is_some()
|
error.kind() == ErrorKind::BrokenPipe && settings.filter.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -555,11 +555,7 @@ fn ignorable_io_error(error: &std::io::Error, settings: &Settings) -> bool {
|
||||||
/// If ignorable io error occurs, return number of bytes as if all bytes written
|
/// If ignorable io error occurs, return number of bytes as if all bytes written
|
||||||
/// Should not be used for Kth chunk number sub-strategies
|
/// Should not be used for Kth chunk number sub-strategies
|
||||||
/// as those do not work with `--filter` option
|
/// as those do not work with `--filter` option
|
||||||
fn custom_write<T: Write>(
|
fn custom_write<T: Write>(bytes: &[u8], writer: &mut T, settings: &Settings) -> io::Result<usize> {
|
||||||
bytes: &[u8],
|
|
||||||
writer: &mut T,
|
|
||||||
settings: &Settings,
|
|
||||||
) -> std::io::Result<usize> {
|
|
||||||
match writer.write(bytes) {
|
match writer.write(bytes) {
|
||||||
Ok(n) => Ok(n),
|
Ok(n) => Ok(n),
|
||||||
Err(e) if ignorable_io_error(&e, settings) => Ok(bytes.len()),
|
Err(e) if ignorable_io_error(&e, settings) => Ok(bytes.len()),
|
||||||
|
@ -576,7 +572,7 @@ fn custom_write_all<T: Write>(
|
||||||
bytes: &[u8],
|
bytes: &[u8],
|
||||||
writer: &mut T,
|
writer: &mut T,
|
||||||
settings: &Settings,
|
settings: &Settings,
|
||||||
) -> std::io::Result<bool> {
|
) -> io::Result<bool> {
|
||||||
match writer.write_all(bytes) {
|
match writer.write_all(bytes) {
|
||||||
Ok(()) => Ok(true),
|
Ok(()) => Ok(true),
|
||||||
Err(e) if ignorable_io_error(&e, settings) => Ok(false),
|
Err(e) if ignorable_io_error(&e, settings) => Ok(false),
|
||||||
|
@ -610,7 +606,7 @@ fn get_input_size<R>(
|
||||||
reader: &mut R,
|
reader: &mut R,
|
||||||
buf: &mut Vec<u8>,
|
buf: &mut Vec<u8>,
|
||||||
io_blksize: &Option<u64>,
|
io_blksize: &Option<u64>,
|
||||||
) -> std::io::Result<u64>
|
) -> io::Result<u64>
|
||||||
where
|
where
|
||||||
R: BufRead,
|
R: BufRead,
|
||||||
{
|
{
|
||||||
|
@ -734,7 +730,7 @@ impl<'a> ByteChunkWriter<'a> {
|
||||||
|
|
||||||
impl Write for ByteChunkWriter<'_> {
|
impl Write for ByteChunkWriter<'_> {
|
||||||
/// Implements `--bytes=SIZE`
|
/// Implements `--bytes=SIZE`
|
||||||
fn write(&mut self, mut buf: &[u8]) -> std::io::Result<usize> {
|
fn write(&mut self, mut buf: &[u8]) -> io::Result<usize> {
|
||||||
// If the length of `buf` exceeds the number of bytes remaining
|
// If the length of `buf` exceeds the number of bytes remaining
|
||||||
// in the current chunk, we will need to write to multiple
|
// in the current chunk, we will need to write to multiple
|
||||||
// different underlying writers. In that case, each iteration of
|
// different underlying writers. In that case, each iteration of
|
||||||
|
@ -753,7 +749,7 @@ impl Write for ByteChunkWriter<'_> {
|
||||||
|
|
||||||
// Allocate the new file, since at this point we know there are bytes to be written to it.
|
// Allocate the new file, since at this point we know there are bytes to be written to it.
|
||||||
let filename = self.filename_iterator.next().ok_or_else(|| {
|
let filename = self.filename_iterator.next().ok_or_else(|| {
|
||||||
std::io::Error::new(ErrorKind::Other, "output file suffixes exhausted")
|
io::Error::new(ErrorKind::Other, "output file suffixes exhausted")
|
||||||
})?;
|
})?;
|
||||||
if self.settings.verbose {
|
if self.settings.verbose {
|
||||||
println!("creating file {}", filename.quote());
|
println!("creating file {}", filename.quote());
|
||||||
|
@ -794,7 +790,7 @@ impl Write for ByteChunkWriter<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn flush(&mut self) -> std::io::Result<()> {
|
fn flush(&mut self) -> io::Result<()> {
|
||||||
self.inner.flush()
|
self.inner.flush()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -858,7 +854,7 @@ impl<'a> LineChunkWriter<'a> {
|
||||||
|
|
||||||
impl Write for LineChunkWriter<'_> {
|
impl Write for LineChunkWriter<'_> {
|
||||||
/// Implements `--lines=NUMBER`
|
/// Implements `--lines=NUMBER`
|
||||||
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
|
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||||
// If the number of lines in `buf` exceeds the number of lines
|
// If the number of lines in `buf` exceeds the number of lines
|
||||||
// remaining in the current chunk, we will need to write to
|
// remaining in the current chunk, we will need to write to
|
||||||
// multiple different underlying writers. In that case, each
|
// multiple different underlying writers. In that case, each
|
||||||
|
@ -874,7 +870,7 @@ impl Write for LineChunkWriter<'_> {
|
||||||
if self.num_lines_remaining_in_current_chunk == 0 {
|
if self.num_lines_remaining_in_current_chunk == 0 {
|
||||||
self.num_chunks_written += 1;
|
self.num_chunks_written += 1;
|
||||||
let filename = self.filename_iterator.next().ok_or_else(|| {
|
let filename = self.filename_iterator.next().ok_or_else(|| {
|
||||||
std::io::Error::new(ErrorKind::Other, "output file suffixes exhausted")
|
io::Error::new(ErrorKind::Other, "output file suffixes exhausted")
|
||||||
})?;
|
})?;
|
||||||
if self.settings.verbose {
|
if self.settings.verbose {
|
||||||
println!("creating file {}", filename.quote());
|
println!("creating file {}", filename.quote());
|
||||||
|
@ -898,7 +894,7 @@ impl Write for LineChunkWriter<'_> {
|
||||||
Ok(total_bytes_written)
|
Ok(total_bytes_written)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flush(&mut self) -> std::io::Result<()> {
|
fn flush(&mut self) -> io::Result<()> {
|
||||||
self.inner.flush()
|
self.inner.flush()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1121,7 +1117,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
// In Kth chunk of N mode - we will write to stdout instead of to a file.
|
// In Kth chunk of N mode - we will write to stdout instead of to a file.
|
||||||
let mut stdout_writer = std::io::stdout().lock();
|
let mut stdout_writer = io::stdout().lock();
|
||||||
// In N chunks mode - we will write to `num_chunks` files
|
// In N chunks mode - we will write to `num_chunks` files
|
||||||
let mut out_files: OutFiles = OutFiles::new();
|
let mut out_files: OutFiles = OutFiles::new();
|
||||||
|
|
||||||
|
@ -1247,7 +1243,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
// In Kth chunk of N mode - we will write to stdout instead of to a file.
|
// In Kth chunk of N mode - we will write to stdout instead of to a file.
|
||||||
let mut stdout_writer = std::io::stdout().lock();
|
let mut stdout_writer = io::stdout().lock();
|
||||||
// In N chunks mode - we will write to `num_chunks` files
|
// In N chunks mode - we will write to `num_chunks` files
|
||||||
let mut out_files: OutFiles = OutFiles::new();
|
let mut out_files: OutFiles = OutFiles::new();
|
||||||
|
|
||||||
|
@ -1367,7 +1363,7 @@ where
|
||||||
R: BufRead,
|
R: BufRead,
|
||||||
{
|
{
|
||||||
// In Kth chunk of N mode - we will write to stdout instead of to a file.
|
// In Kth chunk of N mode - we will write to stdout instead of to a file.
|
||||||
let mut stdout_writer = std::io::stdout().lock();
|
let mut stdout_writer = io::stdout().lock();
|
||||||
// In N chunks mode - we will write to `num_chunks` files
|
// In N chunks mode - we will write to `num_chunks` files
|
||||||
let mut out_files: OutFiles = OutFiles::new();
|
let mut out_files: OutFiles = OutFiles::new();
|
||||||
|
|
||||||
|
@ -1414,7 +1410,7 @@ where
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Like `std::io::Lines`, but includes the line ending character.
|
/// Like `io::Lines`, but includes the line ending character.
|
||||||
///
|
///
|
||||||
/// This struct is generally created by calling `lines_with_sep` on a
|
/// This struct is generally created by calling `lines_with_sep` on a
|
||||||
/// reader.
|
/// reader.
|
||||||
|
@ -1427,7 +1423,7 @@ impl<R> Iterator for LinesWithSep<R>
|
||||||
where
|
where
|
||||||
R: BufRead,
|
R: BufRead,
|
||||||
{
|
{
|
||||||
type Item = std::io::Result<Vec<u8>>;
|
type Item = io::Result<Vec<u8>>;
|
||||||
|
|
||||||
/// Read bytes from a buffer up to the requested number of lines.
|
/// Read bytes from a buffer up to the requested number of lines.
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
@ -1464,8 +1460,7 @@ where
|
||||||
// to be overwritten for sure at the beginning of the loop below
|
// to be overwritten for sure at the beginning of the loop below
|
||||||
// because we start with `remaining == 0`, indicating that a new
|
// because we start with `remaining == 0`, indicating that a new
|
||||||
// chunk should start.
|
// chunk should start.
|
||||||
let mut writer: BufWriter<Box<dyn Write>> =
|
let mut writer: BufWriter<Box<dyn Write>> = BufWriter::new(Box::new(io::Cursor::new(vec![])));
|
||||||
BufWriter::new(Box::new(std::io::Cursor::new(vec![])));
|
|
||||||
|
|
||||||
let mut remaining = 0;
|
let mut remaining = 0;
|
||||||
for line in lines_with_sep(reader, settings.separator) {
|
for line in lines_with_sep(reader, settings.separator) {
|
||||||
|
@ -1560,11 +1555,11 @@ fn split(settings: &Settings) -> UResult<()> {
|
||||||
}
|
}
|
||||||
Strategy::Lines(chunk_size) => {
|
Strategy::Lines(chunk_size) => {
|
||||||
let mut writer = LineChunkWriter::new(chunk_size, settings)?;
|
let mut writer = LineChunkWriter::new(chunk_size, settings)?;
|
||||||
match std::io::copy(&mut reader, &mut writer) {
|
match io::copy(&mut reader, &mut writer) {
|
||||||
Ok(_) => Ok(()),
|
Ok(_) => Ok(()),
|
||||||
Err(e) => match e.kind() {
|
Err(e) => match e.kind() {
|
||||||
// TODO Since the writer object controls the creation of
|
// TODO Since the writer object controls the creation of
|
||||||
// new files, we need to rely on the `std::io::Result`
|
// new files, we need to rely on the `io::Result`
|
||||||
// returned by its `write()` method to communicate any
|
// returned by its `write()` method to communicate any
|
||||||
// errors to this calling scope. If a new file cannot be
|
// errors to this calling scope. If a new file cannot be
|
||||||
// created because we have exceeded the number of
|
// created because we have exceeded the number of
|
||||||
|
@ -1578,11 +1573,11 @@ fn split(settings: &Settings) -> UResult<()> {
|
||||||
}
|
}
|
||||||
Strategy::Bytes(chunk_size) => {
|
Strategy::Bytes(chunk_size) => {
|
||||||
let mut writer = ByteChunkWriter::new(chunk_size, settings)?;
|
let mut writer = ByteChunkWriter::new(chunk_size, settings)?;
|
||||||
match std::io::copy(&mut reader, &mut writer) {
|
match io::copy(&mut reader, &mut writer) {
|
||||||
Ok(_) => Ok(()),
|
Ok(_) => Ok(()),
|
||||||
Err(e) => match e.kind() {
|
Err(e) => match e.kind() {
|
||||||
// TODO Since the writer object controls the creation of
|
// TODO Since the writer object controls the creation of
|
||||||
// new files, we need to rely on the `std::io::Result`
|
// new files, we need to rely on the `io::Result`
|
||||||
// returned by its `write()` method to communicate any
|
// returned by its `write()` method to communicate any
|
||||||
// errors to this calling scope. If a new file cannot be
|
// errors to this calling scope. If a new file cannot be
|
||||||
// created because we have exceeded the number of
|
// created because we have exceeded the number of
|
||||||
|
|
|
@ -972,8 +972,7 @@ impl Stater {
|
||||||
'Y' => {
|
'Y' => {
|
||||||
let sec = meta.mtime();
|
let sec = meta.mtime();
|
||||||
let nsec = meta.mtime_nsec();
|
let nsec = meta.mtime_nsec();
|
||||||
let tm =
|
let tm = DateTime::from_timestamp(sec, nsec as u32).unwrap_or_default();
|
||||||
chrono::DateTime::from_timestamp(sec, nsec as u32).unwrap_or_default();
|
|
||||||
let tm: DateTime<Local> = tm.into();
|
let tm: DateTime<Local> = tm.into();
|
||||||
match tm.timestamp_nanos_opt() {
|
match tm.timestamp_nanos_opt() {
|
||||||
None => {
|
None => {
|
||||||
|
@ -1186,7 +1185,7 @@ const PRETTY_DATETIME_FORMAT: &str = "%Y-%m-%d %H:%M:%S.%f %z";
|
||||||
|
|
||||||
fn pretty_time(sec: i64, nsec: i64) -> String {
|
fn pretty_time(sec: i64, nsec: i64) -> String {
|
||||||
// Return the date in UTC
|
// Return the date in UTC
|
||||||
let tm = chrono::DateTime::from_timestamp(sec, nsec as u32).unwrap_or_default();
|
let tm = DateTime::from_timestamp(sec, nsec as u32).unwrap_or_default();
|
||||||
let tm: DateTime<Local> = tm.into();
|
let tm: DateTime<Local> = tm.into();
|
||||||
|
|
||||||
tm.format(PRETTY_DATETIME_FORMAT).to_string()
|
tm.format(PRETTY_DATETIME_FORMAT).to_string()
|
||||||
|
|
|
@ -181,7 +181,7 @@ impl Settings {
|
||||||
settings
|
settings
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from(matches: &clap::ArgMatches) -> UResult<Self> {
|
pub fn from(matches: &ArgMatches) -> UResult<Self> {
|
||||||
// We're parsing --follow, -F and --retry under the following conditions:
|
// We're parsing --follow, -F and --retry under the following conditions:
|
||||||
// * -F sets --retry and --follow=name
|
// * -F sets --retry and --follow=name
|
||||||
// * plain --follow or short -f is the same like specifying --follow=descriptor
|
// * plain --follow or short -f is the same like specifying --follow=descriptor
|
||||||
|
@ -236,7 +236,7 @@ impl Settings {
|
||||||
// * not applied here but it supports customizable time units and provides better error
|
// * not applied here but it supports customizable time units and provides better error
|
||||||
// messages
|
// messages
|
||||||
settings.sleep_sec = match DurationParser::without_time_units().parse(source) {
|
settings.sleep_sec = match DurationParser::without_time_units().parse(source) {
|
||||||
Ok(duration) => SaturatingInto::<std::time::Duration>::saturating_into(duration),
|
Ok(duration) => SaturatingInto::<Duration>::saturating_into(duration),
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
return Err(UUsageError::new(
|
return Err(UUsageError::new(
|
||||||
1,
|
1,
|
||||||
|
|
|
@ -229,7 +229,7 @@ impl Observer {
|
||||||
watcher = Box::new(notify::PollWatcher::new(tx, watcher_config).unwrap());
|
watcher = Box::new(notify::PollWatcher::new(tx, watcher_config).unwrap());
|
||||||
} else {
|
} else {
|
||||||
let tx_clone = tx.clone();
|
let tx_clone = tx.clone();
|
||||||
match notify::RecommendedWatcher::new(tx, notify::Config::default()) {
|
match RecommendedWatcher::new(tx, notify::Config::default()) {
|
||||||
Ok(w) => watcher = Box::new(w),
|
Ok(w) => watcher = Box::new(w),
|
||||||
Err(e) if e.to_string().starts_with("Too many open files") => {
|
Err(e) if e.to_string().starts_with("Too many open files") => {
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -11,11 +11,11 @@ use std::io::Error;
|
||||||
pub type Pid = libc::pid_t;
|
pub type Pid = libc::pid_t;
|
||||||
|
|
||||||
pub struct ProcessChecker {
|
pub struct ProcessChecker {
|
||||||
pid: self::Pid,
|
pid: Pid,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProcessChecker {
|
impl ProcessChecker {
|
||||||
pub fn new(process_id: self::Pid) -> Self {
|
pub fn new(process_id: Pid) -> Self {
|
||||||
Self { pid: process_id }
|
Self { pid: process_id }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ impl Drop for ProcessChecker {
|
||||||
fn drop(&mut self) {}
|
fn drop(&mut self) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn supports_pid_checks(pid: self::Pid) -> bool {
|
pub fn supports_pid_checks(pid: Pid) -> bool {
|
||||||
unsafe { !(libc::kill(pid, 0) != 0 && get_errno() == libc::ENOSYS) }
|
unsafe { !(libc::kill(pid, 0) != 0 && get_errno() == libc::ENOSYS) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ pub struct ProcessChecker {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProcessChecker {
|
impl ProcessChecker {
|
||||||
pub fn new(process_id: self::Pid) -> Self {
|
pub fn new(process_id: Pid) -> Self {
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
let FALSE: BOOL = 0;
|
let FALSE: BOOL = 0;
|
||||||
let h = unsafe { OpenProcess(PROCESS_SYNCHRONIZE, FALSE, process_id) };
|
let h = unsafe { OpenProcess(PROCESS_SYNCHRONIZE, FALSE, process_id) };
|
||||||
|
@ -47,6 +47,6 @@ impl Drop for ProcessChecker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn supports_pid_checks(_pid: self::Pid) -> bool {
|
pub fn supports_pid_checks(_pid: Pid) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
|
@ -163,7 +163,7 @@ fn tail_file(
|
||||||
true,
|
true,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
Err(e) if e.kind() == std::io::ErrorKind::PermissionDenied => {
|
Err(e) if e.kind() == ErrorKind::PermissionDenied => {
|
||||||
observer.add_bad_path(path, input.display_name.as_str(), false)?;
|
observer.add_bad_path(path, input.display_name.as_str(), false)?;
|
||||||
show!(e.map_err_context(|| {
|
show!(e.map_err_context(|| {
|
||||||
format!("cannot open '{}' for reading", input.display_name)
|
format!("cannot open '{}' for reading", input.display_name)
|
||||||
|
@ -290,7 +290,7 @@ fn forwards_thru_file(
|
||||||
reader: &mut impl Read,
|
reader: &mut impl Read,
|
||||||
num_delimiters: u64,
|
num_delimiters: u64,
|
||||||
delimiter: u8,
|
delimiter: u8,
|
||||||
) -> std::io::Result<usize> {
|
) -> io::Result<usize> {
|
||||||
// If num_delimiters == 0, always return 0.
|
// If num_delimiters == 0, always return 0.
|
||||||
if num_delimiters == 0 {
|
if num_delimiters == 0 {
|
||||||
return Ok(0);
|
return Ok(0);
|
||||||
|
@ -405,7 +405,7 @@ fn bounded_tail(file: &mut File, settings: &Settings) {
|
||||||
// Print the target section of the file.
|
// Print the target section of the file.
|
||||||
let stdout = stdout();
|
let stdout = stdout();
|
||||||
let mut stdout = stdout.lock();
|
let mut stdout = stdout.lock();
|
||||||
std::io::copy(file, &mut stdout).unwrap();
|
io::copy(file, &mut stdout).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unbounded_tail<T: Read>(reader: &mut BufReader<T>, settings: &Settings) -> UResult<()> {
|
fn unbounded_tail<T: Read>(reader: &mut BufReader<T>, settings: &Settings) -> UResult<()> {
|
||||||
|
|
|
@ -66,7 +66,7 @@ impl Config {
|
||||||
Some(signal_value) => signal_value,
|
Some(signal_value) => signal_value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => uucore::signals::signal_by_name_or_value("TERM").unwrap(),
|
_ => signal_by_name_or_value("TERM").unwrap(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let kill_after = match options.get_one::<String>(options::KILL_AFTER) {
|
let kill_after = match options.get_one::<String>(options::KILL_AFTER) {
|
||||||
|
|
|
@ -443,7 +443,7 @@ fn touch_file(
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Err(e) = metadata_result {
|
if let Err(e) = metadata_result {
|
||||||
if e.kind() != std::io::ErrorKind::NotFound {
|
if e.kind() != ErrorKind::NotFound {
|
||||||
return Err(e.map_err_context(|| format!("setting times of {}", filename.quote())));
|
return Err(e.map_err_context(|| format!("setting times of {}", filename.quote())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -687,7 +687,7 @@ fn parse_timestamp(s: &str) -> UResult<FileTime> {
|
||||||
|
|
||||||
let local = NaiveDateTime::parse_from_str(&ts, format)
|
let local = NaiveDateTime::parse_from_str(&ts, format)
|
||||||
.map_err(|_| USimpleError::new(1, format!("invalid date ts format {}", ts.quote())))?;
|
.map_err(|_| USimpleError::new(1, format!("invalid date ts format {}", ts.quote())))?;
|
||||||
let LocalResult::Single(mut local) = chrono::Local.from_local_datetime(&local) else {
|
let LocalResult::Single(mut local) = Local.from_local_datetime(&local) else {
|
||||||
return Err(USimpleError::new(
|
return Err(USimpleError::new(
|
||||||
1,
|
1,
|
||||||
format!("invalid date ts format {}", ts.quote()),
|
format!("invalid date ts format {}", ts.quote()),
|
||||||
|
|
|
@ -180,7 +180,7 @@ pub fn uu_app() -> Command {
|
||||||
/// size of the file.
|
/// size of the file.
|
||||||
fn file_truncate(filename: &str, create: bool, size: u64) -> UResult<()> {
|
fn file_truncate(filename: &str, create: bool, size: u64) -> UResult<()> {
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
if let Ok(metadata) = std::fs::metadata(filename) {
|
if let Ok(metadata) = metadata(filename) {
|
||||||
if metadata.file_type().is_fifo() {
|
if metadata.file_type().is_fifo() {
|
||||||
return Err(USimpleError::new(
|
return Err(USimpleError::new(
|
||||||
1,
|
1,
|
||||||
|
|
|
@ -311,7 +311,7 @@ fn next_char_info(uflag: bool, buf: &[u8], byte: usize) -> (CharType, usize, usi
|
||||||
#[allow(clippy::cognitive_complexity)]
|
#[allow(clippy::cognitive_complexity)]
|
||||||
fn unexpand_line(
|
fn unexpand_line(
|
||||||
buf: &mut Vec<u8>,
|
buf: &mut Vec<u8>,
|
||||||
output: &mut BufWriter<std::io::Stdout>,
|
output: &mut BufWriter<Stdout>,
|
||||||
options: &Options,
|
options: &Options,
|
||||||
lastcol: usize,
|
lastcol: usize,
|
||||||
ts: &[usize],
|
ts: &[usize],
|
||||||
|
|
|
@ -805,7 +805,7 @@ fn files0_iter<'a>(
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
// Loop until there is an error; yield that error and then nothing else.
|
// Loop until there is an error; yield that error and then nothing else.
|
||||||
std::iter::from_fn(move || {
|
iter::from_fn(move || {
|
||||||
let next = i.as_mut().and_then(Iterator::next);
|
let next = i.as_mut().and_then(Iterator::next);
|
||||||
if matches!(next, Some(Err(_)) | None) {
|
if matches!(next, Some(Err(_)) | None) {
|
||||||
i = None;
|
i = None;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue