From ed5c4e770a27862813c0182be8680abeb005d15b Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Wed, 30 Jan 2008 13:43:15 +0100 Subject: Improve "rmdir --ignore-fail-on-non-empty" * src/rmdir.c (remove_parents, main): With --ignore-fail-on-non-empty, suppress a diagnostic also for other errno values, which can arise with read-only media or when the parent directory has the immutable attribute (set via chattr +i). (errno_may_be_empty, ignorable_failure): New functions. * src/remove.c (is_empty_dir): Move function to ... * src/system.h (is_empty_dir): ...here, and make it inline. Suggested by Josselin Mouette in via Bob Proulx. * NEWS: Mention the improvement. --- src/rmdir.c | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) (limited to 'src/rmdir.c') diff --git a/src/rmdir.c b/src/rmdir.c index 96aa9af22..bb1a0c8b3 100644 --- a/src/rmdir.c +++ b/src/rmdir.c @@ -74,13 +74,41 @@ static struct option const longopts[] = /* Return true if ERROR_NUMBER is one of the values associated with a failed rmdir due to non-empty target directory. */ - static bool errno_rmdir_non_empty (int error_number) { return (error_number == RMDIR_ERRNO_NOT_EMPTY); } +/* Return true if when rmdir fails with errno == ERROR_NUMBER + the directory may be empty. */ +static bool +errno_may_be_empty (int error_number) +{ + switch (error_number) + { + case EACCES: + case EPERM: + case EROFS: + case EEXIST: + case EBUSY: + return true; + default: + return false; + } +} + +/* Return true if an rmdir failure with errno == error_number + for DIR is ignorable. */ +static bool +ignorable_failure (int error_number, char const *dir) +{ + return (ignore_fail_on_non_empty + && (errno_rmdir_non_empty (error_number) + || (errno_may_be_empty (error_number) + && is_empty_dir (AT_FDCWD, dir)))); +} + /* Remove any empty parent directories of DIR. If DIR contains slash characters, at least one of them (beginning with the rightmost) is replaced with a NUL byte. @@ -113,8 +141,7 @@ remove_parents (char *dir) if (!ok) { /* Stop quietly if --ignore-fail-on-non-empty. */ - if (ignore_fail_on_non_empty - && errno_rmdir_non_empty (errno)) + if (ignorable_failure (errno, dir)) { ok = true; } @@ -210,8 +237,7 @@ main (int argc, char **argv) if (rmdir (dir) != 0) { - if (ignore_fail_on_non_empty - && errno_rmdir_non_empty (errno)) + if (ignorable_failure (errno, dir)) continue; /* Here, the diagnostic is less precise, since we have no idea -- cgit v1.2.3-54-g00ecf