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
Andrey Ignatov
rdna at rdna.ru
Tue Jul 17 18:00:27 UTC 2012
The following reply was made to PR bin/169723; it has been noted by GNATS.
From: Andrey Ignatov <rdna at rdna.ru>
To: Jilles Tjoelker <jilles at stack.nl>
Cc: bug-followup at FreeBSD.org, Valery Khromov <qwerty at yandex-team.ru>
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 <jilles at stack.nl> [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--
More information about the freebsd-bugs
mailing list