mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-29 20:17:45 +00:00
Merge branch 'master' of https://github.com/uutils/coreutils into cp/close-fd
This commit is contained in:
commit
dfaaa8c787
5 changed files with 59 additions and 34 deletions
|
@ -1261,17 +1261,16 @@ fn copy_helper(source: &Path, dest: &Path, options: &Options) -> CopyResult<()>
|
|||
fn copy_on_write_linux(source: &Path, dest: &Path, mode: ReflinkMode) -> CopyResult<()> {
|
||||
debug_assert!(mode != ReflinkMode::Never);
|
||||
|
||||
let src_file = File::open(source).unwrap().as_raw_fd();
|
||||
let src_file = File::open(source).context(&*context_for(source, dest))?;
|
||||
let dst_file = OpenOptions::new()
|
||||
.write(true)
|
||||
.truncate(false)
|
||||
.create(true)
|
||||
.open(dest)
|
||||
.unwrap()
|
||||
.as_raw_fd();
|
||||
.context(&*context_for(source, dest))?;
|
||||
match mode {
|
||||
ReflinkMode::Always => unsafe {
|
||||
let result = ficlone(dst_file, src_file as *const i32);
|
||||
let result = ficlone(dst_file.as_raw_fd(), src_file.as_raw_fd() as *const i32);
|
||||
if result != 0 {
|
||||
return Err(format!(
|
||||
"failed to clone {:?} from {:?}: {}",
|
||||
|
@ -1285,7 +1284,7 @@ fn copy_on_write_linux(source: &Path, dest: &Path, mode: ReflinkMode) -> CopyRes
|
|||
}
|
||||
},
|
||||
ReflinkMode::Auto => unsafe {
|
||||
let result = ficlone(dst_file, src_file as *const i32);
|
||||
let result = ficlone(dst_file.as_raw_fd(), src_file.as_raw_fd() as *const i32);
|
||||
if result != 0 {
|
||||
fs::copy(source, dest).context(&*context_for(source, dest))?;
|
||||
}
|
||||
|
|
|
@ -62,7 +62,6 @@ impl Number {
|
|||
|
||||
impl FromStr for Number {
|
||||
type Err = String;
|
||||
/// Tries to parse this string as a BigInt, or if that fails as an f64.
|
||||
fn from_str(mut s: &str) -> Result<Self, Self::Err> {
|
||||
if s.starts_with('+') {
|
||||
s = &s[1..];
|
||||
|
@ -71,10 +70,16 @@ impl FromStr for Number {
|
|||
match s.parse::<BigInt>() {
|
||||
Ok(n) => Ok(Number::BigInt(n)),
|
||||
Err(_) => match s.parse::<f64>() {
|
||||
Ok(n) => Ok(Number::F64(n)),
|
||||
Err(e) => Err(format!(
|
||||
"seq: invalid floating point argument `{}`: {}",
|
||||
s, e
|
||||
Ok(value) if value.is_nan() => Err(format!(
|
||||
"invalid 'not-a-number' argument: '{}'\nTry '{} --help' for more information.",
|
||||
s,
|
||||
executable!(),
|
||||
)),
|
||||
Ok(value) => Ok(Number::F64(value)),
|
||||
Err(_) => Err(format!(
|
||||
"invalid floating point argument: '{}'\nTry '{} --help' for more information.",
|
||||
s,
|
||||
executable!(),
|
||||
)),
|
||||
},
|
||||
}
|
||||
|
@ -136,13 +141,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
|||
let dec = slice.find('.').unwrap_or(len);
|
||||
largest_dec = len - dec;
|
||||
padding = dec;
|
||||
match slice.parse() {
|
||||
Ok(n) => n,
|
||||
Err(s) => {
|
||||
show_error!("{}", s);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return_if_err!(1, slice.parse())
|
||||
} else {
|
||||
Number::BigInt(BigInt::one())
|
||||
};
|
||||
|
@ -152,30 +151,22 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
|||
let dec = slice.find('.').unwrap_or(len);
|
||||
largest_dec = cmp::max(largest_dec, len - dec);
|
||||
padding = cmp::max(padding, dec);
|
||||
match slice.parse() {
|
||||
Ok(n) => n,
|
||||
Err(s) => {
|
||||
show_error!("{}", s);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return_if_err!(1, slice.parse())
|
||||
} else {
|
||||
Number::BigInt(BigInt::one())
|
||||
};
|
||||
if increment.is_zero() {
|
||||
show_error!("increment value: '{}'", numbers[1]);
|
||||
show_error!(
|
||||
"invalid Zero increment value: '{}'\nTry '{} --help' for more information.",
|
||||
numbers[1],
|
||||
executable!()
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
let last = {
|
||||
let slice = numbers[numbers.len() - 1];
|
||||
padding = cmp::max(padding, slice.find('.').unwrap_or_else(|| slice.len()));
|
||||
match slice.parse::<Number>() {
|
||||
Ok(n) => n,
|
||||
Err(s) => {
|
||||
show_error!("{}", s);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return_if_err!(1, slice.parse())
|
||||
};
|
||||
if largest_dec > 0 {
|
||||
largest_dec -= 1;
|
||||
|
|
|
@ -7,6 +7,8 @@ use std::fs::set_permissions;
|
|||
#[cfg(not(windows))]
|
||||
use std::os::unix::fs;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
#[cfg(windows)]
|
||||
use std::os::windows::fs::symlink_file;
|
||||
|
||||
|
@ -1257,3 +1259,20 @@ fn test_cp_reflink_bad() {
|
|||
.fails()
|
||||
.stderr_contains("invalid argument");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(target_os = "linux")]
|
||||
fn test_cp_reflink_insufficient_permission() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
|
||||
at.make_file("unreadable")
|
||||
.set_permissions(PermissionsExt::from_mode(0o000))
|
||||
.unwrap();
|
||||
|
||||
ucmd.arg("-r")
|
||||
.arg("--reflink=auto")
|
||||
.arg("unreadable")
|
||||
.arg(TEST_EXISTING_FILE)
|
||||
.fails()
|
||||
.stderr_only("cp: 'unreadable' -> 'existing_file.txt': Permission denied (os error 13)");
|
||||
}
|
||||
|
|
|
@ -1,5 +1,21 @@
|
|||
use crate::common::util::*;
|
||||
|
||||
#[test]
|
||||
fn test_rejects_nan() {
|
||||
new_ucmd!()
|
||||
.args(&["NaN"])
|
||||
.fails()
|
||||
.stderr_only("seq: invalid 'not-a-number' argument: 'NaN'\nTry 'seq --help' for more information.");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rejects_non_floats() {
|
||||
new_ucmd!()
|
||||
.args(&["foo"])
|
||||
.fails()
|
||||
.stderr_only("seq: invalid floating point argument: 'foo'\nTry 'seq --help' for more information.");
|
||||
}
|
||||
|
||||
// ---- Tests for the big integer based path ----
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -50,14 +50,14 @@ macro_rules! new_ucmd {
|
|||
/// Convenience macro for acquiring a [`UCommand`] builder and a test path.
|
||||
///
|
||||
/// Returns a tuple containing the following:
|
||||
/// - an [`AsPath`] that points to a unique temporary test directory
|
||||
/// - an [`AtPath`] that points to a unique temporary test directory
|
||||
/// - a [`UCommand`] builder for invoking the binary to be tested
|
||||
///
|
||||
/// This macro is intended for quick, single-call tests. For more complex tests
|
||||
/// that require multiple invocations of the tested binary, see [`TestScenario`]
|
||||
///
|
||||
/// [`UCommand`]: crate::tests::common::util::UCommand
|
||||
/// [`AsPath`]: crate::tests::common::util::AsPath
|
||||
/// [`AtPath`]: crate::tests::common::util::AtPath
|
||||
/// [`TestScenario]: crate::tests::common::util::TestScenario
|
||||
#[macro_export]
|
||||
macro_rules! at_and_ucmd {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue