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