From owner-freebsd-bugs@FreeBSD.ORG Tue Jul 17 18:00:26 2012 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id E17D3106566C for ; Tue, 17 Jul 2012 18:00:26 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id CB0B08FC16 for ; Tue, 17 Jul 2012 18:00:26 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.5/8.14.5) with ESMTP id q6HI0QUw064902 for ; Tue, 17 Jul 2012 18:00:26 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.5/8.14.5/Submit) id q6HI0Qn5064901; Tue, 17 Jul 2012 18:00:26 GMT (envelope-from gnats) Date: Tue, 17 Jul 2012 18:00:26 GMT Message-Id: <201207171800.q6HI0Qn5064901@freefall.freebsd.org> To: freebsd-bugs@FreeBSD.org From: Andrey Ignatov Cc: Subject: Re: bin/169723: [patch] find(1) exits with non-zero return code if any file in a directory is deleted while find(1) is traversing the directory X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: Andrey Ignatov List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 17 Jul 2012 18:00:27 -0000 The following reply was made to PR bin/169723; it has been noted by GNATS. From: Andrey Ignatov To: Jilles Tjoelker Cc: bug-followup@FreeBSD.org, Valery Khromov Subject: Re: bin/169723: [patch] find(1) exits with non-zero return code if any file in a directory is deleted while find(1) is traversing the directory Date: Tue, 17 Jul 2012 21:53:16 +0400 --LQksG6bCIzRHxTLp Content-Type: text/plain; charset=koi8-r Content-Disposition: inline Hi, Jilles! Thank you for the information! We've taken into account all your points and impletemted both options (-ignore_readdir_race and -noignore_readdir_race). The default behaviour is -noignore_readdir_race. The patch is attached as well as the new Makefile to test it. Jilles Tjoelker [2012-07-15 19:43]: > In PR 169723, you wrote: > > [find(1) prints an error message if a file is deleted between readdir > > and stat or opendir] > > This patch appears to match the description of > -ignore_readdir_race in the documentation of GNU find. Perhaps it is > appropriate to suppress these error messages only if > -ignore_readdir_race is given (and -noignore_readdir_race is not given > afterwards). > > Furthermore, it only seems appropriate to me to suppress the error for > FTS_DNR and FTS_NS. FTS_ERR covers things like inability to open "." > which should never fail (so if they do, find(1) should tell the user > about it). > > -- > Jilles Tjoelker -- Andrey Ignatov --LQksG6bCIzRHxTLp Content-Type: text/x-diff; charset=koi8-r Content-Disposition: attachment; filename="freebsd9-ignore_readdir_race_v4.patch" Index: usr.bin/find/find.1 =================================================================== --- usr.bin/find/find.1 (revision 238532) +++ usr.bin/find/find.1 (working copy) @@ -467,7 +467,10 @@ .Ar gname is treated as a group ID. .It Ic -ignore_readdir_race -This option is for GNU find compatibility and is ignored. +Ignore errors which occur if a file or a directory in a starting point gets +deleted between reading the name and calling stat on it while find is +traversing the starting point. +This option doesn't affect errors occuring on starting points. .It Ic -ilname Ar pattern Like .Ic -lname , @@ -615,7 +618,9 @@ .It Ic -nogroup True if the file belongs to an unknown group. .It Ic -noignore_readdir_race -This option is for GNU find compatibility and is ignored. +Turn off the effect of +.Ic -ignore_readdir_race . +This is default behaviour. .It Ic -noleaf This option is for GNU find compatibility. In GNU find it disables an optimization not relevant to Index: usr.bin/find/find.c =================================================================== --- usr.bin/find/find.c (revision 238532) +++ usr.bin/find/find.c (working copy) @@ -197,8 +197,11 @@ continue; break; case FTS_DNR: + case FTS_NS: + if (ignore_readdir_race && + entry->fts_errno == ENOENT && entry->fts_level) + continue; case FTS_ERR: - case FTS_NS: (void)fflush(stdout); warnx("%s: %s", entry->fts_path, strerror(entry->fts_errno)); @@ -228,7 +231,7 @@ for (p = plan; p && (p->execute)(p, entry); p = p->next); } finish_execplus(); - if (errno) + if (errno && (!ignore_readdir_race || errno != ENOENT)) err(1, "fts_read"); return (rval); } Index: usr.bin/find/main.c =================================================================== --- usr.bin/find/main.c (revision 238532) +++ usr.bin/find/main.c (working copy) @@ -64,6 +64,7 @@ time_t now; /* time find was run */ int dotfd; /* starting directory */ int ftsoptions; /* options for the ftsopen(3) call */ +int ignore_readdir_race = 0; /* ignore readdir race */ int isdeprecated; /* using deprecated syntax */ int isdepth; /* do directories on post-order visit */ int isoutput; /* user specified output operator */ Index: usr.bin/find/function.c =================================================================== --- usr.bin/find/function.c (revision 238532) +++ usr.bin/find/function.c (working copy) @@ -975,6 +975,25 @@ } /* + * -ignore_readdir_race functions -- + * + * Always true. Ignore errors which occur if a file or a directory + * in a starting point gets deleted between reading the name and calling + * stat on it while find is traversing the starting point. + */ + +PLAN * +c_ignore_readdir_race(OPTION *option, char ***argvp __unused) +{ + if (strcmp(option->name, "-ignore_readdir_race") == 0) + ignore_readdir_race = 1; + else + ignore_readdir_race = 0; + + return palloc(option); +} + +/* * -inum n functions -- * * True if the file has inode # n. Index: usr.bin/find/option.c =================================================================== --- usr.bin/find/option.c (revision 238532) +++ usr.bin/find/option.c (working copy) @@ -88,7 +88,7 @@ { "-fstype", c_fstype, f_fstype, 0 }, { "-gid", c_group, f_group, 0 }, { "-group", c_group, f_group, 0 }, - { "-ignore_readdir_race",c_simple, f_always_true,0 }, + { "-ignore_readdir_race",c_ignore_readdir_race, f_always_true,0 }, { "-ilname", c_name, f_name, F_LINK | F_IGNCASE }, { "-iname", c_name, f_name, F_IGNCASE }, { "-inum", c_inum, f_inum, 0 }, @@ -127,7 +127,7 @@ { "-newermm", c_newer, f_newer, 0 }, { "-newermt", c_newer, f_newer, F_TIME2_T }, { "-nogroup", c_nogroup, f_nogroup, 0 }, - { "-noignore_readdir_race",c_simple, f_always_true,0 }, + { "-noignore_readdir_race",c_ignore_readdir_race, f_always_true,0 }, { "-noleaf", c_simple, f_always_true, 0 }, { "-not", c_simple, f_not, 0 }, { "-nouser", c_nouser, f_nouser, 0 }, Index: usr.bin/find/extern.h =================================================================== --- usr.bin/find/extern.h (revision 238532) +++ usr.bin/find/extern.h (working copy) @@ -58,6 +58,7 @@ creat_f c_follow; creat_f c_fstype; creat_f c_group; +creat_f c_ignore_readdir_race; creat_f c_inum; creat_f c_links; creat_f c_ls; @@ -111,7 +112,8 @@ exec_f f_type; exec_f f_user; -extern int ftsoptions, isdeprecated, isdepth, isoutput, issort, isxargs; +extern int ftsoptions, ignore_readdir_race, isdeprecated, isdepth, isoutput; +extern int issort, isxargs; extern int mindepth, maxdepth; extern int regexp_flags; extern time_t now; --LQksG6bCIzRHxTLp Content-Type: text/plain; charset=koi8-r Content-Disposition: attachment; filename=Makefile D:=testdir FIND?=find all: prepare $(MAKE) -j16 mkfiles mkdirs rmfiles find mkfiles: dd if=/dev/urandom | hexdump -e '"" 8/1 "%02x" "\n"' | while read i ; do touch "$(D)/$$i"; done mkdirs: dd if=/dev/urandom | hexdump -e '"" 8/1 "%02x" "\n"' | while read i ; do mkdir "$(D)/$$i"; done rmfiles: while :; do rm -rf $(D)/*; sleep 1; done find: while :; do $(FIND) $(D)/ $(FINDFLAGS) -type f -name '*NAME*' || echo FAILED; done prepare: rm -rf $(D) mkdir -p $(D) --LQksG6bCIzRHxTLp--