Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -666,7 +666,6 @@ redundant_closure_for_method_calls = "allow" # 125
cast_possible_truncation = "allow" # 122
too_many_lines = "allow" # 101
trivially_copy_pass_by_ref = "allow" # 84
single_match_else = "allow" # 82
cast_possible_wrap = "allow" # 78
cast_sign_loss = "allow" # 70
struct_excessive_bools = "allow" # 68
Expand Down
42 changes: 18 additions & 24 deletions src/uu/cat/src/cat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -639,40 +639,34 @@ fn write_end<W: Write>(

fn write_to_end<W: Write>(in_buf: &[u8], writer: &mut W) -> io::Result<usize> {
// using memchr2 significantly improves performances
match memchr2(b'\n', b'\r', in_buf) {
Some(p) => {
writer.write_all(&in_buf[..p])?;
Ok(p)
}
None => {
writer.write_all(in_buf)?;
Ok(in_buf.len())
}
if let Some(p) = memchr2(b'\n', b'\r', in_buf) {
writer.write_all(&in_buf[..p])?;
Ok(p)
} else {
writer.write_all(in_buf)?;
Ok(in_buf.len())
}
}

fn write_tab_to_end<W: Write>(mut in_buf: &[u8], writer: &mut W) -> io::Result<usize> {
let mut count = 0;
loop {
match in_buf
if let Some(p) = in_buf
.iter()
.position(|c| *c == b'\n' || *c == b'\t' || *c == b'\r')
{
Some(p) => {
writer.write_all(&in_buf[..p])?;
if in_buf[p] == b'\t' {
writer.write_all(b"^I")?;
in_buf = &in_buf[p + 1..];
count += p + 1;
} else {
// b'\n' or b'\r'
return Ok(count + p);
}
}
None => {
writer.write_all(in_buf)?;
return Ok(in_buf.len() + count);
writer.write_all(&in_buf[..p])?;
if in_buf[p] == b'\t' {
writer.write_all(b"^I")?;
in_buf = &in_buf[p + 1..];
count += p + 1;
} else {
// b'\n' or b'\r'
return Ok(count + p);
}
} else {
writer.write_all(in_buf)?;
return Ok(in_buf.len() + count);
}
}
}
Expand Down
114 changes: 56 additions & 58 deletions src/uu/chmod/src/chmod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,42 +272,41 @@ impl Chmoder {
/// Calculate the new mode based on the current mode and the chmod specification.
/// Returns (`new_mode`, `naively_expected_new_mode`) for symbolic modes, or (`new_mode`, `new_mode`) for numeric/reference modes.
fn calculate_new_mode(&self, current_mode: u32, is_dir: bool) -> UResult<(u32, u32)> {
match self.fmode {
Some(mode) => Ok((mode, mode)),
None => {
let cmode_unwrapped = self.cmode.clone().unwrap();
let mut new_mode = current_mode;
let mut naively_expected_new_mode = current_mode;

for mode in cmode_unwrapped.split(',') {
let result = if mode.chars().any(|c| c.is_ascii_digit()) {
mode::parse_numeric(new_mode, mode, is_dir).map(|v| (v, v))
} else {
mode::parse_symbolic(new_mode, mode, mode::get_umask(), is_dir).map(|m| {
// calculate the new mode as if umask was 0
let naive_mode =
mode::parse_symbolic(naively_expected_new_mode, mode, 0, is_dir)
.unwrap(); // we know that mode must be valid, so this cannot fail
(m, naive_mode)
})
};

match result {
Ok((mode, naive_mode)) => {
new_mode = mode;
naively_expected_new_mode = naive_mode;
}
Err(f) => {
return if self.quiet {
Err(ExitCode::new(1))
} else {
Err(USimpleError::new(1, f))
};
}
if let Some(mode) = self.fmode {
Ok((mode, mode))
} else {
let cmode_unwrapped = self.cmode.clone().unwrap();
let mut new_mode = current_mode;
let mut naively_expected_new_mode = current_mode;

for mode in cmode_unwrapped.split(',') {
let result = if mode.chars().any(|c| c.is_ascii_digit()) {
mode::parse_numeric(new_mode, mode, is_dir).map(|v| (v, v))
} else {
mode::parse_symbolic(new_mode, mode, mode::get_umask(), is_dir).map(|m| {
// calculate the new mode as if umask was 0
let naive_mode =
mode::parse_symbolic(naively_expected_new_mode, mode, 0, is_dir)
.unwrap(); // we know that mode must be valid, so this cannot fail
(m, naive_mode)
})
};

match result {
Ok((mode, naive_mode)) => {
new_mode = mode;
naively_expected_new_mode = naive_mode;
}
Err(f) => {
return if self.quiet {
Err(ExitCode::new(1))
} else {
Err(USimpleError::new(1, f))
};
}
}
Ok((new_mode, naively_expected_new_mode))
}
Ok((new_mode, naively_expected_new_mode))
}
}

Expand Down Expand Up @@ -655,32 +654,31 @@ impl Chmoder {
self.calculate_new_mode(fperm, file.is_dir())?;

// Determine how to apply the permissions
match self.fmode {
Some(mode) => self.change_file(fperm, mode, file)?,
None => {
// Special handling for symlinks when not dereferencing
if file.is_symlink() && !dereference {
// TODO: On most Unix systems, symlink permissions are ignored by the kernel,
// so changing them has no effect. We skip this operation for compatibility.
// Note that "chmod without dereferencing" effectively does nothing on symlinks.
if self.verbose {
println!(
"neither symbolic link {} nor referent has been changed",
file.quote()
);
}
} else {
self.change_file(fperm, new_mode, file)?;
}
// if a permission would have been removed if umask was 0, but it wasn't because umask was not 0, print an error and fail
if (new_mode & !naively_expected_new_mode) != 0 {
return Err(ChmodError::NewPermissions(
file.into(),
display_permissions_unix(new_mode as mode_t, false),
display_permissions_unix(naively_expected_new_mode as mode_t, false),
)
.into());
if let Some(mode) = self.fmode {
self.change_file(fperm, mode, file)?;
} else {
// Special handling for symlinks when not dereferencing
if file.is_symlink() && !dereference {
// TODO: On most Unix systems, symlink permissions are ignored by the kernel,
// so changing them has no effect. We skip this operation for compatibility.
// Note that "chmod without dereferencing" effectively does nothing on symlinks.
if self.verbose {
println!(
"neither symbolic link {} nor referent has been changed",
file.quote()
);
}
} else {
self.change_file(fperm, new_mode, file)?;
}
// if a permission would have been removed if umask was 0, but it wasn't because umask was not 0, print an error and fail
if (new_mode & !naively_expected_new_mode) != 0 {
return Err(ChmodError::NewPermissions(
file.into(),
display_permissions_unix(new_mode as mode_t, false),
display_permissions_unix(naively_expected_new_mode as mode_t, false),
)
.into());
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/uu/cp/src/cp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -828,12 +828,12 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let (sources, target) = parse_path_args(paths, &options)?;

if let Err(error) = copy(&sources, &target, &options) {
match error {
if let CpError::NotAllFilesCopied = error {
// Error::NotAllFilesCopied is non-fatal, but the error
// code should still be EXIT_ERR as does GNU cp
CpError::NotAllFilesCopied => {}
} else {
// Else we caught a fatal bubbled-up error, log it to stderr
_ => show_error!("{error}"),
show_error!("{error}");
}
set_exit_code(EXIT_ERR);
}
Expand Down
51 changes: 23 additions & 28 deletions src/uu/cp/src/platform/macos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,37 +85,32 @@ pub(crate) fn copy_on_write(
if raw_pfn.is_null() || error != 0 {
// clonefile(2) is either not supported or it errored out (possibly because the FS does not
// support COW).
match reflink_mode {
ReflinkMode::Always => {
return Err(translate!("cp-error-failed-to-clone", "source" => source.quote(), "dest" => dest.quote(), "error" => error)
if reflink_mode == ReflinkMode::Always {
return Err(translate!("cp-error-failed-to-clone", "source" => source.quote(), "dest" => dest.quote(), "error" => error)
.into());
}
_ => {
copy_debug.reflink = OffloadReflinkDebug::Yes;
if source_is_stream {
let mut src_file = File::open(source)?;
let mode = 0o622 & !get_umask();
let mut dst_file = OpenOptions::new()
.create(true)
.write(true)
.mode(mode)
.open(dest)?;

let dest_is_stream = is_stream(&dst_file.metadata()?);
if !dest_is_stream {
// `copy_stream` doesn't clear the dest file, if dest is not a stream, we should clear it manually.
dst_file.set_len(0)?;
}
}
copy_debug.reflink = OffloadReflinkDebug::Yes;
if source_is_stream {
let mut src_file = File::open(source)?;
let mode = 0o622 & !get_umask();
let mut dst_file = OpenOptions::new()
.create(true)
.write(true)
.mode(mode)
.open(dest)?;

buf_copy::copy_stream(&mut src_file, &mut dst_file)
.map_err(|_| std::io::Error::from(std::io::ErrorKind::Other))
.map_err(|e| CpError::IoErrContext(e, context.to_owned()))?
} else {
fs::copy(source, dest)
.map_err(|e| CpError::IoErrContext(e, context.to_owned()))?
}
let dest_is_stream = is_stream(&dst_file.metadata()?);
if !dest_is_stream {
// `copy_stream` doesn't clear the dest file, if dest is not a stream, we should clear it manually.
dst_file.set_len(0)?;
}
};

buf_copy::copy_stream(&mut src_file, &mut dst_file)
.map_err(|_| std::io::Error::from(std::io::ErrorKind::Other))
.map_err(|e| CpError::IoErrContext(e, context.to_owned()))?;
} else {
fs::copy(source, dest).map_err(|e| CpError::IoErrContext(e, context.to_owned()))?;
}
}

Ok(copy_debug)
Expand Down
15 changes: 5 additions & 10 deletions src/uu/csplit/src/csplit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@
/// Some [`io::Error`] may occur when attempting to write the line.
fn writeln(&mut self, line: &str) -> io::Result<()> {
if !self.dev_null {
match self.current_writer {

Check failure on line 294 in src/uu/csplit/src/csplit.rs

View workflow job for this annotation

GitHub Actions / Style and Lint (unix)

ERROR: `cargo clippy`: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` (file:'src/uu/csplit/src/csplit.rs', line:294)
Some(ref mut current_writer) => {
let bytes = line.as_bytes();
current_writer.write_all(bytes)?;
Expand Down Expand Up @@ -454,16 +454,11 @@

// write the extra lines required by the offset
while offset > 0 {
match input_iter.next() {
Some((_, line)) => {
self.writeln(&line?)?;
}
None => {
self.finish_split()?;
return Err(CsplitError::LineOutOfRange(
pattern_as_str.to_string(),
));
}
if let Some((_, line)) = input_iter.next() {
self.writeln(&line?)?;
} else {
self.finish_split()?;
return Err(CsplitError::LineOutOfRange(pattern_as_str.to_string()));
}
offset -= 1;
}
Expand Down
21 changes: 9 additions & 12 deletions src/uu/csplit/src/patterns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,21 +71,18 @@ impl Iterator for ExecutePatternIter {
type Item = (Option<usize>, usize);

fn next(&mut self) -> Option<(Option<usize>, usize)> {
match self.max {
if let Some(m) = self.max {
// iterate until m is reached
Some(m) => {
if self.cur == m {
None
} else {
self.cur += 1;
Some((self.max, self.cur))
}
}
// no limit, just increment a counter
None => {
if self.cur == m {
None
} else {
self.cur += 1;
Some((None, self.cur))
Some((self.max, self.cur))
}
} else {
// no limit, just increment a counter
self.cur += 1;
Some((None, self.cur))
}
}
}
Expand Down
Loading
Loading