mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 19:47:45 +00:00
cp: add support of cp --debug
This commit is contained in:
parent
e295cb7acb
commit
f2006a9a6b
5 changed files with 391 additions and 16 deletions
|
@ -229,10 +229,79 @@ pub struct Options {
|
||||||
backup_suffix: String,
|
backup_suffix: String,
|
||||||
target_dir: Option<PathBuf>,
|
target_dir: Option<PathBuf>,
|
||||||
update: UpdateMode,
|
update: UpdateMode,
|
||||||
|
debug: bool,
|
||||||
verbose: bool,
|
verbose: bool,
|
||||||
progress_bar: bool,
|
progress_bar: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Enum representing various debug states of the offload and reflink actions.
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[allow(dead_code)] // All of them are used on Linux
|
||||||
|
enum OffloadReflinkDebug {
|
||||||
|
Unknown,
|
||||||
|
No,
|
||||||
|
Yes,
|
||||||
|
Avoided,
|
||||||
|
Unsupported,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Enum representing various debug states of the sparse detection.
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[allow(dead_code)] // silent for now until we use them
|
||||||
|
enum SparseDebug {
|
||||||
|
Unknown,
|
||||||
|
No,
|
||||||
|
Zeros,
|
||||||
|
SeekHole,
|
||||||
|
SeekHoleZeros,
|
||||||
|
Unsupported,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Struct that contains the debug state for each action in a file copy operation.
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct CopyDebug {
|
||||||
|
offload: OffloadReflinkDebug,
|
||||||
|
reflink: OffloadReflinkDebug,
|
||||||
|
sparse_detection: SparseDebug,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OffloadReflinkDebug {
|
||||||
|
fn to_string(&self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
Self::No => "no",
|
||||||
|
Self::Yes => "yes",
|
||||||
|
Self::Avoided => "avoided",
|
||||||
|
Self::Unsupported => "unsupported",
|
||||||
|
Self::Unknown => "unknown",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SparseDebug {
|
||||||
|
fn to_string(&self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
Self::No => "no",
|
||||||
|
Self::Zeros => "zeros",
|
||||||
|
Self::SeekHole => "SEEK_HOLE",
|
||||||
|
Self::SeekHoleZeros => "SEEK_HOLE + zeros",
|
||||||
|
Self::Unsupported => "unsupported",
|
||||||
|
Self::Unknown => "unknown",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This function prints the debug information of a file copy operation if
|
||||||
|
/// no hard link or symbolic link is required, and data copy is required.
|
||||||
|
/// It prints the debug information of the offload, reflink, and sparse detection actions.
|
||||||
|
fn show_debug(copy_debug: &CopyDebug) {
|
||||||
|
println!(
|
||||||
|
"copy offload: {}, reflink: {}, sparse detection: {}",
|
||||||
|
copy_debug.offload.to_string(),
|
||||||
|
copy_debug.reflink.to_string(),
|
||||||
|
copy_debug.sparse_detection.to_string(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const ABOUT: &str = help_about!("cp.md");
|
const ABOUT: &str = help_about!("cp.md");
|
||||||
const USAGE: &str = help_usage!("cp.md");
|
const USAGE: &str = help_usage!("cp.md");
|
||||||
const AFTER_HELP: &str = help_section!("after help", "cp.md");
|
const AFTER_HELP: &str = help_section!("after help", "cp.md");
|
||||||
|
@ -269,6 +338,7 @@ mod options {
|
||||||
pub const STRIP_TRAILING_SLASHES: &str = "strip-trailing-slashes";
|
pub const STRIP_TRAILING_SLASHES: &str = "strip-trailing-slashes";
|
||||||
pub const SYMBOLIC_LINK: &str = "symbolic-link";
|
pub const SYMBOLIC_LINK: &str = "symbolic-link";
|
||||||
pub const TARGET_DIRECTORY: &str = "target-directory";
|
pub const TARGET_DIRECTORY: &str = "target-directory";
|
||||||
|
pub const DEBUG: &str = "debug";
|
||||||
pub const VERBOSE: &str = "verbose";
|
pub const VERBOSE: &str = "verbose";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -361,6 +431,12 @@ pub fn uu_app() -> Command {
|
||||||
.help("remove any trailing slashes from each SOURCE argument")
|
.help("remove any trailing slashes from each SOURCE argument")
|
||||||
.action(ArgAction::SetTrue),
|
.action(ArgAction::SetTrue),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new(options::DEBUG)
|
||||||
|
.long(options::DEBUG)
|
||||||
|
.help("explain how a file is copied. Implies -v")
|
||||||
|
.action(ArgAction::SetTrue),
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new(options::VERBOSE)
|
Arg::new(options::VERBOSE)
|
||||||
.short('v')
|
.short('v')
|
||||||
|
@ -831,7 +907,8 @@ impl Options {
|
||||||
one_file_system: matches.get_flag(options::ONE_FILE_SYSTEM),
|
one_file_system: matches.get_flag(options::ONE_FILE_SYSTEM),
|
||||||
parents: matches.get_flag(options::PARENTS),
|
parents: matches.get_flag(options::PARENTS),
|
||||||
update: update_mode,
|
update: update_mode,
|
||||||
verbose: matches.get_flag(options::VERBOSE),
|
debug: matches.get_flag(options::DEBUG),
|
||||||
|
verbose: matches.get_flag(options::VERBOSE) || matches.get_flag(options::DEBUG),
|
||||||
strip_trailing_slashes: matches.get_flag(options::STRIP_TRAILING_SLASHES),
|
strip_trailing_slashes: matches.get_flag(options::STRIP_TRAILING_SLASHES),
|
||||||
reflink_mode: {
|
reflink_mode: {
|
||||||
if let Some(reflink) = matches.get_one::<String>(options::REFLINK) {
|
if let Some(reflink) = matches.get_one::<String>(options::REFLINK) {
|
||||||
|
@ -1745,7 +1822,7 @@ fn copy_helper(
|
||||||
} else if source_is_symlink {
|
} else if source_is_symlink {
|
||||||
copy_link(source, dest, symlinked_files)?;
|
copy_link(source, dest, symlinked_files)?;
|
||||||
} else {
|
} else {
|
||||||
copy_on_write(
|
let copy_debug = copy_on_write(
|
||||||
source,
|
source,
|
||||||
dest,
|
dest,
|
||||||
options.reflink_mode,
|
options.reflink_mode,
|
||||||
|
@ -1754,6 +1831,10 @@ fn copy_helper(
|
||||||
#[cfg(any(target_os = "linux", target_os = "android", target_os = "macos"))]
|
#[cfg(any(target_os = "linux", target_os = "android", target_os = "macos"))]
|
||||||
source_is_fifo,
|
source_is_fifo,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
if !options.attributes_only && options.debug {
|
||||||
|
show_debug(©_debug);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -13,7 +13,7 @@ use quick_error::ResultExt;
|
||||||
|
|
||||||
use uucore::mode::get_umask;
|
use uucore::mode::get_umask;
|
||||||
|
|
||||||
use crate::{CopyResult, ReflinkMode, SparseMode};
|
use crate::{CopyDebug, CopyResult, OffloadReflinkDebug, ReflinkMode, SparseDebug, SparseMode};
|
||||||
|
|
||||||
// From /usr/include/linux/fs.h:
|
// From /usr/include/linux/fs.h:
|
||||||
// #define FICLONE _IOW(0x94, 9, int)
|
// #define FICLONE _IOW(0x94, 9, int)
|
||||||
|
@ -145,24 +145,51 @@ pub(crate) fn copy_on_write(
|
||||||
sparse_mode: SparseMode,
|
sparse_mode: SparseMode,
|
||||||
context: &str,
|
context: &str,
|
||||||
source_is_fifo: bool,
|
source_is_fifo: bool,
|
||||||
) -> CopyResult<()> {
|
) -> CopyResult<CopyDebug> {
|
||||||
|
let mut copy_debug = CopyDebug {
|
||||||
|
offload: OffloadReflinkDebug::Unknown,
|
||||||
|
reflink: OffloadReflinkDebug::Unsupported,
|
||||||
|
sparse_detection: SparseDebug::No,
|
||||||
|
};
|
||||||
|
|
||||||
let result = match (reflink_mode, sparse_mode) {
|
let result = match (reflink_mode, sparse_mode) {
|
||||||
(ReflinkMode::Never, SparseMode::Always) => sparse_copy(source, dest),
|
(ReflinkMode::Never, SparseMode::Always) => {
|
||||||
(ReflinkMode::Never, _) => std::fs::copy(source, dest).map(|_| ()),
|
copy_debug.sparse_detection = SparseDebug::Zeros;
|
||||||
(ReflinkMode::Auto, SparseMode::Always) => sparse_copy(source, dest),
|
copy_debug.offload = OffloadReflinkDebug::Avoided;
|
||||||
|
copy_debug.reflink = OffloadReflinkDebug::No;
|
||||||
|
sparse_copy(source, dest)
|
||||||
|
}
|
||||||
|
(ReflinkMode::Never, _) => {
|
||||||
|
copy_debug.sparse_detection = SparseDebug::No;
|
||||||
|
copy_debug.reflink = OffloadReflinkDebug::No;
|
||||||
|
std::fs::copy(source, dest).map(|_| ())
|
||||||
|
}
|
||||||
|
(ReflinkMode::Auto, SparseMode::Always) => {
|
||||||
|
copy_debug.offload = OffloadReflinkDebug::Avoided;
|
||||||
|
copy_debug.sparse_detection = SparseDebug::Zeros;
|
||||||
|
copy_debug.reflink = OffloadReflinkDebug::Unsupported;
|
||||||
|
sparse_copy(source, dest)
|
||||||
|
}
|
||||||
|
|
||||||
(ReflinkMode::Auto, _) => {
|
(ReflinkMode::Auto, _) => {
|
||||||
|
copy_debug.sparse_detection = SparseDebug::No;
|
||||||
|
copy_debug.reflink = OffloadReflinkDebug::Unsupported;
|
||||||
if source_is_fifo {
|
if source_is_fifo {
|
||||||
copy_fifo_contents(source, dest).map(|_| ())
|
copy_fifo_contents(source, dest).map(|_| ())
|
||||||
} else {
|
} else {
|
||||||
clone(source, dest, CloneFallback::FSCopy)
|
clone(source, dest, CloneFallback::FSCopy)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(ReflinkMode::Always, SparseMode::Auto) => clone(source, dest, CloneFallback::Error),
|
(ReflinkMode::Always, SparseMode::Auto) => {
|
||||||
|
copy_debug.sparse_detection = SparseDebug::No;
|
||||||
|
copy_debug.reflink = OffloadReflinkDebug::Yes;
|
||||||
|
|
||||||
|
clone(source, dest, CloneFallback::Error)
|
||||||
|
}
|
||||||
(ReflinkMode::Always, _) => {
|
(ReflinkMode::Always, _) => {
|
||||||
return Err("`--reflink=always` can be used only with --sparse=auto".into())
|
return Err("`--reflink=always` can be used only with --sparse=auto".into())
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
result.context(context)?;
|
result.context(context)?;
|
||||||
Ok(())
|
Ok(copy_debug)
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ use std::path::Path;
|
||||||
|
|
||||||
use quick_error::ResultExt;
|
use quick_error::ResultExt;
|
||||||
|
|
||||||
use crate::{CopyResult, ReflinkMode, SparseMode};
|
use crate::{CopyDebug, CopyResult, OffloadReflinkDebug, ReflinkMode, SparseDebug, SparseMode};
|
||||||
|
|
||||||
/// Copies `source` to `dest` using copy-on-write if possible.
|
/// Copies `source` to `dest` using copy-on-write if possible.
|
||||||
///
|
///
|
||||||
|
@ -24,10 +24,15 @@ pub(crate) fn copy_on_write(
|
||||||
sparse_mode: SparseMode,
|
sparse_mode: SparseMode,
|
||||||
context: &str,
|
context: &str,
|
||||||
source_is_fifo: bool,
|
source_is_fifo: bool,
|
||||||
) -> CopyResult<()> {
|
) -> CopyResult<CopyDebug> {
|
||||||
if sparse_mode != SparseMode::Auto {
|
if sparse_mode != SparseMode::Auto {
|
||||||
return Err("--sparse is only supported on linux".to_string().into());
|
return Err("--sparse is only supported on linux".to_string().into());
|
||||||
}
|
}
|
||||||
|
let mut copy_debug = CopyDebug {
|
||||||
|
offload: OffloadReflinkDebug::Unknown,
|
||||||
|
reflink: OffloadReflinkDebug::Unsupported,
|
||||||
|
sparse_detection: SparseDebug::Unsupported,
|
||||||
|
};
|
||||||
|
|
||||||
// Extract paths in a form suitable to be passed to a syscall.
|
// Extract paths in a form suitable to be passed to a syscall.
|
||||||
// The unwrap() is safe because they come from the command-line and so contain non nul
|
// The unwrap() is safe because they come from the command-line and so contain non nul
|
||||||
|
@ -72,6 +77,7 @@ pub(crate) fn copy_on_write(
|
||||||
return Err(format!("failed to clone {source:?} from {dest:?}: {error}").into())
|
return Err(format!("failed to clone {source:?} from {dest:?}: {error}").into())
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
copy_debug.reflink = OffloadReflinkDebug::Yes;
|
||||||
if source_is_fifo {
|
if source_is_fifo {
|
||||||
let mut src_file = File::open(source)?;
|
let mut src_file = File::open(source)?;
|
||||||
let mut dst_file = File::create(dest)?;
|
let mut dst_file = File::create(dest)?;
|
||||||
|
@ -83,5 +89,5 @@ pub(crate) fn copy_on_write(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(copy_debug)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ use std::path::Path;
|
||||||
|
|
||||||
use quick_error::ResultExt;
|
use quick_error::ResultExt;
|
||||||
|
|
||||||
use crate::{CopyResult, ReflinkMode, SparseMode};
|
use crate::{CopyDebug, CopyResult, OffloadReflinkDebug, ReflinkMode, SparseDebug, SparseMode};
|
||||||
|
|
||||||
/// Copies `source` to `dest` for systems without copy-on-write
|
/// Copies `source` to `dest` for systems without copy-on-write
|
||||||
pub(crate) fn copy_on_write(
|
pub(crate) fn copy_on_write(
|
||||||
|
@ -17,7 +17,7 @@ pub(crate) fn copy_on_write(
|
||||||
reflink_mode: ReflinkMode,
|
reflink_mode: ReflinkMode,
|
||||||
sparse_mode: SparseMode,
|
sparse_mode: SparseMode,
|
||||||
context: &str,
|
context: &str,
|
||||||
) -> CopyResult<()> {
|
) -> CopyResult<CopyDebug> {
|
||||||
if reflink_mode != ReflinkMode::Never {
|
if reflink_mode != ReflinkMode::Never {
|
||||||
return Err("--reflink is only supported on linux and macOS"
|
return Err("--reflink is only supported on linux and macOS"
|
||||||
.to_string()
|
.to_string()
|
||||||
|
@ -26,8 +26,12 @@ pub(crate) fn copy_on_write(
|
||||||
if sparse_mode != SparseMode::Auto {
|
if sparse_mode != SparseMode::Auto {
|
||||||
return Err("--sparse is only supported on linux".to_string().into());
|
return Err("--sparse is only supported on linux".to_string().into());
|
||||||
}
|
}
|
||||||
|
let copy_debug = CopyDebug {
|
||||||
|
offload: OffloadReflinkDebug::Unsupported,
|
||||||
|
reflink: OffloadReflinkDebug::Unsupported,
|
||||||
|
sparse_detection: SparseDebug::Unsupported,
|
||||||
|
};
|
||||||
fs::copy(source, dest).context(context)?;
|
fs::copy(source, dest).context(context)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(copy_debug)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2909,3 +2909,260 @@ fn test_cp_archive_on_directory_ending_dot() {
|
||||||
ucmd.args(&["-a", "dir1/.", "dir2"]).succeeds();
|
ucmd.args(&["-a", "dir1/.", "dir2"]).succeeds();
|
||||||
assert!(at.file_exists("dir2/file"));
|
assert!(at.file_exists("dir2/file"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_cp_debug_default() {
|
||||||
|
let ts = TestScenario::new(util_name!());
|
||||||
|
let at = &ts.fixtures;
|
||||||
|
at.touch("a");
|
||||||
|
let result = ts.ucmd().arg("--debug").arg("a").arg("b").succeeds();
|
||||||
|
|
||||||
|
let stdout_str = result.stdout_str();
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
if !stdout_str
|
||||||
|
.contains("copy offload: unknown, reflink: unsupported, sparse detection: unsupported")
|
||||||
|
{
|
||||||
|
println!("Failure: stdout was \n{stdout_str}");
|
||||||
|
assert!(false);
|
||||||
|
}
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
if !stdout_str.contains("copy offload: unknown, reflink: unsupported, sparse detection: no") {
|
||||||
|
println!("Failure: stdout was \n{stdout_str}");
|
||||||
|
assert!(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
if !stdout_str
|
||||||
|
.contains("copy offload: unsupported, reflink: unsupported, sparse detection: unsupported")
|
||||||
|
{
|
||||||
|
println!("Failure: stdout was \n{stdout_str}");
|
||||||
|
assert!(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_cp_debug_multiple_default() {
|
||||||
|
let ts = TestScenario::new(util_name!());
|
||||||
|
let at = &ts.fixtures;
|
||||||
|
let dir = "dir";
|
||||||
|
at.touch("a");
|
||||||
|
at.touch("b");
|
||||||
|
at.mkdir(dir);
|
||||||
|
let result = ts
|
||||||
|
.ucmd()
|
||||||
|
.arg("--debug")
|
||||||
|
.arg("a")
|
||||||
|
.arg("b")
|
||||||
|
.arg(dir)
|
||||||
|
.succeeds();
|
||||||
|
|
||||||
|
let stdout_str = result.stdout_str();
|
||||||
|
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
{
|
||||||
|
if !stdout_str
|
||||||
|
.contains("copy offload: unknown, reflink: unsupported, sparse detection: unsupported")
|
||||||
|
{
|
||||||
|
println!("Failure: stdout was \n{stdout_str}");
|
||||||
|
assert!(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// two files, two occurrences
|
||||||
|
assert_eq!(
|
||||||
|
result
|
||||||
|
.stdout_str()
|
||||||
|
.matches(
|
||||||
|
"copy offload: unknown, reflink: unsupported, sparse detection: unsupported"
|
||||||
|
)
|
||||||
|
.count(),
|
||||||
|
2
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
{
|
||||||
|
if !stdout_str.contains("copy offload: unknown, reflink: unsupported, sparse detection: no")
|
||||||
|
{
|
||||||
|
println!("Failure: stdout was \n{stdout_str}");
|
||||||
|
assert!(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// two files, two occurrences
|
||||||
|
assert_eq!(
|
||||||
|
result
|
||||||
|
.stdout_str()
|
||||||
|
.matches("copy offload: unknown, reflink: unsupported, sparse detection: no")
|
||||||
|
.count(),
|
||||||
|
2
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
{
|
||||||
|
if !stdout_str.contains(
|
||||||
|
"copy offload: unsupported, reflink: unsupported, sparse detection: unsupported",
|
||||||
|
) {
|
||||||
|
println!("Failure: stdout was \n{stdout_str}");
|
||||||
|
assert!(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// two files, two occurrences
|
||||||
|
assert_eq!(
|
||||||
|
result
|
||||||
|
.stdout_str()
|
||||||
|
.matches("copy offload: unsupported, reflink: unsupported, sparse detection: unsupported")
|
||||||
|
.count(),
|
||||||
|
2
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
fn test_cp_debug_sparse_reflink() {
|
||||||
|
let ts = TestScenario::new(util_name!());
|
||||||
|
let at = &ts.fixtures;
|
||||||
|
at.touch("a");
|
||||||
|
let result = ts
|
||||||
|
.ucmd()
|
||||||
|
.arg("--debug")
|
||||||
|
.arg("--sparse=always")
|
||||||
|
.arg("--reflink=never")
|
||||||
|
.arg("a")
|
||||||
|
.arg("b")
|
||||||
|
.succeeds();
|
||||||
|
|
||||||
|
let stdout_str = result.stdout_str();
|
||||||
|
if !stdout_str.contains("copy offload: avoided, reflink: no, sparse detection: zeros") {
|
||||||
|
println!("Failure: stdout was \n{stdout_str}");
|
||||||
|
assert!(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
fn test_cp_debug_sparse_always() {
|
||||||
|
let ts = TestScenario::new(util_name!());
|
||||||
|
let at = &ts.fixtures;
|
||||||
|
at.touch("a");
|
||||||
|
let result = ts
|
||||||
|
.ucmd()
|
||||||
|
.arg("--debug")
|
||||||
|
.arg("--sparse=always")
|
||||||
|
.arg("a")
|
||||||
|
.arg("b")
|
||||||
|
.succeeds();
|
||||||
|
let stdout_str = result.stdout_str();
|
||||||
|
if !stdout_str.contains("copy offload: avoided, reflink: unsupported, sparse detection: zeros")
|
||||||
|
{
|
||||||
|
println!("Failure: stdout was \n{stdout_str}");
|
||||||
|
assert!(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
fn test_cp_debug_sparse_never() {
|
||||||
|
let ts = TestScenario::new(util_name!());
|
||||||
|
let at = &ts.fixtures;
|
||||||
|
at.touch("a");
|
||||||
|
let result = ts
|
||||||
|
.ucmd()
|
||||||
|
.arg("--debug")
|
||||||
|
.arg("--sparse=never")
|
||||||
|
.arg("a")
|
||||||
|
.arg("b")
|
||||||
|
.succeeds();
|
||||||
|
let stdout_str = result.stdout_str();
|
||||||
|
if !stdout_str.contains("copy offload: unknown, reflink: unsupported, sparse detection: no") {
|
||||||
|
println!("Failure: stdout was \n{stdout_str}");
|
||||||
|
assert!(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_cp_debug_sparse_auto() {
|
||||||
|
let ts = TestScenario::new(util_name!());
|
||||||
|
let at = &ts.fixtures;
|
||||||
|
at.touch("a");
|
||||||
|
let result = ts
|
||||||
|
.ucmd()
|
||||||
|
.arg("--debug")
|
||||||
|
.arg("--sparse=auto")
|
||||||
|
.arg("a")
|
||||||
|
.arg("b")
|
||||||
|
.succeeds();
|
||||||
|
let stdout_str = result.stdout_str();
|
||||||
|
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
if !stdout_str
|
||||||
|
.contains("copy offload: unknown, reflink: unsupported, sparse detection: unsupported")
|
||||||
|
{
|
||||||
|
println!("Failure: stdout was \n{stdout_str}");
|
||||||
|
assert!(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
if !stdout_str.contains("copy offload: unknown, reflink: unsupported, sparse detection: no") {
|
||||||
|
println!("Failure: stdout was \n{stdout_str}");
|
||||||
|
assert!(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(any(target_os = "linux", target_os = "android", target_os = "macos"))]
|
||||||
|
fn test_cp_debug_reflink_auto() {
|
||||||
|
let ts = TestScenario::new(util_name!());
|
||||||
|
let at = &ts.fixtures;
|
||||||
|
at.touch("a");
|
||||||
|
let result = ts
|
||||||
|
.ucmd()
|
||||||
|
.arg("--debug")
|
||||||
|
.arg("--reflink=auto")
|
||||||
|
.arg("a")
|
||||||
|
.arg("b")
|
||||||
|
.succeeds();
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
{
|
||||||
|
let stdout_str = result.stdout_str();
|
||||||
|
if !stdout_str.contains("copy offload: unknown, reflink: unsupported, sparse detection: no")
|
||||||
|
{
|
||||||
|
println!("Failure: stdout was \n{stdout_str}");
|
||||||
|
assert!(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
{
|
||||||
|
let stdout_str = result.stdout_str();
|
||||||
|
if !stdout_str
|
||||||
|
.contains("copy offload: unknown, reflink: unsupported, sparse detection: unsupported")
|
||||||
|
{
|
||||||
|
println!("Failure: stdout was \n{stdout_str}");
|
||||||
|
assert!(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
fn test_cp_debug_sparse_always_reflink_auto() {
|
||||||
|
let ts = TestScenario::new(util_name!());
|
||||||
|
let at = &ts.fixtures;
|
||||||
|
at.touch("a");
|
||||||
|
let result = ts
|
||||||
|
.ucmd()
|
||||||
|
.arg("--debug")
|
||||||
|
.arg("--sparse=always")
|
||||||
|
.arg("--reflink=auto")
|
||||||
|
.arg("a")
|
||||||
|
.arg("b")
|
||||||
|
.succeeds();
|
||||||
|
let stdout_str = result.stdout_str();
|
||||||
|
if !stdout_str.contains("copy offload: avoided, reflink: unsupported, sparse detection: zeros")
|
||||||
|
{
|
||||||
|
println!("Failure: stdout was \n{stdout_str}");
|
||||||
|
assert!(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue