| From a3f4821c4a3f723d21c9298d54bee8a656bfd7fb Mon Sep 17 00:00:00 2001 |
| From: Bernhard Voelker <mail@bernhard-voelker.de> |
| Date: Tue, 30 Jan 2018 23:30:09 +0100 |
| Subject: [PATCH] find: make -delete honour the -ignore_readdir_race option |
| |
| * find/pred.c (pred_delete): Return true when the -ignore_readdir_race |
| option is active and unlinkat() came back with ENOENT. |
| * doc/find.texi (Option -ignore_readdir_race): Document the change. |
| (Action -delete): Likewise. |
| * find/find.1: Likewise. |
| * NEWS (Bug Fixes): Mention the fix. |
| |
| For now, it seems a bit hard to add a proper test for this, |
| so the following shell snippet demonstrates the race: |
| |
| $ seq 10 | xargs touch |
| $ env time -f 'find exit status: %x\nfind time: %e' \ |
| find -ignore_readdir_race -type f \ |
| -delete \ |
| -exec sh -c 'sleep $(basename {})' \; \ |
| -printf 'find deleted: %p\n' \ |
| & \ |
| sleep 20; \ |
| seq 10 | xargs rm -fv; \ |
| wait $! |
| |
| Reported by Alexander Golubev in |
| https://savannah.gnu.org/bugs/?52981 |
| |
| Upstream-Status: Backport |
| Signed-off-by: Zhixiong Chi <zhixiong.chi@windriver.com> |
| |
| --- |
| NEWS | 4 ++++ |
| doc/find.texi | 15 ++++++++++++++- |
| find/find.1 | 22 ++++++++++++++++++++++ |
| find/pred.c | 6 ++++++ |
| 4 files changed, 46 insertions(+), 1 deletion(-) |
| |
| diff --git a/NEWS b/NEWS |
| index 660c241..b86ec1e 100644 |
| --- a/NEWS |
| +++ b/NEWS |
| @@ -42,6 +42,10 @@ Updated the Danish translation. |
| |
| ** Bug Fixes: |
| |
| +#52981: find: the '-delete' action no longer complains about disappeared files |
| + when the '-ignore_readdir_race' option is given, too. That action will |
| + also returns true in such a case now. |
| + |
| Applied patch #8688: Spelling fixes. |
| |
| * Major changes in release 4.5.18, 2015-12-27 |
| diff --git a/doc/find.texi b/doc/find.texi |
| index fdeb841..247c19a 100644 |
| --- a/doc/find.texi |
| +++ b/doc/find.texi |
| @@ -1418,7 +1418,15 @@ gives a significant increase in search speed. |
| If a file disappears after its name has been read from a directory but |
| before @code{find} gets around to examining the file with @code{stat}, |
| don't issue an error message. If you don't specify this option, an |
| -error message will be issued. This option can be useful in system |
| +error message will be issued. |
| + |
| +Furthermore, @code{find} with the @samp{-ignore_readdir_race} option |
| +will ignore errors of the @samp{-delete} action in the case the file |
| +has disappeared since the parent directory was read: it will not output |
| +an error diagnostic, and the return code of the @samp{-delete} action |
| +will be true. |
| + |
| +This option can be useful in system |
| scripts (cron scripts, for example) that examine areas of the |
| filesystem that change frequently (mail queues, temporary directories, |
| and so forth), because this scenario is common for those sorts of |
| @@ -2779,6 +2787,11 @@ explicitly. |
| |
| If @samp{-delete} fails, @code{find}'s exit status will be nonzero |
| (when it eventually exits). |
| + |
| +Together with the @samp{-ignore_readdir_race} option, @code{find} will |
| +ignore errors of the @samp{-delete} action in the case the file has disappeared |
| +since the parent directory was read: it will not output an error diagnostic, and |
| +the return code of the @samp{-delete} action will be true. |
| @end deffn |
| |
| @node Adding Tests |
| diff --git a/find/find.1 b/find/find.1 |
| index 7b141b8..0eec41c 100644 |
| --- a/find/find.1 |
| +++ b/find/find.1 |
| @@ -479,6 +479,17 @@ one part of the filesystem with this option on and part of it with this option |
| off (if you need to do that, you will need to issue two \fBfind\fR commands |
| instead, one with the option and one without it). |
| |
| +Furthermore, |
| +.B find |
| +with the |
| +.B \-ignore_readdir_race |
| +option will ignore errors of the |
| +.B \-delete |
| +action in the case the file has disappeared since the parent directory was read: |
| +it will not output an error diagnostic, and the return code of the |
| +.B \-delete |
| +action will be true. |
| + |
| .IP "\-maxdepth \fIlevels\fR" |
| Descend at most \fIlevels\fR (a non-negative integer) levels of |
| directories below the starting-points. |
| @@ -1030,6 +1041,17 @@ and |
| .B \-delete |
| together. |
| |
| +Together with the |
| +.B \-ignore_readdir_race |
| +option, |
| +.B find |
| +will ignore errors of the |
| +.B \-delete |
| +action in the case the file has disappeared since the parent directory was |
| +read: it will not output an error diagnostic, and the return code of the |
| +.B \-delete |
| +action will be true. |
| + |
| .IP "\-exec \fIcommand\fR ;" |
| Execute \fIcommand\fR; true if 0 status is returned. All following |
| arguments to |
| diff --git a/find/pred.c b/find/pred.c |
| index 32938fb..431f065 100644 |
| --- a/find/pred.c |
| +++ b/find/pred.c |
| @@ -324,6 +324,12 @@ pred_delete (const char *pathname, struct stat *stat_buf, struct predicate *pred |
| } |
| else |
| { |
| + if (ENOENT == errno && options.ignore_readdir_race) |
| + { |
| + /* Ignore unlink() error for vanished files. */ |
| + errno = 0; |
| + return true; |
| + } |
| if (EISDIR == errno) |
| { |
| if ((flags & AT_REMOVEDIR) == 0) |