Skip to content

Commit 818bf02

Browse files
committed
rm: Check filesystem checks in rm command
- Rename `validate_single_filesystem` to `check_one_fs` for improved clarity and alignment with its functionality. - Refactore `check_one_fs` to directly handle options such as `--one-file-system` and `--preserve-root=all` and return detailed error messages when the conditions are not met. - Integrate `check_one_fs` into `remove_dir_recursive` and `handle_dir` for consistent handling of files and directories on different file systems.
1 parent 196ac9f commit 818bf02

File tree

3 files changed

+36
-42
lines changed

3 files changed

+36
-42
lines changed

src/uu/rm/src/rm.rs

Lines changed: 29 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,17 @@ fn remove_dir_recursive(path: &Path, options: &Options) -> bool {
456456
}
457457
}
458458

459+
if let Err(additional_reason) = check_one_fs(path, options) {
460+
if !additional_reason.is_empty() {
461+
show_error!("{}", additional_reason);
462+
}
463+
show_error!(
464+
"skipping {}, since it's on a different device",
465+
path.quote()
466+
);
467+
return true;
468+
}
469+
459470
// Base case 1: this is a file or a symbolic link.
460471
//
461472
// The symbolic link case is important because it could be a link to
@@ -550,10 +561,16 @@ fn mount_for_path<'a>(path: &Path, mounts: &'a [MountInfo]) -> Option<&'a MountI
550561
best.map(|(mi, _len)| mi)
551562
}
552563

553-
/// Validates that a path is on the same file system as its parent.
564+
/// Check if a path is on the same file system when `--one-file-system` or `--preserve-root=all` options are enabled.
554565
/// Return `OK(())` if the path is on the same file system,
555566
/// or an additional error describing why it should be skipped.
556-
fn validate_single_filesystem(path: &Path) -> Result<(), String> {
567+
fn check_one_fs(path: &Path, options: &Options) -> Result<(), String> {
568+
// If neither `--one-file-system` nor `--preserve-root=all` is active,
569+
// always proceed
570+
if !options.one_fs && options.preserve_root != PreserveRoot::YesAll {
571+
return Ok(());
572+
}
573+
557574
// Read mount information
558575
let fs_list = read_fs_list().map_err(|err| format!("cannot read mount info: {err}"))?;
559576

@@ -578,42 +595,20 @@ fn validate_single_filesystem(path: &Path) -> Result<(), String> {
578595
Ok(())
579596
}
580597

581-
/// Check if a path is on the same file system when `--one-file-system` or `--preserve-root=all` options are enabled.
582-
/// Return `true` if the path can be processed, `false` if it should be skipped.
583-
fn check_one_fs(path: &Path, options: &Options) -> bool {
584-
// If neither `--one-file-system` nor `--preserve-root=all` is active,
585-
// always proceed
586-
if !options.one_fs && options.preserve_root != PreserveRoot::YesAll {
587-
return true;
588-
}
589-
590-
let result = validate_single_filesystem(path);
591-
if result.is_ok() {
592-
return true;
593-
}
598+
fn handle_dir(path: &Path, options: &Options) -> bool {
599+
let mut had_err = false;
594600

595-
if let Err(additional_reason) = result {
601+
if let Err(additional_reason) = check_one_fs(path, options) {
596602
if !additional_reason.is_empty() {
597603
show_error!("{}", additional_reason);
598604
}
599-
}
600-
601-
show_error!(
602-
"skipping {}, since it's on a different device",
603-
path.quote()
604-
);
605-
606-
if options.preserve_root == PreserveRoot::YesAll {
607-
show_error!("and --preserve-root=all is in effect");
608-
}
609-
610-
false
611-
}
612-
613-
fn handle_dir(path: &Path, options: &Options) -> bool {
614-
let mut had_err = false;
615-
616-
if !check_one_fs(path, options) {
605+
show_error!(
606+
"skipping {}, since it's on a different device",
607+
path.quote()
608+
);
609+
if options.preserve_root == PreserveRoot::YesAll {
610+
show_error!("and --preserve-root=all is in effect");
611+
}
617612
return true;
618613
}
619614

tests/by-util/test_rm.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1026,8 +1026,8 @@ fn test_rm_one_file_system() {
10261026
// Define paths for temporary files and directories
10271027
let img_path = "fs.img";
10281028
let mount_point = "fs";
1029-
let src_dir = "a/b";
1030-
let bind_mount_point = "a";
1029+
let remove_dir = "a";
1030+
let bind_mount_point = "a/b";
10311031

10321032
at.touch(img_path);
10331033

@@ -1046,8 +1046,8 @@ fn test_rm_one_file_system() {
10461046
scene.cmd("/sbin/mkfs.ext4").arg(img_path).succeeds();
10471047

10481048
// Prepare directory structure
1049-
at.mkdir_all(src_dir);
10501049
at.mkdir_all(mount_point);
1050+
at.mkdir_all(bind_mount_point);
10511051

10521052
// Mount as loop device
10531053
scene
@@ -1067,7 +1067,7 @@ fn test_rm_one_file_system() {
10671067
// Run the test
10681068
scene
10691069
.ucmd()
1070-
.args(&["--one-file-system", "-rf", bind_mount_point])
1070+
.args(&["--one-file-system", "-rf", remove_dir])
10711071
.fails()
10721072
.stderr_contains(format!("rm: skipping '{}'", bind_mount_point));
10731073

@@ -1095,8 +1095,7 @@ fn test_rm_preserve_root() {
10951095
// Define paths for temporary files and directories
10961096
let img_path = "fs.img";
10971097
let mount_point = "fs";
1098-
let src_dir = "a/b";
1099-
let bind_mount_point = "a";
1098+
let bind_mount_point = "a/b";
11001099

11011100
at.touch(img_path);
11021101

@@ -1115,8 +1114,8 @@ fn test_rm_preserve_root() {
11151114
scene.cmd("/sbin/mkfs.ext4").arg(img_path).succeeds();
11161115

11171116
// Prepare directory structure
1118-
at.mkdir_all(src_dir);
11191117
at.mkdir_all(mount_point);
1118+
at.mkdir_all(bind_mount_point);
11201119

11211120
// Mount as loop device
11221121
scene

util/build-gnu.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ sed -i -e "s|removed directory 'a/'|removed directory 'a'|g" tests/rm/v-slash.sh
207207

208208
if test "$(grep -c 'rm: skipping ' tests/rm/one-file-system.sh)" -eq 1; then
209209
# Do it only once.
210-
sed -i -e "s|rm: skipping 'a/b'|rm: skipping 'a'|g" -e "s/ >> exp/ > exp/g" -e "s|rm: and --preserve-root=all is in effect|rm: skipping 'a/b', since it's on a different device\nrm: and --preserve-root=all is in effect|g" tests/rm/one-file-system.sh
210+
sed -i -e "s/ >> exp/ > exp/g" -e "s|rm: and --preserve-root=all is in effect|rm: skipping 'a/b', since it's on a different device\nrm: and --preserve-root=all is in effect|g" tests/rm/one-file-system.sh
211211
fi
212212

213213
# 'rel' doesn't exist. Our implementation is giving a better message.

0 commit comments

Comments
 (0)