Skip to content

Conversation

@jfinkels
Copy link
Collaborator

@jfinkels jfinkels commented Feb 16, 2025

This includes the changes from #7306 and #7308.

Change the implementation of rm -r so that it is explicitly recursive
so that (1) there is one code path regardless of whether --verbose is
given and (2) it is easier to be compatible with GNU rm.

This change eliminates a dependency on the walkdir crate.

Fixes #7033, fixes #7305.

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@jfinkels jfinkels changed the title [WIP] rm: use recursive directory traversal with --recursive rm: use recursive directory traversal with --recursive Feb 16, 2025
@github-actions

This comment was marked as outdated.

Check the user write permission directly from the mode instead of using
the `Permissions::readonly()` method. This seems to more closely match
the behavior of GNU `rm`.
Change the implementation of `rm -r` so that it is explicitly recursive
so that (1) there is one code path regardless of whether `--verbose` is
given and (2) it is easier to be compatible with GNU `rm`.

This change eliminates a dependency on the `walkdir` crate.

Fixes uutils#7033, fixes uutils#7305, fixes uutils#7307.
Comment on lines +386 to +406
// Special case: if we cannot access the metadata because the
// filename is too long, fall back to try
// `std::fs::remove_dir_all()`.
//
// 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
// causes a `InvalidFilename` error when trying to access the file
// metadata, we should be able to use just the last part of the
// path, "z", and know that it is relative to the parent, "x/y".
if let Some(s) = path.to_str() {
if s.len() > 1000 {
match std::fs::remove_dir_all(path) {
Ok(_) => return false,
Err(e) => {
let e = e.map_err_context(|| format!("cannot remove {}", path.quote()));
show_error!("{e}");
return true;
}
}
}
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is here to pass the GNU test case tests/rm/deep-2.sh, where a very deep directory with a long name is created and then removed (like xxxx/xxxxx/xxxxx/...). The issue is that calling path.metadata() on a path that is too long returns an InvalidFilename error. Instead what we should do is use a relative path name and keep setting the working directory as we recurse. It must be possible because std::fs::remove_dir_all(path) seems to work on the very long path. I wasn't sure how to do that, so if someone knows how, I could update the code here. Otherwise, we can just leave this for now and fix it later.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar issue with du in #7217

@jfinkels jfinkels marked this pull request as ready for review February 17, 2025 16:33
@github-actions
Copy link

GNU testsuite comparison:

Congrats! The gnu test tests/rm/ir-1 is no longer failing!
Skipping an intermittent issue tests/rm/rm1 (passes in this run but fails in the 'main' branch)

@sylvestre
Copy link
Contributor

kudos !
i worked on it too but could not make it work, bravo!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

rm: fails to remove unreadable directory with -d flag rm: -r option fails to remove unreadable directory

2 participants