Skip to content

Commit 0f1059f

Browse files
committed
refactor(uu/rm): wrap current_fd in Option for better ownership management in recursive directory removal
- Modified safe_remove_dir_recursive_impl to use Option<DirFd> instead of DirFd for current_fd - Enables taking ownership during descent and restore cycles to optimize file descriptor handling - Updated all accesses to use as_ref(), and_then(), take(), and Some() appropriately - Ensures safe borrowing when calling handler functions like open_subdir, unlink_at, and handle_unlink
1 parent 3f4e52a commit 0f1059f

File tree

1 file changed

+20
-15
lines changed

1 file changed

+20
-15
lines changed

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

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,8 @@ pub fn safe_remove_dir_recursive_impl(
343343
}
344344
}
345345
let mut error = false;
346-
let mut current_fd = dir_fd;
346+
// Wrap in Option to allow taking ownership each descent/restore cycle
347+
let mut current_fd = Some(dir_fd);
347348

348349
for (entry_name, entry_stat) in collected {
349350
let entry_path = path.join(&entry_name);
@@ -357,12 +358,18 @@ pub fn safe_remove_dir_recursive_impl(
357358
continue;
358359
}
359360

360-
let child_dir_fd = match current_fd.open_subdir(&entry_name) {
361+
let child_dir_fd = match current_fd
362+
.as_ref()
363+
.and_then(|fd| fd.open_subdir(&entry_name).ok())
364+
{
361365
Ok(fd) => fd,
362366
Err(e) => {
363367
if e.kind() == std::io::ErrorKind::PermissionDenied {
364368
// Try to remove the unreadable directory directly via parent dirfd
365-
match current_fd.unlink_at(entry_name.as_ref(), true) {
369+
match current_fd
370+
.as_ref()
371+
.and_then(|fd| fd.unlink_at(entry_name.as_ref(), true).ok())
372+
{
366373
Ok(_) => {
367374
if let Some(pb) = progress_bar {
368375
pb.inc(1);
@@ -391,14 +398,14 @@ pub fn safe_remove_dir_recursive_impl(
391398
};
392399

393400
// Release current dir fd to keep FD usage low
394-
drop(current_fd);
401+
drop(current_fd.take());
395402

396403
let (child_error, returned_fd) =
397404
safe_remove_dir_recursive_impl(&entry_path, child_dir_fd, options, progress_bar);
398405
error = error || child_error;
399406

400407
// Restore current directory fd
401-
current_fd = match returned_fd {
408+
current_fd = Some(match returned_fd {
402409
Some(fd) => fd,
403410
None => match DirFd::open(path) {
404411
Ok(fd) => fd,
@@ -407,7 +414,7 @@ pub fn safe_remove_dir_recursive_impl(
407414
continue;
408415
}
409416
},
410-
};
417+
});
411418

412419
if !child_error
413420
&& options.interactive == InteractiveMode::Always
@@ -420,20 +427,18 @@ pub fn safe_remove_dir_recursive_impl(
420427
if let Some(pb) = progress_bar {
421428
pb.inc(1);
422429
}
423-
error = handle_unlink(&current_fd, entry_name.as_ref(), &entry_path, true, options)
424-
|| error;
430+
if let Some(ref fd) = current_fd {
431+
error =
432+
handle_unlink(fd, entry_name.as_ref(), &entry_path, true, options) || error;
433+
}
425434
}
426435
} else if prompt_file_with_stat(&entry_path, &entry_stat, options) {
427436
if let Some(pb) = progress_bar {
428437
pb.inc(1);
429438
}
430-
error = handle_unlink(
431-
&current_fd,
432-
entry_name.as_ref(),
433-
&entry_path,
434-
false,
435-
options,
436-
) || error;
439+
if let Some(ref fd) = current_fd {
440+
error = handle_unlink(fd, entry_name.as_ref(), &entry_path, false, options) || error;
441+
}
437442
}
438443
}
439444

0 commit comments

Comments
 (0)