Skip to content

Commit 6603d64

Browse files
committed
feat: improve directory removal on Linux for permission denied
Enhance safe_remove_dir_recursive_impl to handle PermissionDenied errors when opening unreadable directories by attempting direct removal via parent directory file descriptor. This improves robustness for cases where directories cannot be read internally, allowing successful deletion without read permissions.
1 parent 43cccdf commit 6603d64

File tree

1 file changed

+34
-2
lines changed

1 file changed

+34
-2
lines changed

src/uu/rm/src/platform/linux.rs

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -361,8 +361,40 @@ pub fn safe_remove_dir_recursive_impl(
361361
let child_dir_fd = match DirFd::open(&entry_path) {
362362
Ok(fd) => fd,
363363
Err(e) => {
364-
error = handle_error_with_force(e, &entry_path, options) || error;
365-
continue;
364+
if e.kind() == std::io::ErrorKind::PermissionDenied {
365+
// Try to remove the unreadable directory directly via parent dirfd
366+
match DirFd::open(path) {
367+
Ok(parent_fd) => {
368+
match parent_fd.unlink_at(entry_name.as_ref(), true) {
369+
Ok(_) => {
370+
if let Some(pb) = progress_bar {
371+
pb.inc(1);
372+
}
373+
verbose_removed_directory(&entry_path, options);
374+
continue;
375+
}
376+
Err(remove_err) => {
377+
if remove_err.kind() == std::io::ErrorKind::PermissionDenied {
378+
if !options.force {
379+
show_permission_denied_error(&entry_path);
380+
}
381+
error = !options.force || error;
382+
} else {
383+
error = handle_error_with_force(remove_err, &entry_path, options) || error;
384+
}
385+
continue;
386+
}
387+
}
388+
}
389+
Err(parent_e) => {
390+
error = handle_error_with_force(parent_e, &entry_path, options) || error;
391+
continue;
392+
}
393+
}
394+
} else {
395+
error = handle_error_with_force(e, &entry_path, options) || error;
396+
continue;
397+
}
366398
}
367399
};
368400

0 commit comments

Comments
 (0)